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

Add liquidity input changes&fixes (#893)

* disable add liquidity input when not asset network

* clear amount on coin selection change

* fix switch token error

* disable trade tab inputs when not connected to asset network

* disable inputs and buttons inside remove when not connected

* remove ocean function calls when not connected to asset network

* fix send undefined as string inside Trade component to TokenApproval

* return from calculatePoolShares function if no wallet connected

* set amount on use max button click, use 3 digits after decimal
This commit is contained in:
Norbi 2021-10-14 15:48:20 +03:00 committed by GitHub
parent d1206c291b
commit b881fdd88f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 85 additions and 20 deletions

View File

@ -63,6 +63,7 @@ export default function InputElement({
id={name} id={name}
className={styleClasses} className={styleClasses}
{...props} {...props}
disabled={disabled}
multiple={multiple} multiple={multiple}
> >
{field !== undefined && field.value === '' && ( {field !== undefined && field.value === '' && (

View File

@ -77,7 +77,7 @@ export default function TokenApproval({
amount: string amount: string
coin: string coin: string
}): ReactElement { }): ReactElement {
const { ddo, price } = useAsset() const { ddo, price, isAssetNetwork } = useAsset()
const [tokenApproved, setTokenApproved] = useState(false) const [tokenApproved, setTokenApproved] = useState(false)
const [loading, setLoading] = useState(false) const [loading, setLoading] = useState(false)
const { ocean } = useOcean() const { ocean } = useOcean()
@ -90,7 +90,8 @@ export default function TokenApproval({
const spender = price.address const spender = price.address
const checkTokenApproval = useCallback(async () => { const checkTokenApproval = useCallback(async () => {
if (!ocean || !tokenAddress || !spender) return if (!ocean || !tokenAddress || !spender || !isAssetNetwork || !amount)
return
const allowance = await ocean.datatokens.allowance( const allowance = await ocean.datatokens.allowance(
tokenAddress, tokenAddress,

View File

@ -17,6 +17,7 @@ import { useWeb3 } from '../../../../../providers/Web3'
import { isValidNumber } from './../../../../../utils/numberValidations' import { isValidNumber } from './../../../../../utils/numberValidations'
import Decimal from 'decimal.js' import Decimal from 'decimal.js'
import { useAsset } from '../../../../../providers/Asset'
export default function FormAdd({ export default function FormAdd({
coin, coin,
@ -45,6 +46,7 @@ export default function FormAdd({
}): ReactElement { }): ReactElement {
const { balance } = useWeb3() const { balance } = useWeb3()
const { ocean } = useOcean() const { ocean } = useOcean()
const { isAssetNetwork } = useAsset()
// Connect with form // Connect with form
const { const {
@ -68,7 +70,10 @@ export default function FormAdd({
useEffect(() => { useEffect(() => {
async function calculatePoolShares() { async function calculatePoolShares() {
if (!values.amount) { if (!ocean) return
const tokenInAddress =
coin === 'OCEAN' ? ocean.pool.oceanAddress : ocean.pool.dtAddress
if (!values.amount || !tokenInAddress) {
setNewPoolTokens('0') setNewPoolTokens('0')
setNewPoolShare('0') setNewPoolShare('0')
return return
@ -78,7 +83,7 @@ export default function FormAdd({
const poolTokens = await ocean.pool.calcPoolOutGivenSingleIn( const poolTokens = await ocean.pool.calcPoolOutGivenSingleIn(
poolAddress, poolAddress,
coin === 'OCEAN' ? ocean.pool.oceanAddress : ocean.pool.dtAddress, tokenInAddress,
`${values.amount}` `${values.amount}`
) )
@ -109,6 +114,10 @@ export default function FormAdd({
setNewPoolShare setNewPoolShare
]) ])
useEffect(() => {
setFieldValue('amount', undefined)
}, [coin])
return ( return (
<> <>
<UserLiquidity <UserLiquidity
@ -132,12 +141,18 @@ export default function FormAdd({
min="0" min="0"
value={`${values.amount}`} value={`${values.amount}`}
step="any" step="any"
prefix={<CoinSelect dtSymbol={dtSymbol} setCoin={setCoin} />} prefix={
<CoinSelect
dtSymbol={dtSymbol}
setCoin={setCoin}
disabled={!ocean || !isAssetNetwork}
/>
}
placeholder="0" placeholder="0"
field={field} field={field}
form={form} form={form}
onChange={handleFieldChange} onChange={handleFieldChange}
disabled={!ocean} disabled={!ocean || !isAssetNetwork}
/> />
)} )}
</Field> </Field>
@ -148,7 +163,10 @@ export default function FormAdd({
style="text" style="text"
size="small" size="small"
disabled={!ocean} disabled={!ocean}
onClick={() => setFieldValue('amount', amountMax)} onClick={() => {
setAmount(amountMax)
setFieldValue('amount', amountMax)
}}
> >
Use Max Use Max
</Button> </Button>

View File

@ -14,6 +14,7 @@ import Output from './Output'
import DebugOutput from '../../../../atoms/DebugOutput' import DebugOutput from '../../../../atoms/DebugOutput'
import { useOcean } from '../../../../../providers/Ocean' import { useOcean } from '../../../../../providers/Ocean'
import { useWeb3 } from '../../../../../providers/Web3' import { useWeb3 } from '../../../../../providers/Web3'
import { useAsset } from '../../../../../providers/Asset'
const contentQuery = graphql` const contentQuery = graphql`
query PoolAddQuery { query PoolAddQuery {
@ -67,6 +68,7 @@ export default function Add({
const { accountId, balance } = useWeb3() const { accountId, balance } = useWeb3()
const { ocean } = useOcean() const { ocean } = useOcean()
const { isAssetNetwork } = useAsset()
const { debug } = useUserPreferences() const { debug } = useUserPreferences()
const [txId, setTxId] = useState<string>() const [txId, setTxId] = useState<string>()
const [coin, setCoin] = useState('OCEAN') const [coin, setCoin] = useState('OCEAN')
@ -91,7 +93,7 @@ export default function Add({
// Get datatoken balance when datatoken selected // Get datatoken balance when datatoken selected
useEffect(() => { useEffect(() => {
if (!ocean || coin === 'OCEAN') return if (!ocean || !isAssetNetwork || coin === 'OCEAN') return
async function getDtBalance() { async function getDtBalance() {
const dtBalance = await ocean.datatokens.balance(dtAddress, accountId) const dtBalance = await ocean.datatokens.balance(dtAddress, accountId)
@ -102,7 +104,7 @@ export default function Add({
// Get maximum amount for either OCEAN or datatoken // Get maximum amount for either OCEAN or datatoken
useEffect(() => { useEffect(() => {
if (!ocean || !poolAddress) return if (!ocean || !isAssetNetwork || !poolAddress) return
async function getMaximum() { async function getMaximum() {
const amountMaxPool = const amountMaxPool =
@ -118,7 +120,7 @@ export default function Add({
: Number(dtBalance) > Number(amountMaxPool) : Number(dtBalance) > Number(amountMaxPool)
? amountMaxPool ? amountMaxPool
: dtBalance : dtBalance
setAmountMax(amountMax) setAmountMax(Number(amountMax).toFixed(3))
} }
getMaximum() getMaximum()
}, [ocean, poolAddress, coin, dtBalance, balance.ocean]) }, [ocean, poolAddress, coin, dtBalance, balance.ocean])

View File

@ -3,15 +3,18 @@ import styles from './CoinSelect.module.css'
export default function CoinSelect({ export default function CoinSelect({
dtSymbol, dtSymbol,
disabled,
setCoin setCoin
}: { }: {
dtSymbol: string dtSymbol: string
disabled: boolean
setCoin: (coin: string) => void setCoin: (coin: string) => void
}): ReactElement { }): ReactElement {
return ( return (
<select <select
className={styles.coinSelect} className={styles.coinSelect}
onChange={(e) => setCoin(e.target.value)} onChange={(e) => setCoin(e.target.value)}
disabled={disabled}
> >
<option className={styles.option} value="OCEAN"> <option className={styles.option} value="OCEAN">
OCEAN OCEAN

View File

@ -22,6 +22,7 @@ import InputElement from '../../../atoms/Input/InputElement'
import { useOcean } from '../../../../providers/Ocean' import { useOcean } from '../../../../providers/Ocean'
import { useWeb3 } from '../../../../providers/Web3' import { useWeb3 } from '../../../../providers/Web3'
import Decimal from 'decimal.js' import Decimal from 'decimal.js'
import { useAsset } from '../../../../providers/Asset'
const contentQuery = graphql` const contentQuery = graphql`
query PoolRemoveQuery { query PoolRemoveQuery {
@ -69,6 +70,7 @@ export default function Remove({
const slippagePresets = ['5', '10', '15', '25', '50'] const slippagePresets = ['5', '10', '15', '25', '50']
const { accountId } = useWeb3() const { accountId } = useWeb3()
const { ocean } = useOcean() const { ocean } = useOcean()
const { isAssetNetwork } = useAsset()
const [amountPercent, setAmountPercent] = useState('0') const [amountPercent, setAmountPercent] = useState('0')
const [amountMaxPercent, setAmountMaxPercent] = useState('100') const [amountMaxPercent, setAmountMaxPercent] = useState('100')
const [amountPoolShares, setAmountPoolShares] = useState('0') const [amountPoolShares, setAmountPoolShares] = useState('0')
@ -231,6 +233,7 @@ export default function Remove({
type="range" type="range"
min="0" min="0"
max={amountMaxPercent} max={amountMaxPercent}
disabled={!isAssetNetwork}
value={amountPercent} value={amountPercent}
onChange={handleAmountPercentChange} onChange={handleAmountPercentChange}
/> />
@ -238,6 +241,7 @@ export default function Remove({
style="text" style="text"
size="small" size="small"
className={styles.maximum} className={styles.maximum}
disabled={!isAssetNetwork}
onClick={handleMaxButton} onClick={handleMaxButton}
> >
{`${amountMaxPercent}% max`} {`${amountMaxPercent}% max`}
@ -251,6 +255,7 @@ export default function Remove({
style="text" style="text"
size="small" size="small"
onClick={handleAdvancedButton} onClick={handleAdvancedButton}
disabled={!isAssetNetwork}
className={styles.toggle} className={styles.toggle}
> >
{isAdvanced === true ? 'Simple' : 'Advanced'} {isAdvanced === true ? 'Simple' : 'Advanced'}
@ -283,6 +288,7 @@ export default function Remove({
postfix="%" postfix="%"
sortOptions={false} sortOptions={false}
options={slippagePresets} options={slippagePresets}
disabled={!isAssetNetwork}
value={slippage} value={slippage}
onChange={handleSlippageChange} onChange={handleSlippageChange}
/> />
@ -293,6 +299,7 @@ export default function Remove({
actionName={content.action} actionName={content.action}
action={handleRemoveLiquidity} action={handleRemoveLiquidity}
successMessage="Successfully removed liquidity." successMessage="Successfully removed liquidity."
isDisabled={!isAssetNetwork}
txId={txId} txId={txId}
/> />
</div> </div>

View File

@ -164,9 +164,15 @@ export default function FormTrade({
loaderMessage="Swapping tokens..." loaderMessage="Swapping tokens..."
successMessage="Successfully swapped tokens." successMessage="Successfully swapped tokens."
actionName={content.action} actionName={content.action}
amount={`${ amount={
values.type === 'sell' ? values.datatoken : values.ocean values.type === 'sell'
}`} ? values.datatoken
? `${values.datatoken}`
: undefined
: values.ocean
? `${values.ocean}`
: undefined
}
action={submitForm} action={submitForm}
coin={coinFrom} coin={coinFrom}
txId={txId} txId={txId}

View File

@ -5,7 +5,11 @@ import InputElement from '../../../atoms/Input/InputElement'
import Tooltip from '../../../atoms/Tooltip' import Tooltip from '../../../atoms/Tooltip'
import styles from './Slippage.module.css' import styles from './Slippage.module.css'
export default function Slippage(): ReactElement { export default function Slippage({
disabled
}: {
disabled: boolean
}): ReactElement {
// Connect with form // Connect with form
const { setFieldValue, values }: FormikContextType<FormTradeData> = const { setFieldValue, values }: FormikContextType<FormTradeData> =
useFormikContext() useFormikContext()
@ -26,6 +30,7 @@ export default function Slippage(): ReactElement {
sortOptions={false} sortOptions={false}
options={slippagePresets} options={slippagePresets}
value={values.slippage} value={values.slippage}
disabled={disabled}
onChange={handleChange} onChange={handleChange}
/> />
<Tooltip content="Your transaction will revert if the price changes unfavorably by more than this percentage." /> <Tooltip content="Your transaction will revert if the price changes unfavorably by more than this percentage." />

View File

@ -14,6 +14,7 @@ import PriceImpact from './PriceImpact'
import Decimal from 'decimal.js' import Decimal from 'decimal.js'
import { BestPrice } from '../../../../models/BestPrice' import { BestPrice } from '../../../../models/BestPrice'
import { useAsset } from '../../../../providers/Asset'
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 }) Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
@ -36,7 +37,8 @@ export default function Swap({
setMaximumOcean: (value: string) => void setMaximumOcean: (value: string) => void
setCoin: (value: string) => void setCoin: (value: string) => void
}): ReactElement { }): ReactElement {
const { ocean, config } = useOcean() const { ocean } = useOcean()
const { isAssetNetwork } = useAsset()
const [oceanItem, setOceanItem] = useState<TradeItem>({ const [oceanItem, setOceanItem] = useState<TradeItem>({
amount: '0', amount: '0',
token: price.oceanSymbol, token: price.oceanSymbol,
@ -203,16 +205,23 @@ export default function Swap({
<TradeInput <TradeInput
name={values.type === 'sell' ? 'datatoken' : 'ocean'} name={values.type === 'sell' ? 'datatoken' : 'ocean'}
item={values.type === 'sell' ? dtItem : oceanItem} item={values.type === 'sell' ? dtItem : oceanItem}
disabled={!isAssetNetwork}
handleValueChange={handleValueChange} handleValueChange={handleValueChange}
/> />
<Button className={styles.swapButton} style="text" onClick={switchTokens}> <Button
className={styles.swapButton}
style="text"
onClick={switchTokens}
disabled={!isAssetNetwork}
>
<Arrow /> <Arrow />
</Button> </Button>
<TradeInput <TradeInput
name={values.type === 'sell' ? 'ocean' : 'datatoken'} name={values.type === 'sell' ? 'ocean' : 'datatoken'}
item={values.type === 'sell' ? oceanItem : dtItem} item={values.type === 'sell' ? oceanItem : dtItem}
disabled={!isAssetNetwork}
handleValueChange={handleValueChange} handleValueChange={handleValueChange}
/> />
@ -227,7 +236,7 @@ export default function Swap({
tokenAmount={tokenAmount} tokenAmount={tokenAmount}
spotPrice={spotPrice} spotPrice={spotPrice}
/> />
<Slippage /> <Slippage disabled={!isAssetNetwork} />
</div> </div>
) )
} }

View File

@ -15,10 +15,12 @@ import { useOcean } from '../../../../providers/Ocean'
export default function TradeInput({ export default function TradeInput({
name, name,
item, item,
disabled,
handleValueChange handleValueChange
}: { }: {
name: string name: string
item: TradeItem item: TradeItem
disabled: boolean
handleValueChange: (name: string, value: number) => void handleValueChange: (name: string, value: number) => void
}): ReactElement { }): ReactElement {
const { ocean } = useOcean() const { ocean } = useOcean()
@ -62,13 +64,14 @@ export default function TradeInput({
validateForm() validateForm()
handleChange(e) handleChange(e)
}} }}
disabled={!ocean} disabled={!ocean || disabled}
/> />
)} )}
</Field> </Field>
{!isTopField && ( {!isTopField && (
<Button <Button
className={styles.buttonMax} className={styles.buttonMax}
disabled={disabled}
style="text" style="text"
size="small" size="small"
onClick={() => { onClick={() => {

View File

@ -13,6 +13,7 @@ Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
export default function Trade(): ReactElement { export default function Trade(): ReactElement {
const { accountId, balance } = useWeb3() const { accountId, balance } = useWeb3()
const { ocean } = useOcean() const { ocean } = useOcean()
const { isAssetNetwork } = useAsset()
const [tokenBalance, setTokenBalance] = useState<PoolBalance>() const [tokenBalance, setTokenBalance] = useState<PoolBalance>()
const { price, ddo } = useAsset() const { price, ddo } = useAsset()
const [maxDt, setMaxDt] = useState('0') const [maxDt, setMaxDt] = useState('0')
@ -20,7 +21,14 @@ export default function Trade(): ReactElement {
// Get datatoken balance, and combine with OCEAN balance from hooks into one object // Get datatoken balance, and combine with OCEAN balance from hooks into one object
useEffect(() => { useEffect(() => {
if (!ocean || !balance?.ocean || !accountId || !ddo?.dataToken) return if (
!ocean ||
!isAssetNetwork ||
!balance?.ocean ||
!accountId ||
!ddo?.dataToken
)
return
async function getTokenBalance() { async function getTokenBalance() {
const dtBalance = await ocean.datatokens.balance(ddo.dataToken, accountId) const dtBalance = await ocean.datatokens.balance(ddo.dataToken, accountId)
@ -34,12 +42,13 @@ export default function Trade(): ReactElement {
// Get maximum amount for either OCEAN or datatoken // Get maximum amount for either OCEAN or datatoken
useEffect(() => { useEffect(() => {
if (!ocean || !price || price.value === 0) return if (!ocean || !isAssetNetwork || !price || price.value === 0) return
async function getMaximum() { async function getMaximum() {
const maxTokensInPool = await ocean.pool.getDTMaxBuyQuantity( const maxTokensInPool = await ocean.pool.getDTMaxBuyQuantity(
price.address price.address
) )
setMaxDt( setMaxDt(
isValidNumber(maxTokensInPool) isValidNumber(maxTokensInPool)
? new Decimal(maxTokensInPool).toString() ? new Decimal(maxTokensInPool).toString()
@ -49,6 +58,7 @@ export default function Trade(): ReactElement {
const maxOceanInPool = await ocean.pool.getOceanMaxBuyQuantity( const maxOceanInPool = await ocean.pool.getOceanMaxBuyQuantity(
price.address price.address
) )
setMaxOcean( setMaxOcean(
isValidNumber(maxOceanInPool) isValidNumber(maxOceanInPool)
? new Decimal(maxOceanInPool).toString() ? new Decimal(maxOceanInPool).toString()