Deposit Cap and Utilization Fix (#654)
* fix: fixed the deposit cap and total supplied / utilization rate * fix: fixed build * fix: fixed build * fix: avoid deposit cap usage over 100% * refactor market data apy/ltv * fix: fixed the withdraw from vaults modal * tidy: refactor --------- Co-authored-by: Bob van der Helm <34470358+bobthebuidlr@users.noreply.github.com>
This commit is contained in:
parent
e7ce4f600a
commit
85533cdea3
@ -1,11 +1,11 @@
|
||||
import getMarket from 'api/markets/getMarket'
|
||||
import getTotalActiveEmissionValue from 'api/incentives/getTotalActiveEmissionValue'
|
||||
import getMarket from 'api/markets/getMarket'
|
||||
import getUnderlyingLiquidityAmount from 'api/markets/getMarketUnderlyingLiquidityAmount'
|
||||
import { BN } from 'utils/helpers'
|
||||
import { SECONDS_IN_A_YEAR } from 'utils/constants'
|
||||
import getPrice from 'api/prices/getPrice'
|
||||
import { ASSETS } from 'constants/assets'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { SECONDS_IN_A_YEAR } from 'utils/constants'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export default async function calculateAssetIncentivesApy(
|
||||
denom: string,
|
||||
@ -29,7 +29,7 @@ export default async function calculateAssetIncentivesApy(
|
||||
.shiftedBy(-assetDecimals)
|
||||
.multipliedBy(assetPrice)
|
||||
|
||||
const marketReturns = BN(market.liquidityRate).multipliedBy(marketLiquidityValue)
|
||||
const marketReturns = BN(market.apy.deposit).multipliedBy(marketLiquidityValue)
|
||||
const annualEmission = totalActiveEmissionValue.multipliedBy(SECONDS_IN_A_YEAR)
|
||||
|
||||
const totalAnnualReturnsValue = annualEmission.plus(marketReturns)
|
||||
|
@ -17,7 +17,7 @@ export default async function getMarketBorrowings(): Promise<BorrowAsset[]> {
|
||||
|
||||
return {
|
||||
...asset,
|
||||
borrowRate: market.borrowRate ?? 0,
|
||||
borrowRate: market.apy.borrow ?? 0,
|
||||
liquidity: {
|
||||
amount: BN(amount),
|
||||
value: BN(amount).multipliedBy(price),
|
||||
|
@ -8,8 +8,6 @@ import { ASSETS } from 'constants/assets'
|
||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { convertLiquidityRateToAPR } from 'utils/formatters'
|
||||
import { convertAprToApy } from 'utils/parsers'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
@ -45,11 +43,9 @@ export default function useAccountBalanceData(props: Props) {
|
||||
|
||||
const lends = accountLends.map((lending) => {
|
||||
const asset = ASSETS.find(byDenom(lending.denom)) ?? ASSETS[0]
|
||||
const apr = convertLiquidityRateToAPR(
|
||||
lendingData.find((market) => market.asset.denom === lending.denom)?.marketLiquidityRate ??
|
||||
0,
|
||||
)
|
||||
const apy = convertAprToApy(apr, 365)
|
||||
const apy =
|
||||
lendingData.find((market) => market.asset.denom === lending.denom)?.apy.deposit ?? 0
|
||||
|
||||
const prevLending = updatedAccount
|
||||
? account?.lends.find((position) => position.denom === lending.denom)
|
||||
: lending
|
||||
@ -66,7 +62,7 @@ export default function useAccountBalanceData(props: Props) {
|
||||
|
||||
const debts = accountDebts.map((debt) => {
|
||||
const asset = ASSETS.find(byDenom(debt.denom)) ?? ASSETS[0]
|
||||
const apy = borrowingData.find((market) => market.asset.denom === debt.denom)?.borrowRate ?? 0
|
||||
const apy = borrowingData.find((market) => market.asset.denom === debt.denom)?.apy.borrow ?? 0
|
||||
const prevDebt = updatedAccount
|
||||
? account?.debts.find((position) => position.denom === debt.denom)
|
||||
: debt
|
||||
|
@ -1,5 +1,3 @@
|
||||
import React from 'react'
|
||||
|
||||
import AvailableBorrowingsTable from 'components/Borrow/Table/AvailableBorrowingsTable'
|
||||
import DepositedBorrowingsTable from 'components/Borrow/Table/DepositedBorrowingsTable'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
@ -24,13 +22,18 @@ function Fallback() {
|
||||
const assets = getBorrowEnabledAssets()
|
||||
const data: BorrowMarketTableData[] = assets.map((asset) => ({
|
||||
asset,
|
||||
borrowRate: null,
|
||||
apy: {
|
||||
borrow: 0,
|
||||
deposit: 0,
|
||||
},
|
||||
ltv: {
|
||||
max: 0,
|
||||
liq: 0,
|
||||
},
|
||||
liquidity: null,
|
||||
marketMaxLtv: 0,
|
||||
marketDepositAmount: BN_ZERO,
|
||||
marketLiquidityRate: 0,
|
||||
marketLiquidityAmount: BN_ZERO,
|
||||
marketLiquidationThreshold: 0,
|
||||
}))
|
||||
|
||||
return <AvailableBorrowingsTable data={data} isLoading />
|
||||
|
@ -18,7 +18,7 @@ export default function useAvailableColumns() {
|
||||
},
|
||||
{
|
||||
...BORROW_RATE_META,
|
||||
cell: ({ row }) => <BorrowRate borrowRate={row.original.borrowRate} />,
|
||||
cell: ({ row }) => <BorrowRate borrowRate={row.original.apy.borrow} />,
|
||||
},
|
||||
{
|
||||
...LIQUIDITY_META,
|
||||
|
@ -24,7 +24,7 @@ export default function useDepositedColumns() {
|
||||
},
|
||||
{
|
||||
...BORROW_RATE_META,
|
||||
cell: ({ row }) => <BorrowRate borrowRate={row.original.borrowRate} />,
|
||||
cell: ({ row }) => <BorrowRate borrowRate={row.original.apy.borrow} />,
|
||||
},
|
||||
{
|
||||
...LIQUIDITY_META,
|
||||
|
@ -12,7 +12,7 @@ export default function DepositCapCell(props: Props) {
|
||||
.dividedBy(props.depositCap.max.multipliedBy(VAULT_DEPOSIT_BUFFER))
|
||||
.multipliedBy(100)
|
||||
.integerValue()
|
||||
|
||||
const depositCapUsed = Math.min(percent.toNumber(), 100)
|
||||
const decimals = getAssetByDenom(props.depositCap.denom)?.decimals ?? 6
|
||||
|
||||
return (
|
||||
@ -27,7 +27,7 @@ export default function DepositCapCell(props: Props) {
|
||||
}
|
||||
sub={
|
||||
<FormattedNumber
|
||||
amount={percent.toNumber()}
|
||||
amount={depositCapUsed}
|
||||
options={{ minDecimals: 2, maxDecimals: 2, suffix: '% Filled' }}
|
||||
className='text-xs'
|
||||
animate
|
||||
|
@ -1,5 +1,3 @@
|
||||
import React from 'react'
|
||||
|
||||
import AvailableLendsTable from 'components/Earn/Lend/Table/AvailableLendsTable'
|
||||
import DepositedLendsTable from 'components/Earn/Lend/Table/DepositedLendsTable'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
@ -26,11 +24,21 @@ function Fallback() {
|
||||
asset,
|
||||
marketDepositCap: BN_ZERO,
|
||||
borrowEnabled: false,
|
||||
marketMaxLtv: 0,
|
||||
marketDepositAmount: BN_ZERO,
|
||||
marketLiquidityRate: 0,
|
||||
marketLiquidityAmount: BN_ZERO,
|
||||
marketLiquidationThreshold: 0,
|
||||
cap: {
|
||||
max: BN_ZERO,
|
||||
used: BN_ZERO,
|
||||
denom: asset.denom,
|
||||
},
|
||||
apy: {
|
||||
borrow: 0,
|
||||
deposit: 0,
|
||||
},
|
||||
ltv: {
|
||||
max: 0,
|
||||
liq: 0,
|
||||
},
|
||||
}))
|
||||
|
||||
return <AvailableLendsTable data={data} isLoading />
|
||||
|
@ -1,11 +1,10 @@
|
||||
import AssetRate from 'components/Asset/AssetRate'
|
||||
import Loading from 'components/Loading'
|
||||
import { convertAprToApy } from 'utils/parsers'
|
||||
|
||||
export const APY_META = { accessorKey: 'marketLiquidityRate', header: 'APY' }
|
||||
export const APY_META = { accessorKey: 'apy.deposit', header: 'APY' }
|
||||
|
||||
interface Props {
|
||||
marketLiquidityRate: number
|
||||
apy: number
|
||||
borrowEnabled: boolean
|
||||
isLoading: boolean
|
||||
}
|
||||
@ -14,7 +13,7 @@ export default function Apr(props: Props) {
|
||||
|
||||
return (
|
||||
<AssetRate
|
||||
rate={convertAprToApy(props.marketLiquidityRate ?? 0, 365)}
|
||||
rate={props.apy ?? 0}
|
||||
isEnabled={props.borrowEnabled}
|
||||
className='justify-end text-xs'
|
||||
type='apy'
|
||||
|
@ -17,10 +17,10 @@ export const marketDepositCapSortingFn = (
|
||||
): number => {
|
||||
const assetA = a.original.asset
|
||||
const assetB = b.original.asset
|
||||
if (!a.original.marketDepositCap || !b.original.marketDepositCap) return 0
|
||||
if (!a.original.cap.max || !b.original.cap.max) return 0
|
||||
|
||||
const marketDepositCapA = demagnify(a.original.marketDepositCap, assetA)
|
||||
const marketDepositCapB = demagnify(b.original.marketDepositCap, assetB)
|
||||
const marketDepositCapA = demagnify(a.original.cap.max, assetA)
|
||||
const marketDepositCapB = demagnify(b.original.cap.max, assetB)
|
||||
return marketDepositCapA - marketDepositCapB
|
||||
}
|
||||
|
||||
@ -30,22 +30,23 @@ interface Props {
|
||||
}
|
||||
export default function DepositCap(props: Props) {
|
||||
if (props.isLoading) return <Loading />
|
||||
const { marketDepositCap, marketDepositAmount, asset } = props.data
|
||||
const percent = marketDepositAmount.dividedBy(marketDepositCap).multipliedBy(100)
|
||||
const { cap, asset } = props.data
|
||||
const percent = cap.used.dividedBy(cap.max).multipliedBy(100)
|
||||
const depositCapUsed = Math.min(percent.toNumber(), 100)
|
||||
|
||||
return (
|
||||
<TitleAndSubCell
|
||||
className='text-xs'
|
||||
title={
|
||||
<FormattedNumber
|
||||
amount={marketDepositCap.toNumber()}
|
||||
amount={cap.max.toNumber()}
|
||||
options={{ abbreviated: true, decimals: asset.decimals }}
|
||||
animate
|
||||
/>
|
||||
}
|
||||
sub={
|
||||
<FormattedNumber
|
||||
amount={percent.toNumber()}
|
||||
amount={depositCapUsed}
|
||||
options={{ minDecimals: 2, maxDecimals: 2, suffix: '% used' }}
|
||||
animate
|
||||
/>
|
||||
|
@ -26,7 +26,7 @@ export default function useAvailableColumns(props: Props) {
|
||||
<Apy
|
||||
isLoading={props.isLoading}
|
||||
borrowEnabled={row.original.borrowEnabled}
|
||||
marketLiquidityRate={row.original.marketLiquidityRate}
|
||||
apy={row.original.apy.deposit}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
@ -37,7 +37,7 @@ export default function useDepositedColumns(props: Props) {
|
||||
<Apy
|
||||
isLoading={props.isLoading}
|
||||
borrowEnabled={row.original.borrowEnabled}
|
||||
marketLiquidityRate={row.original.marketLiquidityRate}
|
||||
apy={row.original.apy.deposit}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
@ -23,13 +23,7 @@ export default function MarketDetails({ row, type }: Props) {
|
||||
symbol: displayCurrencySymbol,
|
||||
} = useDisplayCurrencyPrice()
|
||||
|
||||
const {
|
||||
asset,
|
||||
marketMaxLtv,
|
||||
marketDepositAmount,
|
||||
marketLiquidityAmount,
|
||||
marketLiquidationThreshold,
|
||||
} = row.original
|
||||
const { asset, ltv, marketDepositAmount, marketLiquidityAmount } = row.original
|
||||
|
||||
const totalBorrowed = marketDepositAmount.minus(marketLiquidityAmount)
|
||||
|
||||
@ -48,12 +42,12 @@ export default function MarketDetails({ row, type }: Props) {
|
||||
title: 'Total Supplied',
|
||||
},
|
||||
{
|
||||
amount: marketMaxLtv * 100,
|
||||
amount: ltv.max * 100,
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Max LTV',
|
||||
},
|
||||
{
|
||||
amount: marketLiquidationThreshold * 100,
|
||||
amount: ltv.liq * 100,
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Liquidation LTV',
|
||||
},
|
||||
@ -114,8 +108,7 @@ export default function MarketDetails({ row, type }: Props) {
|
||||
type,
|
||||
asset,
|
||||
marketDepositAmount,
|
||||
marketMaxLtv,
|
||||
marketLiquidationThreshold,
|
||||
ltv,
|
||||
totalBorrowed,
|
||||
displayCurrencySymbol,
|
||||
convertAmount,
|
||||
|
@ -10,7 +10,6 @@ import Text from 'components/Text'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { getAssetByDenom } from 'utils/assets'
|
||||
import { demagnify, formatPercent } from 'utils/formatters'
|
||||
import { convertAprToApy } from 'utils/parsers'
|
||||
|
||||
function showBorrowRate(data: AssetTableRow[]) {
|
||||
const assetData = data.length && (data[0].asset as BorrowAsset)
|
||||
@ -29,8 +28,7 @@ export default function useAssetTableColumns(isBorrow: boolean) {
|
||||
const market = row.original.market
|
||||
const borrowAsset = row.original.asset as BorrowAsset
|
||||
const showRate = !borrowAsset?.borrowRate
|
||||
const rate = isBorrow ? market?.borrowRate : market?.liquidityRate
|
||||
const apy = convertAprToApy(rate ?? 0, 365)
|
||||
const apy = isBorrow ? market?.apy.borrow : market?.apy.deposit
|
||||
|
||||
return (
|
||||
<div className='flex items-center'>
|
||||
@ -47,7 +45,7 @@ export default function useAssetTableColumns(isBorrow: boolean) {
|
||||
</Text>
|
||||
{showRate && market ? (
|
||||
<AssetRate
|
||||
rate={apy}
|
||||
rate={apy ?? 0}
|
||||
isEnabled={market.borrowEnabled}
|
||||
className='text-xs'
|
||||
type='apy'
|
||||
|
@ -81,7 +81,7 @@ function BorrowModal(props: Props) {
|
||||
const [max, setMax] = useState(BN_ZERO)
|
||||
const { simulateBorrow, simulateRepay } = useUpdatedAccount(account)
|
||||
const { autoLendEnabledAccountIds } = useAutoLend()
|
||||
const apr = modal.marketData?.borrowRate ?? '0'
|
||||
const apy = modal.marketData.apy.borrow
|
||||
const isAutoLendEnabled = autoLendEnabledAccountIds.includes(account.id)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(account)
|
||||
const totalDebt = BN(getDebtAmount(modal))
|
||||
@ -95,8 +95,8 @@ function BorrowModal(props: Props) {
|
||||
)
|
||||
|
||||
const totalDebtRepayAmount = useMemo(
|
||||
() => getDebtAmountWithInterest(totalDebt, Number(apr)),
|
||||
[totalDebt, apr],
|
||||
() => getDebtAmountWithInterest(totalDebt, apy),
|
||||
[totalDebt, apy],
|
||||
)
|
||||
|
||||
const maxRepayAmount = useMemo(() => {
|
||||
@ -201,7 +201,7 @@ function BorrowModal(props: Props) {
|
||||
>
|
||||
<div className='flex gap-3 px-6 py-4 border-b border-white/5 gradient-header'>
|
||||
<TitleAndSubCell
|
||||
title={formatPercent(modal.marketData.borrowRate || '0')}
|
||||
title={formatPercent(modal.marketData.apy.borrow)}
|
||||
sub={'Borrow Rate APY'}
|
||||
/>
|
||||
{totalDebt.isGreaterThan(0) && (
|
||||
|
@ -10,7 +10,7 @@ interface Props {
|
||||
}
|
||||
|
||||
function DetailsHeader({ data }: Props) {
|
||||
const { asset, marketDepositCap, accountLentAmount } = data
|
||||
const { asset, cap, accountLentAmount } = data
|
||||
const { data: assetApy } = useAssetIncentivesApy(asset.denom)
|
||||
const balanceInWallet = useCurrentWalletBalance(asset.denom)
|
||||
|
||||
@ -59,9 +59,7 @@ function DetailsHeader({ data }: Props) {
|
||||
)}
|
||||
<TitleAndSubCell
|
||||
title={
|
||||
<DisplayCurrency
|
||||
coin={new BNCoin({ denom: asset.denom, amount: marketDepositCap.toString() })}
|
||||
/>
|
||||
<DisplayCurrency coin={new BNCoin({ denom: asset.denom, amount: cap.max.toString() })} />
|
||||
}
|
||||
sub={'Deposit Cap'}
|
||||
/>
|
||||
|
@ -225,7 +225,7 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
||||
</div>
|
||||
{props.borrowings.map((coin) => {
|
||||
const asset = getAssetByDenom(coin.denom)
|
||||
const borrowRate = marketAssets?.find((market) => market.denom === coin.denom)?.borrowRate
|
||||
const borrowRate = marketAssets?.find((market) => market.denom === coin.denom)?.apy.borrow
|
||||
|
||||
if (!asset || !borrowRate)
|
||||
return <React.Fragment key={`borrow-rate-${coin.denom}`}></React.Fragment>
|
||||
|
@ -7,18 +7,20 @@ import Modal from 'components/Modal'
|
||||
import Text from 'components/Text'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
import { LocalStorageKeys } from 'constants/localStorageKeys'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import useAccountId from 'hooks/useAccountId'
|
||||
import useLocalStorage from 'hooks/useLocalStorage'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { getAssetByDenom } from 'utils/assets'
|
||||
import { demagnify } from 'utils/formatters'
|
||||
|
||||
export default function WithdrawFromVaultsModal() {
|
||||
const modal = useStore((s) => s.withdrawFromVaultsModal)
|
||||
const accountId = useAccountId()
|
||||
const { data: prices } = usePrices()
|
||||
const withdrawFromVaults = useStore((s) => s.withdrawFromVaults)
|
||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
||||
const [slippage] = useLocalStorage<number>(LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage)
|
||||
|
||||
function onClose() {
|
||||
@ -52,12 +54,18 @@ export default function WithdrawFromVaultsModal() {
|
||||
{modal ? (
|
||||
<div className='flex flex-wrap w-full gap-4'>
|
||||
{modal.map((vault) => {
|
||||
const positionValue = vault.values.primary.plus(vault.values.secondary)
|
||||
const coin = BNCoin.fromDenomAndBigNumber(baseCurrency.denom, positionValue)
|
||||
const positionValue = vault.values.unlocking
|
||||
const coin = BNCoin.fromDenomAndBigNumber(ORACLE_DENOM, positionValue)
|
||||
const primaryAsset = getAssetByDenom(vault.denoms.primary)
|
||||
const secondaryAsset = getAssetByDenom(vault.denoms.secondary)
|
||||
|
||||
if (!primaryAsset || !secondaryAsset) return null
|
||||
const primaryAssetPrice = prices.find(byDenom(primaryAsset.denom))?.amount ?? 1
|
||||
const secondaryAssetPrice = prices.find(byDenom(secondaryAsset.denom))?.amount ?? 1
|
||||
|
||||
const primaryAssetAmount = positionValue.dividedBy(primaryAssetPrice).dividedBy(2)
|
||||
const secondaryAssetAmount = positionValue.dividedBy(secondaryAssetPrice).dividedBy(2)
|
||||
|
||||
return (
|
||||
<div className='flex items-center gap-4' key={vault.unlockId}>
|
||||
<DoubleLogo
|
||||
@ -73,15 +81,21 @@ export default function WithdrawFromVaultsModal() {
|
||||
<div className='flex flex-wrap'>
|
||||
<DisplayCurrency coin={coin} className='w-full text-right' />
|
||||
<FormattedNumber
|
||||
amount={demagnify(vault.amounts.primary, primaryAsset)}
|
||||
amount={Number(primaryAssetAmount.toPrecision(4))}
|
||||
className='w-full text-sm text-right text-white/50'
|
||||
options={{ suffix: ` ${vault.symbols.primary}` }}
|
||||
options={{
|
||||
suffix: ` ${vault.symbols.primary}`,
|
||||
maxDecimals: primaryAsset.decimals,
|
||||
}}
|
||||
animate
|
||||
/>
|
||||
<FormattedNumber
|
||||
amount={demagnify(vault.amounts.secondary, secondaryAsset)}
|
||||
amount={Number(secondaryAssetAmount.toPrecision(4))}
|
||||
className='w-full text-sm text-right text-white/50'
|
||||
options={{ suffix: ` ${vault.symbols.secondary}` }}
|
||||
options={{
|
||||
suffix: ` ${vault.symbols.secondary}`,
|
||||
maxDecimals: secondaryAsset.decimals,
|
||||
}}
|
||||
animate
|
||||
/>
|
||||
</div>
|
||||
|
@ -11,7 +11,6 @@ import useMarketAssets from 'hooks/useMarketAssets'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { formatValue } from 'utils/formatters'
|
||||
import { convertAprToApy } from 'utils/parsers'
|
||||
|
||||
interface Props extends SelectOption {
|
||||
isSelected?: boolean
|
||||
@ -80,7 +79,7 @@ export default function Option(props: Props) {
|
||||
})}
|
||||
</Text>
|
||||
<AssetRate
|
||||
rate={convertAprToApy(marketAsset?.borrowRate ?? 0, 365)}
|
||||
rate={marketAsset?.apy.borrow ?? 0}
|
||||
isEnabled={marketAsset?.borrowEnabled ?? false}
|
||||
className='col-span-2 text-white/50'
|
||||
type='apy'
|
||||
|
@ -26,7 +26,7 @@ export default function useBorrowMarketAssetsTableData(suspense = true) {
|
||||
const accountBorrowedAssets: BorrowMarketTableData[] = [],
|
||||
availableAssets: BorrowMarketTableData[] = []
|
||||
|
||||
markets.forEach(({ denom, liquidityRate, liquidationThreshold, maxLtv }) => {
|
||||
markets.forEach(({ denom, apy, ltv }) => {
|
||||
const asset = getAssetByDenom(denom) as Asset
|
||||
const borrow = borrowData.find((borrow) => borrow.denom === denom)
|
||||
const marketDepositAmount = BN(marketDeposits.find(byDenom(denom))?.amount ?? 0)
|
||||
@ -41,9 +41,8 @@ export default function useBorrowMarketAssetsTableData(suspense = true) {
|
||||
debt: debt?.amount,
|
||||
marketDepositAmount,
|
||||
marketLiquidityAmount,
|
||||
marketLiquidityRate: liquidityRate,
|
||||
marketLiquidationThreshold: liquidationThreshold,
|
||||
marketMaxLtv: maxLtv,
|
||||
apy,
|
||||
ltv,
|
||||
}
|
||||
;(borrowMarketAsset.debt ? accountBorrowedAssets : availableAssets).push(borrowMarketAsset)
|
||||
})
|
||||
|
@ -3,6 +3,7 @@ import { useMemo } from 'react'
|
||||
import useCurrentAccountLends from 'hooks/useCurrentAccountLends'
|
||||
import useDepositEnabledMarkets from 'hooks/useDepositEnabledMarkets'
|
||||
import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice'
|
||||
import useMarketDeposits from 'hooks/useMarketDeposits'
|
||||
import useMarketLiquidities from 'hooks/useMarketLiquidities'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { getAssetByDenom } from 'utils/assets'
|
||||
@ -16,46 +17,45 @@ function useLendingMarketAssetsTableData(): {
|
||||
const markets = useDepositEnabledMarkets()
|
||||
const accountLentAmounts = useCurrentAccountLends()
|
||||
const { data: marketLiquidities } = useMarketLiquidities()
|
||||
const { data: marketDeposits } = useMarketDeposits()
|
||||
const { convertAmount } = useDisplayCurrencyPrice()
|
||||
|
||||
return useMemo(() => {
|
||||
const accountLentAssets: LendingMarketTableData[] = [],
|
||||
availableAssets: LendingMarketTableData[] = []
|
||||
|
||||
markets.forEach(
|
||||
({ denom, cap, liquidityRate, liquidationThreshold, maxLtv, borrowEnabled }) => {
|
||||
const asset = getAssetByDenom(denom) as Asset
|
||||
const marketLiquidityAmount = BN(marketLiquidities.find(byDenom(denom))?.amount ?? 0)
|
||||
const accountLentAmount = accountLentAmounts.find(byDenom(denom))?.amount
|
||||
const accountLentValue = accountLentAmount
|
||||
? convertAmount(asset, accountLentAmount)
|
||||
: undefined
|
||||
markets.forEach(({ denom, cap, ltv, apy, borrowEnabled }) => {
|
||||
const asset = getAssetByDenom(denom) as Asset
|
||||
const marketDepositAmount = BN(marketDeposits.find(byDenom(denom))?.amount ?? 0)
|
||||
const marketLiquidityAmount = BN(marketLiquidities.find(byDenom(denom))?.amount ?? 0)
|
||||
const accountLentAmount = accountLentAmounts.find(byDenom(denom))?.amount
|
||||
const accountLentValue = accountLentAmount
|
||||
? convertAmount(asset, accountLentAmount)
|
||||
: undefined
|
||||
|
||||
const lendingMarketAsset: LendingMarketTableData = {
|
||||
asset,
|
||||
marketDepositAmount: cap.used,
|
||||
accountLentValue,
|
||||
accountLentAmount,
|
||||
marketLiquidityAmount,
|
||||
marketDepositCap: cap.max,
|
||||
marketLiquidityRate: liquidityRate,
|
||||
marketLiquidationThreshold: liquidationThreshold,
|
||||
marketMaxLtv: maxLtv,
|
||||
borrowEnabled,
|
||||
}
|
||||
const lendingMarketAsset: LendingMarketTableData = {
|
||||
asset,
|
||||
marketDepositAmount,
|
||||
accountLentValue,
|
||||
accountLentAmount,
|
||||
marketLiquidityAmount,
|
||||
apy,
|
||||
ltv,
|
||||
borrowEnabled,
|
||||
cap,
|
||||
}
|
||||
|
||||
;(lendingMarketAsset.accountLentValue ? accountLentAssets : availableAssets).push(
|
||||
lendingMarketAsset,
|
||||
)
|
||||
},
|
||||
)
|
||||
;(lendingMarketAsset.accountLentValue ? accountLentAssets : availableAssets).push(
|
||||
lendingMarketAsset,
|
||||
)
|
||||
})
|
||||
|
||||
return {
|
||||
accountLentAssets,
|
||||
availableAssets,
|
||||
allAssets: [...accountLentAssets, ...availableAssets],
|
||||
}
|
||||
}, [markets, marketLiquidities, accountLentAmounts, convertAmount])
|
||||
}, [markets, marketLiquidities, accountLentAmounts, marketDeposits, convertAmount])
|
||||
}
|
||||
|
||||
export default useLendingMarketAssetsTableData
|
||||
|
14
src/types/interfaces/asset.d.ts
vendored
14
src/types/interfaces/asset.d.ts
vendored
@ -88,7 +88,6 @@ interface BigNumberCoin {
|
||||
}
|
||||
|
||||
interface BorrowMarketTableData extends MarketTableData {
|
||||
borrowRate: number | null
|
||||
liquidity: {
|
||||
amount: BigNumber
|
||||
value: BigNumber
|
||||
@ -97,19 +96,24 @@ interface BorrowMarketTableData extends MarketTableData {
|
||||
}
|
||||
|
||||
interface LendingMarketTableData extends MarketTableData {
|
||||
marketDepositCap: BigNumber
|
||||
accountLentAmount?: string
|
||||
accountLentValue?: BigNumber
|
||||
borrowEnabled: boolean
|
||||
cap: DepositCap
|
||||
}
|
||||
|
||||
interface MarketTableData {
|
||||
asset: Asset
|
||||
marketMaxLtv: number
|
||||
marketDepositAmount: BigNumber
|
||||
marketLiquidityRate: number
|
||||
marketLiquidityAmount: BigNumber
|
||||
marketLiquidationThreshold: number
|
||||
apy: {
|
||||
borrow: number
|
||||
deposit: number
|
||||
}
|
||||
ltv: {
|
||||
max: number
|
||||
liq: number
|
||||
}
|
||||
}
|
||||
|
||||
interface HLSStrategy extends HLSStrategyNoCap {
|
||||
|
12
src/types/interfaces/market.d.ts
vendored
12
src/types/interfaces/market.d.ts
vendored
@ -1,12 +1,16 @@
|
||||
interface Market {
|
||||
denom: string
|
||||
borrowRate: number
|
||||
debtTotalScaled: string
|
||||
collateralTotalScaled: string
|
||||
depositEnabled: boolean
|
||||
borrowEnabled: boolean
|
||||
cap: DepositCap
|
||||
maxLtv: number
|
||||
liquidityRate: number
|
||||
liquidationThreshold: number
|
||||
apy: {
|
||||
borrow: number
|
||||
deposit: number
|
||||
}
|
||||
ltv: {
|
||||
max: number
|
||||
liq: number
|
||||
}
|
||||
}
|
||||
|
@ -107,10 +107,15 @@ export const calculateAccountApr = (
|
||||
if (!asset) return BN_ZERO
|
||||
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)
|
||||
?.marketLiquidityRate ?? 0
|
||||
const positionInterest = amount.multipliedBy(price).multipliedBy(apr).dividedBy(100)
|
||||
const apy = lendingAssetsData.find((lendingAsset) => lendingAsset.asset.denom === lend.denom)
|
||||
?.apy.deposit
|
||||
|
||||
if (!apy) return
|
||||
|
||||
const positionInterest = amount
|
||||
.multipliedBy(price)
|
||||
.multipliedBy(convertApyToApr(apy, 365))
|
||||
.dividedBy(100)
|
||||
totalLendsInterestValue = totalLendsInterestValue.plus(positionInterest)
|
||||
})
|
||||
|
||||
@ -125,9 +130,11 @@ export const calculateAccountApr = (
|
||||
if (!asset) return BN_ZERO
|
||||
const price = prices.find(byDenom(debt.denom))?.amount ?? 0
|
||||
const amount = BN(debt.amount).shiftedBy(-asset.decimals)
|
||||
const apy =
|
||||
borrowAssetsData.find((borrowAsset) => borrowAsset.asset.denom === debt.denom)?.borrowRate ??
|
||||
0
|
||||
const apy = borrowAssetsData.find((borrowAsset) => borrowAsset.asset.denom === debt.denom)?.apy
|
||||
.borrow
|
||||
|
||||
if (!apy) return
|
||||
|
||||
const positionInterest = amount
|
||||
.multipliedBy(price)
|
||||
.multipliedBy(convertApyToApr(apy, 365))
|
||||
|
@ -14,7 +14,10 @@ export function resolveMarketResponse(
|
||||
): Market {
|
||||
return {
|
||||
denom: marketResponse.denom,
|
||||
borrowRate: convertAprToApy(Number(marketResponse.borrow_rate), 365) * 100,
|
||||
apy: {
|
||||
borrow: convertAprToApy(Number(marketResponse.borrow_rate), 365) * 100,
|
||||
deposit: convertAprToApy(Number(marketResponse.liquidity_rate), 365) * 100,
|
||||
},
|
||||
debtTotalScaled: marketResponse.debt_total_scaled,
|
||||
collateralTotalScaled: marketResponse.collateral_total_scaled,
|
||||
depositEnabled: assetParamsResponse.red_bank.deposit_enabled,
|
||||
@ -24,9 +27,10 @@ export function resolveMarketResponse(
|
||||
used: BN(assetCapResponse.amount),
|
||||
max: BN(assetParamsResponse.deposit_cap),
|
||||
},
|
||||
maxLtv: Number(assetParamsResponse.max_loan_to_value),
|
||||
liquidityRate: Number(marketResponse.liquidity_rate) * 100,
|
||||
liquidationThreshold: Number(assetParamsResponse.liquidation_threshold),
|
||||
ltv: {
|
||||
max: Number(assetParamsResponse.max_loan_to_value),
|
||||
liq: Number(assetParamsResponse.liquidation_threshold),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user