-
Notifications
You must be signed in to change notification settings - Fork 442
Refactor Maket Page to use Aave-sdk #2686
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
114328f
940cdf4
fcb1a39
92eeffd
a80c04b
4a5e1fe
eff6ed6
8653eb9
be28f80
d3d3e45
3610842
4e83b97
de6b877
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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, | ||
})); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<number, EmodeCategory>; | ||
user?: ExtendedFormattedUser; | ||
|
@@ -62,6 +73,34 @@ export const AppDataProvider: React.FC<PropsWithChildren> = ({ 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<PropsWithChildren> = ({ children }) => { | |
const isReservesLoading = reservesDataLoading || formattedPoolReservesLoading; | ||
const isUserDataLoading = userReservesDataLoading || userSummaryLoading; | ||
|
||
const loading = isPending || isReservesLoading || (!!currentAccount && isUserDataLoading); | ||
|
||
return ( | ||
<AppDataContext.Provider | ||
value={{ | ||
loading: isReservesLoading || (!!currentAccount && isUserDataLoading), | ||
loading, | ||
market: sdkMarket, | ||
totalBorrows, | ||
supplyReserves, | ||
borrowReserves, | ||
eModeCategories, | ||
userState: marketUserState, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this one used? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually not yet, but I have a feeling I’ll need it for another part of the |
||
// Legacy fields (to be removed once consumers migrate) | ||
reserves: formattedPoolReserves || [], | ||
eModes, | ||
user: userSummary, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { AaveClient, chainId, evmAddress, OrderDirection } from '@aave/client'; | ||
import { markets } from '@aave/client/actions'; | ||
import { useQuery } from '@tanstack/react-query'; | ||
import { MarketDataType } from 'src/ui-config/marketsConfig'; | ||
import { queryKeysFactory } from 'src/ui-config/queries'; | ||
|
||
type UseMarketsDataParams = { | ||
client: AaveClient; | ||
marketData: MarketDataType; | ||
account?: string | null; | ||
}; | ||
|
||
export const useMarketsData = ({ client, marketData, account }: UseMarketsDataParams) => { | ||
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; | ||
}, | ||
}); | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.