diff --git a/src/components/incentives/incentives.helper.ts b/src/components/incentives/incentives.helper.ts new file mode 100644 index 0000000000..4dbaaab5aa --- /dev/null +++ b/src/components/incentives/incentives.helper.ts @@ -0,0 +1,55 @@ +import type { AaveBorrowIncentive, AaveSupplyIncentive, ReserveIncentive } from '@aave/graphql'; +import type { ReserveIncentiveResponse } from '@aave/math-utils/dist/esm/formatters/incentive/calculate-reserve-incentives'; + +//Typescript GUARDS +const isAaveSupplyIncentive = (incentive: ReserveIncentive): incentive is AaveSupplyIncentive => { + return incentive.__typename === 'AaveSupplyIncentive'; +}; + +const isAaveBorrowIncentive = (incentive: ReserveIncentive): incentive is AaveBorrowIncentive => { + return incentive.__typename === 'AaveBorrowIncentive'; +}; + +export const isAaveProtocolIncentive = (incentive: ReserveIncentive): boolean => { + return isAaveSupplyIncentive(incentive) || isAaveBorrowIncentive(incentive); +}; + +export const getIncentiveAPR = (incentive: ReserveIncentive): string => { + // For AaveSupplyIncentive + if (isAaveSupplyIncentive(incentive) && incentive.extraSupplyApr?.value) { + return incentive.extraSupplyApr.value.toString(); + } + + // For AaveBorrowIncentive + if (isAaveBorrowIncentive(incentive) && incentive.borrowAprDiscount?.value) { + return incentive.borrowAprDiscount.value.toString(); + } + + // Fallback for previous structure) + if ('incentiveAPR' in incentive) { + return String(incentive.incentiveAPR); + } + + return '0'; +}; + +// Mapping sdk structure to legacy structure used in incentives card logic +export const mapAaveProtocolIncentives = ( + incentives: ReserveIncentive[] | undefined, + direction: 'supply' | 'borrow' +): ReserveIncentiveResponse[] => { + if (!incentives || incentives.length === 0) { + return []; + } + + const typedIncentives = + direction === 'supply' + ? incentives.filter(isAaveSupplyIncentive) + : incentives.filter(isAaveBorrowIncentive); + + return typedIncentives.map((incentive) => ({ + incentiveAPR: getIncentiveAPR(incentive), + rewardTokenAddress: incentive.rewardTokenAddress, + rewardTokenSymbol: incentive.rewardTokenSymbol, + })); +}; diff --git a/src/components/lists/ListMobileItem.tsx b/src/components/lists/ListMobileItem.tsx index 045e2f565c..c16f6102b8 100644 --- a/src/components/lists/ListMobileItem.tsx +++ b/src/components/lists/ListMobileItem.tsx @@ -20,6 +20,7 @@ interface ListMobileItemProps { showBorrowCapTooltips?: boolean; showDebtCeilingTooltips?: boolean; isIsolated: boolean; + onIconError?: () => void; } export const ListMobileItem = ({ @@ -35,6 +36,7 @@ export const ListMobileItem = ({ showBorrowCapTooltips = false, showDebtCeilingTooltips = false, isIsolated, + onIconError, }: ListMobileItemProps) => { const { supplyCap, borrowCap, debtCeiling } = useAssetCaps(); return ( @@ -59,7 +61,7 @@ export const ListMobileItem = ({ href={ROUTES.reserveOverview(underlyingAsset, currentMarket)} sx={{ display: 'inline-flex', alignItems: 'center' }} > - + {name} diff --git a/src/hooks/app-data-provider/useAppDataProvider.tsx b/src/hooks/app-data-provider/useAppDataProvider.tsx index 0c930901ab..4591e2c312 100644 --- a/src/hooks/app-data-provider/useAppDataProvider.tsx +++ b/src/hooks/app-data-provider/useAppDataProvider.tsx @@ -1,4 +1,6 @@ +import type { EmodeMarketCategory, Market, MarketUserState, Reserve } from '@aave/graphql'; import { UserReserveData } from '@aave/math-utils'; +import { client } from 'pages/_app.page'; import React, { PropsWithChildren, useContext } from 'react'; import { EmodeCategory } from 'src/helpers/types'; import { useWeb3Context } from 'src/libs/hooks/useWeb3Context'; @@ -16,6 +18,7 @@ import { import { usePoolReservesHumanized } from '../pool/usePoolReserves'; import { useUserPoolReservesHumanized } from '../pool/useUserPoolReserves'; import { FormattedUserReserves } from '../pool/useUserSummaryAndIncentives'; +import { useMarketsData } from './useMarketsData'; /** * removes the marketPrefix from a symbol @@ -40,9 +43,17 @@ export type ComputedUserReserveData = FormattedUserReserves; * @deprecated Use ExtendedFormattedUser type from useExtendedUserSummaryAndIncentives hook */ export type ExtendedFormattedUser = _ExtendedFormattedUser; - +export type ReserveWithId = Reserve & { id: string }; export interface AppDataContextType { loading: boolean; + /** SDK market snapshot */ + market?: Market; + totalBorrows?: number; + supplyReserves: ReserveWithId[]; + borrowReserves: ReserveWithId[]; + eModeCategories: EmodeMarketCategory[]; + userState?: MarketUserState; + /** Legacy fields (deprecated) kept temporarily for incremental migration */ reserves: ComputedReserveData[]; eModes: Record; user?: ExtendedFormattedUser; @@ -62,6 +73,34 @@ export const AppDataProvider: React.FC = ({ children }) => { const currentMarketData = useRootStore((state) => state.currentMarketData); + const { data, isPending } = useMarketsData({ + client, + marketData: currentMarketData, + account: currentAccount, + }); + + const marketAddress = currentMarketData.addresses.LENDING_POOL.toLowerCase(); + + const sdkMarket = data?.find((item) => item.address.toLowerCase() === marketAddress); + + const totalBorrows = sdkMarket?.borrowReserves.reduce((acc, reserve) => { + const value = reserve.borrowInfo?.total?.usd ?? 0; + return acc + Number(value); + }, 0); + + const supplyReserves = (sdkMarket?.supplyReserves ?? []).map((reserve) => ({ + ...reserve, + id: `${sdkMarket?.address}-${reserve.underlyingToken.address}`, + })); + + const borrowReserves = (sdkMarket?.borrowReserves ?? []).map((reserve) => ({ + ...reserve, + id: `${sdkMarket?.address}-${reserve.underlyingToken.address}`, + })); + + const eModeCategories = sdkMarket?.eModeCategories ?? []; + const marketUserState = sdkMarket?.userState ?? undefined; + const { data: reservesData, isPending: reservesDataLoading } = usePoolReservesHumanized(currentMarketData); const { data: formattedPoolReserves, isPending: formattedPoolReservesLoading } = @@ -81,10 +120,19 @@ export const AppDataProvider: React.FC = ({ children }) => { const isReservesLoading = reservesDataLoading || formattedPoolReservesLoading; const isUserDataLoading = userReservesDataLoading || userSummaryLoading; + const loading = isPending || isReservesLoading || (!!currentAccount && isUserDataLoading); + return ( { + const userAddress = account ? evmAddress(account) : undefined; + const marketKey = [ + ...queryKeysFactory.market(marketData), + ...queryKeysFactory.user(userAddress ?? 'anonymous'), + ]; + + return useQuery({ + queryKey: marketKey, + enabled: !!client, + queryFn: async () => { + const response = await markets(client, { + chainIds: [chainId(marketData.chainId)], + user: userAddress, + suppliesOrderBy: { tokenName: OrderDirection.Asc }, + borrowsOrderBy: { tokenName: OrderDirection.Asc }, + }); + + if (response.isErr()) { + throw response.error; + } + + return response.value; + }, + }); +}; diff --git a/src/hooks/useMerklIncentives.ts b/src/hooks/useMerklIncentives.ts index 40537d6706..8ce74dcc4d 100644 --- a/src/hooks/useMerklIncentives.ts +++ b/src/hooks/useMerklIncentives.ts @@ -1,6 +1,5 @@ import { ProtocolAction } from '@aave/contract-helpers'; import { ReserveIncentiveResponse } from '@aave/math-utils/dist/esm/formatters/incentive/calculate-reserve-incentives'; -import { AaveV3Plasma } from '@bgd-labs/aave-address-book'; import { useQuery } from '@tanstack/react-query'; import { useRootStore } from 'src/store/root'; import { convertAprToApy } from 'src/utils/utils'; @@ -100,28 +99,6 @@ type WhitelistApiResponse = { additionalIncentiveInfo: Record; }; -const hardcodedIncentives: Record = { - [AaveV3Plasma.ASSETS.USDe.A_TOKEN]: { - incentiveAPR: '0.12', - rewardTokenAddress: AaveV3Plasma.ASSETS.USDe.A_TOKEN, - rewardTokenSymbol: 'aPlaUSDe', - customMessage: - 'You must supply USDe and hold an equal or greater amount of sUSDe (by USD value) to receive the incentives. To be eligible, your assets supplied must be at least 2x your account equity, and you must not be borrowing any USDe. The rate provided to eligible users will change week by week, but will be roughly in line with the sUSDe rate for the forseeable future.', - breakdown: { - protocolAPY: 0, - protocolIncentivesAPR: 0, - merklIncentivesAPR: 0, - totalAPY: 0, - isBorrow: false, - breakdown: { - protocol: 0, - protocolIncentives: 0, - merklIncentives: 0, - }, - }, - }, -}; - const MERKL_ENDPOINT = 'https://api.merkl.xyz/v4/opportunities?mainProtocolId=aave'; // Merkl API const WHITELIST_ENDPOINT = 'https://apps.aavechan.com/api/aave/merkl/whitelist-token-list'; // Endpoint to fetch whitelisted tokens const checkOpportunityAction = ( @@ -176,24 +153,6 @@ export const useMerklIncentives = ({ queryKey: ['merklIncentives', market], staleTime: 1000 * 60 * 5, select: (merklOpportunities) => { - const hardcodedIncentive = rewardedAsset ? hardcodedIncentives[rewardedAsset] : undefined; - - if (hardcodedIncentive) { - const protocolIncentivesAPR = protocolIncentives.reduce((sum, inc) => { - return sum + (inc.incentiveAPR === 'Infinity' ? 0 : +inc.incentiveAPR); - }, 0); - const merklIncentivesAPY = convertAprToApy(0.06); - return { - ...hardcodedIncentive, - breakdown: { - protocolAPY, - protocolIncentivesAPR, - merklIncentivesAPR: merklIncentivesAPY, - totalAPY: protocolAPY + protocolIncentivesAPR + merklIncentivesAPY, - } as MerklIncentivesBreakdown, - } as ExtendedReserveIncentiveResponse; - } - const opportunities = merklOpportunities.filter( (opportunitiy) => rewardedAsset && diff --git a/src/modules/dashboard/lists/ListMobileItemWrapper.tsx b/src/modules/dashboard/lists/ListMobileItemWrapper.tsx index 11df134304..3b138559fb 100644 --- a/src/modules/dashboard/lists/ListMobileItemWrapper.tsx +++ b/src/modules/dashboard/lists/ListMobileItemWrapper.tsx @@ -32,6 +32,7 @@ interface ListMobileItemWrapperProps { showDebtCeilingTooltips?: boolean; isIsolated?: boolean; showExternalIncentivesTooltips?: ExternalIncentivesTooltipsConfig; + onIconError?: () => void; } export const ListMobileItemWrapper = ({ @@ -54,6 +55,7 @@ export const ListMobileItemWrapper = ({ spkAirdrop: false, kernelPoints: false, }, + onIconError, }: ListMobileItemWrapperProps) => { const WarningComponent: React.FC = () => { const showFrozenTooltip = frozen && symbol !== 'renFIL'; @@ -94,6 +96,7 @@ export const ListMobileItemWrapper = ({ showSupplyCapTooltips={showSupplyCapTooltips} showBorrowCapTooltips={showBorrowCapTooltips} showDebtCeilingTooltips={showDebtCeilingTooltips} + onIconError={onIconError} > {children} diff --git a/src/modules/markets/MarketAssetsList.tsx b/src/modules/markets/MarketAssetsList.tsx index 3b3e8ac07b..7c88146a0b 100644 --- a/src/modules/markets/MarketAssetsList.tsx +++ b/src/modules/markets/MarketAssetsList.tsx @@ -1,12 +1,13 @@ import { Trans } from '@lingui/macro'; import { useMediaQuery } from '@mui/material'; import { useState } from 'react'; +import { mapAaveProtocolIncentives } from 'src/components/incentives/incentives.helper'; import { VariableAPYTooltip } from 'src/components/infoTooltips/VariableAPYTooltip'; import { ListColumn } from 'src/components/lists/ListColumn'; import { ListHeaderTitle } from 'src/components/lists/ListHeaderTitle'; import { ListHeaderWrapper } from 'src/components/lists/ListHeaderWrapper'; -import { ComputedReserveData } from 'src/hooks/app-data-provider/useAppDataProvider'; +import { ReserveWithId } from '../../hooks/app-data-provider/useAppDataProvider'; import { MarketAssetsListItem } from './MarketAssetsListItem'; import { MarketAssetsListItemLoader } from './MarketAssetsListItemLoader'; import { MarketAssetsListMobileItem } from './MarketAssetsListMobileItem'; @@ -15,19 +16,19 @@ import { MarketAssetsListMobileItemLoader } from './MarketAssetsListMobileItemLo const listHeaders = [ { title: Asset, - sortKey: 'symbol', + sortKey: 'underlyingToken.symbol', }, { title: Total supplied, - sortKey: 'totalLiquidityUSD', + sortKey: 'size.usd', }, { title: Supply APY, - sortKey: 'supplyAPY', + sortKey: 'supplyInfo.apy.value', }, { title: Total borrowed, - sortKey: 'totalDebtUSD', + sortKey: 'borrowInfo.total.usd', }, { title: ( @@ -37,37 +38,71 @@ const listHeaders = [ variant="subheader2" /> ), - sortKey: 'variableBorrowAPY', + sortKey: 'borrowInfo.apy.value', }, ]; type MarketAssetsListProps = { - reserves: ComputedReserveData[]; + reserves: ReserveWithId[]; loading: boolean; }; +export type ReserveWithProtocolIncentives = ReserveWithId & { + supplyProtocolIncentives: ReturnType; + borrowProtocolIncentives: ReturnType; +}; export default function MarketAssetsList({ reserves, loading }: MarketAssetsListProps) { const isTableChangedToCards = useMediaQuery('(max-width:1125px)'); const [sortName, setSortName] = useState(''); const [sortDesc, setSortDesc] = useState(false); - if (sortDesc) { - if (sortName === 'symbol') { - reserves.sort((a, b) => (a.symbol.toUpperCase() < b.symbol.toUpperCase() ? -1 : 1)); - } else { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - reserves.sort((a, b) => a[sortName] - b[sortName]); - } - } else { - if (sortName === 'symbol') { - reserves.sort((a, b) => (b.symbol.toUpperCase() < a.symbol.toUpperCase() ? -1 : 1)); - } else { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - reserves.sort((a, b) => b[sortName] - a[sortName]); + const sortedReserves = [...reserves].sort((a, b) => { + if (!sortName) return 0; + + let aValue: number | string; + let bValue: number | string; + + switch (sortName) { + case 'underlyingToken.symbol': + aValue = a.underlyingToken.symbol.toUpperCase(); + bValue = b.underlyingToken.symbol.toUpperCase(); + if (sortDesc) { + return aValue < bValue ? -1 : 1; + } + return bValue < aValue ? -1 : 1; + + case 'size.usd': + aValue = Number(a.size.usd) || 0; + bValue = Number(b.size.usd) || 0; + break; + + case 'supplyInfo.apy.value': + aValue = Number(a.supplyInfo.apy.value) || 0; + bValue = Number(b.supplyInfo.apy.value) || 0; + break; + + case 'borrowInfo.total.usd': + aValue = Number(a.borrowInfo?.total.usd) || 0; + bValue = Number(b.borrowInfo?.total.usd) || 0; + break; + + case 'borrowInfo.apy.value': + aValue = Number(a.borrowInfo?.apy.value) || 0; + bValue = Number(b.borrowInfo?.apy.value) || 0; + break; + + default: + return 0; } - } + return sortDesc + ? (aValue as number) - (bValue as number) + : (bValue as number) - (aValue as number); + }); + const reservesWithIncentives: ReserveWithProtocolIncentives[] = sortedReserves.map((reserve) => ({ + ...reserve, + supplyProtocolIncentives: mapAaveProtocolIncentives(reserve.incentives, 'supply'), + borrowProtocolIncentives: mapAaveProtocolIncentives(reserve.incentives, 'borrow'), + })); // Show loading state when loading if (loading) { return isTableChangedToCards ? ( @@ -95,8 +130,8 @@ export default function MarketAssetsList({ reserves, loading }: MarketAssetsList {listHeaders.map((col) => ( )} - {reserves.map((reserve) => + {reservesWithIncentives.map((reserve) => isTableChangedToCards ? ( ) : ( diff --git a/src/modules/markets/MarketAssetsListContainer.tsx b/src/modules/markets/MarketAssetsListContainer.tsx index 9b158c3b21..75ae10e00a 100644 --- a/src/modules/markets/MarketAssetsListContainer.tsx +++ b/src/modules/markets/MarketAssetsListContainer.tsx @@ -1,4 +1,3 @@ -import { API_ETH_MOCK_ADDRESS } from '@aave/contract-helpers'; import { Trans } from '@lingui/macro'; import { Box, Switch, Typography, useMediaQuery, useTheme } from '@mui/material'; import { useState } from 'react'; @@ -13,7 +12,6 @@ import { useAppDataContext } from 'src/hooks/app-data-provider/useAppDataProvide import { useCoingeckoCategories } from 'src/hooks/useCoinGeckoCategories'; import MarketAssetsList from 'src/modules/markets/MarketAssetsList'; import { useRootStore } from 'src/store/root'; -import { fetchIconSymbolAndName } from 'src/ui-config/reservePatches'; import { GHO_MINTING_MARKETS, GHO_SYMBOL } from 'src/utils/ghoUtilities'; import { useShallow } from 'zustand/shallow'; @@ -42,7 +40,8 @@ function shouldDisplayGhoBanner(marketTitle: string, searchTerm: string): boolea export const MarketAssetsListContainer = () => { const { data, isLoading, error } = useCoingeckoCategories(); - const { reserves, loading } = useAppDataContext(); + const { supplyReserves, loading } = useAppDataContext(); + const [trackEvent, currentMarket, currentMarketData, currentNetworkConfig] = useRootStore( useShallow((store) => [ store.trackEvent, @@ -60,19 +59,19 @@ export const MarketAssetsListContainer = () => { const displayGhoBanner = shouldDisplayGhoBanner(currentMarket, searchTerm); - const filteredData = reserves + const filteredData = supplyReserves // Filter out any non-active reserves - .filter((res) => res.isActive) + .filter((res) => !res.isPaused) // Filter out any hidden assets - .filter((res) => !isAssetHidden(currentMarketData.market, res.underlyingAsset)) + .filter((res) => !isAssetHidden(currentMarketData.market, res.underlyingToken.address)) // filter out any that don't meet search term criteria .filter((res) => { if (!searchTerm) return true; const term = searchTerm.toLowerCase().trim(); return ( - res.symbol.toLowerCase().includes(term) || - res.name.toLowerCase().includes(term) || - res.underlyingAsset.toLowerCase().includes(term) + res.underlyingToken.symbol.toLowerCase().includes(term) || + res.underlyingToken.name.toLowerCase().includes(term) || + res.underlyingToken.address.toLowerCase().includes(term) ); }) // Filter by category @@ -81,27 +80,39 @@ export const MarketAssetsListContainer = () => { selectedCategories.length === 0 || selectedCategories.some((category) => isAssetInCategoryDynamic( - res.symbol, + res.underlyingToken.symbol, category, data?.stablecoinSymbols, data?.ethCorrelatedSymbols ) ) ) + // Add initial sorting by total supplied in USD descending + .sort((a, b) => { + const aValue = Number(a.size.usd) || 0; + const bValue = Number(b.size.usd) || 0; + return bValue - aValue; + }) // Transform the object for list to consume it .map((reserve) => ({ ...reserve, - ...(reserve.isWrappedBaseAsset - ? fetchIconSymbolAndName({ - symbol: currentNetworkConfig.baseAssetSymbol, - underlyingAsset: API_ETH_MOCK_ADDRESS.toLowerCase(), - }) + ...(reserve.acceptsNative + ? { + underlyingToken: { + ...reserve.underlyingToken, + name: currentNetworkConfig.baseAssetSymbol, // e.g., "Ethereum" + symbol: currentNetworkConfig.baseAssetSymbol, // e.g., "ETH" + imageUrl: currentNetworkConfig.baseAssetSymbol.toLowerCase(), // This might need adjustment based on your icon system + }, + } : {}), })); + // const marketFrozen = !reserves.some((reserve) => !reserve.isFrozen); // const showFrozenMarketWarning = // marketFrozen && ['Fantom', 'Ethereum AMM'].includes(currentMarketData.marketTitle); const unfrozenReserves = filteredData.filter((r) => !r.isFrozen && !r.isPaused); + const [showFrozenMarketsToggle, setShowFrozenMarketsToggle] = useState(false); const handleChange = () => { diff --git a/src/modules/markets/MarketAssetsListItem.tsx b/src/modules/markets/MarketAssetsListItem.tsx index 9fbf9a1ca9..cd79f875cf 100644 --- a/src/modules/markets/MarketAssetsListItem.tsx +++ b/src/modules/markets/MarketAssetsListItem.tsx @@ -12,6 +12,7 @@ import { NoData } from 'src/components/primitives/NoData'; import { ReserveSubheader } from 'src/components/ReserveSubheader'; import { AssetsBeingOffboarded } from 'src/components/Warnings/OffboardingWarning'; import { useRootStore } from 'src/store/root'; +import { fetchIconSymbolAndName } from 'src/ui-config/reservePatches'; import { MARKETS } from 'src/utils/events'; import { showExternalIncentivesTooltip } from 'src/utils/utils'; import { useShallow } from 'zustand/shallow'; @@ -23,25 +24,35 @@ import { ListItem } from '../../components/lists/ListItem'; import { FormattedNumber } from '../../components/primitives/FormattedNumber'; import { Link, ROUTES } from '../../components/primitives/Link'; import { TokenIcon } from '../../components/primitives/TokenIcon'; -import { ComputedReserveData } from '../../hooks/app-data-provider/useAppDataProvider'; +import { ReserveWithProtocolIncentives } from './MarketAssetsList'; -export const MarketAssetsListItem = ({ ...reserve }: ComputedReserveData) => { +export const MarketAssetsListItem = ({ ...reserve }: ReserveWithProtocolIncentives) => { const router = useRouter(); const [trackEvent, currentMarket] = useRootStore( useShallow((store) => [store.trackEvent, store.currentMarket]) ); - - const offboardingDiscussion = AssetsBeingOffboarded[currentMarket]?.[reserve.symbol]; + const offboardingDiscussion = + AssetsBeingOffboarded[currentMarket]?.[reserve.underlyingToken.symbol]; const externalIncentivesTooltipsSupplySide = showExternalIncentivesTooltip( - reserve.symbol, + reserve.underlyingToken.symbol, currentMarket, ProtocolAction.supply ); const externalIncentivesTooltipsBorrowSide = showExternalIncentivesTooltip( - reserve.symbol, + reserve.underlyingToken.symbol, currentMarket, ProtocolAction.borrow ); + const { iconSymbol } = fetchIconSymbolAndName({ + underlyingAsset: reserve.underlyingToken.address, + symbol: reserve.underlyingToken.symbol, + name: reserve.underlyingToken.name, + }); + + const displayIconSymbol = + iconSymbol?.toLowerCase() !== reserve.underlyingToken.symbol.toLowerCase() + ? iconSymbol + : reserve.underlyingToken.symbol; return ( { onClick={() => { trackEvent(MARKETS.DETAILS_NAVIGATION, { type: 'Row', - assetName: reserve.name, - asset: reserve.underlyingAsset, + assetName: reserve.underlyingToken.name, + asset: reserve.underlyingToken.address.toLowerCase(), market: currentMarket, }); - router.push(ROUTES.reserveOverview(reserve.underlyingAsset, currentMarket)); + router.push( + ROUTES.reserveOverview(reserve.underlyingToken.address.toLowerCase(), currentMarket) + ); }} sx={{ cursor: 'pointer' }} button - data-cy={`marketListItemListItem_${reserve.symbol.toUpperCase()}`} + data-cy={`marketListItemListItem_${reserve.underlyingToken.symbol.toUpperCase()}`} > - + - {reserve.name} + {reserve.underlyingToken.name} { }} > - {reserve.symbol} - {reserve.isIsolated && ( + {reserve.underlyingToken.symbol} + {reserve.isolationModeConfig?.canBeCollateral && ( @@ -82,22 +95,22 @@ export const MarketAssetsListItem = ({ ...reserve }: ComputedReserveData) => { - {reserve.symbol === 'AMPL' && } - {reserve.symbol === 'renFIL' && } + {reserve.underlyingToken.symbol === 'AMPL' && } + {reserve.underlyingToken.symbol === 'renFIL' && } {offboardingDiscussion && } - - + + { - {reserve.borrowingEnabled || Number(reserve.totalDebt) > 0 ? ( + {reserve.borrowInfo && Number(reserve.borrowInfo.total.amount.value) > 0 ? ( <> - {' '} - + {' '} + ) : ( @@ -125,10 +142,14 @@ export const MarketAssetsListItem = ({ ...reserve }: ComputedReserveData) => { 0 ? reserve.variableBorrowAPY : '-1'} - incentives={reserve.vIncentivesData || []} - address={reserve.variableDebtTokenAddress} - symbol={reserve.symbol} + value={ + Number(reserve.borrowInfo?.total.amount.value) > 0 + ? String(reserve.borrowInfo?.apy.value) + : '-1' + } + incentives={reserve.borrowProtocolIncentives} + address={reserve.vToken.address} + symbol={reserve.underlyingToken.symbol} variant="main16" symbolsVariant="secondary16" tooltip={ @@ -140,21 +161,24 @@ export const MarketAssetsListItem = ({ ...reserve }: ComputedReserveData) => { market={currentMarket} protocolAction={ProtocolAction.borrow} /> - {!reserve.borrowingEnabled && - Number(reserve.totalVariableDebt) > 0 && - !reserve.isFrozen && } + {reserve.borrowInfo?.borrowingState === 'DISABLED' && + !reserve.isFrozen && + reserve.borrowInfo.total.amount.value !== '0' && }