mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Merge pull request #73 from oceanprotocol/feature/dt-name-output
handle generated dt names during publish
This commit is contained in:
commit
b70fa86273
@ -100,11 +100,11 @@
|
||||
"price": {
|
||||
"fixed": {
|
||||
"title": "Fixed",
|
||||
"info": "Set your price for accessing this data set. A Data Token contract for this data set, worth the entered amount of OCEAN will be created."
|
||||
"info": "Set your price for accessing this data set. A Data Token for this data set, worth the entered amount of OCEAN, will be created."
|
||||
},
|
||||
"dynamic": {
|
||||
"title": "Dynamic",
|
||||
"info": "Let's create a decentralized, automated market for your data set. A Data Token contract for this data set worth the entered amount of OCEAN will be created. Additionally, you will provide liquidity into a Data Token/OCEAN liquidity pool with Balancer.",
|
||||
"info": "Let's create a decentralized, automated market for your data set. A Data Token for this data set, worth the entered amount of OCEAN, will be created. Additionally, you will provide liquidity into a Data Token/OCEAN liquidity pool with Balancer.",
|
||||
"tooltips": {
|
||||
"poolInfo": "Help me",
|
||||
"liquidityProviderFee": "Help me"
|
||||
|
@ -19,6 +19,7 @@ interface ButtonProps {
|
||||
download?: boolean
|
||||
target?: string
|
||||
rel?: string
|
||||
title?: string
|
||||
}
|
||||
|
||||
export default function Button({
|
||||
|
@ -18,14 +18,18 @@
|
||||
border: 1px solid var(--brand-grey-lighter);
|
||||
border-radius: 50%;
|
||||
background-color: var(--brand-white);
|
||||
margin-bottom: var(--spacer);
|
||||
margin-bottom: calc(var(--spacer) / 2);
|
||||
}
|
||||
|
||||
.coin:last-child .icon path {
|
||||
fill: var(--brand-grey-dimmed);
|
||||
stroke: var(--brand-black);
|
||||
stroke-width: 5px;
|
||||
stroke-linejoin: round;
|
||||
fill: var(--brand-violet);
|
||||
}
|
||||
|
||||
.tokenName {
|
||||
font-size: var(--font-size-base);
|
||||
color: var(--brand-grey);
|
||||
text-align: center;
|
||||
margin-bottom: calc(var(--spacer) / 6);
|
||||
}
|
||||
|
||||
.data {
|
||||
@ -47,7 +51,8 @@
|
||||
|
||||
.weight {
|
||||
width: 100%;
|
||||
margin-top: var(--spacer);
|
||||
text-align: center;
|
||||
margin-bottom: calc(var(--spacer) / 2);
|
||||
text-transform: uppercase;
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--color-secondary);
|
||||
@ -55,5 +60,4 @@
|
||||
|
||||
.weight strong {
|
||||
color: var(--brand-grey);
|
||||
font-size: var(--font-size-base);
|
||||
}
|
||||
|
@ -4,20 +4,24 @@ import styles from './Coin.module.css'
|
||||
import InputElement from '../../../atoms/Input/InputElement'
|
||||
import { ReactComponent as Logo } from '../../../../images/logo.svg'
|
||||
import Conversion from '../../../atoms/Price/Conversion'
|
||||
import { DataTokenOptions } from '@oceanprotocol/react'
|
||||
import RefreshName from './RefreshName'
|
||||
|
||||
export default function Coin({
|
||||
symbol,
|
||||
datatokenOptions,
|
||||
name,
|
||||
value,
|
||||
weight,
|
||||
onOceanChange,
|
||||
generateName,
|
||||
readOnly
|
||||
}: {
|
||||
symbol: string
|
||||
datatokenOptions: DataTokenOptions
|
||||
name: string
|
||||
value: string
|
||||
weight: string
|
||||
onOceanChange?: (event: ChangeEvent<HTMLInputElement>) => void
|
||||
generateName?: () => void
|
||||
readOnly?: boolean
|
||||
}): ReactElement {
|
||||
return (
|
||||
@ -26,6 +30,17 @@ export default function Coin({
|
||||
<Logo />
|
||||
</figure>
|
||||
|
||||
<h4 className={styles.tokenName}>
|
||||
{datatokenOptions?.name || 'Data Token'}
|
||||
{datatokenOptions?.name && generateName && (
|
||||
<RefreshName generateName={generateName} />
|
||||
)}
|
||||
</h4>
|
||||
|
||||
<div className={styles.weight}>
|
||||
Weight <strong>{weight}</strong>
|
||||
</div>
|
||||
|
||||
<div className={styles.data}>
|
||||
<InputElement
|
||||
value={value}
|
||||
@ -33,13 +48,11 @@ export default function Coin({
|
||||
type="number"
|
||||
onChange={onOceanChange}
|
||||
readOnly={readOnly}
|
||||
prefix={symbol}
|
||||
prefix={datatokenOptions?.symbol || 'DT'}
|
||||
/>
|
||||
<Conversion price={value} className={stylesIndex.conversion} />
|
||||
|
||||
<div className={styles.weight}>
|
||||
Weight <strong>{weight}</strong>
|
||||
</div>
|
||||
{datatokenOptions?.symbol === 'OCEAN' && (
|
||||
<Conversion price={value} className={stylesIndex.conversion} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
.advanced {
|
||||
.dynamic {
|
||||
composes: content from './index.module.css';
|
||||
}
|
||||
|
||||
.wallet {
|
||||
@ -36,8 +37,8 @@
|
||||
.tokens {
|
||||
display: grid;
|
||||
|
||||
margin-left: -3rem;
|
||||
margin-right: -3rem;
|
||||
margin-left: -2rem;
|
||||
margin-right: -2rem;
|
||||
border-bottom: 1px solid var(--brand-grey-lighter);
|
||||
}
|
||||
|
||||
@ -50,7 +51,6 @@
|
||||
.summary {
|
||||
text-align: center;
|
||||
margin-top: var(--spacer);
|
||||
margin-bottom: -2rem;
|
||||
}
|
||||
|
||||
.summary input {
|
||||
@ -58,8 +58,8 @@
|
||||
}
|
||||
|
||||
.alertArea {
|
||||
margin-left: -3rem;
|
||||
margin-right: -3rem;
|
||||
margin-left: -2rem;
|
||||
margin-right: -2rem;
|
||||
padding: var(--spacer) calc(var(--spacer) / 2);
|
||||
padding-bottom: 0;
|
||||
margin-top: var(--spacer);
|
||||
|
@ -1,10 +1,9 @@
|
||||
import React, { ReactElement, useState, ChangeEvent, useEffect } from 'react'
|
||||
import { graphql, useStaticQuery } from 'gatsby'
|
||||
import stylesIndex from './index.module.css'
|
||||
import styles from './Dynamic.module.css'
|
||||
import FormHelp from '../../../atoms/Input/Help'
|
||||
import Wallet from '../../Wallet'
|
||||
import { useOcean } from '@oceanprotocol/react'
|
||||
import { DataTokenOptions, PriceOptions, useOcean } from '@oceanprotocol/react'
|
||||
import Alert from '../../../atoms/Alert'
|
||||
import Coin from './Coin'
|
||||
import { isCorrectNetwork } from '../../../../utils/wallet'
|
||||
@ -15,21 +14,22 @@ import Tooltip from '../../../atoms/Tooltip'
|
||||
|
||||
export default function Dynamic({
|
||||
ocean,
|
||||
tokensToMint,
|
||||
weightOnDataToken,
|
||||
liquidityProviderFee,
|
||||
priceOptions,
|
||||
datatokenOptions,
|
||||
onOceanChange,
|
||||
generateName,
|
||||
content
|
||||
}: {
|
||||
ocean: string
|
||||
tokensToMint: number
|
||||
weightOnDataToken: string
|
||||
liquidityProviderFee: string
|
||||
priceOptions: PriceOptions
|
||||
datatokenOptions: DataTokenOptions
|
||||
onOceanChange: (event: ChangeEvent<HTMLInputElement>) => void
|
||||
generateName: () => void
|
||||
content: any
|
||||
}): ReactElement {
|
||||
const { appConfig } = useSiteMetadata()
|
||||
const { account, balance, chainId, refreshBalance } = useOcean()
|
||||
const { weightOnDataToken, tokensToMint, liquidityProviderFee } = priceOptions
|
||||
|
||||
const [error, setError] = useState<string>()
|
||||
const correctNetwork = isCorrectNetwork(chainId)
|
||||
@ -63,60 +63,59 @@ export default function Dynamic({
|
||||
}, [ocean, chainId, account])
|
||||
|
||||
return (
|
||||
<div className={stylesIndex.content}>
|
||||
<div className={styles.advanced}>
|
||||
<FormHelp className={stylesIndex.help}>{content.info}</FormHelp>
|
||||
<div className={styles.dynamic}>
|
||||
<FormHelp className={stylesIndex.help}>{content.info}</FormHelp>
|
||||
|
||||
<aside className={styles.wallet}>
|
||||
{balance?.ocean && (
|
||||
<div className={styles.balance}>
|
||||
OCEAN <strong>{balance.ocean}</strong>
|
||||
</div>
|
||||
)}
|
||||
<Wallet />
|
||||
</aside>
|
||||
|
||||
<h4 className={styles.title}>
|
||||
Data Token Liquidity Pool{' '}
|
||||
<Tooltip content={content.tooltips.poolInfo} />
|
||||
</h4>
|
||||
|
||||
<div className={styles.tokens}>
|
||||
<Coin
|
||||
name="ocean"
|
||||
symbol="OCEAN"
|
||||
value={ocean}
|
||||
weight={`${100 - Number(Number(weightOnDataToken) * 10)}%`}
|
||||
onOceanChange={onOceanChange}
|
||||
/>
|
||||
<Coin
|
||||
name="tokensToMint"
|
||||
symbol="OCEAN-CAV"
|
||||
value={tokensToMint.toString()}
|
||||
weight={`${Number(weightOnDataToken) * 10}%`}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
|
||||
<footer className={styles.summary}>
|
||||
<Label htmlFor="liquidityProviderFee">
|
||||
Liquidity Provider Fee{' '}
|
||||
<Tooltip content={content.tooltips.liquidityProviderFee} />
|
||||
</Label>
|
||||
<InputElement
|
||||
value={liquidityProviderFee}
|
||||
name="liquidityProviderFee"
|
||||
readOnly
|
||||
postfix="%"
|
||||
/>
|
||||
</footer>
|
||||
|
||||
{error && (
|
||||
<div className={styles.alertArea}>
|
||||
<Alert text={error} state="error" />
|
||||
<aside className={styles.wallet}>
|
||||
{balance?.ocean && (
|
||||
<div className={styles.balance}>
|
||||
OCEAN <strong>{balance.ocean}</strong>
|
||||
</div>
|
||||
)}
|
||||
<Wallet />
|
||||
</aside>
|
||||
|
||||
<h4 className={styles.title}>
|
||||
Data Token Liquidity Pool{' '}
|
||||
<Tooltip content={content.tooltips.poolInfo} />
|
||||
</h4>
|
||||
|
||||
<div className={styles.tokens}>
|
||||
<Coin
|
||||
name="ocean"
|
||||
datatokenOptions={{ symbol: 'OCEAN', name: 'Ocean Token' }}
|
||||
value={ocean}
|
||||
weight={`${100 - Number(Number(weightOnDataToken) * 10)}%`}
|
||||
onOceanChange={onOceanChange}
|
||||
/>
|
||||
<Coin
|
||||
name="tokensToMint"
|
||||
datatokenOptions={datatokenOptions}
|
||||
value={tokensToMint.toString()}
|
||||
weight={`${Number(weightOnDataToken) * 10}%`}
|
||||
generateName={generateName}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
|
||||
<footer className={styles.summary}>
|
||||
<Label htmlFor="liquidityProviderFee">
|
||||
Liquidity Provider Fee{' '}
|
||||
<Tooltip content={content.tooltips.liquidityProviderFee} />
|
||||
</Label>
|
||||
<InputElement
|
||||
value={liquidityProviderFee}
|
||||
name="liquidityProviderFee"
|
||||
readOnly
|
||||
postfix="%"
|
||||
/>
|
||||
</footer>
|
||||
|
||||
{error && (
|
||||
<div className={styles.alertArea}>
|
||||
<Alert text={error} state="error" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,8 +1,32 @@
|
||||
.fixed {
|
||||
composes: content from './index.module.css';
|
||||
}
|
||||
|
||||
.form {
|
||||
max-width: 12rem;
|
||||
margin: 0 auto;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.grid {
|
||||
margin-top: var(--spacer);
|
||||
display: grid;
|
||||
gap: var(--spacer);
|
||||
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.fixed label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.datatoken {
|
||||
color: var(--color-secondary);
|
||||
font-size: var(--font-size-small);
|
||||
font-weight: var(--font-weight-bold);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.datatoken strong {
|
||||
color: var(--brand-grey);
|
||||
}
|
||||
|
@ -5,24 +5,29 @@ import FormHelp from '../../../atoms/Input/Help'
|
||||
import Label from '../../../atoms/Input/Label'
|
||||
import InputElement from '../../../atoms/Input/InputElement'
|
||||
import Conversion from '../../../atoms/Price/Conversion'
|
||||
import { DataTokenOptions } from '@oceanprotocol/react'
|
||||
import RefreshName from './RefreshName'
|
||||
|
||||
export default function Fixed({
|
||||
ocean,
|
||||
datatokenOptions,
|
||||
onChange,
|
||||
generateName,
|
||||
content
|
||||
}: {
|
||||
ocean: string
|
||||
datatokenOptions: DataTokenOptions
|
||||
onChange: (event: ChangeEvent<HTMLInputElement>) => void
|
||||
generateName: () => void
|
||||
content: any
|
||||
}): ReactElement {
|
||||
return (
|
||||
<div className={stylesIndex.content}>
|
||||
<div className={styles.fixed}>
|
||||
<FormHelp className={stylesIndex.help}>{content.info}</FormHelp>
|
||||
<div className={styles.fixed}>
|
||||
<FormHelp className={stylesIndex.help}>{content.info}</FormHelp>
|
||||
|
||||
<div className={styles.grid}>
|
||||
<div className={styles.form}>
|
||||
<Label htmlFor="ocean">Ocean Tokens</Label>
|
||||
|
||||
<Label htmlFor="ocean">Ocean Token</Label>
|
||||
<InputElement
|
||||
value={ocean}
|
||||
name="ocean"
|
||||
@ -30,9 +35,16 @@ export default function Fixed({
|
||||
prefix="OCEAN"
|
||||
onChange={onChange}
|
||||
/>
|
||||
|
||||
<Conversion price={ocean} className={stylesIndex.conversion} />
|
||||
</div>
|
||||
{datatokenOptions && (
|
||||
<div className={styles.datatoken}>
|
||||
<strong>Data Token</strong>
|
||||
<RefreshName generateName={generateName} />
|
||||
<br />
|
||||
{datatokenOptions?.name} | {datatokenOptions?.symbol}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -0,0 +1,9 @@
|
||||
.refresh {
|
||||
margin-left: calc(var(--spacer) / 4) !important;
|
||||
}
|
||||
|
||||
.refresh svg {
|
||||
fill: var(--brand-pink);
|
||||
width: var(--font-size-mini);
|
||||
height: var(--font-size-mini);
|
||||
}
|
25
src/components/molecules/FormFields/Price/RefreshName.tsx
Normal file
25
src/components/molecules/FormFields/Price/RefreshName.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import styles from './RefreshName.module.css'
|
||||
import Button from '../../../atoms/Button'
|
||||
import { ReactComponent as Refresh } from '../../../../images/refresh.svg'
|
||||
|
||||
export default function RefreshName({
|
||||
generateName
|
||||
}: {
|
||||
generateName: () => void
|
||||
}): ReactElement {
|
||||
return (
|
||||
<Button
|
||||
style="text"
|
||||
size="small"
|
||||
className={styles.refresh}
|
||||
title="Generate new name & symbol"
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
generateName()
|
||||
}}
|
||||
>
|
||||
<Refresh />
|
||||
</Button>
|
||||
)
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 0 calc(var(--spacer) / 2);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.content label {
|
||||
|
@ -7,6 +7,7 @@ import Fixed from './Fixed'
|
||||
import Dynamic from './Dynamic'
|
||||
import { useField } from 'formik'
|
||||
import { useUserPreferences } from '../../../../providers/UserPreferences'
|
||||
import { DataTokenOptions, PriceOptions, useOcean } from '@oceanprotocol/react'
|
||||
|
||||
const query = graphql`
|
||||
query PriceFieldQuery {
|
||||
@ -39,15 +40,17 @@ export default function Price(props: InputProps): ReactElement {
|
||||
const { debug } = useUserPreferences()
|
||||
const data = useStaticQuery(query)
|
||||
const content = data.content.edges[0].node.childPagesJson.price
|
||||
const { ocean } = useOcean()
|
||||
|
||||
const [field, meta, helpers] = useField(props)
|
||||
const { weightOnDataToken, liquidityProviderFee } = field.value
|
||||
const priceOptions: PriceOptions = field.value
|
||||
|
||||
const [ocean, setOcean] = useState('1')
|
||||
const [amountOcean, setAmountOcean] = useState('1')
|
||||
const [tokensToMint, setTokensToMint] = useState<number>()
|
||||
const [datatokenOptions, setDatatokenOptions] = useState<DataTokenOptions>()
|
||||
|
||||
function handleOceanChange(event: ChangeEvent<HTMLInputElement>) {
|
||||
setOcean(event.target.value)
|
||||
setAmountOcean(event.target.value)
|
||||
}
|
||||
|
||||
function handleTabChange(tabName: string) {
|
||||
@ -55,11 +58,23 @@ export default function Price(props: InputProps): ReactElement {
|
||||
helpers.setValue({ ...field.value, type })
|
||||
}
|
||||
|
||||
// Always update everything when ocean changes
|
||||
function generateName() {
|
||||
if (!ocean) return
|
||||
const newDatatokenOptions = ocean.datatokens.generateDtName()
|
||||
setDatatokenOptions(newDatatokenOptions)
|
||||
}
|
||||
|
||||
// Always update everything when amountOcean changes
|
||||
useEffect(() => {
|
||||
const tokensToMint = Number(ocean) * Number(weightOnDataToken)
|
||||
const tokensToMint =
|
||||
Number(amountOcean) * Number(priceOptions.weightOnDataToken)
|
||||
setTokensToMint(tokensToMint)
|
||||
helpers.setValue({ ...field.value, tokensToMint })
|
||||
}, [amountOcean])
|
||||
|
||||
// Generate new DT name & symbol
|
||||
useEffect(() => {
|
||||
generateName()
|
||||
}, [ocean])
|
||||
|
||||
const tabs = [
|
||||
@ -67,8 +82,10 @@ export default function Price(props: InputProps): ReactElement {
|
||||
title: content.fixed.title,
|
||||
content: (
|
||||
<Fixed
|
||||
ocean={ocean}
|
||||
ocean={amountOcean}
|
||||
datatokenOptions={datatokenOptions}
|
||||
onChange={handleOceanChange}
|
||||
generateName={generateName}
|
||||
content={content.fixed}
|
||||
/>
|
||||
)
|
||||
@ -77,11 +94,11 @@ export default function Price(props: InputProps): ReactElement {
|
||||
title: content.dynamic.title,
|
||||
content: (
|
||||
<Dynamic
|
||||
ocean={ocean}
|
||||
tokensToMint={tokensToMint}
|
||||
weightOnDataToken={weightOnDataToken}
|
||||
ocean={amountOcean}
|
||||
priceOptions={{ ...priceOptions, tokensToMint }}
|
||||
datatokenOptions={datatokenOptions}
|
||||
onOceanChange={handleOceanChange}
|
||||
liquidityProviderFee={liquidityProviderFee}
|
||||
generateName={generateName}
|
||||
content={content.dynamic}
|
||||
/>
|
||||
)
|
||||
|
@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
|
||||
import { useNavigate } from '@reach/router'
|
||||
import { toast } from 'react-toastify'
|
||||
import { Formik } from 'formik'
|
||||
import { usePublish, useOcean, PriceOptions } from '@oceanprotocol/react'
|
||||
import { usePublish, DataTokenOptions } from '@oceanprotocol/react'
|
||||
import styles from './index.module.css'
|
||||
import PublishForm from './PublishForm'
|
||||
import Web3Feedback from '../../molecules/Wallet/Feedback'
|
||||
@ -11,7 +11,7 @@ import { initialValues, validationSchema } from '../../../models/FormPublish'
|
||||
import { transformPublishFormToMetadata } from './utils'
|
||||
import Preview from './Preview'
|
||||
import { MetadataPublishForm } from '../../../@types/MetaData'
|
||||
import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
|
||||
// import { useSiteMetadata } from '../../../hooks/useSiteMetadata'
|
||||
import { useUserPreferences } from '../../../providers/UserPreferences'
|
||||
|
||||
export default function PublishPage({
|
||||
@ -19,7 +19,8 @@ export default function PublishPage({
|
||||
}: {
|
||||
content: { form: FormContent }
|
||||
}): ReactElement {
|
||||
const { marketFeeAddress, marketFeeAmount } = useSiteMetadata()
|
||||
// TODO: implement marketFee
|
||||
// const { marketFeeAddress, marketFeeAmount } = useSiteMetadata()
|
||||
const { debug } = useUserPreferences()
|
||||
const { publish, publishError, isLoading, publishStepText } = usePublish()
|
||||
const navigate = useNavigate()
|
||||
@ -31,15 +32,15 @@ export default function PublishPage({
|
||||
const metadata = transformPublishFormToMetadata(values)
|
||||
const priceOptions = values.price
|
||||
const serviceType = values.access === 'Download' ? 'access' : 'compute'
|
||||
let datatokenOptions: DataTokenOptions
|
||||
|
||||
try {
|
||||
// mpAddress and mpFee are not yet implemented in ocean js so are not used
|
||||
const ddo = await publish(
|
||||
metadata as any,
|
||||
priceOptions,
|
||||
serviceType
|
||||
// marketFeeAddress,
|
||||
// marketFeeAmount
|
||||
serviceType,
|
||||
datatokenOptions
|
||||
)
|
||||
|
||||
if (publishError) {
|
||||
|
3
src/images/refresh.svg
Normal file
3
src/images/refresh.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.64 2.35C12.19 0.9 10.2 0 7.99 0C3.57 0 0 3.58 0 8C0 12.42 3.57 16 7.99 16C11.72 16 14.83 13.45 15.72 10H13.64C12.82 12.33 10.6 14 7.99 14C4.68 14 1.99 11.31 1.99 8C1.99 4.69 4.68 2 7.99 2C9.65 2 11.13 2.69 12.21 3.78L8.99 7H15.99V0L13.64 2.35Z" />
|
||||
</svg>
|
After Width: | Height: | Size: 353 B |
Loading…
Reference in New Issue
Block a user