mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
put back Remove Liquidity components (#1551)
* put back Remove Liquidity components * remove Pool Share Lock action
This commit is contained in:
parent
e885a5c921
commit
65045ba7b9
@ -0,0 +1,25 @@
|
||||
.actions {
|
||||
margin-left: -2rem;
|
||||
margin-right: -2rem;
|
||||
padding-left: var(--spacer);
|
||||
padding-right: var(--spacer);
|
||||
padding-top: calc(var(--spacer) / 1.5);
|
||||
border-top: 1px solid var(--border-color);
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.success {
|
||||
margin-top: calc(var(--spacer) / 2);
|
||||
margin-bottom: calc(var(--spacer) / 2);
|
||||
}
|
||||
|
||||
.actions button {
|
||||
margin-left: calc(var(--spacer) / 4);
|
||||
margin-right: calc(var(--spacer) / 4);
|
||||
}
|
||||
|
||||
.actions button svg {
|
||||
fill: currentColor;
|
||||
}
|
75
src/components/organisms/AssetActions/Pool/Actions.tsx
Normal file
75
src/components/organisms/AssetActions/Pool/Actions.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import Loader from '../../../atoms/Loader'
|
||||
import Button from '../../../atoms/Button'
|
||||
import styles from './Actions.module.css'
|
||||
import ExplorerLink from '../../../atoms/ExplorerLink'
|
||||
import SuccessConfetti from '../../../atoms/SuccessConfetti'
|
||||
import { useOcean } from '../../../../providers/Ocean'
|
||||
import { useWeb3 } from '../../../../providers/Web3'
|
||||
import TokenApproval from '../../../molecules/TokenApproval'
|
||||
|
||||
export default function Actions({
|
||||
isLoading,
|
||||
loaderMessage,
|
||||
successMessage,
|
||||
txId,
|
||||
actionName,
|
||||
amount,
|
||||
coin,
|
||||
action,
|
||||
isDisabled
|
||||
}: {
|
||||
isLoading: boolean
|
||||
loaderMessage: string
|
||||
successMessage: string
|
||||
txId: string
|
||||
actionName: string
|
||||
amount?: string
|
||||
coin?: string
|
||||
action: () => void
|
||||
isDisabled?: boolean
|
||||
}): ReactElement {
|
||||
const { networkId } = useWeb3()
|
||||
const { ocean } = useOcean()
|
||||
|
||||
const actionButton = (
|
||||
<Button
|
||||
style="primary"
|
||||
size="small"
|
||||
onClick={() => action()}
|
||||
disabled={!ocean || isDisabled}
|
||||
>
|
||||
{actionName}
|
||||
</Button>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.actions}>
|
||||
{isLoading ? (
|
||||
<Loader message={loaderMessage} />
|
||||
) : actionName === 'Supply' || actionName === 'Swap' ? (
|
||||
<TokenApproval
|
||||
actionButton={actionButton}
|
||||
amount={amount}
|
||||
coin={coin}
|
||||
disabled={!ocean || isDisabled}
|
||||
/>
|
||||
) : (
|
||||
actionButton
|
||||
)}
|
||||
</div>
|
||||
{txId && (
|
||||
<SuccessConfetti
|
||||
className={styles.success}
|
||||
success={successMessage}
|
||||
action={
|
||||
<ExplorerLink networkId={networkId} path={`/tx/${txId}`}>
|
||||
View transaction
|
||||
</ExplorerLink>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
.output {
|
||||
display: grid;
|
||||
gap: var(--spacer);
|
||||
grid-template-columns: 1fr 1fr;
|
||||
padding-bottom: calc(var(--spacer) / 2);
|
||||
}
|
||||
|
||||
.output p {
|
||||
font-weight: var(--font-weight-bold);
|
||||
margin-bottom: calc(var(--spacer) / 8);
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
|
||||
.output div:first-child [class*='token'] {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.output div:first-child [class*='token'] > figure {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.help {
|
||||
text-align: center;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
.addInput {
|
||||
margin: 0 auto calc(var(--spacer) / 1.5) auto;
|
||||
background: var(--background-highlight);
|
||||
padding: var(--spacer) calc(var(--spacer) * 2.5) calc(var(--spacer) * 1.2)
|
||||
calc(var(--spacer) * 2.5);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
margin-top: -2rem;
|
||||
margin-left: -2rem;
|
||||
margin-right: -2rem;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.addInput input {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.addInput div[class*='field'] {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.warning {
|
||||
margin-left: -3rem;
|
||||
margin-right: -3rem;
|
||||
}
|
70
src/components/organisms/AssetActions/Pool/Remove.module.css
Normal file
70
src/components/organisms/AssetActions/Pool/Remove.module.css
Normal file
@ -0,0 +1,70 @@
|
||||
.removeInput {
|
||||
composes: addInput from './Add/index.module.css';
|
||||
padding-left: calc(var(--spacer) * 2);
|
||||
padding-right: calc(var(--spacer) * 2);
|
||||
padding-bottom: calc(var(--spacer) / 2);
|
||||
}
|
||||
|
||||
.range {
|
||||
margin-top: calc(var(--spacer) / 2);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.range h3 {
|
||||
margin-bottom: calc(var(--spacer) / 4);
|
||||
}
|
||||
|
||||
.range input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.range p {
|
||||
margin-bottom: 0;
|
||||
margin-left: -2rem;
|
||||
margin-right: -2rem;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.maximum {
|
||||
position: absolute;
|
||||
right: -2rem;
|
||||
bottom: 2rem;
|
||||
font-size: var(--font-size-mini);
|
||||
min-width: 5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
margin-top: calc(var(--spacer) / 2);
|
||||
margin-bottom: 0;
|
||||
font-size: var(--font-size-mini);
|
||||
margin-bottom: -2rem;
|
||||
}
|
||||
|
||||
.output {
|
||||
composes: output from './Add/Output.module.css';
|
||||
}
|
||||
|
||||
.output [class*='token'] {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.output [class*='token'] > figure {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.output figure[class*='pool shares'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.output p {
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
|
||||
.slippage {
|
||||
composes: slippage from '../Trade/Slippage.module.css';
|
||||
}
|
313
src/components/organisms/AssetActions/Pool/Remove.tsx
Normal file
313
src/components/organisms/AssetActions/Pool/Remove.tsx
Normal file
@ -0,0 +1,313 @@
|
||||
import React, {
|
||||
ReactElement,
|
||||
useState,
|
||||
ChangeEvent,
|
||||
useEffect,
|
||||
FormEvent,
|
||||
useRef
|
||||
} from 'react'
|
||||
import styles from './Remove.module.css'
|
||||
import Header from './Header'
|
||||
import { toast } from 'react-toastify'
|
||||
import Actions from './Actions'
|
||||
import { Logger } from '@oceanprotocol/lib'
|
||||
import Token from './Token'
|
||||
import FormHelp from '../../../atoms/Input/Help'
|
||||
import Button from '../../../atoms/Button'
|
||||
import { getMaxPercentRemove } from './utils'
|
||||
import { graphql, useStaticQuery } from 'gatsby'
|
||||
import debounce from 'lodash.debounce'
|
||||
import UserLiquidity from '../../../atoms/UserLiquidity'
|
||||
import InputElement from '../../../atoms/Input/InputElement'
|
||||
import { useOcean } from '../../../../providers/Ocean'
|
||||
import { useWeb3 } from '../../../../providers/Web3'
|
||||
import Decimal from 'decimal.js'
|
||||
import { useAsset } from '../../../../providers/Asset'
|
||||
|
||||
const contentQuery = graphql`
|
||||
query PoolRemoveQuery {
|
||||
content: allFile(filter: { relativePath: { eq: "price.json" } }) {
|
||||
edges {
|
||||
node {
|
||||
childContentJson {
|
||||
pool {
|
||||
remove {
|
||||
title
|
||||
simple
|
||||
advanced
|
||||
output {
|
||||
titleIn
|
||||
titleOut
|
||||
}
|
||||
action
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export default function Remove({
|
||||
setShowRemove,
|
||||
refreshInfo,
|
||||
poolAddress,
|
||||
poolTokens,
|
||||
totalPoolTokens,
|
||||
dtSymbol
|
||||
}: {
|
||||
setShowRemove: (show: boolean) => void
|
||||
refreshInfo: () => void
|
||||
poolAddress: string
|
||||
poolTokens: string
|
||||
totalPoolTokens: string
|
||||
dtSymbol: string
|
||||
}): ReactElement {
|
||||
const data = useStaticQuery(contentQuery)
|
||||
const content = data.content.edges[0].node.childContentJson.pool.remove
|
||||
|
||||
const slippagePresets = ['5', '10', '15', '25', '50']
|
||||
const { accountId } = useWeb3()
|
||||
const { ocean } = useOcean()
|
||||
const { isAssetNetwork } = useAsset()
|
||||
const [amountPercent, setAmountPercent] = useState('0')
|
||||
const [amountMaxPercent, setAmountMaxPercent] = useState('100')
|
||||
const [amountPoolShares, setAmountPoolShares] = useState('0')
|
||||
const [amountOcean, setAmountOcean] = useState('0')
|
||||
const [amountDatatoken, setAmountDatatoken] = useState('0')
|
||||
const [isAdvanced, setIsAdvanced] = useState(false)
|
||||
const [isLoading, setIsLoading] = useState<boolean>()
|
||||
const [txId, setTxId] = useState<string>()
|
||||
const [slippage, setSlippage] = useState<string>('5')
|
||||
const [minOceanAmount, setMinOceanAmount] = useState<string>('0')
|
||||
const [minDatatokenAmount, setMinDatatokenAmount] = useState<string>('0')
|
||||
|
||||
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
|
||||
|
||||
async function handleRemoveLiquidity() {
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const result =
|
||||
isAdvanced === true
|
||||
? await ocean.pool.removePoolLiquidity(
|
||||
accountId,
|
||||
poolAddress,
|
||||
amountPoolShares,
|
||||
minDatatokenAmount,
|
||||
minOceanAmount
|
||||
)
|
||||
: await ocean.pool.removeOceanLiquidityWithMinimum(
|
||||
accountId,
|
||||
poolAddress,
|
||||
amountPoolShares,
|
||||
minOceanAmount
|
||||
)
|
||||
|
||||
setTxId(result?.transactionHash)
|
||||
refreshInfo()
|
||||
} catch (error) {
|
||||
Logger.error(error.message)
|
||||
toast.error(error.message)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
// Get and set max percentage
|
||||
useEffect(() => {
|
||||
if (!ocean || !poolTokens) return
|
||||
|
||||
async function getMax() {
|
||||
const amountMaxPercent =
|
||||
isAdvanced === true
|
||||
? '100'
|
||||
: await getMaxPercentRemove(ocean, poolAddress, poolTokens)
|
||||
setAmountMaxPercent(amountMaxPercent)
|
||||
}
|
||||
getMax()
|
||||
}, [ocean, isAdvanced, poolAddress, poolTokens])
|
||||
|
||||
const getValues = useRef(
|
||||
debounce(async (newAmountPoolShares, isAdvanced) => {
|
||||
if (isAdvanced === true) {
|
||||
const tokens = await ocean.pool.getTokensRemovedforPoolShares(
|
||||
poolAddress,
|
||||
`${newAmountPoolShares}`
|
||||
)
|
||||
setAmountOcean(tokens?.oceanAmount)
|
||||
setAmountDatatoken(tokens?.dtAmount)
|
||||
return
|
||||
}
|
||||
|
||||
const amountOcean = await ocean.pool.getOceanRemovedforPoolShares(
|
||||
poolAddress,
|
||||
newAmountPoolShares
|
||||
)
|
||||
setAmountOcean(amountOcean)
|
||||
}, 150)
|
||||
)
|
||||
// Check and set outputs when amountPoolShares changes
|
||||
useEffect(() => {
|
||||
if (!ocean || !poolTokens) return
|
||||
getValues.current(amountPoolShares, isAdvanced)
|
||||
}, [
|
||||
amountPoolShares,
|
||||
isAdvanced,
|
||||
ocean,
|
||||
poolTokens,
|
||||
poolAddress,
|
||||
totalPoolTokens
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
const minOceanAmount = new Decimal(amountOcean)
|
||||
.mul(new Decimal(100).minus(new Decimal(slippage)))
|
||||
.dividedBy(100)
|
||||
.toString()
|
||||
|
||||
const minDatatokenAmount = new Decimal(amountDatatoken)
|
||||
.mul(new Decimal(100).minus(new Decimal(slippage)))
|
||||
.dividedBy(100)
|
||||
.toString()
|
||||
|
||||
setMinOceanAmount(minOceanAmount.slice(0, 18))
|
||||
setMinDatatokenAmount(minDatatokenAmount.slice(0, 18))
|
||||
}, [slippage, amountOcean, amountDatatoken, isAdvanced])
|
||||
|
||||
// Set amountPoolShares based on set slider value
|
||||
function handleAmountPercentChange(e: ChangeEvent<HTMLInputElement>) {
|
||||
setAmountPercent(e.target.value)
|
||||
if (!poolTokens) return
|
||||
|
||||
const amountPoolShares = new Decimal(e.target.value)
|
||||
.dividedBy(100)
|
||||
.mul(new Decimal(poolTokens))
|
||||
.toString()
|
||||
|
||||
setAmountPoolShares(`${amountPoolShares.slice(0, 18)}`)
|
||||
}
|
||||
|
||||
function handleMaxButton(e: ChangeEvent<HTMLInputElement>) {
|
||||
e.preventDefault()
|
||||
setAmountPercent(amountMaxPercent)
|
||||
|
||||
const amountPoolShares = new Decimal(amountMaxPercent)
|
||||
.dividedBy(100)
|
||||
.mul(new Decimal(poolTokens))
|
||||
.toString()
|
||||
|
||||
setAmountPoolShares(`${amountPoolShares.slice(0, 18)}`)
|
||||
}
|
||||
|
||||
function handleAdvancedButton(e: FormEvent<HTMLButtonElement>) {
|
||||
e.preventDefault()
|
||||
setIsAdvanced(!isAdvanced)
|
||||
|
||||
setAmountPoolShares('0')
|
||||
setAmountPercent('0')
|
||||
setAmountOcean('0')
|
||||
setSlippage('5')
|
||||
setMinOceanAmount('0')
|
||||
setMinDatatokenAmount('0')
|
||||
|
||||
if (isAdvanced === true) {
|
||||
setAmountDatatoken('0')
|
||||
}
|
||||
}
|
||||
|
||||
function handleSlippageChange(e: ChangeEvent<HTMLSelectElement>) {
|
||||
setSlippage(e.target.value)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.remove}>
|
||||
<Header title={content.title} backAction={() => setShowRemove(false)} />
|
||||
|
||||
<form className={styles.removeInput}>
|
||||
<UserLiquidity amount={poolTokens} symbol="pool shares" />
|
||||
<div className={styles.range}>
|
||||
<h3>{amountPercent}%</h3>
|
||||
<div className={styles.slider}>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max={amountMaxPercent}
|
||||
disabled={!isAssetNetwork}
|
||||
value={amountPercent}
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
handleAmountPercentChange(e)
|
||||
}
|
||||
/>
|
||||
<Button
|
||||
style="text"
|
||||
size="small"
|
||||
className={styles.maximum}
|
||||
disabled={!isAssetNetwork}
|
||||
onClick={(e: ChangeEvent<HTMLInputElement>) => handleMaxButton(e)}
|
||||
>
|
||||
{`${amountMaxPercent}% max`}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<FormHelp>
|
||||
{isAdvanced === true ? content.advanced : content.simple}
|
||||
</FormHelp>
|
||||
<Button
|
||||
style="text"
|
||||
size="small"
|
||||
onClick={(e: FormEvent<HTMLButtonElement>) =>
|
||||
handleAdvancedButton(e)
|
||||
}
|
||||
disabled={!isAssetNetwork}
|
||||
className={styles.toggle}
|
||||
>
|
||||
{isAdvanced === true ? 'Simple' : 'Advanced'}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
<div className={styles.output}>
|
||||
<div>
|
||||
<p>{content.output.titleIn}</p>
|
||||
<Token symbol="pool shares" balance={amountPoolShares} noIcon />
|
||||
</div>
|
||||
<div>
|
||||
<p>{content.output.titleOut} minimum</p>
|
||||
{isAdvanced === true ? (
|
||||
<>
|
||||
<Token symbol="OCEAN" balance={minOceanAmount} />
|
||||
<Token symbol={dtSymbol} balance={minDatatokenAmount} />
|
||||
</>
|
||||
) : (
|
||||
<Token symbol="OCEAN" balance={minOceanAmount} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.slippage}>
|
||||
<strong>Expected price impact</strong>
|
||||
<InputElement
|
||||
name="slippage"
|
||||
type="select"
|
||||
size="mini"
|
||||
postfix="%"
|
||||
sortOptions={false}
|
||||
options={slippagePresets}
|
||||
disabled={!isAssetNetwork}
|
||||
value={slippage}
|
||||
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
|
||||
handleSlippageChange(e)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<Actions
|
||||
isLoading={isLoading}
|
||||
loaderMessage="Removing Liquidity..."
|
||||
actionName={content.action}
|
||||
action={() => handleRemoveLiquidity()}
|
||||
successMessage="Successfully removed liquidity."
|
||||
isDisabled={!isAssetNetwork}
|
||||
txId={txId}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import { Logger } from '@oceanprotocol/lib'
|
||||
import styles from './index.module.css'
|
||||
import stylesActions from './Actions.module.css'
|
||||
import PriceUnit from '../../../atoms/Price/PriceUnit'
|
||||
import Alert from '../../../atoms/Alert'
|
||||
import Tooltip from '../../../atoms/Tooltip'
|
||||
import ExplorerLink from '../../../atoms/ExplorerLink'
|
||||
import Token from './Token'
|
||||
@ -19,10 +19,8 @@ import PoolTransactions from '../../../molecules/PoolTransactions'
|
||||
import { fetchData, getQueryContext } from '../../../../utils/subgraph'
|
||||
import { isValidNumber } from './../../../../utils/numberValidations'
|
||||
import Decimal from 'decimal.js'
|
||||
import {
|
||||
MigrationStatus,
|
||||
useMigrationStatus
|
||||
} from '../../../../providers/Migration'
|
||||
import Remove from './Remove'
|
||||
import Button from '../../../atoms/Button'
|
||||
|
||||
const REFETCH_INTERVAL = 5000
|
||||
|
||||
@ -86,11 +84,10 @@ export default function Pool(): ReactElement {
|
||||
const content = data.content.edges[0].node.childContentJson.pool
|
||||
|
||||
const { accountId } = useWeb3()
|
||||
const { status } = useMigrationStatus()
|
||||
|
||||
const [dtSymbol, setDtSymbol] = useState<string>()
|
||||
const [oceanSymbol, setOceanSymbol] = useState<string>()
|
||||
const { ddo, owner, price } = useAsset()
|
||||
const { ddo, owner, price, isInPurgatory, isAssetNetwork } = useAsset()
|
||||
|
||||
const [poolTokens, setPoolTokens] = useState<string>()
|
||||
const [totalPoolTokens, setTotalPoolTokens] = useState<string>()
|
||||
@ -116,6 +113,13 @@ export default function Pool(): ReactElement {
|
||||
const [liquidityFetchInterval, setLiquidityFetchInterval] =
|
||||
useState<NodeJS.Timeout>()
|
||||
|
||||
const [showRemove, setShowRemove] = useState(false)
|
||||
const [isRemoveDisabled, setIsRemoveDisabled] = useState(false)
|
||||
|
||||
const [hasAddedLiquidity, setHasAddedLiquidity] = useState(false)
|
||||
// the purpose of the value is just to trigger the effect
|
||||
const [refreshPool, setRefreshPool] = useState(false)
|
||||
|
||||
async function getPoolLiquidity() {
|
||||
const queryContext = getQueryContext(ddo.chainId)
|
||||
const queryVariables = {
|
||||
@ -267,6 +271,10 @@ export default function Pool(): ReactElement {
|
||||
init()
|
||||
}, [dataLiquidity, ddo.dataToken, price.datatoken, price.ocean, price?.value])
|
||||
|
||||
useEffect(() => {
|
||||
setIsRemoveDisabled(isInPurgatory && owner === accountId)
|
||||
}, [isInPurgatory, owner, accountId])
|
||||
|
||||
useEffect(() => {
|
||||
if (!dataLiquidity) return
|
||||
const poolShare =
|
||||
@ -280,6 +288,7 @@ export default function Pool(): ReactElement {
|
||||
.toFixed(5)
|
||||
|
||||
setPoolShare(poolShare)
|
||||
setHasAddedLiquidity(Number(poolShare) > 0)
|
||||
|
||||
const totalUserLiquidityInOcean =
|
||||
isValidNumber(userLiquidity?.ocean) &&
|
||||
@ -350,7 +359,23 @@ export default function Pool(): ReactElement {
|
||||
init()
|
||||
}, [accountId, price, ddo, owner, totalPoolTokens])
|
||||
|
||||
return (
|
||||
const refreshInfo = async () => {
|
||||
setRefreshPool(!refreshPool)
|
||||
|
||||
// need some form of replacement or something.
|
||||
// await refreshPrice()
|
||||
}
|
||||
|
||||
return showRemove ? (
|
||||
<Remove
|
||||
setShowRemove={setShowRemove}
|
||||
refreshInfo={refreshInfo}
|
||||
poolAddress={price.address}
|
||||
poolTokens={poolTokens}
|
||||
totalPoolTokens={totalPoolTokens}
|
||||
dtSymbol={dtSymbol}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<div className={styles.dataToken}>
|
||||
<PriceUnit price="1" symbol={dtSymbol} /> ={' '}
|
||||
@ -433,15 +458,16 @@ export default function Pool(): ReactElement {
|
||||
>
|
||||
<Token symbol="% swap fee" balance={swapFee} noIcon />
|
||||
</TokenList>
|
||||
<Alert
|
||||
title="Adding and removing liquidity is disabled"
|
||||
text={
|
||||
status === MigrationStatus.ALLOWED
|
||||
? 'Pool Shares are currently being locked. Adding and removing liquidity is disabled while the pool shares are being locked.'
|
||||
: 'Adding and removing liquidity is currently disabled for all pools.'
|
||||
}
|
||||
state="info"
|
||||
/>
|
||||
|
||||
<div className={stylesActions.actions}>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => setShowRemove(true)}
|
||||
disabled={!isAssetNetwork || !hasAddedLiquidity || isRemoveDisabled}
|
||||
>
|
||||
Remove Liquidity
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{accountId && (
|
||||
<AssetActionHistoryTable title="Your Pool Transactions">
|
||||
|
37
src/components/organisms/AssetActions/Pool/utils.ts
Normal file
37
src/components/organisms/AssetActions/Pool/utils.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { Ocean } from '@oceanprotocol/lib'
|
||||
|
||||
import { isValidNumber } from './../../../../utils/numberValidations'
|
||||
import Decimal from 'decimal.js'
|
||||
|
||||
Decimal.set({ toExpNeg: -18, precision: 18, rounding: 1 })
|
||||
|
||||
export async function getMaxPercentRemove(
|
||||
ocean: Ocean,
|
||||
poolAddress: string,
|
||||
poolTokens: string
|
||||
): Promise<string> {
|
||||
const amountMaxOcean = await ocean.pool.getOceanMaxRemoveLiquidity(
|
||||
poolAddress
|
||||
)
|
||||
|
||||
const amountMaxPoolShares =
|
||||
await ocean.pool.getPoolSharesRequiredToRemoveOcean(
|
||||
poolAddress,
|
||||
amountMaxOcean
|
||||
)
|
||||
|
||||
let amountMaxPercent =
|
||||
isValidNumber(amountMaxPoolShares) && isValidNumber(poolTokens)
|
||||
? new Decimal(amountMaxPoolShares)
|
||||
.dividedBy(new Decimal(poolTokens))
|
||||
.mul(100)
|
||||
.floor()
|
||||
.toString()
|
||||
: '0'
|
||||
|
||||
if (Number(amountMaxPercent) > 100) {
|
||||
amountMaxPercent = '100'
|
||||
}
|
||||
|
||||
return amountMaxPercent
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
.slippage {
|
||||
font-size: var(--font-size-small);
|
||||
border-top: 1px solid var(--border-color);
|
||||
margin-left: -2rem;
|
||||
margin-right: -2rem;
|
||||
padding: calc(var(--spacer) / 4) var(--spacer);
|
||||
color: var(--color-secondary);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: calc(var(--spacer) / 3);
|
||||
}
|
||||
|
||||
.slippage strong {
|
||||
font-weight: var(--font-weight-base);
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-family: var(--font-family-base);
|
||||
font-weight: var(--font-weight-base);
|
||||
font-size: var(--font-size-mini);
|
||||
text-align: center;
|
||||
margin-bottom: calc(var(--spacer) / 4);
|
||||
color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.slippage select {
|
||||
width: fit-content;
|
||||
display: inline-block;
|
||||
}
|
@ -135,7 +135,6 @@ export default function AssetActions(): ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
{price?.type === 'pool' && <Migration />}
|
||||
<Permission eventType="consume">
|
||||
<Tabs items={tabs} className={styles.actions} />
|
||||
</Permission>
|
||||
|
Loading…
x
Reference in New Issue
Block a user