Skip to content

Commit 90c565b

Browse files
authored
perf: Reduce graphql requests in farms page (#9865)
<!-- Before opening a pull request, please read the [contributing guidelines](https://github.com/pancakeswap/pancake-frontend/blob/develop/CONTRIBUTING.md) first --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on restructuring import paths for helper functions in the Info section of the web app. It updates import paths to improve organization and consistency. ### Detailed summary - Updated import paths for `infoDataHelpers` and `infoQueryHelpers` in multiple files to `utils` directory - Added new interfaces `V3FarmWithoutStakedValue` and `V2FarmWithoutStakedValue` in `state/farms/types.ts` - Updated import paths for `getChangeForPeriod` in various files to `utils` - Updated import paths for `getPercentChange` in multiple files to `utils` - Updated import paths for `useBCakeProxyContractAddress` in different components and hooks to match new directory structure > The following files were skipped due to too many changes: `doc/Info.md`, `apps/web/src/views/Farms/components/FarmCard/V3/FarmV3ApyButton.tsx`, `apps/web/src/views/Farms/FarmsV3.tsx`, `apps/web/src/state/farms/hooks.ts` > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent f22bfce commit 90c565b

30 files changed

+150
-58
lines changed

apps/web/src/__tests__/views/info/utils/infoData.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getAmountChange, getPercentChange } from 'views/Info/utils/infoDataHelpers'
1+
import { getAmountChange, getPercentChange } from 'utils/infoDataHelpers'
22
import { getLpFeesAndApr } from 'utils/getLpFeesAndApr'
33
import { getChangeForPeriod } from 'utils/getChangeForPeriod'
44

apps/web/src/hooks/usePoolAvgInfo.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export interface UsePoolAvgInfoParams {
99
numberOfDays?: number
1010
address?: string
1111
chainId?: ChainId
12+
enabled?: boolean
1213
}
1314

1415
export const averageArray = (dataToCalculate: number[]): number => {
@@ -33,9 +34,9 @@ const defaultInfo: Info = {
3334
feeUSD: 0,
3435
}
3536

36-
export function usePoolAvgInfo({ address = '', numberOfDays = 7, chainId }: UsePoolAvgInfoParams) {
37+
export function usePoolAvgInfo({ address = '', numberOfDays = 7, chainId, enabled = true }: UsePoolAvgInfoParams) {
3738
const { data } = useQuery({
38-
queryKey: [address, chainId],
39+
queryKey: ['poolAvgInfo', address, chainId],
3940

4041
queryFn: async () => {
4142
if (!chainId) return undefined
@@ -70,7 +71,7 @@ export function usePoolAvgInfo({ address = '', numberOfDays = 7, chainId }: UseP
7071
}
7172
},
7273

73-
enabled: Boolean(address && chainId),
74+
enabled: Boolean(address && chainId && enabled),
7475
refetchOnWindowFocus: false,
7576
})
7677

apps/web/src/hooks/v3/useAllV3TicksQuery.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ export type AllV3TicksQuery = {
1717
export type Ticks = AllV3TicksQuery['ticks']
1818
export type TickData = Ticks[number]
1919

20-
export default function useAllV3TicksQuery(poolAddress: string | undefined, interval: number) {
20+
export default function useAllV3TicksQuery(poolAddress: string | undefined, interval: number, enabled = true) {
2121
const { chainId } = useActiveChainId()
2222
const { data, isLoading, error } = useQuery({
2323
queryKey: [`useAllV3TicksQuery-${poolAddress}-${chainId}`],
2424
queryFn: async () => {
2525
if (!chainId || !poolAddress) return undefined
2626
return getPoolTicks(chainId, poolAddress)
2727
},
28-
enabled: Boolean(poolAddress && chainId && v3Clients[chainId]),
28+
enabled: Boolean(poolAddress && chainId && v3Clients[chainId] && enabled),
2929
refetchInterval: interval,
3030
refetchOnMount: false,
3131
refetchOnReconnect: false,

apps/web/src/hooks/v3/usePoolTickData.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,28 @@ function useTicksFromSubgraph(
1818
currencyA: Currency | undefined | null,
1919
currencyB: Currency | undefined | null,
2020
feeAmount: FeeAmount | undefined,
21+
enabled = true,
2122
) {
2223
const poolAddress =
2324
currencyA && currencyB && feeAmount
2425
? Pool.getAddress(currencyA?.wrapped, currencyB?.wrapped, feeAmount, undefined)
2526
: undefined
2627

27-
return useAllV3TicksQuery(poolAddress, 30000)
28+
return useAllV3TicksQuery(poolAddress, 30000, enabled)
2829
}
2930

3031
// Fetches all ticks for a given pool
3132
export function useAllV3Ticks(
3233
currencyA: Currency | undefined | null,
3334
currencyB: Currency | undefined | null,
3435
feeAmount: FeeAmount | undefined,
36+
enabled = true,
3537
): {
3638
isLoading: boolean
3739
error: unknown
3840
ticks: TickData[] | undefined
3941
} {
40-
const subgraphTickData = useTicksFromSubgraph(currencyA, currencyB, feeAmount)
42+
const subgraphTickData = useTicksFromSubgraph(currencyA, currencyB, feeAmount, enabled)
4143

4244
return {
4345
isLoading: subgraphTickData.isLoading,

apps/web/src/state/farms/hooks.ts

+83-7
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,28 @@ import { useMemo } from 'react'
77
import { useSelector } from 'react-redux'
88
import { useAppDispatch } from 'state'
99
import { getMasterChefContract } from 'utils/contractHelpers'
10-
import { useBCakeProxyContractAddress } from 'views/Farms/hooks/useBCakeProxyContractAddress'
10+
import { useBCakeProxyContractAddress } from 'hooks/useBCakeProxyContractAddress'
1111

1212
import useAccountActiveChain from 'hooks/useAccountActiveChain'
13-
import {
14-
fetchBCakeWrapperDataAsync,
15-
fetchBCakeWrapperUserDataAsync,
16-
fetchFarmsPublicDataAsync,
17-
fetchFarmUserDataAsync,
18-
} from '.'
13+
import { v3Clients } from 'utils/graphql'
14+
import { gql } from 'graphql-request'
15+
import { averageArray } from 'hooks/usePoolAvgInfo'
16+
import { multiQuery } from 'utils/infoQueryHelpers'
17+
import mapKeys from 'lodash/mapKeys'
18+
import mapValues from 'lodash/mapValues'
19+
import { V2FarmWithoutStakedValue, V3FarmWithoutStakedValue } from 'state/farms/types'
1920
import {
2021
farmSelector,
2122
makeFarmFromPidSelector,
2223
makeLpTokenPriceFromLpSymbolSelector,
2324
makeUserFarmFromPidSelector,
2425
} from './selectors'
26+
import {
27+
fetchBCakeWrapperDataAsync,
28+
fetchBCakeWrapperUserDataAsync,
29+
fetchFarmsPublicDataAsync,
30+
fetchFarmUserDataAsync,
31+
} from '.'
2532

2633
export function useFarmsLength() {
2734
const { chainId } = useActiveChainId()
@@ -63,6 +70,75 @@ export function useFarmV2PublicAPI() {
6370
})
6471
}
6572

73+
export const usePollFarmsAvgInfo = (activeFarms: (V3FarmWithoutStakedValue | V2FarmWithoutStakedValue)[]) => {
74+
const { chainId } = useAccountActiveChain()
75+
76+
const activeFarmAddresses = useMemo(() => {
77+
return activeFarms.map((farm) => farm.lpAddress).sort()
78+
}, [activeFarms])
79+
80+
const { data } = useQuery({
81+
queryKey: ['farmsAvgInfo', chainId, activeFarmAddresses],
82+
placeholderData: {},
83+
queryFn: async () => {
84+
if (!chainId) return undefined
85+
const client = v3Clients[chainId]
86+
if (!client) {
87+
console.error('[Failed] Trading volume', chainId)
88+
return {}
89+
}
90+
91+
const addresses = activeFarms
92+
.map((farm) => farm.lpAddress)
93+
.map((lpAddress) => {
94+
return lpAddress.toLowerCase()
95+
})
96+
97+
const rawResult: any | undefined = await multiQuery(
98+
(subqueries) => gql`
99+
query getVolume {
100+
${subqueries}
101+
}
102+
`,
103+
addresses.map(
104+
(tokenAddress) => `
105+
t${tokenAddress}:poolDayDatas(first: 7, orderBy: date, orderDirection: desc, where: { pool: "${tokenAddress.toLowerCase()}"}) {
106+
volumeUSD
107+
tvlUSD
108+
feesUSD
109+
protocolFeesUSD
110+
}
111+
`,
112+
),
113+
client,
114+
)
115+
116+
const results = mapKeys(rawResult, (_, key) => {
117+
return key.substring(1, key.length)
118+
})
119+
120+
return mapValues(results, (value) => {
121+
const volumes = value.map((d: { volumeUSD: string }) => Number(d.volumeUSD))
122+
const feeUSDs = value.map(
123+
(d: { feesUSD: string; protocolFeesUSD: string }) => Number(d.feesUSD) - Number(d.protocolFeesUSD),
124+
)
125+
return {
126+
volumeUSD: averageArray(volumes),
127+
tvlUSD: parseFloat(value[0]?.tvlUSD) || 0,
128+
feeUSD: averageArray(feeUSDs),
129+
}
130+
})
131+
},
132+
133+
enabled: Boolean(chainId && activeFarms?.length),
134+
refetchOnReconnect: false,
135+
refetchOnWindowFocus: false,
136+
refetchOnMount: false,
137+
})
138+
139+
return data
140+
}
141+
66142
export const usePollFarmsWithUserData = () => {
67143
const dispatch = useAppDispatch()
68144
const { account, chainId } = useAccountActiveChain()

apps/web/src/state/farms/types.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { DeserializedFarm, FarmV3DataWithPriceAndUserInfo } from '@pancakeswap/farms'
2+
3+
export interface V3FarmWithoutStakedValue extends FarmV3DataWithPriceAndUserInfo {
4+
version: 3
5+
}
6+
7+
export interface V2FarmWithoutStakedValue extends DeserializedFarm {
8+
version: 2
9+
}

apps/web/src/state/info/queries/pools/poolData.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { subgraphTokenSymbol } from 'state/info/constant'
44
import { Block, PoolData } from 'state/info/types'
55
import { getChangeForPeriod } from 'utils/getChangeForPeriod'
66
import { getLpFeesAndApr } from 'utils/getLpFeesAndApr'
7-
import { getAmountChange, getPercentChange } from 'views/Info/utils/infoDataHelpers'
7+
import { getAmountChange, getPercentChange } from 'utils/infoDataHelpers'
88

99
import { safeGetAddress } from 'utils'
1010
import {

apps/web/src/state/info/queries/protocol/overview.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Block, ProtocolData } from 'state/info/types'
55
import { getChangeForPeriod } from 'utils/getChangeForPeriod'
66
import { getDeltaTimestamps } from 'utils/getDeltaTimestamps'
77
import { useBlocksFromTimestamps } from 'views/Info/hooks/useBlocksFromTimestamps'
8-
import { getPercentChange } from 'views/Info/utils/infoDataHelpers'
8+
import { getPercentChange } from 'utils/infoDataHelpers'
99
import { MultiChainName, checkIsStableSwap, getMultiChainQueryEndPointWithStableSwap } from '../../constant'
1010
import { useGetChainName } from '../../hooks'
1111

apps/web/src/state/info/queries/tokens/priceData.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import orderBy from 'lodash/orderBy'
44

55
import { PriceChartEntry } from 'state/info/types'
66
import { getBlocksFromTimestamps } from 'utils/getBlocksFromTimestamps'
7-
import { multiQuery } from 'views/Info/utils/infoQueryHelpers'
7+
import { multiQuery } from 'utils/infoQueryHelpers'
88
import { MultiChainName, checkIsStableSwap, getMultiChainQueryEndPointWithStableSwap } from '../../constant'
99

1010
interface FormattedHistory {

apps/web/src/state/info/queries/tokens/tokenData.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { gql } from 'graphql-request'
33
import { Block, TokenData } from 'state/info/types'
44
import { getChangeForPeriod } from 'utils/getChangeForPeriod'
5-
import { getAmountChange, getPercentChange } from 'views/Info/utils/infoDataHelpers'
5+
import { getAmountChange, getPercentChange } from 'utils/infoDataHelpers'
66
import {
77
MultiChainNameExtend,
88
STABLESWAP_SUBGRAPHS_START_BLOCK,

apps/web/src/state/swap/fetch/fetchDerivedPriceData.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import orderBy from 'lodash/orderBy'
88
import { multiChainName } from 'state/info/constant'
99
import { Block } from 'state/info/types'
1010
import { getBlocksFromTimestamps } from 'utils/getBlocksFromTimestamps'
11-
import { multiQuery } from 'views/Info/utils/infoQueryHelpers'
11+
import { multiQuery } from 'utils/infoQueryHelpers'
1212
import { getDerivedPrices, getDerivedPricesQueryConstructor, getTVL } from '../queries/getDerivedPrices'
1313
import { PairDataTimeWindowEnum } from '../types'
1414

apps/web/src/utils/getBlocksFromTimestamps.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import orderBy from 'lodash/orderBy'
33
import { multiChainBlocksClient, multiChainName, MultiChainNameExtend } from 'state/info/constant'
44
import { ChainId, getLlamaChainName } from '@pancakeswap/chains'
55
import { Block } from 'state/info/types'
6-
import { multiQuery } from 'views/Info/utils/infoQueryHelpers'
6+
import { multiQuery } from 'utils/infoQueryHelpers'
77

88
const getBlockSubqueries = (timestamps: number[]) =>
99
timestamps.map((timestamp) => {

apps/web/src/utils/getChangeForPeriod.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getAmountChange, getPercentChange } from '../views/Info/utils/infoDataHelpers'
1+
import { getAmountChange, getPercentChange } from './infoDataHelpers'
22

33
/**
44
* Given current value and value 1 and 2 periods (e.g. 1day + 2days, 1week - 2weeks) returns the amount change for latest period

apps/web/src/views/Farms/FarmsV3.tsx

+6-18
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,5 @@
11
import { ChainId } from '@pancakeswap/chains'
2-
import {
3-
DeserializedFarm,
4-
FarmV3DataWithPriceAndUserInfo,
5-
FarmWithStakedValue,
6-
filterFarmsByQuery,
7-
supportedChainIdV2,
8-
supportedChainIdV3,
9-
} from '@pancakeswap/farms'
2+
import { FarmWithStakedValue, filterFarmsByQuery, supportedChainIdV2, supportedChainIdV3 } from '@pancakeswap/farms'
103
import { useIntersectionObserver } from '@pancakeswap/hooks'
114
import { useTranslation } from '@pancakeswap/localization'
125
import partition from 'lodash/partition'
@@ -40,7 +33,7 @@ import { useCakePrice } from 'hooks/useCakePrice'
4033
import orderBy from 'lodash/orderBy'
4134
import { useRouter } from 'next/router'
4235
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
43-
import { useFarms, usePollFarmsWithUserData } from 'state/farms/hooks'
36+
import { useFarms, usePollFarmsAvgInfo, usePollFarmsWithUserData } from 'state/farms/hooks'
4437
import { useFarmsV3WithPositionsAndBooster } from 'state/farmsV3/hooks'
4538
import { useCakeVaultUserData } from 'state/pools/hooks'
4639
import { ViewMode } from 'state/user/actions'
@@ -50,6 +43,7 @@ import { getFarmApr } from 'utils/apr'
5043
import { getStakedFarms } from 'views/Farms/utils/getStakedFarms'
5144
import { BCakeMigrationBanner } from 'views/Home/components/Banners/BCakeMigrationBanner'
5245
import { useAccount } from 'wagmi'
46+
import { V2FarmWithoutStakedValue, V3FarmWithoutStakedValue } from 'state/farms/types'
5347
import Table from './components/FarmTable/FarmTable'
5448
import { FarmTypesFilter } from './components/FarmTypesFilter'
5549
import { BCakeBoosterCard } from './components/YieldBooster/components/bCakeV3/BCakeBoosterCard'
@@ -166,18 +160,10 @@ const FinishedTextLink = styled(Link)`
166160

167161
const NUMBER_OF_FARMS_VISIBLE = 12
168162

169-
export interface V3FarmWithoutStakedValue extends FarmV3DataWithPriceAndUserInfo {
170-
version: 3
171-
}
172-
173163
export interface V3Farm extends V3FarmWithoutStakedValue {
174164
version: 3
175165
}
176166

177-
export interface V2FarmWithoutStakedValue extends DeserializedFarm {
178-
version: 2
179-
}
180-
181167
export interface V2Farm extends FarmWithStakedValue {
182168
version: 2
183169
}
@@ -271,6 +257,8 @@ const Farms: React.FC<React.PropsWithChildren> = ({ children }) => {
271257
[farmsLP, v2PoolLength, v3PoolLength],
272258
)
273259

260+
const farmsAvgInfo = usePollFarmsAvgInfo(activeFarms)
261+
274262
const archivedFarms = farmsLP
275263

276264
const stakedOnlyFarms = useMemo(() => getStakedFarms(activeFarms), [activeFarms])
@@ -426,7 +414,7 @@ const Farms: React.FC<React.PropsWithChildren> = ({ children }) => {
426414
setQuery(event.target.value)
427415
}, [])
428416

429-
const providerValue = useMemo(() => ({ chosenFarmsMemoized }), [chosenFarmsMemoized])
417+
const providerValue = useMemo(() => ({ chosenFarmsMemoized, farmsAvgInfo }), [chosenFarmsMemoized, farmsAvgInfo])
430418

431419
return (
432420
<FarmsV3Context.Provider value={providerValue}>

apps/web/src/views/Farms/components/BCakeMigrateModal.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import useCatchTxError from 'hooks/useCatchTxError'
1919
import { useBCakeProxyContract, useERC20 } from 'hooks/useContract'
2020
import { useEffect, useMemo, useState } from 'react'
2121
import { styled } from 'styled-components'
22-
import { useBCakeProxyContractAddress } from '../hooks/useBCakeProxyContractAddress'
22+
import { useBCakeProxyContractAddress } from '../../../hooks/useBCakeProxyContractAddress'
2323
import useProxyStakedActions from './YieldBooster/hooks/useProxyStakedActions'
2424

2525
export const StepperCircle = styled.div`

apps/web/src/views/Farms/components/FarmCard/ApyButton.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import { MouseEvent, useCallback, useMemo } from 'react'
77
import { useFarmFromPid, useFarmUser } from 'state/farms/hooks'
88

99
import { BIG_ZERO } from '@pancakeswap/utils/bigNumber'
10-
import { V2FarmWithoutStakedValue, V3FarmWithoutStakedValue } from 'views/Farms/FarmsV3'
1110
import { useAccount } from 'wagmi'
11+
import { V2FarmWithoutStakedValue, V3FarmWithoutStakedValue } from 'state/farms/types'
1212

1313
export interface ApyButtonProps {
1414
variant: 'text' | 'text-and-button'

0 commit comments

Comments
 (0)