1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

Merge branch 'v4' into feature/v4-c2d

This commit is contained in:
Bogdan Fazakas 2022-04-04 15:19:31 +03:00
commit 0c87abe24d
14 changed files with 104 additions and 34 deletions

16
package-lock.json generated
View File

@ -13,7 +13,7 @@
"@coingecko/cryptoformat": "^0.4.4", "@coingecko/cryptoformat": "^0.4.4",
"@loadable/component": "^5.15.2", "@loadable/component": "^5.15.2",
"@oceanprotocol/art": "^3.2.0", "@oceanprotocol/art": "^3.2.0",
"@oceanprotocol/lib": "^1.0.0-next.29", "@oceanprotocol/lib": "^1.0.0-next.32",
"@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^4.0.7", "@portis/web3": "^4.0.7",
"@tippyjs/react": "^4.2.6", "@tippyjs/react": "^4.2.6",
@ -3404,9 +3404,9 @@
} }
}, },
"node_modules/@oceanprotocol/lib": { "node_modules/@oceanprotocol/lib": {
"version": "1.0.0-next.29", "version": "1.0.0-next.32",
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.29.tgz", "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.32.tgz",
"integrity": "sha512-/QualMxcT8XvnhZ/ixtShI7MVQn6Arkg0R9f8lMeQw4Dyykh7ZuIlfJxvIjzsMeSavdAgt2BIy1slzr6Z5VtyA==", "integrity": "sha512-J+4A2rIE8IAXLCGBhyXuWM+0gwJxXf3JG/3XBZEhjMvWUNFEGeJLD26fr7evQY13Oy9mXHyUpp6rQxxHvE2/zA==",
"dependencies": { "dependencies": {
"@oceanprotocol/contracts": "1.0.0-alpha.26", "@oceanprotocol/contracts": "1.0.0-alpha.26",
"bignumber.js": "^9.0.2", "bignumber.js": "^9.0.2",
@ -26719,16 +26719,15 @@
} }
}, },
"@oceanprotocol/lib": { "@oceanprotocol/lib": {
"version": "1.0.0-next.29", "version": "1.0.0-next.32",
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.29.tgz", "resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-1.0.0-next.32.tgz",
"integrity": "sha512-/QualMxcT8XvnhZ/ixtShI7MVQn6Arkg0R9f8lMeQw4Dyykh7ZuIlfJxvIjzsMeSavdAgt2BIy1slzr6Z5VtyA==", "integrity": "sha512-J+4A2rIE8IAXLCGBhyXuWM+0gwJxXf3JG/3XBZEhjMvWUNFEGeJLD26fr7evQY13Oy9mXHyUpp6rQxxHvE2/zA==",
"requires": { "requires": {
"@oceanprotocol/contracts": "1.0.0-alpha.26", "@oceanprotocol/contracts": "1.0.0-alpha.26",
"bignumber.js": "^9.0.2", "bignumber.js": "^9.0.2",
"cross-fetch": "^3.1.5", "cross-fetch": "^3.1.5",
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"decimal.js": "^10.3.1", "decimal.js": "^10.3.1",
"web3": "^1.7.1",
"web3-core": "^1.7.1", "web3-core": "^1.7.1",
"web3-eth-contract": "^1.7.1" "web3-eth-contract": "^1.7.1"
} }
@ -26831,7 +26830,6 @@
"integrity": "sha512-5vwpq6kbvwkQwKqAoOU3L72GZ3Ta8RRrewKj9OJRolx28KLJJ8Dg9Rf7obRwt5jQA9bkYd8gqzMTrI7H3xLfaw==", "integrity": "sha512-5vwpq6kbvwkQwKqAoOU3L72GZ3Ta8RRrewKj9OJRolx28KLJJ8Dg9Rf7obRwt5jQA9bkYd8gqzMTrI7H3xLfaw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@oclif/config": "^1.15.1",
"@oclif/errors": "^1.3.3", "@oclif/errors": "^1.3.3",
"@oclif/parser": "^3.8.3", "@oclif/parser": "^3.8.3",
"@oclif/plugin-help": "^3", "@oclif/plugin-help": "^3",

View File

@ -21,7 +21,7 @@
"@coingecko/cryptoformat": "^0.4.4", "@coingecko/cryptoformat": "^0.4.4",
"@loadable/component": "^5.15.2", "@loadable/component": "^5.15.2",
"@oceanprotocol/art": "^3.2.0", "@oceanprotocol/art": "^3.2.0",
"@oceanprotocol/lib": "^1.0.0-next.29", "@oceanprotocol/lib": "^1.0.0-next.32",
"@oceanprotocol/typographies": "^0.1.0", "@oceanprotocol/typographies": "^0.1.0",
"@portis/web3": "^4.0.7", "@portis/web3": "^4.0.7",
"@tippyjs/react": "^4.2.6", "@tippyjs/react": "^4.2.6",

View File

@ -56,7 +56,13 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
// const [fetchInterval, setFetchInterval] = useState<NodeJS.Timeout>() // const [fetchInterval, setFetchInterval] = useState<NodeJS.Timeout>()
const fetchAllData = useCallback(async () => { const fetchAllData = useCallback(async () => {
if (!asset?.chainId || !asset?.accessDetails?.addressOrId || !owner) return if (
!accountId ||
!asset?.chainId ||
!asset?.accessDetails?.addressOrId ||
!owner
)
return
const response = await getPoolData( const response = await getPoolData(
asset.chainId, asset.chainId,
@ -64,6 +70,7 @@ function PoolProvider({ children }: { children: ReactNode }): ReactElement {
owner, owner,
accountId || '' accountId || ''
) )
if (!response) return if (!response) return
setPoolData(response.poolData) setPoolData(response.poolData)

View File

@ -1 +1 @@
export const MAX_DECIMALS = 5 export const MAX_DECIMALS = 6

View File

@ -65,7 +65,7 @@ export default function FilesInput(props: InputProps): ReactElement {
return ( return (
<> <>
{field.value[0].valid !== undefined ? ( {field?.value && field?.value[0]?.valid !== undefined ? (
<FileInfo file={field.value[0]} handleClose={handleClose} /> <FileInfo file={field.value[0]} handleClose={handleClose} />
) : ( ) : (
<UrlInput <UrlInput

View File

@ -23,7 +23,7 @@ const txHistoryQueryByPool = gql`
poolTransactions( poolTransactions(
orderBy: timestamp orderBy: timestamp
orderDirection: desc orderDirection: desc
where: { pool: $pool } where: { pool: $pool, user: $user }
first: 1000 first: 1000
) { ) {
baseToken { baseToken {
@ -40,6 +40,9 @@ const txHistoryQueryByPool = gql`
tx tx
timestamp timestamp
pool { pool {
datatoken {
id
}
id id
} }
} }
@ -67,6 +70,9 @@ const txHistoryQuery = gql`
tx tx
timestamp timestamp
pool { pool {
datatoken {
id
}
id id
} }
} }
@ -124,7 +130,7 @@ export default function PoolTransactions({
accountId accountId
}: { }: {
poolAddress?: string poolAddress?: string
poolChainId?: number[] poolChainId?: number
minimal?: boolean minimal?: boolean
accountId: string accountId: string
}): ReactElement { }): ReactElement {
@ -146,7 +152,7 @@ export default function PoolTransactions({
const result = await fetchDataForMultipleChains( const result = await fetchDataForMultipleChains(
poolAddress ? txHistoryQueryByPool : txHistoryQuery, poolAddress ? txHistoryQueryByPool : txHistoryQuery,
variables, variables,
poolAddress ? poolChainId : chainIds poolAddress ? [poolChainId] : chainIds
) )
for (let i = 0; i < result.length; i++) { for (let i = 0; i < result.length; i++) {
@ -166,24 +172,24 @@ export default function PoolTransactions({
return return
} }
const poolTransactions: PoolTransaction[] = [] const poolTransactions: PoolTransaction[] = []
const dtList: string[] = [] let dtList: string[] = []
for (let i = 0; i < data.length; i++) {
dtList.push(data[i]?.datatoken?.address)
}
dtList = [...new Set(data.map((item) => item.pool.datatoken.id))]
if (dtList.length === 0) { if (dtList.length === 0) {
setTransactions([]) setTransactions([])
setIsLoading(false) setIsLoading(false)
return return
} }
const ddoList = await getAssetsFromDtList(dtList, chainIds, cancelToken) const ddoList = !minimal
? await getAssetsFromDtList(dtList, chainIds, cancelToken)
: []
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
poolTransactions.push({ poolTransactions.push({
...data[i], ...data[i],
networkId: getAsset(ddoList, data[i].datatoken.address).chainId, networkId: !minimal
asset: getAsset(ddoList, data[i].datatoken.address) ? getAsset(ddoList, data[i].pool.datatoken.id).chainId
: poolChainId,
asset: !minimal ? getAsset(ddoList, data[i].pool.datatoken.id) : null
}) })
} }
const sortedTransactions = poolTransactions.sort( const sortedTransactions = poolTransactions.sort(

View File

@ -26,6 +26,7 @@
.button:last-child { .button:last-child {
margin-right: 0; margin-right: 0;
min-width: auto;
} }
.button:hover, .button:hover,
@ -33,8 +34,8 @@
color: var(--brand-white); color: var(--brand-white);
background: var(--brand-grey-light); background: var(--brand-grey-light);
text-decoration: none; text-decoration: none;
transform: translate3d(0, -0.05rem, 0);
box-shadow: 0 12px 30px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 12px 30px 0 rgba(0, 0, 0, 0.1);
transform: translate3d(0, -0.05rem, 0);
} }
.button:active { .button:active {

View File

@ -25,7 +25,7 @@ export function getOptions(
borderColor: isDarkMode ? `#41474e` : `#e2e2e2`, borderColor: isDarkMode ? `#41474e` : `#e2e2e2`,
callbacks: { callbacks: {
label: (tooltipItem: TooltipItem<any>) => label: (tooltipItem: TooltipItem<any>) =>
`${formatPrice(`${tooltipItem.formattedValue}`, locale)} ${symbol}` `${tooltipItem.formattedValue} ${symbol}`
} }
} }
}, },

View File

@ -31,13 +31,17 @@
.maximum { .maximum {
position: absolute; position: absolute;
right: -2rem; right: 0;
bottom: 2rem; bottom: 2.5rem;
font-size: var(--font-size-mini); font-size: var(--font-size-mini);
min-width: 5rem; min-width: 5rem;
text-align: center; text-align: center;
} }
.maximum:hover {
transform: none;
}
.toggle { .toggle {
margin-top: calc(var(--spacer) / 2); margin-top: calc(var(--spacer) / 2);
margin-bottom: 0; margin-bottom: 0;

View File

@ -67,11 +67,16 @@ export default function Remove({
minOceanAmount minOceanAmount
) )
setTxId(result?.transactionHash) setTxId(result?.transactionHash)
// fetch new data
fetchAllData() fetchAllData()
} catch (error) { } catch (error) {
LoggerInstance.error(error.message) LoggerInstance.error(error.message)
toast.error(error.message) toast.error(error.message)
} finally { } finally {
// reset slider after transaction
setAmountPercent('0')
setAmountOcean('0')
setMinOceanAmount('0')
setIsLoading(false) setIsLoading(false)
} }
} }
@ -80,8 +85,10 @@ export default function Remove({
if (!accountId || !poolTokens) return if (!accountId || !poolTokens) return
async function getMax() { async function getMax() {
const poolTokensAmount =
!poolTokens || poolTokens === '0' ? '1' : poolTokens
const maxTokensToRemoveFromPool = calcMaxExactOut(totalPoolTokens) const maxTokensToRemoveFromPool = calcMaxExactOut(totalPoolTokens)
const poolTokensDecimal = new Decimal(poolTokens) const poolTokensDecimal = new Decimal(poolTokensAmount)
const maxTokensToRemoveForUser = maxTokensToRemoveFromPool.greaterThan( const maxTokensToRemoveForUser = maxTokensToRemoveFromPool.greaterThan(
poolTokensDecimal poolTokensDecimal
) )
@ -105,6 +112,7 @@ export default function Remove({
tokenOutAddress, tokenOutAddress,
newAmountPoolShares newAmountPoolShares
) )
setAmountOcean(newAmountOcean) setAmountOcean(newAmountOcean)
}, 150) }, 150)
) )
@ -116,6 +124,11 @@ export default function Remove({
}, [amountPoolShares, accountId, poolTokens, poolAddress, totalPoolTokens]) }, [amountPoolShares, accountId, poolTokens, poolAddress, totalPoolTokens])
useEffect(() => { useEffect(() => {
if (!amountOcean || amountPercent === '0') {
setMinOceanAmount('0')
return
}
const minOceanAmount = new Decimal(amountOcean) const minOceanAmount = new Decimal(amountOcean)
.mul(new Decimal(100).minus(new Decimal(slippage))) .mul(new Decimal(100).minus(new Decimal(slippage)))
.dividedBy(100) .dividedBy(100)
@ -220,7 +233,12 @@ export default function Remove({
actionName={content.pool.remove.action} actionName={content.pool.remove.action}
action={handleRemoveLiquidity} action={handleRemoveLiquidity}
successMessage="Successfully removed liquidity." successMessage="Successfully removed liquidity."
isDisabled={!isAssetNetwork || amountOcean === '0'} isDisabled={
!isAssetNetwork ||
amountPercent === '0' ||
amountOcean === '0' ||
poolTokens === '0'
}
txId={txId} txId={txId}
tokenAddress={tokenOutAddress} tokenAddress={tokenOutAddress}
tokenSymbol={tokenOutSymbol} tokenSymbol={tokenOutSymbol}

View File

@ -208,7 +208,7 @@ export default function Pool(): ReactElement {
<PoolTransactions <PoolTransactions
accountId={accountId} accountId={accountId}
poolAddress={asset?.accessDetails?.addressOrId} poolAddress={asset?.accessDetails?.addressOrId}
poolChainId={[asset?.chainId]} poolChainId={asset?.chainId}
minimal minimal
/> />
</AssetActionHistoryTable> </AssetActionHistoryTable>

View File

@ -34,7 +34,13 @@ export default function Price({
<> <>
<div className={styles.grid}> <div className={styles.grid}>
<div className={styles.form}> <div className={styles.form}>
<Input type="number" prefix="OCEAN" {...field} /> <Input
type="number"
min="1"
placeholder="0"
prefix="OCEAN"
{...field}
/>
<Error meta={meta} /> <Error meta={meta} />
</div> </div>
<div className={styles.datatoken}> <div className={styles.datatoken}>

View File

@ -207,7 +207,7 @@ export async function createTokensAndPricing(
const ercParams: Erc20CreateParams = { const ercParams: Erc20CreateParams = {
templateIndex: values.pricing.type === 'dynamic' ? 1 : 2, templateIndex: values.pricing.type === 'dynamic' ? 1 : 2,
minter: accountId, minter: accountId,
feeManager: accountId, paymentCollector: accountId,
mpFeeAddress: appConfig.marketFeeAddress, mpFeeAddress: appConfig.marketFeeAddress,
feeToken: config.oceanTokenAddress, feeToken: config.oceanTokenAddress,
feeAmount: appConfig.publisherMarketOrderFee, feeAmount: appConfig.publisherMarketOrderFee,

View File

@ -1,8 +1,10 @@
import { MAX_DECIMALS } from '@utils/constants'
import * as Yup from 'yup' import * as Yup from 'yup'
// TODO: conditional validation // TODO: conditional validation
// e.g. when algo is selected, Docker image is required // e.g. when algo is selected, Docker image is required
// hint, hint: https://github.com/jquense/yup#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema // hint, hint: https://github.com/jquense/yup#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema
const validationMetadata = { const validationMetadata = {
type: Yup.string() type: Yup.string()
.matches(/dataset|algorithm/g, { excludeEmptyString: true }) .matches(/dataset|algorithm/g, { excludeEmptyString: true })
@ -54,25 +56,53 @@ const validationService = {
}) })
} }
const maxDecimalsValidation = new RegExp(
'^\\d+(\\.\\d{1,' + MAX_DECIMALS + '})?$'
)
const validationPricing = { const validationPricing = {
type: Yup.string() type: Yup.string()
.matches(/fixed|dynamic|free/g, { excludeEmptyString: true }) .matches(/fixed|dynamic|free/g, { excludeEmptyString: true })
.required('Required'), .required('Required'),
// https://github.com/jquense/yup#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema // https://github.com/jquense/yup#mixedwhenkeys-string--arraystring-builder-object--value-schema-schema-schema
price: Yup.number() price: Yup.number()
.min(1, (param: { min: number }) => `Must be more or equal to ${param.min}`) .min(1, (param: { min: number }) => `Must be more or equal to ${param.min}`)
.max(
1000000,
(param: { max: number }) => `Must be less than or equal to ${param.max}`
)
.test(
'maxDigitsAfterDecimal',
`Must have maximum ${MAX_DECIMALS} decimal digits`,
(param) => maxDecimalsValidation.test(param?.toString())
)
.required('Required'), .required('Required'),
amountDataToken: Yup.number() amountDataToken: Yup.number()
.min(50, (param) => `Must be more or equal to ${param.min}`) .min(50, (param) => `Must be more or equal to ${param.min}`)
.required('Required'), .required('Required'),
amountOcean: Yup.number() amountOcean: Yup.number()
.min(50, (param) => `Must be more or equal to ${param.min}`) .min(50, (param) => `Must be more or equal to ${param.min}`)
.max(
1000000,
(param: { max: number }) => `Must be less than or equal to ${param.max}`
)
.test(
'maxDigitsAfterDecimal',
`Must have maximum ${MAX_DECIMALS} decimal digits`,
(param) => maxDecimalsValidation.test(param?.toString())
)
.required('Required'), .required('Required'),
weightOnDataToken: Yup.string().required('Required'), weightOnDataToken: Yup.string().required('Required'),
weightOnOcean: Yup.string().required('Required'), weightOnOcean: Yup.string().required('Required'),
swapFee: Yup.number() swapFee: Yup.number()
.min(0.1, (param) => `Must be more or equal to ${param.min}`) .min(0.1, (param) => `Must be more or equal to ${param.min}`)
.max(10, 'Maximum is 10%') .max(10, 'Maximum is 10%')
.test(
'maxDigitsAfterDecimal',
`Must have maximum ${MAX_DECIMALS} decimal digits`,
(param) => maxDecimalsValidation.test(param?.toString())
)
.required('Required') .required('Required')
} }