Skip to content

Commit

Permalink
Merge pull request #180 from privacy-scaling-explorations/feat/fetch-…
Browse files Browse the repository at this point in the history
…poll-subgraph

feat: fetch poll data from subgraph
  • Loading branch information
0xmad authored Jun 28, 2024
2 parents 13ba63a + ce6c9dc commit a64329c
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 11 deletions.
52 changes: 41 additions & 11 deletions src/contexts/Maci.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export const MaciProvider: React.FC<MaciProviderProps> = ({ children }: MaciProv
{ enabled: Boolean(maciPubKey && config.maciSubgraphUrl) },
);

const poll = api.maci.poll.useQuery(undefined, { enabled: Boolean(config.maciSubgraphUrl) });

const attestations = api.voters.approvedAttestations.useQuery({
address,
});
Expand All @@ -70,6 +72,15 @@ export const MaciProvider: React.FC<MaciProviderProps> = ({ children }: MaciProv
}
}, [setMaciPrivKey, setMaciPubKey]);

// on load we fetch the data from the poll
useEffect(() => {
if (poll.data) {
return;
}

poll.refetch().catch(console.error);
}, [poll]);

const generateKeypair = useCallback(async () => {
// if we are not connected then do not generate the key pair
if (!address) {
Expand Down Expand Up @@ -98,15 +109,13 @@ export const MaciProvider: React.FC<MaciProviderProps> = ({ children }: MaciProv
setIsLoading(true);

try {
const { stateIndex: index, hash } = await signup({
const { stateIndex: index } = await signup({
maciPubKey,
maciAddress: config.maciAddress!,
sgDataArg: attestationId,
signer,
});

console.log(`Signup transaction hash: ${hash}`);

if (index) {
setIsRegistered(true);
setStateIndex(index);
Expand Down Expand Up @@ -234,7 +243,28 @@ export const MaciProvider: React.FC<MaciProviderProps> = ({ children }: MaciProv

setIsLoading(true);

Promise.all([
// if we have the subgraph url then it means we can get the poll data through there
if (config.maciSubgraphUrl) {
if (!poll.data) {
setIsLoading(false);
return;
}

const { isStateAqMerged, id } = poll.data;

setPollData(poll.data);

if (isStateAqMerged) {
fetch(`${config.tallyUrl}/tally-${id}.json`)
.then((res) => res.json() as Promise<TallyData>)
.then((res) => {
setTallyData(res);
})
.catch(() => undefined);
}

setIsLoading(false);
} else {
getPoll({
maciAddress: config.maciAddress!,
signer,
Expand All @@ -255,13 +285,13 @@ export const MaciProvider: React.FC<MaciProviderProps> = ({ children }: MaciProv
setTallyData(res);
})
.catch(() => undefined);
}),
])
.catch(console.error)
.finally(() => {
setIsLoading(false);
});
}, [signer, votingEndsAt, setIsLoading, setTallyData, setPollData]);
})
.catch(console.error)
.finally(() => {
setIsLoading(false);
});
}
}, [signer, votingEndsAt, setIsLoading, setTallyData, setPollData, poll.data]);

const value = useMemo(
() => ({
Expand Down
2 changes: 2 additions & 0 deletions src/server/api/routers/maci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { PubKey } from "maci-domainobjs";
import { z } from "zod";

import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
import { fetchPoll } from "~/utils/fetchPoll";
import { fetchUser } from "~/utils/fetchUser";

export const maciRouter = createTRPCRouter({
user: publicProcedure
.input(z.object({ publicKey: z.string() }))
.query(async ({ input }) => fetchUser(PubKey.deserialize(input.publicKey).rawPubKey)),
poll: publicProcedure.query(async () => fetchPoll()),
});
58 changes: 58 additions & 0 deletions src/utils/fetchPoll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { IGetPollData } from "maci-cli/sdk";

import { config } from "~/config";

import { createCachedFetch } from "./fetch";

const cachedFetch = createCachedFetch({ ttl: 1000 * 60 * 10 });

interface Poll {
pollId: string;
createdAt: string;
duration: string;
stateRoot: string;
messageRoot: string;
numSignups: string;
id: string;
}

export interface GraphQLResponse {
data?: {
polls: Poll[];
};
}

const PollQuery = `
query Poll {
polls(orderBy: createdAt, orderDirection: desc, first: 1) {
pollId
duration
createdAt
stateRoot
messageRoot
numSignups
id
}
}
`;

export async function fetchPoll(): Promise<IGetPollData> {
const poll = (
await cachedFetch<{ polls: Poll[] }>(config.maciSubgraphUrl, {
method: "POST",
body: JSON.stringify({
query: PollQuery,
}),
}).then((response: GraphQLResponse) => response.data?.polls)
)?.at(0);

// cast this to a IGetPollData object so that we can deal with one object only in MACIContext
return {
isStateAqMerged: !!poll?.messageRoot,
id: poll?.pollId ?? 0,
duration: poll?.duration ?? 0,
deployTime: poll?.createdAt ?? 0,
numSignups: poll?.numSignups ?? 0,
address: poll?.id ?? "",
};
}

0 comments on commit a64329c

Please sign in to comment.