176 lines
4.3 KiB
TypeScript
176 lines
4.3 KiB
TypeScript
import React, { ChangeEvent, ReactElement, useEffect } from 'react'
|
|
import styles from './FormAdd.module.css'
|
|
import Input from '@shared/FormInput'
|
|
import {
|
|
Field,
|
|
FieldInputProps,
|
|
FormikContextType,
|
|
useFormikContext
|
|
} from 'formik'
|
|
import Button from '@shared/atoms/Button'
|
|
import CoinSelect from '../CoinSelect'
|
|
import { FormAddLiquidity } from '.'
|
|
import UserLiquidity from '../../UserLiquidity'
|
|
import { useOcean } from '@context/Ocean'
|
|
import { useWeb3 } from '@context/Web3'
|
|
|
|
import { isValidNumber } from '@utils/numbers'
|
|
import Decimal from 'decimal.js'
|
|
import { useAsset } from '@context/Asset'
|
|
|
|
export default function FormAdd({
|
|
coin,
|
|
dtBalance,
|
|
dtSymbol,
|
|
amountMax,
|
|
setCoin,
|
|
setAmount,
|
|
totalPoolTokens,
|
|
totalBalance,
|
|
poolAddress,
|
|
setNewPoolTokens,
|
|
setNewPoolShare
|
|
}: {
|
|
coin: string
|
|
dtBalance: string
|
|
dtSymbol: string
|
|
amountMax: string
|
|
setCoin: (value: string) => void
|
|
setAmount: (value: string) => void
|
|
totalPoolTokens: string
|
|
totalBalance: PoolBalance
|
|
poolAddress: string
|
|
setNewPoolTokens: (value: string) => void
|
|
setNewPoolShare: (value: string) => void
|
|
}): ReactElement {
|
|
const { balance } = useWeb3()
|
|
const { ocean } = useOcean()
|
|
const { isAssetNetwork } = useAsset()
|
|
|
|
// Connect with form
|
|
const {
|
|
touched,
|
|
setTouched,
|
|
setFieldValue,
|
|
validateField,
|
|
values
|
|
}: FormikContextType<FormAddLiquidity> = useFormikContext()
|
|
|
|
function handleFieldChange(e: ChangeEvent<HTMLInputElement>) {
|
|
// 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)
|
|
}
|
|
|
|
useEffect(() => {
|
|
async function calculatePoolShares() {
|
|
if (!ocean) 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)
|
|
}
|
|
calculatePoolShares()
|
|
}, [
|
|
values.amount,
|
|
totalBalance,
|
|
totalPoolTokens,
|
|
amountMax,
|
|
coin,
|
|
poolAddress,
|
|
ocean?.pool,
|
|
setNewPoolTokens,
|
|
setNewPoolShare
|
|
])
|
|
|
|
useEffect(() => {
|
|
setFieldValue('amount', undefined)
|
|
}, [coin])
|
|
|
|
return (
|
|
<>
|
|
<UserLiquidity
|
|
amount={coin === 'OCEAN' ? balance.ocean : dtBalance}
|
|
amountMax={amountMax}
|
|
symbol={coin}
|
|
/>
|
|
|
|
<Field name="amount">
|
|
{({
|
|
field,
|
|
form
|
|
}: {
|
|
field: FieldInputProps<FormAddLiquidity>
|
|
form: any
|
|
}) => (
|
|
<Input
|
|
type="number"
|
|
name="amount"
|
|
max={amountMax}
|
|
min="0"
|
|
value={`${values.amount}`}
|
|
step="any"
|
|
prefix={
|
|
<CoinSelect
|
|
dtSymbol={dtSymbol}
|
|
setCoin={setCoin}
|
|
disabled={!ocean || !isAssetNetwork}
|
|
/>
|
|
}
|
|
placeholder="0"
|
|
field={field}
|
|
form={form}
|
|
onChange={handleFieldChange}
|
|
disabled={!ocean || !isAssetNetwork}
|
|
/>
|
|
)}
|
|
</Field>
|
|
|
|
{(Number(balance.ocean) || dtBalance) > (values.amount || 0) && (
|
|
<Button
|
|
className={styles.buttonMax}
|
|
style="text"
|
|
size="small"
|
|
disabled={!ocean}
|
|
onClick={() => {
|
|
setAmount(amountMax)
|
|
setFieldValue('amount', amountMax)
|
|
}}
|
|
>
|
|
Use Max
|
|
</Button>
|
|
)}
|
|
</>
|
|
)
|
|
}
|