From bc36caf1bdb885c20ab52c9d8f38598f349cf2a1 Mon Sep 17 00:00:00 2001 From: nijoe1 Date: Wed, 2 Apr 2025 21:33:19 +0300 Subject: [PATCH 1/2] feat: new hook to get total stakes for a round application --- .../hooks/useGetApplicationStakes.ts | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 packages/grant-explorer/src/features/round/ViewProjectDetails/hooks/useGetApplicationStakes.ts diff --git a/packages/grant-explorer/src/features/round/ViewProjectDetails/hooks/useGetApplicationStakes.ts b/packages/grant-explorer/src/features/round/ViewProjectDetails/hooks/useGetApplicationStakes.ts new file mode 100644 index 0000000000..31d1b924e1 --- /dev/null +++ b/packages/grant-explorer/src/features/round/ViewProjectDetails/hooks/useGetApplicationStakes.ts @@ -0,0 +1,93 @@ +import { useQuery } from "@tanstack/react-query"; +import { gql } from "graphql-request"; + +const endpoint = "https://indexer.hyperindex.xyz/98cb471/v1/graphql"; + +const getStakesQuery = gql` + query getStakes($chainId: numeric!, $poolId: numeric!, $recipient: String!) { + TokenLock_Locked( + where: { + chainId: { _eq: $chainId } + poolId: { _eq: $poolId } + recipient: { _eq: $recipient } + } + ) { + amount + chainId + poolId + recipient + sender + } + } +`; + +export const useGetApplicationStakes = ( + chainId: number, + poolId: number, + recipient: string, + isStakableRound: boolean +) => { + const query = useQuery({ + enabled: isStakableRound, + queryKey: ["getApplicationStakes", chainId, poolId, recipient], + queryFn: () => getApplicationStakes(chainId, poolId, recipient), + }); + + return { + data: query.data, + isLoading: query.isLoading, + isError: query.isError, + error: query.error, + refetch: query.refetch, + }; +}; + +const GET = async (chainId: number, poolId: number, recipient: string) => { + const response = await fetch(endpoint, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + query: getStakesQuery, + variables: { chainId, poolId, recipient }, + }), + }); + + if (!response.ok) { + const errorData = await response.json(); + throw new Error( + `Error: ${response.status} - ${errorData.message || "Unknown error"}` + ); + } + + return response.json(); +}; + +interface ApplicationStake { + amount: string; + chainId: string; + poolId: string; + recipient: string; + sender: string; +} + +export async function getApplicationStakes( + chainId: number, + poolId: number, + recipient: string +): Promise { + try { + const response = (await GET(chainId, poolId, recipient)).data + .TokenLock_Locked as ApplicationStake[]; + const totalStakes = response.reduce( + (acc, stake) => acc + Number(stake.amount), + 0 + ); + + return (totalStakes / 10 ** 18).toFixed(3); + } catch (error) { + console.error("Error fetching pool info and stakes:", error); + throw error; + } +} From 9a00c816cda6ccb7743704725a03766ac0821cd6 Mon Sep 17 00:00:00 2001 From: nijoe1 Date: Wed, 2 Apr 2025 21:33:54 +0300 Subject: [PATCH 2/2] chore: integrate hook to display staked amount in application view page --- .../ViewProjectDetails/ViewProjectDetails.tsx | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/packages/grant-explorer/src/features/round/ViewProjectDetails/ViewProjectDetails.tsx b/packages/grant-explorer/src/features/round/ViewProjectDetails/ViewProjectDetails.tsx index 31527c64b5..57ae451e3c 100644 --- a/packages/grant-explorer/src/features/round/ViewProjectDetails/ViewProjectDetails.tsx +++ b/packages/grant-explorer/src/features/round/ViewProjectDetails/ViewProjectDetails.tsx @@ -33,7 +33,8 @@ import { ProjectLogo, StakingBannerAndModal, } from "./components"; - +import { useGetApplicationStakes } from "./hooks/useGetApplicationStakes"; +import { useIsStakable } from "./components/StakingBannerAndModal/hooks/useIsStakable"; export default function ViewProjectDetails() { const [selectedTab, setSelectedTab] = useState(0); @@ -58,6 +59,11 @@ export default function ViewProjectDetails() { applicationId = paramApplicationId; } + const isStakableRound = useIsStakable({ + chainId: Number(chainId), + roundId, + }); + const { data: application, error, @@ -70,6 +76,13 @@ export default function ViewProjectDetails() { }, dataLayer ); + const { data: totalStaked } = useGetApplicationStakes( + Number(chainId), + Number(roundId), + application?.anchorAddress ?? "", + isStakableRound + ); + const { round: roundDetails } = useRoundById(Number(chainId), roundId); const projectToRender = application && mapApplicationToProject(application); @@ -218,12 +231,15 @@ export default function ViewProjectDetails() { )} -
+
+ {totalStaked && Number(totalStaked) > 0 && ( + + )}
@@ -275,3 +291,40 @@ export default function ViewProjectDetails() { ); } + +const StakedAmountCard = ({ totalStaked }: { totalStaked: number }) => { + return ( +
+
+ + + +
+
+
+
+ {totalStaked} +
+
+ GTC +
+
+
+ Total staked +
+
+
+ ); +};