Mp 3260 finalize account summary (#395)
This commit is contained in:
parent
6d4c09981f
commit
2d146449ca
@ -11,6 +11,7 @@ import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import {
|
||||
calculateAccountApr,
|
||||
@ -20,7 +21,6 @@ import {
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
change?: AccountChange
|
||||
}
|
||||
|
||||
interface ItemProps {
|
||||
@ -33,7 +33,9 @@ interface ItemProps {
|
||||
}
|
||||
|
||||
export default function AccountComposition(props: Props) {
|
||||
const { account, change } = props
|
||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||
const { account } = props
|
||||
const hasChanged = !!updatedAccount
|
||||
const { data: prices } = usePrices()
|
||||
const { availableAssets: borrowAvailableAssets, accountBorrowedAssets } =
|
||||
useBorrowMarketAssetsTableData()
|
||||
@ -48,64 +50,74 @@ export default function AccountComposition(props: Props) {
|
||||
[lendingAvailableAssets, accountLentAssets],
|
||||
)
|
||||
|
||||
const [depositsBalance, lendsBalance, debtsBalance] = useMemo(
|
||||
const [depositsBalance, lendsBalance, debtsBalance, vaultsBalance] = useMemo(
|
||||
() => getAccountPositionValues(account, prices),
|
||||
[account, prices],
|
||||
)
|
||||
const [depositsBalanceChange, lendsBalanceChange, debtsBalanceChange] = useMemo(
|
||||
() => (change ? getAccountPositionValues(change, prices) : [BN_ZERO, BN_ZERO, BN_ZERO]),
|
||||
[change, prices],
|
||||
)
|
||||
const positionValue = depositsBalance.plus(lendsBalance).plus(vaultsBalance)
|
||||
|
||||
const [updatedPositionValue, updatedDebtsBalance] = useMemo(() => {
|
||||
const [updatedDepositsBalance, updatedLendsBalance, updatedDebtsBalance, updatedVaultsBalance] =
|
||||
updatedAccount
|
||||
? getAccountPositionValues(updatedAccount, prices)
|
||||
: [BN_ZERO, BN_ZERO, BN_ZERO]
|
||||
|
||||
const updatedPositionValue = updatedDepositsBalance
|
||||
.plus(updatedLendsBalance)
|
||||
.plus(updatedVaultsBalance)
|
||||
|
||||
return [updatedPositionValue, updatedDebtsBalance]
|
||||
}, [updatedAccount, prices])
|
||||
|
||||
const totalBalance = useMemo(
|
||||
() => calculateAccountBalanceValue(account, prices),
|
||||
[account, prices],
|
||||
)
|
||||
const totalBalanceChange = useMemo(
|
||||
() => (change ? calculateAccountBalanceValue(change, prices) : BN_ZERO),
|
||||
[change, prices],
|
||||
const updatedTotalBalance = useMemo(
|
||||
() => (updatedAccount ? calculateAccountBalanceValue(updatedAccount, prices) : BN_ZERO),
|
||||
[updatedAccount, prices],
|
||||
)
|
||||
const balance = depositsBalance.plus(lendsBalance)
|
||||
const balanceChange = depositsBalanceChange.plus(lendsBalanceChange)
|
||||
|
||||
const apr = useMemo(
|
||||
() => calculateAccountApr(account, totalBalance, borrowAssetsData, lendingAssetsData, prices),
|
||||
[account, totalBalance, borrowAssetsData, lendingAssetsData, prices],
|
||||
() => calculateAccountApr(account, borrowAssetsData, lendingAssetsData, prices),
|
||||
[account, borrowAssetsData, lendingAssetsData, prices],
|
||||
)
|
||||
const aprChange = useMemo(
|
||||
const updatedApr = useMemo(
|
||||
() =>
|
||||
change
|
||||
? calculateAccountApr(
|
||||
change,
|
||||
totalBalance.plus(totalBalanceChange),
|
||||
borrowAssetsData,
|
||||
lendingAssetsData,
|
||||
prices,
|
||||
)
|
||||
updatedAccount
|
||||
? calculateAccountApr(updatedAccount, borrowAssetsData, lendingAssetsData, prices)
|
||||
: BN_ZERO,
|
||||
[change, totalBalance, totalBalanceChange, borrowAssetsData, lendingAssetsData, prices],
|
||||
[updatedAccount, borrowAssetsData, lendingAssetsData, prices],
|
||||
)
|
||||
|
||||
return (
|
||||
<div className='flex-wrap w-full p-4 pb-1'>
|
||||
<Item
|
||||
title='Total Position Value'
|
||||
current={balance}
|
||||
change={balance.plus(balanceChange)}
|
||||
current={positionValue}
|
||||
change={hasChanged ? updatedPositionValue : positionValue}
|
||||
className='pb-3'
|
||||
/>
|
||||
<Item
|
||||
title='Total Debt'
|
||||
current={debtsBalance}
|
||||
change={debtsBalance.plus(debtsBalanceChange)}
|
||||
change={hasChanged ? updatedDebtsBalance : debtsBalance}
|
||||
className='pb-3'
|
||||
isDecrease
|
||||
/>
|
||||
<Item
|
||||
title='Total Balance'
|
||||
current={totalBalance}
|
||||
change={totalBalance.plus(totalBalanceChange)}
|
||||
change={hasChanged ? updatedTotalBalance : totalBalance}
|
||||
className='py-3 font-bold border border-transparent border-y-white/20'
|
||||
/>
|
||||
<Item title='APR' current={apr} change={apr.plus(aprChange)} className='py-3' isPercentage />
|
||||
<Item
|
||||
title='APR'
|
||||
current={apr}
|
||||
change={hasChanged ? updatedApr : apr}
|
||||
className='py-3'
|
||||
isPercentage
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -135,7 +147,7 @@ function Item(props: ItemProps) {
|
||||
className='text-sm'
|
||||
/>
|
||||
)}
|
||||
{!current.isEqualTo(change) && (
|
||||
{current.toFixed(2) !== change.toFixed(2) && (
|
||||
<>
|
||||
<span className={classNames('w-3', increase ? 'text-profit' : 'text-loss')}>
|
||||
<ArrowRight />
|
||||
|
@ -7,7 +7,7 @@ import Card from 'components/Card'
|
||||
import DisplayCurrency from 'components/DisplayCurrency'
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import { Gauge } from 'components/Gauge'
|
||||
import { ArrowRight, ChevronLeft, ChevronRight, Heart } from 'components/Icons'
|
||||
import { ChevronLeft, ChevronRight, Heart } from 'components/Icons'
|
||||
import Text from 'components/Text'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
@ -43,7 +43,6 @@ function AccountDetails(props: Props) {
|
||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||
const [isExpanded, setIsExpanded] = useToggle()
|
||||
const { health } = useHealthComputer(account)
|
||||
const { health: updatedHealth } = useHealthComputer(updatedAccount)
|
||||
const { data: prices } = usePrices()
|
||||
const accountBalanceValue = useMemo(
|
||||
() => calculateAccountBalanceValue(updatedAccount ? updatedAccount : account, prices),
|
||||
@ -67,15 +66,8 @@ function AccountDetails(props: Props) {
|
||||
[lendingAvailableAssets, accountLentAssets],
|
||||
)
|
||||
const apr = useMemo(
|
||||
() =>
|
||||
calculateAccountApr(
|
||||
account,
|
||||
accountBalanceValue,
|
||||
borrowAssetsData,
|
||||
lendingAssetsData,
|
||||
prices,
|
||||
),
|
||||
[account, accountBalanceValue, borrowAssetsData, lendingAssetsData, prices],
|
||||
() => calculateAccountApr(account, borrowAssetsData, lendingAssetsData, prices),
|
||||
[account, borrowAssetsData, lendingAssetsData, prices],
|
||||
)
|
||||
return (
|
||||
<div
|
||||
@ -116,34 +108,18 @@ function AccountDetails(props: Props) {
|
||||
options={{ maxDecimals: 0, minDecimals: 0, suffix: '%' }}
|
||||
animate
|
||||
/>
|
||||
{updatedHealth > 0 && health !== updatedHealth && (
|
||||
<>
|
||||
<ArrowRight
|
||||
width={16}
|
||||
className={classNames(health > updatedHealth ? 'text-loss' : 'text-success')}
|
||||
/>
|
||||
<FormattedNumber
|
||||
className={'w-full text-center text-xs'}
|
||||
amount={updatedHealth}
|
||||
options={{ maxDecimals: 0, minDecimals: 0, suffix: '%' }}
|
||||
animate
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className='w-full py-4 border-t border-white/20'>
|
||||
<Text size='2xs' className='mb-0.5 w-full text-center text-white/50'>
|
||||
Leverage
|
||||
</Text>
|
||||
<Text size='2xs' className='text-center'>
|
||||
<FormattedNumber
|
||||
className={'w-full text-center text-2xs'}
|
||||
amount={leverage.toNumber()}
|
||||
options={{ maxDecimals: 2, minDecimals: 2, suffix: 'x' }}
|
||||
animate
|
||||
/>
|
||||
</Text>
|
||||
<FormattedNumber
|
||||
className={'w-full text-center text-2xs'}
|
||||
amount={leverage.toNumber()}
|
||||
options={{ maxDecimals: 2, minDecimals: 2, suffix: 'x' }}
|
||||
animate
|
||||
/>
|
||||
</div>
|
||||
<div className='w-full py-4 border-t border-white/20'>
|
||||
<Text size='2xs' className='mb-0.5 w-full text-center text-white/50'>
|
||||
@ -163,7 +139,7 @@ function AccountDetails(props: Props) {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex w-80'>
|
||||
<div className='flex w-80 backdrop-blur-sticky'>
|
||||
<Card className='w-full bg-white/5' title={`Account ${account.id}`}>
|
||||
<AccountComposition account={account} />
|
||||
<Text className='w-full px-4 py-2 bg-white/10 text-white/40'>Balances</Text>
|
||||
|
@ -18,6 +18,7 @@ import { getPage, getRoute } from 'utils/route'
|
||||
|
||||
interface Props {
|
||||
accounts: Account[]
|
||||
setShowMenu: (show: boolean) => void
|
||||
}
|
||||
|
||||
const accountCardHeaderClasses = classNames(
|
||||
@ -27,6 +28,7 @@ const accountCardHeaderClasses = classNames(
|
||||
)
|
||||
|
||||
export default function AccountList(props: Props) {
|
||||
const { accounts, setShowMenu } = props
|
||||
const navigate = useNavigate()
|
||||
const { pathname } = useLocation()
|
||||
const { address } = useParams()
|
||||
@ -47,11 +49,11 @@ export default function AccountList(props: Props) {
|
||||
}
|
||||
}, [accountId])
|
||||
|
||||
if (!props.accounts?.length) return null
|
||||
if (!accounts?.length) return null
|
||||
|
||||
return (
|
||||
<div className='flex flex-wrap w-full p-4'>
|
||||
{props.accounts.map((account) => {
|
||||
{accounts.map((account) => {
|
||||
const positionBalance = calculateAccountBalanceValue(account, prices)
|
||||
const isActive = accountId === account.id
|
||||
|
||||
@ -88,6 +90,7 @@ export default function AccountList(props: Props) {
|
||||
color='tertiary'
|
||||
leftIcon={<ArrowUpLine />}
|
||||
onClick={() => {
|
||||
setShowMenu(false)
|
||||
if (positionBalance.isLessThanOrEqualTo(0)) {
|
||||
useStore.setState({
|
||||
focusComponent: {
|
||||
@ -108,6 +111,7 @@ export default function AccountList(props: Props) {
|
||||
leftIcon={<ArrowDownLine />}
|
||||
text='Withdraw'
|
||||
onClick={() => {
|
||||
setShowMenu(false)
|
||||
useStore.setState({ fundAndWithdrawModal: 'withdraw' })
|
||||
}}
|
||||
disabled={positionBalance.isLessThanOrEqualTo(0)}
|
||||
@ -117,7 +121,10 @@ export default function AccountList(props: Props) {
|
||||
color='tertiary'
|
||||
leftIcon={<TrashBin />}
|
||||
text='Delete'
|
||||
onClick={() => deleteAccountHandler()}
|
||||
onClick={() => {
|
||||
setShowMenu(false)
|
||||
deleteAccountHandler()
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
className='w-full'
|
||||
|
@ -138,7 +138,9 @@ export default function AccountMenuContent(props: Props) {
|
||||
<CircularProgress size={40} />
|
||||
</div>
|
||||
)}
|
||||
{hasCreditAccounts && !isLoadingAccount && <AccountList accounts={props.accounts} />}
|
||||
{hasCreditAccounts && !isLoadingAccount && (
|
||||
<AccountList accounts={props.accounts} setShowMenu={setShowMenu} />
|
||||
)}
|
||||
</div>
|
||||
</Overlay>
|
||||
</div>
|
||||
|
@ -36,15 +36,8 @@ export default function AccountStats(props: Props) {
|
||||
[lendingAvailableAssets, accountLentAssets],
|
||||
)
|
||||
const apr = useMemo(
|
||||
() =>
|
||||
calculateAccountApr(
|
||||
props.account,
|
||||
positionBalance,
|
||||
borrowAssetsData,
|
||||
lendingAssetsData,
|
||||
prices,
|
||||
),
|
||||
[props.account, positionBalance, borrowAssetsData, lendingAssetsData, prices],
|
||||
() => calculateAccountApr(props.account, borrowAssetsData, lendingAssetsData, prices),
|
||||
[props.account, borrowAssetsData, lendingAssetsData, prices],
|
||||
)
|
||||
return (
|
||||
<div className='flex-wrap w-full'>
|
||||
|
@ -19,8 +19,7 @@ import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { calculateAccountBalanceValue, calculateAccountLeverage } from 'utils/accounts'
|
||||
|
||||
interface Props {
|
||||
account?: Account
|
||||
change?: AccountChange
|
||||
account: Account
|
||||
}
|
||||
|
||||
export default function AccountSummary(props: Props) {
|
||||
@ -42,7 +41,6 @@ export default function AccountSummary(props: Props) {
|
||||
() => [...lendingAvailableAssets, ...accountLentAssets],
|
||||
[lendingAvailableAssets, accountLentAssets],
|
||||
)
|
||||
|
||||
const { health } = useHealthComputer(props.account)
|
||||
const leverage = useMemo(
|
||||
() => (props.account ? calculateAccountLeverage(props.account, prices) : BN_ZERO),
|
||||
@ -76,9 +74,7 @@ export default function AccountSummary(props: Props) {
|
||||
{
|
||||
title: `Subaccount ${props.account.id} Composition`,
|
||||
renderContent: () =>
|
||||
props.account ? (
|
||||
<AccountComposition account={props.account} change={props.change} />
|
||||
) : null,
|
||||
props.account ? <AccountComposition account={props.account} /> : null,
|
||||
isOpen: isOpen[0],
|
||||
toggleOpen: (index: number) => toggleOpen(index),
|
||||
renderSubTitle: () => <></>,
|
||||
|
@ -1,10 +1,10 @@
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import AccountSummary from 'components/Account/AccountSummary'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
|
||||
function CurrentAccountSummary({ change }: { change?: AccountChange }) {
|
||||
function CurrentAccountSummary() {
|
||||
const account = useCurrentAccount()
|
||||
|
||||
return <AccountSummary account={account} change={change} />
|
||||
if (!account) return
|
||||
return <AccountSummary account={account} />
|
||||
}
|
||||
|
||||
export default CurrentAccountSummary
|
||||
|
@ -20,7 +20,6 @@ interface Props {
|
||||
actionButtonText: string
|
||||
contentHeader?: JSX.Element
|
||||
showProgressIndicator: boolean
|
||||
accountSummaryChange?: AccountChange
|
||||
onClose: () => void
|
||||
onChange: (value: BigNumber) => void
|
||||
onAction: (value: BigNumber, isMax: boolean) => void
|
||||
@ -32,7 +31,6 @@ export default function AssetAmountSelectActionModal(props: Props) {
|
||||
title,
|
||||
coinBalances,
|
||||
actionButtonText,
|
||||
accountSummaryChange,
|
||||
contentHeader = null,
|
||||
showProgressIndicator,
|
||||
onClose,
|
||||
@ -67,9 +65,9 @@ export default function AssetAmountSelectActionModal(props: Props) {
|
||||
contentClassName='flex flex-col min-h-[400px]'
|
||||
>
|
||||
{contentHeader}
|
||||
<div className='flex flex-1 items-start gap-6 p-6'>
|
||||
<div className='flex items-start flex-1 gap-6 p-6'>
|
||||
<Card
|
||||
className='flex flex-1 bg-white/5 p-4'
|
||||
className='flex flex-1 p-4 bg-white/5'
|
||||
contentClassName='gap-6 flex flex-col justify-between h-full'
|
||||
>
|
||||
<TokenInputWithSlider
|
||||
@ -91,7 +89,7 @@ export default function AssetAmountSelectActionModal(props: Props) {
|
||||
rightIcon={<ArrowRight />}
|
||||
/>
|
||||
</Card>
|
||||
<CurrentAccountSummary change={accountSummaryChange} />
|
||||
<CurrentAccountSummary />
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
|
@ -1,5 +1,5 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
import AccountSummary from 'components/Account/AccountSummary'
|
||||
import AssetImage from 'components/AssetImage'
|
||||
@ -12,11 +12,13 @@ import Switch from 'components/Switch'
|
||||
import Text from 'components/Text'
|
||||
import TitleAndSubCell from 'components/TitleAndSubCell'
|
||||
import TokenInputWithSlider from 'components/TokenInput/TokenInputWithSlider'
|
||||
import { ASSETS } from 'constants/assets'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useAutoLendEnabledAccountIds from 'hooks/useAutoLendEnabledAccountIds'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import useToggle from 'hooks/useToggle'
|
||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||
import { getDepositsAndLendsAfterCoinSpent } from 'hooks/useUpdatedAccount/functions'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { formatPercent, formatValue } from 'utils/formatters'
|
||||
@ -51,15 +53,17 @@ function BorrowModal(props: Props) {
|
||||
const { modal, account } = props
|
||||
const [percentage, setPercentage] = useState(0)
|
||||
const [amount, setAmount] = useState(BN_ZERO)
|
||||
const [change, setChange] = useState<AccountChange | undefined>()
|
||||
const [isConfirming, setIsConfirming] = useToggle()
|
||||
const [borrowToWallet, setBorrowToWallet] = useToggle()
|
||||
const borrow = useStore((s) => s.borrow)
|
||||
const repay = useStore((s) => s.repay)
|
||||
const asset = modal.asset ?? ASSETS[0]
|
||||
const asset = modal.asset
|
||||
const isRepay = modal.isRepay ?? false
|
||||
const [max, setMax] = useState(BN_ZERO)
|
||||
const { simulateBorrow, simulateRepay } = useUpdatedAccount(account)
|
||||
|
||||
const { autoLendEnabledAccountIds } = useAutoLendEnabledAccountIds()
|
||||
const isAutoLendEnabled = autoLendEnabledAccountIds.includes(account.id)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(account)
|
||||
|
||||
function resetState() {
|
||||
@ -69,19 +73,24 @@ function BorrowModal(props: Props) {
|
||||
}
|
||||
|
||||
async function onConfirmClick() {
|
||||
if (!modal.asset) return
|
||||
if (!asset) return
|
||||
setIsConfirming(true)
|
||||
let result
|
||||
const { lends } = getDepositsAndLendsAfterCoinSpent(
|
||||
BNCoin.fromDenomAndBigNumber(asset.denom, amount),
|
||||
account,
|
||||
)
|
||||
if (isRepay) {
|
||||
result = await repay({
|
||||
accountId: account.id,
|
||||
coin: BNCoin.fromDenomAndBigNumber(modal.asset.denom, amount),
|
||||
coin: BNCoin.fromDenomAndBigNumber(asset.denom, amount),
|
||||
accountBalance: percentage === 100,
|
||||
lends,
|
||||
})
|
||||
} else {
|
||||
result = await borrow({
|
||||
accountId: account.id,
|
||||
coin: { denom: modal.asset.denom, amount: amount.toString() },
|
||||
coin: { denom: asset.denom, amount: amount.toString() },
|
||||
borrowToWallet,
|
||||
})
|
||||
}
|
||||
@ -108,6 +117,15 @@ function BorrowModal(props: Props) {
|
||||
decimals: 6,
|
||||
})
|
||||
|
||||
const handleChange = useCallback(
|
||||
(newAmount: BigNumber) => {
|
||||
const coin = BNCoin.fromDenomAndBigNumber(asset.denom, newAmount)
|
||||
if (!amount.isEqualTo(newAmount)) setAmount(newAmount)
|
||||
if (isRepay) simulateRepay(coin)
|
||||
},
|
||||
[asset, amount, isRepay, simulateRepay],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (isRepay) {
|
||||
setMax(BN(getDebtAmount(modal)))
|
||||
@ -123,25 +141,20 @@ function BorrowModal(props: Props) {
|
||||
}, [isRepay, modal, asset.denom, computeMaxBorrowAmount, borrowToWallet])
|
||||
|
||||
useEffect(() => {
|
||||
if (!modal.asset) return
|
||||
if (amount.isGreaterThan(max)) {
|
||||
handleChange(max)
|
||||
setAmount(max)
|
||||
}
|
||||
}, [amount, max, handleChange])
|
||||
|
||||
setChange({
|
||||
deposits: [
|
||||
{
|
||||
amount: isRepay ? BN_ZERO.minus(amount).toString() : BN_ZERO.plus(amount).toString(),
|
||||
denom: modal.asset.denom,
|
||||
},
|
||||
],
|
||||
debts: [
|
||||
{
|
||||
amount: isRepay ? BN_ZERO.minus(amount).toString() : BN_ZERO.plus(amount).toString(),
|
||||
denom: modal.asset.denom,
|
||||
},
|
||||
],
|
||||
})
|
||||
}, [amount, modal.asset, account, isRepay])
|
||||
useEffect(() => {
|
||||
if (isRepay) return
|
||||
const coin = BNCoin.fromDenomAndBigNumber(asset.denom, amount.isGreaterThan(max) ? max : amount)
|
||||
const target = borrowToWallet ? 'wallet' : isAutoLendEnabled ? 'lend' : 'deposit'
|
||||
simulateBorrow(target, coin)
|
||||
}, [isRepay, borrowToWallet, isAutoLendEnabled, simulateBorrow, asset, amount, max])
|
||||
|
||||
if (!modal) return null
|
||||
if (!modal || !asset) return null
|
||||
return (
|
||||
<Modal
|
||||
onClose={onClose}
|
||||
@ -183,7 +196,7 @@ function BorrowModal(props: Props) {
|
||||
<div className='flex flex-wrap w-full'>
|
||||
<TokenInputWithSlider
|
||||
asset={asset}
|
||||
onChange={setAmount}
|
||||
onChange={handleChange}
|
||||
amount={amount}
|
||||
max={max}
|
||||
className='w-full'
|
||||
@ -219,7 +232,7 @@ function BorrowModal(props: Props) {
|
||||
rightIcon={<ArrowRight />}
|
||||
/>
|
||||
</Card>
|
||||
<AccountSummary account={account} change={change} />
|
||||
<AccountSummary account={account} />
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
|
@ -9,6 +9,7 @@ import WalletBridges from 'components/Wallet/WalletBridges'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useAutoLendEnabledAccountIds from 'hooks/useAutoLendEnabledAccountIds'
|
||||
import useToggle from 'hooks/useToggle'
|
||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||
import useWalletBalances from 'hooks/useWalletBalances'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
@ -19,11 +20,10 @@ import { BN } from 'utils/helpers'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
setChange: (change: AccountChange | undefined) => void
|
||||
}
|
||||
|
||||
export default function FundAccount(props: Props) {
|
||||
const { account, setChange } = props
|
||||
const { account } = props
|
||||
const accountId = account.id
|
||||
const address = useStore((s) => s.address)
|
||||
const deposit = useStore((s) => s.deposit)
|
||||
@ -37,6 +37,7 @@ export default function FundAccount(props: Props) {
|
||||
fundingAssets.length > 0 && fundingAssets.every((a) => a.toCoin().amount !== '0')
|
||||
const { autoLendEnabledAccountIds } = useAutoLendEnabledAccountIds()
|
||||
const isAutoLendEnabled = autoLendEnabledAccountIds.includes(accountId)
|
||||
const { simulateDeposits } = useUpdatedAccount(account)
|
||||
|
||||
const baseBalance = useMemo(
|
||||
() => walletBalances.find(byDenom(baseAsset.denom))?.amount ?? '0',
|
||||
@ -86,21 +87,18 @@ export default function FundAccount(props: Props) {
|
||||
|
||||
const updateFundingAssets = useCallback(
|
||||
(amount: BigNumber, denom: string) => {
|
||||
setFundingAssets((prevAssets) => {
|
||||
const assetToUpdateIdx = prevAssets.findIndex(byDenom(denom))
|
||||
if (assetToUpdateIdx > -1) {
|
||||
prevAssets[assetToUpdateIdx].amount = amount
|
||||
}
|
||||
setChange({ [isAutoLendEnabled ? 'lends' : 'deposits']: prevAssets })
|
||||
return prevAssets
|
||||
})
|
||||
const assetToUpdate = fundingAssets.find(byDenom(denom))
|
||||
if (assetToUpdate) {
|
||||
assetToUpdate.amount = amount
|
||||
setFundingAssets([...fundingAssets.filter((a) => a.denom !== denom), assetToUpdate])
|
||||
}
|
||||
},
|
||||
[setChange, isAutoLendEnabled],
|
||||
[fundingAssets],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setChange({ [isAutoLendEnabled ? 'lends' : 'deposits']: fundingAssets })
|
||||
}, [isAutoLendEnabled, fundingAssets, setChange])
|
||||
simulateDeposits(isAutoLendEnabled ? 'lend' : 'deposit', fundingAssets)
|
||||
}, [isAutoLendEnabled, fundingAssets, simulateDeposits])
|
||||
|
||||
useEffect(() => {
|
||||
if (BN(baseBalance).isLessThan(defaultFee.amount[0].amount)) {
|
||||
|
@ -4,6 +4,7 @@ import AccountSummary from 'components/Account/AccountSummary'
|
||||
import Card from 'components/Card'
|
||||
import FundAccount from 'components/Modals/FundWithdraw/FundAccount'
|
||||
import WithdrawFromAccount from 'components/Modals/FundWithdraw/WithdrawFromAccount'
|
||||
import useStore from 'store'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
@ -12,21 +13,15 @@ interface Props {
|
||||
|
||||
export default function FundWithdrawModalContent(props: Props) {
|
||||
const { account, isFunding } = props
|
||||
const [change, setChange] = useState<AccountChange | undefined>()
|
||||
|
||||
return (
|
||||
<div className='flex items-start flex-1 gap-6 p-6'>
|
||||
<Card
|
||||
className='flex flex-1 p-4 bg-white/5'
|
||||
contentClassName='gap-6 flex flex-col justify-between h-full min-h-[380px]'
|
||||
>
|
||||
{isFunding ? (
|
||||
<FundAccount account={account} setChange={setChange} />
|
||||
) : (
|
||||
<WithdrawFromAccount account={account} setChange={setChange} />
|
||||
)}
|
||||
{isFunding ? <FundAccount account={account} /> : <WithdrawFromAccount account={account} />}
|
||||
</Card>
|
||||
<AccountSummary account={account} change={change} />
|
||||
<AccountSummary account={account} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useState } from 'react'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import Divider from 'components/Divider'
|
||||
@ -18,18 +18,19 @@ import { byDenom } from 'utils/array'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
setChange: (change: AccountChange | undefined) => void
|
||||
}
|
||||
|
||||
export default function WithdrawFromAccount(props: Props) {
|
||||
const { account, setChange } = props
|
||||
const defaultAsset = ASSETS.find(byDenom(account.deposits[0].denom)) ?? ASSETS[0]
|
||||
const { account } = props
|
||||
const defaultAsset =
|
||||
ASSETS.find(byDenom(account.deposits[0]?.denom || account.lends[0]?.denom)) ?? ASSETS[0]
|
||||
const withdraw = useStore((s) => s.withdraw)
|
||||
const [withdrawWithBorrowing, setWithdrawWithBorrowing] = useToggle()
|
||||
const [isConfirming, setIsConfirming] = useToggle()
|
||||
const [currentAsset, setCurrentAsset] = useState(defaultAsset)
|
||||
const [amount, setAmount] = useState(BN_ZERO)
|
||||
const { updatedAccount, removeDepositByDenom } = useUpdatedAccount(account)
|
||||
const { updatedAccount, removeDepositAndLendsByDenom, removeDeposits, addDebts } =
|
||||
useUpdatedAccount(account)
|
||||
const { computeMaxWithdrawAmount } = useHealthComputer(account)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount)
|
||||
const maxWithdrawAmount = computeMaxWithdrawAmount(currentAsset.denom)
|
||||
@ -37,27 +38,19 @@ export default function WithdrawFromAccount(props: Props) {
|
||||
maxWithdrawAmount,
|
||||
)
|
||||
const isWithinBalance = amount.isLessThan(maxWithdrawAmount)
|
||||
const depositAmount = BN_ZERO.minus(isWithinBalance ? amount : maxWithdrawAmount)
|
||||
const withdrawAmount = isWithinBalance ? amount : maxWithdrawAmount
|
||||
const debtAmount = isWithinBalance ? BN_ZERO : amount.minus(maxWithdrawAmount)
|
||||
const max = withdrawWithBorrowing ? maxWithdrawWithBorrowAmount : maxWithdrawAmount
|
||||
|
||||
function onChangeAmount(val: BigNumber) {
|
||||
setAmount(val)
|
||||
setChange({
|
||||
deposits: [
|
||||
{
|
||||
amount: depositAmount.toString(),
|
||||
denom: currentAsset.denom,
|
||||
},
|
||||
],
|
||||
debts: [{ amount: debtAmount.toString(), denom: currentAsset.denom }],
|
||||
})
|
||||
removeDeposits([BNCoin.fromDenomAndBigNumber(currentAsset.denom, withdrawAmount)])
|
||||
addDebts([BNCoin.fromDenomAndBigNumber(currentAsset.denom, debtAmount)])
|
||||
}
|
||||
|
||||
function resetState() {
|
||||
setCurrentAsset(defaultAsset)
|
||||
setAmount(BN_ZERO)
|
||||
setChange(undefined)
|
||||
}
|
||||
|
||||
async function onConfirm() {
|
||||
@ -77,13 +70,9 @@ export default function WithdrawFromAccount(props: Props) {
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
removeDepositByDenom(currentAsset.denom)
|
||||
}, [currentAsset.denom, removeDepositByDenom])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='flex w-full flex-wrap'>
|
||||
<div className='flex flex-wrap w-full'>
|
||||
<TokenInputWithSlider
|
||||
asset={currentAsset}
|
||||
onChange={onChangeAmount}
|
||||
@ -98,9 +87,9 @@ export default function WithdrawFromAccount(props: Props) {
|
||||
disabled={isConfirming}
|
||||
/>
|
||||
<Divider className='my-6' />
|
||||
<div className='flex w-full flex-wrap'>
|
||||
<div className='flex flex-1 flex-wrap'>
|
||||
<Text className='mb-1 w-full'>Withdraw with borrowing</Text>
|
||||
<div className='flex flex-wrap w-full'>
|
||||
<div className='flex flex-wrap flex-1'>
|
||||
<Text className='w-full mb-1'>Withdraw with borrowing</Text>
|
||||
<Text size='xs' className='text-white/50'>
|
||||
Borrow assets from your credit account to withdraw to your wallet
|
||||
</Text>
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
import useStore from 'store'
|
||||
import useToggle from 'hooks/useToggle'
|
||||
import AssetAmountSelectActionModal from 'components/Modals/AssetAmountSelectActionModal'
|
||||
import DetailsHeader from 'components/Modals/LendAndReclaim/DetailsHeader'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import useLendAndReclaimModal from 'hooks/useLendAndReclaimModal'
|
||||
import DetailsHeader from 'components/Modals/LendAndReclaim/DetailsHeader'
|
||||
import AssetAmountSelectActionModal from 'components/Modals/AssetAmountSelectActionModal'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import useToggle from 'hooks/useToggle'
|
||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
||||
function LendAndReclaimModalController() {
|
||||
const currentAccount = useCurrentAccount()
|
||||
@ -28,9 +28,7 @@ function LendAndReclaimModal({ currentAccount, config }: Props) {
|
||||
const reclaim = useStore((s) => s.reclaim)
|
||||
const { close } = useLendAndReclaimModal()
|
||||
const [isConfirming, setIsConfirming] = useToggle()
|
||||
const [accountChange, setAccountChange] = useState<AccountChange | undefined>()
|
||||
const { setAddedLends, setRemovedLends, removeDeposits, addDeposits } =
|
||||
useUpdatedAccount(currentAccount)
|
||||
const { simulateLending } = useUpdatedAccount(currentAccount)
|
||||
|
||||
const { data, action } = config
|
||||
const { asset } = data
|
||||
@ -41,18 +39,10 @@ function LendAndReclaimModal({ currentAccount, config }: Props) {
|
||||
|
||||
const handleAmountChange = useCallback(
|
||||
(value: BigNumber) => {
|
||||
setAccountChange(getAccountChange(isLendAction, value, asset.denom))
|
||||
|
||||
const coin = BNCoin.fromDenomAndBigNumber(asset.denom, value)
|
||||
if (isLendAction) {
|
||||
setAddedLends([coin])
|
||||
removeDeposits([coin])
|
||||
} else {
|
||||
addDeposits([coin])
|
||||
setRemovedLends([coin])
|
||||
}
|
||||
simulateLending(isLendAction, coin)
|
||||
},
|
||||
[addDeposits, asset.denom, isLendAction, removeDeposits, setAddedLends, setRemovedLends],
|
||||
[asset.denom, isLendAction, simulateLending],
|
||||
)
|
||||
|
||||
const handleAction = useCallback(
|
||||
@ -80,7 +70,6 @@ function LendAndReclaimModal({ currentAccount, config }: Props) {
|
||||
coinBalances={coinBalances}
|
||||
actionButtonText={actionText}
|
||||
showProgressIndicator={isConfirming}
|
||||
accountSummaryChange={accountChange}
|
||||
title={`${actionText} ${asset.symbol}`}
|
||||
onClose={close}
|
||||
onAction={handleAction}
|
||||
@ -89,18 +78,4 @@ function LendAndReclaimModal({ currentAccount, config }: Props) {
|
||||
)
|
||||
}
|
||||
|
||||
const getAccountChange = (isLend: boolean, value: BigNumber, denom: string): AccountChange => {
|
||||
const makeCoin = (denom: string, shouldNegate: boolean) => [
|
||||
{
|
||||
amount: (shouldNegate ? value.negated() : value).toString(),
|
||||
denom,
|
||||
},
|
||||
]
|
||||
|
||||
return {
|
||||
deposits: makeCoin(denom, isLend),
|
||||
lends: makeCoin(denom, !isLend),
|
||||
}
|
||||
}
|
||||
|
||||
export default LendAndReclaimModalController
|
||||
|
@ -20,7 +20,6 @@ import { findCoinByDenom, getAssetByDenom } from 'utils/assets'
|
||||
import { formatPercent } from 'utils/formatters'
|
||||
|
||||
export interface VaultBorrowingsProps {
|
||||
updatedAccount: Account
|
||||
borrowings: BNCoin[]
|
||||
deposits: BNCoin[]
|
||||
primaryAsset: Asset
|
||||
@ -37,7 +36,8 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
||||
const vaultModal = useStore((s) => s.vaultModal)
|
||||
const depositIntoVault = useStore((s) => s.depositIntoVault)
|
||||
const [isConfirming, setIsConfirming] = useState(false)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(props.updatedAccount)
|
||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount)
|
||||
|
||||
const maxBorrowAmounts: BNCoin[] = useMemo(() => {
|
||||
return props.borrowings.map((borrowing) => {
|
||||
@ -141,9 +141,10 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
||||
}
|
||||
|
||||
async function onConfirm() {
|
||||
if (!updatedAccount) return
|
||||
setIsConfirming(true)
|
||||
const isSuccess = await depositIntoVault({
|
||||
accountId: props.updatedAccount.id,
|
||||
accountId: updatedAccount.id,
|
||||
actions: props.depositActions,
|
||||
})
|
||||
setIsConfirming(false)
|
||||
|
@ -10,8 +10,8 @@ import { BN_ZERO } from 'constants/math'
|
||||
import useDepositVault from 'hooks/broadcast/useDepositVault'
|
||||
import useIsOpenArray from 'hooks/useIsOpenArray'
|
||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
|
||||
interface Props {
|
||||
vault: Vault | DepositedVault
|
||||
@ -23,12 +23,12 @@ interface Props {
|
||||
|
||||
export default function VaultModalContent(props: Props) {
|
||||
const {
|
||||
addDebt,
|
||||
addDebts,
|
||||
removeDeposits,
|
||||
addedDebt,
|
||||
addedDebts,
|
||||
removedDeposits,
|
||||
removedLends,
|
||||
setRemovedLends,
|
||||
removeLends,
|
||||
updatedAccount,
|
||||
addVaultValues,
|
||||
} = useUpdatedAccount(props.account)
|
||||
@ -41,7 +41,7 @@ export default function VaultModalContent(props: Props) {
|
||||
vault: props.vault,
|
||||
reclaims: removedLends,
|
||||
deposits: removedDeposits,
|
||||
borrowings: addedDebt,
|
||||
borrowings: addedDebts,
|
||||
})
|
||||
|
||||
const handleDepositSelect = useCallback(
|
||||
@ -67,11 +67,11 @@ export default function VaultModalContent(props: Props) {
|
||||
}
|
||||
})
|
||||
|
||||
setRemovedLends(reclaims)
|
||||
removeLends(reclaims)
|
||||
removeDeposits(deposits)
|
||||
setSelectedCoins(selectedCoins)
|
||||
},
|
||||
[props.account.deposits, removeDeposits, setRemovedLends],
|
||||
[props.account.deposits, removeDeposits, removeLends],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
@ -115,11 +115,11 @@ export default function VaultModalContent(props: Props) {
|
||||
|
||||
if (isOpen[1]) return null
|
||||
|
||||
return <VaultBorrowingsSubTitle borrowings={addedDebt} />
|
||||
return <VaultBorrowingsSubTitle borrowings={addedDebts} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex flex-1 items-start gap-6 p-6'>
|
||||
<div className='flex items-start flex-1 gap-6 p-6'>
|
||||
<Accordion
|
||||
className='h-[546px] overflow-y-scroll scrollbar-hide'
|
||||
items={[
|
||||
@ -144,12 +144,11 @@ export default function VaultModalContent(props: Props) {
|
||||
{
|
||||
renderContent: () => (
|
||||
<VaultBorrowings
|
||||
updatedAccount={updatedAccount || props.account}
|
||||
borrowings={addedDebt}
|
||||
borrowings={addedDebts}
|
||||
deposits={removedDeposits}
|
||||
primaryAsset={props.primaryAsset}
|
||||
secondaryAsset={props.secondaryAsset}
|
||||
onChangeBorrowings={addDebt}
|
||||
onChangeBorrowings={addDebts}
|
||||
vault={props.vault}
|
||||
depositActions={depositActions}
|
||||
/>
|
||||
|
@ -47,7 +47,7 @@ export default function SwapForm(props: Props) {
|
||||
const [estimatedFee, setEstimatedFee] = useState(defaultFee)
|
||||
|
||||
const throttledEstimateExactIn = useMemo(() => asyncThrottle(estimateExactIn, 250), [])
|
||||
const { removeDeposits, addDeposits, addDebt } = useUpdatedAccount(account)
|
||||
const { removeDeposits, addDeposits, addDebts } = useUpdatedAccount(account)
|
||||
|
||||
const borrowAsset = useMemo(
|
||||
() => borrowAssets.find(byDenom(sellAsset.denom)),
|
||||
@ -163,9 +163,9 @@ export default function SwapForm(props: Props) {
|
||||
debounce((removeCoin: BNCoin, addCoin: BNCoin, debtCoin: BNCoin) => {
|
||||
removeDeposits([removeCoin])
|
||||
addDeposits([addCoin])
|
||||
if (debtCoin.amount.isGreaterThan(BN_ZERO)) addDebt([debtCoin])
|
||||
if (debtCoin.amount.isGreaterThan(BN_ZERO)) addDebts([debtCoin])
|
||||
}, 1000),
|
||||
[removeDeposits, addDeposits, addDebt],
|
||||
[removeDeposits, addDeposits, addDebts],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
@ -173,8 +173,8 @@ export default function SwapForm(props: Props) {
|
||||
setSellAssetAmount(BN_ZERO)
|
||||
removeDeposits([])
|
||||
addDeposits([])
|
||||
addDebt([])
|
||||
}, [buyAsset.denom, sellAsset.denom, removeDeposits, addDeposits, addDebt])
|
||||
addDebts([])
|
||||
}, [buyAsset.denom, sellAsset.denom, removeDeposits, addDeposits, addDebts])
|
||||
|
||||
useEffect(() => {
|
||||
const removeDepositAmount = sellAssetAmount.isGreaterThanOrEqualTo(sellSideMarginThreshold)
|
||||
|
@ -1,13 +1,21 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useAssetParams from 'hooks/useAssetParams'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useVaultConfigs from 'hooks/useVaultConfigs'
|
||||
import useStore from 'store'
|
||||
import {
|
||||
Positions,
|
||||
VaultPositionValue,
|
||||
} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
import { VaultConfigBaseForString } from 'types/generated/mars-params/MarsParams.types'
|
||||
import {
|
||||
AssetParamsBaseForAddr,
|
||||
HealthComputer,
|
||||
} from 'types/generated/mars-rover-health-computer/MarsRoverHealthComputer.types'
|
||||
import { VaultConfigBaseForString } from 'types/generated/mars-params/MarsParams.types'
|
||||
import useVaultConfigs from 'hooks/useVaultConfigs'
|
||||
import { convertAccountToPositions } from 'utils/accounts'
|
||||
import { HEALTH_BUFFER } from 'utils/constants'
|
||||
import {
|
||||
BorrowTarget,
|
||||
compute_health_js,
|
||||
@ -16,15 +24,7 @@ import {
|
||||
max_withdraw_estimate_js,
|
||||
SwapKind,
|
||||
} from 'utils/health_computer'
|
||||
import { convertAccountToPositions } from 'utils/accounts'
|
||||
import {
|
||||
Positions,
|
||||
VaultPositionValue,
|
||||
} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
import useStore from 'store'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import { BN } from 'utils/helpers'
|
||||
import { HEALTH_BUFFER } from 'utils/constants'
|
||||
|
||||
export default function useHealthComputer(account?: Account) {
|
||||
const { data: prices } = usePrices()
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { BN } from 'utils/helpers'
|
||||
import { VaultValue } from 'hooks/useUpdatedAccount'
|
||||
import { getVaultMetaData } from 'utils/vaults'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import { MOCK_DEPOSITED_VAULT_POSITION } from 'constants/vaults'
|
||||
import { VaultValue } from 'hooks/useUpdatedAccount'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { BN } from 'utils/helpers'
|
||||
import { getVaultMetaData } from 'utils/vaults'
|
||||
|
||||
export function addCoins(additionalCoins: BNCoin[], currentCoins: BNCoin[]) {
|
||||
const currentDenoms = currentCoins.map((coin) => coin.denom)
|
||||
@ -67,3 +69,26 @@ export function addValueToVaults(
|
||||
|
||||
return vaults
|
||||
}
|
||||
|
||||
export function getDepositsAndLendsAfterCoinSpent(coin: BNCoin, account?: Account) {
|
||||
const makeOutput = (depositsAmount: BigNumber, lendsAmount: BigNumber) => ({
|
||||
deposits: BNCoin.fromDenomAndBigNumber(coin.denom, depositsAmount),
|
||||
lends: BNCoin.fromDenomAndBigNumber(coin.denom, lendsAmount),
|
||||
})
|
||||
|
||||
if (!account) return makeOutput(BN_ZERO, BN_ZERO)
|
||||
|
||||
const accountDepositAmount = account.deposits.find(byDenom(coin.denom))?.amount ?? BN_ZERO
|
||||
const accountLendsAmount = account.lends.find(byDenom(coin.denom))?.amount ?? BN_ZERO
|
||||
const accountDepositAndLendAmount = accountDepositAmount.plus(accountLendsAmount)
|
||||
|
||||
if (coin.amount.isLessThanOrEqualTo(accountDepositAmount)) {
|
||||
return makeOutput(coin.amount, BN_ZERO)
|
||||
}
|
||||
|
||||
if (coin.amount.isGreaterThanOrEqualTo(accountDepositAndLendAmount)) {
|
||||
return makeOutput(accountDepositAmount, accountLendsAmount)
|
||||
}
|
||||
|
||||
return makeOutput(accountDepositAmount, coin.amount.minus(accountDepositAmount))
|
||||
}
|
||||
|
@ -1,9 +1,15 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
import { addCoins, addValueToVaults, removeCoins } from 'hooks/useUpdatedAccount/functions'
|
||||
import {
|
||||
addCoins,
|
||||
addValueToVaults,
|
||||
getDepositsAndLendsAfterCoinSpent,
|
||||
removeCoins,
|
||||
} from 'hooks/useUpdatedAccount/functions'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { cloneAccount } from 'utils/accounts'
|
||||
import useStore from 'store'
|
||||
import { byDenom } from 'utils/array'
|
||||
|
||||
export interface VaultValue {
|
||||
address: string
|
||||
@ -16,16 +22,17 @@ export function useUpdatedAccount(account?: Account) {
|
||||
)
|
||||
const [addedDeposits, addDeposits] = useState<BNCoin[]>([])
|
||||
const [removedDeposits, removeDeposits] = useState<BNCoin[]>([])
|
||||
const [addedDebt, addDebt] = useState<BNCoin[]>([])
|
||||
const [removedDebt, removeDebt] = useState<BNCoin[]>([])
|
||||
const [addedDebts, addDebts] = useState<BNCoin[]>([])
|
||||
const [removedDebts, removeDebts] = useState<BNCoin[]>([])
|
||||
const [addedVaultValues, addVaultValues] = useState<VaultValue[]>([])
|
||||
const [addedLends, setAddedLends] = useState<BNCoin[]>([])
|
||||
const [removedLends, setRemovedLends] = useState<BNCoin[]>([])
|
||||
const [addedLends, addLends] = useState<BNCoin[]>([])
|
||||
const [removedLends, removeLends] = useState<BNCoin[]>([])
|
||||
|
||||
const removeDepositByDenom = useCallback(
|
||||
const removeDepositAndLendsByDenom = useCallback(
|
||||
(denom: string) => {
|
||||
if (!account) return
|
||||
const deposit = account.deposits.find((deposit) => deposit.denom === denom)
|
||||
const deposit = account.deposits.find(byDenom(denom))
|
||||
const lend = account.lends.find(byDenom(denom))
|
||||
|
||||
if (deposit) {
|
||||
removeDeposits((prevRemovedDeposits) => {
|
||||
@ -35,19 +42,84 @@ export function useUpdatedAccount(account?: Account) {
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
if (lend) {
|
||||
removeLends((prevRemovedLends) => {
|
||||
return [...prevRemovedLends.filter((removedLends) => removedLends.denom !== denom), lend]
|
||||
})
|
||||
}
|
||||
},
|
||||
[account, removeDeposits],
|
||||
)
|
||||
|
||||
const simulateBorrow = useCallback(
|
||||
(target: 'wallet' | 'deposit' | 'lend', coin: BNCoin) => {
|
||||
if (!account) return
|
||||
resetAccount()
|
||||
addDebts([coin])
|
||||
if (target === 'deposit') addDeposits([coin])
|
||||
if (target === 'lend') addLends([coin])
|
||||
},
|
||||
[account, addDebts, addDeposits, addLends],
|
||||
)
|
||||
|
||||
const simulateLending = useCallback(
|
||||
(isLendAction: boolean, coin: BNCoin) => {
|
||||
if (!account) return
|
||||
|
||||
resetAccount()
|
||||
|
||||
if (isLendAction) {
|
||||
addLends([coin])
|
||||
removeDeposits([coin])
|
||||
return
|
||||
}
|
||||
|
||||
removeLends([coin])
|
||||
addDeposits([coin])
|
||||
},
|
||||
[account, addDeposits, addLends, removeDeposits, removeLends],
|
||||
)
|
||||
|
||||
const simulateRepay = useCallback(
|
||||
(coin: BNCoin) => {
|
||||
if (!account) return
|
||||
removeDebts([coin])
|
||||
const { deposits, lends } = getDepositsAndLendsAfterCoinSpent(coin, account)
|
||||
removeDeposits([deposits])
|
||||
removeLends([lends])
|
||||
},
|
||||
[account, removeDebts, removeDeposits, removeLends],
|
||||
)
|
||||
|
||||
const simulateDeposits = useCallback(
|
||||
(target: 'deposit' | 'lend', coins: BNCoin[]) => {
|
||||
if (!account) return
|
||||
resetAccount()
|
||||
if (target === 'deposit') addDeposits(coins)
|
||||
if (target === 'lend') addLends(coins)
|
||||
},
|
||||
[account, addDeposits, addLends],
|
||||
)
|
||||
|
||||
const resetAccount = () => {
|
||||
addDeposits([])
|
||||
removeDeposits([])
|
||||
addDebts([])
|
||||
removeDebts([])
|
||||
addVaultValues([])
|
||||
addLends([])
|
||||
removeLends([])
|
||||
}
|
||||
useEffect(() => {
|
||||
if (!account) return
|
||||
|
||||
const accountCopy = cloneAccount(account)
|
||||
accountCopy.deposits = addCoins(addedDeposits, [...accountCopy.deposits])
|
||||
accountCopy.debts = addCoins(addedDebt, [...accountCopy.debts])
|
||||
accountCopy.debts = addCoins(addedDebts, [...accountCopy.debts])
|
||||
accountCopy.vaults = addValueToVaults(addedVaultValues, [...accountCopy.vaults])
|
||||
accountCopy.deposits = removeCoins(removedDeposits, [...accountCopy.deposits])
|
||||
accountCopy.debts = removeCoins(removedDebt, [...accountCopy.debts])
|
||||
accountCopy.debts = removeCoins(removedDebts, [...accountCopy.debts])
|
||||
accountCopy.lends = addCoins(addedLends, [...accountCopy.lends])
|
||||
accountCopy.lends = removeCoins(removedLends, [...accountCopy.lends])
|
||||
setUpdatedAccount(accountCopy)
|
||||
@ -56,8 +128,8 @@ export function useUpdatedAccount(account?: Account) {
|
||||
return () => useStore.setState({ updatedAccount: undefined })
|
||||
}, [
|
||||
account,
|
||||
addedDebt,
|
||||
removedDebt,
|
||||
addedDebts,
|
||||
removedDebts,
|
||||
addedDeposits,
|
||||
removedDeposits,
|
||||
addedVaultValues,
|
||||
@ -69,17 +141,21 @@ export function useUpdatedAccount(account?: Account) {
|
||||
updatedAccount,
|
||||
addDeposits,
|
||||
removeDeposits,
|
||||
removeDepositByDenom,
|
||||
addDebt,
|
||||
removeDebt,
|
||||
removeDepositAndLendsByDenom,
|
||||
addDebts,
|
||||
removeDebts,
|
||||
addLends,
|
||||
removeLends,
|
||||
addVaultValues,
|
||||
addedDeposits,
|
||||
addedDebt,
|
||||
removedDeposits,
|
||||
removedDebt,
|
||||
addedDebts,
|
||||
addedLends,
|
||||
setAddedLends,
|
||||
removedDeposits,
|
||||
removedDebts,
|
||||
removedLends,
|
||||
setRemovedLends,
|
||||
simulateBorrow,
|
||||
simulateDeposits,
|
||||
simulateLending,
|
||||
simulateRepay,
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import DesktopHeader from 'components/Header/DesktopHeader'
|
||||
import ModalsContainer from 'components/Modals/ModalsContainer'
|
||||
import PageMetadata from 'components/PageMetadata'
|
||||
import Toaster from 'components/Toaster'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import useStore from 'store'
|
||||
|
||||
interface Props {
|
||||
@ -38,6 +39,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
const location = useLocation()
|
||||
const focusComponent = useStore((s) => s.focusComponent)
|
||||
const isFullWidth = location.pathname.includes('trade') || location.pathname === '/'
|
||||
const account = useCurrentAccount()
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -49,6 +51,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
'lg:min-h-[calc(100vh-65px)]',
|
||||
'lg:mt-[65px]',
|
||||
'min-h-screen gap-6 p-6 w-full relative',
|
||||
account && 'pr-18',
|
||||
focusComponent || isMobile
|
||||
? 'flex justify-center'
|
||||
: 'grid grid-cols-[auto_min-content] place-items-start',
|
||||
|
@ -333,17 +333,27 @@ export default function createBroadcastSlice(
|
||||
)
|
||||
return !!response.result
|
||||
},
|
||||
repay: async (options: { accountId: string; coin: BNCoin; accountBalance?: boolean }) => {
|
||||
repay: async (options: {
|
||||
accountId: string
|
||||
coin: BNCoin
|
||||
accountBalance?: boolean
|
||||
lends?: BNCoin
|
||||
}) => {
|
||||
const actions: Action[] = [
|
||||
{
|
||||
repay: {
|
||||
coin: options.coin.toActionCoin(options.accountBalance),
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
if (options.lends && options.lends.amount.isGreaterThan(0))
|
||||
actions.unshift({ reclaim: options.lends.toActionCoin() })
|
||||
|
||||
const msg: CreditManagerExecuteMsg = {
|
||||
update_credit_account: {
|
||||
account_id: options.accountId,
|
||||
actions: [
|
||||
{
|
||||
repay: {
|
||||
coin: options.coin.toActionCoin(options.accountBalance),
|
||||
},
|
||||
},
|
||||
],
|
||||
actions,
|
||||
},
|
||||
}
|
||||
|
||||
|
1
src/types/interfaces/store/broadcast.d.ts
vendored
1
src/types/interfaces/store/broadcast.d.ts
vendored
@ -24,6 +24,7 @@ interface BroadcastSlice {
|
||||
accountId: string
|
||||
coin: BNCoin
|
||||
accountBalance?: boolean
|
||||
lends?: BNCoin
|
||||
}) => Promise<boolean>
|
||||
swap: (options: {
|
||||
accountId: string
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
Positions,
|
||||
VaultPosition,
|
||||
} from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { getAssetByDenom } from 'utils/assets'
|
||||
import { BN } from 'utils/helpers'
|
||||
import { convertApyToApr } from 'utils/parsers'
|
||||
@ -58,12 +59,12 @@ export const calculateAccountValue = (
|
||||
}
|
||||
|
||||
export const calculateAccountApr = (
|
||||
account: Account | AccountChange,
|
||||
totalValue: BigNumber,
|
||||
account: Account,
|
||||
borrowAssetsData: BorrowMarketTableData[],
|
||||
lendingAssetsData: LendingMarketTableData[],
|
||||
prices: BNCoin[],
|
||||
): BigNumber => {
|
||||
const totalValue = calculateAccountBalanceValue(account, prices)
|
||||
if (totalValue.isZero()) return BN_ZERO
|
||||
const { vaults, lends, debts } = account
|
||||
|
||||
@ -74,7 +75,7 @@ export const calculateAccountApr = (
|
||||
lends?.forEach((lend) => {
|
||||
const asset = getAssetByDenom(lend.denom)
|
||||
if (!asset) return BN_ZERO
|
||||
const price = prices.find((price) => price.denom === lend.denom)?.amount ?? 0
|
||||
const price = prices.find(byDenom(lend.denom))?.amount ?? 0
|
||||
const amount = BN(lend.amount).shiftedBy(-asset.decimals)
|
||||
const apr =
|
||||
lendingAssetsData.find((lendingAsset) => lendingAsset.asset.denom === lend.denom)
|
||||
@ -86,7 +87,7 @@ export const calculateAccountApr = (
|
||||
vaults?.forEach((vault) => {
|
||||
const asset = getAssetByDenom(vault.denoms.lp)
|
||||
if (!asset) return BN_ZERO
|
||||
const price = prices.find((price) => price.denom === vault.denoms.lp)?.amount ?? 0
|
||||
const price = prices.find(byDenom(vault.denoms.lp))?.amount ?? 0
|
||||
const amount = BN(vault.amounts.locked).shiftedBy(-asset.decimals)
|
||||
const positionInterest = amount
|
||||
.multipliedBy(price)
|
||||
@ -97,20 +98,19 @@ export const calculateAccountApr = (
|
||||
debts?.forEach((debt) => {
|
||||
const asset = getAssetByDenom(debt.denom)
|
||||
if (!asset) return BN_ZERO
|
||||
const price = prices.find((price) => price.denom === debt.denom)?.amount ?? 0
|
||||
const price = prices.find(byDenom(debt.denom))?.amount ?? 0
|
||||
const amount = BN(debt.amount).shiftedBy(-asset.decimals)
|
||||
const apr =
|
||||
borrowAssetsData.find((borrowAsset) => borrowAsset.asset.denom === debt.denom)
|
||||
?.marketLiquidityRate ?? 0
|
||||
borrowAssetsData.find((borrowAsset) => borrowAsset.asset.denom === debt.denom)?.borrowRate ??
|
||||
0
|
||||
const positionInterest = amount.multipliedBy(price).multipliedBy(apr)
|
||||
totalDeptsInterestValue = totalDeptsInterestValue.plus(positionInterest)
|
||||
})
|
||||
|
||||
const totalPositiveInterestValue = totalLendsInterestValue
|
||||
const totalInterstValue = totalLendsInterestValue
|
||||
.plus(totalVaultsInterestValue)
|
||||
.minus(totalDeptsInterestValue)
|
||||
|
||||
const totalApr = totalPositiveInterestValue.dividedBy(totalValue).times(100)
|
||||
const totalApr = totalInterstValue.dividedBy(totalValue).times(100)
|
||||
|
||||
return totalApr
|
||||
}
|
||||
|
@ -174,6 +174,7 @@ module.exports = {
|
||||
},
|
||||
padding: {
|
||||
5.5: '22px',
|
||||
18: '72px',
|
||||
21: '84px',
|
||||
},
|
||||
screens: {
|
||||
|
Loading…
Reference in New Issue
Block a user