vault: separate aprs (#777)
This commit is contained in:
parent
ef9c353b6b
commit
b2b8f93bc3
@ -1,31 +0,0 @@
|
|||||||
import { aprsCache, aprsCacheResponse, cacheFn } from 'api/cache'
|
|
||||||
|
|
||||||
export default async function getAprs(chainConfig: ChainConfig) {
|
|
||||||
if (!chainConfig.farm) return []
|
|
||||||
try {
|
|
||||||
const response = await cacheFn(
|
|
||||||
() => fetch(chainConfig.endpoints.aprs.vaults),
|
|
||||||
aprsCacheResponse,
|
|
||||||
`${chainConfig.id}/aprsResponse`,
|
|
||||||
60,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (response.ok) {
|
|
||||||
const data: AprResponse = await cacheFn(
|
|
||||||
() => response.json(),
|
|
||||||
aprsCache,
|
|
||||||
`${chainConfig.id}/aprs`,
|
|
||||||
60,
|
|
||||||
)
|
|
||||||
|
|
||||||
return data.vaults.map((aprData) => {
|
|
||||||
const finalApr = aprData.apr.projected_apr * 100
|
|
||||||
return { address: aprData.address, apr: finalApr } as Apr
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return []
|
|
||||||
} catch {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +1,20 @@
|
|||||||
import getAssetParams from 'api/params/getAssetParams'
|
import getAssetParams from 'api/params/getAssetParams'
|
||||||
import getAprs from 'api/vaults/getVaultAprs'
|
|
||||||
import { getVaultConfigs } from 'api/vaults/getVaultConfigs'
|
import { getVaultConfigs } from 'api/vaults/getVaultConfigs'
|
||||||
import { getVaultUtilizations } from 'api/vaults/getVaultUtilizations'
|
import { getVaultUtilizations } from 'api/vaults/getVaultUtilizations'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN } from 'utils/helpers'
|
||||||
import { convertAprToApy } from 'utils/parsers'
|
|
||||||
import { resolveHLSStrategies } from 'utils/resolvers'
|
import { resolveHLSStrategies } from 'utils/resolvers'
|
||||||
|
|
||||||
export default async function getVaults(chainConfig: ChainConfig): Promise<Vault[]> {
|
export default async function getVaults(chainConfig: ChainConfig): Promise<Vault[]> {
|
||||||
const assetParams = await getAssetParams(chainConfig)
|
const assetParams = await getAssetParams(chainConfig)
|
||||||
const vaultConfigs = await getVaultConfigs(chainConfig)
|
const vaultConfigs = await getVaultConfigs(chainConfig)
|
||||||
const $vaultUtilizations = getVaultUtilizations(chainConfig, vaultConfigs)
|
const $vaultUtilizations = getVaultUtilizations(chainConfig, vaultConfigs)
|
||||||
const $aprs = getAprs(chainConfig)
|
|
||||||
const vaultMetaDatas = chainConfig.vaults
|
const vaultMetaDatas = chainConfig.vaults
|
||||||
const HLSAssets = assetParams.filter((asset) => asset.credit_manager.hls)
|
const HLSAssets = assetParams.filter((asset) => asset.credit_manager.hls)
|
||||||
const hlsStrategies = resolveHLSStrategies('vault', HLSAssets)
|
const hlsStrategies = resolveHLSStrategies('vault', HLSAssets)
|
||||||
|
|
||||||
const vaults: Vault[] = []
|
const vaults: Vault[] = []
|
||||||
await Promise.all([$vaultUtilizations, $aprs]).then(([vaultUtilizations, aprs]) => {
|
await $vaultUtilizations.then((vaultUtilizations) => {
|
||||||
return vaultConfigs.map((vaultConfig) => {
|
return vaultConfigs.map((vaultConfig) => {
|
||||||
const apr = aprs.find((apr) => apr.address === vaultConfig.addr)
|
|
||||||
const vaultMetaData = vaultMetaDatas.find(
|
const vaultMetaData = vaultMetaDatas.find(
|
||||||
(vaultMetaData) => vaultMetaData.address === vaultConfig.addr,
|
(vaultMetaData) => vaultMetaData.address === vaultConfig.addr,
|
||||||
)
|
)
|
||||||
@ -36,8 +32,6 @@ export default async function getVaults(chainConfig: ChainConfig): Promise<Vault
|
|||||||
)?.utilization.amount || 0,
|
)?.utilization.amount || 0,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
apy: apr ? convertAprToApy(apr.apr, 365) : null,
|
|
||||||
apr: apr ? apr.apr : null,
|
|
||||||
ltv: {
|
ltv: {
|
||||||
max: Number(vaultConfig.max_loan_to_value),
|
max: Number(vaultConfig.max_loan_to_value),
|
||||||
liq: Number(vaultConfig.liquidation_threshold),
|
liq: Number(vaultConfig.liquidation_threshold),
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
|
||||||
import AssetRate from 'components/common/assets/AssetRate'
|
import AssetRate from 'components/common/assets/AssetRate'
|
||||||
|
import Loading from 'components/common/Loading'
|
||||||
|
import Text from 'components/common/Text'
|
||||||
|
|
||||||
export const APY_META = { accessorKey: 'apy', header: 'APY', meta: { className: 'w-30' } }
|
export const APY_META = { accessorKey: 'apy', header: 'APY', meta: { className: 'w-30' } }
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
apy: number
|
apy?: number | null
|
||||||
markets: Market[]
|
markets: Market[]
|
||||||
denom: string
|
denom: string
|
||||||
type: PositionType
|
type: PositionType
|
||||||
@ -14,12 +16,16 @@ interface Props {
|
|||||||
export default function Apr(props: Props) {
|
export default function Apr(props: Props) {
|
||||||
const { markets, type, denom, apy } = props
|
const { markets, type, denom, apy } = props
|
||||||
|
|
||||||
|
if (apy === undefined) return <Loading />
|
||||||
|
if (apy === null) return <Text size='xs'>N/A</Text>
|
||||||
|
|
||||||
if (apy === 0)
|
if (apy === 0)
|
||||||
return (
|
return (
|
||||||
<p className={classNames('w-full text-xs text-right number', type === 'vault' && 'pb-4')}>
|
<p className={classNames('w-full text-xs text-right number', type === 'vault' && 'pb-4')}>
|
||||||
–
|
–
|
||||||
</p>
|
</p>
|
||||||
)
|
)
|
||||||
|
|
||||||
const isEnabled =
|
const isEnabled =
|
||||||
markets.find((market) => market.asset.denom === props.denom)?.borrowEnabled ?? false
|
markets.find((market) => market.asset.denom === props.denom)?.borrowEnabled ?? false
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import { ORACLE_DENOM } from 'constants/oracle'
|
|||||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
|
import useVaultAprs from 'hooks/vaults/useVaultAprs'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { calculateAccountApr, getAccountPositionValues } from 'utils/accounts'
|
import { calculateAccountApr, getAccountPositionValues } from 'utils/accounts'
|
||||||
@ -37,6 +38,7 @@ export default function AccountComposition(props: Props) {
|
|||||||
const hasChanged = !!updatedAccount
|
const hasChanged = !!updatedAccount
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
const { data: hlsStrategies } = useHLSStakingAssets()
|
const { data: hlsStrategies } = useHLSStakingAssets()
|
||||||
|
const { data: vaultAprs } = useVaultAprs()
|
||||||
const assets = useAllAssets()
|
const assets = useAllAssets()
|
||||||
const data = useBorrowMarketAssetsTableData()
|
const data = useBorrowMarketAssetsTableData()
|
||||||
const borrowAssetsData = useMemo(() => data?.allAssets || [], [data])
|
const borrowAssetsData = useMemo(() => data?.allAssets || [], [data])
|
||||||
@ -75,9 +77,19 @@ export default function AccountComposition(props: Props) {
|
|||||||
prices,
|
prices,
|
||||||
hlsStrategies,
|
hlsStrategies,
|
||||||
assets,
|
assets,
|
||||||
|
vaultAprs,
|
||||||
props.isHls,
|
props.isHls,
|
||||||
),
|
),
|
||||||
[account, assets, borrowAssetsData, hlsStrategies, lendingAssetsData, prices, props.isHls],
|
[
|
||||||
|
account,
|
||||||
|
assets,
|
||||||
|
borrowAssetsData,
|
||||||
|
hlsStrategies,
|
||||||
|
lendingAssetsData,
|
||||||
|
prices,
|
||||||
|
props.isHls,
|
||||||
|
vaultAprs,
|
||||||
|
],
|
||||||
)
|
)
|
||||||
const updatedApr = useMemo(
|
const updatedApr = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -89,6 +101,7 @@ export default function AccountComposition(props: Props) {
|
|||||||
prices,
|
prices,
|
||||||
hlsStrategies,
|
hlsStrategies,
|
||||||
assets,
|
assets,
|
||||||
|
vaultAprs,
|
||||||
props.isHls,
|
props.isHls,
|
||||||
)
|
)
|
||||||
: BN_ZERO,
|
: BN_ZERO,
|
||||||
@ -99,6 +112,7 @@ export default function AccountComposition(props: Props) {
|
|||||||
prices,
|
prices,
|
||||||
hlsStrategies,
|
hlsStrategies,
|
||||||
assets,
|
assets,
|
||||||
|
vaultAprs,
|
||||||
props.isHls,
|
props.isHls,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -22,9 +22,10 @@ import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
|||||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||||
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
||||||
import useAccountId from 'hooks/useAccountId'
|
import useAccountId from 'hooks/useAccountId'
|
||||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
|
||||||
import useHealthComputer from 'hooks/useHealthComputer'
|
import useHealthComputer from 'hooks/useHealthComputer'
|
||||||
|
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
|
import useVaultAprs from 'hooks/vaults/useVaultAprs'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import {
|
import {
|
||||||
@ -38,6 +39,7 @@ export default function AccountDetailsController() {
|
|||||||
const isHLS = useStore((s) => s.isHLS)
|
const isHLS = useStore((s) => s.isHLS)
|
||||||
const { data: _, isLoading } = useAccounts('default', address)
|
const { data: _, isLoading } = useAccounts('default', address)
|
||||||
const { data: accountIds } = useAccountIds(address, false, true)
|
const { data: accountIds } = useAccountIds(address, false, true)
|
||||||
|
|
||||||
const accountId = useAccountId()
|
const accountId = useAccountId()
|
||||||
|
|
||||||
const account = useCurrentAccount()
|
const account = useCurrentAccount()
|
||||||
@ -59,6 +61,7 @@ function AccountDetails(props: Props) {
|
|||||||
const { account } = props
|
const { account } = props
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const { data: hlsStrategies } = useHLSStakingAssets()
|
const { data: hlsStrategies } = useHLSStakingAssets()
|
||||||
|
const { data: vaultAprs } = useVaultAprs()
|
||||||
const [reduceMotion] = useLocalStorage<boolean>(
|
const [reduceMotion] = useLocalStorage<boolean>(
|
||||||
LocalStorageKeys.REDUCE_MOTION,
|
LocalStorageKeys.REDUCE_MOTION,
|
||||||
DEFAULT_SETTINGS.reduceMotion,
|
DEFAULT_SETTINGS.reduceMotion,
|
||||||
@ -107,9 +110,19 @@ function AccountDetails(props: Props) {
|
|||||||
prices,
|
prices,
|
||||||
hlsStrategies,
|
hlsStrategies,
|
||||||
assets,
|
assets,
|
||||||
|
vaultAprs,
|
||||||
account.kind === 'high_levered_strategy',
|
account.kind === 'high_levered_strategy',
|
||||||
),
|
),
|
||||||
[account, assets, borrowAssetsData, hlsStrategies, lendingAssetsData, prices, updatedAccount],
|
[
|
||||||
|
account,
|
||||||
|
assets,
|
||||||
|
borrowAssetsData,
|
||||||
|
hlsStrategies,
|
||||||
|
lendingAssetsData,
|
||||||
|
prices,
|
||||||
|
updatedAccount,
|
||||||
|
vaultAprs,
|
||||||
|
],
|
||||||
)
|
)
|
||||||
const isFullWidth =
|
const isFullWidth =
|
||||||
location.pathname.includes('trade') ||
|
location.pathname.includes('trade') ||
|
||||||
@ -128,7 +141,7 @@ function AccountDetails(props: Props) {
|
|||||||
data-testid='account-details'
|
data-testid='account-details'
|
||||||
className={classNames(
|
className={classNames(
|
||||||
accountDetailsExpanded ? 'right-4' : '-right-74',
|
accountDetailsExpanded ? 'right-4' : '-right-74',
|
||||||
'w-94 flex items-start gap-4 absolute top-6',
|
'w-94 flex items-start gap-4 absolute top-6 z-2',
|
||||||
!reduceMotion && 'transition-all duration-500',
|
!reduceMotion && 'transition-all duration-500',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
@ -12,6 +12,7 @@ import useAllAssets from 'hooks/assets/useAllAssets'
|
|||||||
import useHealthComputer from 'hooks/useHealthComputer'
|
import useHealthComputer from 'hooks/useHealthComputer'
|
||||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
|
import useVaultAprs from 'hooks/vaults/useVaultAprs'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { calculateAccountApr, calculateAccountBalanceValue } from 'utils/accounts'
|
import { calculateAccountApr, calculateAccountBalanceValue } from 'utils/accounts'
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ export default function AccountStats(props: Props) {
|
|||||||
const { data: account } = useAccount(accountId)
|
const { data: account } = useAccount(accountId)
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
const { data: hlsStrategies } = useHLSStakingAssets()
|
const { data: hlsStrategies } = useHLSStakingAssets()
|
||||||
|
const { data: vaultAprs } = useVaultAprs()
|
||||||
|
|
||||||
const positionBalance = useMemo(
|
const positionBalance = useMemo(
|
||||||
() => (!account ? null : calculateAccountBalanceValue(account, prices, assets)),
|
() => (!account ? null : calculateAccountBalanceValue(account, prices, assets)),
|
||||||
@ -52,9 +54,10 @@ export default function AccountStats(props: Props) {
|
|||||||
prices,
|
prices,
|
||||||
hlsStrategies,
|
hlsStrategies,
|
||||||
assets,
|
assets,
|
||||||
|
vaultAprs,
|
||||||
account.kind === 'high_levered_strategy',
|
account.kind === 'high_levered_strategy',
|
||||||
),
|
),
|
||||||
[account, assets, borrowAssetsData, hlsStrategies, lendingAssetsData, prices],
|
[account, assets, borrowAssetsData, hlsStrategies, lendingAssetsData, prices, vaultAprs],
|
||||||
)
|
)
|
||||||
|
|
||||||
const deleteAccountHandler = useCallback(() => {
|
const deleteAccountHandler = useCallback(() => {
|
||||||
|
@ -4,8 +4,8 @@ import { byDenom } from 'utils/array'
|
|||||||
|
|
||||||
export function getVaultAccountStrategiesRow(
|
export function getVaultAccountStrategiesRow(
|
||||||
vault: DepositedVault,
|
vault: DepositedVault,
|
||||||
apy: number,
|
|
||||||
prices: BNCoin[],
|
prices: BNCoin[],
|
||||||
|
apy?: number | null,
|
||||||
prev?: DepositedVault,
|
prev?: DepositedVault,
|
||||||
): AccountStrategyRow {
|
): AccountStrategyRow {
|
||||||
const { name } = vault
|
const { name } = vault
|
||||||
@ -17,7 +17,7 @@ export function getVaultAccountStrategiesRow(
|
|||||||
.plus(previous.values.unlocked)
|
.plus(previous.values.unlocked)
|
||||||
.plus(previous.values.unlocking)
|
.plus(previous.values.unlocking)
|
||||||
|
|
||||||
if (totalLockedValue.isLessThan(totalValue)) {
|
if (totalLockedValue.isLessThan(totalValue) && apy) {
|
||||||
apy = totalLockedValue.dividedBy(totalValue).times(apy).toNumber()
|
apy = totalLockedValue.dividedBy(totalValue).times(apy).toNumber()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import { useMemo } from 'react'
|
|||||||
|
|
||||||
import { getVaultAccountStrategiesRow } from 'components/account/AccountStrategiesTable/functions'
|
import { getVaultAccountStrategiesRow } from 'components/account/AccountStrategiesTable/functions'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
|
import useVaultAprs from 'hooks/vaults/useVaultAprs'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
account: Account
|
account: Account
|
||||||
@ -11,17 +12,18 @@ interface Props {
|
|||||||
export default function useAccountStategiesData(props: Props) {
|
export default function useAccountStategiesData(props: Props) {
|
||||||
const { account, updatedAccount } = props
|
const { account, updatedAccount } = props
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
|
const { data: vaultAprs } = useVaultAprs()
|
||||||
return useMemo<AccountStrategyRow[]>(() => {
|
return useMemo<AccountStrategyRow[]>(() => {
|
||||||
const usedAccount = updatedAccount ?? account
|
const usedAccount = updatedAccount ?? account
|
||||||
const accountVaults = usedAccount?.vaults ?? []
|
const accountVaults = usedAccount?.vaults ?? []
|
||||||
|
|
||||||
return accountVaults.map((vault) => {
|
return accountVaults.map((vault) => {
|
||||||
const apy = vault.apy ?? 0
|
const apy = vaultAprs.find((vaultApr) => vaultApr.address === vault.address)?.apy
|
||||||
const prevVault = updatedAccount
|
const prevVault = updatedAccount
|
||||||
? account?.vaults.find((position) => position.name === vault.name)
|
? account?.vaults.find((position) => position.name === vault.name)
|
||||||
: vault
|
: vault
|
||||||
|
|
||||||
return getVaultAccountStrategiesRow(vault, apy, prices, prevVault)
|
return getVaultAccountStrategiesRow(vault, prices, apy, prevVault)
|
||||||
})
|
})
|
||||||
}, [account, updatedAccount, prices])
|
}, [updatedAccount, account, vaultAprs, prices])
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,10 @@ import { LocalStorageKeys } from 'constants/localStorageKeys'
|
|||||||
import { BN_ZERO } from 'constants/math'
|
import { BN_ZERO } from 'constants/math'
|
||||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||||
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
||||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
|
||||||
import useHealthComputer from 'hooks/useHealthComputer'
|
import useHealthComputer from 'hooks/useHealthComputer'
|
||||||
|
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
|
import useVaultAprs from 'hooks/vaults/useVaultAprs'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { calculateAccountApr, calculateAccountLeverage } from 'utils/accounts'
|
import { calculateAccountApr, calculateAccountLeverage } from 'utils/accounts'
|
||||||
|
|
||||||
@ -36,6 +37,7 @@ export default function AccountSummary(props: Props) {
|
|||||||
storageKey,
|
storageKey,
|
||||||
defaultSetting,
|
defaultSetting,
|
||||||
)
|
)
|
||||||
|
const { data: vaultAprs } = useVaultAprs()
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
const assets = useAllAssets()
|
const assets = useAllAssets()
|
||||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||||
@ -79,16 +81,18 @@ export default function AccountSummary(props: Props) {
|
|||||||
prices,
|
prices,
|
||||||
hlsStrategies,
|
hlsStrategies,
|
||||||
assets,
|
assets,
|
||||||
|
vaultAprs,
|
||||||
props.account.kind === 'high_levered_strategy',
|
props.account.kind === 'high_levered_strategy',
|
||||||
),
|
),
|
||||||
[
|
[
|
||||||
|
updatedAccount,
|
||||||
props.account,
|
props.account,
|
||||||
assets,
|
|
||||||
borrowAssetsData,
|
borrowAssetsData,
|
||||||
hlsStrategies,
|
|
||||||
lendingAssetsData,
|
lendingAssetsData,
|
||||||
prices,
|
prices,
|
||||||
updatedAccount,
|
hlsStrategies,
|
||||||
|
assets,
|
||||||
|
vaultAprs,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { FormattedNumber } from 'components/common/FormattedNumber'
|
import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||||
import Loading from 'components/common/Loading'
|
import Loading from 'components/common/Loading'
|
||||||
|
import Text from 'components/common/Text'
|
||||||
|
|
||||||
export const APY_META = { accessorKey: 'apy', header: 'APY' }
|
export const APY_META = { accessorKey: 'apy', header: 'APY' }
|
||||||
|
|
||||||
@ -10,7 +11,9 @@ interface Props {
|
|||||||
export default function Apy(props: Props) {
|
export default function Apy(props: Props) {
|
||||||
const { vault } = props
|
const { vault } = props
|
||||||
|
|
||||||
if (vault.apy === null) return <Loading />
|
if (vault.apy === undefined) return <Loading />
|
||||||
|
if (vault.apy === null) return <Text size='xs'>N/A</Text>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormattedNumber
|
<FormattedNumber
|
||||||
amount={vault.apy ?? 0}
|
amount={vault.apy ?? 0}
|
||||||
|
@ -8,12 +8,14 @@ import useAccountId from 'hooks/useAccountId'
|
|||||||
import useChainConfig from 'hooks/useChainConfig'
|
import useChainConfig from 'hooks/useChainConfig'
|
||||||
import useDepositedVaults from 'hooks/useDepositedVaults'
|
import useDepositedVaults from 'hooks/useDepositedVaults'
|
||||||
import useVaults from 'hooks/useVaults'
|
import useVaults from 'hooks/useVaults'
|
||||||
|
import useVaultAprs from 'hooks/vaults/useVaultAprs'
|
||||||
import { VaultStatus } from 'types/enums/vault'
|
import { VaultStatus } from 'types/enums/vault'
|
||||||
|
|
||||||
function Content() {
|
function Content() {
|
||||||
const accountId = useAccountId()
|
const accountId = useAccountId()
|
||||||
const { data: vaults } = useVaults()
|
const { data: vaults } = useVaults()
|
||||||
const { data: depositedVaults } = useDepositedVaults(accountId || '')
|
const { data: depositedVaults } = useDepositedVaults(accountId || '')
|
||||||
|
const { data: vaultAprs } = useVaultAprs()
|
||||||
const chainConfig = useChainConfig()
|
const chainConfig = useChainConfig()
|
||||||
const vaultMetaData = chainConfig.vaults
|
const vaultMetaData = chainConfig.vaults
|
||||||
|
|
||||||
@ -23,18 +25,19 @@ function Content() {
|
|||||||
if (!vaults) return prev
|
if (!vaults) return prev
|
||||||
const vault = vaults.find((vault) => vault.address === curr.address)
|
const vault = vaults.find((vault) => vault.address === curr.address)
|
||||||
const depositedVault = depositedVaults?.find((vault) => vault.address === curr.address)
|
const depositedVault = depositedVaults?.find((vault) => vault.address === curr.address)
|
||||||
|
const apr = vaultAprs.find((vaultApr) => vaultApr.address === curr.address)!
|
||||||
|
|
||||||
if (depositedVault) {
|
if (depositedVault) {
|
||||||
prev.deposited.push(depositedVault)
|
prev.deposited.push({ ...depositedVault, ...apr })
|
||||||
} else if (vault) {
|
} else if (vault) {
|
||||||
prev.available.push(vault)
|
prev.available.push({ ...vault, ...apr })
|
||||||
}
|
}
|
||||||
|
|
||||||
return prev
|
return prev
|
||||||
},
|
},
|
||||||
{ deposited: [], available: [] },
|
{ deposited: [], available: [] },
|
||||||
)
|
)
|
||||||
}, [vaults, depositedVaults, vaultMetaData])
|
}, [vaultMetaData, vaults, depositedVaults, vaultAprs])
|
||||||
|
|
||||||
const unlockedVaults: DepositedVault[] = []
|
const unlockedVaults: DepositedVault[] = []
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import React from 'react'
|
|||||||
|
|
||||||
import { FormattedNumber } from 'components/common/FormattedNumber'
|
import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||||
import Loading from 'components/common/Loading'
|
import Loading from 'components/common/Loading'
|
||||||
|
import Text from 'components/common/Text'
|
||||||
import useMarket from 'hooks/markets/useMarket'
|
import useMarket from 'hooks/markets/useMarket'
|
||||||
|
|
||||||
export const APY_META = { accessorKey: 'apy', header: 'APY Range' }
|
export const APY_META = { accessorKey: 'apy', header: 'APY Range' }
|
||||||
@ -14,7 +15,8 @@ export default function Apy(props: Props) {
|
|||||||
const { vault } = props
|
const { vault } = props
|
||||||
const borrowRate = useMarket(vault.hls?.borrowDenom || '')?.apy.borrow
|
const borrowRate = useMarket(vault.hls?.borrowDenom || '')?.apy.borrow
|
||||||
|
|
||||||
if (vault.apy === null || borrowRate === null) return <Loading />
|
if (vault.apy === undefined || borrowRate === null) return <Loading />
|
||||||
|
if (vault.apy === null) return <Text size='xs'>N/A</Text>
|
||||||
|
|
||||||
const APYs = [vault.apy, vault.apy * (vault.hls?.maxLeverage || 1) - (borrowRate || 0) * 100]
|
const APYs = [vault.apy, vault.apy * (vault.hls?.maxLeverage || 1) - (borrowRate || 0) * 100]
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import useAllAssets from 'hooks/assets/useAllAssets'
|
|||||||
import useHealthComputer from 'hooks/useHealthComputer'
|
import useHealthComputer from 'hooks/useHealthComputer'
|
||||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
|
import useVaultAprs from 'hooks/vaults/useVaultAprs'
|
||||||
import { getAccountSummaryStats } from 'utils/accounts'
|
import { getAccountSummaryStats } from 'utils/accounts'
|
||||||
import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants'
|
import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants'
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ interface Props {
|
|||||||
function Content(props: Props) {
|
function Content(props: Props) {
|
||||||
const { data: account } = useAccount(props.accountId, true)
|
const { data: account } = useAccount(props.accountId, true)
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
|
const { data: vaultAprs } = useVaultAprs()
|
||||||
const { health, healthFactor } = useHealthComputer(account)
|
const { health, healthFactor } = useHealthComputer(account)
|
||||||
const data = useBorrowMarketAssetsTableData()
|
const data = useBorrowMarketAssetsTableData()
|
||||||
const borrowAssets = useMemo(() => data?.allAssets || [], [data])
|
const borrowAssets = useMemo(() => data?.allAssets || [], [data])
|
||||||
@ -37,6 +39,7 @@ function Content(props: Props) {
|
|||||||
lendingAssets,
|
lendingAssets,
|
||||||
hlsStrategies,
|
hlsStrategies,
|
||||||
assets,
|
assets,
|
||||||
|
vaultAprs,
|
||||||
account.kind === 'high_levered_strategy',
|
account.kind === 'high_levered_strategy',
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -78,7 +81,7 @@ function Content(props: Props) {
|
|||||||
sub: DEFAULT_PORTFOLIO_STATS[4].sub,
|
sub: DEFAULT_PORTFOLIO_STATS[4].sub,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}, [account, assets, borrowAssets, hlsStrategies, lendingAssets, prices])
|
}, [account, assets, borrowAssets, hlsStrategies, lendingAssets, prices, vaultAprs])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Skeleton
|
<Skeleton
|
||||||
|
@ -17,6 +17,7 @@ import useAccountId from 'hooks/useAccountId'
|
|||||||
import useHealthComputer from 'hooks/useHealthComputer'
|
import useHealthComputer from 'hooks/useHealthComputer'
|
||||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
|
import useVaultAprs from 'hooks/vaults/useVaultAprs'
|
||||||
import {
|
import {
|
||||||
calculateAccountApr,
|
calculateAccountApr,
|
||||||
calculateAccountLeverage,
|
calculateAccountLeverage,
|
||||||
@ -37,6 +38,7 @@ export default function PortfolioCard(props: Props) {
|
|||||||
const { allAssets: lendingAssets } = useLendingMarketAssetsTableData()
|
const { allAssets: lendingAssets } = useLendingMarketAssetsTableData()
|
||||||
const data = useBorrowMarketAssetsTableData()
|
const data = useBorrowMarketAssetsTableData()
|
||||||
const { data: hlsStrategies } = useHLSStakingAssets()
|
const { data: hlsStrategies } = useHLSStakingAssets()
|
||||||
|
const { data: vaultAprs } = useVaultAprs()
|
||||||
const [searchParams] = useSearchParams()
|
const [searchParams] = useSearchParams()
|
||||||
const assets = useAllAssets()
|
const assets = useAllAssets()
|
||||||
const borrowAssets = useMemo(() => data?.allAssets || [], [data])
|
const borrowAssets = useMemo(() => data?.allAssets || [], [data])
|
||||||
@ -64,9 +66,10 @@ export default function PortfolioCard(props: Props) {
|
|||||||
prices,
|
prices,
|
||||||
hlsStrategies,
|
hlsStrategies,
|
||||||
assets,
|
assets,
|
||||||
|
vaultAprs,
|
||||||
account.kind === 'high_levered_strategy',
|
account.kind === 'high_levered_strategy',
|
||||||
)
|
)
|
||||||
}, [lendingAssets, borrowAssets, prices, account, hlsStrategies, assets])
|
}, [lendingAssets, borrowAssets, prices, account, hlsStrategies, assets, vaultAprs])
|
||||||
|
|
||||||
const stats: { title: ReactNode; sub: string }[] = useMemo(() => {
|
const stats: { title: ReactNode; sub: string }[] = useMemo(() => {
|
||||||
const isLoaded = account && prices.length && apr !== null
|
const isLoaded = account && prices.length && apr !== null
|
||||||
|
@ -11,6 +11,7 @@ import useAccounts from 'hooks/accounts/useAccounts'
|
|||||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
|
import useVaultAprs from 'hooks/vaults/useVaultAprs'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { getAccountSummaryStats } from 'utils/accounts'
|
import { getAccountSummaryStats } from 'utils/accounts'
|
||||||
import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants'
|
import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants'
|
||||||
@ -24,6 +25,7 @@ export default function PortfolioSummary() {
|
|||||||
const { allAssets: lendingAssets } = useLendingMarketAssetsTableData()
|
const { allAssets: lendingAssets } = useLendingMarketAssetsTableData()
|
||||||
const { data: accounts } = useAccounts('default', urlAddress || walletAddress)
|
const { data: accounts } = useAccounts('default', urlAddress || walletAddress)
|
||||||
const { data: hlsStrategies } = useHLSStakingAssets()
|
const { data: hlsStrategies } = useHLSStakingAssets()
|
||||||
|
const { data: vaultAprs } = useVaultAprs()
|
||||||
const assets = useAllAssets()
|
const assets = useAllAssets()
|
||||||
const stats = useMemo(() => {
|
const stats = useMemo(() => {
|
||||||
if (!accounts?.length) return
|
if (!accounts?.length) return
|
||||||
@ -53,6 +55,7 @@ export default function PortfolioSummary() {
|
|||||||
lendingAssets,
|
lendingAssets,
|
||||||
hlsStrategies,
|
hlsStrategies,
|
||||||
assets,
|
assets,
|
||||||
|
vaultAprs,
|
||||||
)
|
)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
@ -93,7 +96,7 @@ export default function PortfolioSummary() {
|
|||||||
sub: 'Combined leverage',
|
sub: 'Combined leverage',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}, [accounts, assets, borrowAssets, hlsStrategies, lendingAssets, prices])
|
}, [accounts, assets, borrowAssets, hlsStrategies, lendingAssets, prices, vaultAprs])
|
||||||
|
|
||||||
if (!walletAddress && !urlAddress) return null
|
if (!walletAddress && !urlAddress) return null
|
||||||
|
|
||||||
|
40
src/hooks/vaults/useVaultAprs.ts
Normal file
40
src/hooks/vaults/useVaultAprs.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import useSWR from 'swr'
|
||||||
|
|
||||||
|
import useChainConfig from 'hooks/useChainConfig'
|
||||||
|
import { convertAprToApy } from 'utils/parsers'
|
||||||
|
|
||||||
|
export default function useVaultAprs() {
|
||||||
|
const chainConfig = useChainConfig()
|
||||||
|
|
||||||
|
return useSWR(`chains/${chainConfig.id}/vaults/aprs`, () => getAprs(chainConfig), {
|
||||||
|
fallbackData: getEmptyAprData(chainConfig),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAprs(chainConfig: ChainConfig) {
|
||||||
|
if (!chainConfig.farm) return []
|
||||||
|
try {
|
||||||
|
const response = await fetch(chainConfig.endpoints.aprs.vaults)
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const data: AprResponse = await response.json()
|
||||||
|
|
||||||
|
return data.vaults.map((aprData) => {
|
||||||
|
const finalApr = aprData.apr.projected_apr * 100
|
||||||
|
return {
|
||||||
|
address: aprData.address,
|
||||||
|
apr: finalApr,
|
||||||
|
apy: convertAprToApy(finalApr, 365),
|
||||||
|
} as Apr
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return getEmptyAprData(chainConfig, null)
|
||||||
|
} catch {
|
||||||
|
return getEmptyAprData(chainConfig, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEmptyAprData(chainConfig: ChainConfig, apr?: null) {
|
||||||
|
return chainConfig.vaults.map((vault) => ({ address: vault.address, apr: apr, apy: apr }) as Apr)
|
||||||
|
}
|
4
src/types/interfaces/account.d.ts
vendored
4
src/types/interfaces/account.d.ts
vendored
@ -20,7 +20,7 @@ interface AccountChange extends Account {
|
|||||||
|
|
||||||
interface AccountBalanceRow {
|
interface AccountBalanceRow {
|
||||||
amount: BigNumber
|
amount: BigNumber
|
||||||
apy: number
|
apy?: number | null
|
||||||
denom: string
|
denom: string
|
||||||
size: number
|
size: number
|
||||||
symbol: string
|
symbol: string
|
||||||
@ -30,7 +30,7 @@ interface AccountBalanceRow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface AccountStrategyRow {
|
interface AccountStrategyRow {
|
||||||
apy: number
|
apy?: number | null
|
||||||
name: string
|
name: string
|
||||||
denom: string
|
denom: string
|
||||||
amount: BNCoin[]
|
amount: BNCoin[]
|
||||||
|
7
src/types/interfaces/vaults.d.ts
vendored
7
src/types/interfaces/vaults.d.ts
vendored
@ -39,8 +39,8 @@ interface Vault extends VaultConfig {
|
|||||||
maxLeverage: number
|
maxLeverage: number
|
||||||
borrowDenom: string
|
borrowDenom: string
|
||||||
}
|
}
|
||||||
apy: number | null
|
apr?: number | null
|
||||||
apr: number | null
|
apy?: number | null
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VaultValuesAndAmounts {
|
interface VaultValuesAndAmounts {
|
||||||
@ -120,5 +120,6 @@ interface AprBreakdown {
|
|||||||
|
|
||||||
interface Apr {
|
interface Apr {
|
||||||
address: string
|
address: string
|
||||||
apr: number
|
apr?: number | null
|
||||||
|
apy?: number | null
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,7 @@ export const calculateAccountApr = (
|
|||||||
prices: BNCoin[],
|
prices: BNCoin[],
|
||||||
hlsStrategies: HLSStrategy[],
|
hlsStrategies: HLSStrategy[],
|
||||||
assets: Asset[],
|
assets: Asset[],
|
||||||
|
vaultAprs: Apr[],
|
||||||
isHls?: boolean,
|
isHls?: boolean,
|
||||||
): BigNumber => {
|
): BigNumber => {
|
||||||
const depositValue = calculateAccountValue('deposits', account, prices, assets)
|
const depositValue = calculateAccountValue('deposits', account, prices, assets)
|
||||||
@ -125,8 +126,10 @@ export const calculateAccountApr = (
|
|||||||
})
|
})
|
||||||
|
|
||||||
vaults?.forEach((vault) => {
|
vaults?.forEach((vault) => {
|
||||||
|
const apr = vaultAprs.find((vaultApr) => vaultApr.address === vault.address)?.apr
|
||||||
|
if (!apr) return
|
||||||
const lockedValue = vault.values.primary.plus(vault.values.secondary)
|
const lockedValue = vault.values.primary.plus(vault.values.secondary)
|
||||||
const positionInterest = lockedValue.multipliedBy(vault?.apr ?? 0).dividedBy(100)
|
const positionInterest = lockedValue.multipliedBy(apr).dividedBy(100)
|
||||||
totalVaultsInterestValue = totalVaultsInterestValue.plus(positionInterest)
|
totalVaultsInterestValue = totalVaultsInterestValue.plus(positionInterest)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -307,6 +310,7 @@ export function getAccountSummaryStats(
|
|||||||
lendingAssets: LendingMarketTableData[],
|
lendingAssets: LendingMarketTableData[],
|
||||||
hlsStrategies: HLSStrategy[],
|
hlsStrategies: HLSStrategy[],
|
||||||
assets: Asset[],
|
assets: Asset[],
|
||||||
|
vaultAprs: Apr[],
|
||||||
isHls?: boolean,
|
isHls?: boolean,
|
||||||
) {
|
) {
|
||||||
const [deposits, lends, debts, vaults] = getAccountPositionValues(account, prices, assets)
|
const [deposits, lends, debts, vaults] = getAccountPositionValues(account, prices, assets)
|
||||||
@ -318,6 +322,7 @@ export function getAccountSummaryStats(
|
|||||||
prices,
|
prices,
|
||||||
hlsStrategies,
|
hlsStrategies,
|
||||||
assets,
|
assets,
|
||||||
|
vaultAprs,
|
||||||
isHls,
|
isHls,
|
||||||
)
|
)
|
||||||
const leverage = calculateAccountLeverage(account, prices, assets)
|
const leverage = calculateAccountLeverage(account, prices, assets)
|
||||||
|
@ -5,7 +5,7 @@ export const debugSWR: Middleware = (useSWRNext: SWRHook) => (key, fetcher, conf
|
|||||||
const startTime = Date.now()
|
const startTime = Date.now()
|
||||||
const res = await fetcher!(...args)
|
const res = await fetcher!(...args)
|
||||||
process.env.NODE_ENV !== 'production' &&
|
process.env.NODE_ENV !== 'production' &&
|
||||||
console.log('⬇️ GET: ', key, ' in ', Date.now() - startTime, 'ms')
|
console.log('⬇️ GET: ', key, ' in ', Date.now() - startTime, 'ms', 'data: ', res)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
// ...
|
// ...
|
||||||
|
Loading…
Reference in New Issue
Block a user