Moved Markets data to SWR (#749)

This commit is contained in:
Bob van der Helm 2024-01-26 16:55:45 +01:00 committed by GitHub
parent 7cfe05ebb7
commit a00c8e391b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
77 changed files with 604 additions and 810 deletions

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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'))
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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'))
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -1,9 +1,9 @@
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import AssetsSelect from 'components/Modals/AssetsSelect'
import SearchBar from 'components/common/SearchBar' import SearchBar from 'components/common/SearchBar'
import Text from 'components/common/Text' 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' import useStore from 'store'
interface Props { interface Props {
@ -14,16 +14,16 @@ interface Props {
export default function AddVaultAssetsModalContent(props: Props) { export default function AddVaultAssetsModalContent(props: Props) {
const [searchString, setSearchString] = useState<string>('') const [searchString, setSearchString] = useState<string>('')
const { data: borrowAssets } = useMarketBorrowings() const markets = useMarkets()
const filteredBorrowAssets: BorrowAsset[] = useMemo(() => { const filteredMarkets: Market[] = useMemo(() => {
return borrowAssets.filter( return markets.filter(
(asset) => (market) =>
asset.name.toLowerCase().includes(searchString.toLowerCase()) || market.asset.name.toLowerCase().includes(searchString.toLowerCase()) ||
asset.denom.toLowerCase().includes(searchString.toLowerCase()) || market.asset.denom.toLowerCase().includes(searchString.toLowerCase()) ||
asset.symbol.toLowerCase().includes(searchString.toLowerCase()), market.asset.symbol.toLowerCase().includes(searchString.toLowerCase()),
) )
}, [borrowAssets, searchString]) }, [markets, searchString])
function onChangeSearchString(value: string) { function onChangeSearchString(value: string) {
setSearchString(value) setSearchString(value)
@ -31,21 +31,21 @@ export default function AddVaultAssetsModalContent(props: Props) {
const [poolAssets, stableAssets] = useMemo( const [poolAssets, stableAssets] = useMemo(
() => () =>
filteredBorrowAssets.reduce( filteredMarkets.reduce(
(acc, asset) => { (acc, market) => {
if ( if (
asset.denom === props.vault.denoms.primary || market.asset.denom === props.vault.denoms.primary ||
asset.denom === props.vault.denoms.secondary market.asset.denom === props.vault.denoms.secondary
) { ) {
acc[0].push(asset) acc[0].push(market.asset)
} else if (asset.isStable) { } else if (market.asset.isStable) {
acc[1].push(asset) acc[1].push(market.asset)
} }
return acc 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) const selectedDenoms = useStore((s) => s.addVaultBorrowingsModal?.selectedDenoms)

View File

@ -1,15 +1,16 @@
import { RowSelectionState } from '@tanstack/react-table' import { RowSelectionState } from '@tanstack/react-table'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import useAssetSelectColumns from 'components/Modals/AssetsSelect/Columns/useAssetSelectColumns'
import Table from 'components/common/Table' import Table from 'components/common/Table'
import useAssetSelectColumns from 'components/Modals/AssetsSelect/Columns/useAssetSelectColumns'
import useGetCoinValue from 'hooks/assets/useGetCoinValue' import useGetCoinValue from 'hooks/assets/useGetCoinValue'
import useMarketAssets from 'hooks/markets/useMarketAssets' import useMarkets from 'hooks/markets/useMarkets'
import useStore from 'store' import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin' import { BNCoin } from 'types/classes/BNCoin'
import { byDenom } from 'utils/array' import { byDenom } from 'utils/array'
import { BN } from 'utils/helpers' import { BN } from 'utils/helpers'
// TODO: Pass the market data directly here instead of the assets
interface Props { interface Props {
assets: Asset[] assets: Asset[]
onChangeSelected: (selected: string[]) => void onChangeSelected: (selected: string[]) => void
@ -20,12 +21,11 @@ interface Props {
export default function AssetsSelect(props: Props) { export default function AssetsSelect(props: Props) {
const { assets, onChangeSelected, selectedDenoms, isBorrow } = props const { assets, onChangeSelected, selectedDenoms, isBorrow } = props
const columns = useAssetSelectColumns(isBorrow) const columns = useAssetSelectColumns(isBorrow)
const { data: markets } = useMarketAssets() const markets = useMarkets()
const getCoinValue = useGetCoinValue() const getCoinValue = useGetCoinValue()
const defaultSelected = useMemo(() => { const defaultSelected = useMemo(() => {
const selectableAssets = assets return assets.reduce(
return selectableAssets.reduce(
(acc, asset, index) => { (acc, asset, index) => {
if (selectedDenoms?.includes(asset.denom)) { if (selectedDenoms?.includes(asset.denom)) {
acc[index] = true acc[index] = true
@ -48,7 +48,7 @@ export default function AssetsSelect(props: Props) {
asset, asset,
balance: balancesForAsset?.amount ?? '0', balance: balancesForAsset?.amount ?? '0',
value, value,
market: markets.find((market) => market.denom === asset.denom), market: markets.find((market) => market.asset.denom === asset.denom),
} }
}) })
}, [balances, assets, markets, getCoinValue]) }, [balances, assets, markets, getCoinValue])

View File

@ -16,7 +16,7 @@ import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSli
import Modal from 'components/Modals/Modal' import Modal from 'components/Modals/Modal'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import useCurrentAccount from 'hooks/accounts/useCurrentAccount' import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import useMarketAssets from 'hooks/markets/useMarketAssets' import useMarkets from 'hooks/markets/useMarkets'
import useAutoLend from 'hooks/useAutoLend' import useAutoLend from 'hooks/useAutoLend'
import useHealthComputer from 'hooks/useHealthComputer' import useHealthComputer from 'hooks/useHealthComputer'
import useToggle from 'hooks/useToggle' import useToggle from 'hooks/useToggle'
@ -91,7 +91,7 @@ function BorrowModal(props: Props) {
const isAutoLendEnabled = autoLendEnabledAccountIds.includes(account.id) const isAutoLendEnabled = autoLendEnabledAccountIds.includes(account.id)
const { computeMaxBorrowAmount } = useHealthComputer(account) const { computeMaxBorrowAmount } = useHealthComputer(account)
const totalDebt = BN(getDebtAmount(modal)) const totalDebt = BN(getDebtAmount(modal))
const { data: marketAssets } = useMarketAssets() const markets = useMarkets()
const [depositBalance, lendBalance] = useMemo( const [depositBalance, lendBalance] = useMemo(
() => [ () => [
@ -107,13 +107,13 @@ function BorrowModal(props: Props) {
) )
const overpayExeedsCap = useMemo(() => { const overpayExeedsCap = useMemo(() => {
const marketAsset = marketAssets.find(byDenom(asset.denom)) const marketAsset = markets.find(byDenom(asset.denom))
if (!marketAsset) return if (!marketAsset) return
const overpayAmount = totalDebtRepayAmount.minus(totalDebt) const overpayAmount = totalDebtRepayAmount.minus(totalDebt)
const marketCapAfterOverpay = marketAsset.cap.used.plus(overpayAmount) const marketCapAfterOverpay = marketAsset.cap.used.plus(overpayAmount)
return marketAsset.cap.max.isLessThanOrEqualTo(marketCapAfterOverpay) return marketAsset.cap.max.isLessThanOrEqualTo(marketCapAfterOverpay)
}, [marketAssets, asset.denom, totalDebt, totalDebtRepayAmount]) }, [markets, asset.denom, totalDebt, totalDebtRepayAmount])
const maxRepayAmount = useMemo(() => { const maxRepayAmount = useMemo(() => {
const maxBalance = repayFromWallet const maxBalance = repayFromWallet
@ -187,7 +187,7 @@ function BorrowModal(props: Props) {
? BN_ZERO ? BN_ZERO
: computeMaxBorrowAmount(asset.denom, borrowToWallet ? 'wallet' : 'deposit') : 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]) }, [asset.denom, borrowToWallet, computeMaxBorrowAmount, isRepay, modal.marketData])
useEffect(() => { useEffect(() => {
@ -266,7 +266,7 @@ function BorrowModal(props: Props) {
<div className='flex gap-2'> <div className='flex gap-2'>
<FormattedNumber <FormattedNumber
className='text-xs' 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}` }} options={{ decimals: asset.decimals, abbreviated: true, suffix: ` ${asset.symbol}` }}
animate animate
/> />
@ -274,7 +274,7 @@ function BorrowModal(props: Props) {
className='text-xs' className='text-xs'
coin={BNCoin.fromDenomAndBigNumber( coin={BNCoin.fromDenomAndBigNumber(
asset.denom, asset.denom,
modal.marketData?.liquidity?.amount ?? BN_ZERO, modal.marketData?.liquidity ?? BN_ZERO,
)} )}
parentheses parentheses
/> />

View File

@ -2,13 +2,13 @@ import React, { useMemo } from 'react'
import Button from 'components/common/Button' import Button from 'components/common/Button'
import { ArrowRight } from 'components/common/Icons' import { ArrowRight } from 'components/common/Icons'
import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary'
import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider' import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary'
import { getLeveragedApy } from 'utils/math' import { getLeveragedApy } from 'utils/math'
interface Props { interface Props {
amount: BigNumber amount: BigNumber
asset: BorrowAsset borrowMarket: Market
max: BigNumber max: BigNumber
onChangeAmount: (amount: BigNumber) => void onChangeAmount: (amount: BigNumber) => void
onClickBtn: () => void onClickBtn: () => void
@ -21,15 +21,15 @@ interface Props {
export default function Leverage(props: Props) { export default function Leverage(props: Props) {
const apy = useMemo(() => { const apy = useMemo(() => {
if (!props.asset.borrowRate) return 0 if (!props.borrowMarket.apy.borrow) return 0
return getLeveragedApy(props.baseApy, props.asset.borrowRate, props.leverage) return getLeveragedApy(props.baseApy, props.borrowMarket.apy.borrow, props.leverage)
}, [props.asset.borrowRate, props.baseApy, props.leverage]) }, [props.baseApy, props.borrowMarket.apy.borrow, props.leverage])
return ( return (
<div id='item-1' className='flex-col gap-6 flex justify-between h-full p-4'> <div id='item-1' className='flex-col gap-6 flex justify-between h-full p-4'>
<TokenInputWithSlider <TokenInputWithSlider
amount={props.amount} amount={props.amount}
asset={props.asset} asset={props.borrowMarket.asset}
max={props.max} max={props.max}
onChange={props.onChangeAmount} onChange={props.onChangeAmount}
maxText='Max borrow' maxText='Max borrow'
@ -40,7 +40,11 @@ export default function Leverage(props: Props) {
warningMessages={props.warningMessages} warningMessages={props.warningMessages}
/> />
<div className='flex flex-col gap-6'> <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 />} /> <Button onClick={props.onClickBtn} text='Continue' rightIcon={<ArrowRight />} />
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import React, { useMemo } from 'react' import React, { useMemo } from 'react'
import SummaryItems from 'components/common/SummaryItems' import SummaryItems from 'components/common/SummaryItems'
import useBorrowAsset from 'hooks/useBorrowAsset' import useMarket from 'hooks/markets/useMarket'
interface Props { interface Props {
asset: Asset asset: Asset
@ -10,7 +10,7 @@ interface Props {
} }
export default function LeverageSummary(props: Props) { export default function LeverageSummary(props: Props) {
const borrowAsset = useBorrowAsset(props.asset.denom) const market = useMarket(props.asset.denom)
const items: SummaryItem[] = useMemo(() => { const items: SummaryItem[] = useMemo(() => {
return [ return [
@ -21,7 +21,7 @@ export default function LeverageSummary(props: Props) {
}, },
{ {
title: `Borrow APR ${props.asset.symbol}`, title: `Borrow APR ${props.asset.symbol}`,
amount: borrowAsset?.borrowRate || 0, amount: market?.apy.borrow || 0,
options: { suffix: '%', minDecimals: 2, maxDecimals: 2 }, options: { suffix: '%', minDecimals: 2, maxDecimals: 2 },
}, },
{ {
@ -30,7 +30,7 @@ export default function LeverageSummary(props: Props) {
options: { prefix: '$' }, 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} /> return <SummaryItems items={items} />
} }

View File

@ -4,13 +4,12 @@ import Button from 'components/common/Button'
import { ArrowRight } from 'components/common/Icons' import { ArrowRight } from 'components/common/Icons'
import AssetSummary from 'components/Modals/HLS/Deposit/Summary/AssetSummary' import AssetSummary from 'components/Modals/HLS/Deposit/Summary/AssetSummary'
import YourPosition from 'components/Modals/HLS/Deposit/Summary/YourPosition' import YourPosition from 'components/Modals/HLS/Deposit/Summary/YourPosition'
import useBorrowAsset from 'hooks/useBorrowAsset'
import { BNCoin } from 'types/classes/BNCoin' import { BNCoin } from 'types/classes/BNCoin'
interface Props { interface Props {
apy: number apy: number
borrowAmount: BigNumber borrowAmount: BigNumber
borrowAsset: Asset borrowMarket: Market
collateralAsset: Asset collateralAsset: Asset
depositAmount: BigNumber depositAmount: BigNumber
leverage: number leverage: number
@ -20,18 +19,14 @@ interface Props {
} }
export default function Summary(props: Props) { export default function Summary(props: Props) {
const borrowAsset = useBorrowAsset(props.borrowAsset.denom)
if (!borrowAsset) return null
return ( return (
<div id='item-3' className='p-4 flex flex-col gap-4'> <div id='item-3' className='p-4 flex flex-col gap-4'>
<AssetSummary asset={props.collateralAsset} amount={props.depositAmount} /> <AssetSummary asset={props.collateralAsset} amount={props.depositAmount} />
<AssetSummary asset={borrowAsset} amount={props.borrowAmount} isBorrow /> <AssetSummary asset={props.borrowMarket.asset} amount={props.borrowAmount} isBorrow />
<YourPosition <YourPosition
positionValue={BNCoin.fromDenomAndBigNumber('usd', props.positionValue)} positionValue={BNCoin.fromDenomAndBigNumber('usd', props.positionValue)}
baseApy={props.apy || 0} baseApy={props.apy || 0}
borrowRate={borrowAsset.borrowRate || 0} borrowRate={props.borrowMarket.apy.borrow || 0}
leverage={props.leverage} leverage={props.leverage}
/> />
<Button <Button

View File

@ -13,7 +13,7 @@ import useStore from 'store'
import { isAccountEmpty } from 'utils/accounts' import { isAccountEmpty } from 'utils/accounts'
interface Props { interface Props {
borrowAsset: BorrowAsset borrowMarket: Market
collateralAsset: Asset collateralAsset: Asset
vaultAddress: string | null vaultAddress: string | null
strategy?: HLSStrategy strategy?: HLSStrategy
@ -42,7 +42,7 @@ export default function Controller(props: Props) {
walletCollateralAsset={walletCollateralAsset} walletCollateralAsset={walletCollateralAsset}
vault={vault} vault={vault}
collateralAsset={props.collateralAsset} collateralAsset={props.collateralAsset}
borrowAsset={props.borrowAsset} borrowMarket={props.borrowMarket}
emptyHlsAccounts={emptyHlsAccounts} emptyHlsAccounts={emptyHlsAccounts}
hlsAccounts={hlsAccounts} hlsAccounts={hlsAccounts}
isOpen={isOpen} isOpen={isOpen}
@ -57,7 +57,7 @@ export default function Controller(props: Props) {
<StakingContent <StakingContent
walletCollateralAsset={walletCollateralAsset} walletCollateralAsset={walletCollateralAsset}
collateralAsset={props.collateralAsset} collateralAsset={props.collateralAsset}
borrowAsset={props.borrowAsset} borrowMarket={props.borrowMarket}
emptyHlsAccounts={emptyHlsAccounts} emptyHlsAccounts={emptyHlsAccounts}
hlsAccounts={hlsAccounts} hlsAccounts={hlsAccounts}
isOpen={isOpen} isOpen={isOpen}
@ -73,7 +73,7 @@ export default function Controller(props: Props) {
} }
interface ContentProps { interface ContentProps {
borrowAsset: BorrowAsset borrowMarket: Market
collateralAsset: Asset collateralAsset: Asset
emptyHlsAccounts: Account[] emptyHlsAccounts: Account[]
hlsAccounts: Account[] hlsAccounts: Account[]
@ -102,14 +102,14 @@ function Vault(props: VaultContentProps) {
} = useVaultController({ } = useVaultController({
vault: props.vault, vault: props.vault,
collateralAsset: props.collateralAsset, collateralAsset: props.collateralAsset,
borrowAsset: props.borrowAsset, borrowMarket: props.borrowMarket,
selectedAccount: props.selectedAccount, selectedAccount: props.selectedAccount,
}) })
const items = useAccordionItems({ const items = useAccordionItems({
apy: props.vault.apy || 0, apy: props.vault.apy || 0,
borrowAmount, borrowAmount,
borrowAsset: props.borrowAsset, borrowMarket: props.borrowMarket,
collateralAsset: props.collateralAsset, collateralAsset: props.collateralAsset,
depositAmount, depositAmount,
emptyHlsAccounts: props.emptyHlsAccounts, emptyHlsAccounts: props.emptyHlsAccounts,
@ -148,13 +148,13 @@ function StakingContent(props: StakingContentProps) {
execute, execute,
} = useStakingController({ } = useStakingController({
collateralAsset: props.collateralAsset, collateralAsset: props.collateralAsset,
borrowAsset: props.borrowAsset, borrowMarket: props.borrowMarket,
selectedAccount: props.selectedAccount, selectedAccount: props.selectedAccount,
}) })
const items = useAccordionItems({ const items = useAccordionItems({
borrowAmount, borrowAmount,
borrowAsset: props.borrowAsset, borrowMarket: props.borrowMarket,
collateralAsset: props.collateralAsset, collateralAsset: props.collateralAsset,
depositAmount, depositAmount,
emptyHlsAccounts: props.emptyHlsAccounts, emptyHlsAccounts: props.emptyHlsAccounts,

View File

@ -26,7 +26,7 @@ import {
interface Props { interface Props {
apy: number apy: number
borrowAmount: BigNumber borrowAmount: BigNumber
borrowAsset: BorrowAsset borrowMarket: Market
collateralAsset: Asset collateralAsset: Asset
depositAmount: BigNumber depositAmount: BigNumber
emptyHlsAccounts: Account[] emptyHlsAccounts: Account[]
@ -56,18 +56,24 @@ export default function useAccordionItems(props: Props) {
}, [props.strategy]) }, [props.strategy])
const borrowLiquidity = useMemo( const borrowLiquidity = useMemo(
() => props.borrowAsset.liquidity?.amount || BN_ZERO, () => props.borrowMarket.liquidity || BN_ZERO,
[props.borrowAsset.liquidity?.amount], [props.borrowMarket.liquidity],
) )
const additionalDepositFromSwap = useMemo(() => { const additionalDepositFromSwap = useMemo(() => {
const value = getCoinValue( const value = getCoinValue(
BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, props.borrowAmount), BNCoin.fromDenomAndBigNumber(props.borrowMarket.asset.denom, props.borrowAmount),
prices, prices,
assets, assets,
) )
return getCoinAmount(props.collateralAsset.denom, value, 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 collateralWarningMessages = useMemo(() => {
const messages: string[] = [] const messages: string[] = []
@ -96,16 +102,23 @@ export default function useAccordionItems(props: Props) {
if (props.borrowAmount.isGreaterThan(props.maxBorrowAmount)) { if (props.borrowAmount.isGreaterThan(props.maxBorrowAmount)) {
messages.push( messages.push(
getHealthFactorMessage(props.borrowAsset.denom, props.maxBorrowAmount, 'borrow', assets), getHealthFactorMessage(
props.borrowMarket.asset.denom,
props.maxBorrowAmount,
'borrow',
assets,
),
) )
} }
if (props.borrowAmount.isGreaterThan(borrowLiquidity)) { 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)) { 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 return messages
@ -115,7 +128,7 @@ export default function useAccordionItems(props: Props) {
borrowLiquidity, borrowLiquidity,
depositCapLeft, depositCapLeft,
props.borrowAmount, props.borrowAmount,
props.borrowAsset.denom, props.borrowMarket.asset.denom,
props.depositAmount, props.depositAmount,
props.maxBorrowAmount, props.maxBorrowAmount,
]) ])
@ -160,7 +173,7 @@ export default function useAccordionItems(props: Props) {
<Leverage <Leverage
leverage={props.leverage} leverage={props.leverage}
amount={props.borrowAmount} amount={props.borrowAmount}
asset={props.borrowAsset} borrowMarket={props.borrowMarket}
onChangeAmount={props.onChangeDebt} onChangeAmount={props.onChangeDebt}
onClickBtn={() => props.toggleIsOpen(2)} onClickBtn={() => props.toggleIsOpen(2)}
max={props.maxBorrowAmount} max={props.maxBorrowAmount}
@ -228,7 +241,7 @@ export default function useAccordionItems(props: Props) {
leverage={props.leverage} leverage={props.leverage}
positionValue={props.positionValue} positionValue={props.positionValue}
collateralAsset={props.collateralAsset} collateralAsset={props.collateralAsset}
borrowAsset={props.borrowAsset} borrowMarket={props.borrowMarket}
apy={props.apy} apy={props.apy}
onClickBtn={props.execute} onClickBtn={props.execute}
disabled={ disabled={

View File

@ -10,17 +10,17 @@ import { SWAP_FEE_BUFFER } from 'utils/constants'
import { BN } from 'utils/helpers' import { BN } from 'utils/helpers'
interface Props { interface Props {
borrowAsset: Asset borrowMarket: Market
collateralAsset: Asset collateralAsset: Asset
selectedAccount: Account selectedAccount: Account
} }
export default function useStakingController(props: Props) { export default function useStakingController(props: Props) {
const { collateralAsset, borrowAsset, selectedAccount } = props const { collateralAsset, borrowMarket, selectedAccount } = props
const addToStakingStrategy = useStore((s) => s.addToStakingStrategy) const addToStakingStrategy = useStore((s) => s.addToStakingStrategy)
const { data: swapValueLoss } = useSwapValueLoss( const { data: swapValueLoss } = useSwapValueLoss(
props.borrowAsset.denom, props.borrowMarket.asset.denom,
props.collateralAsset.denom, props.collateralAsset.denom,
) )
const { const {
@ -33,34 +33,39 @@ export default function useStakingController(props: Props) {
actions, actions,
} = useDepositHlsVault({ } = useDepositHlsVault({
collateralDenom: collateralAsset.denom, collateralDenom: collateralAsset.denom,
borrowDenom: borrowAsset.denom, borrowDenom: borrowMarket.asset.denom,
}) })
const { updatedAccount, addDeposits } = useUpdatedAccount(selectedAccount) const { updatedAccount, addDeposits } = useUpdatedAccount(selectedAccount)
const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount) const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount)
const maxBorrowAmount = useMemo(() => { const maxBorrowAmount = useMemo(() => {
return computeMaxBorrowAmount(props.borrowAsset.denom, { return computeMaxBorrowAmount(props.borrowMarket.asset.denom, {
swap: { swap: {
denom_out: props.collateralAsset.denom, denom_out: props.collateralAsset.denom,
slippage: BN(swapValueLoss).plus(SWAP_FEE_BUFFER).toString(), 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(() => { const execute = useCallback(() => {
useStore.setState({ hlsModal: null }) useStore.setState({ hlsModal: null })
addToStakingStrategy({ addToStakingStrategy({
actions, actions,
accountId: selectedAccount.id, accountId: selectedAccount.id,
borrowCoin: BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount), borrowCoin: BNCoin.fromDenomAndBigNumber(borrowMarket.asset.denom, borrowAmount),
depositCoin: BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount), depositCoin: BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount),
}) })
}, [ }, [
actions, actions,
addToStakingStrategy, addToStakingStrategy,
borrowAmount, borrowAmount,
borrowAsset.denom, borrowMarket.asset.denom,
collateralAsset.denom, collateralAsset.denom,
depositAmount, depositAmount,
selectedAccount.id, selectedAccount.id,

View File

@ -8,14 +8,14 @@ import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin' import { BNCoin } from 'types/classes/BNCoin'
interface Props { interface Props {
borrowAsset: Asset borrowMarket: Market
collateralAsset: Asset collateralAsset: Asset
selectedAccount: Account selectedAccount: Account
vault: Vault vault: Vault
} }
export default function useVaultController(props: Props) { export default function useVaultController(props: Props) {
const { vault, collateralAsset, borrowAsset, selectedAccount } = props const { vault, collateralAsset, borrowMarket, selectedAccount } = props
const depositIntoVault = useStore((s) => s.depositIntoVault) const depositIntoVault = useStore((s) => s.depositIntoVault)
@ -28,14 +28,14 @@ export default function useVaultController(props: Props) {
positionValue, positionValue,
} = useDepositHlsVault({ } = useDepositHlsVault({
collateralDenom: collateralAsset.denom, collateralDenom: collateralAsset.denom,
borrowDenom: borrowAsset.denom, borrowDenom: borrowMarket.asset.denom,
}) })
const { actions } = useDepositVault({ const { actions } = useDepositVault({
vault, vault,
reclaims: [], reclaims: [],
deposits: [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)], deposits: [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)],
borrowings: [BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount)], borrowings: [BNCoin.fromDenomAndBigNumber(borrowMarket.asset.denom, borrowAmount)],
kind: 'high_levered_strategy', kind: 'high_levered_strategy',
}) })
@ -43,17 +43,17 @@ export default function useVaultController(props: Props) {
const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount) const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount)
const maxBorrowAmount = useMemo(() => { const maxBorrowAmount = useMemo(() => {
return computeMaxBorrowAmount(props.borrowAsset.denom, { return computeMaxBorrowAmount(props.borrowMarket.asset.denom, {
vault: { address: props.vault?.address }, vault: { address: props.vault?.address },
}).plus(borrowAmount) }).plus(borrowAmount)
}, [borrowAmount, computeMaxBorrowAmount, props.borrowAsset.denom, props.vault?.address]) }, [borrowAmount, computeMaxBorrowAmount, props.borrowMarket.asset.denom, props.vault?.address])
const execute = useCallback(() => { const execute = useCallback(() => {
depositIntoVault({ depositIntoVault({
accountId: selectedAccount.id, accountId: selectedAccount.id,
actions, actions,
deposits: [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)], deposits: [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)],
borrowings: [BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount)], borrowings: [BNCoin.fromDenomAndBigNumber(borrowMarket.asset.denom, borrowAmount)],
isCreate: true, isCreate: true,
kind: 'high_levered_strategy', kind: 'high_levered_strategy',
}) })
@ -63,7 +63,7 @@ export default function useVaultController(props: Props) {
borrowAmount, borrowAmount,
depositAmount, depositAmount,
depositIntoVault, depositIntoVault,
borrowAsset.denom, borrowMarket.asset.denom,
collateralAsset.denom, collateralAsset.denom,
selectedAccount.id, selectedAccount.id,
]) ])
@ -75,12 +75,12 @@ export default function useVaultController(props: Props) {
simulateVaultDeposit( simulateVaultDeposit(
vault.address, vault.address,
[BNCoin.fromDenomAndBigNumber(collateralAsset.denom, amount)], [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, amount)],
[BNCoin.fromDenomAndBigNumber(borrowAsset.denom, borrowAmount)], [BNCoin.fromDenomAndBigNumber(borrowMarket.asset.denom, borrowAmount)],
) )
}, },
[ [
borrowAmount, borrowAmount,
borrowAsset, borrowMarket,
collateralAsset, collateralAsset,
vault.address, vault.address,
setDepositAmount, setDepositAmount,
@ -95,11 +95,11 @@ export default function useVaultController(props: Props) {
simulateVaultDeposit( simulateVaultDeposit(
vault.address, vault.address,
[BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)], [BNCoin.fromDenomAndBigNumber(collateralAsset.denom, depositAmount)],
[BNCoin.fromDenomAndBigNumber(borrowAsset.denom, amount)], [BNCoin.fromDenomAndBigNumber(borrowMarket.asset.denom, amount)],
) )
}, },
[ [
borrowAsset, borrowMarket,
collateralAsset, collateralAsset,
depositAmount, depositAmount,
vault.address, vault.address,

View File

@ -1,8 +1,8 @@
import React, { useCallback, useMemo, useState } from 'react' import React, { useCallback, useMemo, useState } from 'react'
import Button from 'components/common/Button' import Button from 'components/common/Button'
import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary'
import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider' import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider'
import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings' import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys' import { LocalStorageKeys } from 'constants/localStorageKeys'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
@ -23,7 +23,7 @@ import { getDepositCapMessage, getHealthFactorMessage, getLiquidityMessage } fro
interface Props { interface Props {
account: HLSAccountWithStrategy account: HLSAccountWithStrategy
action: HlsStakingManageAction action: HlsStakingManageAction
borrowAsset: BorrowAsset borrowMarket: Market
collateralAsset: Asset collateralAsset: Asset
} }
@ -42,19 +42,24 @@ export default function ChangeLeverage(props: Props) {
const changeHlsStakingLeverage = useStore((s) => s.changeHlsStakingLeverage) const changeHlsStakingLeverage = useStore((s) => s.changeHlsStakingLeverage)
const { computeMaxBorrowAmount } = useHealthComputer(props.account) const { computeMaxBorrowAmount } = useHealthComputer(props.account)
const previousDebt: BigNumber = useMemo( const previousDebt: BigNumber = useMemo(
() => props.account.debts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO, () => props.account.debts.find(byDenom(props.borrowMarket.asset.denom))?.amount || BN_ZERO,
[props.account.debts, props.borrowAsset.denom], [props.account.debts, props.borrowMarket.asset.denom],
) )
const [currentDebt, setAmount] = useState(previousDebt) const [currentDebt, setAmount] = useState(previousDebt)
const maxBorrowAmount = useMemo(() => { const maxBorrowAmount = useMemo(() => {
return computeMaxBorrowAmount(props.borrowAsset.denom, { return computeMaxBorrowAmount(props.borrowMarket.asset.denom, {
swap: { swap: {
denom_out: props.collateralAsset.denom, denom_out: props.collateralAsset.denom,
slippage: SWAP_FEE_BUFFER.toString(), slippage: SWAP_FEE_BUFFER.toString(),
}, },
}).plus(previousDebt) }).plus(previousDebt)
}, [computeMaxBorrowAmount, previousDebt, props.borrowAsset.denom, props.collateralAsset.denom]) }, [
computeMaxBorrowAmount,
previousDebt,
props.borrowMarket.asset.denom,
props.collateralAsset.denom,
])
const onChangeAmount = useCallback( const onChangeAmount = useCallback(
(currentDebt: BigNumber) => { (currentDebt: BigNumber) => {
@ -62,19 +67,22 @@ export default function ChangeLeverage(props: Props) {
if (currentDebt.isLessThan(previousDebt)) { if (currentDebt.isLessThan(previousDebt)) {
simulateHlsStakingWithdraw( simulateHlsStakingWithdraw(
props.collateralAsset.denom, props.collateralAsset.denom,
props.borrowAsset.denom, props.borrowMarket.asset.denom,
previousDebt.minus(currentDebt), previousDebt.minus(currentDebt),
) )
} else { } else {
simulateHlsStakingDeposit( simulateHlsStakingDeposit(
BNCoin.fromDenomAndBigNumber(props.collateralAsset.denom, BN_ZERO), 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, previousDebt,
props.borrowAsset.denom, props.borrowMarket.asset.denom,
props.collateralAsset.denom, props.collateralAsset.denom,
simulateHlsStakingDeposit, simulateHlsStakingDeposit,
simulateHlsStakingWithdraw, simulateHlsStakingWithdraw,
@ -98,7 +106,7 @@ export default function ChangeLeverage(props: Props) {
previousDebt, previousDebt,
currentDebt, currentDebt,
props.collateralAsset.denom, props.collateralAsset.denom,
props.borrowAsset.denom, props.borrowMarket.asset.denom,
slippage, slippage,
prices, prices,
assets, assets,
@ -108,7 +116,7 @@ export default function ChangeLeverage(props: Props) {
currentDebt, currentDebt,
previousDebt, previousDebt,
props.collateralAsset.denom, props.collateralAsset.denom,
props.borrowAsset.denom, props.borrowMarket.asset.denom,
props.account.id, props.account.id,
slippage, slippage,
prices, prices,
@ -127,22 +135,22 @@ export default function ChangeLeverage(props: Props) {
) )
const apy = useMemo(() => { const apy = useMemo(() => {
if (!props.borrowAsset.borrowRate || !props.account.strategy.apy) return 0 if (!props.borrowMarket.apy.borrow || !props.account.strategy.apy) return 0
return getLeveragedApy(props.account.strategy.apy, props.borrowAsset.borrowRate, leverage) return getLeveragedApy(props.account.strategy.apy, props.borrowMarket.apy.borrow, leverage)
}, [leverage, props.account.strategy.apy, props.borrowAsset.borrowRate]) }, [leverage, props.account.strategy.apy, props.borrowMarket.apy.borrow])
const warningMessages = useMemo(() => { const warningMessages = useMemo(() => {
const messages: string[] = [] const messages: string[] = []
const borrowLiquidity = props.borrowAsset.liquidity?.amount || BN_ZERO const borrowLiquidity = props.borrowMarket.liquidity || BN_ZERO
if (borrowLiquidity.isLessThan(currentDebt.minus(previousDebt))) { 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)) { if (maxBorrowAmount.isLessThan(currentDebt)) {
messages.push( 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, depositCapLeft,
maxBorrowAmount, maxBorrowAmount,
previousDebt, previousDebt,
props.borrowAsset.denom, props.borrowMarket.asset.denom,
props.borrowAsset.liquidity?.amount, props.borrowMarket.liquidity,
props.collateralAsset.denom, props.collateralAsset.denom,
]) ])
@ -169,7 +177,7 @@ export default function ChangeLeverage(props: Props) {
<> <>
<TokenInputWithSlider <TokenInputWithSlider
amount={currentDebt} amount={currentDebt}
asset={props.borrowAsset} asset={props.borrowMarket.asset}
max={maxBorrowAmount} max={maxBorrowAmount}
onChange={onChangeAmount} onChange={onChangeAmount}
maxText='Max borrow' maxText='Max borrow'
@ -180,7 +188,7 @@ export default function ChangeLeverage(props: Props) {
warningMessages={warningMessages} warningMessages={warningMessages}
/> />
<div className='flex flex-col gap-6'> <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 <Button
onClick={handleOnClick} onClick={handleOnClick}
text='Confirm' text='Confirm'

View File

@ -10,7 +10,7 @@ import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSli
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import useAllAssets from 'hooks/assets/useAllAssets' import useAllAssets from 'hooks/assets/useAllAssets'
import useDepositActions from 'hooks/hls/useDepositActions' import useDepositActions from 'hooks/hls/useDepositActions'
import useBorrowAsset from 'hooks/useBorrowAsset' import useMarket from 'hooks/markets/useMarket'
import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance' import useCurrentWalletBalance from 'hooks/useCurrentWalletBalance'
import useHealthComputer from 'hooks/useHealthComputer' import useHealthComputer from 'hooks/useHealthComputer'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
@ -32,7 +32,7 @@ import {
interface Props { interface Props {
account: HLSAccountWithStrategy account: HLSAccountWithStrategy
action: HlsStakingManageAction action: HlsStakingManageAction
borrowAsset: BorrowAsset borrowMarket: Market
collateralAsset: Asset collateralAsset: Asset
} }
@ -48,7 +48,7 @@ export default function Deposit(props: Props) {
useCurrentWalletBalance(props.collateralAsset.denom)?.amount || '0', useCurrentWalletBalance(props.collateralAsset.denom)?.amount || '0',
) )
const addToStakingStrategy = useStore((s) => s.addToStakingStrategy) 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( const currentLeverage = useMemo(
() => calculateAccountLeverage(props.account, prices, assets).toNumber(), () => calculateAccountLeverage(props.account, prices, assets).toNumber(),
@ -72,10 +72,10 @@ export default function Deposit(props: Props) {
const borrowCoin = useMemo( const borrowCoin = useMemo(
() => () =>
BNCoin.fromDenomAndBigNumber( BNCoin.fromDenomAndBigNumber(
props.borrowAsset.denom, props.borrowMarket.asset.denom,
addedDebts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO, addedDebts.find(byDenom(props.borrowMarket.asset.denom))?.amount || BN_ZERO,
), ),
[addedDebts, props.borrowAsset.denom], [addedDebts, props.borrowMarket.asset.denom],
) )
const warningMessages = useMemo(() => { const warningMessages = useMemo(() => {
@ -105,22 +105,22 @@ export default function Deposit(props: Props) {
]) ])
const maxBorrowAmount = useMemo( const maxBorrowAmount = useMemo(
() => computeMaxBorrowAmount(props.borrowAsset.denom, 'deposit'), () => computeMaxBorrowAmount(props.borrowMarket.asset.denom, 'deposit'),
[computeMaxBorrowAmount, props.borrowAsset.denom], [computeMaxBorrowAmount, props.borrowMarket.asset.denom],
) )
const borrowWarningMessages = useMemo(() => { const borrowWarningMessages = useMemo(() => {
let messages: string[] = [] let messages: string[] = []
if (borrowCoin.amount.isGreaterThan(maxBorrowAmount)) { if (borrowCoin.amount.isGreaterThan(maxBorrowAmount)) {
messages.push( 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)) { if (borrowCoin.amount.isGreaterThan(borrowLiquidity)) {
messages.push(getLiquidityMessage(props.borrowAsset.denom, borrowLiquidity, assets)) messages.push(getLiquidityMessage(props.borrowMarket.asset.denom, borrowLiquidity, assets))
} }
return messages return messages
@ -128,15 +128,15 @@ export default function Deposit(props: Props) {
assets, assets,
borrowCoin.amount, borrowCoin.amount,
maxBorrowAmount, maxBorrowAmount,
props.borrowAsset.denom, props.borrowMarket.asset.denom,
props.borrowAsset.liquidity?.amount, props.borrowMarket.liquidity,
]) ])
const actions = useDepositActions({ depositCoin, borrowCoin }) const actions = useDepositActions({ depositCoin, borrowCoin })
const currentDebt: BigNumber = useMemo( const currentDebt: BigNumber = useMemo(
() => props.account.debts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO, () => props.account.debts.find(byDenom(props.borrowMarket.asset.denom))?.amount || BN_ZERO,
[props.account.debts, props.borrowAsset.denom], [props.account.debts, props.borrowMarket.asset.denom],
) )
const handleDeposit = useCallback(() => { const handleDeposit = useCallback(() => {
@ -160,19 +160,19 @@ export default function Deposit(props: Props) {
assets, assets,
) )
const borrowValue = BN(currentLeverage - 1).times(depositValue) 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( simulateHlsStakingDeposit(
BNCoin.fromDenomAndBigNumber(props.collateralAsset.denom, amount), BNCoin.fromDenomAndBigNumber(props.collateralAsset.denom, amount),
BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, additionalDebt), BNCoin.fromDenomAndBigNumber(props.borrowMarket.asset.denom, additionalDebt),
) )
}, },
[ [
currentLeverage, currentLeverage,
keepLeverage, keepLeverage,
prices, prices,
props.borrowAsset.denom, props.borrowMarket.asset.denom,
props.collateralAsset.denom, props.collateralAsset.denom,
simulateHlsStakingDeposit, simulateHlsStakingDeposit,
assets, assets,
@ -197,18 +197,18 @@ export default function Deposit(props: Props) {
amount: borrowCoin.amount.toNumber(), amount: borrowCoin.amount.toNumber(),
warningMessages: borrowWarningMessages, warningMessages: borrowWarningMessages,
options: { options: {
suffix: ` ${props.borrowAsset.symbol}`, suffix: ` ${props.borrowMarket.asset.symbol}`,
abbreviated: true, abbreviated: true,
decimals: props.borrowAsset.decimals, decimals: props.borrowMarket.asset.decimals,
}, },
}, },
{ {
title: 'New Debt Amount', title: 'New Debt Amount',
amount: currentDebt.plus(borrowCoin.amount).toNumber(), amount: currentDebt.plus(borrowCoin.amount).toNumber(),
options: { options: {
suffix: ` ${props.borrowAsset.symbol}`, suffix: ` ${props.borrowMarket.asset.symbol}`,
abbreviated: true, abbreviated: true,
decimals: props.borrowAsset.decimals, decimals: props.borrowMarket.asset.decimals,
}, },
}, },
] ]
@ -220,8 +220,8 @@ export default function Deposit(props: Props) {
borrowWarningMessages, borrowWarningMessages,
currentDebt, currentDebt,
keepLeverage, keepLeverage,
props.borrowAsset.decimals, props.borrowMarket.asset.decimals,
props.borrowAsset.symbol, props.borrowMarket.asset.symbol,
], ],
) )

View File

@ -16,25 +16,25 @@ import { getNoBalanceInWalletMessage } from 'utils/messages'
interface Props { interface Props {
account: Account account: Account
action: HlsStakingManageAction action: HlsStakingManageAction
borrowAsset: Asset borrowMarket: Market
collateralAsset: Asset collateralAsset: Asset
} }
export default function Repay(props: Props) { export default function Repay(props: Props) {
const { removeDebts, removedDebts } = useUpdatedAccount(props.account) const { removeDebts, removedDebts } = useUpdatedAccount(props.account)
const borrowAssetAmountInWallet = BN( const borrowAssetAmountInWallet = BN(
useCurrentWalletBalance(props.borrowAsset.denom)?.amount || '0', useCurrentWalletBalance(props.borrowMarket.asset.denom)?.amount || '0',
) )
const repay = useStore((s) => s.repay) const repay = useStore((s) => s.repay)
const currentDebt: BigNumber = useMemo( const currentDebt: BigNumber = useMemo(
() => props.account.debts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO, () => props.account.debts.find(byDenom(props.borrowMarket.asset.denom))?.amount || BN_ZERO,
[props.account.debts, props.borrowAsset.denom], [props.account.debts, props.borrowMarket.asset.denom],
) )
const repayAmount: BigNumber = useMemo( const repayAmount: BigNumber = useMemo(
() => removedDebts.find(byDenom(props.borrowAsset.denom))?.amount || BN_ZERO, () => removedDebts.find(byDenom(props.borrowMarket.asset.denom))?.amount || BN_ZERO,
[removedDebts, props.borrowAsset.denom], [removedDebts, props.borrowMarket.asset.denom],
) )
const maxRepayAmount = useMemo( const maxRepayAmount = useMemo(
@ -48,51 +48,51 @@ export default function Repay(props: Props) {
title: 'Total Debt Repayable', title: 'Total Debt Repayable',
amount: currentDebt.toNumber(), amount: currentDebt.toNumber(),
options: { options: {
suffix: ` ${props.borrowAsset.symbol}`, suffix: ` ${props.borrowMarket.asset.symbol}`,
abbreviated: true, abbreviated: true,
decimals: props.borrowAsset.decimals, decimals: props.borrowMarket.asset.decimals,
}, },
}, },
{ {
title: 'New Debt Amount', title: 'New Debt Amount',
amount: currentDebt.minus(repayAmount).toNumber(), amount: currentDebt.minus(repayAmount).toNumber(),
options: { options: {
suffix: ` ${props.borrowAsset.symbol}`, suffix: ` ${props.borrowMarket.asset.symbol}`,
abbreviated: true, 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(() => { const handleRepay = useCallback(() => {
useStore.setState({ hlsManageModal: null }) useStore.setState({ hlsManageModal: null })
repay({ repay({
accountId: props.account.id, accountId: props.account.id,
coin: BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, repayAmount), coin: BNCoin.fromDenomAndBigNumber(props.borrowMarket.asset.denom, repayAmount),
fromWallet: true, fromWallet: true,
}) })
}, [props.account.id, props.borrowAsset.denom, repay, repayAmount]) }, [props.account.id, props.borrowMarket.asset.denom, repay, repayAmount])
const handleOnChange = useCallback( const handleOnChange = useCallback(
(amount: BigNumber) => (amount: BigNumber) =>
removeDebts([BNCoin.fromDenomAndBigNumber(props.borrowAsset.denom, amount)]), removeDebts([BNCoin.fromDenomAndBigNumber(props.borrowMarket.asset.denom, amount)]),
[props.borrowAsset.denom, removeDebts], [props.borrowMarket.asset.denom, removeDebts],
) )
const warningMessages = useMemo(() => { const warningMessages = useMemo(() => {
if (borrowAssetAmountInWallet.isZero()) { if (borrowAssetAmountInWallet.isZero()) {
return [getNoBalanceInWalletMessage(props.borrowAsset.symbol)] return [getNoBalanceInWalletMessage(props.borrowMarket.asset.symbol)]
} }
return [] return []
}, [borrowAssetAmountInWallet, props.borrowAsset.symbol]) }, [borrowAssetAmountInWallet, props.borrowMarket.asset.symbol])
return ( return (
<> <>
<TokenInputWithSlider <TokenInputWithSlider
amount={repayAmount} amount={repayAmount}
asset={props.borrowAsset} asset={props.borrowMarket.asset}
max={maxRepayAmount} max={maxRepayAmount}
onChange={handleOnChange} onChange={handleOnChange}
maxText='In Wallet' maxText='In Wallet'

View File

@ -14,7 +14,6 @@ import { getHealthFactorMessage } from 'utils/messages'
interface Props { interface Props {
account: Account account: Account
action: HlsStakingManageAction action: HlsStakingManageAction
borrowAsset: Asset
collateralAsset: Asset collateralAsset: Asset
} }

View File

@ -8,23 +8,23 @@ import Withdraw from 'components/Modals/HLS/Manage/Withdraw'
import ModalContentWithSummary from 'components/Modals/ModalContentWithSummary' import ModalContentWithSummary from 'components/Modals/ModalContentWithSummary'
import useAccount from 'hooks/accounts/useAccount' import useAccount from 'hooks/accounts/useAccount'
import useAsset from 'hooks/assets/useAsset' import useAsset from 'hooks/assets/useAsset'
import useBorrowAsset from 'hooks/useBorrowAsset' import useMarket from 'hooks/markets/useMarket'
import useStore from 'store' import useStore from 'store'
export default function HlsManageModalController() { export default function HlsManageModalController() {
const modal = useStore((s) => s.hlsManageModal) const modal = useStore((s) => s.hlsManageModal)
const { data: account } = useAccount(modal?.accountId) const { data: account } = useAccount(modal?.accountId)
const collateralAsset = useAsset(modal?.staking.strategy.denoms.deposit || '') 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 ( return (
<HlsModal <HlsModal
account={{ ...account, strategy: modal.staking.strategy } as HLSAccountWithStrategy} account={{ ...account, strategy: modal.staking.strategy } as HLSAccountWithStrategy}
action={modal.staking.action} action={modal.staking.action}
collateralAsset={collateralAsset} collateralAsset={collateralAsset}
borrowAsset={borrowAsset} borrowMarket={market}
/> />
) )
} }
@ -32,12 +32,11 @@ export default function HlsManageModalController() {
interface Props { interface Props {
account: HLSAccountWithStrategy account: HLSAccountWithStrategy
action: HlsStakingManageAction action: HlsStakingManageAction
borrowAsset: BorrowAsset borrowMarket: Market
collateralAsset: Asset collateralAsset: Asset
} }
function HlsModal(props: Props) { function HlsModal(props: Props) {
const updatedAccount = useStore((s) => s.updatedAccount)
function handleClose() { function handleClose() {
useStore.setState({ hlsManageModal: null }) useStore.setState({ hlsManageModal: null })
} }
@ -65,7 +64,7 @@ function HlsModal(props: Props) {
<Header <Header
action={props.action} action={props.action}
primaryAsset={props.collateralAsset} primaryAsset={props.collateralAsset}
secondaryAsset={props.borrowAsset} secondaryAsset={props.borrowMarket.asset}
/> />
} }
onClose={handleClose} onClose={handleClose}

View File

@ -1,10 +1,10 @@
import React from 'react' import React from 'react'
import Modal from 'components/Modals/Modal'
import Content from 'components/Modals/HLS/Deposit' import Content from 'components/Modals/HLS/Deposit'
import Header from 'components/Modals/HLS/Header' import Header from 'components/Modals/HLS/Header'
import Modal from 'components/Modals/Modal'
import useAsset from 'hooks/assets/useAsset' import useAsset from 'hooks/assets/useAsset'
import useBorrowAsset from 'hooks/useBorrowAsset' import useMarket from 'hooks/markets/useMarket'
import useStore from 'store' import useStore from 'store'
export default function HlsModalController() { export default function HlsModalController() {
@ -14,7 +14,7 @@ export default function HlsModalController() {
modal?.vault?.denoms.primary || modal?.strategy?.denoms.deposit || '', 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 if (!primaryAsset || !secondaryAsset) return null
@ -41,7 +41,7 @@ export default function HlsModalController() {
interface Props { interface Props {
primaryAsset: Asset primaryAsset: Asset
secondaryAsset: BorrowAsset secondaryAsset: Market
strategy?: HLSStrategy strategy?: HLSStrategy
vaultAddress: string | null vaultAddress: string | null
} }
@ -53,7 +53,9 @@ function HlsModal(props: Props) {
return ( return (
<Modal <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' headerClassName='gradient-header pl-2 pr-2.5 py-3 border-b-white/5 border-b'
contentClassName='flex flex-col p-6' contentClassName='flex flex-col p-6'
modalClassName='max-w-modal-md' modalClassName='max-w-modal-md'
@ -61,7 +63,7 @@ function HlsModal(props: Props) {
> >
<Content <Content
collateralAsset={props.primaryAsset} collateralAsset={props.primaryAsset}
borrowAsset={props.secondaryAsset} borrowMarket={props.secondaryAsset}
vaultAddress={props.vaultAddress} vaultAddress={props.vaultAddress}
strategy={props.strategy} strategy={props.strategy}
/> />

View File

@ -12,7 +12,7 @@ import TokenInput from 'components/common/TokenInput'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import { ORACLE_DENOM } from 'constants/oracle' import { ORACLE_DENOM } from 'constants/oracle'
import useAllAssets from 'hooks/assets/useAllAssets' import useAllAssets from 'hooks/assets/useAllAssets'
import useMarketAssets from 'hooks/markets/useMarketAssets' import useMarkets from 'hooks/markets/useMarkets'
import useHealthComputer from 'hooks/useHealthComputer' import useHealthComputer from 'hooks/useHealthComputer'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import useStore from 'store' import useStore from 'store'
@ -39,7 +39,7 @@ export interface VaultBorrowingsProps {
export default function VaultBorrowings(props: VaultBorrowingsProps) { export default function VaultBorrowings(props: VaultBorrowingsProps) {
const assets = useAllAssets() const assets = useAllAssets()
const { borrowings, onChangeBorrowings } = props const { borrowings, onChangeBorrowings } = props
const { data: marketAssets } = useMarketAssets() const markets = useMarkets()
const { data: prices } = usePrices() const { data: prices } = usePrices()
const vaultModal = useStore((s) => s.vaultModal) const vaultModal = useStore((s) => s.vaultModal)
const depositIntoVault = useStore((s) => s.depositIntoVault) const depositIntoVault = useStore((s) => s.depositIntoVault)
@ -227,7 +227,8 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
</div> </div>
{props.borrowings.map((coin) => { {props.borrowings.map((coin) => {
const asset = assets.find(byDenom(coin.denom)) 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) if (!asset || !borrowRate)
return <React.Fragment key={`borrow-rate-${coin.denom}`}></React.Fragment> return <React.Fragment key={`borrow-rate-${coin.denom}`}></React.Fragment>

View File

@ -13,7 +13,7 @@ import Value, {
VALUE_META, VALUE_META,
valueBalancesSortingFn, valueBalancesSortingFn,
} from 'components/account/AccountBalancesTable/Columns/Value' } from 'components/account/AccountBalancesTable/Columns/Value'
import useMarketAssets from 'hooks/markets/useMarketAssets' import useMarkets from 'hooks/markets/useMarkets'
import useHealthComputer from 'hooks/useHealthComputer' import useHealthComputer from 'hooks/useHealthComputer'
import useStore from 'store' import useStore from 'store'
@ -21,7 +21,8 @@ export default function useAccountBalancesColumns(
account: Account, account: Account,
showLiquidationPrice?: boolean, showLiquidationPrice?: boolean,
) { ) {
const { data: markets } = useMarketAssets() const markets = useMarkets()
const updatedAccount = useStore((s) => s.updatedAccount) const updatedAccount = useStore((s) => s.updatedAccount)
const { computeLiquidationPrice } = useHealthComputer(updatedAccount ?? account) const { computeLiquidationPrice } = useHealthComputer(updatedAccount ?? account)

View File

@ -2,16 +2,16 @@ import BigNumber from 'bignumber.js'
import classNames from 'classnames' import classNames from 'classnames'
import { useMemo } from 'react' import { useMemo } from 'react'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import DisplayCurrency from 'components/common/DisplayCurrency' import DisplayCurrency from 'components/common/DisplayCurrency'
import { FormattedNumber } from 'components/common/FormattedNumber' import { FormattedNumber } from 'components/common/FormattedNumber'
import { ArrowRight } from 'components/common/Icons' import { ArrowRight } from 'components/common/Icons'
import Text from 'components/common/Text' import Text from 'components/common/Text'
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
import { BN_ZERO, MAX_AMOUNT_DECIMALS } from 'constants/math' import { BN_ZERO, MAX_AMOUNT_DECIMALS } from 'constants/math'
import { ORACLE_DENOM } from 'constants/oracle' import { ORACLE_DENOM } from 'constants/oracle'
import useAllAssets from 'hooks/assets/useAllAssets' import useAllAssets from 'hooks/assets/useAllAssets'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
import useHLSStakingAssets from 'hooks/useHLSStakingAssets' import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import useStore from 'store' import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin' import { BNCoin } from 'types/classes/BNCoin'

View File

@ -8,6 +8,7 @@ import AccountDetailsLeverage from 'components/account/AccountDetails/AccountDet
import Skeleton from 'components/account/AccountDetails/Skeleton' import Skeleton from 'components/account/AccountDetails/Skeleton'
import AccountPerpPositionTable from 'components/account/AccountPerpPositionTable' import AccountPerpPositionTable from 'components/account/AccountPerpPositionTable'
import { HealthGauge } from 'components/account/Health/HealthGauge' import { HealthGauge } from 'components/account/Health/HealthGauge'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import EscButton from 'components/common/Button/EscButton' import EscButton from 'components/common/Button/EscButton'
import { glowElement } from 'components/common/Button/utils' import { glowElement } from 'components/common/Button/utils'
import Card from 'components/common/Card' import Card from 'components/common/Card'
@ -15,6 +16,7 @@ import DisplayCurrency from 'components/common/DisplayCurrency'
import { FormattedNumber } from 'components/common/FormattedNumber' import { FormattedNumber } from 'components/common/FormattedNumber'
import { ThreeDots } from 'components/common/Icons' import { ThreeDots } from 'components/common/Icons'
import Text from 'components/common/Text' import Text from 'components/common/Text'
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings' import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys' import { LocalStorageKeys } from 'constants/localStorageKeys'
import { ORACLE_DENOM } from 'constants/oracle' import { ORACLE_DENOM } from 'constants/oracle'
@ -24,10 +26,8 @@ import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import useAllAssets from 'hooks/assets/useAllAssets' import useAllAssets from 'hooks/assets/useAllAssets'
import useLocalStorage from 'hooks/localStorage/useLocalStorage' import useLocalStorage from 'hooks/localStorage/useLocalStorage'
import useAccountId from 'hooks/useAccountId' import useAccountId from 'hooks/useAccountId'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
import useHealthComputer from 'hooks/useHealthComputer' import useHealthComputer from 'hooks/useHealthComputer'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import useStore from 'store' import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin' import { BNCoin } from 'types/classes/BNCoin'

View File

@ -10,7 +10,7 @@ import Text from 'components/common/Text'
import WalletBridges from 'components/Wallet/WalletBridges' import WalletBridges from 'components/Wallet/WalletBridges'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import useBaseAsset from 'hooks/assets/useBasetAsset' import useBaseAsset from 'hooks/assets/useBasetAsset'
import useMarketAssets from 'hooks/markets/useMarketAssets' import useMarkets from 'hooks/markets/useMarkets'
import useAutoLend from 'hooks/useAutoLend' import useAutoLend from 'hooks/useAutoLend'
import { useUpdatedAccount } from 'hooks/useUpdatedAccount' import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
import useWalletBalances from 'hooks/useWalletBalances' import useWalletBalances from 'hooks/useWalletBalances'
@ -35,7 +35,8 @@ export default function AccountFundContent(props: Props) {
const { autoLendEnabledAccountIds } = useAutoLend() const { autoLendEnabledAccountIds } = useAutoLend()
const isLending = autoLendEnabledAccountIds.includes(props.accountId) const isLending = autoLendEnabledAccountIds.includes(props.accountId)
const [fundingAssets, setFundingAssets] = useState<BNCoin[]>([]) const [fundingAssets, setFundingAssets] = useState<BNCoin[]>([])
const { data: marketAssets } = useMarketAssets() const markets = useMarkets()
const { data: walletBalances } = useWalletBalances(props.address) const { data: walletBalances } = useWalletBalances(props.address)
const { simulateDeposits } = useUpdatedAccount(props.account) const { simulateDeposits } = useUpdatedAccount(props.account)
const baseAsset = useBaseAsset() const baseAsset = useBaseAsset()
@ -127,7 +128,7 @@ export default function AccountFundContent(props: Props) {
const depositCapReachedCoins = useMemo(() => { const depositCapReachedCoins = useMemo(() => {
const depositCapReachedCoins: BNCoin[] = [] const depositCapReachedCoins: BNCoin[] = []
fundingAssets.forEach((asset) => { fundingAssets.forEach((asset) => {
const marketAsset = marketAssets.find(byDenom(asset.denom)) const marketAsset = markets.find(byDenom(asset.denom))
if (!marketAsset) return if (!marketAsset) return
const capLeft = getCapLeftWithBuffer(marketAsset.cap) const capLeft = getCapLeftWithBuffer(marketAsset.cap)
@ -137,7 +138,7 @@ export default function AccountFundContent(props: Props) {
depositCapReachedCoins.push(BNCoin.fromDenomAndBigNumber(asset.denom, capLeft)) depositCapReachedCoins.push(BNCoin.fromDenomAndBigNumber(asset.denom, capLeft))
}) })
return depositCapReachedCoins return depositCapReachedCoins
}, [fundingAssets, marketAssets]) }, [fundingAssets, markets])
return ( return (
<> <>

View File

@ -2,15 +2,15 @@ import { useCallback, useMemo } from 'react'
import AccountFundFullPage from 'components/account/AccountFund/AccountFundFullPage' import AccountFundFullPage from 'components/account/AccountFund/AccountFundFullPage'
import Skeleton from 'components/account/AccountList/Skeleton' import Skeleton from 'components/account/AccountList/Skeleton'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import Button from 'components/common/Button' import Button from 'components/common/Button'
import { ArrowDownLine, ArrowUpLine, TrashBin } from 'components/common/Icons' import { ArrowDownLine, ArrowUpLine, TrashBin } from 'components/common/Icons'
import SwitchAutoLend from 'components/common/Switch/SwitchAutoLend' import SwitchAutoLend from 'components/common/Switch/SwitchAutoLend'
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
import useAccount from 'hooks/accounts/useAccount' import useAccount from 'hooks/accounts/useAccount'
import useAllAssets from 'hooks/assets/useAllAssets' import useAllAssets from 'hooks/assets/useAllAssets'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
import useHealthComputer from 'hooks/useHealthComputer' import useHealthComputer from 'hooks/useHealthComputer'
import useHLSStakingAssets from 'hooks/useHLSStakingAssets' import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import useStore from 'store' import useStore from 'store'
import { calculateAccountApr, calculateAccountBalanceValue } from 'utils/accounts' import { calculateAccountApr, calculateAccountBalanceValue } from 'utils/accounts'

View File

@ -5,21 +5,21 @@ import AccountBalancesTable from 'components/account/AccountBalancesTable'
import AccountComposition from 'components/account/AccountComposition' import AccountComposition from 'components/account/AccountComposition'
import AccountPerpPositionTable from 'components/account/AccountPerpPositionTable' import AccountPerpPositionTable from 'components/account/AccountPerpPositionTable'
import HealthBar from 'components/account/Health/HealthBar' import HealthBar from 'components/account/Health/HealthBar'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import Accordion from 'components/common/Accordion' import Accordion from 'components/common/Accordion'
import Card from 'components/common/Card' import Card from 'components/common/Card'
import DisplayCurrency from 'components/common/DisplayCurrency' import DisplayCurrency from 'components/common/DisplayCurrency'
import { FormattedNumber } from 'components/common/FormattedNumber' import { FormattedNumber } from 'components/common/FormattedNumber'
import { ArrowRight } from 'components/common/Icons' import { ArrowRight } from 'components/common/Icons'
import Text from 'components/common/Text' import Text from 'components/common/Text'
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings' import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys' import { LocalStorageKeys } from 'constants/localStorageKeys'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import { ORACLE_DENOM } from 'constants/oracle' import { ORACLE_DENOM } from 'constants/oracle'
import useAllAssets from 'hooks/assets/useAllAssets' import useAllAssets from 'hooks/assets/useAllAssets'
import useLocalStorage from 'hooks/localStorage/useLocalStorage' import useLocalStorage from 'hooks/localStorage/useLocalStorage'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
import useHealthComputer from 'hooks/useHealthComputer' import useHealthComputer from 'hooks/useHealthComputer'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import useStore from 'store' import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin' import { BNCoin } from 'types/classes/BNCoin'

View File

@ -1,8 +1,8 @@
import AvailableBorrowingsTable from 'components/borrow/Table/AvailableBorrowingsTable' import AvailableBorrowingsTable from 'components/borrow/Table/AvailableBorrowingsTable'
import DepositedBorrowingsTable from 'components/borrow/Table/DepositedBorrowingsTable' import DepositedBorrowingsTable from 'components/borrow/Table/DepositedBorrowingsTable'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import useBorrowEnabledAssets from 'hooks/assets/useBorrowEnabledAssets' import useBorrowEnabledAssets from 'hooks/assets/useBorrowEnabledAssets'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
export default function Borrowings() { export default function Borrowings() {
const data = useBorrowMarketAssetsTableData() const data = useBorrowMarketAssetsTableData()
@ -30,10 +30,18 @@ function Fallback() {
max: 0, max: 0,
liq: 0, liq: 0,
}, },
liquidity: null, liquidity: BN_ZERO,
marketDepositAmount: BN_ZERO,
marketLiquidityRate: 0, 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 /> return <AvailableBorrowingsTable data={data} isLoading />

View File

@ -16,15 +16,9 @@ export const debtSortingFn = (
): number => { ): number => {
const assetA = a.original.asset const assetA = a.original.asset
const assetB = b.original.asset const assetB = b.original.asset
if (!a.original.debt || !b.original.debt) return 0 if (!a.original.accountDebt || !b.original.accountDebt) return 0
const assetAPrice = (a.original.liquidity?.value ?? BN_ZERO).div( const debtA = a.original.accountDebt.shiftedBy(-assetA.decimals)
a.original.liquidity?.amount ?? BN_ZERO, const debtB = b.original.accountDebt.shiftedBy(-assetB.decimals)
)
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)
return debtA.minus(debtB).toNumber() return debtA.minus(debtB).toNumber()
} }
@ -38,5 +32,5 @@ export default function Debt(props: Props) {
if (!asset) return null if (!asset) return null
return <AmountAndValue asset={asset} amount={props.data?.debt ?? BN_ZERO} /> return <AmountAndValue asset={asset} amount={props.data?.accountDebt ?? BN_ZERO} />
} }

View File

@ -19,8 +19,8 @@ export const liquiditySortingFn = (
): number => { ): number => {
const assetA = a.original.asset const assetA = a.original.asset
const assetB = b.original.asset const assetB = b.original.asset
const liquidityA = demagnify(a.original.liquidity?.amount ?? 0, assetA) const liquidityA = demagnify(a.original.liquidity ?? 0, assetA)
const liquidityB = demagnify(b.original.liquidity?.amount ?? 0, assetB) const liquidityB = demagnify(b.original.liquidity ?? 0, assetB)
return liquidityA - liquidityB return liquidityA - liquidityB
} }
@ -35,9 +35,9 @@ export default function Liquidity(props: Props) {
if (!asset) return null if (!asset) return null
if (liquidity === null) { if (liquidity.isZero()) {
return <Loading /> return <Loading />
} }
return <AmountAndValue asset={asset} amount={liquidity.amount ?? BN_ZERO} /> return <AmountAndValue asset={asset} amount={liquidity ?? BN_ZERO} />
} }

View File

@ -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])
}

View File

@ -2,28 +2,27 @@ import { FormattedNumber } from 'components/common/FormattedNumber'
import Text from 'components/common/Text' import Text from 'components/common/Text'
interface Props { interface Props {
availableLiquidity: BigNumber market: Market
asset: BorrowAsset
} }
export default function AvailableLiquidityMessage(props: Props) { export default function AvailableLiquidityMessage(props: Props) {
const { availableLiquidity, asset } = props const { market } = props
return ( return (
<div className='flex items-start p-4 bg-white/5'> <div className='flex items-start p-4 bg-white/5'>
<div className='flex flex-col gap-2'> <div className='flex flex-col gap-2'>
<Text size='sm'>Not enough Liquidty!</Text> <Text size='sm'>Not enough Liquidty!</Text>
<Text size='xs' className='text-white/40'> <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> </Text>
<div className='flex gap-1'> <div className='flex gap-1'>
<Text size='xs'>Available Liquidity:</Text> <Text size='xs'>Available Liquidity:</Text>
<FormattedNumber <FormattedNumber
amount={availableLiquidity.toNumber()} amount={market.liquidity.toNumber()}
options={{ options={{
abbreviated: true, abbreviated: true,
decimals: asset.decimals, decimals: market.asset.decimals,
suffix: ` ${asset.symbol}`, suffix: ` ${market.asset.symbol}`,
}} }}
className='text-xs text-white/60' className='text-xs text-white/60'
/> />

View File

@ -23,9 +23,7 @@ export default function MarketDetails({ row, type }: Props) {
symbol: displayCurrencySymbol, symbol: displayCurrencySymbol,
} = useDisplayCurrencyPrice() } = useDisplayCurrencyPrice()
const { asset, ltv, marketDepositAmount, marketLiquidityAmount } = row.original const { asset, ltv, cap, liquidity, deposits, debt } = row.original
const totalBorrowed = marketDepositAmount.minus(marketLiquidityAmount)
const details: Detail[] = useMemo(() => { const details: Detail[] = useMemo(() => {
const isDollar = displayCurrencySymbol === '$' const isDollar = displayCurrencySymbol === '$'
@ -33,7 +31,7 @@ export default function MarketDetails({ row, type }: Props) {
function getLendingMarketDetails() { function getLendingMarketDetails() {
return [ return [
{ {
amount: convertAmount(asset, marketDepositAmount).toNumber(), amount: convertAmount(asset, deposits).toNumber(),
options: { options: {
abbreviated: true, abbreviated: true,
suffix: isDollar ? undefined : ` ${displayCurrencySymbol}`, suffix: isDollar ? undefined : ` ${displayCurrencySymbol}`,
@ -62,9 +60,7 @@ export default function MarketDetails({ row, type }: Props) {
title: 'Oracle Price', title: 'Oracle Price',
}, },
{ {
amount: totalBorrowed.isZero() amount: debt.isZero() ? 0 : debt.dividedBy(deposits).multipliedBy(100).toNumber(), // TODO: Check if this number is still correct
? 0
: totalBorrowed.dividedBy(marketDepositAmount).multipliedBy(100).toNumber(),
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' }, options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
title: 'Utilization Rate', title: 'Utilization Rate',
}, },
@ -74,7 +70,7 @@ export default function MarketDetails({ row, type }: Props) {
function getBorrowMarketDetails() { function getBorrowMarketDetails() {
return [ return [
{ {
amount: convertAmount(asset, totalBorrowed).toNumber(), amount: convertAmount(asset, debt).toNumber(),
options: { options: {
abbreviated: true, abbreviated: true,
suffix: isDollar ? undefined : ` ${displayCurrencySymbol}`, suffix: isDollar ? undefined : ` ${displayCurrencySymbol}`,
@ -93,9 +89,7 @@ export default function MarketDetails({ row, type }: Props) {
title: 'Oracle Price', title: 'Oracle Price',
}, },
{ {
amount: totalBorrowed.isZero() amount: debt.isZero() ? 0 : debt.dividedBy(deposits).multipliedBy(100).toNumber(), // TODO: CHeck if this is still correct
? 0
: totalBorrowed.dividedBy(marketDepositAmount).multipliedBy(100).toNumber(),
options: { minDecimals: 2, maxDecimals: 2, suffix: '%' }, options: { minDecimals: 2, maxDecimals: 2, suffix: '%' },
title: 'Utilization Rate', title: 'Utilization Rate',
}, },
@ -105,14 +99,15 @@ export default function MarketDetails({ row, type }: Props) {
if (type === 'lend') return getLendingMarketDetails() if (type === 'lend') return getLendingMarketDetails()
return getBorrowMarketDetails() return getBorrowMarketDetails()
}, [ }, [
type,
asset,
marketDepositAmount,
ltv,
totalBorrowed,
displayCurrencySymbol, displayCurrencySymbol,
type,
convertAmount, convertAmount,
asset,
debt,
ltv.max,
ltv.liq,
getConversionRate, getConversionRate,
deposits,
]) ])
return ( return (

View File

@ -7,7 +7,7 @@ import { ChevronDown, ChevronRight } from 'components/common/Icons'
import Text from 'components/common/Text' import Text from 'components/common/Text'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import useAsset from 'hooks/assets/useAsset' 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 { BNCoin } from 'types/classes/BNCoin'
import { byDenom } from 'utils/array' import { byDenom } from 'utils/array'
import { formatValue } from 'utils/formatters' import { formatValue } from 'utils/formatters'
@ -22,7 +22,8 @@ interface Props extends SelectOption {
export default function Option(props: Props) { export default function Option(props: Props) {
const isCoin = !!props.denom const isCoin = !!props.denom
const { data: marketAssets } = useMarketAssets() const markets = useMarkets()
const asset = useAsset(props.denom || '') const asset = useAsset(props.denom || '')
function handleOnClick(value: string | undefined) { function handleOnClick(value: string | undefined) {
@ -32,7 +33,7 @@ export default function Option(props: Props) {
if (isCoin) { if (isCoin) {
const balance = props.amount ?? BN_ZERO 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 if (!asset || !marketAsset) return null

View File

@ -1,8 +1,8 @@
import AvailableLendsTable from 'components/earn/lend/Table/AvailableLendsTable' import AvailableLendsTable from 'components/earn/lend/Table/AvailableLendsTable'
import DepositedLendsTable from 'components/earn/lend/Table/DepositedLendsTable' import DepositedLendsTable from 'components/earn/lend/Table/DepositedLendsTable'
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import useLendEnabledAssets from 'hooks/assets/useLendEnabledAssets' import useLendEnabledAssets from 'hooks/assets/useLendEnabledAssets'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
export default function Lends() { export default function Lends() {
const { accountLentAssets, availableAssets, allAssets } = useLendingMarketAssetsTableData() const { accountLentAssets, availableAssets, allAssets } = useLendingMarketAssetsTableData()
@ -23,10 +23,11 @@ function Fallback() {
const data: LendingMarketTableData[] = assets.map((asset) => ({ const data: LendingMarketTableData[] = assets.map((asset) => ({
asset, asset,
marketDepositCap: BN_ZERO, borrowEnabled: true,
borrowEnabled: false, depositEnabled: true,
marketDepositAmount: BN_ZERO, debt: BN_ZERO,
marketLiquidityAmount: BN_ZERO, deposits: BN_ZERO,
liquidity: BN_ZERO,
cap: { cap: {
max: BN_ZERO, max: BN_ZERO,
used: BN_ZERO, used: BN_ZERO,

View File

@ -1,50 +1,35 @@
import { useMemo } from 'react' import { useMemo } from 'react'
import { BN_ZERO } from 'constants/math' import { BN_ZERO } from 'constants/math'
import useAllAssets from 'hooks/assets/useAllAssets' import useMarkets from 'hooks/markets/useMarkets'
import useMarketDeposits from 'hooks/markets/useMarketDeposits'
import useMarketLiquidities from 'hooks/markets/useMarketLiquidities'
import useCurrentAccountLends from 'hooks/useCurrentAccountLends' import useCurrentAccountLends from 'hooks/useCurrentAccountLends'
import useDepositEnabledMarkets from 'hooks/useDepositEnabledMarkets'
import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice' import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice'
import { byDenom } from 'utils/array' import { byDenom } from 'utils/array'
import { BN } from 'utils/helpers'
function useLendingMarketAssetsTableData(): { function useLendingMarketAssetsTableData(): {
accountLentAssets: LendingMarketTableData[] accountLentAssets: LendingMarketTableData[]
availableAssets: LendingMarketTableData[] availableAssets: LendingMarketTableData[]
allAssets: LendingMarketTableData[] allAssets: LendingMarketTableData[]
} { } {
const markets = useDepositEnabledMarkets() const markets = useMarkets()
const accountLentAmounts = useCurrentAccountLends() const accountLentAmounts = useCurrentAccountLends()
const { data: marketLiquidities } = useMarketLiquidities()
const { data: marketDeposits } = useMarketDeposits()
const { convertAmount } = useDisplayCurrencyPrice() const { convertAmount } = useDisplayCurrencyPrice()
const assets = useAllAssets()
return useMemo(() => { return useMemo(() => {
const accountLentAssets: LendingMarketTableData[] = [], const accountLentAssets: LendingMarketTableData[] = [],
availableAssets: LendingMarketTableData[] = [] availableAssets: LendingMarketTableData[] = []
markets.forEach(({ denom, cap, ltv, apy, borrowEnabled }) => { markets.forEach((market) => {
const asset = assets.find(byDenom(denom)) as Asset const accountLentAmount =
const marketDepositAmount = BN(marketDeposits.find(byDenom(denom))?.amount ?? 0) accountLentAmounts.find(byDenom(market.asset.denom))?.amount ?? BN_ZERO
const marketLiquidityAmount = BN(marketLiquidities.find(byDenom(denom))?.amount ?? 0)
const accountLentAmount = accountLentAmounts.find(byDenom(denom))?.amount ?? BN_ZERO
const accountLentValue = accountLentAmount const accountLentValue = accountLentAmount
? convertAmount(asset, accountLentAmount) ? convertAmount(market.asset, accountLentAmount)
: undefined : undefined
const lendingMarketAsset: LendingMarketTableData = { const lendingMarketAsset: LendingMarketTableData = {
asset, ...market,
marketDepositAmount,
accountLentValue, accountLentValue,
accountLentAmount, accountLentAmount,
marketLiquidityAmount,
apy,
ltv,
borrowEnabled,
cap,
} }
if (lendingMarketAsset.accountLentAmount?.isZero()) { if (lendingMarketAsset.accountLentAmount?.isZero()) {
@ -59,7 +44,7 @@ function useLendingMarketAssetsTableData(): {
availableAssets, availableAssets,
allAssets: [...accountLentAssets, ...availableAssets], allAssets: [...accountLentAssets, ...availableAssets],
} }
}, [markets, assets, marketDeposits, marketLiquidities, accountLentAmounts, convertAmount]) }, [markets, accountLentAmounts, convertAmount])
} }
export default useLendingMarketAssetsTableData export default useLendingMarketAssetsTableData

View File

@ -2,7 +2,7 @@ import React from 'react'
import { FormattedNumber } from 'components/common/FormattedNumber' import { FormattedNumber } from 'components/common/FormattedNumber'
import Loading from 'components/common/Loading' import Loading from 'components/common/Loading'
import useMarketBorrowings from 'hooks/markets/useMarketBorrowings' import useMarket from 'hooks/markets/useMarket'
export const APY_META = { accessorKey: 'apy', header: 'APY Range' } export const APY_META = { accessorKey: 'apy', header: 'APY Range' }
@ -12,10 +12,7 @@ interface Props {
export default function Apy(props: Props) { export default function Apy(props: Props) {
const { vault } = props const { vault } = props
const { data: marketBorrowings } = useMarketBorrowings() const borrowRate = useMarket(vault.hls?.borrowDenom || '')?.apy.borrow
const borrowRate = marketBorrowings.find((asset) => asset.denom === vault.hls?.borrowDenom)
?.borrowRate
if (vault.apy === null || borrowRate === null) return <Loading /> if (vault.apy === null || borrowRate === null) return <Loading />

View File

@ -5,7 +5,7 @@ import { FormattedNumber } from 'components/common/FormattedNumber'
import Loading from 'components/common/Loading' import Loading from 'components/common/Loading'
import TitleAndSubCell from 'components/common/TitleAndSubCell' import TitleAndSubCell from 'components/common/TitleAndSubCell'
import useAllAssets from 'hooks/assets/useAllAssets' import useAllAssets from 'hooks/assets/useAllAssets'
import useBorrowAsset from 'hooks/useBorrowAsset' import useMarket from 'hooks/markets/useMarket'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import { calculateAccountLeverage } from 'utils/accounts' import { calculateAccountLeverage } from 'utils/accounts'
import { getLeveragedApy } from 'utils/math' import { getLeveragedApy } from 'utils/math'
@ -27,7 +27,7 @@ interface Props {
export default function ActiveAPY(props: Props) { export default function ActiveAPY(props: Props) {
const { data: prices } = usePrices() const { data: prices } = usePrices()
const assets = useAllAssets() 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( const leverage = useMemo(
() => calculateAccountLeverage(props.account, prices, assets), () => calculateAccountLeverage(props.account, prices, assets),

View File

@ -3,7 +3,7 @@ import { Row } from '@tanstack/react-table'
import { FormattedNumber } from 'components/common/FormattedNumber' import { FormattedNumber } from 'components/common/FormattedNumber'
import Loading from 'components/common/Loading' import Loading from 'components/common/Loading'
import TitleAndSubCell from 'components/common/TitleAndSubCell' import TitleAndSubCell from 'components/common/TitleAndSubCell'
import useBorrowAsset from 'hooks/useBorrowAsset' import useMarket from 'hooks/markets/useMarket'
import { getLeveragedApy } from 'utils/math' import { getLeveragedApy } from 'utils/math'
export const APY_RANGE_META = { header: 'APY range', accessorKey: 'apy' } export const APY_RANGE_META = { header: 'APY range', accessorKey: 'apy' }
@ -19,7 +19,7 @@ interface Props {
export default function ApyRange(props: Props) { export default function ApyRange(props: Props) {
const baseApy = props.strategy.apy 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) { if (!borrowRate || props.isLoading || !baseApy) {
return <Loading /> return <Loading />

View File

@ -1,12 +1,12 @@
import React, { Suspense, useMemo } from 'react' import React, { Suspense, useMemo } from 'react'
import AccountBalancesTable from 'components/account/AccountBalancesTable' import AccountBalancesTable from 'components/account/AccountBalancesTable'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import Card from 'components/common/Card' import Card from 'components/common/Card'
import TableSkeleton from 'components/common/Table/TableSkeleton' import TableSkeleton from 'components/common/Table/TableSkeleton'
import Text from 'components/common/Text' import Text from 'components/common/Text'
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
import useAccount from 'hooks/accounts/useAccount' import useAccount from 'hooks/accounts/useAccount'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
interface Props { interface Props {
accountId: string accountId: string

View File

@ -1,15 +1,15 @@
import { Suspense, useMemo } from 'react' import { Suspense, useMemo } from 'react'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import DisplayCurrency from 'components/common/DisplayCurrency' import DisplayCurrency from 'components/common/DisplayCurrency'
import { FormattedNumber } from 'components/common/FormattedNumber' import { FormattedNumber } from 'components/common/FormattedNumber'
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
import Skeleton from 'components/portfolio/SummarySkeleton' import Skeleton from 'components/portfolio/SummarySkeleton'
import { MAX_AMOUNT_DECIMALS } from 'constants/math' import { MAX_AMOUNT_DECIMALS } from 'constants/math'
import useAccount from 'hooks/accounts/useAccount' import useAccount from 'hooks/accounts/useAccount'
import useAllAssets from 'hooks/assets/useAllAssets' import useAllAssets from 'hooks/assets/useAllAssets'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
import useHealthComputer from 'hooks/useHealthComputer' import useHealthComputer from 'hooks/useHealthComputer'
import useHLSStakingAssets from 'hooks/useHLSStakingAssets' import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import { getAccountSummaryStats } from 'utils/accounts' import { getAccountSummaryStats } from 'utils/accounts'
import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants' import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants'

View File

@ -2,8 +2,10 @@ import classNames from 'classnames'
import { ReactNode, useMemo } from 'react' import { ReactNode, useMemo } from 'react'
import { NavLink, useParams, useSearchParams } from 'react-router-dom' import { NavLink, useParams, useSearchParams } from 'react-router-dom'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import { FormattedNumber } from 'components/common/FormattedNumber' import { FormattedNumber } from 'components/common/FormattedNumber'
import Loading from 'components/common/Loading' import Loading from 'components/common/Loading'
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
import Skeleton from 'components/portfolio/Card/Skeleton' import Skeleton from 'components/portfolio/Card/Skeleton'
import { DEFAULT_SETTINGS } from 'constants/defaultSettings' import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys' import { LocalStorageKeys } from 'constants/localStorageKeys'
@ -12,10 +14,8 @@ import useAccount from 'hooks/accounts/useAccount'
import useAllAssets from 'hooks/assets/useAllAssets' import useAllAssets from 'hooks/assets/useAllAssets'
import useLocalStorage from 'hooks/localStorage/useLocalStorage' import useLocalStorage from 'hooks/localStorage/useLocalStorage'
import useAccountId from 'hooks/useAccountId' import useAccountId from 'hooks/useAccountId'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
import useHealthComputer from 'hooks/useHealthComputer' import useHealthComputer from 'hooks/useHealthComputer'
import useHLSStakingAssets from 'hooks/useHLSStakingAssets' import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import { import {
calculateAccountApr, calculateAccountApr,

View File

@ -1,15 +1,15 @@
import { useMemo } from 'react' import { useMemo } from 'react'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData'
import DisplayCurrency from 'components/common/DisplayCurrency' import DisplayCurrency from 'components/common/DisplayCurrency'
import { FormattedNumber } from 'components/common/FormattedNumber' import { FormattedNumber } from 'components/common/FormattedNumber'
import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData'
import SummarySkeleton from 'components/portfolio/SummarySkeleton' import SummarySkeleton from 'components/portfolio/SummarySkeleton'
import { MAX_AMOUNT_DECIMALS } from 'constants/math' import { MAX_AMOUNT_DECIMALS } from 'constants/math'
import useAccounts from 'hooks/accounts/useAccounts' import useAccounts from 'hooks/accounts/useAccounts'
import useAllAssets from 'hooks/assets/useAllAssets' import useAllAssets from 'hooks/assets/useAllAssets'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
import useHLSStakingAssets from 'hooks/useHLSStakingAssets' import useHLSStakingAssets from 'hooks/useHLSStakingAssets'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import useStore from 'store' import useStore from 'store'
import { getAccountSummaryStats } from 'utils/accounts' import { getAccountSummaryStats } from 'utils/accounts'

View File

@ -1,9 +1,9 @@
import { useMemo } from 'react' import { useMemo } from 'react'
import AccountBalancesTable from 'components/account/AccountBalancesTable' 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 useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
export default function AccountDetailsCard() { export default function AccountDetailsCard() {
const account = useCurrentAccount() const account = useCurrentAccount()

View File

@ -6,8 +6,7 @@ import Text from 'components/common/Text'
import AssetSelectorItem from 'components/trade/TradeModule/AssetSelector/AssetSelectorItem' import AssetSelectorItem from 'components/trade/TradeModule/AssetSelector/AssetSelectorItem'
import useCurrentAccount from 'hooks/accounts/useCurrentAccount' import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets' import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets'
import useMarketAssets from 'hooks/markets/useMarketAssets' import useMarkets from 'hooks/markets/useMarkets'
import useMarketDeposits from 'hooks/markets/useMarketDeposits'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import useStore from 'store' import useStore from 'store'
import { getMergedBalancesForAsset } from 'utils/accounts' 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 baseDenom = useStore((s) => s.chainConfig.assets[0].denom)
const { assets, type, isOpen, toggleOpen, onChangeAsset } = props const { assets, type, isOpen, toggleOpen, onChangeAsset } = props
const account = useCurrentAccount() const account = useCurrentAccount()
const { data: marketAssets } = useMarketAssets() const markets = useMarkets()
const { data: marketDeposits } = useMarketDeposits()
const { data: prices } = usePrices() const { data: prices } = usePrices()
const marketEnabledAssets = useMarketEnabledAssets() const marketEnabledAssets = useMarketEnabledAssets()
const balances = useMemo(() => { const balances = useMemo(() => {
@ -36,8 +34,8 @@ export default function AssetList(props: Props) {
}, [account, marketEnabledAssets]) }, [account, marketEnabledAssets])
const sortedAssets = useMemo( const sortedAssets = useMemo(
() => sortAssetsOrPairs(assets, prices, marketDeposits, balances, baseDenom) as Asset[], () => sortAssetsOrPairs(assets, prices, markets, balances, baseDenom) as Asset[],
[assets, prices, marketDeposits, balances, baseDenom], [assets, prices, markets, balances, baseDenom],
) )
return ( return (
@ -63,9 +61,7 @@ export default function AssetList(props: Props) {
balances={balances} balances={balances}
key={`${type}-${asset.symbol}`} key={`${type}-${asset.symbol}`}
onSelect={props.onChangeAsset} onSelect={props.onChangeAsset}
depositCap={ depositCap={type === 'buy' ? markets?.find(byDenom(asset.denom))?.cap : undefined}
type === 'buy' ? marketAssets?.find(byDenom(asset.denom))?.cap : undefined
}
asset={asset} asset={asset}
/> />
))} ))}

View File

@ -5,8 +5,7 @@ import AssetSelectorItem from 'components/trade/TradeModule/AssetSelector/AssetS
import useCurrentAccount from 'hooks/accounts/useCurrentAccount' import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import useBaseAsset from 'hooks/assets/useBasetAsset' import useBaseAsset from 'hooks/assets/useBasetAsset'
import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets' import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets'
import useMarketAssets from 'hooks/markets/useMarketAssets' import useMarkets from 'hooks/markets/useMarkets'
import useMarketDeposits from 'hooks/markets/useMarketDeposits'
import usePrices from 'hooks/usePrices' import usePrices from 'hooks/usePrices'
import { getMergedBalancesForAsset } from 'utils/accounts' import { getMergedBalancesForAsset } from 'utils/accounts'
import { byDenom } from 'utils/array' import { byDenom } from 'utils/array'
@ -22,8 +21,7 @@ interface Props {
export default function PairsList(props: Props) { export default function PairsList(props: Props) {
const account = useCurrentAccount() const account = useCurrentAccount()
const { data: marketAssets } = useMarketAssets() const markets = useMarkets()
const { data: marketDeposits } = useMarketDeposits()
const { data: prices } = usePrices() const { data: prices } = usePrices()
const baseDenom = useBaseAsset().denom const baseDenom = useBaseAsset().denom
const marketEnabledAssets = useMarketEnabledAssets() const marketEnabledAssets = useMarketEnabledAssets()
@ -44,8 +42,8 @@ export default function PairsList(props: Props) {
}, [props.stables, props.assets]) }, [props.stables, props.assets])
const sortedPairs = useMemo( const sortedPairs = useMemo(
() => sortAssetsOrPairs(pairs, prices, marketDeposits, balances, baseDenom) as AssetPair[], () => sortAssetsOrPairs(pairs, prices, markets, balances, baseDenom) as AssetPair[],
[pairs, prices, marketDeposits, balances, baseDenom], [pairs, prices, markets, balances, baseDenom],
) )
return ( return (
@ -62,7 +60,7 @@ export default function PairsList(props: Props) {
balances={balances} balances={balances}
key={`${assetPair.buy.symbol}-${assetPair.sell.symbol}`} key={`${assetPair.buy.symbol}-${assetPair.sell.symbol}`}
onSelect={props.onChangeAssetPair} onSelect={props.onChangeAssetPair}
depositCap={marketAssets?.find(byDenom(assetPair.buy.denom))?.cap} depositCap={markets?.find(byDenom(assetPair.buy.denom))?.cap}
asset={assetPair.buy} asset={assetPair.buy}
sellAsset={assetPair.sell} sellAsset={assetPair.sell}
/> />

View File

@ -22,8 +22,7 @@ import { BN_ZERO } from 'constants/math'
import useCurrentAccount from 'hooks/accounts/useCurrentAccount' import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets' import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets'
import useLocalStorage from 'hooks/localStorage/useLocalStorage' import useLocalStorage from 'hooks/localStorage/useLocalStorage'
import useMarketAssets from 'hooks/markets/useMarketAssets' import useMarkets from 'hooks/markets/useMarkets'
import useMarketBorrowings from 'hooks/markets/useMarketBorrowings'
import useAutoLend from 'hooks/useAutoLend' import useAutoLend from 'hooks/useAutoLend'
import useChainConfig from 'hooks/useChainConfig' import useChainConfig from 'hooks/useChainConfig'
import useHealthComputer from 'hooks/useHealthComputer' import useHealthComputer from 'hooks/useHealthComputer'
@ -53,8 +52,7 @@ export default function SwapForm(props: Props) {
const [slippage] = useLocalStorage(LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage) const [slippage] = useLocalStorage(LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage)
const { computeMaxSwapAmount } = useHealthComputer(account) const { computeMaxSwapAmount } = useHealthComputer(account)
const [tradeDirection, setTradeDirection] = useState<TradeDirection>('long') const [tradeDirection, setTradeDirection] = useState<TradeDirection>('long')
const { data: borrowAssets } = useMarketBorrowings() const markets = useMarkets()
const { data: marketAssets } = useMarketAssets()
const [inputAsset, outputAsset] = useMemo(() => { const [inputAsset, outputAsset] = useMemo(() => {
if (isAdvanced) return [sellAsset, buyAsset] if (isAdvanced) return [sellAsset, buyAsset]
@ -65,7 +63,7 @@ export default function SwapForm(props: Props) {
inputAsset.denom, inputAsset.denom,
outputAsset.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 isRepayable = !!account?.debts.find(byDenom(outputAsset.denom))
const [isMarginChecked, setMarginChecked] = useToggle(isBorrowEnabled ? useMargin : false) const [isMarginChecked, setMarginChecked] = useToggle(isBorrowEnabled ? useMargin : false)
const [isAutoRepayChecked, setAutoRepayChecked] = useToggle( const [isAutoRepayChecked, setAutoRepayChecked] = useToggle(
@ -87,7 +85,7 @@ export default function SwapForm(props: Props) {
const assets = useMarketEnabledAssets() const assets = useMarketEnabledAssets()
const depositCapReachedCoins: BNCoin[] = useMemo(() => { const depositCapReachedCoins: BNCoin[] = useMemo(() => {
const outputMarketAsset = marketAssets.find(byDenom(outputAsset.denom)) const outputMarketAsset = markets.find(byDenom(outputAsset.denom))
if (!outputMarketAsset) return [] if (!outputMarketAsset) return []
@ -97,7 +95,7 @@ export default function SwapForm(props: Props) {
} }
return [] return []
}, [marketAssets, outputAsset.denom, outputAssetAmount]) }, [markets, outputAsset.denom, outputAssetAmount])
const onChangeInputAmount = useCallback( const onChangeInputAmount = useCallback(
(amount: BigNumber) => { (amount: BigNumber) => {
@ -305,9 +303,9 @@ export default function SwapForm(props: Props) {
modal, modal,
]) ])
const borrowAsset = useMemo( const borrowMarket = useMemo(
() => borrowAssets.find(byDenom(inputAsset.denom)), () => markets.find((market) => market.asset.denom === inputAsset.denom),
[borrowAssets, inputAsset.denom], [markets, inputAsset.denom],
) )
useEffect(() => { useEffect(() => {
@ -324,8 +322,8 @@ export default function SwapForm(props: Props) {
) )
const availableLiquidity = useMemo( const availableLiquidity = useMemo(
() => borrowAsset?.liquidity?.amount ?? BN_ZERO, () => borrowMarket?.liquidity ?? BN_ZERO,
[borrowAsset?.liquidity?.amount], [borrowMarket?.liquidity],
) )
const isSwapDisabled = useMemo( const isSwapDisabled = useMemo(
@ -349,7 +347,7 @@ export default function SwapForm(props: Props) {
<MarginToggle <MarginToggle
checked={isMarginChecked} checked={isMarginChecked}
onChange={handleMarginToggleChange} onChange={handleMarginToggleChange}
disabled={!borrowAsset?.isMarket} disabled={!borrowMarket?.borrowEnabled}
borrowAssetSymbol={inputAsset.symbol} borrowAssetSymbol={inputAsset.symbol}
/> />
<Divider /> <Divider />
@ -411,11 +409,8 @@ export default function SwapForm(props: Props) {
className='p-4 bg-white/5' className='p-4 bg-white/5'
/> />
{borrowAsset && borrowAmount.isGreaterThanOrEqualTo(availableLiquidity) && ( {borrowMarket && borrowAmount.isGreaterThanOrEqualTo(availableLiquidity) && (
<AvailableLiquidityMessage <AvailableLiquidityMessage market={borrowMarket} />
availableLiquidity={borrowAsset?.liquidity?.amount ?? BN_ZERO}
asset={borrowAsset}
/>
)} )}
{isAdvanced ? ( {isAdvanced ? (
<AssetAmountInput <AssetAmountInput
@ -450,7 +445,7 @@ export default function SwapForm(props: Props) {
<TradeSummary <TradeSummary
sellAsset={inputAsset} sellAsset={inputAsset}
buyAsset={outputAsset} buyAsset={outputAsset}
borrowRate={borrowAsset?.borrowRate} borrowRate={borrowMarket?.apy.borrow}
buyAction={handleBuyClick} buyAction={handleBuyClick}
buyButtonDisabled={isSwapDisabled} buyButtonDisabled={isSwapDisabled}
showProgressIndicator={isConfirming || isRouteLoading} showProgressIndicator={isConfirming || isRouteLoading}

View File

@ -6,7 +6,8 @@ import useChainConfig from 'hooks/useChainConfig'
export default function useAccountIdsAndKinds(address?: string, suspense = true, noHls = false) { export default function useAccountIdsAndKinds(address?: string, suspense = true, noHls = false) {
const chainConfig = useChainConfig() const chainConfig = useChainConfig()
return useSWR( 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) => { getAccountIds(chainConfig, address).then((accountIdsAndKinds) => {
if (noHls) { if (noHls) {

View File

@ -8,7 +8,7 @@ export default function useAccounts(kind: AccountKind, address?: string, suspens
const chainConfig = useChainConfig() const chainConfig = useChainConfig()
return useSWR( return useSWR(
`chains/${chainConfig.id}/accounts/${kind}`, address && `chains/${chainConfig.id}/accounts/${kind}`,
() => getAccounts(kind, chainConfig, address), () => getAccounts(kind, chainConfig, address),
{ {
suspense: suspense, suspense: suspense,

View 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])
}

View File

@ -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,
})
}

View File

@ -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,
},
)
}

View 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)
}

View File

@ -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,
})
}

View File

@ -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,
},
)
}

View 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
}

View 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]),
}))
}

View File

@ -1,15 +1,45 @@
import useSWR from 'swr' 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 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) { export default function useAssetIncentivesApy(denom: string) {
const chainConfig = useChainConfig() const chainConfig = useChainConfig()
const market = useMarket(denom)
const price = usePrice(denom)
return useSWR( return useSWR(
`chains/${chainConfig.id}/assets/${denom}/incentives`, market && `chains/${chainConfig.id}/assets/${denom}/incentives`,
() => calculateAssetIncentivesApy(chainConfig, denom), () => calculateAssetIncentivesApy(chainConfig, market!, price),
{ {
revalidateOnFocus: false, 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)
}

View File

@ -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))
}

View File

@ -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])
}

View File

@ -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])
}

View File

@ -34,6 +34,9 @@ export default function useClients() {
} as ContractClients } as ContractClients
}, },
{ {
revalidateOnFocus: false,
revalidateOnReconnect: false,
revalidateIfStale: false,
keepPreviousData: false, keepPreviousData: false,
}, },
) )

View File

@ -1,6 +0,0 @@
import useMarketAssets from 'hooks/markets/useMarketAssets'
export default function useDepositEnabledMarkets() {
const { data: markets } = useMarketAssets()
return markets.filter((market) => market.depositEnabled)
}

View File

@ -5,8 +5,12 @@ import useChainConfig from 'hooks/useChainConfig'
export default function useHLSStakingAssets() { export default function useHLSStakingAssets() {
const chainConfig = useChainConfig() const chainConfig = useChainConfig()
return useSWR('hls-staking', () => getHLSStakingAssets(chainConfig), { return useSWR(
`chains/${chainConfig.id}/assets/hls/staking`,
() => getHLSStakingAssets(chainConfig),
{
fallbackData: [], fallbackData: [],
revalidateOnFocus: false, revalidateOnFocus: false,
}) },
)
} }

View File

@ -1,9 +1,9 @@
import { useMemo } from 'react'
import useVaults from 'hooks/useVaults' import useVaults from 'hooks/useVaults'
export default function useVault(address: string) { export default function useVault(address: string) {
const { data: vaults } = useVaults(false) const { data: vaults } = useVaults(false)
if (!vaults?.length) return null return useMemo(() => vaults?.find((v) => v.address === address) ?? null, [vaults, address])
return vaults.find((v) => v.address === address) ?? null
} }

View File

@ -6,8 +6,12 @@ import useChainConfig from 'hooks/useChainConfig'
export default function useVaults(suspense: boolean = true, address?: string) { export default function useVaults(suspense: boolean = true, address?: string) {
const chainConfig = useChainConfig() const chainConfig = useChainConfig()
return useSWR(`chains/${chainConfig.id}/vaults/${address}`, () => getVaults(chainConfig), { return useSWR(
address && `chains/${chainConfig.id}/vaults/${address}`,
() => getVaults(chainConfig),
{
suspense, suspense,
revalidateOnFocus: false, revalidateOnFocus: false,
}) },
)
} }

View File

@ -7,7 +7,7 @@ export default function useWalletBalances(address?: string) {
const chainConfig = useChainConfig() const chainConfig = useChainConfig()
return useSWR( return useSWR(
`chains/${chainConfig.id}/wallets/${address}/balances`, address && `chains/${chainConfig.id}/wallets/${address}/balances`,
() => getWalletBalances(chainConfig, address || ''), () => getWalletBalances(chainConfig, address || ''),
{ {
isPaused: () => !address, isPaused: () => !address,

View File

@ -2,19 +2,21 @@ import classNames from 'classnames'
import { Suspense } from 'react' import { Suspense } from 'react'
import { isMobile } from 'react-device-detect' import { isMobile } from 'react-device-detect'
import { useLocation } from 'react-router-dom' import { useLocation } from 'react-router-dom'
import { SWRConfig } from 'swr'
import AccountDetails from 'components/account/AccountDetails' import AccountDetails from 'components/account/AccountDetails'
import Background from 'components/common/Background' import Background from 'components/common/Background'
import Footer from 'components/common/Footer' 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 PageMetadata from 'components/common/PageMetadata'
import Toaster from 'components/common/Toaster' 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 { DEFAULT_SETTINGS } from 'constants/defaultSettings'
import { LocalStorageKeys } from 'constants/localStorageKeys' import { LocalStorageKeys } from 'constants/localStorageKeys'
import useLocalStorage from 'hooks/localStorage/useLocalStorage' import useLocalStorage from 'hooks/localStorage/useLocalStorage'
import useAccountId from 'hooks/useAccountId' import useAccountId from 'hooks/useAccountId'
import useStore from 'store' import useStore from 'store'
import { debugSWR } from 'utils/middleware'
interface Props { interface Props {
focusComponent: FocusComponent | null focusComponent: FocusComponent | null
@ -62,6 +64,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
return ( return (
<> <>
<SWRConfig value={{ use: [debugSWR] }}>
<PageMetadata /> <PageMetadata />
<Background /> <Background />
<DesktopHeader /> <DesktopHeader />
@ -92,6 +95,7 @@ export default function Layout({ children }: { children: React.ReactNode }) {
<Footer /> <Footer />
<ModalsContainer /> <ModalsContainer />
<Toaster /> <Toaster />
</SWRConfig>
</> </>
) )
} }

View File

@ -50,35 +50,6 @@ interface BigNumberCoin {
amount: BigNumber 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 { interface HLSStrategy extends HLSStrategyNoCap {
depositCap: DepositCap depositCap: DepositCap
} }

View File

@ -1,10 +1,11 @@
interface Market { interface Market {
denom: string asset: Asset
debtTotalScaled: string cap: DepositCap // Deposits via CM
collateralTotalScaled: string debt: BigNumber // Total outstanding debt
deposits: BigNumber // Deposits directly into the RB
liquidity: BigNumber // Available liqudiity to be borrowed
depositEnabled: boolean depositEnabled: boolean
borrowEnabled: boolean borrowEnabled: boolean
cap: DepositCap
apy: { apy: {
borrow: number borrow: number
deposit: number deposit: number
@ -14,3 +15,12 @@ interface Market {
liq: number liq: number
} }
} }
interface BorrowMarketTableData extends Market {
accountDebt?: BigNumber
}
interface LendingMarketTableData extends Market {
accountLentAmount?: BigNumber
accountLentValue?: BigNumber
}

View File

@ -14,11 +14,11 @@ function isAssetPair(assetPair: Asset | AssetPair): assetPair is AssetPair {
export function sortAssetsOrPairs( export function sortAssetsOrPairs(
assets: Asset[] | AssetPair[], assets: Asset[] | AssetPair[],
prices: BNCoin[], prices: BNCoin[],
marketDeposits: BNCoin[], markets: Market[],
balances: BNCoin[], balances: BNCoin[],
baseDenom: string, baseDenom: string,
): Asset[] | AssetPair[] { ): 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) => { return assets.sort((a, b) => {
const assetA = isAssetPair(a) ? a.buy : a const assetA = isAssetPair(a) ? a.buy : a
@ -37,8 +37,10 @@ export function sortAssetsOrPairs(
if (aDenom === baseDenom) return -1 if (aDenom === baseDenom) return -1
if (bDenom === baseDenom) return 1 if (bDenom === baseDenom) return 1
const aMarketDeposit = marketDeposits?.find(byDenom(aDenom))?.amount ?? BN_ZERO const aMarketDeposit =
const bMarketDeposit = marketDeposits?.find(byDenom(bDenom))?.amount ?? BN_ZERO 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 aMarketValue = demagnify(aMarketDeposit, assetA) * aPrice.toNumber()
const bMarketValue = demagnify(bMarketDeposit, assetB) * bPrice.toNumber() const bMarketValue = demagnify(bMarketDeposit, assetB) * bPrice.toNumber()

13
src/utils/middleware.ts Normal file
View 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)
}

View File

@ -11,18 +11,20 @@ import { BN, getLeverageFromLTV } from 'utils/helpers'
import { convertAprToApy } from 'utils/parsers' import { convertAprToApy } from 'utils/parsers'
export function resolveMarketResponse( export function resolveMarketResponse(
marketResponse: RedBankMarket, asset: Asset,
marketResponse: RedBankMarket & Partial<Market>,
assetParamsResponse: AssetParams, assetParamsResponse: AssetParams,
assetCapResponse: TotalDepositResponse, assetCapResponse: TotalDepositResponse,
): Market { ): Market {
return { return {
denom: marketResponse.denom, asset,
apy: { apy: {
borrow: convertAprToApy(Number(marketResponse.borrow_rate), 365) * 100, borrow: convertAprToApy(Number(marketResponse.borrow_rate), 365) * 100,
deposit: convertAprToApy(Number(marketResponse.liquidity_rate), 365) * 100, deposit: convertAprToApy(Number(marketResponse.liquidity_rate), 365) * 100,
}, },
debtTotalScaled: marketResponse.debt_total_scaled, debt: marketResponse.debt ?? BN_ZERO,
collateralTotalScaled: marketResponse.collateral_total_scaled, deposits: marketResponse.deposits ?? BN_ZERO,
liquidity: marketResponse.liquidity ?? BN_ZERO,
depositEnabled: assetParamsResponse.red_bank.deposit_enabled, depositEnabled: assetParamsResponse.red_bank.deposit_enabled,
borrowEnabled: assetParamsResponse.red_bank.borrow_enabled, borrowEnabled: assetParamsResponse.red_bank.borrow_enabled,
cap: { cap: {