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

Merge branch 'feature/v4-c2d' into 'fix/compute-jobs'

This commit is contained in:
Bogdan Fazakas 2022-04-04 15:22:18 +03:00
commit 2dc12a2542
14 changed files with 199 additions and 35 deletions

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

@ -10,7 +10,7 @@ import { useAsset } from '@context/Asset'
import { useWeb3 } from '@context/Web3' import { useWeb3 } from '@context/Web3'
import content from '../../../../../content/pages/startComputeDataset.json' import content from '../../../../../content/pages/startComputeDataset.json'
import { Asset } from '@oceanprotocol/lib' import { Asset } from '@oceanprotocol/lib'
import { AccessDetails } from 'src/@types/Price' import { AccessDetails, OrderPriceAndFees } from 'src/@types/Price'
import { import {
getAccessDetailsForAssets, getAccessDetailsForAssets,
getAccessDetails getAccessDetails
@ -40,7 +40,9 @@ export default function FormStartCompute({
selectedComputeAssetTimeout, selectedComputeAssetTimeout,
stepText, stepText,
isConsumable, isConsumable,
consumableFeedback consumableFeedback,
datasetOrderPriceAndFees,
algoOrderPriceAndFees
}: { }: {
algorithms: AssetSelectionAsset[] algorithms: AssetSelectionAsset[]
ddoListAlgorithms: Asset[] ddoListAlgorithms: Asset[]
@ -65,11 +67,19 @@ export default function FormStartCompute({
stepText: string stepText: string
isConsumable: boolean isConsumable: boolean
consumableFeedback: string consumableFeedback: string
datasetOrderPriceAndFees?: OrderPriceAndFees
algoOrderPriceAndFees?: OrderPriceAndFees
}): ReactElement { }): ReactElement {
const { isValid, values }: FormikContextType<{ algorithm: string }> = const { isValid, values }: FormikContextType<{ algorithm: string }> =
useFormikContext() useFormikContext()
const { asset, isAssetNetwork } = useAsset() const { asset, isAssetNetwork } = useAsset()
const [totalPrice, setTotalPrice] = useState(asset?.accessDetails?.price) const [totalPrice, setTotalPrice] = useState(asset?.accessDetails?.price)
const [datasetOrderPrice, setDatasetOrderPrice] = useState(
asset?.accessDetails?.price
)
const [algoOrderPrice, setAlgoOrderPrice] = useState(
selectedAlgorithmAsset?.accessDetails?.price
)
const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>(false) const [isBalanceSufficient, setIsBalanceSufficient] = useState<boolean>(false)
const { accountId, balance } = useWeb3() const { accountId, balance } = useWeb3()
@ -106,12 +116,24 @@ export default function FormStartCompute({
useEffect(() => { useEffect(() => {
if (!asset?.accessDetails || !selectedAlgorithmAsset?.accessDetails) return if (!asset?.accessDetails || !selectedAlgorithmAsset?.accessDetails) return
setDatasetOrderPrice(
datasetOrderPriceAndFees?.price || asset.accessDetails.price
)
setAlgoOrderPrice(
algoOrderPriceAndFees?.price ||
selectedAlgorithmAsset?.accessDetails.price
)
const priceDataset = const priceDataset =
hasPreviousOrder || hasDatatoken ? 0 : Number(asset.accessDetails.price) hasPreviousOrder || hasDatatoken
? 0
: Number(datasetOrderPriceAndFees?.price || asset.accessDetails.price)
const priceAlgo = const priceAlgo =
hasPreviousOrderSelectedComputeAsset || hasDatatokenSelectedComputeAsset hasPreviousOrderSelectedComputeAsset || hasDatatokenSelectedComputeAsset
? 0 ? 0
: Number(selectedAlgorithmAsset?.accessDetails.price) : Number(
algoOrderPriceAndFees?.price ||
selectedAlgorithmAsset?.accessDetails.price
)
setTotalPrice((priceDataset + priceAlgo).toString()) setTotalPrice((priceDataset + priceAlgo).toString())
}, [ }, [
@ -120,7 +142,9 @@ export default function FormStartCompute({
hasPreviousOrder, hasPreviousOrder,
hasDatatoken, hasDatatoken,
hasPreviousOrderSelectedComputeAsset, hasPreviousOrderSelectedComputeAsset,
hasDatatokenSelectedComputeAsset hasDatatokenSelectedComputeAsset,
datasetOrderPriceAndFees,
algoOrderPriceAndFees
]) ])
useEffect(() => { useEffect(() => {
@ -153,6 +177,8 @@ export default function FormStartCompute({
algorithmConsumeDetails={selectedAlgorithmAsset?.accessDetails} algorithmConsumeDetails={selectedAlgorithmAsset?.accessDetails}
symbol={oceanSymbol} symbol={oceanSymbol}
totalPrice={Number.parseFloat(totalPrice)} totalPrice={Number.parseFloat(totalPrice)}
datasetOrderPrice={datasetOrderPrice}
algoOrderPrice={algoOrderPrice}
/> />
<ButtonBuy <ButtonBuy

View File

@ -15,6 +15,8 @@ interface PriceOutputProps {
hasDatatokenSelectedComputeAsset: boolean hasDatatokenSelectedComputeAsset: boolean
algorithmConsumeDetails: AccessDetails algorithmConsumeDetails: AccessDetails
selectedComputeAssetTimeout: string selectedComputeAssetTimeout: string
datasetOrderPrice?: number
algoOrderPrice?: number
} }
function Row({ function Row({
@ -62,7 +64,9 @@ export default function PriceOutput({
hasPreviousOrderSelectedComputeAsset, hasPreviousOrderSelectedComputeAsset,
hasDatatokenSelectedComputeAsset, hasDatatokenSelectedComputeAsset,
algorithmConsumeDetails, algorithmConsumeDetails,
selectedComputeAssetTimeout selectedComputeAssetTimeout,
datasetOrderPrice,
algoOrderPrice
}: PriceOutputProps): ReactElement { }: PriceOutputProps): ReactElement {
const { asset } = useAsset() const { asset } = useAsset()
@ -76,14 +80,20 @@ export default function PriceOutput({
<Row <Row
hasPreviousOrder={hasPreviousOrder} hasPreviousOrder={hasPreviousOrder}
hasDatatoken={hasDatatoken} hasDatatoken={hasDatatoken}
price={Number.parseFloat(asset?.accessDetails?.price)} price={
datasetOrderPrice ||
Number.parseFloat(asset?.accessDetails?.price)
}
timeout={assetTimeout} timeout={assetTimeout}
symbol={symbol} symbol={symbol}
/> />
<Row <Row
hasPreviousOrder={hasPreviousOrderSelectedComputeAsset} hasPreviousOrder={hasPreviousOrderSelectedComputeAsset}
hasDatatoken={hasDatatokenSelectedComputeAsset} hasDatatoken={hasDatatokenSelectedComputeAsset}
price={Number.parseFloat(algorithmConsumeDetails?.price)} price={
algoOrderPrice ||
Number.parseFloat(algorithmConsumeDetails?.price)
}
timeout={selectedComputeAssetTimeout} timeout={selectedComputeAssetTimeout}
symbol={symbol} symbol={symbol}
sign="+" sign="+"

View File

@ -83,13 +83,21 @@ export default function Compute({
const [isConsumablePrice, setIsConsumablePrice] = useState(true) const [isConsumablePrice, setIsConsumablePrice] = useState(true)
const [isAlgoConsumablePrice, setIsAlgoConsumablePrice] = useState(true) const [isAlgoConsumablePrice, setIsAlgoConsumablePrice] = useState(true)
const [computeStatusText, setComputeStatusText] = useState('') const [computeStatusText, setComputeStatusText] = useState('')
const [datasetOrderPriceAndFees, setDatasetOrderPriceAndFees] =
useState<OrderPriceAndFees>()
const [isRequestingDataseOrderPrice, setIsRequestingDataseOrderPrice] =
useState(false)
const [algoOrderPriceAndFees, setAlgoOrderPriceAndFees] =
useState<OrderPriceAndFees>()
const [isRequestingAlgoOrderPrice, setIsRequestingAlgoOrderPrice] =
useState(false)
const isComputeButtonDisabled = const isComputeButtonDisabled =
isJobStarting === true || isJobStarting === true ||
file === null || file === null ||
(!validOrderTx && !hasDatatoken && !isConsumablePrice) || (!validOrderTx && !hasDatatoken && !isConsumablePrice) ||
(!validAlgorithmOrderTx && !hasAlgoAssetDatatoken && !isAlgoConsumablePrice) (!validAlgorithmOrderTx && !hasAlgoAssetDatatoken && !isAlgoConsumablePrice)
async function checkAssetDTBalance(asset: DDO) { async function checkAssetDTBalance(asset: DDO): Promise<boolean> {
if (!asset?.services[0].datatokenAddress) return if (!asset?.services[0].datatokenAddress) return
const datatokenInstance = new Datatoken(web3) const datatokenInstance = new Datatoken(web3)
const dtBalance = await datatokenInstance.balance( const dtBalance = await datatokenInstance.balance(
@ -97,7 +105,9 @@ export default function Compute({
accountId accountId
) )
setAlgorithmDTBalance(new Decimal(dtBalance).toString()) setAlgorithmDTBalance(new Decimal(dtBalance).toString())
setHasAlgoAssetDatatoken(Number(dtBalance) >= 1) const hasAlgoDt = Number(dtBalance) >= 1
setHasAlgoAssetDatatoken(hasAlgoDt)
return hasAlgoDt
} }
useEffect(() => { useEffect(() => {
@ -106,16 +116,56 @@ export default function Compute({
setIsConsumablePrice(asset?.accessDetails?.isPurchasable) setIsConsumablePrice(asset?.accessDetails?.isPurchasable)
setIsOwned(asset?.accessDetails?.isOwned) setIsOwned(asset?.accessDetails?.isOwned)
setValidOrderTx(asset?.accessDetails?.validOrderTx) setValidOrderTx(asset?.accessDetails?.validOrderTx)
async function initDatasetPriceAndFees() {
if (
asset?.accessDetails?.addressOrId === ZERO_ADDRESS ||
asset?.accessDetails?.type === 'free'
)
return
setIsRequestingDataseOrderPrice(true)
setComputeStatusText('Calculating price including fees.')
const orderPriceAndFees = await getOrderPriceAndFees(asset, accountId)
setDatasetOrderPriceAndFees(orderPriceAndFees)
setIsRequestingDataseOrderPrice(false)
}
initDatasetPriceAndFees()
}, [asset?.accessDetails]) }, [asset?.accessDetails])
useEffect(() => { useEffect(() => {
if (!selectedAlgorithmAsset?.accessDetails || !accountId) return if (!selectedAlgorithmAsset?.accessDetails || !accountId) return
checkAssetDTBalance(selectedAlgorithmAsset)
setIsConsumablePrice(selectedAlgorithmAsset?.accessDetails?.isPurchasable) setIsConsumablePrice(selectedAlgorithmAsset?.accessDetails?.isPurchasable)
setIsAlgorithmOwned(selectedAlgorithmAsset?.accessDetails?.isOwned) setIsAlgorithmOwned(selectedAlgorithmAsset?.accessDetails?.isOwned)
setValidAlgorithmOrderTx( setValidAlgorithmOrderTx(
selectedAlgorithmAsset?.accessDetails?.validOrderTx selectedAlgorithmAsset?.accessDetails?.validOrderTx
) )
async function initAlgoPriceAndFees() {
if (
selectedAlgorithmAsset?.accessDetails?.addressOrId === ZERO_ADDRESS ||
selectedAlgorithmAsset?.accessDetails?.type === 'free'
)
return
setIsRequestingAlgoOrderPrice(true)
setComputeStatusText('Calculating price including fees.')
const orderPriceAndFees = await getOrderPriceAndFees(
selectedAlgorithmAsset,
accountId
)
setAlgoOrderPriceAndFees(orderPriceAndFees)
setIsRequestingAlgoOrderPrice(false)
}
async function initSelectedAlgo() {
const hasAlgoDt = await checkAssetDTBalance(selectedAlgorithmAsset)
!hasAlgoDt && (await initAlgoPriceAndFees())
}
initSelectedAlgo()
}, [selectedAlgorithmAsset]) }, [selectedAlgorithmAsset])
useEffect(() => { useEffect(() => {
@ -406,7 +456,11 @@ export default function Compute({
ddoListAlgorithms={ddoAlgorithmList} ddoListAlgorithms={ddoAlgorithmList}
selectedAlgorithmAsset={selectedAlgorithmAsset} selectedAlgorithmAsset={selectedAlgorithmAsset}
setSelectedAlgorithm={setSelectedAlgorithmAsset} setSelectedAlgorithm={setSelectedAlgorithmAsset}
isLoading={isJobStarting} isLoading={
isJobStarting ||
isRequestingDataseOrderPrice ||
isRequestingAlgoOrderPrice
}
isComputeButtonDisabled={isComputeButtonDisabled} isComputeButtonDisabled={isComputeButtonDisabled}
hasPreviousOrder={validOrderTx !== undefined} hasPreviousOrder={validOrderTx !== undefined}
hasDatatoken={hasDatatoken} hasDatatoken={hasDatatoken}
@ -436,6 +490,8 @@ export default function Compute({
stepText={computeStatusText} stepText={computeStatusText}
isConsumable={isConsumable} isConsumable={isConsumable}
consumableFeedback={consumableFeedback} consumableFeedback={consumableFeedback}
datasetOrderPriceAndFees={datasetOrderPriceAndFees}
algoOrderPriceAndFees={algoOrderPriceAndFees}
/> />
</Formik> </Formik>
)} )}

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

@ -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')
} }