From 0c5c8effdeb3ea37d266d31dc3b6f49c614a0a6a Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Mon, 24 Jan 2022 10:39:07 +0000 Subject: [PATCH 01/12] restore live calculations --- .../Asset/AssetActions/Pool/Add/FormAdd.tsx | 58 +++++++++------- .../Asset/AssetActions/Pool/Add/index.tsx | 69 ++++++++++++------- 2 files changed, 77 insertions(+), 50 deletions(-) diff --git a/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx b/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx index a6fa4df35..ad88473ec 100644 --- a/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx +++ b/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx @@ -16,8 +16,10 @@ import { useWeb3 } from '@context/Web3' import { isValidNumber } from '@utils/numbers' import Decimal from 'decimal.js' import { useAsset } from '@context/Asset' +import { LoggerInstance, Pool } from '@oceanprotocol/lib' export default function FormAdd({ + tokenInAddress, coin, dtBalance, dtSymbol, @@ -30,6 +32,7 @@ export default function FormAdd({ setNewPoolTokens, setNewPoolShare }: { + tokenInAddress: string coin: string dtBalance: string dtSymbol: string @@ -67,39 +70,42 @@ export default function FormAdd({ useEffect(() => { async function calculatePoolShares() { - // if (!web3) return - // const tokenInAddress = - // coin === 'OCEAN' ? ocean.pool.oceanAddress : ocean.pool.dtAddress - // if (!values.amount || !tokenInAddress) { - // setNewPoolTokens('0') - // setNewPoolShare('0') - // return - // } - // if (Number(values.amount) > Number(amountMax)) return - // const poolTokens = await ocean.pool.calcPoolOutGivenSingleIn( - // poolAddress, - // tokenInAddress, - // `${values.amount}` - // ) - // setNewPoolTokens(poolTokens) - // const newPoolShareDecimal = - // isValidNumber(poolTokens) && isValidNumber(totalPoolTokens) - // ? new Decimal(poolTokens) - // .dividedBy( - // new Decimal(totalPoolTokens).plus(new Decimal(poolTokens)) - // ) - // .mul(100) - // .toString() - // : '0' - // totalBalance && setNewPoolShare(newPoolShareDecimal) + if (!web3) return + + if (!values.amount || !tokenInAddress) { + setNewPoolTokens('0') + setNewPoolShare('0') + return + } + if (Number(values.amount) > Number(amountMax)) return + + const poolInstance = new Pool(web3, LoggerInstance) + + const poolTokens = await poolInstance.calcPoolOutGivenSingleIn( + poolAddress, + tokenInAddress, + `${values.amount}` + ) + setNewPoolTokens(poolTokens) + const newPoolShareDecimal = + isValidNumber(poolTokens) && isValidNumber(totalPoolTokens) + ? new Decimal(poolTokens) + .dividedBy( + new Decimal(totalPoolTokens).plus(new Decimal(poolTokens)) + ) + .mul(100) + .toString() + : '0' + totalBalance && setNewPoolShare(newPoolShareDecimal) } calculatePoolShares() }, [ + tokenInAddress, + web3, values.amount, totalBalance, totalPoolTokens, amountMax, - coin, poolAddress, setNewPoolTokens, setNewPoolShare diff --git a/src/components/Asset/AssetActions/Pool/Add/index.tsx b/src/components/Asset/AssetActions/Pool/Add/index.tsx index 2e058d38a..b83a9e768 100644 --- a/src/components/Asset/AssetActions/Pool/Add/index.tsx +++ b/src/components/Asset/AssetActions/Pool/Add/index.tsx @@ -13,7 +13,7 @@ import DebugOutput from '@shared/DebugOutput' import { useWeb3 } from '@context/Web3' import { useAsset } from '@context/Asset' import content from '../../../../../../content/price.json' -import { Datatoken } from '@oceanprotocol/lib' +import { Datatoken, LoggerInstance, Pool } from '@oceanprotocol/lib' export interface FormAddLiquidity { amount: number @@ -53,6 +53,7 @@ export default function Add({ const [newPoolTokens, setNewPoolTokens] = useState('0') const [newPoolShare, setNewPoolShare] = useState('0') const [isWarningAccepted, setIsWarningAccepted] = useState(false) + const [tokenInAddress, setTokenInAddress] = useState() // Live validation rules // https://github.com/jquense/yup#number @@ -80,37 +81,56 @@ export default function Add({ // Get maximum amount for either OCEAN or datatoken useEffect(() => { - if (!accountId || !isAssetNetwork || !poolAddress) return + if (!web3 || !accountId || !isAssetNetwork || !poolAddress) return async function getMaximum() { - // const amountMaxPool = - // coin === 'OCEAN' - // ? await ocean.pool.getOceanMaxAddLiquidity(poolAddress) - // : await ocean.pool.getDTMaxAddLiquidity(poolAddress) - // const amountMax = - // coin === 'OCEAN' - // ? Number(balance.ocean) > Number(amountMaxPool) - // ? amountMaxPool - // : balance.ocean - // : Number(dtBalance) > Number(amountMaxPool) - // ? amountMaxPool - // : dtBalance - // setAmountMax(Number(amountMax).toFixed(3)) + const poolInstance = new Pool(web3, LoggerInstance) + const baseTokenAddress = await poolInstance.getBasetoken(poolAddress) + + const tokenInAddress = coin === 'OCEAN' ? baseTokenAddress : dtAddress + setTokenInAddress(tokenInAddress) + + const amountMaxPool = await poolInstance.getReserve( + poolAddress, + tokenInAddress + ) + + // coin === 'OCEAN' + // ? await poolInstance.getOceanMaxAddLiquidity(poolAddress) + // : await poolInstance.getDTMaxAddLiquidity(poolAddress) + const amountMax = + coin === 'OCEAN' + ? Number(balance.ocean) > Number(amountMaxPool) + ? amountMaxPool + : balance.ocean + : Number(dtBalance) > Number(amountMaxPool) + ? amountMaxPool + : dtBalance + setAmountMax(Number(amountMax).toFixed(3)) } getMaximum() - }, [accountId, isAssetNetwork, poolAddress, coin, dtBalance, balance.ocean]) + }, [ + web3, + accountId, + isAssetNetwork, + poolAddress, + dtAddress, + coin, + dtBalance, + balance.ocean + ]) // Submit async function handleAddLiquidity(amount: number, resetForm: () => void) { + const poolInstance = new Pool(web3, LoggerInstance) + try { - // const result = - // coin === 'OCEAN' - // ? await ocean.pool.addOceanLiquidity( - // accountId, - // poolAddress, - // `${amount}` - // ) - // : await ocean.pool.addDTLiquidity(accountId, poolAddress, `${amount}`) + // const result = await poolInstance.joinPool( + // accountId, + // poolAddress, + // poolAmountOut, + // amountMax + // ) // setTxId(result?.transactionHash) // resetForm() fetchAllData() @@ -139,6 +159,7 @@ export default function Add({
{isWarningAccepted ? ( Date: Mon, 24 Jan 2022 11:46:58 +0000 Subject: [PATCH 02/12] restore submit methods, token approval workaround --- .../@shared/TokenApproval/index.tsx | 44 +++++++++++-------- .../Asset/AssetActions/Pool/Add/index.tsx | 17 +++---- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/components/@shared/TokenApproval/index.tsx b/src/components/@shared/TokenApproval/index.tsx index 2b0094843..2a87e4362 100644 --- a/src/components/@shared/TokenApproval/index.tsx +++ b/src/components/@shared/TokenApproval/index.tsx @@ -4,6 +4,7 @@ import { useWeb3 } from '@context/Web3' import Decimal from 'decimal.js' import { getOceanConfig } from '@utils/ocean' import { ButtonApprove } from './ButtonApprove' +import { Datatoken } from '@oceanprotocol/lib' export default function TokenApproval({ actionButton, @@ -19,7 +20,7 @@ export default function TokenApproval({ const { ddo, price, isAssetNetwork } = useAsset() const [tokenApproved, setTokenApproved] = useState(false) const [loading, setLoading] = useState(false) - const { accountId } = useWeb3() + const { web3, accountId } = useWeb3() const config = getOceanConfig(ddo.chainId) @@ -29,34 +30,39 @@ export default function TokenApproval({ : ddo.services[0].datatokenAddress const spender = price.address - const checkTokenApproval = useCallback(async () => { - // if (!tokenAddress || !spender || !isAssetNetwork || !amount) return - // const allowance = await ocean.datatokens.allowance( - // tokenAddress, - // accountId, - // spender - // ) - // amount && - // new Decimal(amount).greaterThan(new Decimal('0')) && - // setTokenApproved( - // new Decimal(allowance).greaterThanOrEqualTo(new Decimal(amount)) - // ) - }, [tokenAddress, spender, accountId, amount, isAssetNetwork]) + // TODO: how to check if token is approved as .allowance does not exist? + // const checkTokenApproval = useCallback(async () => { + // if (!web3 || !tokenAddress || !spender || !isAssetNetwork || !amount) return - useEffect(() => { - checkTokenApproval() - }, [checkTokenApproval]) + // const datatokenInstance = new Datatoken(web3) + // const allowance = await datatokenInstance.allowance( + // tokenAddress, + // accountId, + // spender + // ) + // amount && + // new Decimal(amount).greaterThan(new Decimal('0')) && + // setTokenApproved( + // new Decimal(allowance).greaterThanOrEqualTo(new Decimal(amount)) + // ) + // }, [web3, tokenAddress, spender, accountId, amount, isAssetNetwork]) + + // useEffect(() => { + // checkTokenApproval() + // }, [checkTokenApproval]) async function approveTokens(amount: string) { setLoading(true) try { - // await ocean.datatokens.approve(tokenAddress, spender, amount, accountId) + const datatokenInstance = new Datatoken(web3) + await datatokenInstance.approve(tokenAddress, spender, amount, accountId) + setTokenApproved(true) } catch (error) { setLoading(false) } - await checkTokenApproval() + // await checkTokenApproval() setLoading(false) } diff --git a/src/components/Asset/AssetActions/Pool/Add/index.tsx b/src/components/Asset/AssetActions/Pool/Add/index.tsx index b83a9e768..853af5070 100644 --- a/src/components/Asset/AssetActions/Pool/Add/index.tsx +++ b/src/components/Asset/AssetActions/Pool/Add/index.tsx @@ -86,7 +86,6 @@ export default function Add({ async function getMaximum() { const poolInstance = new Pool(web3, LoggerInstance) const baseTokenAddress = await poolInstance.getBasetoken(poolAddress) - const tokenInAddress = coin === 'OCEAN' ? baseTokenAddress : dtAddress setTokenInAddress(tokenInAddress) @@ -123,15 +122,17 @@ export default function Add({ // Submit async function handleAddLiquidity(amount: number, resetForm: () => void) { const poolInstance = new Pool(web3, LoggerInstance) + const minPoolAmountOut = '0' // ? TODO: how to get? try { - // const result = await poolInstance.joinPool( - // accountId, - // poolAddress, - // poolAmountOut, - // amountMax - // ) - // setTxId(result?.transactionHash) + const result = await poolInstance.joinswapExternAmountIn( + accountId, + poolAddress, + tokenInAddress, + `${amount}`, + minPoolAmountOut + ) + setTxId(result?.transactionHash) // resetForm() fetchAllData() } catch (error) { From 4dc188d3e49f77ddf95557b570022bd0046b863a Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Mon, 24 Jan 2022 14:27:28 +0000 Subject: [PATCH 03/12] add/remove baseToken only --- .../Asset/AssetActions/Pool/Actions.tsx | 2 +- .../Asset/AssetActions/Pool/Add/FormAdd.tsx | 30 ++----- .../Asset/AssetActions/Pool/Add/Output.tsx | 15 +--- .../Asset/AssetActions/Pool/Add/index.tsx | 79 ++++++------------- .../AssetActions/Pool/CoinSelect.module.css | 26 ------ .../Asset/AssetActions/Pool/CoinSelect.tsx | 27 ------- .../Asset/AssetActions/Pool/index.tsx | 21 +++-- 7 files changed, 44 insertions(+), 156 deletions(-) delete mode 100644 src/components/Asset/AssetActions/Pool/CoinSelect.module.css delete mode 100644 src/components/Asset/AssetActions/Pool/CoinSelect.tsx diff --git a/src/components/Asset/AssetActions/Pool/Actions.tsx b/src/components/Asset/AssetActions/Pool/Actions.tsx index 50c8b549b..bc06418fa 100644 --- a/src/components/Asset/AssetActions/Pool/Actions.tsx +++ b/src/components/Asset/AssetActions/Pool/Actions.tsx @@ -50,7 +50,7 @@ export default function Actions({ ) : ( diff --git a/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx b/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx index ad88473ec..abcca693a 100644 --- a/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx +++ b/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx @@ -8,11 +8,9 @@ import { useFormikContext } from 'formik' import Button from '@shared/atoms/Button' -import CoinSelect from '../CoinSelect' import { FormAddLiquidity } from '.' import UserLiquidity from '../../UserLiquidity' import { useWeb3 } from '@context/Web3' - import { isValidNumber } from '@utils/numbers' import Decimal from 'decimal.js' import { useAsset } from '@context/Asset' @@ -20,11 +18,8 @@ import { LoggerInstance, Pool } from '@oceanprotocol/lib' export default function FormAdd({ tokenInAddress, - coin, - dtBalance, - dtSymbol, + tokenInSymbol, amountMax, - setCoin, setAmount, totalPoolTokens, totalBalance, @@ -33,11 +28,8 @@ export default function FormAdd({ setNewPoolShare }: { tokenInAddress: string - coin: string - dtBalance: string - dtSymbol: string + tokenInSymbol: string amountMax: string - setCoin: (value: string) => void setAmount: (value: string) => void totalPoolTokens: string totalBalance: PoolBalance @@ -111,16 +103,12 @@ export default function FormAdd({ setNewPoolShare ]) - useEffect(() => { - setFieldValue('amount', undefined) - }, [coin]) - return ( <> @@ -138,13 +126,7 @@ export default function FormAdd({ min="0" value={`${values.amount}`} step="any" - prefix={ - - } + prefix={tokenInSymbol} placeholder="0" field={field} form={form} @@ -154,7 +136,7 @@ export default function FormAdd({ )} - {(Number(balance.ocean) || dtBalance) > (values.amount || 0) && ( + {Number(balance.ocean) && (
- - {isAdvanced === true - ? content.pool.remove.advanced - : content.pool.remove.simple} - - + {content.pool.remove.simple}
@@ -242,14 +181,7 @@ export default function Remove({

{content.pool.remove.output.titleOut} minimum

- {isAdvanced === true ? ( - <> - - - - ) : ( - - )} +
diff --git a/src/components/Asset/AssetActions/Pool/index.tsx b/src/components/Asset/AssetActions/Pool/index.tsx index 31aec10c7..ffa86d0e6 100644 --- a/src/components/Asset/AssetActions/Pool/index.tsx +++ b/src/components/Asset/AssetActions/Pool/index.tsx @@ -33,6 +33,7 @@ interface PoolInfo { weightDt: string datatokenSymbol: string baseTokenSymbol: string + baseTokenAddress: string totalPoolTokens: string totalLiquidityInOcean: Decimal } @@ -162,6 +163,7 @@ export default function Pool(): ReactElement { weightDt: getWeight(poolData.datatokenWeight), datatokenSymbol: poolData.datatoken.symbol, baseTokenSymbol: poolData.baseToken.symbol, + baseTokenAddress: poolData.baseToken.address, totalPoolTokens: poolData.totalShares, totalLiquidityInOcean } @@ -352,7 +354,8 @@ export default function Pool(): ReactElement { poolAddress={price?.address} poolTokens={poolInfoUser?.poolShares} totalPoolTokens={poolInfo?.totalPoolTokens} - datatokenSymbol={poolInfo?.datatokenSymbol} + baseTokenAddress={poolInfo?.baseTokenAddress} + baseTokenSymbol={poolInfo?.baseTokenSymbol} fetchAllData={fetchAllData} /> ) : ( From bfdf7e1b2427c4cc02a18837a5e991260b8c09e1 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Mon, 24 Jan 2022 15:35:34 +0000 Subject: [PATCH 06/12] prepare to use getAmountInExactOut --- .../Asset/AssetActions/Pool/Add/index.tsx | 1 - .../Asset/AssetActions/Pool/Remove.tsx | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/Asset/AssetActions/Pool/Add/index.tsx b/src/components/Asset/AssetActions/Pool/Add/index.tsx index 3226cb1cf..935123cb3 100644 --- a/src/components/Asset/AssetActions/Pool/Add/index.tsx +++ b/src/components/Asset/AssetActions/Pool/Add/index.tsx @@ -14,7 +14,6 @@ import { useWeb3 } from '@context/Web3' import { useAsset } from '@context/Asset' import content from '../../../../../../content/price.json' import { LoggerInstance, Pool } from '@oceanprotocol/lib' -import { getOceanConfig } from '@utils/ocean' export interface FormAddLiquidity { amount: number diff --git a/src/components/Asset/AssetActions/Pool/Remove.tsx b/src/components/Asset/AssetActions/Pool/Remove.tsx index d6fa05348..27429b15d 100644 --- a/src/components/Asset/AssetActions/Pool/Remove.tsx +++ b/src/components/Asset/AssetActions/Pool/Remove.tsx @@ -53,12 +53,12 @@ export default function Remove({ const [minOceanAmount, setMinOceanAmount] = useState('0') Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 }) + const poolInstance = new Pool(web3, LoggerInstance) async function handleRemoveLiquidity() { setIsLoading(true) try { - const poolInstance = new Pool(web3, LoggerInstance) const result = await poolInstance.exitswapPoolAmountIn( accountId, poolAddress, @@ -89,11 +89,19 @@ export default function Remove({ const getValues = useRef( debounce(async (newAmountPoolShares) => { - // const amountOcean = await ocean.pool.getOceanRemovedforPoolShares( + // TODO: check based on pool tokens sent in, what I get out in baseToken. + // Seems to be not possible with getAmountInExactOut(). + // const tokenIn = newAmountPoolShares // TODO: this needs to pool shares? + // const swapMarketFee = '' // TODO: which is it? Swap fee or market fee? + // const baseTokenAmount = '' // TODO: this is what I want to know, why do I need to pass as param then? + // const newAmountOcean = await poolInstance.getAmountInExactOut( // poolAddress, - // newAmountPoolShares + // tokenIn, + // baseTokenAddress, + // baseTokenAmount, + // swapMarketFee // ) - // setAmountOcean(amountOcean) + // setAmountOcean(newAmountOcean) }, 150) ) // Check and set outputs when amountPoolShares changes From 8b31746e57bcb1541f663576899a8b1f90c7afab Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Mon, 24 Jan 2022 16:19:47 +0000 Subject: [PATCH 07/12] make remove output calculation work --- .../Asset/AssetActions/Pool/Remove.tsx | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/components/Asset/AssetActions/Pool/Remove.tsx b/src/components/Asset/AssetActions/Pool/Remove.tsx index 27429b15d..58050e207 100644 --- a/src/components/Asset/AssetActions/Pool/Remove.tsx +++ b/src/components/Asset/AssetActions/Pool/Remove.tsx @@ -43,6 +43,7 @@ export default function Remove({ }): ReactElement { const { accountId, web3 } = useWeb3() const { isAssetNetwork } = useAsset() + const [amountPercent, setAmountPercent] = useState('0') const [amountMaxPercent, setAmountMaxPercent] = useState('100') const [amountPoolShares, setAmountPoolShares] = useState('0') @@ -52,6 +53,7 @@ export default function Remove({ const [slippage, setSlippage] = useState('5') const [minOceanAmount, setMinOceanAmount] = useState('0') + // TODO: precision needs to be set based on baseToken decimals Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 }) const poolInstance = new Pool(web3, LoggerInstance) @@ -89,21 +91,15 @@ export default function Remove({ const getValues = useRef( debounce(async (newAmountPoolShares) => { - // TODO: check based on pool tokens sent in, what I get out in baseToken. - // Seems to be not possible with getAmountInExactOut(). - // const tokenIn = newAmountPoolShares // TODO: this needs to pool shares? - // const swapMarketFee = '' // TODO: which is it? Swap fee or market fee? - // const baseTokenAmount = '' // TODO: this is what I want to know, why do I need to pass as param then? - // const newAmountOcean = await poolInstance.getAmountInExactOut( - // poolAddress, - // tokenIn, - // baseTokenAddress, - // baseTokenAmount, - // swapMarketFee - // ) - // setAmountOcean(newAmountOcean) + const newAmountOcean = await poolInstance.calcSingleOutGivenPoolIn( + poolAddress, + baseTokenAddress, + newAmountPoolShares + ) + setAmountOcean(newAmountOcean) }, 150) ) + // Check and set outputs when amountPoolShares changes useEffect(() => { if (!accountId || !poolTokens) return From 08a691ceee79142713111567defc237fa4695ca7 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Wed, 26 Jan 2022 10:43:32 +0000 Subject: [PATCH 08/12] token approval & allowance fixes --- .../@shared/TokenApproval/index.tsx | 52 +++++++++---------- .../Asset/AssetActions/Pool/Add/index.tsx | 2 +- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/components/@shared/TokenApproval/index.tsx b/src/components/@shared/TokenApproval/index.tsx index 2a87e4362..6d598571b 100644 --- a/src/components/@shared/TokenApproval/index.tsx +++ b/src/components/@shared/TokenApproval/index.tsx @@ -4,7 +4,7 @@ import { useWeb3 } from '@context/Web3' import Decimal from 'decimal.js' import { getOceanConfig } from '@utils/ocean' import { ButtonApprove } from './ButtonApprove' -import { Datatoken } from '@oceanprotocol/lib' +import { allowance, approve, LoggerInstance } from '@oceanprotocol/lib' export default function TokenApproval({ actionButton, @@ -28,42 +28,42 @@ export default function TokenApproval({ coin === 'OCEAN' ? config.oceanTokenAddress : ddo.services[0].datatokenAddress - const spender = price.address + const spender = price?.address - // TODO: how to check if token is approved as .allowance does not exist? - // const checkTokenApproval = useCallback(async () => { - // if (!web3 || !tokenAddress || !spender || !isAssetNetwork || !amount) return + const checkTokenApproval = useCallback(async () => { + if (!web3 || !tokenAddress || !spender || !isAssetNetwork || !amount) return - // const datatokenInstance = new Datatoken(web3) - // const allowance = await datatokenInstance.allowance( - // tokenAddress, - // accountId, - // spender - // ) - // amount && - // new Decimal(amount).greaterThan(new Decimal('0')) && - // setTokenApproved( - // new Decimal(allowance).greaterThanOrEqualTo(new Decimal(amount)) - // ) - // }, [web3, tokenAddress, spender, accountId, amount, isAssetNetwork]) + const allowanceValue = await allowance( + web3, + tokenAddress, + accountId, + spender + ) - // useEffect(() => { - // checkTokenApproval() - // }, [checkTokenApproval]) + if (!allowanceValue) return + + new Decimal(amount).greaterThan(new Decimal('0')) && + setTokenApproved( + new Decimal(allowanceValue).greaterThanOrEqualTo(new Decimal(amount)) + ) + }, [web3, tokenAddress, spender, accountId, amount, isAssetNetwork]) + + useEffect(() => { + checkTokenApproval() + }, [checkTokenApproval]) async function approveTokens(amount: string) { setLoading(true) try { - const datatokenInstance = new Datatoken(web3) - await datatokenInstance.approve(tokenAddress, spender, amount, accountId) - setTokenApproved(true) + const tx = await approve(web3, accountId, tokenAddress, spender, amount) + LoggerInstance.log(`Approve tokens tx:`, tx) } catch (error) { + LoggerInstance.error(`Approve tokens tx failed:`, error.message) + } finally { + await checkTokenApproval() setLoading(false) } - - // await checkTokenApproval() - setLoading(false) } return ( diff --git a/src/components/Asset/AssetActions/Pool/Add/index.tsx b/src/components/Asset/AssetActions/Pool/Add/index.tsx index 935123cb3..ed284e48e 100644 --- a/src/components/Asset/AssetActions/Pool/Add/index.tsx +++ b/src/components/Asset/AssetActions/Pool/Add/index.tsx @@ -72,7 +72,7 @@ export default function Add({ async function getMaximum() { try { const poolInstance = new Pool(web3, LoggerInstance) - const tokenInAddress = await poolInstance.getBasetoken(poolAddress) + const tokenInAddress = await poolInstance.getBaseToken(poolAddress) setTokenInAddress(tokenInAddress) const amountMaxPool = await poolInstance.getReserve( From c10ca06dbcb6fd2d7271e14456132b836ffa7547 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Wed, 26 Jan 2022 11:55:21 +0000 Subject: [PATCH 09/12] fixes --- src/components/@shared/DebugOutput.tsx | 4 ++-- src/components/Asset/AssetActions/Pool/Add/index.tsx | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/@shared/DebugOutput.tsx b/src/components/@shared/DebugOutput.tsx index 9f42da559..1b4d359a2 100644 --- a/src/components/@shared/DebugOutput.tsx +++ b/src/components/@shared/DebugOutput.tsx @@ -4,12 +4,12 @@ export default function DebugOutput({ title, output }: { - title: string + title?: string output: any }): ReactElement { return (
-
{title}
+ {title &&
{title}
}
         {JSON.stringify(output, null, 2)}
       
diff --git a/src/components/Asset/AssetActions/Pool/Add/index.tsx b/src/components/Asset/AssetActions/Pool/Add/index.tsx index ed284e48e..6f97b9c32 100644 --- a/src/components/Asset/AssetActions/Pool/Add/index.tsx +++ b/src/components/Asset/AssetActions/Pool/Add/index.tsx @@ -172,6 +172,7 @@ export default function Add({ isDisabled={ !isValid || !isWarningAccepted || + !amount || amount === '' || amount === '0' } @@ -183,7 +184,7 @@ export default function Add({ amount={amount} txId={txId} /> - {debug && } + {debug && } )} From 0db0bea3f6fd4409ca9b6d494298910b59c4f7bb Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Wed, 26 Jan 2022 12:05:35 +0000 Subject: [PATCH 10/12] more generic TokenApproval props, more logging --- .../@shared/TokenApproval/ButtonApprove.tsx | 20 +++++++++------ .../@shared/TokenApproval/index.tsx | 25 +++++++++---------- .../Asset/AssetActions/Pool/Actions.tsx | 10 +++++++- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/components/@shared/TokenApproval/ButtonApprove.tsx b/src/components/@shared/TokenApproval/ButtonApprove.tsx index 4583200c5..9583d494c 100644 --- a/src/components/@shared/TokenApproval/ButtonApprove.tsx +++ b/src/components/@shared/TokenApproval/ButtonApprove.tsx @@ -7,19 +7,19 @@ import content from '../../../../content/price.json' export function ButtonApprove({ amount, - coin, + tokenSymbol, approveTokens, isLoading }: { amount: string - coin: string + tokenSymbol: string approveTokens: (amount: string) => void isLoading: boolean }): ReactElement { const { infiniteApproval } = useUserPreferences() return isLoading ? ( - + ) : infiniteApproval ? ( ) : ( ) diff --git a/src/components/@shared/TokenApproval/index.tsx b/src/components/@shared/TokenApproval/index.tsx index 6d598571b..f93ecab76 100644 --- a/src/components/@shared/TokenApproval/index.tsx +++ b/src/components/@shared/TokenApproval/index.tsx @@ -2,7 +2,6 @@ import React, { ReactElement, useCallback, useEffect, useState } from 'react' import { useAsset } from '@context/Asset' import { useWeb3 } from '@context/Web3' import Decimal from 'decimal.js' -import { getOceanConfig } from '@utils/ocean' import { ButtonApprove } from './ButtonApprove' import { allowance, approve, LoggerInstance } from '@oceanprotocol/lib' @@ -10,24 +9,20 @@ export default function TokenApproval({ actionButton, disabled, amount, - coin + tokenAddress, + tokenSymbol }: { actionButton: JSX.Element disabled: boolean amount: string - coin: string + tokenAddress: string + tokenSymbol: string }): ReactElement { - const { ddo, price, isAssetNetwork } = useAsset() + const { price, isAssetNetwork } = useAsset() const [tokenApproved, setTokenApproved] = useState(false) const [loading, setLoading] = useState(false) const { web3, accountId } = useWeb3() - const config = getOceanConfig(ddo.chainId) - - const tokenAddress = - coin === 'OCEAN' - ? config.oceanTokenAddress - : ddo.services[0].datatokenAddress const spender = price?.address const checkTokenApproval = useCallback(async () => { @@ -39,6 +34,7 @@ export default function TokenApproval({ accountId, spender ) + LoggerInstance.log(`[token approval] allowanceValue: ${allowanceValue}`) if (!allowanceValue) return @@ -57,9 +53,12 @@ export default function TokenApproval({ try { const tx = await approve(web3, accountId, tokenAddress, spender, amount) - LoggerInstance.log(`Approve tokens tx:`, tx) + LoggerInstance.log(`[token approval] Approve tokens tx:`, tx) } catch (error) { - LoggerInstance.error(`Approve tokens tx failed:`, error.message) + LoggerInstance.error( + `[token approval] Approve tokens tx failed:`, + error.message + ) } finally { await checkTokenApproval() setLoading(false) @@ -78,7 +77,7 @@ export default function TokenApproval({ ) : ( diff --git a/src/components/Asset/AssetActions/Pool/Actions.tsx b/src/components/Asset/AssetActions/Pool/Actions.tsx index bc06418fa..83791e69c 100644 --- a/src/components/Asset/AssetActions/Pool/Actions.tsx +++ b/src/components/Asset/AssetActions/Pool/Actions.tsx @@ -6,6 +6,8 @@ import ExplorerLink from '@shared/ExplorerLink' import SuccessConfetti from '@shared/SuccessConfetti' import { useWeb3 } from '@context/Web3' import TokenApproval from '@shared/TokenApproval' +import { getOceanConfig } from '@utils/ocean' +import { useAsset } from '@context/Asset' export default function Actions({ isLoading, @@ -29,6 +31,7 @@ export default function Actions({ isDisabled?: boolean }): ReactElement { const { networkId } = useWeb3() + const { ddo } = useAsset() const actionButton = (
@@ -210,6 +210,8 @@ export default function Remove({ successMessage="Successfully removed liquidity." isDisabled={!isAssetNetwork} txId={txId} + tokenAddress={tokenOutAddress} + tokenSymbol={tokenOutSymbol} />
) diff --git a/src/components/Asset/AssetActions/Pool/index.tsx b/src/components/Asset/AssetActions/Pool/index.tsx index ffa86d0e6..4a800922b 100644 --- a/src/components/Asset/AssetActions/Pool/index.tsx +++ b/src/components/Asset/AssetActions/Pool/index.tsx @@ -345,7 +345,8 @@ export default function Pool(): ReactElement { }} swapFee={poolInfo?.poolFee} datatokenSymbol={poolInfo?.datatokenSymbol} - baseTokenSymbol={poolInfo?.baseTokenSymbol} + tokenInAddress={poolInfo?.baseTokenAddress} + tokenInSymbol={poolInfo?.baseTokenSymbol} fetchAllData={fetchAllData} /> ) : showRemove ? ( @@ -354,8 +355,8 @@ export default function Pool(): ReactElement { poolAddress={price?.address} poolTokens={poolInfoUser?.poolShares} totalPoolTokens={poolInfo?.totalPoolTokens} - baseTokenAddress={poolInfo?.baseTokenAddress} - baseTokenSymbol={poolInfo?.baseTokenSymbol} + tokenOutAddress={poolInfo?.baseTokenAddress} + tokenOutSymbol={poolInfo?.baseTokenSymbol} fetchAllData={fetchAllData} /> ) : ( diff --git a/src/components/Asset/AssetActions/Trade/FormTrade.tsx b/src/components/Asset/AssetActions/Trade/FormTrade.tsx index 20135bb4c..1581f74d8 100644 --- a/src/components/Asset/AssetActions/Trade/FormTrade.tsx +++ b/src/components/Asset/AssetActions/Trade/FormTrade.tsx @@ -38,6 +38,9 @@ export default function FormTrade({ const [maximumDt, setMaximumDt] = useState(maxDt) const [isWarningAccepted, setIsWarningAccepted] = useState(false) + const tokenAddress = '' + const tokenSymbol = '' + const validationSchema: Yup.SchemaOf = Yup.object() .shape({ ocean: Yup.number() @@ -152,8 +155,9 @@ export default function FormTrade({ : undefined } action={submitForm} - coin={coinFrom} txId={txId} + tokenAddress={tokenAddress} + tokenSymbol={tokenSymbol} /> {debug && ( From 9ce1f6f7d5f625c5992e0787bf98e11fb0338ef1 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Wed, 26 Jan 2022 14:07:33 +0000 Subject: [PATCH 12/12] remove all the custom field change overwrites --- .../Asset/AssetActions/Pool/Add/FormAdd.tsx | 34 ++++--------------- .../Asset/AssetActions/Pool/Add/index.tsx | 20 +++++------ 2 files changed, 15 insertions(+), 39 deletions(-) diff --git a/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx b/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx index abcca693a..168e22d8d 100644 --- a/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx +++ b/src/components/Asset/AssetActions/Pool/Add/FormAdd.tsx @@ -1,4 +1,4 @@ -import React, { ChangeEvent, ReactElement, useEffect } from 'react' +import React, { ReactElement, useEffect } from 'react' import styles from './FormAdd.module.css' import Input from '@shared/FormInput' import { @@ -20,7 +20,6 @@ export default function FormAdd({ tokenInAddress, tokenInSymbol, amountMax, - setAmount, totalPoolTokens, totalBalance, poolAddress, @@ -30,7 +29,6 @@ export default function FormAdd({ tokenInAddress: string tokenInSymbol: string amountMax: string - setAmount: (value: string) => void totalPoolTokens: string totalBalance: PoolBalance poolAddress: string @@ -41,24 +39,8 @@ export default function FormAdd({ const { isAssetNetwork } = useAsset() // Connect with form - const { - touched, - setTouched, - setFieldValue, - validateField, - values - }: FormikContextType = useFormikContext() - - function handleFieldChange(e: ChangeEvent) { - // Workaround so validation kicks in on first touch - !touched?.amount && setTouched({ amount: true }) - setAmount(e.target.value) - - // Manually handle change events instead of using `handleChange` from Formik. - // Solves bug where 0.0 can't be typed. - validateField('amount') - setFieldValue('amount', e.target.value) - } + const { setFieldValue, values }: FormikContextType = + useFormikContext() useEffect(() => { async function calculatePoolShares() { @@ -76,7 +58,7 @@ export default function FormAdd({ const poolTokens = await poolInstance.calcPoolOutGivenSingleIn( poolAddress, tokenInAddress, - `${values.amount}` + values.amount ) setNewPoolTokens(poolTokens) const newPoolShareDecimal = @@ -124,13 +106,12 @@ export default function FormAdd({ name="amount" max={amountMax} min="0" - value={`${values.amount}`} + value={values.amount} step="any" prefix={tokenInSymbol} placeholder="0" field={field} form={form} - onChange={handleFieldChange} disabled={!isAssetNetwork} /> )} @@ -142,10 +123,7 @@ export default function FormAdd({ style="text" size="small" disabled={!web3} - onClick={() => { - setAmount(amountMax) - setFieldValue('amount', amountMax) - }} + onClick={() => setFieldValue('amount', amountMax)} > Use Max diff --git a/src/components/Asset/AssetActions/Pool/Add/index.tsx b/src/components/Asset/AssetActions/Pool/Add/index.tsx index 4c5f3c148..a686eac5f 100644 --- a/src/components/Asset/AssetActions/Pool/Add/index.tsx +++ b/src/components/Asset/AssetActions/Pool/Add/index.tsx @@ -16,11 +16,11 @@ import content from '../../../../../../content/price.json' import { LoggerInstance, Pool } from '@oceanprotocol/lib' export interface FormAddLiquidity { - amount: number + amount: string } const initialValues: FormAddLiquidity = { - amount: undefined + amount: '' } export default function Add({ @@ -49,7 +49,6 @@ export default function Add({ const { debug } = useUserPreferences() const [txId, setTxId] = useState() const [amountMax, setAmountMax] = useState() - const [amount, setAmount] = useState('0') const [newPoolTokens, setNewPoolTokens] = useState('0') const [newPoolShare, setNewPoolShare] = useState('0') const [isWarningAccepted, setIsWarningAccepted] = useState(false) @@ -57,7 +56,7 @@ export default function Add({ // Live validation rules // https://github.com/jquense/yup#number const validationSchema: Yup.SchemaOf = Yup.object().shape({ - amount: Yup.number() + amount: Yup.string() .min(0.00001, (param) => `Must be more or equal to ${param.min}`) .max( Number(amountMax), @@ -99,7 +98,7 @@ export default function Add({ ]) // Submit - async function handleAddLiquidity(amount: number, resetForm: () => void) { + async function handleAddLiquidity(amount: string, resetForm: () => void) { const poolInstance = new Pool(web3, LoggerInstance) const minPoolAmountOut = '0' // ? TODO: how to get? @@ -108,7 +107,7 @@ export default function Add({ accountId, poolAddress, tokenInAddress, - `${amount}`, + amount, minPoolAmountOut ) setTxId(result?.transactionHash) @@ -142,7 +141,6 @@ export default function Add({ tokenInAddress={tokenInAddress} tokenInSymbol={tokenInSymbol} amountMax={amountMax} - setAmount={setAmount} totalPoolTokens={totalPoolTokens} totalBalance={totalBalance} poolAddress={poolAddress} @@ -178,16 +176,16 @@ export default function Add({ isDisabled={ !isValid || !isWarningAccepted || - !amount || - amount === '' || - amount === '0' + !values.amount || + values.amount === '' || + values.amount === '0' } isLoading={isSubmitting} loaderMessage="Adding Liquidity..." successMessage="Successfully added liquidity." actionName={content.pool.add.action} action={submitForm} - amount={amount} + amount={values.amount} tokenAddress={tokenInAddress} tokenSymbol={tokenInSymbol} txId={txId}