Moved Markets data to SWR (#749)
This commit is contained in:
parent
7cfe05ebb7
commit
a00c8e391b
@ -1,41 +0,0 @@
|
||||
import getTotalActiveEmissionValue from 'api/incentives/getTotalActiveEmissionValue'
|
||||
import getMarket from 'api/markets/getMarket'
|
||||
import getUnderlyingLiquidityAmount from 'api/markets/getMarketUnderlyingLiquidityAmount'
|
||||
import getPrice from 'api/prices/getPrice'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { SECONDS_IN_A_YEAR } from 'utils/constants'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export default async function calculateAssetIncentivesApy(
|
||||
chainConfig: ChainConfig,
|
||||
denom: string,
|
||||
): Promise<BigNumber | null> {
|
||||
try {
|
||||
const [totalActiveEmissionValue, market] = await Promise.all([
|
||||
getTotalActiveEmissionValue(chainConfig, denom),
|
||||
getMarket(chainConfig, denom),
|
||||
])
|
||||
|
||||
if (!totalActiveEmissionValue) return null
|
||||
|
||||
const [marketLiquidityAmount, assetPrice] = await Promise.all([
|
||||
getUnderlyingLiquidityAmount(chainConfig, market),
|
||||
getPrice(chainConfig, denom),
|
||||
])
|
||||
|
||||
const assetDecimals = (chainConfig.assets.find(byDenom(denom)) as Asset).decimals
|
||||
|
||||
const marketLiquidityValue = BN(marketLiquidityAmount)
|
||||
.shiftedBy(-assetDecimals)
|
||||
.multipliedBy(assetPrice)
|
||||
|
||||
const marketReturns = BN(market.apy.deposit).multipliedBy(marketLiquidityValue)
|
||||
const annualEmission = totalActiveEmissionValue.multipliedBy(SECONDS_IN_A_YEAR)
|
||||
|
||||
const totalAnnualReturnsValue = annualEmission.plus(marketReturns)
|
||||
return totalAnnualReturnsValue.dividedBy(marketLiquidityValue).multipliedBy(100)
|
||||
} catch (ex) {
|
||||
console.error(ex)
|
||||
return null
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
import { cacheFn, marketCache } from 'api/cache'
|
||||
import { getParamsQueryClient, getRedBankQueryClient } from 'api/cosmwasm-client'
|
||||
import { resolveMarketResponse } from 'utils/resolvers'
|
||||
|
||||
export default async function getMarket(chainConfig: ChainConfig, denom: string): Promise<Market> {
|
||||
return cacheFn(() => fetchMarket(chainConfig, denom), marketCache, denom, 60)
|
||||
}
|
||||
|
||||
async function fetchMarket(chainConfig: ChainConfig, denom: string) {
|
||||
try {
|
||||
const redBankClient = await getRedBankQueryClient(chainConfig)
|
||||
const paramsClient = await getParamsQueryClient(chainConfig)
|
||||
|
||||
const [market, assetParams, assetCap] = await Promise.all([
|
||||
redBankClient.market({ denom }),
|
||||
paramsClient.assetParams({ denom }),
|
||||
paramsClient.totalDeposit({ denom }),
|
||||
])
|
||||
|
||||
return resolveMarketResponse(market, assetParams, assetCap)
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
import getMarketLiquidities from 'api/markets/getMarketLiquidities'
|
||||
import getMarkets from 'api/markets/getMarkets'
|
||||
import getPrices from 'api/prices/getPrices'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export default async function getMarketBorrowings(
|
||||
chainConfig: ChainConfig,
|
||||
): Promise<BorrowAsset[]> {
|
||||
const liquidities = await getMarketLiquidities(chainConfig)
|
||||
const borrowEnabledMarkets = (await getMarkets(chainConfig)).filter(
|
||||
(market: Market) => market.borrowEnabled,
|
||||
)
|
||||
const prices = await getPrices(chainConfig)
|
||||
|
||||
const borrow: BorrowAsset[] = borrowEnabledMarkets.map((market) => {
|
||||
const price = prices.find((coin) => coin.denom === market.denom)?.amount ?? '1'
|
||||
const amount = liquidities.find((coin) => coin.denom === market.denom)?.amount ?? '0'
|
||||
const asset = chainConfig.assets.find((asset) => asset.denom === market.denom)!
|
||||
|
||||
return {
|
||||
...asset,
|
||||
borrowRate: market.apy.borrow ?? 0,
|
||||
liquidity: {
|
||||
amount: BN(amount),
|
||||
value: BN(amount).multipliedBy(price),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
if (borrow) {
|
||||
return borrow
|
||||
}
|
||||
|
||||
return new Promise((_, reject) => reject('No data'))
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
import { cacheFn, underlyingDebtCache } from 'api/cache'
|
||||
import { getRedBankQueryClient } from 'api/cosmwasm-client'
|
||||
import getMarkets from 'api/markets/getMarkets'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
||||
export default async function getMarketDebts(chainConfig: ChainConfig): Promise<BNCoin[]> {
|
||||
try {
|
||||
const markets: Market[] = await getMarkets(chainConfig)
|
||||
const redBankQueryClient = await getRedBankQueryClient(chainConfig)
|
||||
|
||||
const debtQueries = markets.map((asset) =>
|
||||
cacheFn(
|
||||
() =>
|
||||
redBankQueryClient.underlyingDebtAmount({
|
||||
denom: asset.denom,
|
||||
amountScaled: asset.debtTotalScaled,
|
||||
}),
|
||||
underlyingDebtCache,
|
||||
`marketDebts/${asset.denom}/amount/${asset.debtTotalScaled}`,
|
||||
60,
|
||||
),
|
||||
)
|
||||
const debtsResults = await Promise.all(debtQueries)
|
||||
|
||||
return debtsResults.map<BNCoin>(
|
||||
(debt, index) => new BNCoin({ denom: markets[index].denom, amount: debt }),
|
||||
)
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
import getMarkets from 'api/markets/getMarkets'
|
||||
import getUnderlyingLiquidityAmount from 'api/markets/getMarketUnderlyingLiquidityAmount'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
||||
export default async function getMarketDeposits(chainConfig: ChainConfig): Promise<BNCoin[]> {
|
||||
try {
|
||||
const markets: Market[] = await getMarkets(chainConfig)
|
||||
const depositQueries = markets.map((market) =>
|
||||
getUnderlyingLiquidityAmount(chainConfig, market),
|
||||
)
|
||||
const depositsResults = await Promise.all(depositQueries)
|
||||
|
||||
return depositsResults.map<BNCoin>(
|
||||
(deposit, index) =>
|
||||
new BNCoin({
|
||||
denom: markets[index].denom,
|
||||
amount: deposit,
|
||||
}),
|
||||
)
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
import getMarketDebts from 'api/markets/getMarketDebts'
|
||||
import getMarketDeposits from 'api/markets/getMarketDeposits'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
||||
export default async function getMarketLiquidities(chainConfig: ChainConfig): Promise<BNCoin[]> {
|
||||
const deposits = await getMarketDeposits(chainConfig)
|
||||
const debts = await getMarketDebts(chainConfig)
|
||||
|
||||
const liquidity: BNCoin[] = deposits.map((deposit) => {
|
||||
const debt = debts.find((debt) => debt.denom === deposit.denom)
|
||||
|
||||
if (debt) {
|
||||
return new BNCoin({
|
||||
denom: deposit.denom,
|
||||
amount: deposit.amount.minus(debt.amount).toString(),
|
||||
})
|
||||
}
|
||||
|
||||
return new BNCoin({
|
||||
denom: deposit.denom,
|
||||
amount: '0',
|
||||
})
|
||||
})
|
||||
|
||||
if (liquidity) {
|
||||
return liquidity
|
||||
}
|
||||
|
||||
return new Promise((_, reject) => reject('No data'))
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
import { cacheFn, underlyingLiquidityAmountCache } from 'api/cache'
|
||||
import { getRedBankQueryClient } from 'api/cosmwasm-client'
|
||||
|
||||
export default async function getUnderlyingLiquidityAmount(
|
||||
chainConfig: ChainConfig,
|
||||
market: Market,
|
||||
): Promise<string> {
|
||||
return cacheFn(
|
||||
() => fetchUnderlyingLiquidityAmount(chainConfig, market),
|
||||
underlyingLiquidityAmountCache,
|
||||
`underlyingLiquidity/${market.denom}/amount/${market.collateralTotalScaled}`,
|
||||
60,
|
||||
)
|
||||
}
|
||||
|
||||
async function fetchUnderlyingLiquidityAmount(chainConfig: ChainConfig, market: Market) {
|
||||
try {
|
||||
const client = await getRedBankQueryClient(chainConfig)
|
||||
return await client.underlyingLiquidityAmount({
|
||||
denom: market.denom,
|
||||
amountScaled: market.collateralTotalScaled,
|
||||
})
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
import { allParamsCache, cacheFn, marketsCache, totalDepositCache } from 'api/cache'
|
||||
import { getParamsQueryClient, getRedBankQueryClient } from 'api/cosmwasm-client'
|
||||
import {
|
||||
AssetParamsBaseForAddr as AssetParams,
|
||||
TotalDepositResponse,
|
||||
} from 'types/generated/mars-params/MarsParams.types'
|
||||
import { Market as RedBankMarket } from 'types/generated/mars-red-bank/MarsRedBank.types'
|
||||
import { byDenom } from 'utils/array'
|
||||
import iterateContractQuery from 'utils/iterateContractQuery'
|
||||
import { resolveMarketResponse } from 'utils/resolvers'
|
||||
|
||||
export default async function getMarkets(chainConfig: ChainConfig): Promise<Market[]> {
|
||||
try {
|
||||
const redBankClient = await getRedBankQueryClient(chainConfig)
|
||||
const paramsClient = await getParamsQueryClient(chainConfig)
|
||||
|
||||
const marketAssets = chainConfig.assets.filter((asset) => asset.isMarket)
|
||||
|
||||
const capQueries = marketAssets
|
||||
.filter((asset) => asset.isMarket)
|
||||
.map((asset) =>
|
||||
cacheFn(
|
||||
() => paramsClient.totalDeposit({ denom: asset.denom }),
|
||||
totalDepositCache,
|
||||
`chains/${chainConfig.id}/enabledMarkets/${asset.denom}`,
|
||||
60,
|
||||
),
|
||||
)
|
||||
|
||||
const caps = await Promise.all(capQueries)
|
||||
|
||||
const [markets, assetParams, assetCaps] = await Promise.all([
|
||||
cacheFn(
|
||||
() => iterateContractQuery(redBankClient.markets),
|
||||
marketsCache,
|
||||
`chains/${chainConfig.id}/markets`,
|
||||
60,
|
||||
),
|
||||
cacheFn(
|
||||
async () => await iterateContractQuery(paramsClient.allAssetParams),
|
||||
allParamsCache,
|
||||
`chains/${chainConfig.id}/params`,
|
||||
60,
|
||||
),
|
||||
Promise.all(capQueries),
|
||||
])
|
||||
|
||||
return marketAssets.map((asset) =>
|
||||
resolveMarketResponse(
|
||||
markets.find(byDenom(asset.denom)) as RedBankMarket,
|
||||
assetParams.find(byDenom(asset.denom)) as AssetParams,
|
||||
assetCaps.find(byDenom(asset.denom)) as TotalDepositResponse,
|
||||
),
|
||||
)
|
||||
} catch (ex) {
|
||||
console.log(ex)
|
||||
throw ex
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
|
||||
import AssetsSelect from 'components/Modals/AssetsSelect'
|
||||
import SearchBar from 'components/common/SearchBar'
|
||||
import Text from 'components/common/Text'
|
||||
import useMarketBorrowings from 'hooks/markets/useMarketBorrowings'
|
||||
import AssetsSelect from 'components/Modals/AssetsSelect'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import useStore from 'store'
|
||||
|
||||
interface Props {
|
||||
@ -14,16 +14,16 @@ interface Props {
|
||||
|
||||
export default function AddVaultAssetsModalContent(props: Props) {
|
||||
const [searchString, setSearchString] = useState<string>('')
|
||||
const { data: borrowAssets } = useMarketBorrowings()
|
||||
const markets = useMarkets()
|
||||
|
||||
const filteredBorrowAssets: BorrowAsset[] = useMemo(() => {
|
||||
return borrowAssets.filter(
|
||||
(asset) =>
|
||||
asset.name.toLowerCase().includes(searchString.toLowerCase()) ||
|
||||
asset.denom.toLowerCase().includes(searchString.toLowerCase()) ||
|
||||
asset.symbol.toLowerCase().includes(searchString.toLowerCase()),
|
||||
const filteredMarkets: Market[] = useMemo(() => {
|
||||
return markets.filter(
|
||||
(market) =>
|
||||
market.asset.name.toLowerCase().includes(searchString.toLowerCase()) ||
|
||||
market.asset.denom.toLowerCase().includes(searchString.toLowerCase()) ||
|
||||
market.asset.symbol.toLowerCase().includes(searchString.toLowerCase()),
|
||||
)
|
||||
}, [borrowAssets, searchString])
|
||||
}, [markets, searchString])
|
||||
|
||||
function onChangeSearchString(value: string) {
|
||||
setSearchString(value)
|
||||
@ -31,21 +31,21 @@ export default function AddVaultAssetsModalContent(props: Props) {
|
||||
|
||||
const [poolAssets, stableAssets] = useMemo(
|
||||
() =>
|
||||
filteredBorrowAssets.reduce(
|
||||
(acc, asset) => {
|
||||
filteredMarkets.reduce(
|
||||
(acc, market) => {
|
||||
if (
|
||||
asset.denom === props.vault.denoms.primary ||
|
||||
asset.denom === props.vault.denoms.secondary
|
||||
market.asset.denom === props.vault.denoms.primary ||
|
||||
market.asset.denom === props.vault.denoms.secondary
|
||||
) {
|
||||
acc[0].push(asset)
|
||||
} else if (asset.isStable) {
|
||||
acc[1].push(asset)
|
||||
acc[0].push(market.asset)
|
||||
} else if (market.asset.isStable) {
|
||||
acc[1].push(market.asset)
|
||||
}
|
||||
return acc
|
||||
},
|
||||
[[], []] as [BorrowAsset[], BorrowAsset[]],
|
||||
[[], []] as [Asset[], Asset[]],
|
||||
),
|
||||
[filteredBorrowAssets, props.vault.denoms.primary, props.vault.denoms.secondary],
|
||||
[filteredMarkets, props.vault.denoms.primary, props.vault.denoms.secondary],
|
||||
)
|
||||
|
||||
const selectedDenoms = useStore((s) => s.addVaultBorrowingsModal?.selectedDenoms)
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { RowSelectionState } from '@tanstack/react-table'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
|
||||
import useAssetSelectColumns from 'components/Modals/AssetsSelect/Columns/useAssetSelectColumns'
|
||||
import Table from 'components/common/Table'
|
||||
import useAssetSelectColumns from 'components/Modals/AssetsSelect/Columns/useAssetSelectColumns'
|
||||
import useGetCoinValue from 'hooks/assets/useGetCoinValue'
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
// TODO: Pass the market data directly here instead of the assets
|
||||
interface Props {
|
||||
assets: Asset[]
|
||||
onChangeSelected: (selected: string[]) => void
|
||||
@ -20,12 +21,11 @@ interface Props {
|
||||
export default function AssetsSelect(props: Props) {
|
||||
const { assets, onChangeSelected, selectedDenoms, isBorrow } = props
|
||||
const columns = useAssetSelectColumns(isBorrow)
|
||||
const { data: markets } = useMarketAssets()
|
||||
const markets = useMarkets()
|
||||
const getCoinValue = useGetCoinValue()
|
||||
|
||||
const defaultSelected = useMemo(() => {
|
||||
const selectableAssets = assets
|
||||
return selectableAssets.reduce(
|
||||
return assets.reduce(
|
||||
(acc, asset, index) => {
|
||||
if (selectedDenoms?.includes(asset.denom)) {
|
||||
acc[index] = true
|
||||
@ -48,7 +48,7 @@ export default function AssetsSelect(props: Props) {
|
||||
asset,
|
||||
balance: balancesForAsset?.amount ?? '0',
|
||||
value,
|
||||
market: markets.find((market) => market.denom === asset.denom),
|
||||
market: markets.find((market) => market.asset.denom === asset.denom),
|
||||
}
|
||||
})
|
||||
}, [balances, assets, markets, getCoinValue])
|
||||
|
@ -16,7 +16,7 @@ import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSli
|
||||
import Modal from 'components/Modals/Modal'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import useAutoLend from 'hooks/useAutoLend'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import useToggle from 'hooks/useToggle'
|
||||
@ -91,7 +91,7 @@ function BorrowModal(props: Props) {
|
||||
const isAutoLendEnabled = autoLendEnabledAccountIds.includes(account.id)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(account)
|
||||
const totalDebt = BN(getDebtAmount(modal))
|
||||
const { data: marketAssets } = useMarketAssets()
|
||||
const markets = useMarkets()
|
||||
|
||||
const [depositBalance, lendBalance] = useMemo(
|
||||
() => [
|
||||
@ -107,13 +107,13 @@ function BorrowModal(props: Props) {
|
||||
)
|
||||
|
||||
const overpayExeedsCap = useMemo(() => {
|
||||
const marketAsset = marketAssets.find(byDenom(asset.denom))
|
||||
const marketAsset = markets.find(byDenom(asset.denom))
|
||||
if (!marketAsset) return
|
||||
const overpayAmount = totalDebtRepayAmount.minus(totalDebt)
|
||||
const marketCapAfterOverpay = marketAsset.cap.used.plus(overpayAmount)
|
||||
|
||||
return marketAsset.cap.max.isLessThanOrEqualTo(marketCapAfterOverpay)
|
||||
}, [marketAssets, asset.denom, totalDebt, totalDebtRepayAmount])
|
||||
}, [markets, asset.denom, totalDebt, totalDebtRepayAmount])
|
||||
|
||||
const maxRepayAmount = useMemo(() => {
|
||||
const maxBalance = repayFromWallet
|
||||
@ -187,7 +187,7 @@ function BorrowModal(props: Props) {
|
||||
? BN_ZERO
|
||||
: computeMaxBorrowAmount(asset.denom, borrowToWallet ? 'wallet' : 'deposit')
|
||||
|
||||
return BigNumber.min(maxBorrowAmount, modal.marketData?.liquidity?.amount || 0)
|
||||
return BigNumber.min(maxBorrowAmount, modal.marketData?.liquidity || 0)
|
||||
}, [asset.denom, borrowToWallet, computeMaxBorrowAmount, isRepay, modal.marketData])
|
||||
|
||||
useEffect(() => {
|
||||
@ -266,7 +266,7 @@ function BorrowModal(props: Props) {
|
||||
<div className='flex gap-2'>
|
||||
<FormattedNumber
|
||||
className='text-xs'
|
||||
amount={modal.marketData?.liquidity?.amount.toNumber() ?? 0}
|
||||
amount={modal.marketData?.liquidity.toNumber() ?? 0}
|
||||
options={{ decimals: asset.decimals, abbreviated: true, suffix: ` ${asset.symbol}` }}
|
||||
animate
|
||||
/>
|
||||
@ -274,7 +274,7 @@ function BorrowModal(props: Props) {
|
||||
className='text-xs'
|
||||
coin={BNCoin.fromDenomAndBigNumber(
|
||||
asset.denom,
|
||||
modal.marketData?.liquidity?.amount ?? BN_ZERO,
|
||||
modal.marketData?.liquidity ?? BN_ZERO,
|
||||
)}
|
||||
parentheses
|
||||
/>
|
||||
|
@ -2,13 +2,13 @@ import React, { useMemo } from 'react'
|
||||
|
||||
import Button from 'components/common/Button'
|
||||
import { ArrowRight } from 'components/common/Icons'
|
||||
import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary'
|
||||
import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
|
||||
import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary'
|
||||
import { getLeveragedApy } from 'utils/math'
|
||||
|
||||
interface Props {
|
||||
amount: BigNumber
|
||||
asset: BorrowAsset
|
||||
borrowMarket: Market
|
||||
max: BigNumber
|
||||
onChangeAmount: (amount: BigNumber) => void
|
||||
onClickBtn: () => void
|
||||
@ -21,15 +21,15 @@ interface Props {
|
||||
|
||||
export default function Leverage(props: Props) {
|
||||
const apy = useMemo(() => {
|
||||
if (!props.asset.borrowRate) return 0
|
||||
return getLeveragedApy(props.baseApy, props.asset.borrowRate, props.leverage)
|
||||
}, [props.asset.borrowRate, props.baseApy, props.leverage])
|
||||
if (!props.borrowMarket.apy.borrow) return 0
|
||||
return getLeveragedApy(props.baseApy, props.borrowMarket.apy.borrow, props.leverage)
|
||||
}, [props.baseApy, props.borrowMarket.apy.borrow, props.leverage])
|
||||
|
||||
return (
|
||||
<div id='item-1' className='flex-col gap-6 flex justify-between h-full p-4'>
|
||||
<TokenInputWithSlider
|
||||
amount={props.amount}
|
||||
asset={props.asset}
|
||||
asset={props.borrowMarket.asset}
|
||||
max={props.max}
|
||||
onChange={props.onChangeAmount}
|
||||
maxText='Max borrow'
|
||||
@ -40,7 +40,11 @@ export default function Leverage(props: Props) {
|
||||
warningMessages={props.warningMessages}
|
||||
/>
|
||||
<div className='flex flex-col gap-6'>
|
||||
<LeverageSummary asset={props.asset} positionValue={props.positionValue} apy={apy} />
|
||||
<LeverageSummary
|
||||
asset={props.borrowMarket.asset}
|
||||
positionValue={props.positionValue}
|
||||
apy={apy}
|
||||
/>
|
||||
<Button onClick={props.onClickBtn} text='Continue' rightIcon={<ArrowRight />} />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useMemo } from 'react'
|
||||
|
||||
import SummaryItems from 'components/common/SummaryItems'
|
||||
import useBorrowAsset from 'hooks/useBorrowAsset'
|
||||
import useMarket from 'hooks/markets/useMarket'
|
||||
|
||||
interface Props {
|
||||
asset: Asset
|
||||
@ -10,7 +10,7 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function LeverageSummary(props: Props) {
|
||||
const borrowAsset = useBorrowAsset(props.asset.denom)
|
||||
const market = useMarket(props.asset.denom)
|
||||
|
||||
const items: SummaryItem[] = useMemo(() => {
|
||||
return [
|
||||
@ -21,7 +21,7 @@ export default function LeverageSummary(props: Props) {
|
||||
},
|
||||
{
|
||||
title: `Borrow APR ${props.asset.symbol}`,
|
||||
amount: borrowAsset?.borrowRate || 0,
|
||||
amount: market?.apy.borrow || 0,
|
||||
options: { suffix: '%', minDecimals: 2, maxDecimals: 2 },
|
||||
},
|
||||
{
|
||||
@ -30,7 +30,7 @@ export default function LeverageSummary(props: Props) {
|
||||
options: { prefix: '$' },
|
||||
},
|
||||
]
|
||||
}, [borrowAsset?.borrowRate, props.apy, props.asset.symbol, props.positionValue])
|
||||
}, [market?.apy.borrow, props.apy, props.asset.symbol, props.positionValue])
|
||||
|
||||
return <SummaryItems items={items} />
|
||||
}
|
||||
|
@ -4,13 +4,12 @@ import Button from 'components/common/Button'
|
||||
import { ArrowRight } from 'components/common/Icons'
|
||||
import AssetSummary from 'components/Modals/HLS/Deposit/Summary/AssetSummary'
|
||||
import YourPosition from 'components/Modals/HLS/Deposit/Summary/YourPosition'
|
||||
import useBorrowAsset from 'hooks/useBorrowAsset'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
||||
interface Props {
|
||||
apy: number
|
||||
borrowAmount: BigNumber
|
||||
borrowAsset: Asset
|
||||
borrowMarket: Market
|
||||
collateralAsset: Asset
|
||||
depositAmount: BigNumber
|
||||
leverage: number
|
||||
@ -20,18 +19,14 @@ interface Props {
|
||||
}
|
||||
|
||||
export default function Summary(props: Props) {
|
||||
const borrowAsset = useBorrowAsset(props.borrowAsset.denom)
|
||||
|
||||
if (!borrowAsset) return null
|
||||
|
||||
return (
|
||||
<div id='item-3' className='p-4 flex flex-col gap-4'>
|
||||
<AssetSummary asset={props.collateralAsset} amount={props.depositAmount} />
|
||||
<AssetSummary asset={borrowAsset} amount={props.borrowAmount} isBorrow />
|
||||
<AssetSummary asset={props.borrowMarket.asset} amount={props.borrowAmount} isBorrow />
|
||||
<YourPosition
|
||||
positionValue={BNCoin.fromDenomAndBigNumber('usd', props.positionValue)}
|
||||
baseApy={props.apy || 0}
|
||||
borrowRate={borrowAsset.borrowRate || 0}
|
||||
borrowRate={props.borrowMarket.apy.borrow || 0}
|
||||
leverage={props.leverage}
|
||||
/>
|
||||
<Button
|
||||
|
@ -13,7 +13,7 @@ import useStore from 'store'
|
||||
import { isAccountEmpty } from 'utils/accounts'
|
||||
|
||||
interface Props {
|
||||
borrowAsset: BorrowAsset
|
||||
borrowMarket: Market
|
||||
collateralAsset: Asset
|
||||
vaultAddress: string | null
|
||||
strategy?: HLSStrategy
|
||||
@ -42,7 +42,7 @@ export default function Controller(props: Props) {
|
||||
walletCollateralAsset={walletCollateralAsset}
|
||||
vault={vault}
|
||||
collateralAsset={props.collateralAsset}
|
||||
borrowAsset={props.borrowAsset}
|
||||
borrowMarket={props.borrowMarket}
|
||||
emptyHlsAccounts={emptyHlsAccounts}
|
||||
hlsAccounts={hlsAccounts}
|
||||
isOpen={isOpen}
|
||||
@ -57,7 +57,7 @@ export default function Controller(props: Props) {
|
||||
<StakingContent
|
||||
walletCollateralAsset={walletCollateralAsset}
|
||||
collateralAsset={props.collateralAsset}
|
||||
borrowAsset={props.borrowAsset}
|
||||
borrowMarket={props.borrowMarket}
|
||||
emptyHlsAccounts={emptyHlsAccounts}
|
||||
hlsAccounts={hlsAccounts}
|
||||
isOpen={isOpen}
|
||||
@ -73,7 +73,7 @@ export default function Controller(props: Props) {
|
||||
}
|
||||
|
||||
interface ContentProps {
|
||||
borrowAsset: BorrowAsset
|
||||
borrowMarket: Market
|
||||
collateralAsset: Asset
|
||||
emptyHlsAccounts: Account[]
|
||||
hlsAccounts: Account[]
|
||||
@ -102,14 +102,14 @@ function Vault(props: VaultContentProps) {
|
||||
} = useVaultController({
|
||||
vault: props.vault,
|
||||
collateralAsset: props.collateralAsset,
|
||||
borrowAsset: props.borrowAsset,
|
||||
borrowMarket: props.borrowMarket,
|
||||
selectedAccount: props.selectedAccount,
|
||||
})
|
||||
|
||||
const items = useAccordionItems({
|
||||
apy: props.vault.apy || 0,
|
||||
borrowAmount,
|
||||
borrowAsset: props.borrowAsset,
|
||||
borrowMarket: props.borrowMarket,
|
||||
collateralAsset: props.collateralAsset,
|
||||
depositAmount,
|
||||
emptyHlsAccounts: props.emptyHlsAccounts,
|
||||
@ -148,13 +148,13 @@ function StakingContent(props: StakingContentProps) {
|
||||
execute,
|
||||
} = useStakingController({
|
||||
collateralAsset: props.collateralAsset,
|
||||
borrowAsset: props.borrowAsset,
|
||||
borrowMarket: props.borrowMarket,
|
||||
selectedAccount: props.selectedAccount,
|
||||
})
|
||||
|
||||
const items = useAccordionItems({
|
||||
borrowAmount,
|
||||
borrowAsset: props.borrowAsset,
|
||||
borrowMarket: props.borrowMarket,
|
||||
collateralAsset: props.collateralAsset,
|
||||
depositAmount,
|
||||
emptyHlsAccounts: props.emptyHlsAccounts,
|
||||
|
@ -26,7 +26,7 @@ import {
|
||||
interface Props {
|
||||
apy: number
|
||||
borrowAmount: BigNumber
|
||||
borrowAsset: BorrowAsset
|
||||
borrowMarket: Market
|
||||
collateralAsset: Asset
|
||||
depositAmount: BigNumber
|
||||
emptyHlsAccounts: Account[]
|
||||
@ -56,18 +56,24 @@ export default function useAccordionItems(props: Props) {
|
||||
}, [props.strategy])
|
||||
|
||||
const borrowLiquidity = useMemo(
|
||||
() => props.borrowAsset.liquidity?.amount || BN_ZERO,
|
||||
[props.borrowAsset.liquidity?.amount],
|
||||
() => props.borrowMarket.liquidity || BN_ZERO,
|
||||
[props.borrowMarket.liquidity],
|
||||
)
|
||||
|
||||
const additionalDepositFromSwap = useMemo(() => {
|
||||
const value = getCoinValue(
|
||||
BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, props.borrowAmount),
|
||||
BNCoin.fromDenomAndBigNumber(props.borrowMarket.asset.denom, props.borrowAmount),
|
||||
prices,
|
||||
assets,
|
||||
)
|
||||
return getCoinAmount(props.collateralAsset.denom, value, prices, assets)
|
||||
}, [assets, prices, props.borrowAmount, props.borrowAsset.denom, props.collateralAsset.denom])
|
||||
}, [
|
||||
assets,
|
||||
prices,
|
||||
props.borrowAmount,
|
||||
props.borrowMarket.asset.denom,
|
||||
props.collateralAsset.denom,
|
||||
])
|
||||
|
||||
const collateralWarningMessages = useMemo(() => {
|
||||
const messages: string[] = []
|
||||
@ -96,16 +102,23 @@ export default function useAccordionItems(props: Props) {
|
||||
|
||||
if (props.borrowAmount.isGreaterThan(props.maxBorrowAmount)) {
|
||||
messages.push(
|
||||
getHealthFactorMessage(props.borrowAsset.denom, props.maxBorrowAmount, 'borrow', assets),
|
||||
getHealthFactorMessage(
|
||||
props.borrowMarket.asset.denom,
|
||||
props.maxBorrowAmount,
|
||||
'borrow',
|
||||
assets,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if (props.borrowAmount.isGreaterThan(borrowLiquidity)) {
|
||||
messages.push(getLiquidityMessage(props.borrowAsset.denom, borrowLiquidity, assets))
|
||||
messages.push(getLiquidityMessage(props.borrowMarket.asset.denom, borrowLiquidity, assets))
|
||||
}
|
||||
|
||||
if (additionalDepositFromSwap.plus(props.depositAmount).isGreaterThan(props.maxBorrowAmount)) {
|
||||
messages.push(getDepositCapMessage(props.borrowAsset.denom, depositCapLeft, 'borrow', assets))
|
||||
messages.push(
|
||||
getDepositCapMessage(props.borrowMarket.asset.denom, depositCapLeft, 'borrow', assets),
|
||||
)
|
||||
}
|
||||
|
||||
return messages
|
||||
@ -115,7 +128,7 @@ export default function useAccordionItems(props: Props) {
|
||||
borrowLiquidity,
|
||||
depositCapLeft,
|
||||
props.borrowAmount,
|
||||
props.borrowAsset.denom,
|
||||
props.borrowMarket.asset.denom,
|
||||
props.depositAmount,
|
||||
props.maxBorrowAmount,
|
||||
])
|
||||
@ -160,7 +173,7 @@ export default function useAccordionItems(props: Props) {
|
||||
<Leverage
|
||||
leverage={props.leverage}
|
||||
amount={props.borrowAmount}
|
||||
asset={props.borrowAsset}
|
||||
borrowMarket={props.borrowMarket}
|
||||
onChangeAmount={props.onChangeDebt}
|
||||
onClickBtn={() => props.toggleIsOpen(2)}
|
||||
max={props.maxBorrowAmount}
|
||||
@ -228,7 +241,7 @@ export default function useAccordionItems(props: Props) {
|
||||
leverage={props.leverage}
|
||||
positionValue={props.positionValue}
|
||||
collateralAsset={props.collateralAsset}
|
||||
borrowAsset={props.borrowAsset}
|
||||
borrowMarket={props.borrowMarket}
|
||||
apy={props.apy}
|
||||
onClickBtn={props.execute}
|
||||
disabled={
|
||||
|
@ -10,17 +10,17 @@ import { SWAP_FEE_BUFFER } from 'utils/constants'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
interface Props {
|
||||
borrowAsset: Asset
|
||||
borrowMarket: Market
|
||||
collateralAsset: Asset
|
||||
selectedAccount: Account
|
||||
}
|
||||
|
||||
export default function useStakingController(props: Props) {
|
||||
const { collateralAsset, borrowAsset, selectedAccount } = props
|
||||
const { collateralAsset, borrowMarket, selectedAccount } = props
|
||||
const addToStakingStrategy = useStore((s) => s.addToStakingStrategy)
|
||||
|
||||
const { data: swapValueLoss } = useSwapValueLoss(
|
||||
props.borrowAsset.denom,
|
||||
props.borrowMarket.asset.denom,
|
||||
props.collateralAsset.denom,
|
||||
)
|
||||
const {
|
||||
@ -33,34 +33,39 @@ export default function useStakingController(props: Props) {
|
||||
actions,
|
||||
} = useDepositHlsVault({
|
||||
collateralDenom: collateralAsset.denom,
|
||||
borrowDenom: borrowAsset.denom,
|
||||
borrowDenom: borrowMarket.asset.denom,
|
||||
})
|
||||
|
||||
const { updatedAccount, addDeposits } = useUpdatedAccount(selectedAccount)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount)
|
||||
|
||||
const maxBorrowAmount = useMemo(() => {
|
||||
return computeMaxBorrowAmount(props.borrowAsset.denom, {
|
||||
return computeMaxBorrowAmount(props.borrowMarket.asset.denom, {
|
||||
swap: {
|
||||
denom_out: props.collateralAsset.denom,
|
||||
slippage: BN(swapValueLoss).plus(SWAP_FEE_BUFFER).toString(),
|
||||
},
|
||||
})
|
||||
}, [computeMaxBorrowAmount, props.borrowAsset.denom, props.collateralAsset.denom, swapValueLoss])
|
||||
}, [
|
||||
computeMaxBorrowAmount,
|
||||
props.borrowMarket.asset.denom,
|
||||
props.collateralAsset.denom,
|
||||
swapValueLoss,
|
||||
])
|
||||
|
||||
const execute = useCallback(() => {
|
||||
useStore.setState({ hlsModal: null })
|
||||
addToStakingStrategy({
|
||||
actions,
|
||||
accountId: selectedAccount.id,
|
||||
borrowCoin: BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount),
|
||||
borrowCoin: BNCoin.fromDenomAndBigNumber(borrowMarket.asset.denom, borrowAmount),
|
||||
depositCoin: BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount),
|
||||
})
|
||||
}, [
|
||||
actions,
|
||||
addToStakingStrategy,
|
||||
borrowAmount,
|
||||
borrowAsset.denom,
|
||||
borrowMarket.asset.denom,
|
||||
collateralAsset.denom,
|
||||
depositAmount,
|
||||
selectedAccount.id,
|
||||
|
@ -8,14 +8,14 @@ import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
||||
interface Props {
|
||||
borrowAsset: Asset
|
||||
borrowMarket: Market
|
||||
collateralAsset: Asset
|
||||
selectedAccount: Account
|
||||
vault: Vault
|
||||
}
|
||||
|
||||
export default function useVaultController(props: Props) {
|
||||
const { vault, collateralAsset, borrowAsset, selectedAccount } = props
|
||||
const { vault, collateralAsset, borrowMarket, selectedAccount } = props
|
||||
|
||||
const depositIntoVault = useStore((s) => s.depositIntoVault)
|
||||
|
||||
@ -28,14 +28,14 @@ export default function useVaultController(props: Props) {
|
||||
positionValue,
|
||||
} = useDepositHlsVault({
|
||||
collateralDenom: collateralAsset.denom,
|
||||
borrowDenom: borrowAsset.denom,
|
||||
borrowDenom: borrowMarket.asset.denom,
|
||||
})
|
||||
|
||||
const { actions } = useDepositVault({
|
||||
vault,
|
||||
reclaims: [],
|
||||
deposits: [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)],
|
||||
borrowings: [BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount)],
|
||||
borrowings: [BNCoin.fromDenomAndBigNumber(borrowMarket.asset.denom, borrowAmount)],
|
||||
kind: 'high_levered_strategy',
|
||||
})
|
||||
|
||||
@ -43,17 +43,17 @@ export default function useVaultController(props: Props) {
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount)
|
||||
|
||||
const maxBorrowAmount = useMemo(() => {
|
||||
return computeMaxBorrowAmount(props.borrowAsset.denom, {
|
||||
return computeMaxBorrowAmount(props.borrowMarket.asset.denom, {
|
||||
vault: { address: props.vault?.address },
|
||||
}).plus(borrowAmount)
|
||||
}, [borrowAmount, computeMaxBorrowAmount, props.borrowAsset.denom, props.vault?.address])
|
||||
}, [borrowAmount, computeMaxBorrowAmount, props.borrowMarket.asset.denom, props.vault?.address])
|
||||
|
||||
const execute = useCallback(() => {
|
||||
depositIntoVault({
|
||||
accountId: selectedAccount.id,
|
||||
actions,
|
||||
deposits: [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)],
|
||||
borrowings: [BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount)],
|
||||
borrowings: [BNCoin.fromDenomAndBigNumber(borrowMarket.asset.denom, borrowAmount)],
|
||||
isCreate: true,
|
||||
kind: 'high_levered_strategy',
|
||||
})
|
||||
@ -63,7 +63,7 @@ export default function useVaultController(props: Props) {
|
||||
borrowAmount,
|
||||
depositAmount,
|
||||
depositIntoVault,
|
||||
borrowAsset.denom,
|
||||
borrowMarket.asset.denom,
|
||||
collateralAsset.denom,
|
||||
selectedAccount.id,
|
||||
])
|
||||
@ -75,12 +75,12 @@ export default function useVaultController(props: Props) {
|
||||
simulateVaultDeposit(
|
||||
vault.address,
|
||||
[BNCoin.fromDenomAndBigNumber(collateralAsset.denom, amount)],
|
||||
[BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount)],
|
||||
[BNCoin.fromDenomAndBigNumber(borrowMarket.asset.denom, borrowAmount)],
|
||||
)
|
||||
},
|
||||
[
|
||||
borrowAmount,
|
||||
borrowAsset,
|
||||
borrowMarket,
|
||||
collateralAsset,
|
||||
vault.address,
|
||||
setDepositAmount,
|
||||
@ -95,11 +95,11 @@ export default function useVaultController(props: Props) {
|
||||
simulateVaultDeposit(
|
||||
vault.address,
|
||||
[BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)],
|
||||
[BNCoin.fromDenomAndBigNumber(borrowAsset.denom, amount)],
|
||||
[BNCoin.fromDenomAndBigNumber(borrowMarket.asset.denom, amount)],
|
||||
)
|
||||
},
|
||||
[
|
||||
borrowAsset,
|
||||
borrowMarket,
|
||||
collateralAsset,
|
||||
depositAmount,
|
||||
vault.address,
|
||||
|
@ -1,8 +1,8 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react'
|
||||
|
||||
import Button from 'components/common/Button'
|
||||
import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary'
|
||||
import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
|
||||
import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
import { LocalStorageKeys } from 'constants/localStorageKeys'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
@ -23,7 +23,7 @@ import { getDepositCapMessage, getHealthFactorMessage, getLiquidityMessage } fro
|
||||
interface Props {
|
||||
account: HLSAccountWithStrategy
|
||||
action: HlsStakingManageAction
|
||||
borrowAsset: BorrowAsset
|
||||
borrowMarket: Market
|
||||
collateralAsset: Asset
|
||||
}
|
||||
|
||||
@ -42,19 +42,24 @@ export default function ChangeLeverage(props: Props) {
|
||||
const changeHlsStakingLeverage = useStore((s) => s.changeHlsStakingLeverage)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(props.account)
|
||||
const previousDebt: BigNumber = useMemo(
|
||||
() => props.account.debts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO,
|
||||
[props.account.debts, props.borrowAsset.denom],
|
||||
() => props.account.debts.find(byDenom(props.borrowMarket.asset.denom))?.amount || BN_ZERO,
|
||||
[props.account.debts, props.borrowMarket.asset.denom],
|
||||
)
|
||||
|
||||
const [currentDebt, setAmount] = useState(previousDebt)
|
||||
const maxBorrowAmount = useMemo(() => {
|
||||
return computeMaxBorrowAmount(props.borrowAsset.denom, {
|
||||
return computeMaxBorrowAmount(props.borrowMarket.asset.denom, {
|
||||
swap: {
|
||||
denom_out: props.collateralAsset.denom,
|
||||
slippage: SWAP_FEE_BUFFER.toString(),
|
||||
},
|
||||
}).plus(previousDebt)
|
||||
}, [computeMaxBorrowAmount, previousDebt, props.borrowAsset.denom, props.collateralAsset.denom])
|
||||
}, [
|
||||
computeMaxBorrowAmount,
|
||||
previousDebt,
|
||||
props.borrowMarket.asset.denom,
|
||||
props.collateralAsset.denom,
|
||||
])
|
||||
|
||||
const onChangeAmount = useCallback(
|
||||
(currentDebt: BigNumber) => {
|
||||
@ -62,19 +67,22 @@ export default function ChangeLeverage(props: Props) {
|
||||
if (currentDebt.isLessThan(previousDebt)) {
|
||||
simulateHlsStakingWithdraw(
|
||||
props.collateralAsset.denom,
|
||||
props.borrowAsset.denom,
|
||||
props.borrowMarket.asset.denom,
|
||||
previousDebt.minus(currentDebt),
|
||||
)
|
||||
} else {
|
||||
simulateHlsStakingDeposit(
|
||||
BNCoin.fromDenomAndBigNumber(props.collateralAsset.denom, BN_ZERO),
|
||||
BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, currentDebt.minus(previousDebt)),
|
||||
BNCoin.fromDenomAndBigNumber(
|
||||
props.borrowMarket.asset.denom,
|
||||
currentDebt.minus(previousDebt),
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
[
|
||||
previousDebt,
|
||||
props.borrowAsset.denom,
|
||||
props.borrowMarket.asset.denom,
|
||||
props.collateralAsset.denom,
|
||||
simulateHlsStakingDeposit,
|
||||
simulateHlsStakingWithdraw,
|
||||
@ -98,7 +106,7 @@ export default function ChangeLeverage(props: Props) {
|
||||
previousDebt,
|
||||
currentDebt,
|
||||
props.collateralAsset.denom,
|
||||
props.borrowAsset.denom,
|
||||
props.borrowMarket.asset.denom,
|
||||
slippage,
|
||||
prices,
|
||||
assets,
|
||||
@ -108,7 +116,7 @@ export default function ChangeLeverage(props: Props) {
|
||||
currentDebt,
|
||||
previousDebt,
|
||||
props.collateralAsset.denom,
|
||||
props.borrowAsset.denom,
|
||||
props.borrowMarket.asset.denom,
|
||||
props.account.id,
|
||||
slippage,
|
||||
prices,
|
||||
@ -127,22 +135,22 @@ export default function ChangeLeverage(props: Props) {
|
||||
)
|
||||
|
||||
const apy = useMemo(() => {
|
||||
if (!props.borrowAsset.borrowRate || !props.account.strategy.apy) return 0
|
||||
return getLeveragedApy(props.account.strategy.apy, props.borrowAsset.borrowRate, leverage)
|
||||
}, [leverage, props.account.strategy.apy, props.borrowAsset.borrowRate])
|
||||
if (!props.borrowMarket.apy.borrow || !props.account.strategy.apy) return 0
|
||||
return getLeveragedApy(props.account.strategy.apy, props.borrowMarket.apy.borrow, leverage)
|
||||
}, [leverage, props.account.strategy.apy, props.borrowMarket.apy.borrow])
|
||||
|
||||
const warningMessages = useMemo(() => {
|
||||
const messages: string[] = []
|
||||
|
||||
const borrowLiquidity = props.borrowAsset.liquidity?.amount || BN_ZERO
|
||||
const borrowLiquidity = props.borrowMarket.liquidity || BN_ZERO
|
||||
|
||||
if (borrowLiquidity.isLessThan(currentDebt.minus(previousDebt))) {
|
||||
messages.push(getLiquidityMessage(props.borrowAsset.denom, borrowLiquidity, assets))
|
||||
messages.push(getLiquidityMessage(props.borrowMarket.asset.denom, borrowLiquidity, assets))
|
||||
}
|
||||
|
||||
if (maxBorrowAmount.isLessThan(currentDebt)) {
|
||||
messages.push(
|
||||
getHealthFactorMessage(props.borrowAsset.denom, maxBorrowAmount, 'borrow', assets),
|
||||
getHealthFactorMessage(props.borrowMarket.asset.denom, maxBorrowAmount, 'borrow', assets),
|
||||
)
|
||||
}
|
||||
|
||||
@ -160,8 +168,8 @@ export default function ChangeLeverage(props: Props) {
|
||||
depositCapLeft,
|
||||
maxBorrowAmount,
|
||||
previousDebt,
|
||||
props.borrowAsset.denom,
|
||||
props.borrowAsset.liquidity?.amount,
|
||||
props.borrowMarket.asset.denom,
|
||||
props.borrowMarket.liquidity,
|
||||
props.collateralAsset.denom,
|
||||
])
|
||||
|
||||
@ -169,7 +177,7 @@ export default function ChangeLeverage(props: Props) {
|
||||
<>
|
||||
<TokenInputWithSlider
|
||||
amount={currentDebt}
|
||||
asset={props.borrowAsset}
|
||||
asset={props.borrowMarket.asset}
|
||||
max={maxBorrowAmount}
|
||||
onChange={onChangeAmount}
|
||||
maxText='Max borrow'
|
||||
@ -180,7 +188,7 @@ export default function ChangeLeverage(props: Props) {
|
||||
warningMessages={warningMessages}
|
||||
/>
|
||||
<div className='flex flex-col gap-6'>
|
||||
<LeverageSummary asset={props.borrowAsset} positionValue={positionValue} apy={apy} />
|
||||
<LeverageSummary asset={props.borrowMarket.asset} positionValue={positionValue} apy={apy} />
|
||||
<Button
|
||||
onClick={handleOnClick}
|
||||
text='Confirm'
|
||||
|
@ -10,7 +10,7 @@ import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSli
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useDepositActions from 'hooks/hls/useDepositActions'
|
||||
import useBorrowAsset from 'hooks/useBorrowAsset'
|
||||
import useMarket from 'hooks/markets/useMarket'
|
||||
import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
@ -32,7 +32,7 @@ import {
|
||||
interface Props {
|
||||
account: HLSAccountWithStrategy
|
||||
action: HlsStakingManageAction
|
||||
borrowAsset: BorrowAsset
|
||||
borrowMarket: Market
|
||||
collateralAsset: Asset
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ export default function Deposit(props: Props) {
|
||||
useCurrentWalletBalance(props.collateralAsset.denom)?.amount || '0',
|
||||
)
|
||||
const addToStakingStrategy = useStore((s) => s.addToStakingStrategy)
|
||||
const borrowRate = useBorrowAsset(props.borrowAsset.denom)?.borrowRate || 0
|
||||
const borrowRate = useMarket(props.borrowMarket.asset.denom)?.apy.borrow || 0
|
||||
|
||||
const currentLeverage = useMemo(
|
||||
() => calculateAccountLeverage(props.account, prices, assets).toNumber(),
|
||||
@ -72,10 +72,10 @@ export default function Deposit(props: Props) {
|
||||
const borrowCoin = useMemo(
|
||||
() =>
|
||||
BNCoin.fromDenomAndBigNumber(
|
||||
props.borrowAsset.denom,
|
||||
addedDebts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO,
|
||||
props.borrowMarket.asset.denom,
|
||||
addedDebts.find(byDenom(props.borrowMarket.asset.denom))?.amount || BN_ZERO,
|
||||
),
|
||||
[addedDebts, props.borrowAsset.denom],
|
||||
[addedDebts, props.borrowMarket.asset.denom],
|
||||
)
|
||||
|
||||
const warningMessages = useMemo(() => {
|
||||
@ -105,22 +105,22 @@ export default function Deposit(props: Props) {
|
||||
])
|
||||
|
||||
const maxBorrowAmount = useMemo(
|
||||
() => computeMaxBorrowAmount(props.borrowAsset.denom, 'deposit'),
|
||||
[computeMaxBorrowAmount, props.borrowAsset.denom],
|
||||
() => computeMaxBorrowAmount(props.borrowMarket.asset.denom, 'deposit'),
|
||||
[computeMaxBorrowAmount, props.borrowMarket.asset.denom],
|
||||
)
|
||||
|
||||
const borrowWarningMessages = useMemo(() => {
|
||||
let messages: string[] = []
|
||||
if (borrowCoin.amount.isGreaterThan(maxBorrowAmount)) {
|
||||
messages.push(
|
||||
getHealthFactorMessage(props.borrowAsset.denom, maxBorrowAmount, 'borrow', assets),
|
||||
getHealthFactorMessage(props.borrowMarket.asset.denom, maxBorrowAmount, 'borrow', assets),
|
||||
)
|
||||
}
|
||||
|
||||
const borrowLiquidity = props.borrowAsset.liquidity?.amount || BN_ZERO
|
||||
const borrowLiquidity = props.borrowMarket.liquidity || BN_ZERO
|
||||
|
||||
if (borrowCoin.amount.isGreaterThan(borrowLiquidity)) {
|
||||
messages.push(getLiquidityMessage(props.borrowAsset.denom, borrowLiquidity, assets))
|
||||
messages.push(getLiquidityMessage(props.borrowMarket.asset.denom, borrowLiquidity, assets))
|
||||
}
|
||||
|
||||
return messages
|
||||
@ -128,15 +128,15 @@ export default function Deposit(props: Props) {
|
||||
assets,
|
||||
borrowCoin.amount,
|
||||
maxBorrowAmount,
|
||||
props.borrowAsset.denom,
|
||||
props.borrowAsset.liquidity?.amount,
|
||||
props.borrowMarket.asset.denom,
|
||||
props.borrowMarket.liquidity,
|
||||
])
|
||||
|
||||
const actions = useDepositActions({ depositCoin, borrowCoin })
|
||||
|
||||
const currentDebt: BigNumber = useMemo(
|
||||
() => props.account.debts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO,
|
||||
[props.account.debts, props.borrowAsset.denom],
|
||||
() => props.account.debts.find(byDenom(props.borrowMarket.asset.denom))?.amount || BN_ZERO,
|
||||
[props.account.debts, props.borrowMarket.asset.denom],
|
||||
)
|
||||
|
||||
const handleDeposit = useCallback(() => {
|
||||
@ -160,19 +160,19 @@ export default function Deposit(props: Props) {
|
||||
assets,
|
||||
)
|
||||
const borrowValue = BN(currentLeverage - 1).times(depositValue)
|
||||
additionalDebt = getCoinAmount(props.borrowAsset.denom, borrowValue, prices, assets)
|
||||
additionalDebt = getCoinAmount(props.borrowMarket.asset.denom, borrowValue, prices, assets)
|
||||
}
|
||||
|
||||
simulateHlsStakingDeposit(
|
||||
BNCoin.fromDenomAndBigNumber(props.collateralAsset.denom, amount),
|
||||
BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, additionalDebt),
|
||||
BNCoin.fromDenomAndBigNumber(props.borrowMarket.asset.denom, additionalDebt),
|
||||
)
|
||||
},
|
||||
[
|
||||
currentLeverage,
|
||||
keepLeverage,
|
||||
prices,
|
||||
props.borrowAsset.denom,
|
||||
props.borrowMarket.asset.denom,
|
||||
props.collateralAsset.denom,
|
||||
simulateHlsStakingDeposit,
|
||||
assets,
|
||||
@ -197,18 +197,18 @@ export default function Deposit(props: Props) {
|
||||
amount: borrowCoin.amount.toNumber(),
|
||||
warningMessages: borrowWarningMessages,
|
||||
options: {
|
||||
suffix: ` ${props.borrowAsset.symbol}`,
|
||||
suffix: ` ${props.borrowMarket.asset.symbol}`,
|
||||
abbreviated: true,
|
||||
decimals: props.borrowAsset.decimals,
|
||||
decimals: props.borrowMarket.asset.decimals,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'New Debt Amount',
|
||||
amount: currentDebt.plus(borrowCoin.amount).toNumber(),
|
||||
options: {
|
||||
suffix: ` ${props.borrowAsset.symbol}`,
|
||||
suffix: ` ${props.borrowMarket.asset.symbol}`,
|
||||
abbreviated: true,
|
||||
decimals: props.borrowAsset.decimals,
|
||||
decimals: props.borrowMarket.asset.decimals,
|
||||
},
|
||||
},
|
||||
]
|
||||
@ -220,8 +220,8 @@ export default function Deposit(props: Props) {
|
||||
borrowWarningMessages,
|
||||
currentDebt,
|
||||
keepLeverage,
|
||||
props.borrowAsset.decimals,
|
||||
props.borrowAsset.symbol,
|
||||
props.borrowMarket.asset.decimals,
|
||||
props.borrowMarket.asset.symbol,
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -16,25 +16,25 @@ import { getNoBalanceInWalletMessage } from 'utils/messages'
|
||||
interface Props {
|
||||
account: Account
|
||||
action: HlsStakingManageAction
|
||||
borrowAsset: Asset
|
||||
borrowMarket: Market
|
||||
collateralAsset: Asset
|
||||
}
|
||||
|
||||
export default function Repay(props: Props) {
|
||||
const { removeDebts, removedDebts } = useUpdatedAccount(props.account)
|
||||
const borrowAssetAmountInWallet = BN(
|
||||
useCurrentWalletBalance(props.borrowAsset.denom)?.amount || '0',
|
||||
useCurrentWalletBalance(props.borrowMarket.asset.denom)?.amount || '0',
|
||||
)
|
||||
const repay = useStore((s) => s.repay)
|
||||
|
||||
const currentDebt: BigNumber = useMemo(
|
||||
() => props.account.debts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO,
|
||||
[props.account.debts, props.borrowAsset.denom],
|
||||
() => props.account.debts.find(byDenom(props.borrowMarket.asset.denom))?.amount || BN_ZERO,
|
||||
[props.account.debts, props.borrowMarket.asset.denom],
|
||||
)
|
||||
|
||||
const repayAmount: BigNumber = useMemo(
|
||||
() => removedDebts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO,
|
||||
[removedDebts, props.borrowAsset.denom],
|
||||
() => removedDebts.find(byDenom(props.borrowMarket.asset.denom))?.amount || BN_ZERO,
|
||||
[removedDebts, props.borrowMarket.asset.denom],
|
||||
)
|
||||
|
||||
const maxRepayAmount = useMemo(
|
||||
@ -48,51 +48,51 @@ export default function Repay(props: Props) {
|
||||
title: 'Total Debt Repayable',
|
||||
amount: currentDebt.toNumber(),
|
||||
options: {
|
||||
suffix: ` ${props.borrowAsset.symbol}`,
|
||||
suffix: ` ${props.borrowMarket.asset.symbol}`,
|
||||
abbreviated: true,
|
||||
decimals: props.borrowAsset.decimals,
|
||||
decimals: props.borrowMarket.asset.decimals,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'New Debt Amount',
|
||||
amount: currentDebt.minus(repayAmount).toNumber(),
|
||||
options: {
|
||||
suffix: ` ${props.borrowAsset.symbol}`,
|
||||
suffix: ` ${props.borrowMarket.asset.symbol}`,
|
||||
abbreviated: true,
|
||||
decimals: props.borrowAsset.decimals,
|
||||
decimals: props.borrowMarket.asset.decimals,
|
||||
},
|
||||
},
|
||||
],
|
||||
[currentDebt, props.borrowAsset.decimals, props.borrowAsset.symbol, repayAmount],
|
||||
[currentDebt, props.borrowMarket.asset.decimals, props.borrowMarket.asset.symbol, repayAmount],
|
||||
)
|
||||
|
||||
const handleRepay = useCallback(() => {
|
||||
useStore.setState({ hlsManageModal: null })
|
||||
repay({
|
||||
accountId: props.account.id,
|
||||
coin: BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, repayAmount),
|
||||
coin: BNCoin.fromDenomAndBigNumber(props.borrowMarket.asset.denom, repayAmount),
|
||||
fromWallet: true,
|
||||
})
|
||||
}, [props.account.id, props.borrowAsset.denom, repay, repayAmount])
|
||||
}, [props.account.id, props.borrowMarket.asset.denom, repay, repayAmount])
|
||||
|
||||
const handleOnChange = useCallback(
|
||||
(amount: BigNumber) =>
|
||||
removeDebts([BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, amount)]),
|
||||
[props.borrowAsset.denom, removeDebts],
|
||||
removeDebts([BNCoin.fromDenomAndBigNumber(props.borrowMarket.asset.denom, amount)]),
|
||||
[props.borrowMarket.asset.denom, removeDebts],
|
||||
)
|
||||
|
||||
const warningMessages = useMemo(() => {
|
||||
if (borrowAssetAmountInWallet.isZero()) {
|
||||
return [getNoBalanceInWalletMessage(props.borrowAsset.symbol)]
|
||||
return [getNoBalanceInWalletMessage(props.borrowMarket.asset.symbol)]
|
||||
}
|
||||
return []
|
||||
}, [borrowAssetAmountInWallet, props.borrowAsset.symbol])
|
||||
}, [borrowAssetAmountInWallet, props.borrowMarket.asset.symbol])
|
||||
|
||||
return (
|
||||
<>
|
||||
<TokenInputWithSlider
|
||||
amount={repayAmount}
|
||||
asset={props.borrowAsset}
|
||||
asset={props.borrowMarket.asset}
|
||||
max={maxRepayAmount}
|
||||
onChange={handleOnChange}
|
||||
maxText='In Wallet'
|
||||
|
@ -14,7 +14,6 @@ import { getHealthFactorMessage } from 'utils/messages'
|
||||
interface Props {
|
||||
account: Account
|
||||
action: HlsStakingManageAction
|
||||
borrowAsset: Asset
|
||||
collateralAsset: Asset
|
||||
}
|
||||
|
||||
|
@ -8,23 +8,23 @@ import Withdraw from 'components/Modals/HLS/Manage/Withdraw'
|
||||
import ModalContentWithSummary from 'components/Modals/ModalContentWithSummary'
|
||||
import useAccount from 'hooks/accounts/useAccount'
|
||||
import useAsset from 'hooks/assets/useAsset'
|
||||
import useBorrowAsset from 'hooks/useBorrowAsset'
|
||||
import useMarket from 'hooks/markets/useMarket'
|
||||
import useStore from 'store'
|
||||
|
||||
export default function HlsManageModalController() {
|
||||
const modal = useStore((s) => s.hlsManageModal)
|
||||
const { data: account } = useAccount(modal?.accountId)
|
||||
const collateralAsset = useAsset(modal?.staking.strategy.denoms.deposit || '')
|
||||
const borrowAsset = useBorrowAsset(modal?.staking.strategy.denoms.borrow || '')
|
||||
const market = useMarket(modal?.staking.strategy.denoms.borrow || '')
|
||||
|
||||
if (!modal || !collateralAsset || !borrowAsset || !account) return null
|
||||
if (!modal || !collateralAsset || !market || !account) return null
|
||||
|
||||
return (
|
||||
<HlsModal
|
||||
account={{ ...account, strategy: modal.staking.strategy } as HLSAccountWithStrategy}
|
||||
action={modal.staking.action}
|
||||
collateralAsset={collateralAsset}
|
||||
borrowAsset={borrowAsset}
|
||||
borrowMarket={market}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -32,12 +32,11 @@ export default function HlsManageModalController() {
|
||||
interface Props {
|
||||
account: HLSAccountWithStrategy
|
||||
action: HlsStakingManageAction
|
||||
borrowAsset: BorrowAsset
|
||||
borrowMarket: Market
|
||||
collateralAsset: Asset
|
||||
}
|
||||
|
||||
function HlsModal(props: Props) {
|
||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||
function handleClose() {
|
||||
useStore.setState({ hlsManageModal: null })
|
||||
}
|
||||
@ -65,7 +64,7 @@ function HlsModal(props: Props) {
|
||||
<Header
|
||||
action={props.action}
|
||||
primaryAsset={props.collateralAsset}
|
||||
secondaryAsset={props.borrowAsset}
|
||||
secondaryAsset={props.borrowMarket.asset}
|
||||
/>
|
||||
}
|
||||
onClose={handleClose}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React from 'react'
|
||||
|
||||
import Modal from 'components/Modals/Modal'
|
||||
import Content from 'components/Modals/HLS/Deposit'
|
||||
import Header from 'components/Modals/HLS/Header'
|
||||
import Modal from 'components/Modals/Modal'
|
||||
import useAsset from 'hooks/assets/useAsset'
|
||||
import useBorrowAsset from 'hooks/useBorrowAsset'
|
||||
import useMarket from 'hooks/markets/useMarket'
|
||||
import useStore from 'store'
|
||||
|
||||
export default function HlsModalController() {
|
||||
@ -14,7 +14,7 @@ export default function HlsModalController() {
|
||||
modal?.vault?.denoms.primary || modal?.strategy?.denoms.deposit || '',
|
||||
)
|
||||
|
||||
const secondaryAsset = useBorrowAsset(modal?.strategy?.denoms.borrow || '')
|
||||
const secondaryAsset = useMarket(modal?.strategy?.denoms.borrow || '')
|
||||
|
||||
if (!primaryAsset || !secondaryAsset) return null
|
||||
|
||||
@ -41,7 +41,7 @@ export default function HlsModalController() {
|
||||
|
||||
interface Props {
|
||||
primaryAsset: Asset
|
||||
secondaryAsset: BorrowAsset
|
||||
secondaryAsset: Market
|
||||
strategy?: HLSStrategy
|
||||
vaultAddress: string | null
|
||||
}
|
||||
@ -53,7 +53,9 @@ function HlsModal(props: Props) {
|
||||
|
||||
return (
|
||||
<Modal
|
||||
header={<Header primaryAsset={props.primaryAsset} secondaryAsset={props.secondaryAsset} />}
|
||||
header={
|
||||
<Header primaryAsset={props.primaryAsset} secondaryAsset={props.secondaryAsset.asset} />
|
||||
}
|
||||
headerClassName='gradient-header pl-2 pr-2.5 py-3 border-b-white/5 border-b'
|
||||
contentClassName='flex flex-col p-6'
|
||||
modalClassName='max-w-modal-md'
|
||||
@ -61,7 +63,7 @@ function HlsModal(props: Props) {
|
||||
>
|
||||
<Content
|
||||
collateralAsset={props.primaryAsset}
|
||||
borrowAsset={props.secondaryAsset}
|
||||
borrowMarket={props.secondaryAsset}
|
||||
vaultAddress={props.vaultAddress}
|
||||
strategy={props.strategy}
|
||||
/>
|
||||
|
@ -12,7 +12,7 @@ import TokenInput from 'components/common/TokenInput'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useStore from 'store'
|
||||
@ -39,7 +39,7 @@ export interface VaultBorrowingsProps {
|
||||
export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
||||
const assets = useAllAssets()
|
||||
const { borrowings, onChangeBorrowings } = props
|
||||
const { data: marketAssets } = useMarketAssets()
|
||||
const markets = useMarkets()
|
||||
const { data: prices } = usePrices()
|
||||
const vaultModal = useStore((s) => s.vaultModal)
|
||||
const depositIntoVault = useStore((s) => s.depositIntoVault)
|
||||
@ -227,7 +227,8 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
||||
</div>
|
||||
{props.borrowings.map((coin) => {
|
||||
const asset = assets.find(byDenom(coin.denom))
|
||||
const borrowRate = marketAssets?.find((market) => market.denom === coin.denom)?.apy.borrow
|
||||
const borrowRate = markets?.find((market) => market.asset.denom === coin.denom)?.apy
|
||||
.borrow
|
||||
|
||||
if (!asset || !borrowRate)
|
||||
return <React.Fragment key={`borrow-rate-${coin.denom}`}></React.Fragment>
|
||||
|
@ -13,7 +13,7 @@ import Value, {
|
||||
VALUE_META,
|
||||
valueBalancesSortingFn,
|
||||
} from 'components/account/AccountBalancesTable/Columns/Value'
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import useStore from 'store'
|
||||
|
||||
@ -21,7 +21,8 @@ export default function useAccountBalancesColumns(
|
||||
account: Account,
|
||||
showLiquidationPrice?: boolean,
|
||||
) {
|
||||
const { data: markets } = useMarketAssets()
|
||||
const markets = useMarkets()
|
||||
|
||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||
|
||||
const { computeLiquidationPrice } = useHealthComputer(updatedAccount ?? account)
|
||||
|
@ -2,16 +2,16 @@ import BigNumber from 'bignumber.js'
|
||||
import classNames from 'classnames'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
|
||||
import DisplayCurrency from 'components/common/DisplayCurrency'
|
||||
import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||
import { ArrowRight } from 'components/common/Icons'
|
||||
import Text from 'components/common/Text'
|
||||
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
|
||||
import { BN_ZERO, MAX_AMOUNT_DECIMALS } from 'constants/math'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
@ -8,6 +8,7 @@ import AccountDetailsLeverage from 'components/account/AccountDetails/AccountDet
|
||||
import Skeleton from 'components/account/AccountDetails/Skeleton'
|
||||
import AccountPerpPositionTable from 'components/account/AccountPerpPositionTable'
|
||||
import { HealthGauge } from 'components/account/Health/HealthGauge'
|
||||
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
|
||||
import EscButton from 'components/common/Button/EscButton'
|
||||
import { glowElement } from 'components/common/Button/utils'
|
||||
import Card from 'components/common/Card'
|
||||
@ -15,6 +16,7 @@ import DisplayCurrency from 'components/common/DisplayCurrency'
|
||||
import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||
import { ThreeDots } from 'components/common/Icons'
|
||||
import Text from 'components/common/Text'
|
||||
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
import { LocalStorageKeys } from 'constants/localStorageKeys'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
@ -24,10 +26,8 @@ import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
||||
import useAccountId from 'hooks/useAccountId'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
@ -10,7 +10,7 @@ import Text from 'components/common/Text'
|
||||
import WalletBridges from 'components/Wallet/WalletBridges'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useBaseAsset from 'hooks/assets/useBasetAsset'
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import useAutoLend from 'hooks/useAutoLend'
|
||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||
import useWalletBalances from 'hooks/useWalletBalances'
|
||||
@ -35,7 +35,8 @@ export default function AccountFundContent(props: Props) {
|
||||
const { autoLendEnabledAccountIds } = useAutoLend()
|
||||
const isLending = autoLendEnabledAccountIds.includes(props.accountId)
|
||||
const [fundingAssets, setFundingAssets] = useState<BNCoin[]>([])
|
||||
const { data: marketAssets } = useMarketAssets()
|
||||
const markets = useMarkets()
|
||||
|
||||
const { data: walletBalances } = useWalletBalances(props.address)
|
||||
const { simulateDeposits } = useUpdatedAccount(props.account)
|
||||
const baseAsset = useBaseAsset()
|
||||
@ -127,7 +128,7 @@ export default function AccountFundContent(props: Props) {
|
||||
const depositCapReachedCoins = useMemo(() => {
|
||||
const depositCapReachedCoins: BNCoin[] = []
|
||||
fundingAssets.forEach((asset) => {
|
||||
const marketAsset = marketAssets.find(byDenom(asset.denom))
|
||||
const marketAsset = markets.find(byDenom(asset.denom))
|
||||
if (!marketAsset) return
|
||||
|
||||
const capLeft = getCapLeftWithBuffer(marketAsset.cap)
|
||||
@ -137,7 +138,7 @@ export default function AccountFundContent(props: Props) {
|
||||
depositCapReachedCoins.push(BNCoin.fromDenomAndBigNumber(asset.denom, capLeft))
|
||||
})
|
||||
return depositCapReachedCoins
|
||||
}, [fundingAssets, marketAssets])
|
||||
}, [fundingAssets, markets])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -2,15 +2,15 @@ import { useCallback, useMemo } from 'react'
|
||||
|
||||
import AccountFundFullPage from 'components/account/AccountFund/AccountFundFullPage'
|
||||
import Skeleton from 'components/account/AccountList/Skeleton'
|
||||
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
|
||||
import Button from 'components/common/Button'
|
||||
import { ArrowDownLine, ArrowUpLine, TrashBin } from 'components/common/Icons'
|
||||
import SwitchAutoLend from 'components/common/Switch/SwitchAutoLend'
|
||||
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
|
||||
import useAccount from 'hooks/accounts/useAccount'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useStore from 'store'
|
||||
import { calculateAccountApr, calculateAccountBalanceValue } from 'utils/accounts'
|
||||
|
@ -5,21 +5,21 @@ import AccountBalancesTable from 'components/account/AccountBalancesTable'
|
||||
import AccountComposition from 'components/account/AccountComposition'
|
||||
import AccountPerpPositionTable from 'components/account/AccountPerpPositionTable'
|
||||
import HealthBar from 'components/account/Health/HealthBar'
|
||||
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
|
||||
import Accordion from 'components/common/Accordion'
|
||||
import Card from 'components/common/Card'
|
||||
import DisplayCurrency from 'components/common/DisplayCurrency'
|
||||
import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||
import { ArrowRight } from 'components/common/Icons'
|
||||
import Text from 'components/common/Text'
|
||||
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
import { LocalStorageKeys } from 'constants/localStorageKeys'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
@ -1,8 +1,8 @@
|
||||
import AvailableBorrowingsTable from 'components/borrow/Table/AvailableBorrowingsTable'
|
||||
import DepositedBorrowingsTable from 'components/borrow/Table/DepositedBorrowingsTable'
|
||||
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useBorrowEnabledAssets from 'hooks/assets/useBorrowEnabledAssets'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
|
||||
export default function Borrowings() {
|
||||
const data = useBorrowMarketAssetsTableData()
|
||||
@ -30,10 +30,18 @@ function Fallback() {
|
||||
max: 0,
|
||||
liq: 0,
|
||||
},
|
||||
liquidity: null,
|
||||
marketDepositAmount: BN_ZERO,
|
||||
liquidity: BN_ZERO,
|
||||
marketLiquidityRate: 0,
|
||||
marketLiquidityAmount: BN_ZERO,
|
||||
cap: {
|
||||
denom: asset.denom,
|
||||
max: BN_ZERO,
|
||||
used: BN_ZERO,
|
||||
},
|
||||
debt: BN_ZERO,
|
||||
borrowEnabled: true,
|
||||
depositEnabled: true,
|
||||
deposits: BN_ZERO,
|
||||
accountDebt: BN_ZERO,
|
||||
}))
|
||||
|
||||
return <AvailableBorrowingsTable data={data} isLoading />
|
||||
|
@ -16,15 +16,9 @@ export const debtSortingFn = (
|
||||
): number => {
|
||||
const assetA = a.original.asset
|
||||
const assetB = b.original.asset
|
||||
if (!a.original.debt || !b.original.debt) return 0
|
||||
const assetAPrice = (a.original.liquidity?.value ?? BN_ZERO).div(
|
||||
a.original.liquidity?.amount ?? BN_ZERO,
|
||||
)
|
||||
const assetBPrice = (b.original.liquidity?.value ?? BN_ZERO).div(
|
||||
b.original.liquidity?.amount ?? BN_ZERO,
|
||||
)
|
||||
const debtA = a.original.debt.times(assetAPrice).shiftedBy(-assetA.decimals)
|
||||
const debtB = b.original.debt.times(assetBPrice).shiftedBy(-assetB.decimals)
|
||||
if (!a.original.accountDebt || !b.original.accountDebt) return 0
|
||||
const debtA = a.original.accountDebt.shiftedBy(-assetA.decimals)
|
||||
const debtB = b.original.accountDebt.shiftedBy(-assetB.decimals)
|
||||
return debtA.minus(debtB).toNumber()
|
||||
}
|
||||
|
||||
@ -38,5 +32,5 @@ export default function Debt(props: Props) {
|
||||
|
||||
if (!asset) return null
|
||||
|
||||
return <AmountAndValue asset={asset} amount={props.data?.debt ?? BN_ZERO} />
|
||||
return <AmountAndValue asset={asset} amount={props.data?.accountDebt ?? BN_ZERO} />
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ export const liquiditySortingFn = (
|
||||
): number => {
|
||||
const assetA = a.original.asset
|
||||
const assetB = b.original.asset
|
||||
const liquidityA = demagnify(a.original.liquidity?.amount ?? 0, assetA)
|
||||
const liquidityB = demagnify(b.original.liquidity?.amount ?? 0, assetB)
|
||||
const liquidityA = demagnify(a.original.liquidity ?? 0, assetA)
|
||||
const liquidityB = demagnify(b.original.liquidity ?? 0, assetB)
|
||||
|
||||
return liquidityA - liquidityB
|
||||
}
|
||||
@ -35,9 +35,9 @@ export default function Liquidity(props: Props) {
|
||||
|
||||
if (!asset) return null
|
||||
|
||||
if (liquidity === null) {
|
||||
if (liquidity.isZero()) {
|
||||
return <Loading />
|
||||
}
|
||||
|
||||
return <AmountAndValue asset={asset} amount={liquidity.amount ?? BN_ZERO} />
|
||||
return <AmountAndValue asset={asset} amount={liquidity ?? BN_ZERO} />
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
|
||||
export default function useBorrowMarketAssetsTableData() {
|
||||
const account = useCurrentAccount()
|
||||
const markets = useMarkets()
|
||||
|
||||
return useMemo((): {
|
||||
accountBorrowedAssets: BorrowMarketTableData[]
|
||||
availableAssets: BorrowMarketTableData[]
|
||||
allAssets: BorrowMarketTableData[]
|
||||
} => {
|
||||
const accountBorrowedAssets: BorrowMarketTableData[] = [],
|
||||
availableAssets: BorrowMarketTableData[] = []
|
||||
|
||||
markets
|
||||
.filter((market) => market.borrowEnabled)
|
||||
.forEach((market) => {
|
||||
const debt = account?.debts?.find((debt) => debt.denom === market.asset.denom)
|
||||
|
||||
const borrowMarketAsset: BorrowMarketTableData = {
|
||||
...market,
|
||||
accountDebt: debt?.amount,
|
||||
}
|
||||
;(borrowMarketAsset.accountDebt ? accountBorrowedAssets : availableAssets).push(
|
||||
borrowMarketAsset,
|
||||
)
|
||||
})
|
||||
|
||||
return {
|
||||
accountBorrowedAssets,
|
||||
availableAssets,
|
||||
allAssets: [...accountBorrowedAssets, ...availableAssets],
|
||||
}
|
||||
}, [account?.debts, markets])
|
||||
}
|
@ -2,28 +2,27 @@ import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||
import Text from 'components/common/Text'
|
||||
|
||||
interface Props {
|
||||
availableLiquidity: BigNumber
|
||||
asset: BorrowAsset
|
||||
market: Market
|
||||
}
|
||||
|
||||
export default function AvailableLiquidityMessage(props: Props) {
|
||||
const { availableLiquidity, asset } = props
|
||||
const { market } = props
|
||||
return (
|
||||
<div className='flex items-start p-4 bg-white/5'>
|
||||
<div className='flex flex-col gap-2'>
|
||||
<Text size='sm'>Not enough Liquidty!</Text>
|
||||
<Text size='xs' className='text-white/40'>
|
||||
{`This transaction would exceed the amount of ${asset.symbol} currently available for borrowing on Mars.`}
|
||||
{`This transaction would exceed the amount of ${market.asset.symbol} currently available for borrowing on Mars.`}
|
||||
</Text>
|
||||
|
||||
<div className='flex gap-1'>
|
||||
<Text size='xs'>Available Liquidity:</Text>
|
||||
<FormattedNumber
|
||||
amount={availableLiquidity.toNumber()}
|
||||
amount={market.liquidity.toNumber()}
|
||||
options={{
|
||||
abbreviated: true,
|
||||
decimals: asset.decimals,
|
||||
suffix: ` ${asset.symbol}`,
|
||||
decimals: market.asset.decimals,
|
||||
suffix: ` ${market.asset.symbol}`,
|
||||
}}
|
||||
className='text-xs text-white/60'
|
||||
/>
|
||||
|
@ -23,9 +23,7 @@ export default function MarketDetails({ row, type }: Props) {
|
||||
symbol: displayCurrencySymbol,
|
||||
} = useDisplayCurrencyPrice()
|
||||
|
||||
const { asset, ltv, marketDepositAmount, marketLiquidityAmount } = row.original
|
||||
|
||||
const totalBorrowed = marketDepositAmount.minus(marketLiquidityAmount)
|
||||
const { asset, ltv, cap, liquidity, deposits, debt } = row.original
|
||||
|
||||
const details: Detail[] = useMemo(() => {
|
||||
const isDollar = displayCurrencySymbol === '$'
|
||||
@ -33,7 +31,7 @@ export default function MarketDetails({ row, type }: Props) {
|
||||
function getLendingMarketDetails() {
|
||||
return [
|
||||
{
|
||||
amount: convertAmount(asset, marketDepositAmount).toNumber(),
|
||||
amount: convertAmount(asset, deposits).toNumber(),
|
||||
options: {
|
||||
abbreviated: true,
|
||||
suffix: isDollar ? undefined : ` ${displayCurrencySymbol}`,
|
||||
@ -62,9 +60,7 @@ export default function MarketDetails({ row, type }: Props) {
|
||||
title: 'Oracle Price',
|
||||
},
|
||||
{
|
||||
amount: totalBorrowed.isZero()
|
||||
? 0
|
||||
: totalBorrowed.dividedBy(marketDepositAmount).multipliedBy(100).toNumber(),
|
||||
amount: debt.isZero() ? 0 : debt.dividedBy(deposits).multipliedBy(100).toNumber(), // TODO: Check if this number is still correct
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Utilization Rate',
|
||||
},
|
||||
@ -74,7 +70,7 @@ export default function MarketDetails({ row, type }: Props) {
|
||||
function getBorrowMarketDetails() {
|
||||
return [
|
||||
{
|
||||
amount: convertAmount(asset, totalBorrowed).toNumber(),
|
||||
amount: convertAmount(asset, debt).toNumber(),
|
||||
options: {
|
||||
abbreviated: true,
|
||||
suffix: isDollar ? undefined : ` ${displayCurrencySymbol}`,
|
||||
@ -93,9 +89,7 @@ export default function MarketDetails({ row, type }: Props) {
|
||||
title: 'Oracle Price',
|
||||
},
|
||||
{
|
||||
amount: totalBorrowed.isZero()
|
||||
? 0
|
||||
: totalBorrowed.dividedBy(marketDepositAmount).multipliedBy(100).toNumber(),
|
||||
amount: debt.isZero() ? 0 : debt.dividedBy(deposits).multipliedBy(100).toNumber(), // TODO: CHeck if this is still correct
|
||||
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
|
||||
title: 'Utilization Rate',
|
||||
},
|
||||
@ -105,14 +99,15 @@ export default function MarketDetails({ row, type }: Props) {
|
||||
if (type === 'lend') return getLendingMarketDetails()
|
||||
return getBorrowMarketDetails()
|
||||
}, [
|
||||
type,
|
||||
asset,
|
||||
marketDepositAmount,
|
||||
ltv,
|
||||
totalBorrowed,
|
||||
displayCurrencySymbol,
|
||||
type,
|
||||
convertAmount,
|
||||
asset,
|
||||
debt,
|
||||
ltv.max,
|
||||
ltv.liq,
|
||||
getConversionRate,
|
||||
deposits,
|
||||
])
|
||||
|
||||
return (
|
||||
|
@ -7,7 +7,7 @@ import { ChevronDown, ChevronRight } from 'components/common/Icons'
|
||||
import Text from 'components/common/Text'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useAsset from 'hooks/assets/useAsset'
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { formatValue } from 'utils/formatters'
|
||||
@ -22,7 +22,8 @@ interface Props extends SelectOption {
|
||||
|
||||
export default function Option(props: Props) {
|
||||
const isCoin = !!props.denom
|
||||
const { data: marketAssets } = useMarketAssets()
|
||||
const markets = useMarkets()
|
||||
|
||||
const asset = useAsset(props.denom || '')
|
||||
|
||||
function handleOnClick(value: string | undefined) {
|
||||
@ -32,7 +33,7 @@ export default function Option(props: Props) {
|
||||
|
||||
if (isCoin) {
|
||||
const balance = props.amount ?? BN_ZERO
|
||||
const marketAsset = marketAssets.find(byDenom(props.denom || ''))
|
||||
const marketAsset = markets.find(byDenom(props.denom || ''))
|
||||
|
||||
if (!asset || !marketAsset) return null
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import AvailableLendsTable from 'components/earn/lend/Table/AvailableLendsTable'
|
||||
import DepositedLendsTable from 'components/earn/lend/Table/DepositedLendsTable'
|
||||
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useLendEnabledAssets from 'hooks/assets/useLendEnabledAssets'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
|
||||
export default function Lends() {
|
||||
const { accountLentAssets, availableAssets, allAssets } = useLendingMarketAssetsTableData()
|
||||
@ -23,10 +23,11 @@ function Fallback() {
|
||||
|
||||
const data: LendingMarketTableData[] = assets.map((asset) => ({
|
||||
asset,
|
||||
marketDepositCap: BN_ZERO,
|
||||
borrowEnabled: false,
|
||||
marketDepositAmount: BN_ZERO,
|
||||
marketLiquidityAmount: BN_ZERO,
|
||||
borrowEnabled: true,
|
||||
depositEnabled: true,
|
||||
debt: BN_ZERO,
|
||||
deposits: BN_ZERO,
|
||||
liquidity: BN_ZERO,
|
||||
cap: {
|
||||
max: BN_ZERO,
|
||||
used: BN_ZERO,
|
||||
|
@ -1,50 +1,35 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useMarketDeposits from 'hooks/markets/useMarketDeposits'
|
||||
import useMarketLiquidities from 'hooks/markets/useMarketLiquidities'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import useCurrentAccountLends from 'hooks/useCurrentAccountLends'
|
||||
import useDepositEnabledMarkets from 'hooks/useDepositEnabledMarkets'
|
||||
import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
function useLendingMarketAssetsTableData(): {
|
||||
accountLentAssets: LendingMarketTableData[]
|
||||
availableAssets: LendingMarketTableData[]
|
||||
allAssets: LendingMarketTableData[]
|
||||
} {
|
||||
const markets = useDepositEnabledMarkets()
|
||||
const markets = useMarkets()
|
||||
const accountLentAmounts = useCurrentAccountLends()
|
||||
const { data: marketLiquidities } = useMarketLiquidities()
|
||||
const { data: marketDeposits } = useMarketDeposits()
|
||||
const { convertAmount } = useDisplayCurrencyPrice()
|
||||
const assets = useAllAssets()
|
||||
|
||||
return useMemo(() => {
|
||||
const accountLentAssets: LendingMarketTableData[] = [],
|
||||
availableAssets: LendingMarketTableData[] = []
|
||||
|
||||
markets.forEach(({ denom, cap, ltv, apy, borrowEnabled }) => {
|
||||
const asset = assets.find(byDenom(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 ?? BN_ZERO
|
||||
markets.forEach((market) => {
|
||||
const accountLentAmount =
|
||||
accountLentAmounts.find(byDenom(market.asset.denom))?.amount ?? BN_ZERO
|
||||
const accountLentValue = accountLentAmount
|
||||
? convertAmount(asset, accountLentAmount)
|
||||
? convertAmount(market.asset, accountLentAmount)
|
||||
: undefined
|
||||
|
||||
const lendingMarketAsset: LendingMarketTableData = {
|
||||
asset,
|
||||
marketDepositAmount,
|
||||
...market,
|
||||
accountLentValue,
|
||||
accountLentAmount,
|
||||
marketLiquidityAmount,
|
||||
apy,
|
||||
ltv,
|
||||
borrowEnabled,
|
||||
cap,
|
||||
}
|
||||
|
||||
if (lendingMarketAsset.accountLentAmount?.isZero()) {
|
||||
@ -59,7 +44,7 @@ function useLendingMarketAssetsTableData(): {
|
||||
availableAssets,
|
||||
allAssets: [...accountLentAssets, ...availableAssets],
|
||||
}
|
||||
}, [markets, assets, marketDeposits, marketLiquidities, accountLentAmounts, convertAmount])
|
||||
}, [markets, accountLentAmounts, convertAmount])
|
||||
}
|
||||
|
||||
export default useLendingMarketAssetsTableData
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||
|
||||
import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||
import Loading from 'components/common/Loading'
|
||||
import useMarketBorrowings from 'hooks/markets/useMarketBorrowings'
|
||||
import useMarket from 'hooks/markets/useMarket'
|
||||
|
||||
export const APY_META = { accessorKey: 'apy', header: 'APY Range' }
|
||||
|
||||
@ -12,10 +12,7 @@ interface Props {
|
||||
|
||||
export default function Apy(props: Props) {
|
||||
const { vault } = props
|
||||
const { data: marketBorrowings } = useMarketBorrowings()
|
||||
|
||||
const borrowRate = marketBorrowings.find((asset) => asset.denom === vault.hls?.borrowDenom)
|
||||
?.borrowRate
|
||||
const borrowRate = useMarket(vault.hls?.borrowDenom || '')?.apy.borrow
|
||||
|
||||
if (vault.apy === null || borrowRate === null) return <Loading />
|
||||
|
||||
|
@ -5,7 +5,7 @@ import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||
import Loading from 'components/common/Loading'
|
||||
import TitleAndSubCell from 'components/common/TitleAndSubCell'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useBorrowAsset from 'hooks/useBorrowAsset'
|
||||
import useMarket from 'hooks/markets/useMarket'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import { calculateAccountLeverage } from 'utils/accounts'
|
||||
import { getLeveragedApy } from 'utils/math'
|
||||
@ -27,7 +27,7 @@ interface Props {
|
||||
export default function ActiveAPY(props: Props) {
|
||||
const { data: prices } = usePrices()
|
||||
const assets = useAllAssets()
|
||||
const borrowRate = useBorrowAsset(props.account.strategy.denoms.borrow)?.borrowRate
|
||||
const borrowRate = useMarket(props.account.strategy.denoms.borrow)?.apy.borrow
|
||||
|
||||
const leverage = useMemo(
|
||||
() => calculateAccountLeverage(props.account, prices, assets),
|
||||
|
@ -3,7 +3,7 @@ import { Row } from '@tanstack/react-table'
|
||||
import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||
import Loading from 'components/common/Loading'
|
||||
import TitleAndSubCell from 'components/common/TitleAndSubCell'
|
||||
import useBorrowAsset from 'hooks/useBorrowAsset'
|
||||
import useMarket from 'hooks/markets/useMarket'
|
||||
import { getLeveragedApy } from 'utils/math'
|
||||
|
||||
export const APY_RANGE_META = { header: 'APY range', accessorKey: 'apy' }
|
||||
@ -19,7 +19,7 @@ interface Props {
|
||||
|
||||
export default function ApyRange(props: Props) {
|
||||
const baseApy = props.strategy.apy
|
||||
const borrowRate = useBorrowAsset(props.strategy.denoms.borrow)?.borrowRate
|
||||
const borrowRate = useMarket(props.strategy.denoms.borrow)?.apy.borrow
|
||||
|
||||
if (!borrowRate || props.isLoading || !baseApy) {
|
||||
return <Loading />
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React, { Suspense, useMemo } from 'react'
|
||||
|
||||
import AccountBalancesTable from 'components/account/AccountBalancesTable'
|
||||
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
|
||||
import Card from 'components/common/Card'
|
||||
import TableSkeleton from 'components/common/Table/TableSkeleton'
|
||||
import Text from 'components/common/Text'
|
||||
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
|
||||
import useAccount from 'hooks/accounts/useAccount'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
|
||||
interface Props {
|
||||
accountId: string
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { Suspense, useMemo } from 'react'
|
||||
|
||||
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
|
||||
import DisplayCurrency from 'components/common/DisplayCurrency'
|
||||
import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
|
||||
import Skeleton from 'components/portfolio/SummarySkeleton'
|
||||
import { MAX_AMOUNT_DECIMALS } from 'constants/math'
|
||||
import useAccount from 'hooks/accounts/useAccount'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import { getAccountSummaryStats } from 'utils/accounts'
|
||||
import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants'
|
||||
|
@ -2,8 +2,10 @@ import classNames from 'classnames'
|
||||
import { ReactNode, useMemo } from 'react'
|
||||
import { NavLink, useParams, useSearchParams } from 'react-router-dom'
|
||||
|
||||
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
|
||||
import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||
import Loading from 'components/common/Loading'
|
||||
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
|
||||
import Skeleton from 'components/portfolio/Card/Skeleton'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
import { LocalStorageKeys } from 'constants/localStorageKeys'
|
||||
@ -12,10 +14,8 @@ import useAccount from 'hooks/accounts/useAccount'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
||||
import useAccountId from 'hooks/useAccountId'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import {
|
||||
calculateAccountApr,
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useParams } from 'react-router-dom'
|
||||
|
||||
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
|
||||
import DisplayCurrency from 'components/common/DisplayCurrency'
|
||||
import { FormattedNumber } from 'components/common/FormattedNumber'
|
||||
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
|
||||
import SummarySkeleton from 'components/portfolio/SummarySkeleton'
|
||||
import { MAX_AMOUNT_DECIMALS } from 'constants/math'
|
||||
import useAccounts from 'hooks/accounts/useAccounts'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useStore from 'store'
|
||||
import { getAccountSummaryStats } from 'utils/accounts'
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import AccountBalancesTable from 'components/account/AccountBalancesTable'
|
||||
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
|
||||
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
|
||||
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
|
||||
export default function AccountDetailsCard() {
|
||||
const account = useCurrentAccount()
|
||||
|
@ -6,8 +6,7 @@ import Text from 'components/common/Text'
|
||||
import AssetSelectorItem from 'components/trade/TradeModule/AssetSelector/AssetSelectorItem'
|
||||
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
||||
import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets'
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
import useMarketDeposits from 'hooks/markets/useMarketDeposits'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useStore from 'store'
|
||||
import { getMergedBalancesForAsset } from 'utils/accounts'
|
||||
@ -26,8 +25,7 @@ export default function AssetList(props: Props) {
|
||||
const baseDenom = useStore((s) => s.chainConfig.assets[0].denom)
|
||||
const { assets, type, isOpen, toggleOpen, onChangeAsset } = props
|
||||
const account = useCurrentAccount()
|
||||
const { data: marketAssets } = useMarketAssets()
|
||||
const { data: marketDeposits } = useMarketDeposits()
|
||||
const markets = useMarkets()
|
||||
const { data: prices } = usePrices()
|
||||
const marketEnabledAssets = useMarketEnabledAssets()
|
||||
const balances = useMemo(() => {
|
||||
@ -36,8 +34,8 @@ export default function AssetList(props: Props) {
|
||||
}, [account, marketEnabledAssets])
|
||||
|
||||
const sortedAssets = useMemo(
|
||||
() => sortAssetsOrPairs(assets, prices, marketDeposits, balances, baseDenom) as Asset[],
|
||||
[assets, prices, marketDeposits, balances, baseDenom],
|
||||
() => sortAssetsOrPairs(assets, prices, markets, balances, baseDenom) as Asset[],
|
||||
[assets, prices, markets, balances, baseDenom],
|
||||
)
|
||||
|
||||
return (
|
||||
@ -63,9 +61,7 @@ export default function AssetList(props: Props) {
|
||||
balances={balances}
|
||||
key={`${type}-${asset.symbol}`}
|
||||
onSelect={props.onChangeAsset}
|
||||
depositCap={
|
||||
type === 'buy' ? marketAssets?.find(byDenom(asset.denom))?.cap : undefined
|
||||
}
|
||||
depositCap={type === 'buy' ? markets?.find(byDenom(asset.denom))?.cap : undefined}
|
||||
asset={asset}
|
||||
/>
|
||||
))}
|
||||
|
@ -5,8 +5,7 @@ import AssetSelectorItem from 'components/trade/TradeModule/AssetSelector/AssetS
|
||||
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
||||
import useBaseAsset from 'hooks/assets/useBasetAsset'
|
||||
import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets'
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
import useMarketDeposits from 'hooks/markets/useMarketDeposits'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import { getMergedBalancesForAsset } from 'utils/accounts'
|
||||
import { byDenom } from 'utils/array'
|
||||
@ -22,8 +21,7 @@ interface Props {
|
||||
|
||||
export default function PairsList(props: Props) {
|
||||
const account = useCurrentAccount()
|
||||
const { data: marketAssets } = useMarketAssets()
|
||||
const { data: marketDeposits } = useMarketDeposits()
|
||||
const markets = useMarkets()
|
||||
const { data: prices } = usePrices()
|
||||
const baseDenom = useBaseAsset().denom
|
||||
const marketEnabledAssets = useMarketEnabledAssets()
|
||||
@ -44,8 +42,8 @@ export default function PairsList(props: Props) {
|
||||
}, [props.stables, props.assets])
|
||||
|
||||
const sortedPairs = useMemo(
|
||||
() => sortAssetsOrPairs(pairs, prices, marketDeposits, balances, baseDenom) as AssetPair[],
|
||||
[pairs, prices, marketDeposits, balances, baseDenom],
|
||||
() => sortAssetsOrPairs(pairs, prices, markets, balances, baseDenom) as AssetPair[],
|
||||
[pairs, prices, markets, balances, baseDenom],
|
||||
)
|
||||
|
||||
return (
|
||||
@ -62,7 +60,7 @@ export default function PairsList(props: Props) {
|
||||
balances={balances}
|
||||
key={`${assetPair.buy.symbol}-${assetPair.sell.symbol}`}
|
||||
onSelect={props.onChangeAssetPair}
|
||||
depositCap={marketAssets?.find(byDenom(assetPair.buy.denom))?.cap}
|
||||
depositCap={markets?.find(byDenom(assetPair.buy.denom))?.cap}
|
||||
asset={assetPair.buy}
|
||||
sellAsset={assetPair.sell}
|
||||
/>
|
||||
|
@ -22,8 +22,7 @@ import { BN_ZERO } from 'constants/math'
|
||||
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
||||
import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets'
|
||||
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
import useMarketBorrowings from 'hooks/markets/useMarketBorrowings'
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
import useAutoLend from 'hooks/useAutoLend'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
@ -53,8 +52,7 @@ export default function SwapForm(props: Props) {
|
||||
const [slippage] = useLocalStorage(LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage)
|
||||
const { computeMaxSwapAmount } = useHealthComputer(account)
|
||||
const [tradeDirection, setTradeDirection] = useState<TradeDirection>('long')
|
||||
const { data: borrowAssets } = useMarketBorrowings()
|
||||
const { data: marketAssets } = useMarketAssets()
|
||||
const markets = useMarkets()
|
||||
|
||||
const [inputAsset, outputAsset] = useMemo(() => {
|
||||
if (isAdvanced) return [sellAsset, buyAsset]
|
||||
@ -65,7 +63,7 @@ export default function SwapForm(props: Props) {
|
||||
inputAsset.denom,
|
||||
outputAsset.denom,
|
||||
)
|
||||
const isBorrowEnabled = !!marketAssets.find(byDenom(inputAsset.denom))?.borrowEnabled
|
||||
const isBorrowEnabled = !!markets.find(byDenom(inputAsset.denom))?.borrowEnabled
|
||||
const isRepayable = !!account?.debts.find(byDenom(outputAsset.denom))
|
||||
const [isMarginChecked, setMarginChecked] = useToggle(isBorrowEnabled ? useMargin : false)
|
||||
const [isAutoRepayChecked, setAutoRepayChecked] = useToggle(
|
||||
@ -87,7 +85,7 @@ export default function SwapForm(props: Props) {
|
||||
const assets = useMarketEnabledAssets()
|
||||
|
||||
const depositCapReachedCoins: BNCoin[] = useMemo(() => {
|
||||
const outputMarketAsset = marketAssets.find(byDenom(outputAsset.denom))
|
||||
const outputMarketAsset = markets.find(byDenom(outputAsset.denom))
|
||||
|
||||
if (!outputMarketAsset) return []
|
||||
|
||||
@ -97,7 +95,7 @@ export default function SwapForm(props: Props) {
|
||||
}
|
||||
|
||||
return []
|
||||
}, [marketAssets, outputAsset.denom, outputAssetAmount])
|
||||
}, [markets, outputAsset.denom, outputAssetAmount])
|
||||
|
||||
const onChangeInputAmount = useCallback(
|
||||
(amount: BigNumber) => {
|
||||
@ -305,9 +303,9 @@ export default function SwapForm(props: Props) {
|
||||
modal,
|
||||
])
|
||||
|
||||
const borrowAsset = useMemo(
|
||||
() => borrowAssets.find(byDenom(inputAsset.denom)),
|
||||
[borrowAssets, inputAsset.denom],
|
||||
const borrowMarket = useMemo(
|
||||
() => markets.find((market) => market.asset.denom === inputAsset.denom),
|
||||
[markets, inputAsset.denom],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
@ -324,8 +322,8 @@ export default function SwapForm(props: Props) {
|
||||
)
|
||||
|
||||
const availableLiquidity = useMemo(
|
||||
() => borrowAsset?.liquidity?.amount ?? BN_ZERO,
|
||||
[borrowAsset?.liquidity?.amount],
|
||||
() => borrowMarket?.liquidity ?? BN_ZERO,
|
||||
[borrowMarket?.liquidity],
|
||||
)
|
||||
|
||||
const isSwapDisabled = useMemo(
|
||||
@ -349,7 +347,7 @@ export default function SwapForm(props: Props) {
|
||||
<MarginToggle
|
||||
checked={isMarginChecked}
|
||||
onChange={handleMarginToggleChange}
|
||||
disabled={!borrowAsset?.isMarket}
|
||||
disabled={!borrowMarket?.borrowEnabled}
|
||||
borrowAssetSymbol={inputAsset.symbol}
|
||||
/>
|
||||
<Divider />
|
||||
@ -411,11 +409,8 @@ export default function SwapForm(props: Props) {
|
||||
className='p-4 bg-white/5'
|
||||
/>
|
||||
|
||||
{borrowAsset && borrowAmount.isGreaterThanOrEqualTo(availableLiquidity) && (
|
||||
<AvailableLiquidityMessage
|
||||
availableLiquidity={borrowAsset?.liquidity?.amount ?? BN_ZERO}
|
||||
asset={borrowAsset}
|
||||
/>
|
||||
{borrowMarket && borrowAmount.isGreaterThanOrEqualTo(availableLiquidity) && (
|
||||
<AvailableLiquidityMessage market={borrowMarket} />
|
||||
)}
|
||||
{isAdvanced ? (
|
||||
<AssetAmountInput
|
||||
@ -450,7 +445,7 @@ export default function SwapForm(props: Props) {
|
||||
<TradeSummary
|
||||
sellAsset={inputAsset}
|
||||
buyAsset={outputAsset}
|
||||
borrowRate={borrowAsset?.borrowRate}
|
||||
borrowRate={borrowMarket?.apy.borrow}
|
||||
buyAction={handleBuyClick}
|
||||
buyButtonDisabled={isSwapDisabled}
|
||||
showProgressIndicator={isConfirming || isRouteLoading}
|
||||
|
@ -6,7 +6,8 @@ import useChainConfig from 'hooks/useChainConfig'
|
||||
export default function useAccountIdsAndKinds(address?: string, suspense = true, noHls = false) {
|
||||
const chainConfig = useChainConfig()
|
||||
return useSWR(
|
||||
`chains/${chainConfig.id}/wallets/${address}/account-ids${noHls && '-without-hls'}`,
|
||||
address &&
|
||||
`chains/${chainConfig.id}/wallets/${address}/account-ids${noHls ? '-without-hls' : ''}`,
|
||||
() =>
|
||||
getAccountIds(chainConfig, address).then((accountIdsAndKinds) => {
|
||||
if (noHls) {
|
||||
|
@ -8,7 +8,7 @@ export default function useAccounts(kind: AccountKind, address?: string, suspens
|
||||
const chainConfig = useChainConfig()
|
||||
|
||||
return useSWR(
|
||||
`chains/${chainConfig.id}/accounts/${kind}`,
|
||||
address && `chains/${chainConfig.id}/accounts/${kind}`,
|
||||
() => getAccounts(kind, chainConfig, address),
|
||||
{
|
||||
suspense: suspense,
|
||||
|
9
src/hooks/markets/useMarket.ts
Normal file
9
src/hooks/markets/useMarket.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import useMarkets from 'hooks/markets/useMarkets'
|
||||
|
||||
export default function useMarket(denom: string) {
|
||||
const markets = useMarkets()
|
||||
|
||||
return useMemo(() => markets.find((market) => market.asset.denom === denom), [denom, markets])
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
import useSWR from 'swr'
|
||||
|
||||
import getMarkets from 'api/markets/getMarkets'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
|
||||
export default function useMarketAssets() {
|
||||
const chainConfig = useChainConfig()
|
||||
return useSWR(`chains/${chainConfig.id}/markets`, () => getMarkets(chainConfig), {
|
||||
suspense: true,
|
||||
fallbackData: [],
|
||||
revalidateOnFocus: false,
|
||||
keepPreviousData: false,
|
||||
})
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import useSWR from 'swr'
|
||||
|
||||
import getMarketBorrowings from 'api/markets/getMarketBorrowings'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
|
||||
export default function useMarketBorrowings() {
|
||||
const chainConfig = useChainConfig()
|
||||
return useSWR(
|
||||
`chains/${chainConfig.id}/markets/borrowings`,
|
||||
() => getMarketBorrowings(chainConfig),
|
||||
{
|
||||
fallbackData: [],
|
||||
suspense: false,
|
||||
revalidateOnFocus: false,
|
||||
},
|
||||
)
|
||||
}
|
26
src/hooks/markets/useMarketDepositCaps.ts
Normal file
26
src/hooks/markets/useMarketDepositCaps.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import useSWR from 'swr'
|
||||
|
||||
import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
import useClients from 'hooks/useClients'
|
||||
|
||||
export default function useMarketDepositCaps() {
|
||||
const chainConfig = useChainConfig()
|
||||
const clients = useClients()
|
||||
const assets = useMarketEnabledAssets()
|
||||
|
||||
return useSWR(
|
||||
assets.length > 0 && clients && `chains/${chainConfig.id}/markets/depositCap`,
|
||||
() => getMarketsDepositCap(clients!, assets),
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false,
|
||||
revalidateIfStale: false,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
async function getMarketsDepositCap(clients: ContractClients, assets: Asset[]) {
|
||||
const capQueries = assets.map((asset) => clients.params.totalDeposit({ denom: asset.denom }))
|
||||
return Promise.all(capQueries)
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
import useSWR from 'swr'
|
||||
|
||||
import getMarketDeposits from 'api/markets/getMarketDeposits'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
|
||||
export default function useMarketDeposits() {
|
||||
const chainConfig = useChainConfig()
|
||||
return useSWR(`chains/${chainConfig.id}/markets/deposits`, () => getMarketDeposits(chainConfig), {
|
||||
suspense: true,
|
||||
fallbackData: [],
|
||||
revalidateOnFocus: false,
|
||||
})
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import useSWR from 'swr'
|
||||
|
||||
import getMarketLiquidities from 'api/markets/getMarketLiquidities'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
|
||||
export default function useMarketLiquidities() {
|
||||
const chainConfig = useChainConfig()
|
||||
return useSWR(
|
||||
`chains/${chainConfig.id}/markets/liquidities`,
|
||||
() => getMarketLiquidities(chainConfig),
|
||||
{
|
||||
suspense: true,
|
||||
fallbackData: [],
|
||||
revalidateOnFocus: false,
|
||||
},
|
||||
)
|
||||
}
|
42
src/hooks/markets/useMarkets.ts
Normal file
42
src/hooks/markets/useMarkets.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import useSWR from 'swr'
|
||||
|
||||
import useMarketDepositCaps from 'hooks/markets/useMarketDepositCaps'
|
||||
import useMarketsInfo from 'hooks/markets/useMarketsInfo'
|
||||
import useAssetParams from 'hooks/params/useAssetParams'
|
||||
import useAssets from 'hooks/useAssets'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
import {
|
||||
AssetParamsBaseForAddr as AssetParams,
|
||||
TotalDepositResponse,
|
||||
} from 'types/generated/mars-params/MarsParams.types'
|
||||
import { Market as RedBankMarket } from 'types/generated/mars-red-bank/MarsRedBank.types'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { resolveMarketResponse } from 'utils/resolvers'
|
||||
|
||||
export default function useMarkets() {
|
||||
const chainConfig = useChainConfig()
|
||||
const { data: marketInfos } = useMarketsInfo()
|
||||
const { data: marketDepositCaps } = useMarketDepositCaps()
|
||||
const { data: assetParams } = useAssetParams()
|
||||
const assets = useAssets()
|
||||
|
||||
return useSWR(
|
||||
!!marketInfos?.length &&
|
||||
!!marketDepositCaps?.length &&
|
||||
!!assetParams.length &&
|
||||
`chains/${chainConfig.id}/markets`,
|
||||
() => {
|
||||
return assets.map((asset) =>
|
||||
resolveMarketResponse(
|
||||
asset,
|
||||
marketInfos!.find(byDenom(asset.denom)) as RedBankMarket & Partial<Market>,
|
||||
assetParams.find(byDenom(asset.denom)) as AssetParams,
|
||||
marketDepositCaps!.find(byDenom(asset.denom)) as TotalDepositResponse,
|
||||
),
|
||||
)
|
||||
},
|
||||
{
|
||||
fallbackData: [],
|
||||
},
|
||||
).data
|
||||
}
|
47
src/hooks/markets/useMarketsInfo.ts
Normal file
47
src/hooks/markets/useMarketsInfo.ts
Normal file
@ -0,0 +1,47 @@
|
||||
import useSWR from 'swr'
|
||||
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
import useClients from 'hooks/useClients'
|
||||
import { BN } from 'utils/helpers'
|
||||
import iterateContractQuery from 'utils/iterateContractQuery'
|
||||
|
||||
export default function useMarketsInfo() {
|
||||
const chainConfig = useChainConfig()
|
||||
const clients = useClients()
|
||||
return useSWR(
|
||||
clients && `chains/${chainConfig.id}/markets/info`,
|
||||
() => getMarketsInfo(clients!),
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false,
|
||||
revalidateIfStale: false,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
async function getMarketsInfo(clients: ContractClients) {
|
||||
const markets = await iterateContractQuery(clients.redBank.markets)
|
||||
|
||||
const debts$ = markets.map((market) =>
|
||||
clients.redBank.underlyingDebtAmount({
|
||||
denom: market.denom,
|
||||
amountScaled: market.debt_total_scaled,
|
||||
}),
|
||||
)
|
||||
|
||||
const liquidities$ = markets.map((market) =>
|
||||
clients.redBank.underlyingLiquidityAmount({
|
||||
denom: market.denom,
|
||||
amountScaled: market.collateral_total_scaled,
|
||||
}),
|
||||
)
|
||||
|
||||
const [debts, liquidity] = await Promise.all([Promise.all(debts$), Promise.all(liquidities$)])
|
||||
|
||||
return markets.map((market, index) => ({
|
||||
...market,
|
||||
debt: BN(debts[index]),
|
||||
deposits: BN(liquidity[index]),
|
||||
liquidity: BN(liquidity[index]).minus(debts[index]),
|
||||
}))
|
||||
}
|
@ -1,15 +1,45 @@
|
||||
import useSWR from 'swr'
|
||||
|
||||
import calculateAssetIncentivesApy from 'api/incentives/calculateAssetIncentivesApy'
|
||||
import getTotalActiveEmissionValue from 'api/incentives/getTotalActiveEmissionValue'
|
||||
import useMarket from 'hooks/markets/useMarket'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
import usePrice from 'hooks/usePrice'
|
||||
import { SECONDS_IN_A_YEAR } from 'utils/constants'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export default function useAssetIncentivesApy(denom: string) {
|
||||
const chainConfig = useChainConfig()
|
||||
const market = useMarket(denom)
|
||||
const price = usePrice(denom)
|
||||
|
||||
return useSWR(
|
||||
`chains/${chainConfig.id}/assets/${denom}/incentives`,
|
||||
() => calculateAssetIncentivesApy(chainConfig, denom),
|
||||
market && `chains/${chainConfig.id}/assets/${denom}/incentives`,
|
||||
() => calculateAssetIncentivesApy(chainConfig, market!, price),
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
async function calculateAssetIncentivesApy(
|
||||
chainConfig: ChainConfig,
|
||||
market: Market,
|
||||
price: BigNumber,
|
||||
) {
|
||||
const totalActiveEmissionValue = await getTotalActiveEmissionValue(
|
||||
chainConfig,
|
||||
market.asset.denom,
|
||||
)
|
||||
|
||||
if (!totalActiveEmissionValue) return null
|
||||
|
||||
const marketLiquidityValue = BN(market.deposits)
|
||||
.shiftedBy(-market.asset.decimals)
|
||||
.multipliedBy(price)
|
||||
|
||||
const marketReturns = BN(market.apy.deposit).multipliedBy(marketLiquidityValue)
|
||||
const annualEmission = totalActiveEmissionValue.multipliedBy(SECONDS_IN_A_YEAR)
|
||||
|
||||
const totalAnnualReturnsValue = annualEmission.plus(marketReturns)
|
||||
return totalAnnualReturnsValue.dividedBy(marketLiquidityValue).multipliedBy(100)
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
import useMarketBorrowings from 'hooks/markets/useMarketBorrowings'
|
||||
import { byDenom } from 'utils/array'
|
||||
|
||||
export default function useBorrowAsset(denom: string) {
|
||||
const { data: borrowAssets } = useMarketBorrowings()
|
||||
|
||||
if (!borrowAssets.length) return null
|
||||
|
||||
return borrowAssets.find(byDenom(denom))
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
|
||||
export default function useBorrowEnabledMarkets() {
|
||||
const { data: markets } = useMarketAssets()
|
||||
return useMemo(() => markets.filter((market) => market.borrowEnabled), [markets])
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import useMarketBorrowings from 'hooks/markets/useMarketBorrowings'
|
||||
import useMarketDeposits from 'hooks/markets/useMarketDeposits'
|
||||
import useMarketLiquidities from 'hooks/markets/useMarketLiquidities'
|
||||
import useBorrowEnabledMarkets from 'hooks/useBorrowEnabledMarkets'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export default function useBorrowMarketAssetsTableData() {
|
||||
const markets = useBorrowEnabledMarkets()
|
||||
const account = useCurrentAccount()
|
||||
const { data: borrowData } = useMarketBorrowings()
|
||||
const { data: marketDeposits } = useMarketDeposits()
|
||||
const { data: marketLiquidities } = useMarketLiquidities()
|
||||
const assets = useAllAssets()
|
||||
|
||||
return useMemo((): {
|
||||
accountBorrowedAssets: BorrowMarketTableData[]
|
||||
availableAssets: BorrowMarketTableData[]
|
||||
allAssets: BorrowMarketTableData[]
|
||||
} => {
|
||||
const accountBorrowedAssets: BorrowMarketTableData[] = [],
|
||||
availableAssets: BorrowMarketTableData[] = []
|
||||
|
||||
markets.forEach(({ denom, apy, ltv }) => {
|
||||
const asset = assets.find(byDenom(denom)) as Asset
|
||||
const borrow = borrowData.find((borrow) => borrow.denom === denom)
|
||||
const marketDepositAmount = BN(marketDeposits.find(byDenom(denom))?.amount ?? 0)
|
||||
const marketLiquidityAmount = BN(marketLiquidities.find(byDenom(denom))?.amount ?? 0)
|
||||
|
||||
const debt = account?.debts?.find((debt) => debt.denom === denom)
|
||||
if (!borrow) return
|
||||
|
||||
const borrowMarketAsset: BorrowMarketTableData = {
|
||||
...borrow,
|
||||
asset,
|
||||
debt: debt?.amount,
|
||||
marketDepositAmount,
|
||||
marketLiquidityAmount,
|
||||
apy,
|
||||
ltv,
|
||||
}
|
||||
;(borrowMarketAsset.debt ? accountBorrowedAssets : availableAssets).push(borrowMarketAsset)
|
||||
})
|
||||
|
||||
return {
|
||||
accountBorrowedAssets,
|
||||
availableAssets,
|
||||
allAssets: [...accountBorrowedAssets, ...availableAssets],
|
||||
}
|
||||
}, [account?.debts, assets, borrowData, marketDeposits, marketLiquidities, markets])
|
||||
}
|
@ -34,6 +34,9 @@ export default function useClients() {
|
||||
} as ContractClients
|
||||
},
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
revalidateOnReconnect: false,
|
||||
revalidateIfStale: false,
|
||||
keepPreviousData: false,
|
||||
},
|
||||
)
|
||||
|
@ -1,6 +0,0 @@
|
||||
import useMarketAssets from 'hooks/markets/useMarketAssets'
|
||||
|
||||
export default function useDepositEnabledMarkets() {
|
||||
const { data: markets } = useMarketAssets()
|
||||
return markets.filter((market) => market.depositEnabled)
|
||||
}
|
@ -5,8 +5,12 @@ import useChainConfig from 'hooks/useChainConfig'
|
||||
|
||||
export default function useHLSStakingAssets() {
|
||||
const chainConfig = useChainConfig()
|
||||
return useSWR('hls-staking', () => getHLSStakingAssets(chainConfig), {
|
||||
fallbackData: [],
|
||||
revalidateOnFocus: false,
|
||||
})
|
||||
return useSWR(
|
||||
`chains/${chainConfig.id}/assets/hls/staking`,
|
||||
() => getHLSStakingAssets(chainConfig),
|
||||
{
|
||||
fallbackData: [],
|
||||
revalidateOnFocus: false,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import useVaults from 'hooks/useVaults'
|
||||
|
||||
export default function useVault(address: string) {
|
||||
const { data: vaults } = useVaults(false)
|
||||
|
||||
if (!vaults?.length) return null
|
||||
|
||||
return vaults.find((v) => v.address === address) ?? null
|
||||
return useMemo(() => vaults?.find((v) => v.address === address) ?? null, [vaults, address])
|
||||
}
|
||||
|
@ -6,8 +6,12 @@ import useChainConfig from 'hooks/useChainConfig'
|
||||
export default function useVaults(suspense: boolean = true, address?: string) {
|
||||
const chainConfig = useChainConfig()
|
||||
|
||||
return useSWR(`chains/${chainConfig.id}/vaults/${address}`, () => getVaults(chainConfig), {
|
||||
suspense,
|
||||
revalidateOnFocus: false,
|
||||
})
|
||||
return useSWR(
|
||||
address && `chains/${chainConfig.id}/vaults/${address}`,
|
||||
() => getVaults(chainConfig),
|
||||
{
|
||||
suspense,
|
||||
revalidateOnFocus: false,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ export default function useWalletBalances(address?: string) {
|
||||
const chainConfig = useChainConfig()
|
||||
|
||||
return useSWR(
|
||||
`chains/${chainConfig.id}/wallets/${address}/balances`,
|
||||
address && `chains/${chainConfig.id}/wallets/${address}/balances`,
|
||||
() => getWalletBalances(chainConfig, address || ''),
|
||||
{
|
||||
isPaused: () => !address,
|
||||
|
@ -2,19 +2,21 @@ import classNames from 'classnames'
|
||||
import { Suspense } from 'react'
|
||||
import { isMobile } from 'react-device-detect'
|
||||
import { useLocation } from 'react-router-dom'
|
||||
import { SWRConfig } from 'swr'
|
||||
|
||||
import AccountDetails from 'components/account/AccountDetails'
|
||||
import Background from 'components/common/Background'
|
||||
import Footer from 'components/common/Footer'
|
||||
import DesktopHeader from 'components/header/DesktopHeader'
|
||||
import ModalsContainer from 'components/Modals/ModalsContainer'
|
||||
import PageMetadata from 'components/common/PageMetadata'
|
||||
import Toaster from 'components/common/Toaster'
|
||||
import DesktopHeader from 'components/header/DesktopHeader'
|
||||
import ModalsContainer from 'components/Modals/ModalsContainer'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
import { LocalStorageKeys } from 'constants/localStorageKeys'
|
||||
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
||||
import useAccountId from 'hooks/useAccountId'
|
||||
import useStore from 'store'
|
||||
import { debugSWR } from 'utils/middleware'
|
||||
|
||||
interface Props {
|
||||
focusComponent: FocusComponent | null
|
||||
@ -62,36 +64,38 @@ export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageMetadata />
|
||||
<Background />
|
||||
<DesktopHeader />
|
||||
<main
|
||||
className={classNames(
|
||||
'lg:min-h-[calc(100dvh-73px)]',
|
||||
'lg:mt-[73px]',
|
||||
'flex',
|
||||
'min-h-screen gap-6 px-4 py-6 w-full relative',
|
||||
!focusComponent &&
|
||||
address &&
|
||||
isFullWidth &&
|
||||
accountId &&
|
||||
(accountDetailsExpanded ? 'pr-118' : 'pr-24'),
|
||||
!reduceMotion && isFullWidth && 'transition-all duration-300',
|
||||
'justify-center',
|
||||
focusComponent && 'items-center',
|
||||
isMobile && 'items-start',
|
||||
)}
|
||||
>
|
||||
<Suspense>
|
||||
<PageContainer focusComponent={focusComponent} fullWidth={isFullWidth}>
|
||||
{children}
|
||||
</PageContainer>
|
||||
</Suspense>
|
||||
<AccountDetails />
|
||||
</main>
|
||||
<Footer />
|
||||
<ModalsContainer />
|
||||
<Toaster />
|
||||
<SWRConfig value={{ use: [debugSWR] }}>
|
||||
<PageMetadata />
|
||||
<Background />
|
||||
<DesktopHeader />
|
||||
<main
|
||||
className={classNames(
|
||||
'lg:min-h-[calc(100dvh-73px)]',
|
||||
'lg:mt-[73px]',
|
||||
'flex',
|
||||
'min-h-screen gap-6 px-4 py-6 w-full relative',
|
||||
!focusComponent &&
|
||||
address &&
|
||||
isFullWidth &&
|
||||
accountId &&
|
||||
(accountDetailsExpanded ? 'pr-118' : 'pr-24'),
|
||||
!reduceMotion && isFullWidth && 'transition-all duration-300',
|
||||
'justify-center',
|
||||
focusComponent && 'items-center',
|
||||
isMobile && 'items-start',
|
||||
)}
|
||||
>
|
||||
<Suspense>
|
||||
<PageContainer focusComponent={focusComponent} fullWidth={isFullWidth}>
|
||||
{children}
|
||||
</PageContainer>
|
||||
</Suspense>
|
||||
<AccountDetails />
|
||||
</main>
|
||||
<Footer />
|
||||
<ModalsContainer />
|
||||
<Toaster />
|
||||
</SWRConfig>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
29
src/types/interfaces/asset.d.ts
vendored
29
src/types/interfaces/asset.d.ts
vendored
@ -50,35 +50,6 @@ interface BigNumberCoin {
|
||||
amount: BigNumber
|
||||
}
|
||||
|
||||
interface BorrowMarketTableData extends MarketTableData {
|
||||
liquidity: {
|
||||
amount: BigNumber
|
||||
value: BigNumber
|
||||
} | null
|
||||
debt?: BigNumber
|
||||
}
|
||||
|
||||
interface LendingMarketTableData extends MarketTableData {
|
||||
accountLentAmount?: BigNumber
|
||||
accountLentValue?: BigNumber
|
||||
borrowEnabled: boolean
|
||||
cap: DepositCap
|
||||
}
|
||||
|
||||
interface MarketTableData {
|
||||
asset: Asset
|
||||
marketDepositAmount: BigNumber
|
||||
marketLiquidityAmount: BigNumber
|
||||
apy: {
|
||||
borrow: number
|
||||
deposit: number
|
||||
}
|
||||
ltv: {
|
||||
max: number
|
||||
liq: number
|
||||
}
|
||||
}
|
||||
|
||||
interface HLSStrategy extends HLSStrategyNoCap {
|
||||
depositCap: DepositCap
|
||||
}
|
||||
|
18
src/types/interfaces/market.d.ts
vendored
18
src/types/interfaces/market.d.ts
vendored
@ -1,10 +1,11 @@
|
||||
interface Market {
|
||||
denom: string
|
||||
debtTotalScaled: string
|
||||
collateralTotalScaled: string
|
||||
asset: Asset
|
||||
cap: DepositCap // Deposits via CM
|
||||
debt: BigNumber // Total outstanding debt
|
||||
deposits: BigNumber // Deposits directly into the RB
|
||||
liquidity: BigNumber // Available liqudiity to be borrowed
|
||||
depositEnabled: boolean
|
||||
borrowEnabled: boolean
|
||||
cap: DepositCap
|
||||
apy: {
|
||||
borrow: number
|
||||
deposit: number
|
||||
@ -14,3 +15,12 @@ interface Market {
|
||||
liq: number
|
||||
}
|
||||
}
|
||||
|
||||
interface BorrowMarketTableData extends Market {
|
||||
accountDebt?: BigNumber
|
||||
}
|
||||
|
||||
interface LendingMarketTableData extends Market {
|
||||
accountLentAmount?: BigNumber
|
||||
accountLentValue?: BigNumber
|
||||
}
|
||||
|
@ -14,11 +14,11 @@ function isAssetPair(assetPair: Asset | AssetPair): assetPair is AssetPair {
|
||||
export function sortAssetsOrPairs(
|
||||
assets: Asset[] | AssetPair[],
|
||||
prices: BNCoin[],
|
||||
marketDeposits: BNCoin[],
|
||||
markets: Market[],
|
||||
balances: BNCoin[],
|
||||
baseDenom: string,
|
||||
): Asset[] | AssetPair[] {
|
||||
if (prices.length === 0 || marketDeposits.length === 0) return assets
|
||||
if (prices.length === 0 || markets.length === 0) return assets
|
||||
|
||||
return assets.sort((a, b) => {
|
||||
const assetA = isAssetPair(a) ? a.buy : a
|
||||
@ -37,8 +37,10 @@ export function sortAssetsOrPairs(
|
||||
if (aDenom === baseDenom) return -1
|
||||
if (bDenom === baseDenom) return 1
|
||||
|
||||
const aMarketDeposit = marketDeposits?.find(byDenom(aDenom))?.amount ?? BN_ZERO
|
||||
const bMarketDeposit = marketDeposits?.find(byDenom(bDenom))?.amount ?? BN_ZERO
|
||||
const aMarketDeposit =
|
||||
markets.find((market) => market.asset.denom === aDenom)?.deposits ?? BN_ZERO
|
||||
const bMarketDeposit =
|
||||
markets.find((market) => market.asset.denom === bDenom)?.deposits ?? BN_ZERO
|
||||
const aMarketValue = demagnify(aMarketDeposit, assetA) * aPrice.toNumber()
|
||||
const bMarketValue = demagnify(bMarketDeposit, assetB) * bPrice.toNumber()
|
||||
|
||||
|
13
src/utils/middleware.ts
Normal file
13
src/utils/middleware.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { Middleware, SWRHook } from 'swr'
|
||||
|
||||
export const debugSWR: Middleware = (useSWRNext: SWRHook) => (key, fetcher, config) => {
|
||||
const extendedFetcher = async (...args: any[]) => {
|
||||
const startTime = Date.now()
|
||||
const res = await fetcher!(...args)
|
||||
process.env.NODE_ENV !== 'production' &&
|
||||
console.log('⬇️ GET: ', key, ' in ', Date.now() - startTime, 'ms')
|
||||
return res
|
||||
}
|
||||
// ...
|
||||
return useSWRNext(key, extendedFetcher, config)
|
||||
}
|
@ -11,18 +11,20 @@ import { BN, getLeverageFromLTV } from 'utils/helpers'
|
||||
import { convertAprToApy } from 'utils/parsers'
|
||||
|
||||
export function resolveMarketResponse(
|
||||
marketResponse: RedBankMarket,
|
||||
asset: Asset,
|
||||
marketResponse: RedBankMarket & Partial<Market>,
|
||||
assetParamsResponse: AssetParams,
|
||||
assetCapResponse: TotalDepositResponse,
|
||||
): Market {
|
||||
return {
|
||||
denom: marketResponse.denom,
|
||||
asset,
|
||||
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,
|
||||
debt: marketResponse.debt ?? BN_ZERO,
|
||||
deposits: marketResponse.deposits ?? BN_ZERO,
|
||||
liquidity: marketResponse.liquidity ?? BN_ZERO,
|
||||
depositEnabled: assetParamsResponse.red_bank.deposit_enabled,
|
||||
borrowEnabled: assetParamsResponse.red_bank.borrow_enabled,
|
||||
cap: {
|
||||
|
Loading…
Reference in New Issue
Block a user