import BigNumber from 'bignumber.js' import { useMemo, useState } from 'react' import Button from 'components/Button' import DepositCapMessage from 'components/DepositCapMessage' import DisplayCurrency from 'components/DisplayCurrency' import Divider from 'components/Divider' import { Gauge } from 'components/Gauge' 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 { BN_ZERO } from 'constants/math' import { ORACLE_DENOM } from 'constants/oracle' import usePrices from 'hooks/usePrices' import { BNCoin } from 'types/classes/BNCoin' import { accumulateAmounts } from 'utils/accounts' import { byDenom } from 'utils/array' import { BN, getValueFromBNCoins } from 'utils/helpers' interface Props { deposits: BNCoin[] primaryAsset: Asset secondaryAsset: Asset account: Account isCustomRatio: boolean onChangeDeposits: (deposits: BNCoin[]) => void onChangeIsCustomRatio: (isCustomRatio: boolean) => void toggleOpen: (index: number) => void depositCapReachedCoins: BNCoin[] } export default function VaultDeposit(props: Props) { const { deposits, primaryAsset, secondaryAsset, account, onChangeDeposits } = props const [availablePrimaryAmount, availableSecondaryAmount] = useMemo( () => [ accumulateAmounts(primaryAsset.denom, [...account.deposits, ...account.lends]), accumulateAmounts(secondaryAsset.denom, [...account.deposits, ...account.lends]), ], [account.deposits, account.lends, primaryAsset.denom, secondaryAsset.denom], ) const { data: prices } = usePrices() const primaryPrice = prices.find(byDenom(primaryAsset.denom))?.amount ?? BN_ZERO const secondaryPrice = prices.find(byDenom(secondaryAsset.denom))?.amount ?? BN_ZERO const primaryCoin = useMemo(() => { const amount = deposits.find(byDenom(primaryAsset.denom))?.amount ?? BN_ZERO return new BNCoin({ denom: primaryAsset.denom, amount: amount.toString() }) }, [deposits, primaryAsset.denom]) const secondaryCoin = useMemo(() => { const amount = deposits.find(byDenom(secondaryAsset.denom))?.amount ?? BN_ZERO return new BNCoin({ denom: secondaryAsset.denom, amount: amount.toString() }) }, [deposits, secondaryAsset.denom]) const primaryValue = useMemo( () => getValueFromBNCoins([primaryCoin], prices), [primaryCoin, prices], ) const totalValue = useMemo( () => getValueFromBNCoins([primaryCoin, secondaryCoin], prices), [primaryCoin, secondaryCoin, prices], ) const primaryValuePercentage = useMemo(() => { const value = primaryValue.dividedBy(totalValue).multipliedBy(100).decimalPlaces(2).toNumber() return isNaN(value) ? 50 : value }, [primaryValue, totalValue]) const secondaryValuePercentage = useMemo( () => new BigNumber(100).minus(primaryValuePercentage).integerValue(2).toNumber() ?? 50, [primaryValuePercentage], ) const maxAssetValueNonCustom = useMemo( () => BN( Math.min( availablePrimaryAmount .shiftedBy(-primaryAsset.decimals) .multipliedBy(primaryPrice) .toNumber(), availableSecondaryAmount .shiftedBy(-secondaryAsset.decimals) .multipliedBy(secondaryPrice) .toNumber(), ), ), [ availablePrimaryAmount, availableSecondaryAmount, primaryAsset, primaryPrice, secondaryAsset, secondaryPrice, ], ) const primaryMax = useMemo( () => props.isCustomRatio ? availablePrimaryAmount : maxAssetValueNonCustom .dividedBy(primaryPrice) .shiftedBy(primaryAsset.decimals) .integerValue(), [ props.isCustomRatio, availablePrimaryAmount, primaryPrice, primaryAsset, maxAssetValueNonCustom, ], ) const secondaryMax = useMemo(() => { return props.isCustomRatio ? availableSecondaryAmount : maxAssetValueNonCustom .dividedBy(secondaryPrice) .shiftedBy(secondaryAsset.decimals) .integerValue() }, [ props.isCustomRatio, availableSecondaryAmount, secondaryPrice, secondaryAsset, maxAssetValueNonCustom, ]) const [percentage, setPercentage] = useState( primaryValue.dividedBy(maxAssetValueNonCustom).multipliedBy(100).decimalPlaces(0).toNumber() || 0, ) const disableInput = (availablePrimaryAmount.isZero() || availableSecondaryAmount.isZero()) && !props.isCustomRatio function handleSwitch() { const isCustomRatioNew = !props.isCustomRatio if (!isCustomRatioNew) { primaryCoin.amount = BN_ZERO secondaryCoin.amount = BN_ZERO onChangeDeposits([primaryCoin, secondaryCoin]) setPercentage(0) } props.onChangeIsCustomRatio(isCustomRatioNew) } function onChangePrimaryDeposit(amount: BigNumber) { if (amount.isGreaterThan(primaryMax)) { amount = primaryMax } primaryCoin.amount = amount setPercentage(amount.dividedBy(primaryMax).multipliedBy(100).decimalPlaces(0).toNumber()) if (!props.isCustomRatio) { secondaryCoin.amount = secondaryMax.multipliedBy(amount.dividedBy(primaryMax)).integerValue() } onChangeDeposits([primaryCoin, secondaryCoin]) } function onChangeSecondaryDeposit(amount: BigNumber) { if (amount.isGreaterThan(secondaryMax)) { amount = secondaryMax } secondaryCoin.amount = amount setPercentage(amount.dividedBy(secondaryMax).multipliedBy(100).decimalPlaces(0).toNumber()) if (!props.isCustomRatio) { primaryCoin.amount = primaryMax.multipliedBy(amount.dividedBy(secondaryMax)).integerValue() } onChangeDeposits([primaryCoin, secondaryCoin]) } function onChangeSlider(value: number) { setPercentage(value) primaryCoin.amount = primaryMax.multipliedBy(value / 100).integerValue() secondaryCoin.amount = secondaryMax.multipliedBy(value / 100).integerValue() onChangeDeposits([primaryCoin, secondaryCoin]) } function getWarningText(asset: Asset) { return `You don't have ${asset.symbol} balance in your account. Toggle custom amount to deposit.` } return (