From 23e4e4c02ca5e5759008b80b06f0546639943113 Mon Sep 17 00:00:00 2001 From: Danny Delott Date: Tue, 24 Dec 2024 13:07:26 -0800 Subject: [PATCH] Improve caching of rewards resolver functions and token fiat price (#1700) --- .../src/hyperdrive/getLpApy.ts | 16 +++--- .../src/hyperdrive/getYieldSourceRate.ts | 15 +++--- .../ui/hyperdrive/hooks/usePresentValue.ts | 16 +++--- .../ui/hyperdrive/hooks/useUnpausedPools.ts | 20 ++++--- .../src/ui/rewards/useRewards.ts | 45 +++++++++++----- .../src/ui/token/hooks/useTokenFiatPrice.ts | 53 +++++++++---------- 6 files changed, 97 insertions(+), 68 deletions(-) diff --git a/apps/hyperdrive-trading/src/hyperdrive/getLpApy.ts b/apps/hyperdrive-trading/src/hyperdrive/getLpApy.ts index 20d8d4450..8dde86198 100644 --- a/apps/hyperdrive-trading/src/hyperdrive/getLpApy.ts +++ b/apps/hyperdrive-trading/src/hyperdrive/getLpApy.ts @@ -7,11 +7,10 @@ import { HyperdriveConfig, } from "@delvtech/hyperdrive-appconfig"; import { ReadHyperdrive } from "@delvtech/hyperdrive-js"; -import { getPublicClient } from "@wagmi/core"; import { convertMillisecondsToDays } from "src/base/convertMillisecondsToDays"; import { isForkChain } from "src/chains/isForkChain"; -import { wagmiConfig } from "src/network/wagmiClient"; -import { PublicClient } from "viem"; +import { queryClient } from "src/network/queryClient"; +import { makeRewardsQuery } from "src/ui/rewards/useRewards"; export type LpApyResult = { ratePeriodDays: number; @@ -87,17 +86,18 @@ export async function getLpApy({ netLpApy = lpApy; // Add rewards APY if available - const publicClient = getPublicClient(wagmiConfig as any, { - chainId: hyperdrive.chainId, - }) as PublicClient; - const rewardsFn = getRewardsFn({ yieldSourceId: hyperdrive.yieldSource, appConfig, }); if (rewardsFn) { - const rewards = await rewardsFn(publicClient); + const rewards = await queryClient.fetchQuery( + makeRewardsQuery({ + chainId: hyperdrive.chainId, + hyperdriveAddress: hyperdrive.address, + }), + ); rewards?.forEach((reward) => { if (reward.type === "apy") { netLpApy = fixed(reward.apy).add(netLpApy as bigint).bigint; diff --git a/apps/hyperdrive-trading/src/hyperdrive/getYieldSourceRate.ts b/apps/hyperdrive-trading/src/hyperdrive/getYieldSourceRate.ts index 9fcf2fae1..cb37caf84 100644 --- a/apps/hyperdrive-trading/src/hyperdrive/getYieldSourceRate.ts +++ b/apps/hyperdrive-trading/src/hyperdrive/getYieldSourceRate.ts @@ -8,11 +8,10 @@ import { HyperdriveConfig, } from "@delvtech/hyperdrive-appconfig"; import { ReadHyperdrive } from "@delvtech/hyperdrive-js"; -import { getPublicClient } from "@wagmi/core"; import { convertMillisecondsToDays } from "src/base/convertMillisecondsToDays"; import { isForkChain } from "src/chains/isForkChain"; -import { wagmiConfig } from "src/network/wagmiClient"; -import { PublicClient } from "viem"; +import { queryClient } from "src/network/queryClient"; +import { makeRewardsQuery } from "src/ui/rewards/useRewards"; export async function getYieldSourceRate({ readHyperdrive, @@ -94,10 +93,12 @@ async function calcNetRate( appConfig, }); if (rewardsFn) { - const publicClient = getPublicClient(wagmiConfig as any, { - chainId: hyperdrive.chainId, - }) as PublicClient; - const rewards = await rewardsFn(publicClient); + const rewards = await queryClient.fetchQuery( + makeRewardsQuery({ + chainId: hyperdrive.chainId, + hyperdriveAddress: hyperdrive.address, + }), + ); rewards?.forEach((reward) => { if (reward.type === "apy") { netRate = fixed(reward.apy).add( diff --git a/apps/hyperdrive-trading/src/ui/hyperdrive/hooks/usePresentValue.ts b/apps/hyperdrive-trading/src/ui/hyperdrive/hooks/usePresentValue.ts index 5b38ee318..13a2912a6 100644 --- a/apps/hyperdrive-trading/src/ui/hyperdrive/hooks/usePresentValue.ts +++ b/apps/hyperdrive-trading/src/ui/hyperdrive/hooks/usePresentValue.ts @@ -10,9 +10,10 @@ import { getPublicClient } from "@wagmi/core"; import { ZERO_ADDRESS } from "src/base/constants"; import { makeQueryKey2 } from "src/base/makeQueryKey"; import { isTestnetChain } from "src/chains/isTestnetChain"; +import { queryClient } from "src/network/queryClient"; import { wagmiConfig } from "src/network/wagmiClient"; import { useReadHyperdrive } from "src/ui/hyperdrive/hooks/useReadHyperdrive"; -import { getTokenFiatPrice } from "src/ui/token/hooks/useTokenFiatPrice"; +import { makeTokenFiatPriceQuery } from "src/ui/token/hooks/useTokenFiatPrice"; import { Address, PublicClient } from "viem"; export function usePresentValue({ @@ -88,11 +89,14 @@ export function getPresentValue({ const isFiatSupported = !isTestnetChain(chainId) && baseToken.address !== ZERO_ADDRESS; const fiatPricePromise = isFiatSupported - ? getTokenFiatPrice({ - chainId: baseToken.chainId, - publicClient, - tokenAddress: baseToken.address, - }).catch(() => undefined) + ? queryClient + .fetchQuery( + makeTokenFiatPriceQuery({ + chainId: baseToken.chainId, + tokenAddress: baseToken.address, + }), + ) + .catch(() => undefined) : Promise.resolve(undefined); return Promise.all([readHyperdrive.getPresentValue(), fiatPricePromise]).then( diff --git a/apps/hyperdrive-trading/src/ui/hyperdrive/hooks/useUnpausedPools.ts b/apps/hyperdrive-trading/src/ui/hyperdrive/hooks/useUnpausedPools.ts index 6f9c5bfa0..24f086e2b 100644 --- a/apps/hyperdrive-trading/src/ui/hyperdrive/hooks/useUnpausedPools.ts +++ b/apps/hyperdrive-trading/src/ui/hyperdrive/hooks/useUnpausedPools.ts @@ -5,12 +5,11 @@ import { } from "@delvtech/hyperdrive-appconfig"; import { getHyperdrive } from "@delvtech/hyperdrive-js"; import { useQuery } from "@tanstack/react-query"; -import { getPublicClient } from "@wagmi/core"; import { makeQueryKey2 } from "src/base/makeQueryKey"; import { getDrift } from "src/drift/getDrift"; -import { wagmiConfig } from "src/network/wagmiClient"; +import { queryClient } from "src/network/queryClient"; import { useAppConfigForConnectedChain } from "src/ui/appconfig/useAppConfigForConnectedChain"; -import { PublicClient } from "viem"; +import { makeRewardsQuery } from "src/ui/rewards/useRewards"; import { useChainId } from "wagmi"; const HIDDEN_POOLS = [ @@ -59,10 +58,6 @@ export function useUnpausedPools(): { } // Resolve the rewards information and include it for consumers - const publicClient = getPublicClient(wagmiConfig as any, { - chainId: hyperdrive.chainId, - }) as PublicClient; - const rewardsFn = getRewardsFn({ yieldSourceId: hyperdrive.yieldSource, appConfig: appConfigForConnectedChain, @@ -70,7 +65,16 @@ export function useUnpausedPools(): { const rewards = !rewardsFn ? [] - : await rewardsFn(publicClient).catch(() => []); + : await (async () => { + return queryClient + .fetchQuery( + makeRewardsQuery({ + hyperdriveAddress: hyperdrive.address, + chainId: hyperdrive.chainId, + }), + ) + .catch(() => []); + })(); return { ...hyperdrive, rewardsAmount: rewards }; }), diff --git a/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts b/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts index e8640cfe0..4f3e5323c 100644 --- a/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts +++ b/apps/hyperdrive-trading/src/ui/rewards/useRewards.ts @@ -1,48 +1,69 @@ import { AnyReward, appConfig, + getHyperdriveConfig, getRewardsFn, HyperdriveConfig, } from "@delvtech/hyperdrive-appconfig"; -import { useQuery } from "@tanstack/react-query"; +import { useQuery, UseQueryOptions } from "@tanstack/react-query"; import { getPublicClient } from "@wagmi/core"; import { makeQueryKey2 } from "src/base/makeQueryKey"; import { wagmiConfig } from "src/network/wagmiClient"; -import { PublicClient } from "viem"; +import { Address, PublicClient } from "viem"; export function useRewards(hyperdriveConfig: HyperdriveConfig): { rewards: AnyReward[] | undefined; status: "error" | "success" | "loading"; } { + const { data: rewards, status } = useQuery( + makeRewardsQuery({ + hyperdriveAddress: hyperdriveConfig.address, + chainId: hyperdriveConfig.chainId, + }), + ); + + return { + rewards, + status, + }; +} + +export function makeRewardsQuery({ + hyperdriveAddress, + chainId, +}: { + hyperdriveAddress: Address; + chainId: number; +}): UseQueryOptions { + const hyperdriveConfig = getHyperdriveConfig({ + hyperdriveChainId: chainId, + hyperdriveAddress, + appConfig, + }); const rewardsFn = getRewardsFn({ yieldSourceId: hyperdriveConfig.yieldSource, appConfig, }); const queryEnabled = !!rewardsFn; - - const { data: rewards, status } = useQuery({ + return { queryKey: makeQueryKey2({ namespace: "rewards", queryId: "rewards", params: { - chainId: hyperdriveConfig.chainId, - hyperdriveAddress: hyperdriveConfig.address, + chainId, + hyperdriveAddress, }, }), enabled: queryEnabled, + staleTime: Infinity, queryFn: queryEnabled ? async () => { const publicClient = getPublicClient(wagmiConfig as any, { - chainId: hyperdriveConfig.chainId, + chainId, }) as PublicClient; return rewardsFn(publicClient); } : undefined, - }); - - return { - rewards, - status, }; } diff --git a/apps/hyperdrive-trading/src/ui/token/hooks/useTokenFiatPrice.ts b/apps/hyperdrive-trading/src/ui/token/hooks/useTokenFiatPrice.ts index b0dd0a466..80fecd592 100644 --- a/apps/hyperdrive-trading/src/ui/token/hooks/useTokenFiatPrice.ts +++ b/apps/hyperdrive-trading/src/ui/token/hooks/useTokenFiatPrice.ts @@ -1,5 +1,5 @@ import { appConfig, getPriceOracleFn } from "@delvtech/hyperdrive-appconfig"; -import { useQuery } from "@tanstack/react-query"; +import { useQuery, UseQueryOptions } from "@tanstack/react-query"; import { getPublicClient } from "@wagmi/core"; import { ZERO_ADDRESS } from "src/base/constants"; import { makeQueryKey2 } from "src/base/makeQueryKey"; @@ -15,15 +15,26 @@ export function useTokenFiatPrice({ }): { fiatPrice: bigint | undefined; } { + const { data } = useQuery(makeTokenFiatPriceQuery({ chainId, tokenAddress })); + return { fiatPrice: data }; +} +export function makeTokenFiatPriceQuery({ + chainId, + tokenAddress, +}: { + chainId: number; + tokenAddress: Address | undefined; +}): UseQueryOptions { const queryEnabled = !isTestnetChain(chainId) && !!tokenAddress && tokenAddress !== ZERO_ADDRESS; - const { data } = useQuery({ + return { queryKey: makeQueryKey2({ namespace: "tokens", queryId: "tokenFiatPrice", params: { chainId, tokenAddress }, }), + staleTime: Infinity, enabled: queryEnabled, queryFn: queryEnabled ? async () => { @@ -31,31 +42,19 @@ export function useTokenFiatPrice({ chainId, }) as PublicClient; - return getTokenFiatPrice({ chainId, tokenAddress, publicClient }); + const priceOracleFn = getPriceOracleFn({ + chainId, + tokenAddress, + appConfig, + }); + + return priceOracleFn({ + chainId, + denomination: "usd", + publicClient, + tokenAddress, + }); } : undefined, - }); - return { fiatPrice: data }; -} -export function getTokenFiatPrice({ - chainId, - tokenAddress, - publicClient, -}: { - chainId: number; - tokenAddress: Address; - publicClient: PublicClient; -}): Promise { - const priceOracleFn = getPriceOracleFn({ - chainId, - tokenAddress, - appConfig, - }); - - return priceOracleFn({ - chainId, - denomination: "usd", - publicClient, - tokenAddress, - }); + }; }