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