bbbdca6950
* added icon for atom and tokenInfo data update * borrow page initial commit * feat: borrow funds to ca and wallet * close borrow module on tx success * feat: repay funds initial setup * repay funds action hook * repay slider. module state on borrow page component * styling: minor tweak to text colors * limit manual input on repay to max value * borrow funds component slider initial * style: max button typography * AssetRow extracted to separate file. organize imports * ContainerSecondary component added * loading indicator for pending actions * style: progress bar colors * tanstack table added * tanstack react-table dependency missing * table cleanup and layout adjustments * fix account stats formula and update market data to match spreadsheet * calculate max borrow amount hook * reset borrow and repay components on account change * max borrow amount decimals. memorized return * hook tanstack data with real data * redefine borrowedAssetsMap to map * update max borrow amount formulas * remove unnecessary table component. refactor borrow table
87 lines
2.8 KiB
TypeScript
87 lines
2.8 KiB
TypeScript
import { useMemo } from 'react'
|
|
import BigNumber from 'bignumber.js'
|
|
|
|
import useCreditManagerStore from 'stores/useCreditManagerStore'
|
|
import { getTokenDecimals } from 'utils/tokens'
|
|
import useCreditAccountPositions from './useCreditAccountPositions'
|
|
import useMarkets from './useMarkets'
|
|
import useTokenPrices from './useTokenPrices'
|
|
|
|
// displaying 3 levels of risk based on the weighted average of liquidation LTVs
|
|
// 0.85 -> 25% risk
|
|
// 0.65 - 0.85 -> 50% risk
|
|
// < 0.65 -> 100% risk
|
|
const getRiskFromAverageLiquidationLTVs = (value: number) => {
|
|
if (value >= 0.85) return 0.25
|
|
if (value > 0.65) return 0.5
|
|
return 1
|
|
}
|
|
|
|
const useAccountStats = () => {
|
|
const selectedAccount = useCreditManagerStore((s) => s.selectedAccount)
|
|
|
|
const { data: positionsData } = useCreditAccountPositions(selectedAccount ?? '')
|
|
const { data: marketsData } = useMarkets()
|
|
const { data: tokenPrices } = useTokenPrices()
|
|
|
|
return useMemo(() => {
|
|
if (!marketsData || !tokenPrices || !positionsData) return null
|
|
|
|
const getTokenTotalUSDValue = (amount: string, denom: string) => {
|
|
// early return if prices are not fetched yet
|
|
if (!tokenPrices) return 0
|
|
|
|
return BigNumber(amount)
|
|
.div(10 ** getTokenDecimals(denom))
|
|
.times(tokenPrices[denom])
|
|
.toNumber()
|
|
}
|
|
|
|
const totalPosition = positionsData.coins.reduce((acc, coin) => {
|
|
const tokenTotalValue = getTokenTotalUSDValue(coin.amount, coin.denom)
|
|
return BigNumber(tokenTotalValue).plus(acc).toNumber()
|
|
}, 0)
|
|
|
|
const totalDebt = positionsData.debts.reduce((acc, coin) => {
|
|
const tokenTotalValue = getTokenTotalUSDValue(coin.amount, coin.denom)
|
|
return BigNumber(tokenTotalValue).plus(acc).toNumber()
|
|
}, 0)
|
|
|
|
const totalWeightedPositions = positionsData.coins.reduce((acc, coin) => {
|
|
const tokenWeightedValue = BigNumber(getTokenTotalUSDValue(coin.amount, coin.denom)).times(
|
|
Number(marketsData[coin.denom].liquidation_threshold)
|
|
)
|
|
|
|
return tokenWeightedValue.plus(acc).toNumber()
|
|
}, 0)
|
|
|
|
const netWorth = BigNumber(totalPosition).minus(totalDebt).toNumber()
|
|
|
|
const liquidationLTVsWeightedAverage = BigNumber(totalWeightedPositions)
|
|
.div(totalPosition)
|
|
.toNumber()
|
|
|
|
const maxLeverage = BigNumber(1)
|
|
.div(BigNumber(1).minus(liquidationLTVsWeightedAverage))
|
|
.toNumber()
|
|
const currentLeverage = BigNumber(totalPosition).div(netWorth).toNumber()
|
|
const health = BigNumber(1).minus(BigNumber(currentLeverage).div(maxLeverage)).toNumber() || 1
|
|
|
|
const risk = liquidationLTVsWeightedAverage
|
|
? getRiskFromAverageLiquidationLTVs(liquidationLTVsWeightedAverage)
|
|
: 0
|
|
|
|
return {
|
|
health,
|
|
maxLeverage,
|
|
currentLeverage,
|
|
netWorth,
|
|
risk,
|
|
totalPosition,
|
|
totalDebt,
|
|
}
|
|
}, [marketsData, positionsData, tokenPrices])
|
|
}
|
|
|
|
export default useAccountStats
|