import BigNumber from 'bignumber.js' import React, { useEffect, 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 Text from 'components/Text' import TokenInput from 'components/TokenInput' import { BN_ZERO } from 'constants/math' import useHealthComputer from 'hooks/useHealthComputer' import useMarketAssets from 'hooks/useMarketAssets' import usePrices from 'hooks/usePrices' import useStore from 'store' import { BNCoin } from 'types/classes/BNCoin' import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types' import { byDenom } from 'utils/array' import { findCoinByDenom, getAssetByDenom } from 'utils/assets' import { formatPercent } from 'utils/formatters' export interface VaultBorrowingsProps { borrowings: BNCoin[] deposits: BNCoin[] primaryAsset: Asset secondaryAsset: Asset vault: Vault depositActions: Action[] onChangeBorrowings: (borrowings: BNCoin[]) => void } export default function VaultBorrowings(props: VaultBorrowingsProps) { const { data: marketAssets } = useMarketAssets() const { data: prices } = usePrices() const baseCurrency = useStore((s) => s.baseCurrency) const vaultModal = useStore((s) => s.vaultModal) const depositIntoVault = useStore((s) => s.depositIntoVault) const [isConfirming, setIsConfirming] = useState(false) const updatedAccount = useStore((s) => s.updatedAccount) const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount) const maxBorrowAmounts: BNCoin[] = useMemo(() => { return props.borrowings.map((borrowing) => { const maxAmount = computeMaxBorrowAmount(borrowing.denom, { vault: { address: props.vault.address }, }) return new BNCoin({ denom: borrowing.denom, amount: maxAmount.toString(), }) }) }, [props.borrowings, computeMaxBorrowAmount, props.vault.address]) const borrowingValue = useMemo(() => { return props.borrowings.reduce((prev, curr) => { const price = prices.find((price) => price.denom === curr.denom)?.amount if (!price) return prev return prev.plus(curr.amount.multipliedBy(price)) }, BN_ZERO as BigNumber) }, [props.borrowings, prices]) const totalValue = useMemo(() => { const depositValue = props.deposits.reduce((prev, curr) => { const price = prices.find((price) => price.denom === curr.denom)?.amount if (!price) return prev const value = curr.amount.multipliedBy(price) return prev.plus(value) }, BN_ZERO as BigNumber) return depositValue.plus(borrowingValue) }, [props.deposits, borrowingValue, prices]) useEffect(() => { const selectedBorrowDenoms = vaultModal?.selectedBorrowDenoms || [] if ( props.borrowings.length === selectedBorrowDenoms.length && props.borrowings.every((coin) => selectedBorrowDenoms.includes(coin.denom)) ) { return } const updatedBorrowings = selectedBorrowDenoms.map((denom) => { const amount = findCoinByDenom(denom, props.borrowings)?.amount || BN_ZERO return new BNCoin({ denom, amount: amount.toString(), }) }) props.onChangeBorrowings(updatedBorrowings) }, [vaultModal, props]) const [percentage, setPercentage] = useState(0) function onChangeSlider(value: number) { if (props.borrowings.length !== 1) return const denom = props.borrowings[0].denom const currentAmount = props.borrowings[0].amount const maxAmount = maxBorrowAmounts.find((coin) => coin.denom === denom)?.amount ?? BN_ZERO const newBorrowings: BNCoin[] = [ new BNCoin({ denom, amount: ( maxAmount.plus(currentAmount).multipliedBy(value).dividedBy(100).decimalPlaces(0) || BN_ZERO ).toString(), }), ] props.onChangeBorrowings(newBorrowings) setPercentage(value) } function updateAssets(denom: string, amount: BigNumber) { const index = props.borrowings.findIndex((coin) => coin.denom === denom) props.borrowings[index].amount = amount props.onChangeBorrowings([...props.borrowings]) } function onDelete(denom: string) { const index = props.borrowings.findIndex((coin) => coin.denom === denom) props.borrowings.splice(index, 1) props.onChangeBorrowings([...props.borrowings]) if (!vaultModal) return useStore.setState({ vaultModal: { ...vaultModal, selectedBorrowDenoms: props.borrowings.map((coin) => coin.denom), }, }) } function addAsset() { useStore.setState({ addVaultBorrowingsModal: { selectedDenoms: props.borrowings.map((coin) => coin.denom), }, }) } async function onConfirm() { if (!updatedAccount) return setIsConfirming(true) const isSuccess = await depositIntoVault({ accountId: updatedAccount.id, actions: props.depositActions, }) setIsConfirming(false) if (isSuccess) { useStore.setState({ vaultModal: null }) } } return (
{props.borrowings.map((coin) => { const asset = getAssetByDenom(coin.denom) const maxAmount = maxBorrowAmounts.find(byDenom(coin.denom))?.amount if (!asset || !maxAmount) return return ( updateAssets(coin.denom, amount)} onDelete={() => onDelete(coin.denom)} disabled={isConfirming} /> ) })} {props.borrowings.length === 1 && ( )} {props.borrowings.length === 0 && (
You have no borrowing assets selected. Click on select borrow assets if you would like to add assets to borrow.
)}
) }