From a53054fbe92137af345b7568b63bd70f461de858 Mon Sep 17 00:00:00 2001 From: keating Date: Mon, 18 Dec 2023 18:27:11 -0500 Subject: [PATCH] Cleanup and format --- codegen.ts | 14 +-- components/ProposalRow.tsx | 15 +-- graphql/aggregator.graphql | 8 +- graphql/generated/graphql.tsx | 163 +++++++++++++++++++------------- graphql/governor.graphql | 8 +- hooks/useProposals.ts | 169 +++++++++++----------------------- pages/_app.tsx | 42 ++++----- util/constants.ts | 6 +- 8 files changed, 206 insertions(+), 219 deletions(-) diff --git a/codegen.ts b/codegen.ts index 7510139..2690810 100644 --- a/codegen.ts +++ b/codegen.ts @@ -1,15 +1,17 @@ - import type { CodegenConfig } from '@graphql-codegen/cli'; const config: CodegenConfig = { overwrite: true, - schema: ["https://subgraph.satsuma-prod.com/7ae15f9faae2/scopelift/l2-flexible-voting-governor-goerli/api", "https://subgraph.satsuma-prod.com/7ae15f9faae2/scopelift/l2-flexible-voting-vote-aggregator/api"], - documents: "./graphql/**/(!(*.d)).graphql", + schema: [ + 'https://subgraph.satsuma-prod.com/7ae15f9faae2/scopelift/l2-flexible-voting-governor-goerli/api', + 'https://subgraph.satsuma-prod.com/7ae15f9faae2/scopelift/l2-flexible-voting-vote-aggregator/api', + ], + documents: './graphql/**/(!(*.d)).graphql', generates: { - "./graphql/generated/graphql.tsx": { - plugins: ["typescript", "typescript-operations", "typescript-react-query"] + './graphql/generated/graphql.tsx': { + plugins: ['typescript', 'typescript-operations', 'typescript-react-query'], }, - } + }, }; export default config; diff --git a/components/ProposalRow.tsx b/components/ProposalRow.tsx index 7194281..9fee195 100644 --- a/components/ProposalRow.tsx +++ b/components/ProposalRow.tsx @@ -24,9 +24,8 @@ export default function ProposalRow({ const { l2, daoLogo } = useConfig(); const { data: tokenInfo } = useTokenInfo(); - console.log(votes.l1) - // const totalVotesL1 = votes.l1.forVotes + votes.l1.againstVotes + votes.l1.abstainVotes; - const totalVotesL1 = BigInt(0) + console.log(votes.l1); + const totalVotesL1 = votes.l1.forVotes + votes.l1.againstVotes + votes.l1.abstainVotes; const totalVotesNotBridged = votes.l2NotBridged ? votes.l2NotBridged.forVotes + votes.l2NotBridged.againstVotes + @@ -74,10 +73,7 @@ export default function ProposalRow({ >
@@ -141,10 +137,7 @@ export default function ProposalRow({
= Maybe; export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { [_ in K]?: never }; -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - -function fetcher(endpoint: string, requestInit: RequestInit, query: string, variables?: TVariables) { +export type MakeEmpty = { + [_ in K]?: never; +}; +export type Incremental = + | T + | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + +function fetcher( + endpoint: string, + requestInit: RequestInit, + query: string, + variables?: TVariables +) { return async (): Promise => { const res = await fetch(endpoint, { method: 'POST', @@ -24,23 +33,23 @@ function fetcher(endpoint: string, requestInit: RequestInit, } return json.data; - } + }; } /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - BigDecimal: { input: any; output: any; } - BigInt: { input: any; output: any; } - Bytes: { input: any; output: any; } + ID: { input: string; output: string }; + String: { input: string; output: string }; + Boolean: { input: boolean; output: boolean }; + Int: { input: number; output: number }; + Float: { input: number; output: number }; + BigDecimal: { input: any; output: any }; + BigInt: { input: any; output: any }; + Bytes: { input: any; output: any }; /** * 8 bytes signed integer * */ - Int8: { input: any; output: any; } + Int8: { input: any; output: any }; }; export type BlockChangedFilter = { @@ -194,13 +203,13 @@ export enum BridgedVote_OrderBy { TransactionHash = 'transactionHash', VoteAbstain = 'voteAbstain', VoteAgainst = 'voteAgainst', - VoteFor = 'voteFor' + VoteFor = 'voteFor', } /** Defines the order direction, either ascending or descending */ export enum OrderDirection { Asc = 'asc', - Desc = 'desc' + Desc = 'desc', } export type Proposal = { @@ -393,7 +402,7 @@ export enum Proposal_OrderBy { Signatures = 'signatures', StartBlock = 'startBlock', TransactionHash = 'transactionHash', - Values = 'values' + Values = 'values', } export type Query = { @@ -406,19 +415,16 @@ export type Query = { proposals: Array; }; - export type Query_MetaArgs = { block?: InputMaybe; }; - export type QueryBridgedVoteArgs = { block?: InputMaybe; id: Scalars['ID']['input']; subgraphError?: _SubgraphErrorPolicy_; }; - export type QueryBridgedVotesArgs = { block?: InputMaybe; first?: InputMaybe; @@ -429,14 +435,12 @@ export type QueryBridgedVotesArgs = { where?: InputMaybe; }; - export type QueryProposalArgs = { block?: InputMaybe; id: Scalars['ID']['input']; subgraphError?: _SubgraphErrorPolicy_; }; - export type QueryProposalsArgs = { block?: InputMaybe; first?: InputMaybe; @@ -457,19 +461,16 @@ export type Subscription = { proposals: Array; }; - export type Subscription_MetaArgs = { block?: InputMaybe; }; - export type SubscriptionBridgedVoteArgs = { block?: InputMaybe; id: Scalars['ID']['input']; subgraphError?: _SubgraphErrorPolicy_; }; - export type SubscriptionBridgedVotesArgs = { block?: InputMaybe; first?: InputMaybe; @@ -480,14 +481,12 @@ export type SubscriptionBridgedVotesArgs = { where?: InputMaybe; }; - export type SubscriptionProposalArgs = { block?: InputMaybe; id: Scalars['ID']['input']; subgraphError?: _SubgraphErrorPolicy_; }; - export type SubscriptionProposalsArgs = { block?: InputMaybe; first?: InputMaybe; @@ -529,7 +528,7 @@ export enum _SubgraphErrorPolicy_ { /** Data will be returned even if the subgraph has indexing errors */ Allow = 'allow', /** If the subgraph has indexing errors, data will be omitted. The default. */ - Deny = 'deny' + Deny = 'deny', } export type L2ProposalsQueryVariables = Exact<{ @@ -538,8 +537,31 @@ export type L2ProposalsQueryVariables = Exact<{ offset: Scalars['Int']['input']; }>; - -export type L2ProposalsQuery = { __typename?: 'Query', proposals: Array<{ __typename?: 'Proposal', id: string, proposalId: any, proposer: any, startBlock: any, endBlock: any, description: string, governorAddress: any, canceled: boolean, transactionHash: any, blockNumber: any, blockTimestamp: any, bridgedVote?: { __typename?: 'BridgedVote', voteAgainst: any, voteFor: any, voteAbstain: any, blockNumber: any, blockTimestamp: any } | null }> }; +export type L2ProposalsQuery = { + __typename?: 'Query'; + proposals: Array<{ + __typename?: 'Proposal'; + id: string; + proposalId: any; + proposer: any; + startBlock: any; + endBlock: any; + description: string; + governorAddress: any; + canceled: boolean; + transactionHash: any; + blockNumber: any; + blockTimestamp: any; + bridgedVote?: { + __typename?: 'BridgedVote'; + voteAgainst: any; + voteFor: any; + voteAbstain: any; + blockNumber: any; + blockTimestamp: any; + } | null; + }>; +}; export type ProposalsQueryVariables = Exact<{ governor: Scalars['Bytes']['input']; @@ -547,10 +569,23 @@ export type ProposalsQueryVariables = Exact<{ offset: Scalars['Int']['input']; }>; - -export type ProposalsQuery = { __typename?: 'Query', proposals: Array<{ __typename?: 'Proposal', id: string, proposalId: any, proposer: any, startBlock: any, endBlock: any, description: string, governorAddress: any, canceled: boolean, transactionHash: any, blockNumber: any, blockTimestamp: any }> }; - - +export type ProposalsQuery = { + __typename?: 'Query'; + proposals: Array<{ + __typename?: 'Proposal'; + id: string; + proposalId: any; + proposer: any; + startBlock: any; + endBlock: any; + description: string; + governorAddress: any; + canceled: boolean; + transactionHash: any; + blockNumber: any; + blockTimestamp: any; + }>; +}; export const L2ProposalsDocument = ` query L2Proposals($governor: Bytes!, $pageSize: Int!, $offset: Int!) { @@ -583,20 +618,22 @@ export const L2ProposalsDocument = ` } `; -export const useL2ProposalsQuery = < - TData = L2ProposalsQuery, - TError = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - variables: L2ProposalsQueryVariables, - options?: UseQueryOptions - ) => { - - return useQuery( - ['L2Proposals', variables], - fetcher(dataSource.endpoint, dataSource.fetchParams || {}, L2ProposalsDocument, variables), - options - )}; +export const useL2ProposalsQuery = ( + dataSource: { endpoint: string; fetchParams?: RequestInit }, + variables: L2ProposalsQueryVariables, + options?: UseQueryOptions +) => { + return useQuery( + ['L2Proposals', variables], + fetcher( + dataSource.endpoint, + dataSource.fetchParams || {}, + L2ProposalsDocument, + variables + ), + options + ); +}; export const ProposalsDocument = ` query Proposals($governor: Bytes!, $pageSize: Int!, $offset: Int!) { @@ -622,17 +659,19 @@ export const ProposalsDocument = ` } `; -export const useProposalsQuery = < - TData = ProposalsQuery, - TError = unknown - >( - dataSource: { endpoint: string, fetchParams?: RequestInit }, - variables: ProposalsQueryVariables, - options?: UseQueryOptions - ) => { - - return useQuery( - ['Proposals', variables], - fetcher(dataSource.endpoint, dataSource.fetchParams || {}, ProposalsDocument, variables), - options - )}; +export const useProposalsQuery = ( + dataSource: { endpoint: string; fetchParams?: RequestInit }, + variables: ProposalsQueryVariables, + options?: UseQueryOptions +) => { + return useQuery( + ['Proposals', variables], + fetcher( + dataSource.endpoint, + dataSource.fetchParams || {}, + ProposalsDocument, + variables + ), + options + ); +}; diff --git a/graphql/governor.graphql b/graphql/governor.graphql index 17fe539..5c02fbb 100644 --- a/graphql/governor.graphql +++ b/graphql/governor.graphql @@ -1,5 +1,11 @@ query Proposals($governor: Bytes!, $pageSize: Int!, $offset: Int!) { - proposals(first: $pageSize, orderBy: blockTimestamp, orderDirection: desc, where: {governorAddress: $governor}, skip: $offset) { + proposals( + first: $pageSize + orderBy: blockTimestamp + orderDirection: desc + where: { governorAddress: $governor } + skip: $offset + ) { id proposalId proposer diff --git a/hooks/useProposals.ts b/hooks/useProposals.ts index 09966c4..6f232e4 100644 --- a/hooks/useProposals.ts +++ b/hooks/useProposals.ts @@ -3,8 +3,8 @@ import { parseAbiItem } from 'viem'; import { useConfig } from '@/hooks/useConfig'; import useSWR from 'swr'; -import {useProposalsQuery, useL2ProposalsQuery} from "@/graphql/generated/graphql" -import {AGGREGATOR_SUBGRAPH_URL, GOVERNOR_SUBGRAPH_URL} from "@/util/constants" +import { useProposalsQuery, useL2ProposalsQuery } from '@/graphql/generated/graphql'; +import { AGGREGATOR_SUBGRAPH_URL, GOVERNOR_SUBGRAPH_URL } from '@/util/constants'; export type Proposal = { id: string; @@ -34,108 +34,20 @@ export type Proposal = { }; }; -const createFetcher = - ({ - publicClient, - deployBlock, - address, - }: { - publicClient: PublicClient; - deployBlock: bigint; - address: `0x${string}`; - }) => - async () => { - // 1. Get events - // 2. Get voting weight - // 3. Calculate opened or closed - // TODO: Make these concurrent - - const createdLogs = await publicClient.getLogs({ - address, - event: parseAbiItem( - 'event ProposalCreated(uint256, address, address[], uint256[], string[],bytes[], uint256, uint256, string)' - ), - fromBlock: deployBlock, - }); - // Remove this call - const canceledLogs = await publicClient.getLogs({ - address, - event: parseAbiItem('event ProposalCanceled(uint256 proposalId)'), - fromBlock: deployBlock, - }); - // TODO: ensure sorting is indeed time desc - // Get the latest bridged vote - const voteBridgedLogs = await publicClient.getLogs({ - address, - event: parseAbiItem( - 'event VoteBridged(uint256 indexed proposalId, uint256 againstVotes, uint256 forVotes, uint256 abstainVotes)' - ), - strict: true, - fromBlock: deployBlock, - }); - const canceledProposals = new Map(); - for (const canceledProposal of canceledLogs) { - canceledProposals.set(canceledProposal.args, true); - } - const getProposalVotes = async (proposalId: bigint) => { - return publicClient.readContract({ - address, - abi: [ - parseAbiItem( - 'function proposalVotes(uint256) view returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes)' - ), - ], - functionName: 'proposalVotes', - args: [proposalId], - }); - }; - - return Promise.all( - createdLogs.map(async (event) => { - const args = event.args; - const proposalId = args[0]?.toString() || '0'; - const bridgedVotes = voteBridgedLogs?.find( - (event) => event.args.proposalId?.toString() === proposalId - )?.args; - const proposalVotePromise = getProposalVotes(BigInt(proposalId)); - const blockPromise = publicClient.getBlock({ blockNumber: event.blockNumber }); - const [[againstVotes, forVotes, abstainVotes], eventBlock] = await Promise.all([ - proposalVotePromise, - blockPromise, - ]); - return { - proposalId, - startBlock: args[6]?.toString() || '0', - endBlock: args[7]?.toString() || '0', - description: args[8]?.toString() || '', - isCancelled: Boolean(canceledProposals.get(args[0])), - createdBlock: event.blockNumber, - createdTimestamp: eventBlock.timestamp, - votingPower: 0, - votes: { againstVotes, forVotes, abstainVotes }, - bridgedVotes, - }; - }) - ); - }; - export const useL1Proposals = () => { const { l1 } = useConfig(); - // const publicClient = usePublicClient({ chainId: l1.chain.id }); const { address } = useAccount(); - // const fetcher = createFetcher({ - // publicClient, - // deployBlock: BigInt(l1.deployBlock), - // address: l1.governor, - // }); - // Page size should be dynamic - const {data: queryData, isLoading, error} = useProposalsQuery({endpoint: GOVERNOR_SUBGRAPH_URL}, {pageSize: 1000, governor: l1.governor, offset: 0}) - // Add voting data, but sort of working - console.log(queryData) - console.log(isLoading) - - // const { data: proposalData, error, isLoading } = useSWR(`fetchL1Proposals-${daoId}`, fetcher); + // Page size should be dynamic + const { + data: queryData, + isLoading, + error, + } = useProposalsQuery( + { endpoint: GOVERNOR_SUBGRAPH_URL }, + { pageSize: 1000, governor: l1.governor, offset: 0 } + ); + const { data: votingPower } = useContractReads({ contracts: queryData?.proposals.map((proposal) => { return { @@ -151,7 +63,11 @@ export const useL1Proposals = () => { }; }), }); - const {data: proposalVoteData, isLoading: proposalVoteIsLoading, error: proposalVoteError} = useContractReads({ + const { + data: proposalVoteData, + isLoading: proposalVoteIsLoading, + error: proposalVoteError, + } = useContractReads({ contracts: queryData?.proposals.map((proposal) => { return { address: l1.governor, @@ -165,8 +81,7 @@ export const useL1Proposals = () => { chainId: l1.chain.id, }; }), - }) - console.log(queryData?.proposals) + }); const { data: proposalState, @@ -185,20 +100,23 @@ export const useL1Proposals = () => { }); const data = queryData?.proposals?.map((proposal, i) => { - const vote = proposalVoteData?.[i]?.result as [bigint, bigint, bigint] | undefined + const vote = proposalVoteData?.[i]?.result as [bigint, bigint, bigint] | undefined; return { status: proposalState?.[i].result as number, - votes: { againstVotes: vote?.[0] as bigint || BigInt(0), forVotes: vote?.[1] || BigInt(0), abstainVotes: vote?.[2] || BigInt(0)}, + votes: { + againstVotes: (vote?.[0] as bigint) || BigInt(0), + forVotes: vote?.[1] || BigInt(0), + abstainVotes: vote?.[2] || BigInt(0), + }, tallyLink: `${l1.tallyGovernorDomain}/proposal/${proposal.proposalId}`, - ...proposal, + ...proposal, votingPower: (votingPower?.[i]?.result as bigint) || BigInt(0), }; }); - console.log(data) return { data, - isLoading: isLoading || proposalStateIsLoading, - error: error || proposalStateError, + isLoading: isLoading || proposalVoteIsLoading || proposalStateIsLoading, + error: error || proposalVoteError || proposalStateError, }; }; @@ -207,9 +125,20 @@ export const useL2Proposals = ( ) => { const { l2, l1 } = useConfig(); const { address } = useAccount(); - const {data: queryData, isLoading, error} = useL2ProposalsQuery({endpoint: AGGREGATOR_SUBGRAPH_URL}, {pageSize: 1000, governor: l2.voteAggregator, offset: 0}) + const { + data: queryData, + isLoading, + error, + } = useL2ProposalsQuery( + { endpoint: AGGREGATOR_SUBGRAPH_URL }, + { pageSize: 1000, governor: l2.voteAggregator, offset: 0 } + ); - const {data: proposalVoteData, isLoading: proposalVoteIsLoading, error: proposalVoteError} = useContractReads({ + const { + data: proposalVoteData, + isLoading: proposalVoteIsLoading, + error: proposalVoteError, + } = useContractReads({ contracts: queryData?.proposals.map((proposal) => { return { address: l1.governor, @@ -223,7 +152,7 @@ export const useL2Proposals = ( chainId: l1.chain.id, }; }), - }) + }); const { data: votingPower } = useContractReads({ contracts: queryData?.proposals?.map((proposal) => { @@ -246,11 +175,15 @@ export const useL2Proposals = ( }); const data = queryData?.proposals?.map((proposal, i) => { - const vote = proposalVoteData?.[i]?.result as [bigint, bigint, bigint] | undefined + const vote = proposalVoteData?.[i]?.result as [bigint, bigint, bigint] | undefined; return { tallyLink: `${l2.tallyGovernorDomain}/proposal/${proposal.proposalId}`, ...proposal, - votes: { againstVotes: vote?.[0] as bigint || BigInt(0), forVotes: vote?.[1] || BigInt(0), abstainVotes: vote?.[2] || BigInt(0)}, + votes: { + againstVotes: (vote?.[0] as bigint) || BigInt(0), + forVotes: vote?.[1] || BigInt(0), + abstainVotes: vote?.[2] || BigInt(0), + }, votingPower: (votingPower?.[i]?.result as bigint) || BigInt(0), }; }); @@ -357,7 +290,13 @@ export const useProposals = () => { votes: { l1: proposal.votes, l2: l2Proposal?.votes, - l2Bridged: l2Proposal?.bridgedVote ? {againstVotes: l2Proposal.bridgedVote.voteAgainst, forVotes: l2Proposal.bridgedVote.voteFor, abstainVotes: l2Proposal.bridgedVote.voteAbstain} : undefined, + l2Bridged: l2Proposal?.bridgedVote + ? { + againstVotes: l2Proposal.bridgedVote.voteAgainst, + forVotes: l2Proposal.bridgedVote.voteFor, + abstainVotes: l2Proposal.bridgedVote.voteAbstain, + } + : undefined, l2NotBridged: l2Proposal ? { forVotes: diff --git a/pages/_app.tsx b/pages/_app.tsx index 9792b75..cbf8b0d 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -2,7 +2,7 @@ import '@/styles/globals.css'; import '@rainbow-me/rainbowkit/styles.css'; import { getDefaultWallets, RainbowKitProvider, lightTheme } from '@rainbow-me/rainbowkit'; import type { AppProps } from 'next/app'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { configureChains, createConfig, WagmiConfig } from 'wagmi'; import { publicProvider } from 'wagmi/providers/public'; import { alchemyProvider } from 'wagmi/providers/alchemy'; @@ -31,28 +31,28 @@ const wagmiConfig = createConfig({ }); function MyApp({ Component, pageProps }: AppProps) { - const queryClient = new QueryClient() + const queryClient = new QueryClient(); return ( - - - - - - - - - - - + + + + + + + + + + + ); } diff --git a/util/constants.ts b/util/constants.ts index 03ba681..ca34435 100644 --- a/util/constants.ts +++ b/util/constants.ts @@ -1,4 +1,6 @@ export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; export const WORMHOLE_NETWORK_TYPE = process.env.WORMHOLE_NETORK_TYPE || 'TESTNET'; -export const GOVERNOR_SUBGRAPH_URL = "https://subgraph.satsuma-prod.com/7ae15f9faae2/scopelift/l2-flexible-voting-governor-goerli/api" -export const AGGREGATOR_SUBGRAPH_URL = "https://subgraph.satsuma-prod.com/7ae15f9faae2/scopelift/l2-flexible-voting-vote-aggregator/api" +export const GOVERNOR_SUBGRAPH_URL = + 'https://subgraph.satsuma-prod.com/7ae15f9faae2/scopelift/l2-flexible-voting-governor-goerli/api'; +export const AGGREGATOR_SUBGRAPH_URL = + 'https://subgraph.satsuma-prod.com/7ae15f9faae2/scopelift/l2-flexible-voting-vote-aggregator/api';