diff --git a/src/api/incentives/calculateAssetIncentivesApy.ts b/src/api/incentives/calculateAssetIncentivesApy.ts deleted file mode 100644 index 243a952b..00000000 --- a/src/api/incentives/calculateAssetIncentivesApy.ts +++ /dev/null @@ -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 { - 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 - } -} diff --git a/src/api/markets/getMarket.ts b/src/api/markets/getMarket.ts deleted file mode 100644 index 078bf5fc..00000000 --- a/src/api/markets/getMarket.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { cacheFn, marketCache } from 'api/cache' -import { getParamsQueryClient, getRedBankQueryClient } from 'api/cosmwasm-client' -import { resolveMarketResponse } from 'utils/resolvers' - -export default async function getMarket(chainConfig: ChainConfig, denom: string): Promise { - 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 - } -} diff --git a/src/api/markets/getMarketBorrowings.ts b/src/api/markets/getMarketBorrowings.ts deleted file mode 100644 index 1b0c65b8..00000000 --- a/src/api/markets/getMarketBorrowings.ts +++ /dev/null @@ -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 { - 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')) -} diff --git a/src/api/markets/getMarketDebts.ts b/src/api/markets/getMarketDebts.ts deleted file mode 100644 index ab3e3c0f..00000000 --- a/src/api/markets/getMarketDebts.ts +++ /dev/null @@ -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 { - 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( - (debt, index) => new BNCoin({ denom: markets[index].denom, amount: debt }), - ) - } catch (ex) { - throw ex - } -} diff --git a/src/api/markets/getMarketDeposits.ts b/src/api/markets/getMarketDeposits.ts deleted file mode 100644 index 824c824e..00000000 --- a/src/api/markets/getMarketDeposits.ts +++ /dev/null @@ -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 { - try { - const markets: Market[] = await getMarkets(chainConfig) - const depositQueries = markets.map((market) => - getUnderlyingLiquidityAmount(chainConfig, market), - ) - const depositsResults = await Promise.all(depositQueries) - - return depositsResults.map( - (deposit, index) => - new BNCoin({ - denom: markets[index].denom, - amount: deposit, - }), - ) - } catch (ex) { - throw ex - } -} diff --git a/src/api/markets/getMarketLiquidities.ts b/src/api/markets/getMarketLiquidities.ts deleted file mode 100644 index 0c8cb3e0..00000000 --- a/src/api/markets/getMarketLiquidities.ts +++ /dev/null @@ -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 { - 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')) -} diff --git a/src/api/markets/getMarketUnderlyingLiquidityAmount.ts b/src/api/markets/getMarketUnderlyingLiquidityAmount.ts deleted file mode 100644 index e2fe4de0..00000000 --- a/src/api/markets/getMarketUnderlyingLiquidityAmount.ts +++ /dev/null @@ -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 { - 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 - } -} diff --git a/src/api/markets/getMarkets.ts b/src/api/markets/getMarkets.ts deleted file mode 100644 index cbcc4370..00000000 --- a/src/api/markets/getMarkets.ts +++ /dev/null @@ -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 { - 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 - } -} diff --git a/src/components/Modals/AddVaultAssets/AddVaultBorrowAssetsModalContent.tsx b/src/components/Modals/AddVaultAssets/AddVaultBorrowAssetsModalContent.tsx index 8bd8e29f..f68e6a6f 100644 --- a/src/components/Modals/AddVaultAssets/AddVaultBorrowAssetsModalContent.tsx +++ b/src/components/Modals/AddVaultAssets/AddVaultBorrowAssetsModalContent.tsx @@ -1,9 +1,9 @@ import { useCallback, useMemo, useState } from 'react' -import AssetsSelect from 'components/Modals/AssetsSelect' import SearchBar from 'components/common/SearchBar' import Text from 'components/common/Text' -import useMarketBorrowings from 'hooks/markets/useMarketBorrowings' +import AssetsSelect from 'components/Modals/AssetsSelect' +import useMarkets from 'hooks/markets/useMarkets' import useStore from 'store' interface Props { @@ -14,16 +14,16 @@ interface Props { export default function AddVaultAssetsModalContent(props: Props) { const [searchString, setSearchString] = useState('') - const { data: borrowAssets } = useMarketBorrowings() + const markets = useMarkets() - const filteredBorrowAssets: BorrowAsset[] = useMemo(() => { - return borrowAssets.filter( - (asset) => - asset.name.toLowerCase().includes(searchString.toLowerCase()) || - asset.denom.toLowerCase().includes(searchString.toLowerCase()) || - asset.symbol.toLowerCase().includes(searchString.toLowerCase()), + const filteredMarkets: Market[] = useMemo(() => { + return markets.filter( + (market) => + market.asset.name.toLowerCase().includes(searchString.toLowerCase()) || + market.asset.denom.toLowerCase().includes(searchString.toLowerCase()) || + market.asset.symbol.toLowerCase().includes(searchString.toLowerCase()), ) - }, [borrowAssets, searchString]) + }, [markets, searchString]) function onChangeSearchString(value: string) { setSearchString(value) @@ -31,21 +31,21 @@ export default function AddVaultAssetsModalContent(props: Props) { const [poolAssets, stableAssets] = useMemo( () => - filteredBorrowAssets.reduce( - (acc, asset) => { + filteredMarkets.reduce( + (acc, market) => { if ( - asset.denom === props.vault.denoms.primary || - asset.denom === props.vault.denoms.secondary + market.asset.denom === props.vault.denoms.primary || + market.asset.denom === props.vault.denoms.secondary ) { - acc[0].push(asset) - } else if (asset.isStable) { - acc[1].push(asset) + acc[0].push(market.asset) + } else if (market.asset.isStable) { + acc[1].push(market.asset) } return acc }, - [[], []] as [BorrowAsset[], BorrowAsset[]], + [[], []] as [Asset[], Asset[]], ), - [filteredBorrowAssets, props.vault.denoms.primary, props.vault.denoms.secondary], + [filteredMarkets, props.vault.denoms.primary, props.vault.denoms.secondary], ) const selectedDenoms = useStore((s) => s.addVaultBorrowingsModal?.selectedDenoms) diff --git a/src/components/Modals/AssetsSelect/index.tsx b/src/components/Modals/AssetsSelect/index.tsx index 3c8ffbf9..eaa4f7ea 100644 --- a/src/components/Modals/AssetsSelect/index.tsx +++ b/src/components/Modals/AssetsSelect/index.tsx @@ -1,15 +1,16 @@ import { RowSelectionState } from '@tanstack/react-table' import { useEffect, useMemo, useState } from 'react' -import useAssetSelectColumns from 'components/Modals/AssetsSelect/Columns/useAssetSelectColumns' import Table from 'components/common/Table' +import useAssetSelectColumns from 'components/Modals/AssetsSelect/Columns/useAssetSelectColumns' import useGetCoinValue from 'hooks/assets/useGetCoinValue' -import useMarketAssets from 'hooks/markets/useMarketAssets' +import useMarkets from 'hooks/markets/useMarkets' import useStore from 'store' import { BNCoin } from 'types/classes/BNCoin' import { byDenom } from 'utils/array' import { BN } from 'utils/helpers' +// TODO: Pass the market data directly here instead of the assets interface Props { assets: Asset[] onChangeSelected: (selected: string[]) => void @@ -20,12 +21,11 @@ interface Props { export default function AssetsSelect(props: Props) { const { assets, onChangeSelected, selectedDenoms, isBorrow } = props const columns = useAssetSelectColumns(isBorrow) - const { data: markets } = useMarketAssets() + const markets = useMarkets() const getCoinValue = useGetCoinValue() const defaultSelected = useMemo(() => { - const selectableAssets = assets - return selectableAssets.reduce( + return assets.reduce( (acc, asset, index) => { if (selectedDenoms?.includes(asset.denom)) { acc[index] = true @@ -48,7 +48,7 @@ export default function AssetsSelect(props: Props) { asset, balance: balancesForAsset?.amount ?? '0', value, - market: markets.find((market) => market.denom === asset.denom), + market: markets.find((market) => market.asset.denom === asset.denom), } }) }, [balances, assets, markets, getCoinValue]) diff --git a/src/components/Modals/BorrowModal.tsx b/src/components/Modals/BorrowModal.tsx index 81fb7b66..823b1a68 100644 --- a/src/components/Modals/BorrowModal.tsx +++ b/src/components/Modals/BorrowModal.tsx @@ -16,7 +16,7 @@ import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSli import Modal from 'components/Modals/Modal' import { BN_ZERO } from 'constants/math' import useCurrentAccount from 'hooks/accounts/useCurrentAccount' -import useMarketAssets from 'hooks/markets/useMarketAssets' +import useMarkets from 'hooks/markets/useMarkets' import useAutoLend from 'hooks/useAutoLend' import useHealthComputer from 'hooks/useHealthComputer' import useToggle from 'hooks/useToggle' @@ -91,7 +91,7 @@ function BorrowModal(props: Props) { const isAutoLendEnabled = autoLendEnabledAccountIds.includes(account.id) const { computeMaxBorrowAmount } = useHealthComputer(account) const totalDebt = BN(getDebtAmount(modal)) - const { data: marketAssets } = useMarketAssets() + const markets = useMarkets() const [depositBalance, lendBalance] = useMemo( () => [ @@ -107,13 +107,13 @@ function BorrowModal(props: Props) { ) const overpayExeedsCap = useMemo(() => { - const marketAsset = marketAssets.find(byDenom(asset.denom)) + const marketAsset = markets.find(byDenom(asset.denom)) if (!marketAsset) return const overpayAmount = totalDebtRepayAmount.minus(totalDebt) const marketCapAfterOverpay = marketAsset.cap.used.plus(overpayAmount) return marketAsset.cap.max.isLessThanOrEqualTo(marketCapAfterOverpay) - }, [marketAssets, asset.denom, totalDebt, totalDebtRepayAmount]) + }, [markets, asset.denom, totalDebt, totalDebtRepayAmount]) const maxRepayAmount = useMemo(() => { const maxBalance = repayFromWallet @@ -187,7 +187,7 @@ function BorrowModal(props: Props) { ? BN_ZERO : computeMaxBorrowAmount(asset.denom, borrowToWallet ? 'wallet' : 'deposit') - return BigNumber.min(maxBorrowAmount, modal.marketData?.liquidity?.amount || 0) + return BigNumber.min(maxBorrowAmount, modal.marketData?.liquidity || 0) }, [asset.denom, borrowToWallet, computeMaxBorrowAmount, isRepay, modal.marketData]) useEffect(() => { @@ -266,7 +266,7 @@ function BorrowModal(props: Props) {
@@ -274,7 +274,7 @@ function BorrowModal(props: Props) { className='text-xs' coin={BNCoin.fromDenomAndBigNumber( asset.denom, - modal.marketData?.liquidity?.amount ?? BN_ZERO, + modal.marketData?.liquidity ?? BN_ZERO, )} parentheses /> diff --git a/src/components/Modals/HLS/Deposit/Leverage.tsx b/src/components/Modals/HLS/Deposit/Leverage.tsx index acb2da25..b23ac0ff 100644 --- a/src/components/Modals/HLS/Deposit/Leverage.tsx +++ b/src/components/Modals/HLS/Deposit/Leverage.tsx @@ -2,13 +2,13 @@ import React, { useMemo } from 'react' import Button from 'components/common/Button' import { ArrowRight } from 'components/common/Icons' -import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary' import TokenInputWithSlider from 'components/common/TokenInput/TokenInputWithSlider' +import LeverageSummary from 'components/Modals/HLS/Deposit/LeverageSummary' import { getLeveragedApy } from 'utils/math' interface Props { amount: BigNumber - asset: BorrowAsset + borrowMarket: Market max: BigNumber onChangeAmount: (amount: BigNumber) => void onClickBtn: () => void @@ -21,15 +21,15 @@ interface Props { export default function Leverage(props: Props) { const apy = useMemo(() => { - if (!props.asset.borrowRate) return 0 - return getLeveragedApy(props.baseApy, props.asset.borrowRate, props.leverage) - }, [props.asset.borrowRate, props.baseApy, props.leverage]) + if (!props.borrowMarket.apy.borrow) return 0 + return getLeveragedApy(props.baseApy, props.borrowMarket.apy.borrow, props.leverage) + }, [props.baseApy, props.borrowMarket.apy.borrow, props.leverage]) return (
- +
diff --git a/src/components/Modals/HLS/Deposit/LeverageSummary.tsx b/src/components/Modals/HLS/Deposit/LeverageSummary.tsx index 7139eac2..a4d233b1 100644 --- a/src/components/Modals/HLS/Deposit/LeverageSummary.tsx +++ b/src/components/Modals/HLS/Deposit/LeverageSummary.tsx @@ -1,7 +1,7 @@ import React, { useMemo } from 'react' import SummaryItems from 'components/common/SummaryItems' -import useBorrowAsset from 'hooks/useBorrowAsset' +import useMarket from 'hooks/markets/useMarket' interface Props { asset: Asset @@ -10,7 +10,7 @@ interface Props { } export default function LeverageSummary(props: Props) { - const borrowAsset = useBorrowAsset(props.asset.denom) + const market = useMarket(props.asset.denom) const items: SummaryItem[] = useMemo(() => { return [ @@ -21,7 +21,7 @@ export default function LeverageSummary(props: Props) { }, { title: `Borrow APR ${props.asset.symbol}`, - amount: borrowAsset?.borrowRate || 0, + amount: market?.apy.borrow || 0, options: { suffix: '%', minDecimals: 2, maxDecimals: 2 }, }, { @@ -30,7 +30,7 @@ export default function LeverageSummary(props: Props) { options: { prefix: '$' }, }, ] - }, [borrowAsset?.borrowRate, props.apy, props.asset.symbol, props.positionValue]) + }, [market?.apy.borrow, props.apy, props.asset.symbol, props.positionValue]) return } diff --git a/src/components/Modals/HLS/Deposit/Summary/index.tsx b/src/components/Modals/HLS/Deposit/Summary/index.tsx index 43099a90..c780bded 100644 --- a/src/components/Modals/HLS/Deposit/Summary/index.tsx +++ b/src/components/Modals/HLS/Deposit/Summary/index.tsx @@ -4,13 +4,12 @@ import Button from 'components/common/Button' import { ArrowRight } from 'components/common/Icons' import AssetSummary from 'components/Modals/HLS/Deposit/Summary/AssetSummary' import YourPosition from 'components/Modals/HLS/Deposit/Summary/YourPosition' -import useBorrowAsset from 'hooks/useBorrowAsset' import { BNCoin } from 'types/classes/BNCoin' interface Props { apy: number borrowAmount: BigNumber - borrowAsset: Asset + borrowMarket: Market collateralAsset: Asset depositAmount: BigNumber leverage: number @@ -20,18 +19,14 @@ interface Props { } export default function Summary(props: Props) { - const borrowAsset = useBorrowAsset(props.borrowAsset.denom) - - if (!borrowAsset) return null - return (
- +
{props.borrowings.map((coin) => { const asset = assets.find(byDenom(coin.denom)) - const borrowRate = marketAssets?.find((market) => market.denom === coin.denom)?.apy.borrow + const borrowRate = markets?.find((market) => market.asset.denom === coin.denom)?.apy + .borrow if (!asset || !borrowRate) return diff --git a/src/components/account/AccountBalancesTable/Columns/useAccountBalancesColumns.tsx b/src/components/account/AccountBalancesTable/Columns/useAccountBalancesColumns.tsx index 5f488a1e..441e257d 100644 --- a/src/components/account/AccountBalancesTable/Columns/useAccountBalancesColumns.tsx +++ b/src/components/account/AccountBalancesTable/Columns/useAccountBalancesColumns.tsx @@ -13,7 +13,7 @@ import Value, { VALUE_META, valueBalancesSortingFn, } from 'components/account/AccountBalancesTable/Columns/Value' -import useMarketAssets from 'hooks/markets/useMarketAssets' +import useMarkets from 'hooks/markets/useMarkets' import useHealthComputer from 'hooks/useHealthComputer' import useStore from 'store' @@ -21,7 +21,8 @@ export default function useAccountBalancesColumns( account: Account, showLiquidationPrice?: boolean, ) { - const { data: markets } = useMarketAssets() + const markets = useMarkets() + const updatedAccount = useStore((s) => s.updatedAccount) const { computeLiquidationPrice } = useHealthComputer(updatedAccount ?? account) diff --git a/src/components/account/AccountComposition.tsx b/src/components/account/AccountComposition.tsx index 3a791f48..936bc265 100644 --- a/src/components/account/AccountComposition.tsx +++ b/src/components/account/AccountComposition.tsx @@ -2,16 +2,16 @@ import BigNumber from 'bignumber.js' import classNames from 'classnames' import { useMemo } from 'react' +import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' import DisplayCurrency from 'components/common/DisplayCurrency' import { FormattedNumber } from 'components/common/FormattedNumber' import { ArrowRight } from 'components/common/Icons' import Text from 'components/common/Text' +import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData' import { BN_ZERO, MAX_AMOUNT_DECIMALS } from 'constants/math' import { ORACLE_DENOM } from 'constants/oracle' import useAllAssets from 'hooks/assets/useAllAssets' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' import useHLSStakingAssets from 'hooks/useHLSStakingAssets' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' import usePrices from 'hooks/usePrices' import useStore from 'store' import { BNCoin } from 'types/classes/BNCoin' diff --git a/src/components/account/AccountDetails/index.tsx b/src/components/account/AccountDetails/index.tsx index 79d0ff8b..6cc4631d 100644 --- a/src/components/account/AccountDetails/index.tsx +++ b/src/components/account/AccountDetails/index.tsx @@ -8,6 +8,7 @@ import AccountDetailsLeverage from 'components/account/AccountDetails/AccountDet import Skeleton from 'components/account/AccountDetails/Skeleton' import AccountPerpPositionTable from 'components/account/AccountPerpPositionTable' import { HealthGauge } from 'components/account/Health/HealthGauge' +import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' import EscButton from 'components/common/Button/EscButton' import { glowElement } from 'components/common/Button/utils' import Card from 'components/common/Card' @@ -15,6 +16,7 @@ import DisplayCurrency from 'components/common/DisplayCurrency' import { FormattedNumber } from 'components/common/FormattedNumber' import { ThreeDots } from 'components/common/Icons' import Text from 'components/common/Text' +import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData' import { DEFAULT_SETTINGS } from 'constants/defaultSettings' import { LocalStorageKeys } from 'constants/localStorageKeys' import { ORACLE_DENOM } from 'constants/oracle' @@ -24,10 +26,8 @@ import useCurrentAccount from 'hooks/accounts/useCurrentAccount' import useAllAssets from 'hooks/assets/useAllAssets' import useLocalStorage from 'hooks/localStorage/useLocalStorage' import useAccountId from 'hooks/useAccountId' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' -import useHLSStakingAssets from 'hooks/useHLSStakingAssets' import useHealthComputer from 'hooks/useHealthComputer' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' +import useHLSStakingAssets from 'hooks/useHLSStakingAssets' import usePrices from 'hooks/usePrices' import useStore from 'store' import { BNCoin } from 'types/classes/BNCoin' diff --git a/src/components/account/AccountFund/AccountFundContent.tsx b/src/components/account/AccountFund/AccountFundContent.tsx index b28a2734..7232639a 100644 --- a/src/components/account/AccountFund/AccountFundContent.tsx +++ b/src/components/account/AccountFund/AccountFundContent.tsx @@ -10,7 +10,7 @@ import Text from 'components/common/Text' import WalletBridges from 'components/Wallet/WalletBridges' import { BN_ZERO } from 'constants/math' import useBaseAsset from 'hooks/assets/useBasetAsset' -import useMarketAssets from 'hooks/markets/useMarketAssets' +import useMarkets from 'hooks/markets/useMarkets' import useAutoLend from 'hooks/useAutoLend' import { useUpdatedAccount } from 'hooks/useUpdatedAccount' import useWalletBalances from 'hooks/useWalletBalances' @@ -35,7 +35,8 @@ export default function AccountFundContent(props: Props) { const { autoLendEnabledAccountIds } = useAutoLend() const isLending = autoLendEnabledAccountIds.includes(props.accountId) const [fundingAssets, setFundingAssets] = useState([]) - const { data: marketAssets } = useMarketAssets() + const markets = useMarkets() + const { data: walletBalances } = useWalletBalances(props.address) const { simulateDeposits } = useUpdatedAccount(props.account) const baseAsset = useBaseAsset() @@ -127,7 +128,7 @@ export default function AccountFundContent(props: Props) { const depositCapReachedCoins = useMemo(() => { const depositCapReachedCoins: BNCoin[] = [] fundingAssets.forEach((asset) => { - const marketAsset = marketAssets.find(byDenom(asset.denom)) + const marketAsset = markets.find(byDenom(asset.denom)) if (!marketAsset) return const capLeft = getCapLeftWithBuffer(marketAsset.cap) @@ -137,7 +138,7 @@ export default function AccountFundContent(props: Props) { depositCapReachedCoins.push(BNCoin.fromDenomAndBigNumber(asset.denom, capLeft)) }) return depositCapReachedCoins - }, [fundingAssets, marketAssets]) + }, [fundingAssets, markets]) return ( <> diff --git a/src/components/account/AccountList/AccountStats.tsx b/src/components/account/AccountList/AccountStats.tsx index 4cc73228..3dec345f 100644 --- a/src/components/account/AccountList/AccountStats.tsx +++ b/src/components/account/AccountList/AccountStats.tsx @@ -2,15 +2,15 @@ import { useCallback, useMemo } from 'react' import AccountFundFullPage from 'components/account/AccountFund/AccountFundFullPage' import Skeleton from 'components/account/AccountList/Skeleton' +import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' import Button from 'components/common/Button' import { ArrowDownLine, ArrowUpLine, TrashBin } from 'components/common/Icons' import SwitchAutoLend from 'components/common/Switch/SwitchAutoLend' +import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData' import useAccount from 'hooks/accounts/useAccount' import useAllAssets from 'hooks/assets/useAllAssets' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' import useHealthComputer from 'hooks/useHealthComputer' import useHLSStakingAssets from 'hooks/useHLSStakingAssets' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' import usePrices from 'hooks/usePrices' import useStore from 'store' import { calculateAccountApr, calculateAccountBalanceValue } from 'utils/accounts' diff --git a/src/components/account/AccountSummary.tsx b/src/components/account/AccountSummary.tsx index 38e39a58..dcb5c1ff 100644 --- a/src/components/account/AccountSummary.tsx +++ b/src/components/account/AccountSummary.tsx @@ -5,21 +5,21 @@ import AccountBalancesTable from 'components/account/AccountBalancesTable' import AccountComposition from 'components/account/AccountComposition' import AccountPerpPositionTable from 'components/account/AccountPerpPositionTable' import HealthBar from 'components/account/Health/HealthBar' +import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' import Accordion from 'components/common/Accordion' import Card from 'components/common/Card' import DisplayCurrency from 'components/common/DisplayCurrency' import { FormattedNumber } from 'components/common/FormattedNumber' import { ArrowRight } from 'components/common/Icons' import Text from 'components/common/Text' +import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData' import { DEFAULT_SETTINGS } from 'constants/defaultSettings' import { LocalStorageKeys } from 'constants/localStorageKeys' import { BN_ZERO } from 'constants/math' import { ORACLE_DENOM } from 'constants/oracle' import useAllAssets from 'hooks/assets/useAllAssets' import useLocalStorage from 'hooks/localStorage/useLocalStorage' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' import useHealthComputer from 'hooks/useHealthComputer' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' import usePrices from 'hooks/usePrices' import useStore from 'store' import { BNCoin } from 'types/classes/BNCoin' diff --git a/src/components/borrow/Borrowings.tsx b/src/components/borrow/Borrowings.tsx index 9f896c3b..a30cc99e 100644 --- a/src/components/borrow/Borrowings.tsx +++ b/src/components/borrow/Borrowings.tsx @@ -1,8 +1,8 @@ import AvailableBorrowingsTable from 'components/borrow/Table/AvailableBorrowingsTable' import DepositedBorrowingsTable from 'components/borrow/Table/DepositedBorrowingsTable' +import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' import { BN_ZERO } from 'constants/math' import useBorrowEnabledAssets from 'hooks/assets/useBorrowEnabledAssets' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' export default function Borrowings() { const data = useBorrowMarketAssetsTableData() @@ -30,10 +30,18 @@ function Fallback() { max: 0, liq: 0, }, - liquidity: null, - marketDepositAmount: BN_ZERO, + liquidity: BN_ZERO, marketLiquidityRate: 0, - marketLiquidityAmount: BN_ZERO, + cap: { + denom: asset.denom, + max: BN_ZERO, + used: BN_ZERO, + }, + debt: BN_ZERO, + borrowEnabled: true, + depositEnabled: true, + deposits: BN_ZERO, + accountDebt: BN_ZERO, })) return diff --git a/src/components/borrow/Table/Columns/Debt.tsx b/src/components/borrow/Table/Columns/Debt.tsx index ebf827b7..794822c6 100644 --- a/src/components/borrow/Table/Columns/Debt.tsx +++ b/src/components/borrow/Table/Columns/Debt.tsx @@ -16,15 +16,9 @@ export const debtSortingFn = ( ): number => { const assetA = a.original.asset const assetB = b.original.asset - if (!a.original.debt || !b.original.debt) return 0 - const assetAPrice = (a.original.liquidity?.value ?? BN_ZERO).div( - a.original.liquidity?.amount ?? BN_ZERO, - ) - const assetBPrice = (b.original.liquidity?.value ?? BN_ZERO).div( - b.original.liquidity?.amount ?? BN_ZERO, - ) - const debtA = a.original.debt.times(assetAPrice).shiftedBy(-assetA.decimals) - const debtB = b.original.debt.times(assetBPrice).shiftedBy(-assetB.decimals) + if (!a.original.accountDebt || !b.original.accountDebt) return 0 + const debtA = a.original.accountDebt.shiftedBy(-assetA.decimals) + const debtB = b.original.accountDebt.shiftedBy(-assetB.decimals) return debtA.minus(debtB).toNumber() } @@ -38,5 +32,5 @@ export default function Debt(props: Props) { if (!asset) return null - return + return } diff --git a/src/components/borrow/Table/Columns/Liquidity.tsx b/src/components/borrow/Table/Columns/Liquidity.tsx index 78353068..c2202edc 100644 --- a/src/components/borrow/Table/Columns/Liquidity.tsx +++ b/src/components/borrow/Table/Columns/Liquidity.tsx @@ -19,8 +19,8 @@ export const liquiditySortingFn = ( ): number => { const assetA = a.original.asset const assetB = b.original.asset - const liquidityA = demagnify(a.original.liquidity?.amount ?? 0, assetA) - const liquidityB = demagnify(b.original.liquidity?.amount ?? 0, assetB) + const liquidityA = demagnify(a.original.liquidity ?? 0, assetA) + const liquidityB = demagnify(b.original.liquidity ?? 0, assetB) return liquidityA - liquidityB } @@ -35,9 +35,9 @@ export default function Liquidity(props: Props) { if (!asset) return null - if (liquidity === null) { + if (liquidity.isZero()) { return } - return + return } diff --git a/src/components/borrow/Table/useBorrowMarketAssetsTableData.ts b/src/components/borrow/Table/useBorrowMarketAssetsTableData.ts new file mode 100644 index 00000000..d5650cc2 --- /dev/null +++ b/src/components/borrow/Table/useBorrowMarketAssetsTableData.ts @@ -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]) +} diff --git a/src/components/common/AvailableLiquidityMessage.tsx b/src/components/common/AvailableLiquidityMessage.tsx index 78c891e4..2b55af87 100644 --- a/src/components/common/AvailableLiquidityMessage.tsx +++ b/src/components/common/AvailableLiquidityMessage.tsx @@ -2,28 +2,27 @@ import { FormattedNumber } from 'components/common/FormattedNumber' import Text from 'components/common/Text' interface Props { - availableLiquidity: BigNumber - asset: BorrowAsset + market: Market } export default function AvailableLiquidityMessage(props: Props) { - const { availableLiquidity, asset } = props + const { market } = props return (
Not enough Liquidty! - {`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.`}
Available Liquidity: diff --git a/src/components/common/MarketDetails.tsx b/src/components/common/MarketDetails.tsx index 269e2a70..545c3492 100644 --- a/src/components/common/MarketDetails.tsx +++ b/src/components/common/MarketDetails.tsx @@ -23,9 +23,7 @@ export default function MarketDetails({ row, type }: Props) { symbol: displayCurrencySymbol, } = useDisplayCurrencyPrice() - const { asset, ltv, marketDepositAmount, marketLiquidityAmount } = row.original - - const totalBorrowed = marketDepositAmount.minus(marketLiquidityAmount) + const { asset, ltv, cap, liquidity, deposits, debt } = row.original const details: Detail[] = useMemo(() => { const isDollar = displayCurrencySymbol === '$' @@ -33,7 +31,7 @@ export default function MarketDetails({ row, type }: Props) { function getLendingMarketDetails() { return [ { - amount: convertAmount(asset, marketDepositAmount).toNumber(), + amount: convertAmount(asset, deposits).toNumber(), options: { abbreviated: true, suffix: isDollar ? undefined : ` ${displayCurrencySymbol}`, @@ -62,9 +60,7 @@ export default function MarketDetails({ row, type }: Props) { title: 'Oracle Price', }, { - amount: totalBorrowed.isZero() - ? 0 - : totalBorrowed.dividedBy(marketDepositAmount).multipliedBy(100).toNumber(), + amount: debt.isZero() ? 0 : debt.dividedBy(deposits).multipliedBy(100).toNumber(), // TODO: Check if this number is still correct options: { minDecimals: 2, maxDecimals: 2, suffix: '%' }, title: 'Utilization Rate', }, @@ -74,7 +70,7 @@ export default function MarketDetails({ row, type }: Props) { function getBorrowMarketDetails() { return [ { - amount: convertAmount(asset, totalBorrowed).toNumber(), + amount: convertAmount(asset, debt).toNumber(), options: { abbreviated: true, suffix: isDollar ? undefined : ` ${displayCurrencySymbol}`, @@ -93,9 +89,7 @@ export default function MarketDetails({ row, type }: Props) { title: 'Oracle Price', }, { - amount: totalBorrowed.isZero() - ? 0 - : totalBorrowed.dividedBy(marketDepositAmount).multipliedBy(100).toNumber(), + amount: debt.isZero() ? 0 : debt.dividedBy(deposits).multipliedBy(100).toNumber(), // TODO: CHeck if this is still correct options: { minDecimals: 2, maxDecimals: 2, suffix: '%' }, title: 'Utilization Rate', }, @@ -105,14 +99,15 @@ export default function MarketDetails({ row, type }: Props) { if (type === 'lend') return getLendingMarketDetails() return getBorrowMarketDetails() }, [ - type, - asset, - marketDepositAmount, - ltv, - totalBorrowed, displayCurrencySymbol, + type, convertAmount, + asset, + debt, + ltv.max, + ltv.liq, getConversionRate, + deposits, ]) return ( diff --git a/src/components/common/Select/Option.tsx b/src/components/common/Select/Option.tsx index 89fe8e25..893fa043 100644 --- a/src/components/common/Select/Option.tsx +++ b/src/components/common/Select/Option.tsx @@ -7,7 +7,7 @@ import { ChevronDown, ChevronRight } from 'components/common/Icons' import Text from 'components/common/Text' import { BN_ZERO } from 'constants/math' import useAsset from 'hooks/assets/useAsset' -import useMarketAssets from 'hooks/markets/useMarketAssets' +import useMarkets from 'hooks/markets/useMarkets' import { BNCoin } from 'types/classes/BNCoin' import { byDenom } from 'utils/array' import { formatValue } from 'utils/formatters' @@ -22,7 +22,8 @@ interface Props extends SelectOption { export default function Option(props: Props) { const isCoin = !!props.denom - const { data: marketAssets } = useMarketAssets() + const markets = useMarkets() + const asset = useAsset(props.denom || '') function handleOnClick(value: string | undefined) { @@ -32,7 +33,7 @@ export default function Option(props: Props) { if (isCoin) { const balance = props.amount ?? BN_ZERO - const marketAsset = marketAssets.find(byDenom(props.denom || '')) + const marketAsset = markets.find(byDenom(props.denom || '')) if (!asset || !marketAsset) return null diff --git a/src/components/earn/lend/Lends.tsx b/src/components/earn/lend/Lends.tsx index e169f385..f3873d50 100644 --- a/src/components/earn/lend/Lends.tsx +++ b/src/components/earn/lend/Lends.tsx @@ -1,8 +1,8 @@ import AvailableLendsTable from 'components/earn/lend/Table/AvailableLendsTable' import DepositedLendsTable from 'components/earn/lend/Table/DepositedLendsTable' +import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData' import { BN_ZERO } from 'constants/math' import useLendEnabledAssets from 'hooks/assets/useLendEnabledAssets' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' export default function Lends() { const { accountLentAssets, availableAssets, allAssets } = useLendingMarketAssetsTableData() @@ -23,10 +23,11 @@ function Fallback() { const data: LendingMarketTableData[] = assets.map((asset) => ({ asset, - marketDepositCap: BN_ZERO, - borrowEnabled: false, - marketDepositAmount: BN_ZERO, - marketLiquidityAmount: BN_ZERO, + borrowEnabled: true, + depositEnabled: true, + debt: BN_ZERO, + deposits: BN_ZERO, + liquidity: BN_ZERO, cap: { max: BN_ZERO, used: BN_ZERO, diff --git a/src/hooks/useLendingMarketAssetsTableData.ts b/src/components/earn/lend/Table/useLendingMarketAssetsTableData.ts similarity index 51% rename from src/hooks/useLendingMarketAssetsTableData.ts rename to src/components/earn/lend/Table/useLendingMarketAssetsTableData.ts index 4badcd68..6caa3b90 100644 --- a/src/hooks/useLendingMarketAssetsTableData.ts +++ b/src/components/earn/lend/Table/useLendingMarketAssetsTableData.ts @@ -1,50 +1,35 @@ import { useMemo } from 'react' import { BN_ZERO } from 'constants/math' -import useAllAssets from 'hooks/assets/useAllAssets' -import useMarketDeposits from 'hooks/markets/useMarketDeposits' -import useMarketLiquidities from 'hooks/markets/useMarketLiquidities' +import useMarkets from 'hooks/markets/useMarkets' import useCurrentAccountLends from 'hooks/useCurrentAccountLends' -import useDepositEnabledMarkets from 'hooks/useDepositEnabledMarkets' import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice' import { byDenom } from 'utils/array' -import { BN } from 'utils/helpers' function useLendingMarketAssetsTableData(): { accountLentAssets: LendingMarketTableData[] availableAssets: LendingMarketTableData[] allAssets: LendingMarketTableData[] } { - const markets = useDepositEnabledMarkets() + const markets = useMarkets() const accountLentAmounts = useCurrentAccountLends() - const { data: marketLiquidities } = useMarketLiquidities() - const { data: marketDeposits } = useMarketDeposits() const { convertAmount } = useDisplayCurrencyPrice() - const assets = useAllAssets() return useMemo(() => { const accountLentAssets: LendingMarketTableData[] = [], availableAssets: LendingMarketTableData[] = [] - markets.forEach(({ denom, cap, ltv, apy, borrowEnabled }) => { - const asset = assets.find(byDenom(denom)) as Asset - const marketDepositAmount = BN(marketDeposits.find(byDenom(denom))?.amount ?? 0) - const marketLiquidityAmount = BN(marketLiquidities.find(byDenom(denom))?.amount ?? 0) - const accountLentAmount = accountLentAmounts.find(byDenom(denom))?.amount ?? BN_ZERO + markets.forEach((market) => { + const accountLentAmount = + accountLentAmounts.find(byDenom(market.asset.denom))?.amount ?? BN_ZERO const accountLentValue = accountLentAmount - ? convertAmount(asset, accountLentAmount) + ? convertAmount(market.asset, accountLentAmount) : undefined const lendingMarketAsset: LendingMarketTableData = { - asset, - marketDepositAmount, + ...market, accountLentValue, accountLentAmount, - marketLiquidityAmount, - apy, - ltv, - borrowEnabled, - cap, } if (lendingMarketAsset.accountLentAmount?.isZero()) { @@ -59,7 +44,7 @@ function useLendingMarketAssetsTableData(): { availableAssets, allAssets: [...accountLentAssets, ...availableAssets], } - }, [markets, assets, marketDeposits, marketLiquidities, accountLentAmounts, convertAmount]) + }, [markets, accountLentAmounts, convertAmount]) } export default useLendingMarketAssetsTableData diff --git a/src/components/hls/Farm/Table/Columns/APY.tsx b/src/components/hls/Farm/Table/Columns/APY.tsx index 0ccea4aa..7a98bd2e 100644 --- a/src/components/hls/Farm/Table/Columns/APY.tsx +++ b/src/components/hls/Farm/Table/Columns/APY.tsx @@ -2,7 +2,7 @@ import React from 'react' import { FormattedNumber } from 'components/common/FormattedNumber' import Loading from 'components/common/Loading' -import useMarketBorrowings from 'hooks/markets/useMarketBorrowings' +import useMarket from 'hooks/markets/useMarket' export const APY_META = { accessorKey: 'apy', header: 'APY Range' } @@ -12,10 +12,7 @@ interface Props { export default function Apy(props: Props) { const { vault } = props - const { data: marketBorrowings } = useMarketBorrowings() - - const borrowRate = marketBorrowings.find((asset) => asset.denom === vault.hls?.borrowDenom) - ?.borrowRate + const borrowRate = useMarket(vault.hls?.borrowDenom || '')?.apy.borrow if (vault.apy === null || borrowRate === null) return diff --git a/src/components/hls/Staking/Table/Columns/ActiveApy.tsx b/src/components/hls/Staking/Table/Columns/ActiveApy.tsx index 0118c1e6..bec47e52 100644 --- a/src/components/hls/Staking/Table/Columns/ActiveApy.tsx +++ b/src/components/hls/Staking/Table/Columns/ActiveApy.tsx @@ -5,7 +5,7 @@ import { FormattedNumber } from 'components/common/FormattedNumber' import Loading from 'components/common/Loading' import TitleAndSubCell from 'components/common/TitleAndSubCell' import useAllAssets from 'hooks/assets/useAllAssets' -import useBorrowAsset from 'hooks/useBorrowAsset' +import useMarket from 'hooks/markets/useMarket' import usePrices from 'hooks/usePrices' import { calculateAccountLeverage } from 'utils/accounts' import { getLeveragedApy } from 'utils/math' @@ -27,7 +27,7 @@ interface Props { export default function ActiveAPY(props: Props) { const { data: prices } = usePrices() const assets = useAllAssets() - const borrowRate = useBorrowAsset(props.account.strategy.denoms.borrow)?.borrowRate + const borrowRate = useMarket(props.account.strategy.denoms.borrow)?.apy.borrow const leverage = useMemo( () => calculateAccountLeverage(props.account, prices, assets), diff --git a/src/components/hls/Staking/Table/Columns/ApyRange.tsx b/src/components/hls/Staking/Table/Columns/ApyRange.tsx index 6bc154b8..949a33ec 100644 --- a/src/components/hls/Staking/Table/Columns/ApyRange.tsx +++ b/src/components/hls/Staking/Table/Columns/ApyRange.tsx @@ -3,7 +3,7 @@ import { Row } from '@tanstack/react-table' import { FormattedNumber } from 'components/common/FormattedNumber' import Loading from 'components/common/Loading' import TitleAndSubCell from 'components/common/TitleAndSubCell' -import useBorrowAsset from 'hooks/useBorrowAsset' +import useMarket from 'hooks/markets/useMarket' import { getLeveragedApy } from 'utils/math' export const APY_RANGE_META = { header: 'APY range', accessorKey: 'apy' } @@ -19,7 +19,7 @@ interface Props { export default function ApyRange(props: Props) { const baseApy = props.strategy.apy - const borrowRate = useBorrowAsset(props.strategy.denoms.borrow)?.borrowRate + const borrowRate = useMarket(props.strategy.denoms.borrow)?.apy.borrow if (!borrowRate || props.isLoading || !baseApy) { return diff --git a/src/components/portfolio/Account/Balances.tsx b/src/components/portfolio/Account/Balances.tsx index c39fbbb5..6ed57229 100644 --- a/src/components/portfolio/Account/Balances.tsx +++ b/src/components/portfolio/Account/Balances.tsx @@ -1,12 +1,12 @@ import React, { Suspense, useMemo } from 'react' import AccountBalancesTable from 'components/account/AccountBalancesTable' +import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' import Card from 'components/common/Card' import TableSkeleton from 'components/common/Table/TableSkeleton' import Text from 'components/common/Text' +import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData' import useAccount from 'hooks/accounts/useAccount' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' interface Props { accountId: string diff --git a/src/components/portfolio/Account/Summary.tsx b/src/components/portfolio/Account/Summary.tsx index 1728d0d2..cfc81e76 100644 --- a/src/components/portfolio/Account/Summary.tsx +++ b/src/components/portfolio/Account/Summary.tsx @@ -1,15 +1,15 @@ import { Suspense, useMemo } from 'react' +import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' import DisplayCurrency from 'components/common/DisplayCurrency' import { FormattedNumber } from 'components/common/FormattedNumber' +import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData' import Skeleton from 'components/portfolio/SummarySkeleton' import { MAX_AMOUNT_DECIMALS } from 'constants/math' import useAccount from 'hooks/accounts/useAccount' import useAllAssets from 'hooks/assets/useAllAssets' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' import useHealthComputer from 'hooks/useHealthComputer' import useHLSStakingAssets from 'hooks/useHLSStakingAssets' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' import usePrices from 'hooks/usePrices' import { getAccountSummaryStats } from 'utils/accounts' import { DEFAULT_PORTFOLIO_STATS } from 'utils/constants' diff --git a/src/components/portfolio/Card/index.tsx b/src/components/portfolio/Card/index.tsx index 600864e2..e35b9262 100644 --- a/src/components/portfolio/Card/index.tsx +++ b/src/components/portfolio/Card/index.tsx @@ -2,8 +2,10 @@ import classNames from 'classnames' import { ReactNode, useMemo } from 'react' import { NavLink, useParams, useSearchParams } from 'react-router-dom' +import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' import { FormattedNumber } from 'components/common/FormattedNumber' import Loading from 'components/common/Loading' +import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData' import Skeleton from 'components/portfolio/Card/Skeleton' import { DEFAULT_SETTINGS } from 'constants/defaultSettings' import { LocalStorageKeys } from 'constants/localStorageKeys' @@ -12,10 +14,8 @@ import useAccount from 'hooks/accounts/useAccount' import useAllAssets from 'hooks/assets/useAllAssets' import useLocalStorage from 'hooks/localStorage/useLocalStorage' import useAccountId from 'hooks/useAccountId' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' import useHealthComputer from 'hooks/useHealthComputer' import useHLSStakingAssets from 'hooks/useHLSStakingAssets' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' import usePrices from 'hooks/usePrices' import { calculateAccountApr, diff --git a/src/components/portfolio/Overview/Summary.tsx b/src/components/portfolio/Overview/Summary.tsx index c4ec66fd..25187736 100644 --- a/src/components/portfolio/Overview/Summary.tsx +++ b/src/components/portfolio/Overview/Summary.tsx @@ -1,15 +1,15 @@ import { useMemo } from 'react' import { useParams } from 'react-router-dom' +import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' import DisplayCurrency from 'components/common/DisplayCurrency' import { FormattedNumber } from 'components/common/FormattedNumber' +import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData' import SummarySkeleton from 'components/portfolio/SummarySkeleton' import { MAX_AMOUNT_DECIMALS } from 'constants/math' import useAccounts from 'hooks/accounts/useAccounts' import useAllAssets from 'hooks/assets/useAllAssets' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' import useHLSStakingAssets from 'hooks/useHLSStakingAssets' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' import usePrices from 'hooks/usePrices' import useStore from 'store' import { getAccountSummaryStats } from 'utils/accounts' diff --git a/src/components/trade/AccountDetailsCard.tsx b/src/components/trade/AccountDetailsCard.tsx index 49e7bb5e..b922bfc8 100644 --- a/src/components/trade/AccountDetailsCard.tsx +++ b/src/components/trade/AccountDetailsCard.tsx @@ -1,9 +1,9 @@ import { useMemo } from 'react' import AccountBalancesTable from 'components/account/AccountBalancesTable' +import useBorrowMarketAssetsTableData from 'components/borrow/Table/useBorrowMarketAssetsTableData' +import useLendingMarketAssetsTableData from 'components/earn/lend/Table/useLendingMarketAssetsTableData' import useCurrentAccount from 'hooks/accounts/useCurrentAccount' -import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData' -import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData' export default function AccountDetailsCard() { const account = useCurrentAccount() diff --git a/src/components/trade/TradeModule/AssetSelector/AssetList.tsx b/src/components/trade/TradeModule/AssetSelector/AssetList.tsx index 7f21e07b..522d321f 100644 --- a/src/components/trade/TradeModule/AssetSelector/AssetList.tsx +++ b/src/components/trade/TradeModule/AssetSelector/AssetList.tsx @@ -6,8 +6,7 @@ import Text from 'components/common/Text' import AssetSelectorItem from 'components/trade/TradeModule/AssetSelector/AssetSelectorItem' import useCurrentAccount from 'hooks/accounts/useCurrentAccount' import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets' -import useMarketAssets from 'hooks/markets/useMarketAssets' -import useMarketDeposits from 'hooks/markets/useMarketDeposits' +import useMarkets from 'hooks/markets/useMarkets' import usePrices from 'hooks/usePrices' import useStore from 'store' import { getMergedBalancesForAsset } from 'utils/accounts' @@ -26,8 +25,7 @@ export default function AssetList(props: Props) { const baseDenom = useStore((s) => s.chainConfig.assets[0].denom) const { assets, type, isOpen, toggleOpen, onChangeAsset } = props const account = useCurrentAccount() - const { data: marketAssets } = useMarketAssets() - const { data: marketDeposits } = useMarketDeposits() + const markets = useMarkets() const { data: prices } = usePrices() const marketEnabledAssets = useMarketEnabledAssets() const balances = useMemo(() => { @@ -36,8 +34,8 @@ export default function AssetList(props: Props) { }, [account, marketEnabledAssets]) const sortedAssets = useMemo( - () => sortAssetsOrPairs(assets, prices, marketDeposits, balances, baseDenom) as Asset[], - [assets, prices, marketDeposits, balances, baseDenom], + () => sortAssetsOrPairs(assets, prices, markets, balances, baseDenom) as Asset[], + [assets, prices, markets, balances, baseDenom], ) return ( @@ -63,9 +61,7 @@ export default function AssetList(props: Props) { balances={balances} key={`${type}-${asset.symbol}`} onSelect={props.onChangeAsset} - depositCap={ - type === 'buy' ? marketAssets?.find(byDenom(asset.denom))?.cap : undefined - } + depositCap={type === 'buy' ? markets?.find(byDenom(asset.denom))?.cap : undefined} asset={asset} /> ))} diff --git a/src/components/trade/TradeModule/AssetSelector/PairsList.tsx b/src/components/trade/TradeModule/AssetSelector/PairsList.tsx index ea738b40..b5a9399f 100644 --- a/src/components/trade/TradeModule/AssetSelector/PairsList.tsx +++ b/src/components/trade/TradeModule/AssetSelector/PairsList.tsx @@ -5,8 +5,7 @@ import AssetSelectorItem from 'components/trade/TradeModule/AssetSelector/AssetS import useCurrentAccount from 'hooks/accounts/useCurrentAccount' import useBaseAsset from 'hooks/assets/useBasetAsset' import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets' -import useMarketAssets from 'hooks/markets/useMarketAssets' -import useMarketDeposits from 'hooks/markets/useMarketDeposits' +import useMarkets from 'hooks/markets/useMarkets' import usePrices from 'hooks/usePrices' import { getMergedBalancesForAsset } from 'utils/accounts' import { byDenom } from 'utils/array' @@ -22,8 +21,7 @@ interface Props { export default function PairsList(props: Props) { const account = useCurrentAccount() - const { data: marketAssets } = useMarketAssets() - const { data: marketDeposits } = useMarketDeposits() + const markets = useMarkets() const { data: prices } = usePrices() const baseDenom = useBaseAsset().denom const marketEnabledAssets = useMarketEnabledAssets() @@ -44,8 +42,8 @@ export default function PairsList(props: Props) { }, [props.stables, props.assets]) const sortedPairs = useMemo( - () => sortAssetsOrPairs(pairs, prices, marketDeposits, balances, baseDenom) as AssetPair[], - [pairs, prices, marketDeposits, balances, baseDenom], + () => sortAssetsOrPairs(pairs, prices, markets, balances, baseDenom) as AssetPair[], + [pairs, prices, markets, balances, baseDenom], ) return ( @@ -62,7 +60,7 @@ export default function PairsList(props: Props) { balances={balances} key={`${assetPair.buy.symbol}-${assetPair.sell.symbol}`} onSelect={props.onChangeAssetPair} - depositCap={marketAssets?.find(byDenom(assetPair.buy.denom))?.cap} + depositCap={markets?.find(byDenom(assetPair.buy.denom))?.cap} asset={assetPair.buy} sellAsset={assetPair.sell} /> diff --git a/src/components/trade/TradeModule/SwapForm/index.tsx b/src/components/trade/TradeModule/SwapForm/index.tsx index 5e97ac61..bf28bd54 100644 --- a/src/components/trade/TradeModule/SwapForm/index.tsx +++ b/src/components/trade/TradeModule/SwapForm/index.tsx @@ -22,8 +22,7 @@ import { BN_ZERO } from 'constants/math' import useCurrentAccount from 'hooks/accounts/useCurrentAccount' import useMarketEnabledAssets from 'hooks/assets/useMarketEnabledAssets' import useLocalStorage from 'hooks/localStorage/useLocalStorage' -import useMarketAssets from 'hooks/markets/useMarketAssets' -import useMarketBorrowings from 'hooks/markets/useMarketBorrowings' +import useMarkets from 'hooks/markets/useMarkets' import useAutoLend from 'hooks/useAutoLend' import useChainConfig from 'hooks/useChainConfig' import useHealthComputer from 'hooks/useHealthComputer' @@ -53,8 +52,7 @@ export default function SwapForm(props: Props) { const [slippage] = useLocalStorage(LocalStorageKeys.SLIPPAGE, DEFAULT_SETTINGS.slippage) const { computeMaxSwapAmount } = useHealthComputer(account) const [tradeDirection, setTradeDirection] = useState('long') - const { data: borrowAssets } = useMarketBorrowings() - const { data: marketAssets } = useMarketAssets() + const markets = useMarkets() const [inputAsset, outputAsset] = useMemo(() => { if (isAdvanced) return [sellAsset, buyAsset] @@ -65,7 +63,7 @@ export default function SwapForm(props: Props) { inputAsset.denom, outputAsset.denom, ) - const isBorrowEnabled = !!marketAssets.find(byDenom(inputAsset.denom))?.borrowEnabled + const isBorrowEnabled = !!markets.find(byDenom(inputAsset.denom))?.borrowEnabled const isRepayable = !!account?.debts.find(byDenom(outputAsset.denom)) const [isMarginChecked, setMarginChecked] = useToggle(isBorrowEnabled ? useMargin : false) const [isAutoRepayChecked, setAutoRepayChecked] = useToggle( @@ -87,7 +85,7 @@ export default function SwapForm(props: Props) { const assets = useMarketEnabledAssets() const depositCapReachedCoins: BNCoin[] = useMemo(() => { - const outputMarketAsset = marketAssets.find(byDenom(outputAsset.denom)) + const outputMarketAsset = markets.find(byDenom(outputAsset.denom)) if (!outputMarketAsset) return [] @@ -97,7 +95,7 @@ export default function SwapForm(props: Props) { } return [] - }, [marketAssets, outputAsset.denom, outputAssetAmount]) + }, [markets, outputAsset.denom, outputAssetAmount]) const onChangeInputAmount = useCallback( (amount: BigNumber) => { @@ -305,9 +303,9 @@ export default function SwapForm(props: Props) { modal, ]) - const borrowAsset = useMemo( - () => borrowAssets.find(byDenom(inputAsset.denom)), - [borrowAssets, inputAsset.denom], + const borrowMarket = useMemo( + () => markets.find((market) => market.asset.denom === inputAsset.denom), + [markets, inputAsset.denom], ) useEffect(() => { @@ -324,8 +322,8 @@ export default function SwapForm(props: Props) { ) const availableLiquidity = useMemo( - () => borrowAsset?.liquidity?.amount ?? BN_ZERO, - [borrowAsset?.liquidity?.amount], + () => borrowMarket?.liquidity ?? BN_ZERO, + [borrowMarket?.liquidity], ) const isSwapDisabled = useMemo( @@ -349,7 +347,7 @@ export default function SwapForm(props: Props) { @@ -411,11 +409,8 @@ export default function SwapForm(props: Props) { className='p-4 bg-white/5' /> - {borrowAsset && borrowAmount.isGreaterThanOrEqualTo(availableLiquidity) && ( - + {borrowMarket && borrowAmount.isGreaterThanOrEqualTo(availableLiquidity) && ( + )} {isAdvanced ? ( getAccountIds(chainConfig, address).then((accountIdsAndKinds) => { if (noHls) { diff --git a/src/hooks/accounts/useAccounts.tsx b/src/hooks/accounts/useAccounts.tsx index 21027704..c1d6cc48 100644 --- a/src/hooks/accounts/useAccounts.tsx +++ b/src/hooks/accounts/useAccounts.tsx @@ -8,7 +8,7 @@ export default function useAccounts(kind: AccountKind, address?: string, suspens const chainConfig = useChainConfig() return useSWR( - `chains/${chainConfig.id}/accounts/${kind}`, + address && `chains/${chainConfig.id}/accounts/${kind}`, () => getAccounts(kind, chainConfig, address), { suspense: suspense, diff --git a/src/hooks/markets/useMarket.ts b/src/hooks/markets/useMarket.ts new file mode 100644 index 00000000..6b2f4c50 --- /dev/null +++ b/src/hooks/markets/useMarket.ts @@ -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]) +} diff --git a/src/hooks/markets/useMarketAssets.ts b/src/hooks/markets/useMarketAssets.ts deleted file mode 100644 index ec4d24f8..00000000 --- a/src/hooks/markets/useMarketAssets.ts +++ /dev/null @@ -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, - }) -} diff --git a/src/hooks/markets/useMarketBorrowings.tsx b/src/hooks/markets/useMarketBorrowings.tsx deleted file mode 100644 index 40f33a69..00000000 --- a/src/hooks/markets/useMarketBorrowings.tsx +++ /dev/null @@ -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, - }, - ) -} diff --git a/src/hooks/markets/useMarketDepositCaps.ts b/src/hooks/markets/useMarketDepositCaps.ts new file mode 100644 index 00000000..79790ced --- /dev/null +++ b/src/hooks/markets/useMarketDepositCaps.ts @@ -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) +} diff --git a/src/hooks/markets/useMarketDeposits.ts b/src/hooks/markets/useMarketDeposits.ts deleted file mode 100644 index 16f62730..00000000 --- a/src/hooks/markets/useMarketDeposits.ts +++ /dev/null @@ -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, - }) -} diff --git a/src/hooks/markets/useMarketLiquidities.ts b/src/hooks/markets/useMarketLiquidities.ts deleted file mode 100644 index db6a4f50..00000000 --- a/src/hooks/markets/useMarketLiquidities.ts +++ /dev/null @@ -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, - }, - ) -} diff --git a/src/hooks/markets/useMarkets.ts b/src/hooks/markets/useMarkets.ts new file mode 100644 index 00000000..6ed74525 --- /dev/null +++ b/src/hooks/markets/useMarkets.ts @@ -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, + assetParams.find(byDenom(asset.denom)) as AssetParams, + marketDepositCaps!.find(byDenom(asset.denom)) as TotalDepositResponse, + ), + ) + }, + { + fallbackData: [], + }, + ).data +} diff --git a/src/hooks/markets/useMarketsInfo.ts b/src/hooks/markets/useMarketsInfo.ts new file mode 100644 index 00000000..b83e836e --- /dev/null +++ b/src/hooks/markets/useMarketsInfo.ts @@ -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]), + })) +} diff --git a/src/hooks/useAssetIncentiveApy.ts b/src/hooks/useAssetIncentiveApy.ts index 54329fa1..6d5307a8 100644 --- a/src/hooks/useAssetIncentiveApy.ts +++ b/src/hooks/useAssetIncentiveApy.ts @@ -1,15 +1,45 @@ import useSWR from 'swr' -import calculateAssetIncentivesApy from 'api/incentives/calculateAssetIncentivesApy' +import getTotalActiveEmissionValue from 'api/incentives/getTotalActiveEmissionValue' +import useMarket from 'hooks/markets/useMarket' import useChainConfig from 'hooks/useChainConfig' +import usePrice from 'hooks/usePrice' +import { SECONDS_IN_A_YEAR } from 'utils/constants' +import { BN } from 'utils/helpers' export default function useAssetIncentivesApy(denom: string) { const chainConfig = useChainConfig() + const market = useMarket(denom) + const price = usePrice(denom) + return useSWR( - `chains/${chainConfig.id}/assets/${denom}/incentives`, - () => calculateAssetIncentivesApy(chainConfig, denom), + market && `chains/${chainConfig.id}/assets/${denom}/incentives`, + () => calculateAssetIncentivesApy(chainConfig, market!, price), { revalidateOnFocus: false, }, ) } + +async function calculateAssetIncentivesApy( + chainConfig: ChainConfig, + market: Market, + price: BigNumber, +) { + const totalActiveEmissionValue = await getTotalActiveEmissionValue( + chainConfig, + market.asset.denom, + ) + + if (!totalActiveEmissionValue) return null + + const marketLiquidityValue = BN(market.deposits) + .shiftedBy(-market.asset.decimals) + .multipliedBy(price) + + const marketReturns = BN(market.apy.deposit).multipliedBy(marketLiquidityValue) + const annualEmission = totalActiveEmissionValue.multipliedBy(SECONDS_IN_A_YEAR) + + const totalAnnualReturnsValue = annualEmission.plus(marketReturns) + return totalAnnualReturnsValue.dividedBy(marketLiquidityValue).multipliedBy(100) +} diff --git a/src/hooks/useBorrowAsset.ts b/src/hooks/useBorrowAsset.ts deleted file mode 100644 index 99807ae8..00000000 --- a/src/hooks/useBorrowAsset.ts +++ /dev/null @@ -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)) -} diff --git a/src/hooks/useBorrowEnabledMarkets.ts b/src/hooks/useBorrowEnabledMarkets.ts deleted file mode 100644 index 450fafe6..00000000 --- a/src/hooks/useBorrowEnabledMarkets.ts +++ /dev/null @@ -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]) -} diff --git a/src/hooks/useBorrowMarketAssetsTableData.ts b/src/hooks/useBorrowMarketAssetsTableData.ts deleted file mode 100644 index b22b4e36..00000000 --- a/src/hooks/useBorrowMarketAssetsTableData.ts +++ /dev/null @@ -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]) -} diff --git a/src/hooks/useClients.ts b/src/hooks/useClients.ts index 7f2e60e9..e87ca0c2 100644 --- a/src/hooks/useClients.ts +++ b/src/hooks/useClients.ts @@ -34,6 +34,9 @@ export default function useClients() { } as ContractClients }, { + revalidateOnFocus: false, + revalidateOnReconnect: false, + revalidateIfStale: false, keepPreviousData: false, }, ) diff --git a/src/hooks/useDepositEnabledMarkets.ts b/src/hooks/useDepositEnabledMarkets.ts deleted file mode 100644 index 5313d41b..00000000 --- a/src/hooks/useDepositEnabledMarkets.ts +++ /dev/null @@ -1,6 +0,0 @@ -import useMarketAssets from 'hooks/markets/useMarketAssets' - -export default function useDepositEnabledMarkets() { - const { data: markets } = useMarketAssets() - return markets.filter((market) => market.depositEnabled) -} diff --git a/src/hooks/useHLSStakingAssets.ts b/src/hooks/useHLSStakingAssets.ts index ca57f47a..6493b0de 100644 --- a/src/hooks/useHLSStakingAssets.ts +++ b/src/hooks/useHLSStakingAssets.ts @@ -5,8 +5,12 @@ import useChainConfig from 'hooks/useChainConfig' export default function useHLSStakingAssets() { const chainConfig = useChainConfig() - return useSWR('hls-staking', () => getHLSStakingAssets(chainConfig), { - fallbackData: [], - revalidateOnFocus: false, - }) + return useSWR( + `chains/${chainConfig.id}/assets/hls/staking`, + () => getHLSStakingAssets(chainConfig), + { + fallbackData: [], + revalidateOnFocus: false, + }, + ) } diff --git a/src/hooks/useVault.tsx b/src/hooks/useVault.tsx index 528b63b5..9ff666e0 100644 --- a/src/hooks/useVault.tsx +++ b/src/hooks/useVault.tsx @@ -1,9 +1,9 @@ +import { useMemo } from 'react' + import useVaults from 'hooks/useVaults' export default function useVault(address: string) { const { data: vaults } = useVaults(false) - if (!vaults?.length) return null - - return vaults.find((v) => v.address === address) ?? null + return useMemo(() => vaults?.find((v) => v.address === address) ?? null, [vaults, address]) } diff --git a/src/hooks/useVaults.tsx b/src/hooks/useVaults.tsx index de85fc7b..31ed110b 100644 --- a/src/hooks/useVaults.tsx +++ b/src/hooks/useVaults.tsx @@ -6,8 +6,12 @@ import useChainConfig from 'hooks/useChainConfig' export default function useVaults(suspense: boolean = true, address?: string) { const chainConfig = useChainConfig() - return useSWR(`chains/${chainConfig.id}/vaults/${address}`, () => getVaults(chainConfig), { - suspense, - revalidateOnFocus: false, - }) + return useSWR( + address && `chains/${chainConfig.id}/vaults/${address}`, + () => getVaults(chainConfig), + { + suspense, + revalidateOnFocus: false, + }, + ) } diff --git a/src/hooks/useWalletBalances.tsx b/src/hooks/useWalletBalances.tsx index 952edc74..fcba55ec 100644 --- a/src/hooks/useWalletBalances.tsx +++ b/src/hooks/useWalletBalances.tsx @@ -7,7 +7,7 @@ export default function useWalletBalances(address?: string) { const chainConfig = useChainConfig() return useSWR( - `chains/${chainConfig.id}/wallets/${address}/balances`, + address && `chains/${chainConfig.id}/wallets/${address}/balances`, () => getWalletBalances(chainConfig, address || ''), { isPaused: () => !address, diff --git a/src/pages/_layout.tsx b/src/pages/_layout.tsx index 82f212aa..f4490983 100644 --- a/src/pages/_layout.tsx +++ b/src/pages/_layout.tsx @@ -2,19 +2,21 @@ import classNames from 'classnames' import { Suspense } from 'react' import { isMobile } from 'react-device-detect' import { useLocation } from 'react-router-dom' +import { SWRConfig } from 'swr' import AccountDetails from 'components/account/AccountDetails' import Background from 'components/common/Background' import Footer from 'components/common/Footer' -import DesktopHeader from 'components/header/DesktopHeader' -import ModalsContainer from 'components/Modals/ModalsContainer' import PageMetadata from 'components/common/PageMetadata' import Toaster from 'components/common/Toaster' +import DesktopHeader from 'components/header/DesktopHeader' +import ModalsContainer from 'components/Modals/ModalsContainer' import { DEFAULT_SETTINGS } from 'constants/defaultSettings' import { LocalStorageKeys } from 'constants/localStorageKeys' import useLocalStorage from 'hooks/localStorage/useLocalStorage' import useAccountId from 'hooks/useAccountId' import useStore from 'store' +import { debugSWR } from 'utils/middleware' interface Props { focusComponent: FocusComponent | null @@ -62,36 +64,38 @@ export default function Layout({ children }: { children: React.ReactNode }) { return ( <> - - - -
- - - {children} - - - -
-