From 84900720aaf07ef09b4cb5a642ae3fbc29c02042 Mon Sep 17 00:00:00 2001 From: Pierre Bertet Date: Sat, 18 Jan 2025 17:30:19 +0000 Subject: [PATCH] Group GraphQL queries (#708) Query and cache at once: - The interest rate brackets for all collaterals - The stability pools total deposited for all collaterals --- frontend/app/src/graphql/gql.ts | 8 ++-- frontend/app/src/graphql/graphql.ts | 31 ++++++------- frontend/app/src/liquity-utils.ts | 1 - frontend/app/src/subgraph-hooks.ts | 69 +++++++++++++++++----------- frontend/app/src/subgraph-queries.ts | 15 +++--- 5 files changed, 69 insertions(+), 55 deletions(-) diff --git a/frontend/app/src/graphql/gql.ts b/frontend/app/src/graphql/gql.ts index b8845060d..e936170b2 100644 --- a/frontend/app/src/graphql/gql.ts +++ b/frontend/app/src/graphql/gql.ts @@ -19,13 +19,13 @@ const documents = { "\n fragment FullTroveFragment on Trove {\n id\n borrower\n closedAt\n createdAt\n debt\n deposit\n interestRate\n mightBeLeveraged\n stake\n status\n troveId\n updatedAt\n collateral {\n id\n token {\n symbol\n name\n }\n minCollRatio\n collIndex\n }\n interestBatch {\n id\n annualInterestRate\n annualManagementFee\n batchManager\n }\n }\n": types.FullTroveFragmentFragmentDoc, "\n query TrovesByAccount($account: Bytes!) {\n troves(\n where: {\n borrower: $account,\n status_in: [active,redeemed,liquidated],\n }\n orderBy: updatedAt\n orderDirection: desc\n ) {\n id\n borrower\n closedAt\n createdAt\n debt\n deposit\n interestRate\n mightBeLeveraged\n stake\n status\n troveId\n updatedAt\n collateral {\n id\n token {\n symbol\n name\n }\n minCollRatio\n collIndex\n }\n interestBatch {\n id\n annualInterestRate\n annualManagementFee\n batchManager\n }\n }\n }\n": types.TrovesByAccountDocument, "\n query TroveById($id: ID!) {\n trove(id: $id) {\n id\n borrower\n closedAt\n createdAt\n debt\n deposit\n interestRate\n mightBeLeveraged\n stake\n status\n troveId\n updatedAt\n collateral {\n id\n token {\n symbol\n name\n }\n minCollRatio\n collIndex\n }\n interestBatch {\n id\n annualInterestRate\n annualManagementFee\n batchManager\n }\n }\n }\n": types.TroveByIdDocument, - "\n query StabilityPool($id: ID!) {\n stabilityPool(id: $id) {\n id\n totalDeposited\n }\n }\n": types.StabilityPoolDocument, + "\n query StabilityPools {\n stabilityPools {\n id\n totalDeposited\n }\n }\n": types.StabilityPoolsDocument, "\n fragment StabilityPoolDepositFragment on StabilityPoolDeposit {\n id\n deposit\n depositor\n collateral {\n collIndex\n }\n snapshot {\n B\n P\n S\n epoch\n scale\n }\n }\n": types.StabilityPoolDepositFragmentFragmentDoc, "\n query StabilityPoolDepositsByAccount($account: Bytes!) {\n stabilityPoolDeposits(where: { depositor: $account, deposit_gt: 0 }) {\n id\n deposit\n depositor\n collateral {\n collIndex\n }\n snapshot {\n B\n P\n S\n epoch\n scale\n }\n }\n }\n": types.StabilityPoolDepositsByAccountDocument, "\n query StabilityPoolDeposit($id: ID!) {\n stabilityPoolDeposit(id: $id) {\n id\n deposit\n depositor\n collateral {\n collIndex\n }\n snapshot {\n B\n P\n S\n epoch\n scale\n }\n }\n }\n": types.StabilityPoolDepositDocument, "\n query StabilityPoolEpochScale($id: ID!) {\n stabilityPoolEpochScale(id: $id) {\n id\n B\n S\n }\n }\n": types.StabilityPoolEpochScaleDocument, "\n query InterestBatch($id: ID!) {\n interestBatch(id: $id) {\n collateral {\n collIndex\n }\n batchManager\n debt\n coll\n annualInterestRate\n annualManagementFee\n }\n }\n": types.InterestBatchDocument, - "\n query InterestRateBrackets($collId: String!) {\n interestRateBrackets(where: { collateral: $collId }, orderBy: rate) {\n rate\n totalDebt\n }\n }\n": types.InterestRateBracketsDocument, + "\n query AllInterestRateBrackets {\n interestRateBrackets(orderBy: rate) {\n collateral {\n collIndex\n }\n rate\n totalDebt\n }\n }\n": types.AllInterestRateBracketsDocument, "\n query GovernanceInitiatives {\n governanceInitiatives {\n id\n }\n }\n": types.GovernanceInitiativesDocument, "\n query GovernanceUser($id: ID!) {\n governanceUser(id: $id) {\n id\n allocatedLQTY\n stakedLQTY\n stakedOffset\n allocations {\n id\n atEpoch\n vetoLQTY\n voteLQTY\n initiative {\n id\n }\n }\n }\n }\n": types.GovernanceUserDocument, "\n query GovernanceStats {\n governanceStats(id: \"stats\") {\n id\n totalLQTYStaked\n totalOffset\n totalInitiatives\n }\n }\n": types.GovernanceStatsDocument, @@ -51,7 +51,7 @@ export function graphql(source: "\n query TroveById($id: ID!) {\n trove(id: /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query StabilityPool($id: ID!) {\n stabilityPool(id: $id) {\n id\n totalDeposited\n }\n }\n"): typeof import('./graphql').StabilityPoolDocument; +export function graphql(source: "\n query StabilityPools {\n stabilityPools {\n id\n totalDeposited\n }\n }\n"): typeof import('./graphql').StabilityPoolsDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ @@ -75,7 +75,7 @@ export function graphql(source: "\n query InterestBatch($id: ID!) {\n intere /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "\n query InterestRateBrackets($collId: String!) {\n interestRateBrackets(where: { collateral: $collId }, orderBy: rate) {\n rate\n totalDebt\n }\n }\n"): typeof import('./graphql').InterestRateBracketsDocument; +export function graphql(source: "\n query AllInterestRateBrackets {\n interestRateBrackets(orderBy: rate) {\n collateral {\n collIndex\n }\n rate\n totalDebt\n }\n }\n"): typeof import('./graphql').AllInterestRateBracketsDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/frontend/app/src/graphql/graphql.ts b/frontend/app/src/graphql/graphql.ts index 088c1a10f..91958be5f 100644 --- a/frontend/app/src/graphql/graphql.ts +++ b/frontend/app/src/graphql/graphql.ts @@ -2190,12 +2190,10 @@ export type TroveByIdQueryVariables = Exact<{ export type TroveByIdQuery = { __typename?: 'Query', trove?: { __typename?: 'Trove', id: string, borrower: string, closedAt?: bigint | null, createdAt: bigint, debt: bigint, deposit: bigint, interestRate: bigint, mightBeLeveraged: boolean, stake: bigint, status: TroveStatus, troveId: string, updatedAt: bigint, collateral: { __typename?: 'Collateral', id: string, minCollRatio: bigint, collIndex: number, token: { __typename?: 'Token', symbol: string, name: string } }, interestBatch?: { __typename?: 'InterestBatch', id: string, annualInterestRate: bigint, annualManagementFee: bigint, batchManager: string } | null } | null }; -export type StabilityPoolQueryVariables = Exact<{ - id: Scalars['ID']['input']; -}>; +export type StabilityPoolsQueryVariables = Exact<{ [key: string]: never; }>; -export type StabilityPoolQuery = { __typename?: 'Query', stabilityPool?: { __typename?: 'StabilityPool', id: string, totalDeposited: bigint } | null }; +export type StabilityPoolsQuery = { __typename?: 'Query', stabilityPools: Array<{ __typename?: 'StabilityPool', id: string, totalDeposited: bigint }> }; export type StabilityPoolDepositFragmentFragment = { __typename?: 'StabilityPoolDeposit', id: string, deposit: bigint, depositor: string, collateral: { __typename?: 'Collateral', collIndex: number }, snapshot: { __typename?: 'StabilityPoolDepositSnapshot', B: bigint, P: bigint, S: bigint, epoch: bigint, scale: bigint } } & { ' $fragmentName'?: 'StabilityPoolDepositFragmentFragment' }; @@ -2227,12 +2225,10 @@ export type InterestBatchQueryVariables = Exact<{ export type InterestBatchQuery = { __typename?: 'Query', interestBatch?: { __typename?: 'InterestBatch', batchManager: string, debt: bigint, coll: bigint, annualInterestRate: bigint, annualManagementFee: bigint, collateral: { __typename?: 'Collateral', collIndex: number } } | null }; -export type InterestRateBracketsQueryVariables = Exact<{ - collId: Scalars['String']['input']; -}>; +export type AllInterestRateBracketsQueryVariables = Exact<{ [key: string]: never; }>; -export type InterestRateBracketsQuery = { __typename?: 'Query', interestRateBrackets: Array<{ __typename?: 'InterestRateBracket', rate: bigint, totalDebt: bigint }> }; +export type AllInterestRateBracketsQuery = { __typename?: 'Query', interestRateBrackets: Array<{ __typename?: 'InterestRateBracket', rate: bigint, totalDebt: bigint, collateral: { __typename?: 'Collateral', collIndex: number } }> }; export type GovernanceInitiativesQueryVariables = Exact<{ [key: string]: never; }>; @@ -2399,14 +2395,14 @@ export const TroveByIdDocument = new TypedDocumentString(` } } `) as unknown as TypedDocumentString; -export const StabilityPoolDocument = new TypedDocumentString(` - query StabilityPool($id: ID!) { - stabilityPool(id: $id) { +export const StabilityPoolsDocument = new TypedDocumentString(` + query StabilityPools { + stabilityPools { id totalDeposited } } - `) as unknown as TypedDocumentString; + `) as unknown as TypedDocumentString; export const StabilityPoolDepositsByAccountDocument = new TypedDocumentString(` query StabilityPoolDepositsByAccount($account: Bytes!) { stabilityPoolDeposits(where: {depositor: $account, deposit_gt: 0}) { @@ -2468,14 +2464,17 @@ export const InterestBatchDocument = new TypedDocumentString(` } } `) as unknown as TypedDocumentString; -export const InterestRateBracketsDocument = new TypedDocumentString(` - query InterestRateBrackets($collId: String!) { - interestRateBrackets(where: {collateral: $collId}, orderBy: rate) { +export const AllInterestRateBracketsDocument = new TypedDocumentString(` + query AllInterestRateBrackets { + interestRateBrackets(orderBy: rate) { + collateral { + collIndex + } rate totalDebt } } - `) as unknown as TypedDocumentString; + `) as unknown as TypedDocumentString; export const GovernanceInitiativesDocument = new TypedDocumentString(` query GovernanceInitiatives { governanceInitiatives { diff --git a/frontend/app/src/liquity-utils.ts b/frontend/app/src/liquity-utils.ts index 4afd6d669..ecb683e9b 100644 --- a/frontend/app/src/liquity-utils.ts +++ b/frontend/app/src/liquity-utils.ts @@ -207,7 +207,6 @@ export function useStakePosition(address: null | Address) { refetchInterval: DATA_REFRESH_INTERVAL, select: ([depositResult, totalStakedResult]): PositionStake | null => { if (depositResult.status === "failure" || totalStakedResult.status === "failure") { - console.log("useStakePosition", depositResult.error, totalStakedResult.error); return null; } const deposit = dnum18(depositResult.result); diff --git a/frontend/app/src/subgraph-hooks.ts b/frontend/app/src/subgraph-hooks.ts index b514e6762..3393e9956 100644 --- a/frontend/app/src/subgraph-hooks.ts +++ b/frontend/app/src/subgraph-hooks.ts @@ -15,17 +15,17 @@ import { isAddress, shortenAddress } from "@liquity2/uikit"; import { useQuery } from "@tanstack/react-query"; import * as dn from "dnum"; import { + AllInterestRateBracketsQuery, BorrowerInfoQuery, GovernanceInitiatives, GovernanceStats, GovernanceUser, graphQuery, InterestBatchQuery, - InterestRateBracketsQuery, StabilityPoolDepositQuery, StabilityPoolDepositsByAccountQuery, StabilityPoolEpochScaleQuery, - StabilityPoolQuery, + StabilityPoolsQuery, TroveByIdQuery, TrovesByAccountQuery, } from "./subgraph-queries"; @@ -292,30 +292,42 @@ export function useStabilityPoolDeposit( } export function useStabilityPool( - collIndex?: number, + collIndex?: null | number, options?: Options, ) { let queryFn = async () => { - const { stabilityPool } = await graphQuery( - StabilityPoolQuery, - { id: `${collIndex}` }, + const { stabilityPools } = await graphQuery( + StabilityPoolsQuery, ); - return { + return stabilityPools.map((stabilityPool) => ({ + collIndex: parseInt(stabilityPool.id, 10), apr: dnum18(0), - totalDeposited: dnum18(stabilityPool?.totalDeposited ?? 0), - }; + totalDeposited: dnum18(stabilityPool.totalDeposited), + })); }; if (DEMO_MODE) { - queryFn = async () => ({ - apr: dnum18(0), - totalDeposited: dnum18(0), - }); + queryFn = async () => + Array.from({ length: 10 }, (_, collIndex) => ({ + collIndex, + apr: dnum18(0), + totalDeposited: dnum18(0), + })); } return useQuery({ - queryKey: ["StabilityPool", collIndex], + queryKey: ["StabilityPool"], queryFn, + select: (pools) => { + if (typeof collIndex !== "number") { + return null; + } + const pool = pools.find((pool) => pool.collIndex === collIndex); + if (pool === undefined) { + throw new Error(`Stability pool not found: ${collIndex}`); + } + return pool; + }, ...prepareOptions(options), }); } @@ -379,27 +391,28 @@ export function useInterestRateBrackets( collIndex: null | CollIndex, options?: Options, ) { - let queryFn = async () => { - if (collIndex === null) return []; - const { interestRateBrackets } = await graphQuery( - InterestRateBracketsQuery, - { collId: String(collIndex) }, - ); - return [...interestRateBrackets] - .sort((a, b) => (a.rate > b.rate ? 1 : -1)) - .map((bracket) => ({ - rate: dnum18(bracket.rate), - totalDebt: dnum18(bracket.totalDebt), - })); - }; + let queryFn = async () => ( + (await graphQuery(AllInterestRateBracketsQuery)).interestRateBrackets + ); if (DEMO_MODE) { queryFn = async () => []; } return useQuery({ - queryKey: ["InterestRateBrackets", collIndex], + queryKey: ["AllInterestRateBrackets"], queryFn, + select: (brackets) => { + // only filter by collIndex in the select() + // so that we can query all the brackets at once + return brackets + .filter((bracket) => bracket.collateral.collIndex === collIndex) + .sort((a, b) => (a.rate > b.rate ? 1 : -1)) + .map((bracket) => ({ + rate: dnum18(bracket.rate), + totalDebt: dnum18(bracket.totalDebt), + })); + }, ...prepareOptions(options), }); } diff --git a/frontend/app/src/subgraph-queries.ts b/frontend/app/src/subgraph-queries.ts index 7b48b8617..04c48d92f 100644 --- a/frontend/app/src/subgraph-queries.ts +++ b/frontend/app/src/subgraph-queries.ts @@ -149,9 +149,9 @@ export const TroveByIdQuery = graphql(` } `); -export const StabilityPoolQuery = graphql(` - query StabilityPool($id: ID!) { - stabilityPool(id: $id) { +export const StabilityPoolsQuery = graphql(` + query StabilityPools { + stabilityPools { id totalDeposited } @@ -241,9 +241,12 @@ export const InterestBatchQuery = graphql(` } `); -export const InterestRateBracketsQuery = graphql(` - query InterestRateBrackets($collId: String!) { - interestRateBrackets(where: { collateral: $collId }, orderBy: rate) { +export const AllInterestRateBracketsQuery = graphql(` + query AllInterestRateBrackets { + interestRateBrackets(orderBy: rate) { + collateral { + collIndex + } rate totalDebt }