mars-v2-frontend/src/components/Modals/vault/VaultDeposit.tsx
Bob van der Helm 9d09ebdf77
Mp 2544 Vault deposit (#240)
* Show guages on deposit

* Finish VaultDeposit

* resolve PR comments
2023-06-01 15:55:42 +02:00

219 lines
7.7 KiB
TypeScript

import BigNumber from 'bignumber.js'
import { useMemo, useState } from 'react'
import Button from 'components/Button'
import DisplayCurrency from 'components/DisplayCurrency'
import Divider from 'components/Divider'
import { ArrowRight, ExclamationMarkCircled } from 'components/Icons'
import Slider from 'components/Slider'
import Switch from 'components/Switch'
import Text from 'components/Text'
import TokenInput from 'components/TokenInput'
import usePrice from 'hooks/usePrice'
import { getAmount } from 'utils/accounts'
import { BN } from 'utils/helpers'
import { Gauge } from 'components/Gauge'
import useStore from 'store'
interface Props {
primaryAmount: BigNumber
secondaryAmount: BigNumber
primaryAsset: Asset
secondaryAsset: Asset
account: Account
isCustomRatio: boolean
onChangeIsCustomRatio: (isCustomRatio: boolean) => void
onChangePrimaryAmount: (amount: BigNumber) => void
onChangeSecondaryAmount: (amount: BigNumber) => void
toggleOpen: (index: number) => void
}
export default function VaultDeposit(props: Props) {
const baseCurrency = useStore((s) => s.baseCurrency)
const availablePrimaryAmount = getAmount(props.primaryAsset.denom, props.account.deposits)
const availableSecondaryAmount = getAmount(props.secondaryAsset.denom, props.account.deposits)
const primaryPrice = usePrice(props.primaryAsset.denom)
const secondaryPrice = usePrice(props.secondaryAsset.denom)
const primaryValue = useMemo(
() => props.primaryAmount.times(primaryPrice),
[props.primaryAmount, primaryPrice],
)
const secondaryValue = useMemo(
() => props.secondaryAmount.times(secondaryPrice),
[props.secondaryAmount, secondaryPrice],
)
const totalValue = useMemo(
() => primaryValue.plus(secondaryValue),
[primaryValue, secondaryValue],
)
const primaryValuePercentage = useMemo(
() => primaryValue.div(totalValue).times(100).decimalPlaces(2).toNumber() || 50,
[primaryValue, totalValue],
)
const secondaryValuePercentage = useMemo(
() => new BigNumber(100).minus(primaryValuePercentage).decimalPlaces(2).toNumber() || 50,
[primaryValuePercentage],
)
const maxAssetValueNonCustom = useMemo(
() =>
BN(
Math.min(
availablePrimaryAmount.times(primaryPrice).toNumber(),
availableSecondaryAmount.times(secondaryPrice).toNumber(),
),
),
[availablePrimaryAmount, primaryPrice, availableSecondaryAmount, secondaryPrice],
)
const primaryMax = useMemo(
() =>
props.isCustomRatio ? availablePrimaryAmount : maxAssetValueNonCustom.dividedBy(primaryPrice),
[props.isCustomRatio, availablePrimaryAmount, primaryPrice, maxAssetValueNonCustom],
)
const secondaryMax = useMemo(
() =>
props.isCustomRatio
? availableSecondaryAmount
: maxAssetValueNonCustom.dividedBy(secondaryPrice),
[props.isCustomRatio, availableSecondaryAmount, secondaryPrice, maxAssetValueNonCustom],
)
const [percentage, setPercentage] = useState(
primaryValue.dividedBy(maxAssetValueNonCustom).times(100).decimalPlaces(0).toNumber(),
)
const disableInput =
(availablePrimaryAmount.isZero() || availableSecondaryAmount.isZero()) && !props.isCustomRatio
function handleSwitch() {
const isCustomRatioNew = !props.isCustomRatio
if (!isCustomRatioNew) {
props.onChangePrimaryAmount(BN(0))
props.onChangeSecondaryAmount(BN(0))
setPercentage(0)
}
props.onChangeIsCustomRatio(isCustomRatioNew)
}
function onChangePrimaryDeposit(amount: BigNumber) {
if (amount.isGreaterThan(primaryMax)) {
amount = primaryMax
}
props.onChangePrimaryAmount(amount)
setPercentage(amount.dividedBy(primaryMax).times(100).decimalPlaces(0).toNumber())
if (!props.isCustomRatio) {
props.onChangeSecondaryAmount(secondaryMax.multipliedBy(amount.dividedBy(primaryMax)))
}
}
function onChangeSecondaryDeposit(amount: BigNumber) {
if (amount.isGreaterThan(secondaryMax)) {
amount = secondaryMax
}
props.onChangeSecondaryAmount(amount)
setPercentage(amount.dividedBy(secondaryMax).times(100).decimalPlaces(0).toNumber())
if (!props.isCustomRatio) {
props.onChangePrimaryAmount(primaryMax.multipliedBy(amount.dividedBy(secondaryMax)))
}
}
function onChangeSlider(value: number) {
setPercentage(value)
props.onChangePrimaryAmount(primaryMax.multipliedBy(value / 100))
props.onChangeSecondaryAmount(secondaryMax.multipliedBy(value / 100))
}
function getWarningText(asset: Asset) {
return `You don't have ${asset.symbol} balance in your account. Toggle custom amount to deposit.`
}
return (
<div className='flex flex-col'>
<div className='flex gap-4 p-4'>
<div className='flex flex-col items-center justify-between gap-1 pb-[30px] pt-2'>
<Gauge
percentage={primaryValuePercentage}
tooltip={`${primaryValuePercentage}% of value is ${props.primaryAsset.symbol}`}
labelClassName='text-martian-red'
diameter={32}
strokeColor='#FF645F'
strokeWidth={3}
/>
<div className='h-full w-[1px] rounded-xl bg-white/10'></div>
<Gauge
percentage={secondaryValuePercentage}
tooltip={`${secondaryValuePercentage}% of value is ${props.secondaryAsset.symbol}`}
labelClassName='text-martian-red'
diameter={32}
strokeColor='#FF645F'
strokeWidth={3}
/>
</div>
<div className='flex h-full flex-grow flex-col justify-between gap-6'>
<TokenInput
onChange={onChangePrimaryDeposit}
amount={props.primaryAmount}
max={availablePrimaryAmount}
maxText='Balance'
asset={props.primaryAsset}
warning={
availablePrimaryAmount.isZero() ? getWarningText(props.primaryAsset) : undefined
}
disabled={disableInput}
/>
{!props.isCustomRatio && (
<Slider value={percentage} onChange={onChangeSlider} disabled={disableInput} />
)}
<TokenInput
onChange={onChangeSecondaryDeposit}
amount={props.secondaryAmount}
max={availableSecondaryAmount}
maxText='Balance'
asset={props.secondaryAsset}
warning={
availableSecondaryAmount.isZero() ? getWarningText(props.secondaryAsset) : undefined
}
disabled={disableInput}
/>
</div>
</div>
<div className='flex flex-col gap-6 p-4 pt-2'>
{disableInput ? (
<div>
<Divider />
<div className='flex items-center gap-4 py-4'>
<div className='w-5'>
<ExclamationMarkCircled className='w-5 gap-3 text-white' />
</div>
<Text size='xs'>
You currently have little to none of one asset. Toggle custom ratio to supply your
assets asymmetrically.
</Text>
</div>
<Divider />
</div>
) : (
<Divider />
)}
<div className='flex justify-between'>
<Text className='text-white/50'>Custom ratio</Text>
<Switch checked={props.isCustomRatio} onChange={handleSwitch} name='customRatio' />
</div>
<div className='flex justify-between'>
<Text className='text-white/50'>{`${props.primaryAsset.symbol}-${props.secondaryAsset.symbol} Deposit Value`}</Text>
<DisplayCurrency coin={{ denom: baseCurrency.denom, amount: totalValue.toString() }} />
</div>
<Button
onClick={() => props.toggleOpen(1)}
className='w-full'
text='Continue'
rightIcon={<ArrowRight />}
/>
</div>
</div>
)
}