diff --git a/.eslintrc.json b/.eslintrc.json index 63a8e1329..db4f424fc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,7 +3,8 @@ "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", - "prettier" + "prettier", + "plugin:import/recommended" ], "parser": "@typescript-eslint/parser", "plugins": ["@typescript-eslint", "prettier"], diff --git a/.github/workflows/deploy-indexer.yaml b/.github/workflows/deploy-indexer.yaml index 5f61875b0..b54125e17 100644 --- a/.github/workflows/deploy-indexer.yaml +++ b/.github/workflows/deploy-indexer.yaml @@ -4,9 +4,10 @@ on: push: branches: [dev, main] paths: - - "apps/indexer/**/*.ts" - - "apps/api-gateway/**/*.ts" - - "infra/**" + - "apps/indexer/**/*" + - "apps/api-gateway/**/*" + - "infra/**/*" + - "apps/api/**/*" jobs: changes: @@ -22,14 +23,9 @@ jobs: base: ${{ github.ref_name }} filters: | api: - - 'apps/indexer/src/api/**' + - 'apps/api/src/**' indexer: - - 'apps/indexer/src/eventHandlers/**' - - 'apps/indexer/src/indexer/**' - - 'apps/indexer/src/interfaces/**' - - 'apps/indexer/src/lib/**' - - 'apps/indexer/src/*.ts' - - 'apps/indexer/*.ts' + - 'apps/indexer/**/*' get-daos: runs-on: ubuntu-latest diff --git a/.vscode/launch.json b/.vscode/launch.json index 32d0266c6..910d2e473 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -23,16 +23,16 @@ { "type": "node", "request": "launch", - "name": "indexer", + "name": "api", "skipFiles": ["/**"], "runtimeExecutable": "pnpm", - "runtimeArgs": ["run", "serve", "--config", "config/ens.config.ts"], + "runtimeArgs": ["run", "dev:watch"], "env": { "TS_NODE_PROJECT": "${workspaceFolder}/tsconfig.json", - "ENV_FILE": "${workspaceFolder}/apps/indexer/.env" + "ENV_FILE": "${workspaceFolder}/apps/api/.env" }, "outFiles": ["${workspaceFolder}/**/*.js", "!**/node_modules/**"], - "cwd": "${workspaceFolder}/apps/indexer" + "cwd": "${workspaceFolder}/apps/api" } ] } diff --git a/apps/api-gateway/meshrc.ts b/apps/api-gateway/meshrc.ts index 7ff6ac703..2c478e920 100644 --- a/apps/api-gateway/meshrc.ts +++ b/apps/api-gateway/meshrc.ts @@ -19,48 +19,6 @@ export default processConfig( const daoName = key.replace("DAO_API_", ""); return [ - { - name: `graphql_${daoName}`, - handler: { - graphql: { - endpoint: value, - }, - }, - transforms: [ - { - filterSchema: { - filters: [ - "Query.!{accountBalances}", - "Query.!{accountBalance}", - "Query.!{accountPowers}", - "Query.!{accountPower}", - "Query.!{accounts}", - "Query.!{account}", - "Query.!{balanceHistorys}", - "Query.!{balanceHistory}", - "Query.!{daoMetricsDayBucket}", - "Query.!{daoMetricsDayBuckets}", - "Query.!{delegation}", - "Query.!{delegations}", - "Query.!{proposalsOnchains}", - "Query.!{proposalsOnchain}", - "Query.!{tokenPrices}", - "Query.!{tokenPrice}", - "Query.!{tokens}", - "Query.!{token}", - "Query.!{transactions}", - "Query.!{transaction}", - "Query.!{transfers}", - "Query.!{transfer}", - "Query.!{votesOnchain}", - "Query.!{votingPowerHistory}", - // "Query.!{votesOnchains}", TODO: Leave endpoint active for now as it is still used by the [notification bot](https://github.com/blockful/notification-system/blob/main/packages/anticapture-client/queries/votes.graphql) - // 'Query.!{votingPowerHistorys}' TODO: Leave endpoint active for now as it is still used by the notification bot - ], - }, - }, - ], - }, { name: `rest_${daoName}`, handler: { diff --git a/apps/api-gateway/schema.graphql b/apps/api-gateway/schema.graphql index dfb63acf4..ae321a639 100644 --- a/apps/api-gateway/schema.graphql +++ b/apps/api-gateway/schema.graphql @@ -11,10 +11,6 @@ directive @httpOperation(subgraph: String, path: String, operationSpecificHeader directive @transport(subgraph: String, kind: String, location: String, headers: [[String]], queryStringOptions: ObjMap, queryParams: [[String]]) repeatable on SCHEMA type Query { - votingPowerHistorys(where: votingPowerHistoryFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): votingPowerHistoryPage! - votesOnchains(where: votesOnchainFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): votesOnchainPage! - _meta: Meta - """ Get historical delegations for an account, with optional filtering and sorting """ @@ -86,12 +82,6 @@ type Query { """Returns a single proposal by its ID""" proposal(id: String!): proposal_200_response - """Returns the active delegates that did not vote on a given proposal""" - proposalNonVoters(id: String!, skip: NonNegativeInt, limit: PositiveInt = 10, orderDirection: queryInput_proposalNonVoters_orderDirection = desc, addresses: JSON): proposalNonVoters_200_response - - """Returns a paginated list of votes cast on a specific proposal""" - votes(id: String!, skip: NonNegativeInt, limit: PositiveInt = 10, voterAddressIn: JSON, orderBy: queryInput_votes_orderBy = timestamp, orderDirection: queryInput_votes_orderDirection = desc, support: Float): votes_200_response - """TODO""" historicalBalances(address: String!, skip: NonNegativeInt, limit: PositiveInt = 10, orderBy: queryInput_historicalBalances_orderBy = timestamp, orderDirection: queryInput_historicalBalances_orderDirection = desc, fromDate: String, toDate: String, fromValue: String, toValue: String): historicalBalances_200_response @@ -168,13 +158,19 @@ type Query { """Get transfers of a given address""" transfers(address: String!, limit: Float = 10, offset: Float, sortBy: queryInput_transfers_sortBy = timestamp, sortOrder: queryInput_transfers_sortOrder = asc, from: String, to: String, fromDate: Float, toDate: Float, fromValue: String, toValue: String): transfers_200_response + """Returns a paginated list of votes cast on a specific proposal""" + votesByProposalId(id: String!, skip: NonNegativeInt, limit: Float = 10, voterAddressIn: JSON, orderBy: queryInput_votesByProposalId_orderBy = timestamp, orderDirection: queryInput_votesByProposalId_orderDirection = desc, support: Float, fromDate: Float, toDate: Float): votesByProposalId_200_response + + """Get all votes ordered by timestamp or voting power""" + votes(skip: NonNegativeInt, limit: Float = 10, voterAddressIn: JSON, orderBy: queryInput_votes_orderBy = timestamp, orderDirection: queryInput_votes_orderDirection = desc, support: Float, fromDate: Float, toDate: Float): votes_200_response + + """Returns the active delegates that did not vote on a given proposal""" + proposalNonVoters(id: String!, skip: NonNegativeInt, limit: PositiveInt = 10, orderDirection: queryInput_proposalNonVoters_orderDirection = desc, addresses: JSON): proposalNonVoters_200_response + """Returns current governance parameters for this DAO""" dao: dao_200_response - """ - Returns token related metrics for a single metric type. - Available types: TOTAL_SUPPLY, DELEGATED_SUPPLY, CEX_SUPPLY, DEX_SUPPLY, LENDING_SUPPLY, CIRCULATING_SUPPLY, TREASURY - """ + """Returns token related metrics for a single metric type.""" tokenMetrics(metricType: queryInput_tokenMetrics_metricType!, startDate: Float, endDate: Float, orderDirection: queryInput_tokenMetrics_orderDirection = asc, limit: NonNegativeInt = 365, skip: NonNegativeInt): tokenMetrics_200_response """ @@ -215,1242 +211,6 @@ type Query { daos: DAOList! } -""" -The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). -""" -scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") - -scalar BigInt - -type PageInfo { - hasNextPage: Boolean! - hasPreviousPage: Boolean! - startCursor: String - endCursor: String - endDate: String - startDate: String -} - -type ViewPageInfo { - hasNextPage: Boolean! - hasPreviousPage: Boolean! -} - -type Meta { - status: JSON -} - -type token { - id: String! - name: String - decimals: Int! - totalSupply: BigInt! - delegatedSupply: BigInt! - cexSupply: BigInt! - dexSupply: BigInt! - lendingSupply: BigInt! - circulatingSupply: BigInt! - treasury: BigInt! -} - -type tokenPage { - items: [token!]! - pageInfo: PageInfo! - totalCount: Int! -} - -input tokenFilter { - AND: [tokenFilter] - OR: [tokenFilter] - id: String - id_not: String - id_in: [String] - id_not_in: [String] - id_contains: String - id_not_contains: String - id_starts_with: String - id_ends_with: String - id_not_starts_with: String - id_not_ends_with: String - name: String - name_not: String - name_in: [String] - name_not_in: [String] - name_contains: String - name_not_contains: String - name_starts_with: String - name_ends_with: String - name_not_starts_with: String - name_not_ends_with: String - decimals: Int - decimals_not: Int - decimals_in: [Int] - decimals_not_in: [Int] - decimals_gt: Int - decimals_lt: Int - decimals_gte: Int - decimals_lte: Int - totalSupply: BigInt - totalSupply_not: BigInt - totalSupply_in: [BigInt] - totalSupply_not_in: [BigInt] - totalSupply_gt: BigInt - totalSupply_lt: BigInt - totalSupply_gte: BigInt - totalSupply_lte: BigInt - delegatedSupply: BigInt - delegatedSupply_not: BigInt - delegatedSupply_in: [BigInt] - delegatedSupply_not_in: [BigInt] - delegatedSupply_gt: BigInt - delegatedSupply_lt: BigInt - delegatedSupply_gte: BigInt - delegatedSupply_lte: BigInt - cexSupply: BigInt - cexSupply_not: BigInt - cexSupply_in: [BigInt] - cexSupply_not_in: [BigInt] - cexSupply_gt: BigInt - cexSupply_lt: BigInt - cexSupply_gte: BigInt - cexSupply_lte: BigInt - dexSupply: BigInt - dexSupply_not: BigInt - dexSupply_in: [BigInt] - dexSupply_not_in: [BigInt] - dexSupply_gt: BigInt - dexSupply_lt: BigInt - dexSupply_gte: BigInt - dexSupply_lte: BigInt - lendingSupply: BigInt - lendingSupply_not: BigInt - lendingSupply_in: [BigInt] - lendingSupply_not_in: [BigInt] - lendingSupply_gt: BigInt - lendingSupply_lt: BigInt - lendingSupply_gte: BigInt - lendingSupply_lte: BigInt - circulatingSupply: BigInt - circulatingSupply_not: BigInt - circulatingSupply_in: [BigInt] - circulatingSupply_not_in: [BigInt] - circulatingSupply_gt: BigInt - circulatingSupply_lt: BigInt - circulatingSupply_gte: BigInt - circulatingSupply_lte: BigInt - treasury: BigInt - treasury_not: BigInt - treasury_in: [BigInt] - treasury_not_in: [BigInt] - treasury_gt: BigInt - treasury_lt: BigInt - treasury_gte: BigInt - treasury_lte: BigInt -} - -type account { - id: String! - balances(where: accountBalanceFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): accountBalancePage - powers(where: accountPowerFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): accountPowerPage - delegationsFrom(where: delegationFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): delegationPage - delegationsTo(where: delegationFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): delegationPage - sentTransfers(where: transferFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): transferPage - receivedTransfers(where: transferFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): transferPage - proposals(where: proposalsOnchainFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): proposalsOnchainPage - votes(where: votesOnchainFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): votesOnchainPage - delegatedFromBalances(where: accountBalanceFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): accountBalancePage -} - -type accountBalancePage { - items: [accountBalance!]! - pageInfo: PageInfo! - totalCount: Int! -} - -type accountBalance { - accountId: String! - tokenId: String! - balance: BigInt! - delegate: String! - delegatePower: accountPower - account: account - delegateAccount: account - delegatedTo: accountPower - token: token -} - -type accountPower { - accountId: String! - daoId: String! - votingPower: BigInt! - votesCount: Int! - proposalsCount: Int! - delegationsCount: Int! - lastVoteTimestamp: BigInt! - account: account -} - -input accountBalanceFilter { - AND: [accountBalanceFilter] - OR: [accountBalanceFilter] - accountId: String - accountId_not: String - accountId_in: [String] - accountId_not_in: [String] - accountId_contains: String - accountId_not_contains: String - accountId_starts_with: String - accountId_ends_with: String - accountId_not_starts_with: String - accountId_not_ends_with: String - tokenId: String - tokenId_not: String - tokenId_in: [String] - tokenId_not_in: [String] - tokenId_contains: String - tokenId_not_contains: String - tokenId_starts_with: String - tokenId_ends_with: String - tokenId_not_starts_with: String - tokenId_not_ends_with: String - balance: BigInt - balance_not: BigInt - balance_in: [BigInt] - balance_not_in: [BigInt] - balance_gt: BigInt - balance_lt: BigInt - balance_gte: BigInt - balance_lte: BigInt - delegate: String - delegate_not: String - delegate_in: [String] - delegate_not_in: [String] - delegate_contains: String - delegate_not_contains: String - delegate_starts_with: String - delegate_ends_with: String - delegate_not_starts_with: String - delegate_not_ends_with: String -} - -type accountPowerPage { - items: [accountPower!]! - pageInfo: PageInfo! - totalCount: Int! -} - -input accountPowerFilter { - AND: [accountPowerFilter] - OR: [accountPowerFilter] - accountId: String - accountId_not: String - accountId_in: [String] - accountId_not_in: [String] - accountId_contains: String - accountId_not_contains: String - accountId_starts_with: String - accountId_ends_with: String - accountId_not_starts_with: String - accountId_not_ends_with: String - daoId: String - daoId_not: String - daoId_in: [String] - daoId_not_in: [String] - daoId_contains: String - daoId_not_contains: String - daoId_starts_with: String - daoId_ends_with: String - daoId_not_starts_with: String - daoId_not_ends_with: String - votingPower: BigInt - votingPower_not: BigInt - votingPower_in: [BigInt] - votingPower_not_in: [BigInt] - votingPower_gt: BigInt - votingPower_lt: BigInt - votingPower_gte: BigInt - votingPower_lte: BigInt - votesCount: Int - votesCount_not: Int - votesCount_in: [Int] - votesCount_not_in: [Int] - votesCount_gt: Int - votesCount_lt: Int - votesCount_gte: Int - votesCount_lte: Int - proposalsCount: Int - proposalsCount_not: Int - proposalsCount_in: [Int] - proposalsCount_not_in: [Int] - proposalsCount_gt: Int - proposalsCount_lt: Int - proposalsCount_gte: Int - proposalsCount_lte: Int - delegationsCount: Int - delegationsCount_not: Int - delegationsCount_in: [Int] - delegationsCount_not_in: [Int] - delegationsCount_gt: Int - delegationsCount_lt: Int - delegationsCount_gte: Int - delegationsCount_lte: Int - lastVoteTimestamp: BigInt - lastVoteTimestamp_not: BigInt - lastVoteTimestamp_in: [BigInt] - lastVoteTimestamp_not_in: [BigInt] - lastVoteTimestamp_gt: BigInt - lastVoteTimestamp_lt: BigInt - lastVoteTimestamp_gte: BigInt - lastVoteTimestamp_lte: BigInt -} - -type delegationPage { - items: [delegation!]! - pageInfo: PageInfo! - totalCount: Int! -} - -type delegation { - transactionHash: String! - daoId: String! - delegateAccountId: String! - delegatorAccountId: String! - delegatedValue: BigInt! - previousDelegate: String - timestamp: BigInt! - logIndex: Int! - isCex: Boolean! - isDex: Boolean! - isLending: Boolean! - isTotal: Boolean! - delegate: account - delegator: account - transaction: transaction -} - -type transaction { - transactionHash: String! - fromAddress: String - toAddress: String - isCex: Boolean! - isDex: Boolean! - isLending: Boolean! - isTotal: Boolean! - timestamp: BigInt! - transfers(where: transferFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): transferPage - delegations(where: delegationFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): delegationPage -} - -type transferPage { - items: [transfer!]! - pageInfo: PageInfo! - totalCount: Int! -} - -type transfer { - transactionHash: String! - daoId: String! - tokenId: String! - amount: BigInt! - fromAccountId: String! - toAccountId: String! - timestamp: BigInt! - logIndex: Int! - isCex: Boolean! - isDex: Boolean! - isLending: Boolean! - isTotal: Boolean! - from: account - to: account - token: token - transaction: transaction -} - -input transferFilter { - AND: [transferFilter] - OR: [transferFilter] - transactionHash: String - transactionHash_not: String - transactionHash_in: [String] - transactionHash_not_in: [String] - transactionHash_contains: String - transactionHash_not_contains: String - transactionHash_starts_with: String - transactionHash_ends_with: String - transactionHash_not_starts_with: String - transactionHash_not_ends_with: String - daoId: String - daoId_not: String - daoId_in: [String] - daoId_not_in: [String] - daoId_contains: String - daoId_not_contains: String - daoId_starts_with: String - daoId_ends_with: String - daoId_not_starts_with: String - daoId_not_ends_with: String - tokenId: String - tokenId_not: String - tokenId_in: [String] - tokenId_not_in: [String] - tokenId_contains: String - tokenId_not_contains: String - tokenId_starts_with: String - tokenId_ends_with: String - tokenId_not_starts_with: String - tokenId_not_ends_with: String - amount: BigInt - amount_not: BigInt - amount_in: [BigInt] - amount_not_in: [BigInt] - amount_gt: BigInt - amount_lt: BigInt - amount_gte: BigInt - amount_lte: BigInt - fromAccountId: String - fromAccountId_not: String - fromAccountId_in: [String] - fromAccountId_not_in: [String] - fromAccountId_contains: String - fromAccountId_not_contains: String - fromAccountId_starts_with: String - fromAccountId_ends_with: String - fromAccountId_not_starts_with: String - fromAccountId_not_ends_with: String - toAccountId: String - toAccountId_not: String - toAccountId_in: [String] - toAccountId_not_in: [String] - toAccountId_contains: String - toAccountId_not_contains: String - toAccountId_starts_with: String - toAccountId_ends_with: String - toAccountId_not_starts_with: String - toAccountId_not_ends_with: String - timestamp: BigInt - timestamp_not: BigInt - timestamp_in: [BigInt] - timestamp_not_in: [BigInt] - timestamp_gt: BigInt - timestamp_lt: BigInt - timestamp_gte: BigInt - timestamp_lte: BigInt - logIndex: Int - logIndex_not: Int - logIndex_in: [Int] - logIndex_not_in: [Int] - logIndex_gt: Int - logIndex_lt: Int - logIndex_gte: Int - logIndex_lte: Int - isCex: Boolean - isCex_not: Boolean - isCex_in: [Boolean] - isCex_not_in: [Boolean] - isDex: Boolean - isDex_not: Boolean - isDex_in: [Boolean] - isDex_not_in: [Boolean] - isLending: Boolean - isLending_not: Boolean - isLending_in: [Boolean] - isLending_not_in: [Boolean] - isTotal: Boolean - isTotal_not: Boolean - isTotal_in: [Boolean] - isTotal_not_in: [Boolean] -} - -input delegationFilter { - AND: [delegationFilter] - OR: [delegationFilter] - transactionHash: String - transactionHash_not: String - transactionHash_in: [String] - transactionHash_not_in: [String] - transactionHash_contains: String - transactionHash_not_contains: String - transactionHash_starts_with: String - transactionHash_ends_with: String - transactionHash_not_starts_with: String - transactionHash_not_ends_with: String - daoId: String - daoId_not: String - daoId_in: [String] - daoId_not_in: [String] - daoId_contains: String - daoId_not_contains: String - daoId_starts_with: String - daoId_ends_with: String - daoId_not_starts_with: String - daoId_not_ends_with: String - delegateAccountId: String - delegateAccountId_not: String - delegateAccountId_in: [String] - delegateAccountId_not_in: [String] - delegateAccountId_contains: String - delegateAccountId_not_contains: String - delegateAccountId_starts_with: String - delegateAccountId_ends_with: String - delegateAccountId_not_starts_with: String - delegateAccountId_not_ends_with: String - delegatorAccountId: String - delegatorAccountId_not: String - delegatorAccountId_in: [String] - delegatorAccountId_not_in: [String] - delegatorAccountId_contains: String - delegatorAccountId_not_contains: String - delegatorAccountId_starts_with: String - delegatorAccountId_ends_with: String - delegatorAccountId_not_starts_with: String - delegatorAccountId_not_ends_with: String - delegatedValue: BigInt - delegatedValue_not: BigInt - delegatedValue_in: [BigInt] - delegatedValue_not_in: [BigInt] - delegatedValue_gt: BigInt - delegatedValue_lt: BigInt - delegatedValue_gte: BigInt - delegatedValue_lte: BigInt - previousDelegate: String - previousDelegate_not: String - previousDelegate_in: [String] - previousDelegate_not_in: [String] - previousDelegate_contains: String - previousDelegate_not_contains: String - previousDelegate_starts_with: String - previousDelegate_ends_with: String - previousDelegate_not_starts_with: String - previousDelegate_not_ends_with: String - timestamp: BigInt - timestamp_not: BigInt - timestamp_in: [BigInt] - timestamp_not_in: [BigInt] - timestamp_gt: BigInt - timestamp_lt: BigInt - timestamp_gte: BigInt - timestamp_lte: BigInt - logIndex: Int - logIndex_not: Int - logIndex_in: [Int] - logIndex_not_in: [Int] - logIndex_gt: Int - logIndex_lt: Int - logIndex_gte: Int - logIndex_lte: Int - isCex: Boolean - isCex_not: Boolean - isCex_in: [Boolean] - isCex_not_in: [Boolean] - isDex: Boolean - isDex_not: Boolean - isDex_in: [Boolean] - isDex_not_in: [Boolean] - isLending: Boolean - isLending_not: Boolean - isLending_in: [Boolean] - isLending_not_in: [Boolean] - isTotal: Boolean - isTotal_not: Boolean - isTotal_in: [Boolean] - isTotal_not_in: [Boolean] -} - -type proposalsOnchainPage { - items: [proposalsOnchain!]! - pageInfo: PageInfo! - totalCount: Int! -} - -type proposalsOnchain { - id: String! - txHash: String! - daoId: String! - proposerAccountId: String! - targets: JSON! - values: JSON! - signatures: JSON! - calldatas: JSON! - startBlock: Int! - endBlock: Int! - description: String! - timestamp: BigInt! - endTimestamp: BigInt! - status: String! - forVotes: BigInt! - againstVotes: BigInt! - abstainVotes: BigInt! - proposalType: Int - votes(where: votesOnchainFilter, orderBy: String, orderDirection: String, before: String, after: String, limit: Int, offset: Int): votesOnchainPage - proposer: account -} - -type votesOnchainPage { - items: [votesOnchain!]! - pageInfo: PageInfo! - totalCount: Int! -} - -type votesOnchain { - txHash: String! - daoId: String! - voterAccountId: String! - proposalId: String! - support: String! - votingPower: BigInt! - reason: String - timestamp: BigInt! - proposal: proposalsOnchain - voter: account -} - -input votesOnchainFilter { - AND: [votesOnchainFilter] - OR: [votesOnchainFilter] - txHash: String - txHash_not: String - txHash_in: [String] - txHash_not_in: [String] - txHash_contains: String - txHash_not_contains: String - txHash_starts_with: String - txHash_ends_with: String - txHash_not_starts_with: String - txHash_not_ends_with: String - daoId: String - daoId_not: String - daoId_in: [String] - daoId_not_in: [String] - daoId_contains: String - daoId_not_contains: String - daoId_starts_with: String - daoId_ends_with: String - daoId_not_starts_with: String - daoId_not_ends_with: String - voterAccountId: String - voterAccountId_not: String - voterAccountId_in: [String] - voterAccountId_not_in: [String] - voterAccountId_contains: String - voterAccountId_not_contains: String - voterAccountId_starts_with: String - voterAccountId_ends_with: String - voterAccountId_not_starts_with: String - voterAccountId_not_ends_with: String - proposalId: String - proposalId_not: String - proposalId_in: [String] - proposalId_not_in: [String] - proposalId_contains: String - proposalId_not_contains: String - proposalId_starts_with: String - proposalId_ends_with: String - proposalId_not_starts_with: String - proposalId_not_ends_with: String - support: String - support_not: String - support_in: [String] - support_not_in: [String] - support_contains: String - support_not_contains: String - support_starts_with: String - support_ends_with: String - support_not_starts_with: String - support_not_ends_with: String - votingPower: BigInt - votingPower_not: BigInt - votingPower_in: [BigInt] - votingPower_not_in: [BigInt] - votingPower_gt: BigInt - votingPower_lt: BigInt - votingPower_gte: BigInt - votingPower_lte: BigInt - reason: String - reason_not: String - reason_in: [String] - reason_not_in: [String] - reason_contains: String - reason_not_contains: String - reason_starts_with: String - reason_ends_with: String - reason_not_starts_with: String - reason_not_ends_with: String - timestamp: BigInt - timestamp_not: BigInt - timestamp_in: [BigInt] - timestamp_not_in: [BigInt] - timestamp_gt: BigInt - timestamp_lt: BigInt - timestamp_gte: BigInt - timestamp_lte: BigInt -} - -input proposalsOnchainFilter { - AND: [proposalsOnchainFilter] - OR: [proposalsOnchainFilter] - id: String - id_not: String - id_in: [String] - id_not_in: [String] - id_contains: String - id_not_contains: String - id_starts_with: String - id_ends_with: String - id_not_starts_with: String - id_not_ends_with: String - txHash: String - txHash_not: String - txHash_in: [String] - txHash_not_in: [String] - txHash_contains: String - txHash_not_contains: String - txHash_starts_with: String - txHash_ends_with: String - txHash_not_starts_with: String - txHash_not_ends_with: String - daoId: String - daoId_not: String - daoId_in: [String] - daoId_not_in: [String] - daoId_contains: String - daoId_not_contains: String - daoId_starts_with: String - daoId_ends_with: String - daoId_not_starts_with: String - daoId_not_ends_with: String - proposerAccountId: String - proposerAccountId_not: String - proposerAccountId_in: [String] - proposerAccountId_not_in: [String] - proposerAccountId_contains: String - proposerAccountId_not_contains: String - proposerAccountId_starts_with: String - proposerAccountId_ends_with: String - proposerAccountId_not_starts_with: String - proposerAccountId_not_ends_with: String - startBlock: Int - startBlock_not: Int - startBlock_in: [Int] - startBlock_not_in: [Int] - startBlock_gt: Int - startBlock_lt: Int - startBlock_gte: Int - startBlock_lte: Int - endBlock: Int - endBlock_not: Int - endBlock_in: [Int] - endBlock_not_in: [Int] - endBlock_gt: Int - endBlock_lt: Int - endBlock_gte: Int - endBlock_lte: Int - description: String - description_not: String - description_in: [String] - description_not_in: [String] - description_contains: String - description_not_contains: String - description_starts_with: String - description_ends_with: String - description_not_starts_with: String - description_not_ends_with: String - timestamp: BigInt - timestamp_not: BigInt - timestamp_in: [BigInt] - timestamp_not_in: [BigInt] - timestamp_gt: BigInt - timestamp_lt: BigInt - timestamp_gte: BigInt - timestamp_lte: BigInt - endTimestamp: BigInt - endTimestamp_not: BigInt - endTimestamp_in: [BigInt] - endTimestamp_not_in: [BigInt] - endTimestamp_gt: BigInt - endTimestamp_lt: BigInt - endTimestamp_gte: BigInt - endTimestamp_lte: BigInt - status: String - status_not: String - status_in: [String] - status_not_in: [String] - status_contains: String - status_not_contains: String - status_starts_with: String - status_ends_with: String - status_not_starts_with: String - status_not_ends_with: String - forVotes: BigInt - forVotes_not: BigInt - forVotes_in: [BigInt] - forVotes_not_in: [BigInt] - forVotes_gt: BigInt - forVotes_lt: BigInt - forVotes_gte: BigInt - forVotes_lte: BigInt - againstVotes: BigInt - againstVotes_not: BigInt - againstVotes_in: [BigInt] - againstVotes_not_in: [BigInt] - againstVotes_gt: BigInt - againstVotes_lt: BigInt - againstVotes_gte: BigInt - againstVotes_lte: BigInt - abstainVotes: BigInt - abstainVotes_not: BigInt - abstainVotes_in: [BigInt] - abstainVotes_not_in: [BigInt] - abstainVotes_gt: BigInt - abstainVotes_lt: BigInt - abstainVotes_gte: BigInt - abstainVotes_lte: BigInt - proposalType: Int - proposalType_not: Int - proposalType_in: [Int] - proposalType_not_in: [Int] - proposalType_gt: Int - proposalType_lt: Int - proposalType_gte: Int - proposalType_lte: Int -} - -type accountPage { - items: [account!]! - pageInfo: PageInfo! - totalCount: Int! -} - -input accountFilter { - AND: [accountFilter] - OR: [accountFilter] - id: String - id_not: String - id_in: [String] - id_not_in: [String] - id_contains: String - id_not_contains: String - id_starts_with: String - id_ends_with: String - id_not_starts_with: String - id_not_ends_with: String -} - -type votingPowerHistory { - transactionHash: String! - daoId: String! - accountId: String! - votingPower: BigInt! - delta: BigInt! - deltaMod: BigInt! - timestamp: BigInt! - logIndex: Int! - transfer: transfer - delegation: delegation - account: account -} - -type votingPowerHistoryPage { - items: [votingPowerHistory!]! - pageInfo: PageInfo! - totalCount: Int! -} - -input votingPowerHistoryFilter { - AND: [votingPowerHistoryFilter] - OR: [votingPowerHistoryFilter] - transactionHash: String - transactionHash_not: String - transactionHash_in: [String] - transactionHash_not_in: [String] - transactionHash_contains: String - transactionHash_not_contains: String - transactionHash_starts_with: String - transactionHash_ends_with: String - transactionHash_not_starts_with: String - transactionHash_not_ends_with: String - daoId: String - daoId_not: String - daoId_in: [String] - daoId_not_in: [String] - daoId_contains: String - daoId_not_contains: String - daoId_starts_with: String - daoId_ends_with: String - daoId_not_starts_with: String - daoId_not_ends_with: String - accountId: String - accountId_not: String - accountId_in: [String] - accountId_not_in: [String] - accountId_contains: String - accountId_not_contains: String - accountId_starts_with: String - accountId_ends_with: String - accountId_not_starts_with: String - accountId_not_ends_with: String - votingPower: BigInt - votingPower_not: BigInt - votingPower_in: [BigInt] - votingPower_not_in: [BigInt] - votingPower_gt: BigInt - votingPower_lt: BigInt - votingPower_gte: BigInt - votingPower_lte: BigInt - delta: BigInt - delta_not: BigInt - delta_in: [BigInt] - delta_not_in: [BigInt] - delta_gt: BigInt - delta_lt: BigInt - delta_gte: BigInt - delta_lte: BigInt - deltaMod: BigInt - deltaMod_not: BigInt - deltaMod_in: [BigInt] - deltaMod_not_in: [BigInt] - deltaMod_gt: BigInt - deltaMod_lt: BigInt - deltaMod_gte: BigInt - deltaMod_lte: BigInt - timestamp: BigInt - timestamp_not: BigInt - timestamp_in: [BigInt] - timestamp_not_in: [BigInt] - timestamp_gt: BigInt - timestamp_lt: BigInt - timestamp_gte: BigInt - timestamp_lte: BigInt - logIndex: Int - logIndex_not: Int - logIndex_in: [Int] - logIndex_not_in: [Int] - logIndex_gt: Int - logIndex_lt: Int - logIndex_gte: Int - logIndex_lte: Int -} - -type balanceHistory { - transactionHash: String! - daoId: String! - accountId: String! - balance: BigInt! - delta: BigInt! - deltaMod: BigInt! - timestamp: BigInt! - logIndex: Int! -} - -type balanceHistoryPage { - items: [balanceHistory!]! - pageInfo: PageInfo! - totalCount: Int! -} - -input balanceHistoryFilter { - AND: [balanceHistoryFilter] - OR: [balanceHistoryFilter] - transactionHash: String - transactionHash_not: String - transactionHash_in: [String] - transactionHash_not_in: [String] - transactionHash_contains: String - transactionHash_not_contains: String - transactionHash_starts_with: String - transactionHash_ends_with: String - transactionHash_not_starts_with: String - transactionHash_not_ends_with: String - daoId: String - daoId_not: String - daoId_in: [String] - daoId_not_in: [String] - daoId_contains: String - daoId_not_contains: String - daoId_starts_with: String - daoId_ends_with: String - daoId_not_starts_with: String - daoId_not_ends_with: String - accountId: String - accountId_not: String - accountId_in: [String] - accountId_not_in: [String] - accountId_contains: String - accountId_not_contains: String - accountId_starts_with: String - accountId_ends_with: String - accountId_not_starts_with: String - accountId_not_ends_with: String - balance: BigInt - balance_not: BigInt - balance_in: [BigInt] - balance_not_in: [BigInt] - balance_gt: BigInt - balance_lt: BigInt - balance_gte: BigInt - balance_lte: BigInt - delta: BigInt - delta_not: BigInt - delta_in: [BigInt] - delta_not_in: [BigInt] - delta_gt: BigInt - delta_lt: BigInt - delta_gte: BigInt - delta_lte: BigInt - deltaMod: BigInt - deltaMod_not: BigInt - deltaMod_in: [BigInt] - deltaMod_not_in: [BigInt] - deltaMod_gt: BigInt - deltaMod_lt: BigInt - deltaMod_gte: BigInt - deltaMod_lte: BigInt - timestamp: BigInt - timestamp_not: BigInt - timestamp_in: [BigInt] - timestamp_not_in: [BigInt] - timestamp_gt: BigInt - timestamp_lt: BigInt - timestamp_gte: BigInt - timestamp_lte: BigInt - logIndex: Int - logIndex_not: Int - logIndex_in: [Int] - logIndex_not_in: [Int] - logIndex_gt: Int - logIndex_lt: Int - logIndex_gte: Int - logIndex_lte: Int -} - -type daoMetricsDayBucket { - date: BigInt! - daoId: String! - tokenId: String! - metricType: metricType! - open: BigInt! - close: BigInt! - low: BigInt! - high: BigInt! - average: BigInt! - volume: BigInt! - count: Int! - lastUpdate: BigInt! -} - -enum metricType { - TOTAL_SUPPLY - DELEGATED_SUPPLY - CEX_SUPPLY - DEX_SUPPLY - LENDING_SUPPLY - CIRCULATING_SUPPLY - TREASURY -} - -type daoMetricsDayBucketPage { - items: [daoMetricsDayBucket!]! - pageInfo: PageInfo! - totalCount: Int! -} - -input daoMetricsDayBucketFilter { - AND: [daoMetricsDayBucketFilter] - OR: [daoMetricsDayBucketFilter] - date: BigInt - date_not: BigInt - date_in: [BigInt] - date_not_in: [BigInt] - date_gt: BigInt - date_lt: BigInt - date_gte: BigInt - date_lte: BigInt - daoId: String - daoId_not: String - daoId_in: [String] - daoId_not_in: [String] - daoId_contains: String - daoId_not_contains: String - daoId_starts_with: String - daoId_ends_with: String - daoId_not_starts_with: String - daoId_not_ends_with: String - tokenId: String - tokenId_not: String - tokenId_in: [String] - tokenId_not_in: [String] - tokenId_contains: String - tokenId_not_contains: String - tokenId_starts_with: String - tokenId_ends_with: String - tokenId_not_starts_with: String - tokenId_not_ends_with: String - metricType: metricType - metricType_not: metricType - metricType_in: [metricType] - metricType_not_in: [metricType] - open: BigInt - open_not: BigInt - open_in: [BigInt] - open_not_in: [BigInt] - open_gt: BigInt - open_lt: BigInt - open_gte: BigInt - open_lte: BigInt - close: BigInt - close_not: BigInt - close_in: [BigInt] - close_not_in: [BigInt] - close_gt: BigInt - close_lt: BigInt - close_gte: BigInt - close_lte: BigInt - low: BigInt - low_not: BigInt - low_in: [BigInt] - low_not_in: [BigInt] - low_gt: BigInt - low_lt: BigInt - low_gte: BigInt - low_lte: BigInt - high: BigInt - high_not: BigInt - high_in: [BigInt] - high_not_in: [BigInt] - high_gt: BigInt - high_lt: BigInt - high_gte: BigInt - high_lte: BigInt - average: BigInt - average_not: BigInt - average_in: [BigInt] - average_not_in: [BigInt] - average_gt: BigInt - average_lt: BigInt - average_gte: BigInt - average_lte: BigInt - volume: BigInt - volume_not: BigInt - volume_in: [BigInt] - volume_not_in: [BigInt] - volume_gt: BigInt - volume_lt: BigInt - volume_gte: BigInt - volume_lte: BigInt - count: Int - count_not: Int - count_in: [Int] - count_not_in: [Int] - count_gt: Int - count_lt: Int - count_gte: Int - count_lte: Int - lastUpdate: BigInt - lastUpdate_not: BigInt - lastUpdate_in: [BigInt] - lastUpdate_not_in: [BigInt] - lastUpdate_gt: BigInt - lastUpdate_lt: BigInt - lastUpdate_gte: BigInt - lastUpdate_lte: BigInt -} - -type transactionPage { - items: [transaction!]! - pageInfo: PageInfo! - totalCount: Int! -} - -input transactionFilter { - AND: [transactionFilter] - OR: [transactionFilter] - transactionHash: String - transactionHash_not: String - transactionHash_in: [String] - transactionHash_not_in: [String] - transactionHash_contains: String - transactionHash_not_contains: String - transactionHash_starts_with: String - transactionHash_ends_with: String - transactionHash_not_starts_with: String - transactionHash_not_ends_with: String - fromAddress: String - fromAddress_not: String - fromAddress_in: [String] - fromAddress_not_in: [String] - fromAddress_contains: String - fromAddress_not_contains: String - fromAddress_starts_with: String - fromAddress_ends_with: String - fromAddress_not_starts_with: String - fromAddress_not_ends_with: String - toAddress: String - toAddress_not: String - toAddress_in: [String] - toAddress_not_in: [String] - toAddress_contains: String - toAddress_not_contains: String - toAddress_starts_with: String - toAddress_ends_with: String - toAddress_not_starts_with: String - toAddress_not_ends_with: String - isCex: Boolean - isCex_not: Boolean - isCex_in: [Boolean] - isCex_not_in: [Boolean] - isDex: Boolean - isDex_not: Boolean - isDex_in: [Boolean] - isDex_not_in: [Boolean] - isLending: Boolean - isLending_not: Boolean - isLending_in: [Boolean] - isLending_not_in: [Boolean] - isTotal: Boolean - isTotal_not: Boolean - isTotal_in: [Boolean] - isTotal_not_in: [Boolean] - timestamp: BigInt - timestamp_not: BigInt - timestamp_in: [BigInt] - timestamp_not_in: [BigInt] - timestamp_gt: BigInt - timestamp_lt: BigInt - timestamp_gte: BigInt - timestamp_lte: BigInt -} - -type tokenPrice { - price: BigInt! - timestamp: BigInt! -} - -type tokenPricePage { - items: [tokenPrice!]! - pageInfo: PageInfo! - totalCount: Int! -} - -input tokenPriceFilter { - AND: [tokenPriceFilter] - OR: [tokenPriceFilter] - price: BigInt - price_not: BigInt - price_in: [BigInt] - price_not_in: [BigInt] - price_gt: BigInt - price_lt: BigInt - price_gte: BigInt - price_lte: BigInt - timestamp: BigInt - timestamp_not: BigInt - timestamp_in: [BigInt] - timestamp_not_in: [BigInt] - timestamp_gt: BigInt - timestamp_lt: BigInt - timestamp_gte: BigInt - timestamp_lte: BigInt -} - type historicalDelegations_200_response { items: [query_historicalDelegations_items_items]! totalCount: Float! @@ -1464,6 +224,11 @@ type query_historicalDelegations_items_items { transactionHash: String! } +""" +The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). +""" +scalar JSON @specifiedBy(url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf") + """Integers that will have a value of 0 or more.""" scalar NonNegativeInt @@ -1785,7 +550,7 @@ type query_proposalsActivity_proposals_items_userVote { support: String votingPower: String! reason: String - timestamp: String! + timestamp: String } enum queryInput_proposalsActivity_orderBy { @@ -1870,48 +635,6 @@ type proposal_200_response { proposalType: Float } -type proposalNonVoters_200_response { - items: [query_proposalNonVoters_items_items]! - totalCount: Float! -} - -type query_proposalNonVoters_items_items { - voter: String! - votingPower: String! - lastVoteTimestamp: Float! - votingPowerVariation: String! -} - -enum queryInput_proposalNonVoters_orderDirection { - asc - desc -} - -type votes_200_response { - items: [query_votes_items_items]! - totalCount: Float! -} - -type query_votes_items_items { - voterAddress: String! - transactionHash: String! - proposalId: String! - support: Float! - votingPower: String! - reason: String - timestamp: Float! -} - -enum queryInput_votes_orderBy { - timestamp - votingPower -} - -enum queryInput_votes_orderDirection { - asc - desc -} - type historicalBalances_200_response { items: [query_historicalBalances_items_items]! totalCount: Float! @@ -2308,6 +1031,75 @@ enum queryInput_transfers_sortOrder { desc } +type votesByProposalId_200_response { + items: [query_votesByProposalId_items_items]! + totalCount: Float! +} + +type query_votesByProposalId_items_items { + voterAddress: String! + transactionHash: String! + proposalId: String! + support: Float! + votingPower: String! + reason: String + timestamp: Float! + proposalTitle: String! +} + +enum queryInput_votesByProposalId_orderBy { + timestamp + votingPower +} + +enum queryInput_votesByProposalId_orderDirection { + asc + desc +} + +type votes_200_response { + items: [query_votes_items_items]! + totalCount: Float! +} + +type query_votes_items_items { + voterAddress: String! + transactionHash: String! + proposalId: String! + support: Float! + votingPower: String! + reason: String + timestamp: Float! + proposalTitle: String! +} + +enum queryInput_votes_orderBy { + timestamp + votingPower +} + +enum queryInput_votes_orderDirection { + asc + desc +} + +type proposalNonVoters_200_response { + items: [query_proposalNonVoters_items_items]! + totalCount: Float! +} + +type query_proposalNonVoters_items_items { + voter: String! + votingPower: String! + lastVoteTimestamp: Float! + votingPowerVariation: String! +} + +enum queryInput_proposalNonVoters_orderDirection { + asc + desc +} + type dao_200_response { id: String! chainId: Float! @@ -2369,6 +1161,13 @@ type AverageDelegationPercentageItem { high: String! } +type PageInfo { + hasNextPage: Boolean! + hasPreviousPage: Boolean! + endDate: String + startDate: String +} + type AverageDelegationPercentagePage { items: [AverageDelegationPercentageItem!]! diff --git a/apps/api-gateway/src/resolvers/index.ts b/apps/api-gateway/src/resolvers/index.ts index 8f9d839a0..0324a2b3d 100644 --- a/apps/api-gateway/src/resolvers/index.ts +++ b/apps/api-gateway/src/resolvers/index.ts @@ -1,13 +1,9 @@ import { daosResolver } from "./daos"; -import { listResolvers } from "./list"; -import { itemResolvers } from "./item"; import { restResolvers } from "./rest"; import { averageDelegationPercentageByDayResolver } from "./average-delegation-percentage"; export default { Query: { - ...listResolvers, - ...itemResolvers, ...restResolvers, daos: daosResolver, averageDelegationPercentageByDay: averageDelegationPercentageByDayResolver, diff --git a/apps/api-gateway/src/resolvers/item.ts b/apps/api-gateway/src/resolvers/item.ts deleted file mode 100644 index 6cb4467c9..000000000 --- a/apps/api-gateway/src/resolvers/item.ts +++ /dev/null @@ -1,34 +0,0 @@ -const daoItemQueries = ["votesOnchain"]; - -export const itemResolvers = daoItemQueries.reduce((acc, fieldName) => { - acc[fieldName] = { - selectionSet: /* GraphQL */ ` - { - id - } - `, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - resolve: async (root: any, args: any, context: any, info: any) => { - const daoId = args.id || context.headers["anticapture-dao-id"]; - - if (!daoId) { - throw new Error(`Missing where.daoId in query for ${fieldName}`); - } - - const targetClient = context[`graphql_${daoId.toUpperCase()}`]?.Query; - - if (!targetClient || typeof targetClient[fieldName] !== "function") { - return {}; - } - - return targetClient[fieldName]({ - root, - args, - context, - info, - }); - }, - }; - - return acc; -}, {}); diff --git a/apps/api-gateway/src/resolvers/list.ts b/apps/api-gateway/src/resolvers/list.ts deleted file mode 100644 index cee5b2440..000000000 --- a/apps/api-gateway/src/resolvers/list.ts +++ /dev/null @@ -1,43 +0,0 @@ -const daoListQueries = [ - "daoMetricsDayBuckets", - "votesOnchains", - "votingPowerHistorys", // FIXME: Leave endpoint active for now as it is still used by the notification bot -]; - -export const listResolvers = daoListQueries.reduce((acc, fieldName) => { - acc[fieldName] = { - selectionSet: /* GraphQL */ ` - { - where { - daoId - } - } - `, - resolve: async (root: any, args: any, context: any, info) => { - const daoId = args.where?.daoId || context.headers["anticapture-dao-id"]; - - if (!daoId) { - throw new Error(`Missing where.daoId in query for ${fieldName}`); - } - - const targetClient = context[`graphql_${daoId.toUpperCase()}`]?.Query; - - if (!targetClient || typeof targetClient[fieldName] !== "function") { - return {}; - } - - if (args?.where?.daoId) { - args.where.daoId = args.where.daoId.toUpperCase(); - } - - return targetClient[fieldName]({ - root, - args, - context, - info, - }); - }, - }; - - return acc; -}, {}); diff --git a/apps/api-gateway/src/resolvers/rest.ts b/apps/api-gateway/src/resolvers/rest.ts index fac61cf7e..3b459a789 100644 --- a/apps/api-gateway/src/resolvers/rest.ts +++ b/apps/api-gateway/src/resolvers/rest.ts @@ -33,6 +33,7 @@ const daoItemQueries = [ "proposalNonVoters", "proposals", "votes", + "votesByProposalId", "proposalsActivity", "token", "tokenMetrics", diff --git a/apps/api/.eslintrc.json b/apps/api/.eslintrc.json new file mode 100644 index 000000000..c2594e335 --- /dev/null +++ b/apps/api/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["../../.eslintrc.json"] +} diff --git a/apps/indexer/jest.config.js b/apps/api/jest.config.js similarity index 100% rename from apps/indexer/jest.config.js rename to apps/api/jest.config.js diff --git a/apps/api/package.json b/apps/api/package.json new file mode 100644 index 000000000..36af10504 --- /dev/null +++ b/apps/api/package.json @@ -0,0 +1,48 @@ +{ + "name": "@anticapture/api", + "version": "1.0.0", + "main": "dist/index.js", + "type": "module", + "scripts": { + "typecheck": "tsc --noEmit", + "test": "jest", + "test:watch": "jest --watch", + "clean": "rm -rf node_modules *.tsbuildinfo dist", + "start": "node dist/index.js", + "build": "tsup", + "build:watch": "tsc --watch", + "dev": "tsx src/index.ts", + "dev:watch": "tsx watch src/index.ts" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@hono/node-server": "^1.19.9", + "@hono/zod-openapi": "^0.19.6", + "axios": "^1.9.0", + "drizzle-kit": "^0.31.4", + "drizzle-orm": "~0.41.0", + "hono": "^4.7.10", + "pg": "^8.17.2", + "viem": "^2.41.2", + "zod": "^3.25.3", + "zod-validation-error": "^3.4.1" + }, + "devDependencies": { + "@types/jest": "^29.5.14", + "@types/node": "^20.16.5", + "@types/pg": "^8.15.6", + "dotenv": "^16.5.0", + "eslint": "^8.53.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "jest": "^29.7.0", + "prettier": "^3.5.3", + "ts-jest": "^29.4.1", + "tsup": "^8.5.1", + "tsx": "^4.21.0", + "typescript": "^5.8.3" + } +} diff --git a/apps/indexer/src/api/cache/dao-cache.interface.ts b/apps/api/src/cache/dao-cache.interface.ts similarity index 100% rename from apps/indexer/src/api/cache/dao-cache.interface.ts rename to apps/api/src/cache/dao-cache.interface.ts diff --git a/apps/indexer/src/api/cache/dao-cache.ts b/apps/api/src/cache/dao-cache.ts similarity index 96% rename from apps/indexer/src/api/cache/dao-cache.ts rename to apps/api/src/cache/dao-cache.ts index d21f0a751..8a51c6a2d 100644 --- a/apps/indexer/src/api/cache/dao-cache.ts +++ b/apps/api/src/cache/dao-cache.ts @@ -1,4 +1,4 @@ -import { DaoResponse } from "@/api/mappers"; +import { DaoResponse } from "@/mappers"; import { DaoDataCache } from "./dao-cache.interface"; /** diff --git a/apps/api/src/clients/comp/abi/governor.ts b/apps/api/src/clients/comp/abi/governor.ts new file mode 100644 index 000000000..a28f75df0 --- /dev/null +++ b/apps/api/src/clients/comp/abi/governor.ts @@ -0,0 +1,1157 @@ +export const GovernorAbi = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, + { inputs: [], name: "CheckpointUnorderedInsertion", type: "error" }, + { inputs: [], name: "FailedCall", type: "error" }, + { + inputs: [{ internalType: "address", name: "voter", type: "address" }], + name: "GovernorAlreadyCastVote", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "GovernorAlreadyQueuedProposal", + type: "error", + }, + { inputs: [], name: "GovernorDisabledDeposit", type: "error" }, + { + inputs: [ + { internalType: "address", name: "voter", type: "address" }, + { internalType: "uint256", name: "usedVotes", type: "uint256" }, + { internalType: "uint256", name: "remainingWeight", type: "uint256" }, + ], + name: "GovernorExceedRemainingWeight", + type: "error", + }, + { + inputs: [ + { internalType: "address", name: "proposer", type: "address" }, + { internalType: "uint256", name: "votes", type: "uint256" }, + { internalType: "uint256", name: "threshold", type: "uint256" }, + ], + name: "GovernorInsufficientProposerVotes", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "targets", type: "uint256" }, + { internalType: "uint256", name: "calldatas", type: "uint256" }, + { internalType: "uint256", name: "values", type: "uint256" }, + ], + name: "GovernorInvalidProposalLength", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "voter", type: "address" }], + name: "GovernorInvalidSignature", + type: "error", + }, + { inputs: [], name: "GovernorInvalidVoteParams", type: "error" }, + { inputs: [], name: "GovernorInvalidVoteType", type: "error" }, + { + inputs: [ + { internalType: "uint256", name: "votingPeriod", type: "uint256" }, + ], + name: "GovernorInvalidVotingPeriod", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "GovernorNonexistentProposal", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "GovernorNotQueuedProposal", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "GovernorOnlyExecutor", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "GovernorOnlyProposer", + type: "error", + }, + { inputs: [], name: "GovernorQueueNotImplemented", type: "error" }, + { + inputs: [{ internalType: "address", name: "proposer", type: "address" }], + name: "GovernorRestrictedProposer", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { + internalType: "enum IGovernor.ProposalState", + name: "current", + type: "uint8", + }, + { internalType: "bytes32", name: "expectedStates", type: "bytes32" }, + ], + name: "GovernorUnexpectedProposalState", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "balance", type: "uint256" }, + { internalType: "uint256", name: "needed", type: "uint256" }, + ], + name: "InsufficientBalance", + type: "error", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "currentNonce", type: "uint256" }, + ], + name: "InvalidAccountNonce", + type: "error", + }, + { inputs: [], name: "InvalidInitialization", type: "error" }, + { inputs: [], name: "NotInitializing", type: "error" }, + { inputs: [], name: "ProposalIdAlreadySet", type: "error" }, + { + inputs: [ + { internalType: "address", name: "proposer", type: "address" }, + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { + internalType: "enum IGovernor.ProposalState", + name: "state", + type: "uint8", + }, + ], + name: "ProposerActiveProposal", + type: "error", + }, + { + inputs: [ + { internalType: "uint8", name: "bits", type: "uint8" }, + { internalType: "uint256", name: "value", type: "uint256" }, + ], + name: "SafeCastOverflowedUintDowncast", + type: "error", + }, + { + inputs: [ + { internalType: "bytes32", name: "reason", type: "bytes32" }, + { internalType: "address", name: "caller", type: "address" }, + ], + name: "Unauthorized", + type: "error", + }, + { anonymous: false, inputs: [], name: "EIP712DomainChanged", type: "event" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint64", + name: "version", + type: "uint64", + }, + ], + name: "Initialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint64", + name: "oldVoteExtension", + type: "uint64", + }, + { + indexed: false, + internalType: "uint64", + name: "newVoteExtension", + type: "uint64", + }, + ], + name: "LateQuorumVoteExtensionSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "voteStart", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "voteEnd", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint64", + name: "extendedDeadline", + type: "uint64", + }, + ], + name: "ProposalExtended", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldProposalGuardian", + type: "address", + }, + { + indexed: false, + internalType: "uint96", + name: "oldProposalGuardianExpiry", + type: "uint96", + }, + { + indexed: false, + internalType: "address", + name: "newProposalGuardian", + type: "address", + }, + { + indexed: false, + internalType: "uint96", + name: "newProposalGuardianExpiry", + type: "uint96", + }, + ], + name: "ProposalGuardianSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "etaSeconds", + type: "uint256", + }, + ], + name: "ProposalQueued", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldProposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "ProposalThresholdSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldQuorum", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newQuorum", + type: "uint256", + }, + ], + name: "QuorumUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldTimelock", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newTimelock", + type: "address", + }, + ], + name: "TimelockChange", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + { indexed: false, internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "VoteCastWithParams", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingDelay", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingDelay", + type: "uint256", + }, + ], + name: "VotingDelaySet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingPeriod", + type: "uint256", + }, + ], + name: "VotingPeriodSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "expiration", + type: "uint256", + }, + ], + name: "WhitelistAccountExpirationSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldGuardian", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newGuardian", + type: "address", + }, + ], + name: "WhitelistGuardianSet", + type: "event", + }, + { + inputs: [], + name: "BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CLOCK_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "COUNTING_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "EXTENDED_BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "__acceptAdmin", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_proposalId", type: "uint256" }], + name: "cancel", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "_targets", type: "address[]" }, + { internalType: "uint256[]", name: "_values", type: "uint256[]" }, + { internalType: "bytes[]", name: "_calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "_descriptionHash", type: "bytes32" }, + ], + name: "cancel", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "address", name: "voter", type: "address" }, + { internalType: "bytes", name: "signature", type: "bytes" }, + ], + name: "castVoteBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "castVoteWithReasonAndParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "address", name: "voter", type: "address" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + { internalType: "bytes", name: "signature", type: "bytes" }, + ], + name: "castVoteWithReasonAndParamsBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "clock", + outputs: [{ internalType: "uint48", name: "", type: "uint48" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "eip712Domain", + outputs: [ + { internalType: "bytes1", name: "fields", type: "bytes1" }, + { internalType: "string", name: "name", type: "string" }, + { internalType: "string", name: "version", type: "string" }, + { internalType: "uint256", name: "chainId", type: "uint256" }, + { internalType: "address", name: "verifyingContract", type: "address" }, + { internalType: "bytes32", name: "salt", type: "bytes32" }, + { internalType: "uint256[]", name: "extensions", type: "uint256[]" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "execute", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_proposalId", type: "uint256" }], + name: "execute", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [], + name: "getNextProposalId", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "timepoint", type: "uint256" }, + ], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "timepoint", type: "uint256" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "getVotesWithParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasVoted", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "_targets", type: "address[]" }, + { internalType: "uint256[]", name: "_values", type: "uint256[]" }, + { internalType: "bytes[]", name: "_calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "_descriptionHash", type: "bytes32" }, + ], + name: "hashProposal", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint48", name: "_initialVotingDelay", type: "uint48" }, + { internalType: "uint32", name: "_initialVotingPeriod", type: "uint32" }, + { + internalType: "uint256", + name: "_initialProposalThreshold", + type: "uint256", + }, + { internalType: "contract IComp", name: "_compAddress", type: "address" }, + { internalType: "uint256", name: "_quorumVotes", type: "uint256" }, + { + internalType: "contract ICompoundTimelock", + name: "_timelockAddress", + type: "address", + }, + { internalType: "uint48", name: "_initialVoteExtension", type: "uint48" }, + { internalType: "address", name: "_whitelistGuardian", type: "address" }, + { + components: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint96", name: "expiration", type: "uint96" }, + ], + internalType: "struct CompoundGovernor.ProposalGuardian", + name: "_proposalGuardian", + type: "tuple", + }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "_account", type: "address" }], + name: "isWhitelisted", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "lateQuorumVoteExtension", + outputs: [{ internalType: "uint48", name: "", type: "uint48" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "proposer", type: "address" }], + name: "latestProposalIds", + outputs: [ + { internalType: "uint256", name: "latestProposalId", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155BatchReceived", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC721Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "proposalCount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_proposalId", type: "uint256" }], + name: "proposalDeadline", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_proposalId", type: "uint256" }], + name: "proposalDetails", + outputs: [ + { internalType: "address[]", name: "", type: "address[]" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "bytes[]", name: "", type: "bytes[]" }, + { internalType: "bytes32", name: "", type: "bytes32" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalEta", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalGuardian", + outputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint96", name: "expiration", type: "uint96" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_proposalId", type: "uint256" }], + name: "proposalNeedsQueuing", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalProposer", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalSnapshot", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalVotes", + outputs: [ + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "_targets", type: "address[]" }, + { internalType: "uint256[]", name: "_values", type: "uint256[]" }, + { internalType: "bytes[]", name: "_calldatas", type: "bytes[]" }, + { internalType: "string", name: "_description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "queue", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_proposalId", type: "uint256" }], + name: "queue", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_voteStart", type: "uint256" }], + name: "quorum", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "target", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "relay", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { internalType: "uint48", name: "newVoteExtension", type: "uint48" }, + ], + name: "setLateQuorumVoteExtension", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "setNextProposalId", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint96", name: "expiration", type: "uint96" }, + ], + internalType: "struct CompoundGovernor.ProposalGuardian", + name: "_newProposalGuardian", + type: "tuple", + }, + ], + name: "setProposalGuardian", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "setProposalThreshold", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_amount", type: "uint256" }], + name: "setQuorum", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint48", name: "newVotingDelay", type: "uint48" }, + ], + name: "setVotingDelay", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint32", name: "newVotingPeriod", type: "uint32" }, + ], + name: "setVotingPeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_account", type: "address" }, + { internalType: "uint256", name: "_expiration", type: "uint256" }, + ], + name: "setWhitelistAccountExpiration", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_newWhitelistGuardian", + type: "address", + }, + ], + name: "setWhitelistGuardian", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_proposalId", type: "uint256" }], + name: "state", + outputs: [ + { internalType: "enum IGovernor.ProposalState", name: "", type: "uint8" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelock", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [{ internalType: "contract IComp", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract ICompoundTimelock", + name: "newTimelock", + type: "address", + }, + ], + name: "updateTimelock", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "usedVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "version", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "whitelistAccountExpirations", + outputs: [{ internalType: "uint256", name: "timestamp", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "whitelistGuardian", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { stateMutability: "payable", type: "receive" }, +] as const; diff --git a/apps/api/src/clients/comp/abi/index.ts b/apps/api/src/clients/comp/abi/index.ts new file mode 100644 index 000000000..c3304e098 --- /dev/null +++ b/apps/api/src/clients/comp/abi/index.ts @@ -0,0 +1,2 @@ +export { GovernorAbi as COMPGovernorAbi } from "./governor"; +export { TokenAbi as COMPTokenAbi } from "./token"; diff --git a/apps/api/src/clients/comp/abi/token.ts b/apps/api/src/clients/comp/abi/token.ts new file mode 100644 index 000000000..8b359ce7e --- /dev/null +++ b/apps/api/src/clients/comp/abi/token.ts @@ -0,0 +1,298 @@ +export const TokenAbi = [ + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + payable: false, + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "fromDelegate", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "toDelegate", + type: "address", + }, + ], + name: "DelegateChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegate", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "previousBalance", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newBalance", + type: "uint256", + }, + ], + name: "DelegateVotesChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + constant: true, + inputs: [], + name: "DELEGATION_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "DOMAIN_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "approve", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "uint32", name: "", type: "uint32" }, + ], + name: "checkpoints", + outputs: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { internalType: "uint96", name: "votes", type: "uint96" }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [{ internalType: "address", name: "delegatee", type: "address" }], + name: "delegate", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "delegatee", type: "address" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "delegateBySig", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "delegates", + outputs: [{ internalType: "address", name: "", type: "address" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getCurrentVotes", + outputs: [{ internalType: "uint96", name: "", type: "uint96" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getPriorVotes", + outputs: [{ internalType: "uint96", name: "", type: "uint96" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "numCheckpoints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "src", type: "address" }, + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "transferFrom", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/apps/indexer/src/indexer/comp/client.ts b/apps/api/src/clients/comp/index.ts similarity index 93% rename from apps/indexer/src/indexer/comp/client.ts rename to apps/api/src/clients/comp/index.ts index 9aefa4b0b..91bb6ca87 100644 --- a/apps/indexer/src/indexer/comp/client.ts +++ b/apps/api/src/clients/comp/index.ts @@ -8,16 +8,16 @@ import { Transport, } from "viem"; -import { DAOClient } from "@/interfaces/client"; +import { DAOClient } from "@/clients"; import { GovernorBase } from "../governor.base"; import { COMPGovernorAbi } from "./abi"; import { getBlockNumber, readContract } from "viem/actions"; export class COMPClient< - TTransport extends Transport = Transport, - TChain extends Chain = Chain, - TAccount extends Account | undefined = Account | undefined, - > + TTransport extends Transport = Transport, + TChain extends Chain = Chain, + TAccount extends Account | undefined = Account | undefined, +> extends GovernorBase implements DAOClient { diff --git a/apps/api/src/clients/ens/abi/governor.ts b/apps/api/src/clients/ens/abi/governor.ts new file mode 100644 index 000000000..787305172 --- /dev/null +++ b/apps/api/src/clients/ens/abi/governor.ts @@ -0,0 +1,443 @@ +export const GovernorAbi = [ + { + inputs: [ + { internalType: "contract ERC20Votes", name: "_token", type: "address" }, + { + internalType: "contract TimelockController", + name: "_timelock", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint256", name: "eta", type: "uint256" }, + ], + name: "ProposalQueued", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldQuorumNumerator", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newQuorumNumerator", + type: "uint256", + }, + ], + name: "QuorumNumeratorUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldTimelock", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newTimelock", + type: "address", + }, + ], + name: "TimelockChange", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + inputs: [], + name: "BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "COUNTING_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "execute", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasVoted", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "hashProposal", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalDeadline", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalEta", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalSnapshot", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalVotes", + outputs: [ + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "queue", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "blockNumber", type: "uint256" }], + name: "quorum", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "quorumDenominator", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "quorumNumerator", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "state", + outputs: [ + { internalType: "enum IGovernor.ProposalState", name: "", type: "uint8" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelock", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [ + { internalType: "contract ERC20Votes", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newQuorumNumerator", type: "uint256" }, + ], + name: "updateQuorumNumerator", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract TimelockController", + name: "newTimelock", + type: "address", + }, + ], + name: "updateTimelock", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "version", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, +] as const; diff --git a/apps/api/src/clients/ens/abi/index.ts b/apps/api/src/clients/ens/abi/index.ts new file mode 100644 index 000000000..05b364bef --- /dev/null +++ b/apps/api/src/clients/ens/abi/index.ts @@ -0,0 +1,2 @@ +export { GovernorAbi as ENSGovernorAbi } from "./governor"; +export { TokenAbi as ENSTokenAbi } from "./token"; diff --git a/apps/api/src/clients/ens/abi/token.ts b/apps/api/src/clients/ens/abi/token.ts new file mode 100644 index 000000000..7a8b5f7dd --- /dev/null +++ b/apps/api/src/clients/ens/abi/token.ts @@ -0,0 +1,454 @@ +export const TokenAbi = [ + { + inputs: [ + { internalType: "uint256", name: "freeSupply", type: "uint256" }, + { internalType: "uint256", name: "airdropSupply", type: "uint256" }, + { internalType: "uint256", name: "_claimPeriodEnds", type: "uint256" }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "claimant", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Claim", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "fromDelegate", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "toDelegate", + type: "address", + }, + ], + name: "DelegateChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegate", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "previousBalance", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newBalance", + type: "uint256", + }, + ], + name: "DelegateVotesChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "bytes32", + name: "merkleRoot", + type: "bytes32", + }, + ], + name: "MerkleRootChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "approve", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint32", name: "pos", type: "uint32" }, + ], + name: "checkpoints", + outputs: [ + { + components: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { internalType: "uint224", name: "votes", type: "uint224" }, + ], + internalType: "struct ERC20Votes.Checkpoint", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "claimPeriodEnds", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "address", name: "delegate", type: "address" }, + { internalType: "bytes32[]", name: "merkleProof", type: "bytes32[]" }, + ], + name: "claimTokens", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "subtractedValue", type: "uint256" }, + ], + name: "decreaseAllowance", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "delegatee", type: "address" }], + name: "delegate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "delegatee", type: "address" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "delegateBySig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "delegates", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "blockNumber", type: "uint256" }], + name: "getPastTotalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getPastVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "addedValue", type: "uint256" }, + ], + name: "increaseAllowance", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "index", type: "uint256" }], + name: "isClaimed", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "merkleRoot", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "minimumMintInterval", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "dest", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "mintCap", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "nextMint", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "numCheckpoints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "permit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "_merkleRoot", type: "bytes32" }], + name: "setMerkleRoot", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "dest", type: "address" }], + name: "sweep", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "recipient", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "sender", type: "address" }, + { internalType: "address", name: "recipient", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transferFrom", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/apps/indexer/src/indexer/ens/client.ts b/apps/api/src/clients/ens/index.ts similarity index 93% rename from apps/indexer/src/indexer/ens/client.ts rename to apps/api/src/clients/ens/index.ts index 065355692..7f116cb39 100644 --- a/apps/indexer/src/indexer/ens/client.ts +++ b/apps/api/src/clients/ens/index.ts @@ -9,15 +9,15 @@ import { } from "viem"; import { getBlockNumber, readContract } from "viem/actions"; -import { DAOClient } from "@/interfaces/client"; +import { DAOClient } from "@/clients"; import { ENSGovernorAbi } from "./abi"; import { GovernorBase } from "../governor.base"; export class ENSClient< - TTransport extends Transport = Transport, - TChain extends Chain = Chain, - TAccount extends Account | undefined = Account | undefined, - > + TTransport extends Transport = Transport, + TChain extends Chain = Chain, + TAccount extends Account | undefined = Account | undefined, +> extends GovernorBase implements DAOClient { diff --git a/apps/indexer/src/indexer/governor.base.ts b/apps/api/src/clients/governor.base.ts similarity index 88% rename from apps/indexer/src/indexer/governor.base.ts rename to apps/api/src/clients/governor.base.ts index b170848a0..4241a5c12 100644 --- a/apps/indexer/src/indexer/governor.base.ts +++ b/apps/api/src/clients/governor.base.ts @@ -1,6 +1,5 @@ import { Account, Chain, Client, Transport } from "viem"; -import { DBProposal } from "../api/mappers"; import { ProposalStatus } from "../lib/constants"; /** @@ -26,18 +25,15 @@ export abstract class GovernorBase< abstract getQuorum(proposalId: string | null): Promise; - async getProposalStatus( - proposal: Pick< - DBProposal, - | "id" - | "status" - | "startBlock" - | "endBlock" - | "forVotes" - | "againstVotes" - | "abstainVotes" - >, - ): Promise { + async getProposalStatus(proposal: { + id: string; + status: string; + startBlock: number; + endBlock: number; + forVotes: bigint; + againstVotes: bigint; + abstainVotes: bigint; + }): Promise { const currentBlock = await this.getCurrentBlockNumber(); // Skip proposals already finalized via event diff --git a/apps/api/src/clients/gtc/abi/governor.ts b/apps/api/src/clients/gtc/abi/governor.ts new file mode 100644 index 000000000..4964f587b --- /dev/null +++ b/apps/api/src/clients/gtc/abi/governor.ts @@ -0,0 +1,647 @@ +export const GovernorAbi = [ + { + inputs: [ + { internalType: "uint256", name: "_initialVotingDelay", type: "uint256" }, + { + internalType: "uint256", + name: "_initialVotingPeriod", + type: "uint256", + }, + { + internalType: "uint256", + name: "_initialProposalThreshold", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { inputs: [], name: "Empty", type: "error" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint256", name: "eta", type: "uint256" }, + ], + name: "ProposalQueued", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldProposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "ProposalThresholdSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldTimelock", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newTimelock", + type: "address", + }, + ], + name: "TimelockChange", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + { indexed: false, internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "VoteCastWithParams", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingDelay", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingDelay", + type: "uint256", + }, + ], + name: "VotingDelaySet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingPeriod", + type: "uint256", + }, + ], + name: "VotingPeriodSet", + type: "event", + }, + { + inputs: [], + name: "BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "COUNTING_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "EXTENDED_BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "__acceptAdmin", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "castVoteWithReasonAndParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteWithReasonAndParamsBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "execute", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "fractionalVoteNonce", + outputs: [{ internalType: "uint128", name: "", type: "uint128" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "getVotesWithParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasVoted", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "hashProposal", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155BatchReceived", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC721Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalDeadline", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalEta", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalSnapshot", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalVotes", + outputs: [ + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "queue", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "", type: "uint256" }], + name: "quorum", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "target", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "relay", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "setProposalThreshold", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingDelay", type: "uint256" }, + ], + name: "setVotingDelay", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingPeriod", type: "uint256" }, + ], + name: "setVotingPeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "state", + outputs: [ + { internalType: "enum IGovernor.ProposalState", name: "", type: "uint8" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelock", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [ + { internalType: "contract ERC20VotesComp", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract ICompoundTimelock", + name: "newTimelock", + type: "address", + }, + ], + name: "updateTimelock", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "version", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "voteWeightCast", + outputs: [{ internalType: "uint128", name: "", type: "uint128" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { stateMutability: "payable", type: "receive" }, +] as const; diff --git a/apps/api/src/clients/gtc/abi/index.ts b/apps/api/src/clients/gtc/abi/index.ts new file mode 100644 index 000000000..e0776d35e --- /dev/null +++ b/apps/api/src/clients/gtc/abi/index.ts @@ -0,0 +1,2 @@ +export { GovernorAbi } from "./governor"; +export { TokenAbi } from "./token"; diff --git a/apps/api/src/clients/gtc/abi/token.ts b/apps/api/src/clients/gtc/abi/token.ts new file mode 100644 index 000000000..4f2105b63 --- /dev/null +++ b/apps/api/src/clients/gtc/abi/token.ts @@ -0,0 +1,396 @@ +export const TokenAbi = [ + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "address", name: "minter_", type: "address" }, + { + internalType: "uint256", + name: "mintingAllowedAfter_", + type: "uint256", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "fromDelegate", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "toDelegate", + type: "address", + }, + ], + name: "DelegateChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegate", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "previousBalance", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newBalance", + type: "uint256", + }, + ], + name: "DelegateVotesChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "delegator", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "delegatee", + type: "address", + }, + ], + name: "GTCDistChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "minter", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newMinter", + type: "address", + }, + ], + name: "MinterChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [], + name: "DELEGATION_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DOMAIN_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "GTCDist", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "PERMIT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "approve", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "uint32", name: "", type: "uint32" }, + ], + name: "checkpoints", + outputs: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { internalType: "uint96", name: "votes", type: "uint96" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "delegatee", type: "address" }], + name: "delegate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "delegatee", type: "address" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "delegateBySig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "delegator", type: "address" }, + { internalType: "address", name: "delegatee", type: "address" }, + ], + name: "delegateOnDist", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "delegates", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getCurrentVotes", + outputs: [{ internalType: "uint96", name: "", type: "uint96" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getPriorVotes", + outputs: [{ internalType: "uint96", name: "", type: "uint96" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "minimumTimeBetweenMints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "mintCap", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "minter", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "mintingAllowedAfter", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "numCheckpoints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "permit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "GTCDist_", type: "address" }], + name: "setGTCDist", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "minter_", type: "address" }], + name: "setMinter", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "src", type: "address" }, + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "transferFrom", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/apps/indexer/src/indexer/gtc/client.ts b/apps/api/src/clients/gtc/index.ts similarity index 93% rename from apps/indexer/src/indexer/gtc/client.ts rename to apps/api/src/clients/gtc/index.ts index d7fc3f151..d4d69fbc5 100644 --- a/apps/indexer/src/indexer/gtc/client.ts +++ b/apps/api/src/clients/gtc/index.ts @@ -9,15 +9,15 @@ import { } from "viem"; import { getBlockNumber, readContract } from "viem/actions"; -import { DAOClient } from "@/interfaces/client"; +import { DAOClient } from "@/clients"; import { GovernorAbi } from "./abi/governor"; import { GovernorBase } from "../governor.base"; export class GTCClient< - TTransport extends Transport = Transport, - TChain extends Chain = Chain, - TAccount extends Account | undefined = Account | undefined, - > + TTransport extends Transport = Transport, + TChain extends Chain = Chain, + TAccount extends Account | undefined = Account | undefined, +> extends GovernorBase implements DAOClient { diff --git a/apps/indexer/src/interfaces/client.ts b/apps/api/src/clients/index.ts similarity index 55% rename from apps/indexer/src/interfaces/client.ts rename to apps/api/src/clients/index.ts index 32d27b0f2..4a3282151 100644 --- a/apps/indexer/src/interfaces/client.ts +++ b/apps/api/src/clients/index.ts @@ -1,4 +1,12 @@ -import { DBProposal } from "@/api/mappers"; +export * from "./ens"; +export * from "./op"; +export * from "./gtc"; +export * from "./nouns"; +export * from "./scr"; +export * from "./comp"; +export * from "./obol"; +export * from "./zk"; +export * from "./uni"; export interface DAOClient { getDaoId: () => string; @@ -14,16 +22,13 @@ export interface DAOClient { againstVotes: bigint; abstainVotes: bigint; }) => bigint; - getProposalStatus: ( - proposal: Pick< - DBProposal, - | "id" - | "status" - | "startBlock" - | "endBlock" - | "forVotes" - | "againstVotes" - | "abstainVotes" - >, - ) => Promise; + getProposalStatus: (proposal: { + id: string; + status: string; + startBlock: number; + endBlock: number; + forVotes: bigint; + againstVotes: bigint; + abstainVotes: bigint; + }) => Promise; } diff --git a/apps/api/src/clients/nouns/abi/auction.ts b/apps/api/src/clients/nouns/abi/auction.ts new file mode 100644 index 000000000..8db33f107 --- /dev/null +++ b/apps/api/src/clients/nouns/abi/auction.ts @@ -0,0 +1,611 @@ +export const AuctionAbi = [ + { + inputs: [ + { + internalType: "contract INounsToken", + name: "_nouns", + type: "address", + }, + { internalType: "address", name: "_weth", type: "address" }, + { internalType: "uint256", name: "_duration", type: "uint256" }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "nounId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "sender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + indexed: false, + internalType: "bool", + name: "extended", + type: "bool", + }, + ], + name: "AuctionBid", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "nounId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + indexed: true, + internalType: "uint32", + name: "clientId", + type: "uint32", + }, + ], + name: "AuctionBidWithClientId", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "nounId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "startTime", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endTime", + type: "uint256", + }, + ], + name: "AuctionCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "nounId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endTime", + type: "uint256", + }, + ], + name: "AuctionExtended", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "minBidIncrementPercentage", + type: "uint256", + }, + ], + name: "AuctionMinBidIncrementPercentageUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "reservePrice", + type: "uint256", + }, + ], + name: "AuctionReservePriceUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "nounId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "winner", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "AuctionSettled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "nounId", + type: "uint256", + }, + { + indexed: true, + internalType: "uint32", + name: "clientId", + type: "uint32", + }, + ], + name: "AuctionSettledWithClientId", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "timeBuffer", + type: "uint256", + }, + ], + name: "AuctionTimeBufferUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Paused", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "newSanctionsOracle", + type: "address", + }, + ], + name: "SanctionsOracleSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "account", + type: "address", + }, + ], + name: "Unpaused", + type: "event", + }, + { + inputs: [], + name: "MAX_TIME_BUFFER", + outputs: [{ internalType: "uint56", name: "", type: "uint56" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "auction", + outputs: [ + { + components: [ + { internalType: "uint96", name: "nounId", type: "uint96" }, + { internalType: "uint128", name: "amount", type: "uint128" }, + { internalType: "uint40", name: "startTime", type: "uint40" }, + { internalType: "uint40", name: "endTime", type: "uint40" }, + { + internalType: "address payable", + name: "bidder", + type: "address", + }, + { internalType: "bool", name: "settled", type: "bool" }, + ], + internalType: "struct INounsAuctionHouseV3.AuctionV2View", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "auctionStorage", + outputs: [ + { internalType: "uint96", name: "nounId", type: "uint96" }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + { internalType: "uint128", name: "amount", type: "uint128" }, + { internalType: "uint40", name: "startTime", type: "uint40" }, + { internalType: "uint40", name: "endTime", type: "uint40" }, + { internalType: "address payable", name: "bidder", type: "address" }, + { internalType: "bool", name: "settled", type: "bool" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "nounId", type: "uint256" }], + name: "biddingClient", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "nounId", type: "uint256" }], + name: "createBid", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "nounId", type: "uint256" }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + ], + name: "createBid", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [], + name: "duration", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "auctionCount", type: "uint256" }, + ], + name: "getPrices", + outputs: [{ internalType: "uint256[]", name: "prices", type: "uint256[]" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "auctionCount", type: "uint256" }, + { internalType: "bool", name: "skipEmptyValues", type: "bool" }, + ], + name: "getSettlements", + outputs: [ + { + components: [ + { internalType: "uint32", name: "blockTimestamp", type: "uint32" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "address", name: "winner", type: "address" }, + { internalType: "uint256", name: "nounId", type: "uint256" }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + ], + internalType: "struct INounsAuctionHouseV3.Settlement[]", + name: "settlements", + type: "tuple[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "startId", type: "uint256" }, + { internalType: "uint256", name: "endId", type: "uint256" }, + { internalType: "bool", name: "skipEmptyValues", type: "bool" }, + ], + name: "getSettlements", + outputs: [ + { + components: [ + { internalType: "uint32", name: "blockTimestamp", type: "uint32" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "address", name: "winner", type: "address" }, + { internalType: "uint256", name: "nounId", type: "uint256" }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + ], + internalType: "struct INounsAuctionHouseV3.Settlement[]", + name: "settlements", + type: "tuple[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "startId", type: "uint256" }, + { internalType: "uint256", name: "endTimestamp", type: "uint256" }, + { internalType: "bool", name: "skipEmptyValues", type: "bool" }, + ], + name: "getSettlementsFromIdtoTimestamp", + outputs: [ + { + components: [ + { internalType: "uint32", name: "blockTimestamp", type: "uint32" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "address", name: "winner", type: "address" }, + { internalType: "uint256", name: "nounId", type: "uint256" }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + ], + internalType: "struct INounsAuctionHouseV3.Settlement[]", + name: "settlements", + type: "tuple[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint192", name: "_reservePrice", type: "uint192" }, + { internalType: "uint56", name: "_timeBuffer", type: "uint56" }, + { + internalType: "uint8", + name: "_minBidIncrementPercentage", + type: "uint8", + }, + { + internalType: "contract IChainalysisSanctionsList", + name: "_sanctionsOracle", + type: "address", + }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "minBidIncrementPercentage", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "nouns", + outputs: [ + { internalType: "contract INounsToken", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "reservePrice", + outputs: [{ internalType: "uint192", name: "", type: "uint192" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "sanctionsOracle", + outputs: [ + { + internalType: "contract IChainalysisSanctionsList", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "uint8", + name: "_minBidIncrementPercentage", + type: "uint8", + }, + ], + name: "setMinBidIncrementPercentage", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "uint32", name: "blockTimestamp", type: "uint32" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + { internalType: "address", name: "winner", type: "address" }, + { internalType: "uint256", name: "nounId", type: "uint256" }, + ], + internalType: "struct INounsAuctionHouseV3.SettlementNoClientId[]", + name: "settlements", + type: "tuple[]", + }, + ], + name: "setPrices", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint192", name: "_reservePrice", type: "uint192" }, + ], + name: "setReservePrice", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "newSanctionsOracle", + type: "address", + }, + ], + name: "setSanctionsOracle", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint56", name: "_timeBuffer", type: "uint56" }], + name: "setTimeBuffer", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "settleAuction", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "settleCurrentAndCreateNewAuction", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "timeBuffer", + outputs: [{ internalType: "uint56", name: "", type: "uint56" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "unpause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "startId", type: "uint256" }, + { internalType: "uint256", name: "endId", type: "uint256" }, + ], + name: "warmUpSettlementState", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "weth", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, +] as const; diff --git a/apps/api/src/clients/nouns/abi/governor.ts b/apps/api/src/clients/nouns/abi/governor.ts new file mode 100644 index 000000000..933ae3775 --- /dev/null +++ b/apps/api/src/clients/nouns/abi/governor.ts @@ -0,0 +1,1936 @@ +export const GovernorAbi = [ + { inputs: [], name: "AdminOnly", type: "error" }, + { inputs: [], name: "CanOnlyInitializeOnce", type: "error" }, + { inputs: [], name: "InvalidNounsAddress", type: "error" }, + { inputs: [], name: "InvalidTimelockAddress", type: "error" }, + { inputs: [], name: "MustProvideActions", type: "error" }, + { inputs: [], name: "ProposalInfoArityMismatch", type: "error" }, + { inputs: [], name: "ProposerAlreadyHasALiveProposal", type: "error" }, + { inputs: [], name: "TooManyActions", type: "error" }, + { inputs: [], name: "UnsafeUint16Cast", type: "error" }, + { inputs: [], name: "VotesBelowProposalThreshold", type: "error" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "numTokens", + type: "uint256", + }, + { indexed: false, internalType: "address", name: "to", type: "address" }, + ], + name: "DAONounsSupplyIncreasedFromEscrow", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256[]", + name: "tokenIds", + type: "uint256[]", + }, + { indexed: false, internalType: "address", name: "to", type: "address" }, + ], + name: "DAOWithdrawNounsFromEscrow", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address[]", + name: "oldErc20Tokens", + type: "address[]", + }, + { + indexed: false, + internalType: "address[]", + name: "newErc20tokens", + type: "address[]", + }, + ], + name: "ERC20TokensToIncludeInForkSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint32", name: "forkId", type: "uint32" }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: false, + internalType: "uint256[]", + name: "tokenIds", + type: "uint256[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "proposalIds", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "EscrowedToFork", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint32", name: "forkId", type: "uint32" }, + { + indexed: false, + internalType: "address", + name: "forkTreasury", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "forkToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "forkEndTimestamp", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "tokensInEscrow", + type: "uint256", + }, + ], + name: "ExecuteFork", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldForkDAODeployer", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newForkDAODeployer", + type: "address", + }, + ], + name: "ForkDAODeployerSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldForkPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newForkPeriod", + type: "uint256", + }, + ], + name: "ForkPeriodSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldForkThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newForkThreshold", + type: "uint256", + }, + ], + name: "ForkThresholdSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint32", name: "forkId", type: "uint32" }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: false, + internalType: "uint256[]", + name: "tokenIds", + type: "uint256[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "proposalIds", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "JoinFork", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint32", + name: "oldLastMinuteWindowInBlocks", + type: "uint32", + }, + { + indexed: false, + internalType: "uint32", + name: "newLastMinuteWindowInBlocks", + type: "uint32", + }, + ], + name: "LastMinuteWindowSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint16", + name: "oldMaxQuorumVotesBPS", + type: "uint16", + }, + { + indexed: false, + internalType: "uint16", + name: "newMaxQuorumVotesBPS", + type: "uint16", + }, + ], + name: "MaxQuorumVotesBPSSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint16", + name: "oldMinQuorumVotesBPS", + type: "uint16", + }, + { + indexed: false, + internalType: "uint16", + name: "newMinQuorumVotesBPS", + type: "uint16", + }, + ], + name: "MinQuorumVotesBPSSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldAdmin", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newAdmin", + type: "address", + }, + ], + name: "NewAdmin", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldPendingAdmin", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newPendingAdmin", + type: "address", + }, + ], + name: "NewPendingAdmin", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldPendingVetoer", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newPendingVetoer", + type: "address", + }, + ], + name: "NewPendingVetoer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldVetoer", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newVetoer", + type: "address", + }, + ], + name: "NewVetoer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint32", + name: "oldObjectionPeriodDurationInBlocks", + type: "uint32", + }, + { + indexed: false, + internalType: "uint32", + name: "newObjectionPeriodDurationInBlocks", + type: "uint32", + }, + ], + name: "ObjectionPeriodDurationSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + ], + name: "ProposalCreatedOnTimelockV1", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "quorumVotes", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreatedWithRequirements", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: false, + internalType: "address[]", + name: "signers", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256", + name: "updatePeriodEndBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "quorumVotes", + type: "uint256", + }, + { + indexed: true, + internalType: "uint32", + name: "clientId", + type: "uint32", + }, + ], + name: "ProposalCreatedWithRequirements", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + { + indexed: false, + internalType: "string", + name: "updateMessage", + type: "string", + }, + ], + name: "ProposalDescriptionUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: false, + internalType: "uint256", + name: "objectionPeriodEndBlock", + type: "uint256", + }, + ], + name: "ProposalObjectionPeriodSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "eta", type: "uint256" }, + ], + name: "ProposalQueued", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldProposalThresholdBPS", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newProposalThresholdBPS", + type: "uint256", + }, + ], + name: "ProposalThresholdBPSSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "string", + name: "updateMessage", + type: "string", + }, + ], + name: "ProposalTransactionsUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint32", + name: "oldProposalUpdatablePeriodInBlocks", + type: "uint32", + }, + { + indexed: false, + internalType: "uint32", + name: "newProposalUpdatablePeriodInBlocks", + type: "uint32", + }, + ], + name: "ProposalUpdatablePeriodSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + { + indexed: false, + internalType: "string", + name: "updateMessage", + type: "string", + }, + ], + name: "ProposalUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + ], + name: "ProposalVetoed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint32", + name: "oldQuorumCoefficient", + type: "uint32", + }, + { + indexed: false, + internalType: "uint32", + name: "newQuorumCoefficient", + type: "uint32", + }, + ], + name: "QuorumCoefficientSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldQuorumVotesBPS", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newQuorumVotesBPS", + type: "uint256", + }, + ], + name: "QuorumVotesBPSSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "refundAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "bool", + name: "refundSent", + type: "bool", + }, + ], + name: "RefundableVote", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "signer", + type: "address", + }, + { indexed: false, internalType: "bytes", name: "sig", type: "bytes" }, + ], + name: "SignatureCancelled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "timelock", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "timelockV1", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "admin", + type: "address", + }, + ], + name: "TimelocksAndAdminSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "votes", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: true, + internalType: "uint32", + name: "clientId", + type: "uint32", + }, + ], + name: "VoteCastWithClientId", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingDelay", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingDelay", + type: "uint256", + }, + ], + name: "VotingDelaySet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingPeriod", + type: "uint256", + }, + ], + name: "VotingPeriodSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + { indexed: false, internalType: "bool", name: "sent", type: "bool" }, + ], + name: "Withdraw", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint32", name: "forkId", type: "uint32" }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: false, + internalType: "uint256[]", + name: "tokenIds", + type: "uint256[]", + }, + ], + name: "WithdrawFromForkEscrow", + type: "event", + }, + { stateMutability: "payable", type: "fallback" }, + { + inputs: [], + name: "MAX_PROPOSAL_THRESHOLD_BPS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "MAX_VOTING_DELAY", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "MAX_VOTING_PERIOD", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "MIN_PROPOSAL_THRESHOLD_BPS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "MIN_VOTING_DELAY", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "MIN_VOTING_PERIOD", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "adjustedTotalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "admin", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "cancel", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes", name: "sig", type: "bytes" }], + name: "cancelSig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castRefundableVote", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + ], + name: "castRefundableVote", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castRefundableVoteWithReason", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + ], + name: "castRefundableVoteWithReason", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteBySig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { + internalType: "uint256", + name: "adjustedTotalSupply_", + type: "uint256", + }, + { + components: [ + { internalType: "uint16", name: "minQuorumVotesBPS", type: "uint16" }, + { internalType: "uint16", name: "maxQuorumVotesBPS", type: "uint16" }, + { internalType: "uint32", name: "quorumCoefficient", type: "uint32" }, + ], + internalType: "struct NounsDAOTypes.DynamicQuorumParams", + name: "params", + type: "tuple", + }, + ], + name: "dynamicQuorumVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "erc20TokensToIncludeInFork", + outputs: [{ internalType: "address[]", name: "", type: "address[]" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "tokenIds", type: "uint256[]" }, + { internalType: "uint256[]", name: "proposalIds", type: "uint256[]" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "escrowToFork", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "execute", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "executeFork", + outputs: [ + { internalType: "address", name: "forkTreasury", type: "address" }, + { internalType: "address", name: "forkToken", type: "address" }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "forkDAODeployer", + outputs: [ + { internalType: "contract IForkDAODeployer", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "forkEndTimestamp", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "forkEscrow", + outputs: [ + { + internalType: "contract INounsDAOForkEscrow", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "forkPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "forkThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "forkThresholdBPS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "getActions", + outputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "blockNumber_", type: "uint256" }, + ], + name: "getDynamicQuorumParamsAt", + outputs: [ + { + components: [ + { internalType: "uint16", name: "minQuorumVotesBPS", type: "uint16" }, + { internalType: "uint16", name: "maxQuorumVotesBPS", type: "uint16" }, + { internalType: "uint32", name: "quorumCoefficient", type: "uint32" }, + ], + internalType: "struct NounsDAOTypes.DynamicQuorumParams", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "voter", type: "address" }, + ], + name: "getReceipt", + outputs: [ + { + components: [ + { internalType: "bool", name: "hasVoted", type: "bool" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint96", name: "votes", type: "uint96" }, + ], + internalType: "struct NounsDAOTypes.Receipt", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "timelock_", type: "address" }, + { internalType: "address", name: "nouns_", type: "address" }, + { internalType: "address", name: "forkEscrow_", type: "address" }, + { internalType: "address", name: "forkDAODeployer_", type: "address" }, + { internalType: "address", name: "vetoer_", type: "address" }, + { + components: [ + { internalType: "uint256", name: "votingPeriod", type: "uint256" }, + { internalType: "uint256", name: "votingDelay", type: "uint256" }, + { + internalType: "uint256", + name: "proposalThresholdBPS", + type: "uint256", + }, + { + internalType: "uint32", + name: "lastMinuteWindowInBlocks", + type: "uint32", + }, + { + internalType: "uint32", + name: "objectionPeriodDurationInBlocks", + type: "uint32", + }, + { + internalType: "uint32", + name: "proposalUpdatablePeriodInBlocks", + type: "uint32", + }, + ], + internalType: "struct NounsDAOTypes.NounsDAOParams", + name: "daoParams_", + type: "tuple", + }, + { + components: [ + { internalType: "uint16", name: "minQuorumVotesBPS", type: "uint16" }, + { internalType: "uint16", name: "maxQuorumVotesBPS", type: "uint16" }, + { internalType: "uint32", name: "quorumCoefficient", type: "uint32" }, + ], + internalType: "struct NounsDAOTypes.DynamicQuorumParams", + name: "dynamicQuorumParams_", + type: "tuple", + }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "tokenIds", type: "uint256[]" }, + { internalType: "uint256[]", name: "proposalIds", type: "uint256[]" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "joinFork", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "lastMinuteWindowInBlocks", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "latestProposalIds", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "maxQuorumVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "minQuorumVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "nouns", + outputs: [ + { internalType: "contract NounsTokenLike", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "numTokensInForkEscrow", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "objectionPeriodDurationInBlocks", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pendingVetoer", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalCount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "firstProposalId", type: "uint256" }, + { internalType: "uint256", name: "lastProposalId", type: "uint256" }, + { + internalType: "uint16", + name: "proposalEligibilityQuorumBps", + type: "uint16", + }, + { internalType: "bool", name: "excludeCanceled", type: "bool" }, + { internalType: "bool", name: "requireVotingEnded", type: "bool" }, + { internalType: "uint32[]", name: "votingClientIds", type: "uint32[]" }, + ], + name: "proposalDataForRewards", + outputs: [ + { + components: [ + { internalType: "uint256", name: "endBlock", type: "uint256" }, + { + internalType: "uint256", + name: "objectionPeriodEndBlock", + type: "uint256", + }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + { internalType: "uint256", name: "totalSupply", type: "uint256" }, + { + internalType: "uint256", + name: "creationTimestamp", + type: "uint256", + }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + { + components: [ + { internalType: "uint32", name: "votes", type: "uint32" }, + { internalType: "uint32", name: "txs", type: "uint32" }, + ], + internalType: "struct NounsDAOTypes.ClientVoteData[]", + name: "voteData", + type: "tuple[]", + }, + ], + internalType: "struct NounsDAOTypes.ProposalForRewards[]", + name: "", + type: "tuple[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalMaxOperations", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalThresholdBPS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalUpdatablePeriodInBlocks", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposals", + outputs: [ + { + components: [ + { internalType: "uint256", name: "id", type: "uint256" }, + { internalType: "address", name: "proposer", type: "address" }, + { + internalType: "uint256", + name: "proposalThreshold", + type: "uint256", + }, + { internalType: "uint256", name: "quorumVotes", type: "uint256" }, + { internalType: "uint256", name: "eta", type: "uint256" }, + { internalType: "uint256", name: "startBlock", type: "uint256" }, + { internalType: "uint256", name: "endBlock", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + { internalType: "bool", name: "canceled", type: "bool" }, + { internalType: "bool", name: "vetoed", type: "bool" }, + { internalType: "bool", name: "executed", type: "bool" }, + { internalType: "uint256", name: "totalSupply", type: "uint256" }, + { internalType: "uint256", name: "creationBlock", type: "uint256" }, + ], + internalType: "struct NounsDAOTypes.ProposalCondensedV2", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalsV3", + outputs: [ + { + components: [ + { internalType: "uint256", name: "id", type: "uint256" }, + { internalType: "address", name: "proposer", type: "address" }, + { + internalType: "uint256", + name: "proposalThreshold", + type: "uint256", + }, + { internalType: "uint256", name: "quorumVotes", type: "uint256" }, + { internalType: "uint256", name: "eta", type: "uint256" }, + { internalType: "uint256", name: "startBlock", type: "uint256" }, + { internalType: "uint256", name: "endBlock", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + { internalType: "bool", name: "canceled", type: "bool" }, + { internalType: "bool", name: "vetoed", type: "bool" }, + { internalType: "bool", name: "executed", type: "bool" }, + { internalType: "uint256", name: "totalSupply", type: "uint256" }, + { internalType: "uint256", name: "creationBlock", type: "uint256" }, + { internalType: "address[]", name: "signers", type: "address[]" }, + { + internalType: "uint256", + name: "updatePeriodEndBlock", + type: "uint256", + }, + { + internalType: "uint256", + name: "objectionPeriodEndBlock", + type: "uint256", + }, + { internalType: "bool", name: "executeOnTimelockV1", type: "bool" }, + ], + internalType: "struct NounsDAOTypes.ProposalCondensedV3", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "bytes", name: "sig", type: "bytes" }, + { internalType: "address", name: "signer", type: "address" }, + { + internalType: "uint256", + name: "expirationTimestamp", + type: "uint256", + }, + ], + internalType: "struct NounsDAOTypes.ProposerSignature[]", + name: "proposerSignatures", + type: "tuple[]", + }, + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "proposeBySigs", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "bytes", name: "sig", type: "bytes" }, + { internalType: "address", name: "signer", type: "address" }, + { + internalType: "uint256", + name: "expirationTimestamp", + type: "uint256", + }, + ], + internalType: "struct NounsDAOTypes.ProposerSignature[]", + name: "proposerSignatures", + type: "tuple[]", + }, + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + ], + name: "proposeBySigs", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "proposeOnTimelockV1", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "uint32", name: "clientId", type: "uint32" }, + ], + name: "proposeOnTimelockV1", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "queue", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "quorumParamsCheckpoints", + outputs: [ + { + components: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { + components: [ + { + internalType: "uint16", + name: "minQuorumVotesBPS", + type: "uint16", + }, + { + internalType: "uint16", + name: "maxQuorumVotesBPS", + type: "uint16", + }, + { + internalType: "uint32", + name: "quorumCoefficient", + type: "uint32", + }, + ], + internalType: "struct NounsDAOTypes.DynamicQuorumParams", + name: "params", + type: "tuple", + }, + ], + internalType: "struct NounsDAOTypes.DynamicQuorumParamsCheckpoint[]", + name: "", + type: "tuple[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "index", type: "uint256" }], + name: "quorumParamsCheckpoints", + outputs: [ + { + components: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { + components: [ + { + internalType: "uint16", + name: "minQuorumVotesBPS", + type: "uint16", + }, + { + internalType: "uint16", + name: "maxQuorumVotesBPS", + type: "uint16", + }, + { + internalType: "uint32", + name: "quorumCoefficient", + type: "uint32", + }, + ], + internalType: "struct NounsDAOTypes.DynamicQuorumParams", + name: "params", + type: "tuple", + }, + ], + internalType: "struct NounsDAOTypes.DynamicQuorumParamsCheckpoint", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "quorumVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "quorumVotesBPS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "state", + outputs: [ + { + internalType: "enum NounsDAOTypes.ProposalState", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelock", + outputs: [ + { internalType: "contract INounsDAOExecutor", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelockV1", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "string", name: "updateMessage", type: "string" }, + ], + name: "updateProposal", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { + components: [ + { internalType: "bytes", name: "sig", type: "bytes" }, + { internalType: "address", name: "signer", type: "address" }, + { + internalType: "uint256", + name: "expirationTimestamp", + type: "uint256", + }, + ], + internalType: "struct NounsDAOTypes.ProposerSignature[]", + name: "proposerSignatures", + type: "tuple[]", + }, + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "string", name: "updateMessage", type: "string" }, + ], + name: "updateProposalBySigs", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "string", name: "updateMessage", type: "string" }, + ], + name: "updateProposalDescription", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "updateMessage", type: "string" }, + ], + name: "updateProposalTransactions", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "veto", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "vetoer", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "voteSnapshotBlockSwitchProposalId", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "tokenIds", type: "uint256[]" }, + { internalType: "address", name: "to", type: "address" }, + ], + name: "withdrawDAONounsFromEscrowIncreasingTotalSupply", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "tokenIds", type: "uint256[]" }, + ], + name: "withdrawDAONounsFromEscrowToTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "tokenIds", type: "uint256[]" }, + ], + name: "withdrawFromForkEscrow", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { stateMutability: "payable", type: "receive" }, +] as const; diff --git a/apps/api/src/clients/nouns/abi/index.ts b/apps/api/src/clients/nouns/abi/index.ts new file mode 100644 index 000000000..439f9418c --- /dev/null +++ b/apps/api/src/clients/nouns/abi/index.ts @@ -0,0 +1,4 @@ +export { GovernorAbi } from "./governor"; +export { LegacyGovernorABI } from "./legacyGovernor"; +export { TokenAbi } from "./token"; +export { AuctionAbi } from "./auction"; diff --git a/apps/api/src/clients/nouns/abi/legacyGovernor.ts b/apps/api/src/clients/nouns/abi/legacyGovernor.ts new file mode 100644 index 000000000..21349e3d8 --- /dev/null +++ b/apps/api/src/clients/nouns/abi/legacyGovernor.ts @@ -0,0 +1,2098 @@ +export const LegacyGovernorABI = [ + { inputs: [], name: "AdminOnly", type: "error" }, + { inputs: [], name: "CanOnlyInitializeOnce", type: "error" }, + { inputs: [], name: "InvalidNounsAddress", type: "error" }, + { inputs: [], name: "InvalidTimelockAddress", type: "error" }, + { inputs: [], name: "MustProvideActions", type: "error" }, + { inputs: [], name: "ProposalInfoArityMismatch", type: "error" }, + { inputs: [], name: "ProposerAlreadyHasALiveProposal", type: "error" }, + { inputs: [], name: "TooManyActions", type: "error" }, + { inputs: [], name: "UnsafeUint16Cast", type: "error" }, + { inputs: [], name: "VotesBelowProposalThreshold", type: "error" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "numTokens", + type: "uint256", + }, + { indexed: false, internalType: "address", name: "to", type: "address" }, + ], + name: "DAONounsSupplyIncreasedFromEscrow", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256[]", + name: "tokenIds", + type: "uint256[]", + }, + { indexed: false, internalType: "address", name: "to", type: "address" }, + ], + name: "DAOWithdrawNounsFromEscrow", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address[]", + name: "oldErc20Tokens", + type: "address[]", + }, + { + indexed: false, + internalType: "address[]", + name: "newErc20tokens", + type: "address[]", + }, + ], + name: "ERC20TokensToIncludeInForkSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint32", name: "forkId", type: "uint32" }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: false, + internalType: "uint256[]", + name: "tokenIds", + type: "uint256[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "proposalIds", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "EscrowedToFork", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint32", name: "forkId", type: "uint32" }, + { + indexed: false, + internalType: "address", + name: "forkTreasury", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "forkToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "forkEndTimestamp", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "tokensInEscrow", + type: "uint256", + }, + ], + name: "ExecuteFork", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldForkDAODeployer", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newForkDAODeployer", + type: "address", + }, + ], + name: "ForkDAODeployerSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldForkPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newForkPeriod", + type: "uint256", + }, + ], + name: "ForkPeriodSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldForkThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newForkThreshold", + type: "uint256", + }, + ], + name: "ForkThresholdSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint32", name: "forkId", type: "uint32" }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: false, + internalType: "uint256[]", + name: "tokenIds", + type: "uint256[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "proposalIds", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "JoinFork", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint32", + name: "oldLastMinuteWindowInBlocks", + type: "uint32", + }, + { + indexed: false, + internalType: "uint32", + name: "newLastMinuteWindowInBlocks", + type: "uint32", + }, + ], + name: "LastMinuteWindowSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint16", + name: "oldMaxQuorumVotesBPS", + type: "uint16", + }, + { + indexed: false, + internalType: "uint16", + name: "newMaxQuorumVotesBPS", + type: "uint16", + }, + ], + name: "MaxQuorumVotesBPSSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint16", + name: "oldMinQuorumVotesBPS", + type: "uint16", + }, + { + indexed: false, + internalType: "uint16", + name: "newMinQuorumVotesBPS", + type: "uint16", + }, + ], + name: "MinQuorumVotesBPSSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldAdmin", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newAdmin", + type: "address", + }, + ], + name: "NewAdmin", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldImplementation", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newImplementation", + type: "address", + }, + ], + name: "NewImplementation", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldPendingAdmin", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newPendingAdmin", + type: "address", + }, + ], + name: "NewPendingAdmin", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldPendingVetoer", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newPendingVetoer", + type: "address", + }, + ], + name: "NewPendingVetoer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldVetoer", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newVetoer", + type: "address", + }, + ], + name: "NewVetoer", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint32", + name: "oldObjectionPeriodDurationInBlocks", + type: "uint32", + }, + { + indexed: false, + internalType: "uint32", + name: "newObjectionPeriodDurationInBlocks", + type: "uint32", + }, + ], + name: "ObjectionPeriodDurationSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + ], + name: "ProposalCreatedOnTimelockV1", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "signers", + type: "address[]", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "updatePeriodEndBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "quorumVotes", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreatedWithRequirements", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "quorumVotes", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreatedWithRequirements", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + { + indexed: false, + internalType: "string", + name: "updateMessage", + type: "string", + }, + ], + name: "ProposalDescriptionUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: false, + internalType: "uint256", + name: "objectionPeriodEndBlock", + type: "uint256", + }, + ], + name: "ProposalObjectionPeriodSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + { indexed: false, internalType: "uint256", name: "eta", type: "uint256" }, + ], + name: "ProposalQueued", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldProposalThresholdBPS", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newProposalThresholdBPS", + type: "uint256", + }, + ], + name: "ProposalThresholdBPSSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "string", + name: "updateMessage", + type: "string", + }, + ], + name: "ProposalTransactionsUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint32", + name: "oldProposalUpdatablePeriodInBlocks", + type: "uint32", + }, + { + indexed: false, + internalType: "uint32", + name: "newProposalUpdatablePeriodInBlocks", + type: "uint32", + }, + ], + name: "ProposalUpdatablePeriodSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint256", name: "id", type: "uint256" }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + { + indexed: false, + internalType: "string", + name: "updateMessage", + type: "string", + }, + ], + name: "ProposalUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint256", name: "id", type: "uint256" }, + ], + name: "ProposalVetoed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint32", + name: "oldQuorumCoefficient", + type: "uint32", + }, + { + indexed: false, + internalType: "uint32", + name: "newQuorumCoefficient", + type: "uint32", + }, + ], + name: "QuorumCoefficientSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldQuorumVotesBPS", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newQuorumVotesBPS", + type: "uint256", + }, + ], + name: "QuorumVotesBPSSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "refundAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "bool", + name: "refundSent", + type: "bool", + }, + ], + name: "RefundableVote", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "signer", + type: "address", + }, + { indexed: false, internalType: "bytes", name: "sig", type: "bytes" }, + ], + name: "SignatureCancelled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "timelock", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "timelockV1", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "admin", + type: "address", + }, + ], + name: "TimelocksAndAdminSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "votes", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVoteSnapshotBlockSwitchProposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVoteSnapshotBlockSwitchProposalId", + type: "uint256", + }, + ], + name: "VoteSnapshotBlockSwitchProposalIdSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingDelay", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingDelay", + type: "uint256", + }, + ], + name: "VotingDelaySet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingPeriod", + type: "uint256", + }, + ], + name: "VotingPeriodSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + { indexed: false, internalType: "bool", name: "sent", type: "bool" }, + ], + name: "Withdraw", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "uint32", name: "forkId", type: "uint32" }, + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: false, + internalType: "uint256[]", + name: "tokenIds", + type: "uint256[]", + }, + ], + name: "WithdrawFromForkEscrow", + type: "event", + }, + { + inputs: [], + name: "MAX_PROPOSAL_THRESHOLD_BPS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "MAX_VOTING_DELAY", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "MAX_VOTING_PERIOD", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "MIN_PROPOSAL_THRESHOLD_BPS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "MIN_VOTING_DELAY", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "MIN_VOTING_PERIOD", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "_acceptAdmin", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "_acceptVetoer", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "_burnVetoPower", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint16", name: "newMinQuorumVotesBPS", type: "uint16" }, + { internalType: "uint16", name: "newMaxQuorumVotesBPS", type: "uint16" }, + { internalType: "uint32", name: "newQuorumCoefficient", type: "uint32" }, + ], + name: "_setDynamicQuorumParams", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "erc20tokens", type: "address[]" }, + ], + name: "_setErc20TokensToIncludeInFork", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "newForkDAODeployer", type: "address" }, + ], + name: "_setForkDAODeployer", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "newForkEscrow", type: "address" }, + ], + name: "_setForkEscrow", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "forkEscrow_", type: "address" }, + { internalType: "address", name: "forkDAODeployer_", type: "address" }, + { + internalType: "address[]", + name: "erc20TokensToIncludeInFork_", + type: "address[]", + }, + { internalType: "uint256", name: "forkPeriod_", type: "uint256" }, + { internalType: "uint256", name: "forkThresholdBPS_", type: "uint256" }, + ], + name: "_setForkParams", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newForkPeriod", type: "uint256" }, + ], + name: "_setForkPeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newForkThresholdBPS", type: "uint256" }, + ], + name: "_setForkThresholdBPS", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint32", + name: "newLastMinuteWindowInBlocks", + type: "uint32", + }, + ], + name: "_setLastMinuteWindowInBlocks", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint16", name: "newMaxQuorumVotesBPS", type: "uint16" }, + ], + name: "_setMaxQuorumVotesBPS", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint16", name: "newMinQuorumVotesBPS", type: "uint16" }, + ], + name: "_setMinQuorumVotesBPS", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint32", + name: "newObjectionPeriodDurationInBlocks", + type: "uint32", + }, + ], + name: "_setObjectionPeriodDurationInBlocks", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "newPendingAdmin", type: "address" }, + ], + name: "_setPendingAdmin", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "newPendingVetoer", type: "address" }, + ], + name: "_setPendingVetoer", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newProposalThresholdBPS", + type: "uint256", + }, + ], + name: "_setProposalThresholdBPS", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint32", + name: "newProposalUpdatablePeriodInBlocks", + type: "uint32", + }, + ], + name: "_setProposalUpdatablePeriodInBlocks", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint32", name: "newQuorumCoefficient", type: "uint32" }, + ], + name: "_setQuorumCoefficient", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "newTimelock", type: "address" }, + { internalType: "address", name: "newTimelockV1", type: "address" }, + { internalType: "address", name: "newAdmin", type: "address" }, + ], + name: "_setTimelocksAndAdmin", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "_setVoteSnapshotBlockSwitchProposalId", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingDelay", type: "uint256" }, + ], + name: "_setVotingDelay", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingPeriod", type: "uint256" }, + ], + name: "_setVotingPeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "_withdraw", + outputs: [ + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bool", name: "", type: "bool" }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "adjustedTotalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "cancel", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes", name: "sig", type: "bytes" }], + name: "cancelSig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castRefundableVote", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castRefundableVoteWithReason", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteBySig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { + internalType: "uint256", + name: "adjustedTotalSupply_", + type: "uint256", + }, + { + components: [ + { internalType: "uint16", name: "minQuorumVotesBPS", type: "uint16" }, + { internalType: "uint16", name: "maxQuorumVotesBPS", type: "uint16" }, + { internalType: "uint32", name: "quorumCoefficient", type: "uint32" }, + ], + internalType: "struct NounsDAOStorageV3.DynamicQuorumParams", + name: "params", + type: "tuple", + }, + ], + name: "dynamicQuorumVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "erc20TokensToIncludeInFork", + outputs: [{ internalType: "address[]", name: "", type: "address[]" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "tokenIds", type: "uint256[]" }, + { internalType: "uint256[]", name: "proposalIds", type: "uint256[]" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "escrowToFork", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "execute", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "executeFork", + outputs: [ + { internalType: "address", name: "forkTreasury", type: "address" }, + { internalType: "address", name: "forkToken", type: "address" }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "executeOnTimelockV1", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "forkDAODeployer", + outputs: [ + { internalType: "contract IForkDAODeployer", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "forkEndTimestamp", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "forkEscrow", + outputs: [ + { + internalType: "contract INounsDAOForkEscrow", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "forkPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "forkThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "forkThresholdBPS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "getActions", + outputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "blockNumber_", type: "uint256" }, + ], + name: "getDynamicQuorumParamsAt", + outputs: [ + { + components: [ + { internalType: "uint16", name: "minQuorumVotesBPS", type: "uint16" }, + { internalType: "uint16", name: "maxQuorumVotesBPS", type: "uint16" }, + { internalType: "uint32", name: "quorumCoefficient", type: "uint32" }, + ], + internalType: "struct NounsDAOStorageV3.DynamicQuorumParams", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "voter", type: "address" }, + ], + name: "getReceipt", + outputs: [ + { + components: [ + { internalType: "bool", name: "hasVoted", type: "bool" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint96", name: "votes", type: "uint96" }, + ], + internalType: "struct NounsDAOStorageV3.Receipt", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "timelock_", type: "address" }, + { internalType: "address", name: "nouns_", type: "address" }, + { internalType: "address", name: "forkEscrow_", type: "address" }, + { internalType: "address", name: "forkDAODeployer_", type: "address" }, + { internalType: "address", name: "vetoer_", type: "address" }, + { + components: [ + { internalType: "uint256", name: "votingPeriod", type: "uint256" }, + { internalType: "uint256", name: "votingDelay", type: "uint256" }, + { + internalType: "uint256", + name: "proposalThresholdBPS", + type: "uint256", + }, + { + internalType: "uint32", + name: "lastMinuteWindowInBlocks", + type: "uint32", + }, + { + internalType: "uint32", + name: "objectionPeriodDurationInBlocks", + type: "uint32", + }, + { + internalType: "uint32", + name: "proposalUpdatablePeriodInBlocks", + type: "uint32", + }, + ], + internalType: "struct NounsDAOStorageV3.NounsDAOParams", + name: "daoParams_", + type: "tuple", + }, + { + components: [ + { internalType: "uint16", name: "minQuorumVotesBPS", type: "uint16" }, + { internalType: "uint16", name: "maxQuorumVotesBPS", type: "uint16" }, + { internalType: "uint32", name: "quorumCoefficient", type: "uint32" }, + ], + internalType: "struct NounsDAOStorageV3.DynamicQuorumParams", + name: "dynamicQuorumParams_", + type: "tuple", + }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "tokenIds", type: "uint256[]" }, + { internalType: "uint256[]", name: "proposalIds", type: "uint256[]" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "joinFork", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "lastMinuteWindowInBlocks", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "latestProposalIds", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "maxQuorumVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "minQuorumVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "nouns", + outputs: [ + { internalType: "contract NounsTokenLike", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "numTokensInForkEscrow", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "objectionPeriodDurationInBlocks", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "pendingVetoer", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalCount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalMaxOperations", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalThresholdBPS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalUpdatablePeriodInBlocks", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposals", + outputs: [ + { + components: [ + { internalType: "uint256", name: "id", type: "uint256" }, + { internalType: "address", name: "proposer", type: "address" }, + { + internalType: "uint256", + name: "proposalThreshold", + type: "uint256", + }, + { internalType: "uint256", name: "quorumVotes", type: "uint256" }, + { internalType: "uint256", name: "eta", type: "uint256" }, + { internalType: "uint256", name: "startBlock", type: "uint256" }, + { internalType: "uint256", name: "endBlock", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + { internalType: "bool", name: "canceled", type: "bool" }, + { internalType: "bool", name: "vetoed", type: "bool" }, + { internalType: "bool", name: "executed", type: "bool" }, + { internalType: "uint256", name: "totalSupply", type: "uint256" }, + { internalType: "uint256", name: "creationBlock", type: "uint256" }, + ], + internalType: "struct NounsDAOStorageV2.ProposalCondensed", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalsV3", + outputs: [ + { + components: [ + { internalType: "uint256", name: "id", type: "uint256" }, + { internalType: "address", name: "proposer", type: "address" }, + { + internalType: "uint256", + name: "proposalThreshold", + type: "uint256", + }, + { internalType: "uint256", name: "quorumVotes", type: "uint256" }, + { internalType: "uint256", name: "eta", type: "uint256" }, + { internalType: "uint256", name: "startBlock", type: "uint256" }, + { internalType: "uint256", name: "endBlock", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + { internalType: "bool", name: "canceled", type: "bool" }, + { internalType: "bool", name: "vetoed", type: "bool" }, + { internalType: "bool", name: "executed", type: "bool" }, + { internalType: "uint256", name: "totalSupply", type: "uint256" }, + { internalType: "uint256", name: "creationBlock", type: "uint256" }, + { internalType: "address[]", name: "signers", type: "address[]" }, + { + internalType: "uint256", + name: "updatePeriodEndBlock", + type: "uint256", + }, + { + internalType: "uint256", + name: "objectionPeriodEndBlock", + type: "uint256", + }, + { internalType: "bool", name: "executeOnTimelockV1", type: "bool" }, + ], + internalType: "struct NounsDAOStorageV3.ProposalCondensed", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "bytes", name: "sig", type: "bytes" }, + { internalType: "address", name: "signer", type: "address" }, + { + internalType: "uint256", + name: "expirationTimestamp", + type: "uint256", + }, + ], + internalType: "struct NounsDAOStorageV3.ProposerSignature[]", + name: "proposerSignatures", + type: "tuple[]", + }, + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "proposeBySigs", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "proposeOnTimelockV1", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "queue", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "quorumParamsCheckpoints", + outputs: [ + { + components: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { + components: [ + { + internalType: "uint16", + name: "minQuorumVotesBPS", + type: "uint16", + }, + { + internalType: "uint16", + name: "maxQuorumVotesBPS", + type: "uint16", + }, + { + internalType: "uint32", + name: "quorumCoefficient", + type: "uint32", + }, + ], + internalType: "struct NounsDAOStorageV3.DynamicQuorumParams", + name: "params", + type: "tuple", + }, + ], + internalType: + "struct NounsDAOStorageV3.DynamicQuorumParamsCheckpoint[]", + name: "", + type: "tuple[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "index", type: "uint256" }], + name: "quorumParamsCheckpoints", + outputs: [ + { + components: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { + components: [ + { + internalType: "uint16", + name: "minQuorumVotesBPS", + type: "uint16", + }, + { + internalType: "uint16", + name: "maxQuorumVotesBPS", + type: "uint16", + }, + { + internalType: "uint32", + name: "quorumCoefficient", + type: "uint32", + }, + ], + internalType: "struct NounsDAOStorageV3.DynamicQuorumParams", + name: "params", + type: "tuple", + }, + ], + internalType: "struct NounsDAOStorageV3.DynamicQuorumParamsCheckpoint", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "quorumVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "quorumVotesBPS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "state", + outputs: [ + { + internalType: "enum NounsDAOStorageV3.ProposalState", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelock", + outputs: [ + { internalType: "contract INounsDAOExecutor", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelockV1", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "string", name: "updateMessage", type: "string" }, + ], + name: "updateProposal", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { + components: [ + { internalType: "bytes", name: "sig", type: "bytes" }, + { internalType: "address", name: "signer", type: "address" }, + { + internalType: "uint256", + name: "expirationTimestamp", + type: "uint256", + }, + ], + internalType: "struct NounsDAOStorageV3.ProposerSignature[]", + name: "proposerSignatures", + type: "tuple[]", + }, + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "string", name: "updateMessage", type: "string" }, + ], + name: "updateProposalBySigs", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "string", name: "updateMessage", type: "string" }, + ], + name: "updateProposalDescription", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "updateMessage", type: "string" }, + ], + name: "updateProposalTransactions", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "veto", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "vetoer", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "voteSnapshotBlockSwitchProposalId", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "tokenIds", type: "uint256[]" }, + { internalType: "address", name: "to", type: "address" }, + ], + name: "withdrawDAONounsFromEscrowIncreasingTotalSupply", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "tokenIds", type: "uint256[]" }, + ], + name: "withdrawDAONounsFromEscrowToTreasury", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256[]", name: "tokenIds", type: "uint256[]" }, + ], + name: "withdrawFromForkEscrow", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { stateMutability: "payable", type: "receive" }, +] as const; diff --git a/apps/api/src/clients/nouns/abi/token.ts b/apps/api/src/clients/nouns/abi/token.ts new file mode 100644 index 000000000..c1945fe04 --- /dev/null +++ b/apps/api/src/clients/nouns/abi/token.ts @@ -0,0 +1,681 @@ +export const TokenAbi = [ + { + inputs: [ + { internalType: "address", name: "_noundersDAO", type: "address" }, + { internalType: "address", name: "_minter", type: "address" }, + { + internalType: "contract INounsDescriptor", + name: "_descriptor", + type: "address", + }, + { + internalType: "contract INounsSeeder", + name: "_seeder", + type: "address", + }, + { + internalType: "contract IProxyRegistry", + name: "_proxyRegistry", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "approved", + type: "address", + }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "operator", + type: "address", + }, + { indexed: false, internalType: "bool", name: "approved", type: "bool" }, + ], + name: "ApprovalForAll", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "fromDelegate", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "toDelegate", + type: "address", + }, + ], + name: "DelegateChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegate", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "previousBalance", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newBalance", + type: "uint256", + }, + ], + name: "DelegateVotesChanged", + type: "event", + }, + { anonymous: false, inputs: [], name: "DescriptorLocked", type: "event" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "contract INounsDescriptor", + name: "descriptor", + type: "address", + }, + ], + name: "DescriptorUpdated", + type: "event", + }, + { anonymous: false, inputs: [], name: "MinterLocked", type: "event" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "minter", + type: "address", + }, + ], + name: "MinterUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "NounBurned", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + { + components: [ + { internalType: "uint48", name: "background", type: "uint48" }, + { internalType: "uint48", name: "body", type: "uint48" }, + { internalType: "uint48", name: "accessory", type: "uint48" }, + { internalType: "uint48", name: "head", type: "uint48" }, + { internalType: "uint48", name: "glasses", type: "uint48" }, + ], + indexed: false, + internalType: "struct INounsSeeder.Seed", + name: "seed", + type: "tuple", + }, + ], + name: "NounCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "noundersDAO", + type: "address", + }, + ], + name: "NoundersDAOUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { anonymous: false, inputs: [], name: "SeederLocked", type: "event" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "contract INounsSeeder", + name: "seeder", + type: "address", + }, + ], + name: "SeederUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: true, + internalType: "uint256", + name: "tokenId", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [], + name: "DELEGATION_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DOMAIN_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "approve", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "nounId", type: "uint256" }], + name: "burn", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "uint32", name: "", type: "uint32" }, + ], + name: "checkpoints", + outputs: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { internalType: "uint96", name: "votes", type: "uint96" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "contractURI", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "dataURI", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "delegatee", type: "address" }], + name: "delegate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "delegatee", type: "address" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "delegateBySig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "delegator", type: "address" }], + name: "delegates", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "descriptor", + outputs: [ + { internalType: "contract INounsDescriptor", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "getApproved", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getCurrentVotes", + outputs: [{ internalType: "uint96", name: "", type: "uint96" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getPriorVotes", + outputs: [{ internalType: "uint96", name: "", type: "uint96" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "operator", type: "address" }, + ], + name: "isApprovedForAll", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "isDescriptorLocked", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "isMinterLocked", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "isSeederLocked", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "lockDescriptor", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "lockMinter", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "lockSeeder", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "mint", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "minter", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "noundersDAO", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "numCheckpoints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "ownerOf", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proxyRegistry", + outputs: [ + { internalType: "contract IProxyRegistry", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + { internalType: "bytes", name: "_data", type: "bytes" }, + ], + name: "safeTransferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "seeder", + outputs: [ + { internalType: "contract INounsSeeder", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "", type: "uint256" }], + name: "seeds", + outputs: [ + { internalType: "uint48", name: "background", type: "uint48" }, + { internalType: "uint48", name: "body", type: "uint48" }, + { internalType: "uint48", name: "accessory", type: "uint48" }, + { internalType: "uint48", name: "head", type: "uint48" }, + { internalType: "uint48", name: "glasses", type: "uint48" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "operator", type: "address" }, + { internalType: "bool", name: "approved", type: "bool" }, + ], + name: "setApprovalForAll", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "string", name: "newContractURIHash", type: "string" }, + ], + name: "setContractURIHash", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract INounsDescriptor", + name: "_descriptor", + type: "address", + }, + ], + name: "setDescriptor", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "_minter", type: "address" }], + name: "setMinter", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_noundersDAO", type: "address" }, + ], + name: "setNoundersDAO", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract INounsSeeder", + name: "_seeder", + type: "address", + }, + ], + name: "setSeeder", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "index", type: "uint256" }], + name: "tokenByIndex", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "uint256", name: "index", type: "uint256" }, + ], + name: "tokenOfOwnerByIndex", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "tokenId", type: "uint256" }], + name: "tokenURI", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "tokenId", type: "uint256" }, + ], + name: "transferFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "delegator", type: "address" }], + name: "votesToDelegate", + outputs: [{ internalType: "uint96", name: "", type: "uint96" }], + stateMutability: "view", + type: "function", + }, +] as const; diff --git a/apps/indexer/src/indexer/nouns/client.ts b/apps/api/src/clients/nouns/index.ts similarity index 93% rename from apps/indexer/src/indexer/nouns/client.ts rename to apps/api/src/clients/nouns/index.ts index 847eed160..3befd6026 100644 --- a/apps/indexer/src/indexer/nouns/client.ts +++ b/apps/api/src/clients/nouns/index.ts @@ -9,15 +9,15 @@ import { } from "viem"; import { readContract } from "viem/actions"; -import { DAOClient } from "@/interfaces/client"; +import { DAOClient } from "@/clients"; import { GovernorAbi } from "./abi/governor"; import { GovernorBase } from "../governor.base"; export class Client< - TTransport extends Transport = Transport, - TChain extends Chain = Chain, - TAccount extends Account | undefined = Account | undefined, - > + TTransport extends Transport = Transport, + TChain extends Chain = Chain, + TAccount extends Account | undefined = Account | undefined, +> extends GovernorBase implements DAOClient { diff --git a/apps/api/src/clients/obol/abi/governor.ts b/apps/api/src/clients/obol/abi/governor.ts new file mode 100644 index 000000000..ebc242421 --- /dev/null +++ b/apps/api/src/clients/obol/abi/governor.ts @@ -0,0 +1,882 @@ +export const GovernorAbi = [ + { + inputs: [ + { internalType: "contract IVotes", name: "_token", type: "address" }, + { + internalType: "uint256", + name: "_initialQuorumNumerator", + type: "uint256", + }, + { internalType: "uint48", name: "_initialVotingDelay", type: "uint48" }, + { internalType: "uint32", name: "_initialVotingPeriod", type: "uint32" }, + { + internalType: "uint256", + name: "_initialProposalThreshold", + type: "uint256", + }, + { + internalType: "contract TimelockController", + name: "_timelock", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { inputs: [], name: "CheckpointUnorderedInsertion", type: "error" }, + { inputs: [], name: "FailedInnerCall", type: "error" }, + { + inputs: [{ internalType: "address", name: "voter", type: "address" }], + name: "GovernorAlreadyCastVote", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "GovernorAlreadyQueuedProposal", + type: "error", + }, + { + inputs: [], + name: "GovernorCountingFractional_NoVoteWeight", + type: "error", + }, + { + inputs: [], + name: "GovernorCountingFractional__InvalidVoteData", + type: "error", + }, + { + inputs: [], + name: "GovernorCountingFractional__VoteWeightExceeded", + type: "error", + }, + { inputs: [], name: "GovernorDisabledDeposit", type: "error" }, + { + inputs: [ + { internalType: "address", name: "proposer", type: "address" }, + { internalType: "uint256", name: "votes", type: "uint256" }, + { internalType: "uint256", name: "threshold", type: "uint256" }, + ], + name: "GovernorInsufficientProposerVotes", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "targets", type: "uint256" }, + { internalType: "uint256", name: "calldatas", type: "uint256" }, + { internalType: "uint256", name: "values", type: "uint256" }, + ], + name: "GovernorInvalidProposalLength", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "quorumNumerator", type: "uint256" }, + { internalType: "uint256", name: "quorumDenominator", type: "uint256" }, + ], + name: "GovernorInvalidQuorumFraction", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "voter", type: "address" }], + name: "GovernorInvalidSignature", + type: "error", + }, + { inputs: [], name: "GovernorInvalidVoteType", type: "error" }, + { + inputs: [ + { internalType: "uint256", name: "votingPeriod", type: "uint256" }, + ], + name: "GovernorInvalidVotingPeriod", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "GovernorNonexistentProposal", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "GovernorNotQueuedProposal", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "GovernorOnlyExecutor", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "GovernorOnlyProposer", + type: "error", + }, + { inputs: [], name: "GovernorQueueNotImplemented", type: "error" }, + { + inputs: [{ internalType: "address", name: "proposer", type: "address" }], + name: "GovernorRestrictedProposer", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { + internalType: "enum IGovernor.ProposalState", + name: "current", + type: "uint8", + }, + { internalType: "bytes32", name: "expectedStates", type: "bytes32" }, + ], + name: "GovernorUnexpectedProposalState", + type: "error", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "currentNonce", type: "uint256" }, + ], + name: "InvalidAccountNonce", + type: "error", + }, + { inputs: [], name: "InvalidShortString", type: "error" }, + { inputs: [], name: "QueueEmpty", type: "error" }, + { inputs: [], name: "QueueFull", type: "error" }, + { + inputs: [ + { internalType: "uint8", name: "bits", type: "uint8" }, + { internalType: "uint256", name: "value", type: "uint256" }, + ], + name: "SafeCastOverflowedUintDowncast", + type: "error", + }, + { + inputs: [{ internalType: "string", name: "str", type: "string" }], + name: "StringTooLong", + type: "error", + }, + { anonymous: false, inputs: [], name: "EIP712DomainChanged", type: "event" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "voteStart", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "voteEnd", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "etaSeconds", + type: "uint256", + }, + ], + name: "ProposalQueued", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldProposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "ProposalThresholdSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldQuorumNumerator", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newQuorumNumerator", + type: "uint256", + }, + ], + name: "QuorumNumeratorUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldTimelock", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newTimelock", + type: "address", + }, + ], + name: "TimelockChange", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + { indexed: false, internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "VoteCastWithParams", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingDelay", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingDelay", + type: "uint256", + }, + ], + name: "VotingDelaySet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingPeriod", + type: "uint256", + }, + ], + name: "VotingPeriodSet", + type: "event", + }, + { + inputs: [], + name: "BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CLOCK_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "COUNTING_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "EXTENDED_BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "cancel", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "address", name: "voter", type: "address" }, + { internalType: "bytes", name: "signature", type: "bytes" }, + ], + name: "castVoteBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "castVoteWithReasonAndParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "address", name: "voter", type: "address" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + { internalType: "bytes", name: "signature", type: "bytes" }, + ], + name: "castVoteWithReasonAndParamsBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "clock", + outputs: [{ internalType: "uint48", name: "", type: "uint48" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "eip712Domain", + outputs: [ + { internalType: "bytes1", name: "fields", type: "bytes1" }, + { internalType: "string", name: "name", type: "string" }, + { internalType: "string", name: "version", type: "string" }, + { internalType: "uint256", name: "chainId", type: "uint256" }, + { internalType: "address", name: "verifyingContract", type: "address" }, + { internalType: "bytes32", name: "salt", type: "bytes32" }, + { internalType: "uint256[]", name: "extensions", type: "uint256[]" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "execute", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "timepoint", type: "uint256" }, + ], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "timepoint", type: "uint256" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "getVotesWithParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasVoted", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "hashProposal", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155BatchReceived", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC721Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalDeadline", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalEta", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalNeedsQueuing", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalProposer", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalSnapshot", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalVotes", + outputs: [ + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "queue", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "timepoint", type: "uint256" }], + name: "quorum", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "quorumDenominator", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "timepoint", type: "uint256" }], + name: "quorumNumerator", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "quorumNumerator", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "target", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "relay", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "setProposalThreshold", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint48", name: "newVotingDelay", type: "uint48" }, + ], + name: "setVotingDelay", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint32", name: "newVotingPeriod", type: "uint32" }, + ], + name: "setVotingPeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "state", + outputs: [ + { internalType: "enum IGovernor.ProposalState", name: "", type: "uint8" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelock", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [{ internalType: "contract IERC5805", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newQuorumNumerator", type: "uint256" }, + ], + name: "updateQuorumNumerator", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract TimelockController", + name: "newTimelock", + type: "address", + }, + ], + name: "updateTimelock", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "version", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "voteWeightCast", + outputs: [{ internalType: "uint128", name: "", type: "uint128" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { stateMutability: "payable", type: "receive" }, +] as const; diff --git a/apps/api/src/clients/obol/abi/index.ts b/apps/api/src/clients/obol/abi/index.ts new file mode 100644 index 000000000..b039c42a8 --- /dev/null +++ b/apps/api/src/clients/obol/abi/index.ts @@ -0,0 +1,2 @@ +export { GovernorAbi as ObolGovernorAbi } from "./governor"; +export { TokenAbi as ObolTokenAbi } from "./token"; diff --git a/apps/api/src/clients/obol/abi/token.ts b/apps/api/src/clients/obol/abi/token.ts new file mode 100644 index 000000000..c8a319f0d --- /dev/null +++ b/apps/api/src/clients/obol/abi/token.ts @@ -0,0 +1,465 @@ +export const TokenAbi = [ + { + inputs: [ + { internalType: "address", name: "_admin", type: "address" }, + { internalType: "address", name: "_minter", type: "address" }, + { + internalType: "address", + name: "_ensReverseRegistrar", + type: "address", + }, + { internalType: "address", name: "_ensOwner", type: "address" }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "fromDelegate", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "toDelegate", + type: "address", + }, + ], + name: "DelegateChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegate", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "previousBalance", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newBalance", + type: "uint256", + }, + ], + name: "DelegateVotesChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "bytes32", + name: "previousAdminRole", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "newAdminRole", + type: "bytes32", + }, + ], + name: "RoleAdminChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleGranted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleRevoked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [], + name: "DEFAULT_ADMIN_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "MINTER_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "approve", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_amount", type: "uint256" }], + name: "burn", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_owner", type: "address" }, + { internalType: "uint256", name: "_amount", type: "uint256" }, + ], + name: "burnFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint32", name: "pos", type: "uint32" }, + ], + name: "checkpoints", + outputs: [ + { + components: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { internalType: "uint224", name: "votes", type: "uint224" }, + ], + internalType: "struct ERC20Votes.Checkpoint", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "subtractedValue", type: "uint256" }, + ], + name: "decreaseAllowance", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "delegatee", type: "address" }], + name: "delegate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "delegatee", type: "address" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "delegateBySig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "delegates", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "blockNumber", type: "uint256" }], + name: "getPastTotalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getPastVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }], + name: "getRoleAdmin", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "grantRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasRole", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "addedValue", type: "uint256" }, + ], + name: "increaseAllowance", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_to", type: "address" }, + { internalType: "uint256", name: "_amount", type: "uint256" }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "numCheckpoints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "permit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "renounceRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "revokeRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transferFrom", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/apps/indexer/src/indexer/obol/client.ts b/apps/api/src/clients/obol/index.ts similarity index 93% rename from apps/indexer/src/indexer/obol/client.ts rename to apps/api/src/clients/obol/index.ts index 4e54c803e..616fa5b9d 100644 --- a/apps/indexer/src/indexer/obol/client.ts +++ b/apps/api/src/clients/obol/index.ts @@ -9,15 +9,15 @@ import { } from "viem"; import { getBlockNumber, readContract } from "viem/actions"; -import { DAOClient } from "@/interfaces/client"; +import { DAOClient } from "@/clients"; import { ObolGovernorAbi } from "./abi"; import { GovernorBase } from "../governor.base"; export class ObolClient< - TTransport extends Transport = Transport, - TChain extends Chain = Chain, - TAccount extends Account | undefined = Account | undefined, - > + TTransport extends Transport = Transport, + TChain extends Chain = Chain, + TAccount extends Account | undefined = Account | undefined, +> extends GovernorBase implements DAOClient { diff --git a/apps/api/src/clients/op/abi/governor.ts b/apps/api/src/clients/op/abi/governor.ts new file mode 100644 index 000000000..04dac0163 --- /dev/null +++ b/apps/api/src/clients/op/abi/governor.ts @@ -0,0 +1,1134 @@ +export const GovernorAbi = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, + { inputs: [], name: "Empty", type: "error" }, + { inputs: [], name: "InvalidEmptyProposal", type: "error" }, + { inputs: [], name: "InvalidProposalExists", type: "error" }, + { inputs: [], name: "InvalidProposalId", type: "error" }, + { inputs: [], name: "InvalidProposalLength", type: "error" }, + { + inputs: [{ internalType: "uint8", name: "proposalType", type: "uint8" }], + name: "InvalidProposalType", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "target", type: "address" }], + name: "InvalidRelayTarget", + type: "error", + }, + { inputs: [], name: "InvalidVoteType", type: "error" }, + { inputs: [], name: "InvalidVotesBelowThreshold", type: "error" }, + { inputs: [], name: "NotAlligator", type: "error" }, + { inputs: [], name: "NotManagerOrTimelock", type: "error" }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint8", name: "version", type: "uint8" }, + ], + name: "Initialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "oldManager", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newManager", + type: "address", + }, + ], + name: "ManagerSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + { + indexed: false, + internalType: "uint8", + name: "proposalType", + type: "uint8", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "votingModule", + type: "address", + }, + { + indexed: false, + internalType: "bytes", + name: "proposalData", + type: "bytes", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + { + indexed: false, + internalType: "uint8", + name: "proposalType", + type: "uint8", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint64", + name: "deadline", + type: "uint64", + }, + ], + name: "ProposalDeadlineUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint256", name: "eta", type: "uint256" }, + ], + name: "ProposalQueued", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldProposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "ProposalThresholdSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint8", + name: "proposalType", + type: "uint8", + }, + ], + name: "ProposalTypeUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldTimelock", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newTimelock", + type: "address", + }, + ], + name: "TimelockChange", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + { indexed: false, internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "VoteCastWithParams", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingDelay", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingDelay", + type: "uint256", + }, + ], + name: "VotingDelaySet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingPeriod", + type: "uint256", + }, + ], + name: "VotingPeriodSet", + type: "event", + }, + { + inputs: [], + name: "BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "COUNTING_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "EXTENDED_BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "PERCENT_DIVISOR", + outputs: [{ internalType: "uint16", name: "", type: "uint16" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "PROPOSAL_TYPES_CONFIGURATOR", + outputs: [ + { + internalType: "contract IProposalTypesConfigurator", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "VERSION", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "VOTABLE_SUPPLY_ORACLE", + outputs: [ + { + internalType: "contract IVotableSupplyOracle", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "alligator", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "module", type: "address" }], + name: "approvedModules", + outputs: [{ internalType: "bool", name: "approved", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "cancel", + outputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "cancelWithModule", + outputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "voter", type: "address" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "uint256", name: "votes", type: "uint256" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "castVoteFromAlligator", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "castVoteWithReasonAndParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteWithReasonAndParamsBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "proposalType", type: "uint8" }, + ], + name: "editProposalType", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "execute", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "executeWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "getProposalType", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "getVotesWithParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasVoted", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "hashProposal", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "module", type: "address" }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "hashProposalWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "votes", type: "uint256" }, + { internalType: "uint256", name: "accountVotes", type: "uint256" }, + ], + name: "increaseWeightCast", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IVotingToken", + name: "_votingToken", + type: "address", + }, + { + internalType: "contract IVotableSupplyOracle", + name: "_votableSupplyOracle", + type: "address", + }, + { internalType: "address", name: "_manager", type: "address" }, + { internalType: "address", name: "_alligator", type: "address" }, + { + internalType: "contract TimelockControllerUpgradeable", + name: "_timelockAddress", + type: "address", + }, + { + internalType: "contract IProposalTypesConfigurator", + name: "_proposalTypesConfigurator", + type: "address", + }, + { + components: [ + { internalType: "uint16", name: "quorum", type: "uint16" }, + { internalType: "uint16", name: "approvalThreshold", type: "uint16" }, + { internalType: "string", name: "name", type: "string" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "address", name: "module", type: "address" }, + ], + internalType: "struct IProposalTypesConfigurator.ProposalType[]", + name: "_proposalTypes", + type: "tuple[]", + }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "manager", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155BatchReceived", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC721Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalDeadline", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalEta", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalSnapshot", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalVotes", + outputs: [ + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "uint8", name: "proposalType", type: "uint8" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "uint8", name: "proposalType", type: "uint8" }, + ], + name: "proposeWithModule", + outputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "queue", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "queueWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "quorum", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_alligator", type: "address" }, + { + internalType: "address", + name: "_votableSupplyOracle", + type: "address", + }, + { + internalType: "address", + name: "_proposalTypesConfigurator", + type: "address", + }, + { + internalType: "contract TimelockControllerUpgradeable", + name: "_timelockAddress", + type: "address", + }, + ], + name: "reinitialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "target", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "relay", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "_newManager", type: "address" }], + name: "setManager", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "module", type: "address" }, + { internalType: "bool", name: "approved", type: "bool" }, + ], + name: "setModuleApproval", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint64", name: "deadline", type: "uint64" }, + ], + name: "setProposalDeadline", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "setProposalThreshold", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingDelay", type: "uint256" }, + ], + name: "setVotingDelay", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingPeriod", type: "uint256" }, + ], + name: "setVotingPeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "state", + outputs: [ + { + internalType: "enum IGovernorUpgradeable.ProposalState", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelock", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [ + { internalType: "contract IVotingToken", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract TimelockControllerUpgradeable", + name: "newTimelock", + type: "address", + }, + ], + name: "updateTimelock", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "version", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votableSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "blockNumber", type: "uint256" }], + name: "votableSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "weightCast", + outputs: [{ internalType: "uint256", name: "votes", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { stateMutability: "payable", type: "receive" }, +] as const; diff --git a/apps/api/src/clients/op/abi/index.ts b/apps/api/src/clients/op/abi/index.ts new file mode 100644 index 000000000..1fe9f7622 --- /dev/null +++ b/apps/api/src/clients/op/abi/index.ts @@ -0,0 +1,3 @@ +export { GovernorAbi } from "./governor"; +export { LegacyGovernorAbi } from "./legacyGovernor"; +export { TokenAbi } from "./token"; diff --git a/apps/api/src/clients/op/abi/legacyGovernor.ts b/apps/api/src/clients/op/abi/legacyGovernor.ts new file mode 100644 index 000000000..f08923241 --- /dev/null +++ b/apps/api/src/clients/op/abi/legacyGovernor.ts @@ -0,0 +1,1064 @@ +export const LegacyGovernorAbi = [ + { inputs: [], name: "Empty", type: "error" }, + { inputs: [], name: "InvalidProposalId", type: "error" }, + { + inputs: [{ internalType: "uint8", name: "proposalType", type: "uint8" }], + name: "InvalidProposalType", + type: "error", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint8", name: "version", type: "uint8" }, + ], + name: "Initialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + { + indexed: false, + internalType: "uint8", + name: "proposalType", + type: "uint8", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "votingModule", + type: "address", + }, + { + indexed: false, + internalType: "bytes", + name: "proposalData", + type: "bytes", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + { + indexed: false, + internalType: "uint8", + name: "proposalType", + type: "uint8", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "votingModule", + type: "address", + }, + { + indexed: false, + internalType: "bytes", + name: "proposalData", + type: "bytes", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint64", + name: "deadline", + type: "uint64", + }, + ], + name: "ProposalDeadlineUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldProposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "ProposalThresholdSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint8", + name: "proposalType", + type: "uint8", + }, + ], + name: "ProposalTypeUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldQuorumNumerator", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newQuorumNumerator", + type: "uint256", + }, + ], + name: "QuorumNumeratorUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + { indexed: false, internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "VoteCastWithParams", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingDelay", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingDelay", + type: "uint256", + }, + ], + name: "VotingDelaySet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingPeriod", + type: "uint256", + }, + ], + name: "VotingPeriodSet", + type: "event", + }, + { + inputs: [], + name: "ALLIGATOR", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "COUNTING_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "EXTENDED_BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "PERCENT_DIVISOR", + outputs: [{ internalType: "uint16", name: "", type: "uint16" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "PROPOSAL_TYPES_CONFIGURATOR", + outputs: [ + { + internalType: "contract IProposalTypesConfigurator", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "VERSION", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "VOTABLE_SUPPLY_ORACLE", + outputs: [ + { + internalType: "contract IVotableSupplyOracle", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "module", type: "address" }], + name: "approvedModules", + outputs: [{ internalType: "bool", name: "approved", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "cancel", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "cancelWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "voter", type: "address" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "uint256", name: "votes", type: "uint256" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "castVoteFromAlligator", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "castVoteWithReasonAndParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteWithReasonAndParamsBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "proposalType", type: "uint8" }, + ], + name: "editProposalType", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "execute", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "executeWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "getProposalType", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "getVotesWithParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasVoted", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "hashProposal", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "module", type: "address" }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "hashProposalWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "votes", type: "uint256" }, + { internalType: "uint256", name: "accountVotes", type: "uint256" }, + ], + name: "increaseWeightCast", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "manager", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155BatchReceived", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC721Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalDeadline", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalSnapshot", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalVotes", + outputs: [ + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "uint8", name: "proposalType", type: "uint8" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "proposeWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "uint8", name: "proposalType", type: "uint8" }, + ], + name: "proposeWithModule", + outputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "quorum", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "quorumDenominator", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "blockNumber", type: "uint256" }], + name: "quorumNumerator", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "quorumNumerator", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "target", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "relay", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "module", type: "address" }, + { internalType: "bool", name: "approved", type: "bool" }, + ], + name: "setModuleApproval", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint64", name: "deadline", type: "uint64" }, + ], + name: "setProposalDeadline", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "setProposalThreshold", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingDelay", type: "uint256" }, + ], + name: "setVotingDelay", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingPeriod", type: "uint256" }, + ], + name: "setVotingPeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "state", + outputs: [ + { + internalType: "enum IGovernorUpgradeable.ProposalState", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [ + { internalType: "contract IVotesUpgradeable", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token_unused", + outputs: [ + { internalType: "contract IVotesUpgradeable", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newQuorumNumerator", type: "uint256" }, + ], + name: "updateQuorumNumerator", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "version", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votableSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "blockNumber", type: "uint256" }], + name: "votableSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "weightCast", + outputs: [{ internalType: "uint256", name: "votes", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { stateMutability: "payable", type: "receive" }, +] as const; diff --git a/apps/api/src/clients/op/abi/token.ts b/apps/api/src/clients/op/abi/token.ts new file mode 100644 index 000000000..d8c679aac --- /dev/null +++ b/apps/api/src/clients/op/abi/token.ts @@ -0,0 +1,364 @@ +export const TokenAbi = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "fromDelegate", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "toDelegate", + type: "address", + }, + ], + name: "DelegateChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegate", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "previousBalance", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newBalance", + type: "uint256", + }, + ], + name: "DelegateVotesChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "previousOwner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newOwner", + type: "address", + }, + ], + name: "OwnershipTransferred", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "approve", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "amount", type: "uint256" }], + name: "burn", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "burnFrom", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint32", name: "pos", type: "uint32" }, + ], + name: "checkpoints", + outputs: [ + { + components: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { internalType: "uint224", name: "votes", type: "uint224" }, + ], + internalType: "struct ERC20Votes.Checkpoint", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "subtractedValue", type: "uint256" }, + ], + name: "decreaseAllowance", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "delegatee", type: "address" }], + name: "delegate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "delegatee", type: "address" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "delegateBySig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "delegates", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "blockNumber", type: "uint256" }], + name: "getPastTotalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getPastVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "addedValue", type: "uint256" }, + ], + name: "increaseAllowance", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_account", type: "address" }, + { internalType: "uint256", name: "_amount", type: "uint256" }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "numCheckpoints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "permit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transferFrom", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/apps/indexer/src/indexer/op/client.ts b/apps/api/src/clients/op/index.ts similarity index 91% rename from apps/indexer/src/indexer/op/client.ts rename to apps/api/src/clients/op/index.ts index bd95930bf..5a87c78be 100644 --- a/apps/indexer/src/indexer/op/client.ts +++ b/apps/api/src/clients/op/index.ts @@ -9,15 +9,15 @@ import { } from "viem"; import { readContract } from "viem/actions"; -import { DAOClient } from "@/interfaces/client"; +import { DAOClient } from "@/clients"; import { GovernorAbi } from "./abi"; import { GovernorBase } from "../governor.base"; export class OPClient< - TTransport extends Transport = Transport, - TChain extends Chain = Chain, - TAccount extends Account | undefined = Account | undefined, - > + TTransport extends Transport = Transport, + TChain extends Chain = Chain, + TAccount extends Account | undefined = Account | undefined, +> extends GovernorBase implements DAOClient { diff --git a/apps/api/src/clients/scr/abi/governor.ts b/apps/api/src/clients/scr/abi/governor.ts new file mode 100644 index 000000000..a05fba693 --- /dev/null +++ b/apps/api/src/clients/scr/abi/governor.ts @@ -0,0 +1,1124 @@ +export const GovernorAbi = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, + { inputs: [], name: "Empty", type: "error" }, + { inputs: [], name: "InvalidProposalId", type: "error" }, + { + inputs: [{ internalType: "uint8", name: "proposalType", type: "uint8" }], + name: "InvalidProposalType", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "target", type: "address" }], + name: "InvalidRelayTarget", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "oldAdmin", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newAdmin", + type: "address", + }, + ], + name: "AdminSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint8", name: "version", type: "uint8" }, + ], + name: "Initialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "oldManager", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "newManager", + type: "address", + }, + ], + name: "ManagerSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "votingModule", + type: "address", + }, + { + indexed: false, + internalType: "bytes", + name: "proposalData", + type: "bytes", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + { + indexed: false, + internalType: "uint8", + name: "proposalType", + type: "uint8", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "votingModule", + type: "address", + }, + { + indexed: false, + internalType: "bytes", + name: "proposalData", + type: "bytes", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + { + indexed: false, + internalType: "uint8", + name: "proposalType", + type: "uint8", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint64", + name: "deadline", + type: "uint64", + }, + ], + name: "ProposalDeadlineUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint256", name: "eta", type: "uint256" }, + ], + name: "ProposalQueued", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldProposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "ProposalThresholdSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint8", + name: "proposalType", + type: "uint8", + }, + ], + name: "ProposalTypeUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldTimelock", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newTimelock", + type: "address", + }, + ], + name: "TimelockChange", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + { indexed: false, internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "VoteCastWithParams", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingDelay", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingDelay", + type: "uint256", + }, + ], + name: "VotingDelaySet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingPeriod", + type: "uint256", + }, + ], + name: "VotingPeriodSet", + type: "event", + }, + { + inputs: [], + name: "BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "COUNTING_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "EXTENDED_BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "PERCENT_DIVISOR", + outputs: [{ internalType: "uint16", name: "", type: "uint16" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "PROPOSAL_TYPES_CONFIGURATOR", + outputs: [ + { + internalType: "contract IProposalTypesConfigurator", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "VERSION", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "admin", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "module", type: "address" }], + name: "approvedModules", + outputs: [{ internalType: "bool", name: "approved", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "cancel", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "cancelWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "castVoteWithReasonAndParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteWithReasonAndParamsBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "proposalType", type: "uint8" }, + ], + name: "editProposalType", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "execute", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "executeWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "getProposalType", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "getVotesWithParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasVoted", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "hashProposal", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "module", type: "address" }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "hashProposalWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IVotesUpgradeable", + name: "_votingToken", + type: "address", + }, + { internalType: "address", name: "_admin", type: "address" }, + { internalType: "address", name: "_manager", type: "address" }, + { + internalType: "contract TimelockControllerUpgradeable", + name: "_timelock", + type: "address", + }, + { + internalType: "contract IProposalTypesConfigurator", + name: "_proposalTypesConfigurator", + type: "address", + }, + { + components: [ + { internalType: "uint16", name: "quorum", type: "uint16" }, + { internalType: "uint16", name: "approvalThreshold", type: "uint16" }, + { internalType: "string", name: "name", type: "string" }, + { internalType: "address", name: "module", type: "address" }, + ], + internalType: "struct IProposalTypesConfigurator.ProposalType[]", + name: "_proposalTypes", + type: "tuple[]", + }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "manager", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155BatchReceived", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC721Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalDeadline", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalEta", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalSnapshot", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalVotes", + outputs: [ + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "uint8", name: "proposalType", type: "uint8" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "proposeWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "string", name: "description", type: "string" }, + { internalType: "uint8", name: "proposalType", type: "uint8" }, + ], + name: "proposeWithModule", + outputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "queue", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract VotingModule", + name: "module", + type: "address", + }, + { internalType: "bytes", name: "proposalData", type: "bytes" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "queueWithModule", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "quorum", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "target", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "relay", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "_newAdmin", type: "address" }], + name: "setAdmin", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "_newManager", type: "address" }], + name: "setManager", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "module", type: "address" }, + { internalType: "bool", name: "approved", type: "bool" }, + ], + name: "setModuleApproval", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint64", name: "deadline", type: "uint64" }, + ], + name: "setProposalDeadline", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "setProposalThreshold", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingDelay", type: "uint256" }, + ], + name: "setVotingDelay", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingPeriod", type: "uint256" }, + ], + name: "setVotingPeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "state", + outputs: [ + { + internalType: "enum IGovernorUpgradeable.ProposalState", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelock", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [ + { internalType: "contract IVotesUpgradeable", name: "", type: "address" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract TimelockControllerUpgradeable", + name: "newTimelock", + type: "address", + }, + ], + name: "updateTimelock", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "version", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { stateMutability: "payable", type: "receive" }, +] as const; diff --git a/apps/api/src/clients/scr/abi/index.ts b/apps/api/src/clients/scr/abi/index.ts new file mode 100644 index 000000000..db767f1ac --- /dev/null +++ b/apps/api/src/clients/scr/abi/index.ts @@ -0,0 +1,2 @@ +export { GovernorAbi as SCRGovernorAbi } from "./governor"; +export { TokenAbi as SCRTokenAbi } from "./token"; diff --git a/apps/api/src/clients/scr/abi/token.ts b/apps/api/src/clients/scr/abi/token.ts new file mode 100644 index 000000000..71337f1f9 --- /dev/null +++ b/apps/api/src/clients/scr/abi/token.ts @@ -0,0 +1,720 @@ +export const TokenAbi = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, + { inputs: [], name: "AccessControlBadConfirmation", type: "error" }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "bytes32", name: "neededRole", type: "bytes32" }, + ], + name: "AccessControlUnauthorizedAccount", + type: "error", + }, + { inputs: [], name: "CheckpointUnorderedInsertion", type: "error" }, + { + inputs: [{ internalType: "address", name: "delegatee", type: "address" }], + name: "DuplicateOrUnsortedDelegatees", + type: "error", + }, + { inputs: [], name: "ECDSAInvalidSignature", type: "error" }, + { + inputs: [{ internalType: "uint256", name: "length", type: "uint256" }], + name: "ECDSAInvalidSignatureLength", + type: "error", + }, + { + inputs: [{ internalType: "bytes32", name: "s", type: "bytes32" }], + name: "ECDSAInvalidSignatureS", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "increasedSupply", type: "uint256" }, + { internalType: "uint256", name: "cap", type: "uint256" }, + ], + name: "ERC20ExceededSafeSupply", + type: "error", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "allowance", type: "uint256" }, + { internalType: "uint256", name: "needed", type: "uint256" }, + ], + name: "ERC20InsufficientAllowance", + type: "error", + }, + { + inputs: [ + { internalType: "address", name: "sender", type: "address" }, + { internalType: "uint256", name: "balance", type: "uint256" }, + { internalType: "uint256", name: "needed", type: "uint256" }, + ], + name: "ERC20InsufficientBalance", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "approver", type: "address" }], + name: "ERC20InvalidApprover", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "receiver", type: "address" }], + name: "ERC20InvalidReceiver", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "sender", type: "address" }], + name: "ERC20InvalidSender", + type: "error", + }, + { + inputs: [{ internalType: "address", name: "spender", type: "address" }], + name: "ERC20InvalidSpender", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "deadline", type: "uint256" }], + name: "ERC2612ExpiredSignature", + type: "error", + }, + { + inputs: [ + { internalType: "address", name: "signer", type: "address" }, + { internalType: "address", name: "owner", type: "address" }, + ], + name: "ERC2612InvalidSigner", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "timepoint", type: "uint256" }, + { internalType: "uint48", name: "clock", type: "uint48" }, + ], + name: "ERC5805FutureLookup", + type: "error", + }, + { inputs: [], name: "ERC6372InconsistentClock", type: "error" }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "currentNonce", type: "uint256" }, + ], + name: "InvalidAccountNonce", + type: "error", + }, + { inputs: [], name: "InvalidAddressZero", type: "error" }, + { inputs: [], name: "InvalidInitialization", type: "error" }, + { inputs: [], name: "InvalidNumeratorZero", type: "error" }, + { inputs: [], name: "InvalidSignature", type: "error" }, + { inputs: [], name: "NotInitializing", type: "error" }, + { + inputs: [ + { internalType: "uint256", name: "numerator", type: "uint256" }, + { internalType: "uint96", name: "denominator", type: "uint96" }, + ], + name: "NumeratorSumExceedsDenominator", + type: "error", + }, + { + inputs: [ + { internalType: "uint256", name: "length", type: "uint256" }, + { internalType: "uint256", name: "max", type: "uint256" }, + ], + name: "PartialDelegationLimitExceeded", + type: "error", + }, + { + inputs: [ + { internalType: "uint8", name: "bits", type: "uint8" }, + { internalType: "uint256", name: "value", type: "uint256" }, + ], + name: "SafeCastOverflowedUintDowncast", + type: "error", + }, + { + inputs: [{ internalType: "uint256", name: "expiry", type: "uint256" }], + name: "VotesExpiredSignature", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegator", + type: "address", + }, + { + components: [ + { internalType: "address", name: "_delegatee", type: "address" }, + { internalType: "uint96", name: "_numerator", type: "uint96" }, + ], + indexed: false, + internalType: "struct PartialDelegation[]", + name: "oldDelegatees", + type: "tuple[]", + }, + { + components: [ + { internalType: "address", name: "_delegatee", type: "address" }, + { internalType: "uint96", name: "_numerator", type: "uint96" }, + ], + indexed: false, + internalType: "struct PartialDelegation[]", + name: "newDelegatees", + type: "tuple[]", + }, + ], + name: "DelegateChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegate", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "previousVotes", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotes", + type: "uint256", + }, + ], + name: "DelegateVotesChanged", + type: "event", + }, + { anonymous: false, inputs: [], name: "EIP712DomainChanged", type: "event" }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint64", + name: "version", + type: "uint64", + }, + ], + name: "Initialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "bytes32", + name: "previousAdminRole", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "newAdminRole", + type: "bytes32", + }, + ], + name: "RoleAdminChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleGranted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleRevoked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [], + name: "BURNER_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CLOCK_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEFAULT_ADMIN_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DELEGATION_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DENOMINATOR", + outputs: [{ internalType: "uint96", name: "", type: "uint96" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "MAX_PARTIAL_DELEGATIONS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "MINTER_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "PARTIAL_DELEGATION_ON_BEHALF_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "PARTIAL_DELEGATION_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + ], + name: "approve", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_account", type: "address" }, + { internalType: "uint256", name: "_value", type: "uint256" }, + ], + name: "burn", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint32", name: "pos", type: "uint32" }, + ], + name: "checkpoints", + outputs: [ + { + components: [ + { internalType: "uint48", name: "_key", type: "uint48" }, + { internalType: "uint208", name: "_value", type: "uint208" }, + ], + internalType: "struct Checkpoints.Checkpoint208", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "clock", + outputs: [{ internalType: "uint48", name: "", type: "uint48" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "delegatee", type: "address" }], + name: "delegate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + components: [ + { internalType: "address", name: "_delegatee", type: "address" }, + { internalType: "uint96", name: "_numerator", type: "uint96" }, + ], + internalType: "struct PartialDelegation[]", + name: "_partialDelegations", + type: "tuple[]", + }, + ], + name: "delegate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "delegatee", type: "address" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "delegateBySig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_delegator", type: "address" }, + { + components: [ + { internalType: "address", name: "_delegatee", type: "address" }, + { internalType: "uint96", name: "_numerator", type: "uint96" }, + ], + internalType: "struct PartialDelegation[]", + name: "_partialDelegations", + type: "tuple[]", + }, + { internalType: "uint256", name: "_nonce", type: "uint256" }, + { internalType: "uint256", name: "_expiry", type: "uint256" }, + { internalType: "bytes", name: "_signature", type: "bytes" }, + ], + name: "delegatePartiallyOnBehalf", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "delegates", + outputs: [ + { + components: [ + { internalType: "address", name: "_delegatee", type: "address" }, + { internalType: "uint96", name: "_numerator", type: "uint96" }, + ], + internalType: "struct PartialDelegation[]", + name: "", + type: "tuple[]", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "eip712Domain", + outputs: [ + { internalType: "bytes1", name: "fields", type: "bytes1" }, + { internalType: "string", name: "name", type: "string" }, + { internalType: "string", name: "version", type: "string" }, + { internalType: "uint256", name: "chainId", type: "uint256" }, + { internalType: "address", name: "verifyingContract", type: "address" }, + { internalType: "bytes32", name: "salt", type: "bytes32" }, + { internalType: "uint256[]", name: "extensions", type: "uint256[]" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "timepoint", type: "uint256" }], + name: "getPastTotalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "timepoint", type: "uint256" }, + ], + name: "getPastVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }], + name: "getRoleAdmin", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "grantRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasRole", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_admin", type: "address" }, + { internalType: "string", name: "_name", type: "string" }, + { internalType: "string", name: "_symbol", type: "string" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "invalidateNonce", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_account", type: "address" }, + { internalType: "uint256", name: "_amount", type: "uint256" }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "numCheckpoints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "permit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "callerConfirmation", type: "address" }, + ], + name: "renounceRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "revokeRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + ], + name: "transferFrom", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/apps/indexer/src/indexer/scr/client.ts b/apps/api/src/clients/scr/index.ts similarity index 92% rename from apps/indexer/src/indexer/scr/client.ts rename to apps/api/src/clients/scr/index.ts index aa72d6d5b..41ae0786a 100644 --- a/apps/indexer/src/indexer/scr/client.ts +++ b/apps/api/src/clients/scr/index.ts @@ -10,15 +10,15 @@ import { } from "viem"; import { readContract } from "viem/actions"; -import { DAOClient } from "@/interfaces/client"; +import { DAOClient } from "@/clients"; import { GovernorAbi } from "./abi/governor"; import { GovernorBase } from "../governor.base"; export class SCRClient< - TTransport extends Transport = Transport, - TChain extends Chain = Chain, - TAccount extends Account | undefined = Account | undefined, - > + TTransport extends Transport = Transport, + TChain extends Chain = Chain, + TAccount extends Account | undefined = Account | undefined, +> extends GovernorBase implements DAOClient { diff --git a/apps/api/src/clients/uni/abi/governor.ts b/apps/api/src/clients/uni/abi/governor.ts new file mode 100644 index 000000000..e282b2aa7 --- /dev/null +++ b/apps/api/src/clients/uni/abi/governor.ts @@ -0,0 +1,777 @@ +export const GovernorAbi = [ + ...[ + { + inputs: [ + { internalType: "address", name: "timelock_", type: "address" }, + { internalType: "address", name: "uni_", type: "address" }, + { internalType: "address", name: "admin_", type: "address" }, + { internalType: "address", name: "implementation_", type: "address" }, + { internalType: "uint256", name: "votingPeriod_", type: "uint256" }, + { internalType: "uint256", name: "votingDelay_", type: "uint256" }, + { + internalType: "uint256", + name: "proposalThreshold_", + type: "uint256", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldAdmin", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newAdmin", + type: "address", + }, + ], + name: "NewAdmin", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldImplementation", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newImplementation", + type: "address", + }, + ], + name: "NewImplementation", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldPendingAdmin", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newPendingAdmin", + type: "address", + }, + ], + name: "NewPendingAdmin", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "id", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "startBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "endBlock", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "id", + type: "uint256", + }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "id", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "eta", + type: "uint256", + }, + ], + name: "ProposalQueued", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint8", + name: "support", + type: "uint8", + }, + { + indexed: false, + internalType: "uint256", + name: "votes", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingDelay", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingDelay", + type: "uint256", + }, + ], + name: "VotingDelaySet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingPeriod", + type: "uint256", + }, + ], + name: "VotingPeriodSet", + type: "event", + }, + { payable: true, stateMutability: "payable", type: "fallback" }, + { + constant: false, + inputs: [ + { internalType: "address", name: "implementation_", type: "address" }, + ], + name: "_setImplementation", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "admin", + outputs: [{ internalType: "address", name: "", type: "address" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "implementation", + outputs: [{ internalType: "address", name: "", type: "address" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "pendingAdmin", + outputs: [{ internalType: "address", name: "", type: "address" }], + payable: false, + stateMutability: "view", + type: "function", + }, + ], + ...[ + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldProposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "ProposalThresholdSet", + type: "event", + }, + { + constant: true, + inputs: [], + name: "BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "DOMAIN_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "MAX_PROPOSAL_THRESHOLD", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "MAX_VOTING_DELAY", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "MAX_VOTING_PERIOD", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "MIN_PROPOSAL_THRESHOLD", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "MIN_VOTING_DELAY", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "MIN_VOTING_PERIOD", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [], + name: "_acceptAdmin", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "uint256", name: "proposalCount", type: "uint256" }, + ], + name: "_initiate", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "newPendingAdmin", type: "address" }, + ], + name: "_setPendingAdmin", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "_setProposalThreshold", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "uint256", name: "newVotingDelay", type: "uint256" }, + ], + name: "_setVotingDelay", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "uint256", name: "newVotingPeriod", type: "uint256" }, + ], + name: "_setVotingPeriod", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "admin", + outputs: [{ internalType: "address", name: "", type: "address" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + ], + name: "cancel", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteBySig", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + ], + name: "execute", + outputs: [], + payable: true, + stateMutability: "payable", + type: "function", + }, + { + constant: true, + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + ], + name: "getActions", + outputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "voter", type: "address" }, + ], + name: "getReceipt", + outputs: [ + { + components: [ + { internalType: "bool", name: "hasVoted", type: "bool" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint96", name: "votes", type: "uint96" }, + ], + internalType: "struct GovernorBravoDelegateStorageV1.Receipt", + name: "", + type: "tuple", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "implementation", + outputs: [{ internalType: "address", name: "", type: "address" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "initialProposalId", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "timelock_", type: "address" }, + { internalType: "address", name: "uni_", type: "address" }, + { internalType: "uint256", name: "votingPeriod_", type: "uint256" }, + { internalType: "uint256", name: "votingDelay_", type: "uint256" }, + { + internalType: "uint256", + name: "proposalThreshold_", + type: "uint256", + }, + ], + name: "initialize", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "latestProposalIds", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "pendingAdmin", + outputs: [{ internalType: "address", name: "", type: "address" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "proposalCount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "proposalMaxOperations", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "uint256", name: "", type: "uint256" }], + name: "proposals", + outputs: [ + { internalType: "uint256", name: "id", type: "uint256" }, + { internalType: "address", name: "proposer", type: "address" }, + { internalType: "uint256", name: "eta", type: "uint256" }, + { internalType: "uint256", name: "startBlock", type: "uint256" }, + { internalType: "uint256", name: "endBlock", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + { internalType: "bool", name: "canceled", type: "bool" }, + { internalType: "bool", name: "executed", type: "bool" }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "string[]", name: "signatures", type: "string[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + ], + name: "queue", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "quorumVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + ], + name: "state", + outputs: [ + { + internalType: "enum GovernorBravoDelegateStorageV1.ProposalState", + name: "", + type: "uint8", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "timelock", + outputs: [ + { + internalType: "contract TimelockInterface", + name: "", + type: "address", + }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "uni", + outputs: [ + { internalType: "contract UniInterface", name: "", type: "address" }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + ], +] as const; diff --git a/apps/api/src/clients/uni/abi/index.ts b/apps/api/src/clients/uni/abi/index.ts new file mode 100644 index 000000000..6876ec5bf --- /dev/null +++ b/apps/api/src/clients/uni/abi/index.ts @@ -0,0 +1,2 @@ +export { TokenAbi } from "./token"; +export { GovernorAbi } from "./governor"; diff --git a/apps/api/src/clients/uni/abi/token.ts b/apps/api/src/clients/uni/abi/token.ts new file mode 100644 index 000000000..b334ccb13 --- /dev/null +++ b/apps/api/src/clients/uni/abi/token.ts @@ -0,0 +1,408 @@ +export const TokenAbi = [ + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "address", name: "minter_", type: "address" }, + { + internalType: "uint256", + name: "mintingAllowedAfter_", + type: "uint256", + }, + ], + payable: false, + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "fromDelegate", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "toDelegate", + type: "address", + }, + ], + name: "DelegateChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegate", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "previousBalance", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newBalance", + type: "uint256", + }, + ], + name: "DelegateVotesChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "minter", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newMinter", + type: "address", + }, + ], + name: "MinterChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "amount", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + constant: true, + inputs: [], + name: "DELEGATION_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "DOMAIN_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "PERMIT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "approve", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "uint32", name: "", type: "uint32" }, + ], + name: "checkpoints", + outputs: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { internalType: "uint96", name: "votes", type: "uint96" }, + ], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [{ internalType: "address", name: "delegatee", type: "address" }], + name: "delegate", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "delegatee", type: "address" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "delegateBySig", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "delegates", + outputs: [{ internalType: "address", name: "", type: "address" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getCurrentVotes", + outputs: [{ internalType: "uint96", name: "", type: "uint96" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "blockNumber", type: "uint256" }, + ], + name: "getPriorVotes", + outputs: [{ internalType: "uint96", name: "", type: "uint96" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "minimumTimeBetweenMints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "mint", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "mintCap", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "minter", + outputs: [{ internalType: "address", name: "", type: "address" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "mintingAllowedAfter", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "numCheckpoints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "permit", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [{ internalType: "address", name: "minter_", type: "address" }], + name: "setMinter", + outputs: [], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: true, + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: true, + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + payable: false, + stateMutability: "view", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, + { + constant: false, + inputs: [ + { internalType: "address", name: "src", type: "address" }, + { internalType: "address", name: "dst", type: "address" }, + { internalType: "uint256", name: "rawAmount", type: "uint256" }, + ], + name: "transferFrom", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + payable: false, + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/apps/indexer/src/indexer/uni/client.ts b/apps/api/src/clients/uni/index.ts similarity index 92% rename from apps/indexer/src/indexer/uni/client.ts rename to apps/api/src/clients/uni/index.ts index f406bdc62..5a6e8018f 100644 --- a/apps/indexer/src/indexer/uni/client.ts +++ b/apps/api/src/clients/uni/index.ts @@ -9,15 +9,15 @@ import { } from "viem"; import { readContract } from "viem/actions"; -import { DAOClient } from "@/interfaces/client"; +import { DAOClient } from "@/clients"; import { GovernorAbi } from "./abi"; import { GovernorBase } from "../governor.base"; export class UNIClient< - TTransport extends Transport = Transport, - TChain extends Chain = Chain, - TAccount extends Account | undefined = Account | undefined, - > + TTransport extends Transport = Transport, + TChain extends Chain = Chain, + TAccount extends Account | undefined = Account | undefined, +> extends GovernorBase implements DAOClient { diff --git a/apps/api/src/clients/zk/abi/governor.ts b/apps/api/src/clients/zk/abi/governor.ts new file mode 100644 index 000000000..a430c0148 --- /dev/null +++ b/apps/api/src/clients/zk/abi/governor.ts @@ -0,0 +1,839 @@ +export const GovernorAbi = [ + { + inputs: [ + { + components: [ + { internalType: "string", name: "name", type: "string" }, + { internalType: "contract IVotes", name: "token", type: "address" }, + { + internalType: "contract TimelockController", + name: "timelock", + type: "address", + }, + { + internalType: "uint48", + name: "initialVotingDelay", + type: "uint48", + }, + { + internalType: "uint32", + name: "initialVotingPeriod", + type: "uint32", + }, + { + internalType: "uint256", + name: "initialProposalThreshold", + type: "uint256", + }, + { internalType: "uint224", name: "initialQuorum", type: "uint224" }, + { + internalType: "uint64", + name: "initialVoteExtension", + type: "uint64", + }, + { internalType: "address", name: "vetoGuardian", type: "address" }, + { internalType: "address", name: "proposeGuardian", type: "address" }, + { internalType: "bool", name: "isProposeGuarded", type: "bool" }, + ], + internalType: "struct ZkTokenGovernor.ConstructorParams", + name: "params", + type: "tuple", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { inputs: [], name: "Empty", type: "error" }, + { inputs: [], name: "InvalidShortString", type: "error" }, + { + inputs: [{ internalType: "string", name: "str", type: "string" }], + name: "StringTooLong", + type: "error", + }, + { inputs: [], name: "Unauthorized", type: "error" }, + { inputs: [], name: "UncancelableProposalState", type: "error" }, + { anonymous: false, inputs: [], name: "EIP712DomainChanged", type: "event" }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "bool", name: "oldState", type: "bool" }, + { indexed: false, internalType: "bool", name: "newState", type: "bool" }, + ], + name: "IsProposeGuardedToggled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint64", + name: "oldVoteExtension", + type: "uint64", + }, + { + indexed: false, + internalType: "uint64", + name: "newVoteExtension", + type: "uint64", + }, + ], + name: "LateQuorumVoteExtensionSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalCanceled", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "address", + name: "proposer", + type: "address", + }, + { + indexed: false, + internalType: "address[]", + name: "targets", + type: "address[]", + }, + { + indexed: false, + internalType: "uint256[]", + name: "values", + type: "uint256[]", + }, + { + indexed: false, + internalType: "string[]", + name: "signatures", + type: "string[]", + }, + { + indexed: false, + internalType: "bytes[]", + name: "calldatas", + type: "bytes[]", + }, + { + indexed: false, + internalType: "uint256", + name: "voteStart", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "voteEnd", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "description", + type: "string", + }, + ], + name: "ProposalCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + ], + name: "ProposalExecuted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { + indexed: false, + internalType: "uint64", + name: "extendedDeadline", + type: "uint64", + }, + ], + name: "ProposalExtended", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint256", name: "eta", type: "uint256" }, + ], + name: "ProposalQueued", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldProposalThreshold", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "ProposalThresholdSet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldQuorum", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newQuorum", + type: "uint256", + }, + ], + name: "QuorumUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "oldTimelock", + type: "address", + }, + { + indexed: false, + internalType: "address", + name: "newTimelock", + type: "address", + }, + ], + name: "TimelockChange", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + ], + name: "VoteCast", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "voter", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "proposalId", + type: "uint256", + }, + { indexed: false, internalType: "uint8", name: "support", type: "uint8" }, + { + indexed: false, + internalType: "uint256", + name: "weight", + type: "uint256", + }, + { + indexed: false, + internalType: "string", + name: "reason", + type: "string", + }, + { indexed: false, internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "VoteCastWithParams", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingDelay", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingDelay", + type: "uint256", + }, + ], + name: "VotingDelaySet", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "uint256", + name: "oldVotingPeriod", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newVotingPeriod", + type: "uint256", + }, + ], + name: "VotingPeriodSet", + type: "event", + }, + { + inputs: [], + name: "BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CLOCK_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "COUNTING_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "EXTENDED_BALLOT_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "PROPOSE_GUARDIAN", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "VETO_GUARDIAN", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "_targets", type: "address[]" }, + { internalType: "uint256[]", name: "_values", type: "uint256[]" }, + { internalType: "bytes[]", name: "_calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "_descriptionHash", type: "bytes32" }, + ], + name: "cancel", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + ], + name: "castVote", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "castVoteBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + ], + name: "castVoteWithReason", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "uint8", name: "support", type: "uint8" }, + { internalType: "string", name: "reason", type: "string" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "castVoteWithReasonAndParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "_proposalId", type: "uint256" }, + { internalType: "uint8", name: "_support", type: "uint8" }, + { internalType: "string", name: "_reason", type: "string" }, + { internalType: "bytes", name: "_params", type: "bytes" }, + { internalType: "uint8", name: "_v", type: "uint8" }, + { internalType: "bytes32", name: "_r", type: "bytes32" }, + { internalType: "bytes32", name: "_s", type: "bytes32" }, + ], + name: "castVoteWithReasonAndParamsBySig", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "clock", + outputs: [{ internalType: "uint48", name: "", type: "uint48" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "eip712Domain", + outputs: [ + { internalType: "bytes1", name: "fields", type: "bytes1" }, + { internalType: "string", name: "name", type: "string" }, + { internalType: "string", name: "version", type: "string" }, + { internalType: "uint256", name: "chainId", type: "uint256" }, + { internalType: "address", name: "verifyingContract", type: "address" }, + { internalType: "bytes32", name: "salt", type: "bytes32" }, + { internalType: "uint256[]", name: "extensions", type: "uint256[]" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "execute", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "", type: "address" }], + name: "fractionalVoteNonce", + outputs: [{ internalType: "uint128", name: "", type: "uint128" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "timepoint", type: "uint256" }, + ], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "timepoint", type: "uint256" }, + { internalType: "bytes", name: "params", type: "bytes" }, + ], + name: "getVotesWithParams", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasVoted", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "hashProposal", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "pure", + type: "function", + }, + { + inputs: [], + name: "isProposeGuarded", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "lateQuorumVoteExtension", + outputs: [{ internalType: "uint64", name: "", type: "uint64" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "uint256[]", name: "", type: "uint256[]" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155BatchReceived", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC1155Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + { internalType: "address", name: "", type: "address" }, + { internalType: "uint256", name: "", type: "uint256" }, + { internalType: "bytes", name: "", type: "bytes" }, + ], + name: "onERC721Received", + outputs: [{ internalType: "bytes4", name: "", type: "bytes4" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_proposalId", type: "uint256" }], + name: "proposalDeadline", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalEta", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalProposer", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalSnapshot", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "proposalThreshold", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "proposalId", type: "uint256" }], + name: "proposalVotes", + outputs: [ + { internalType: "uint256", name: "againstVotes", type: "uint256" }, + { internalType: "uint256", name: "forVotes", type: "uint256" }, + { internalType: "uint256", name: "abstainVotes", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "string", name: "description", type: "string" }, + ], + name: "propose", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address[]", name: "targets", type: "address[]" }, + { internalType: "uint256[]", name: "values", type: "uint256[]" }, + { internalType: "bytes[]", name: "calldatas", type: "bytes[]" }, + { internalType: "bytes32", name: "descriptionHash", type: "bytes32" }, + ], + name: "queue", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_voteStart", type: "uint256" }], + name: "quorum", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "target", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "bytes", name: "data", type: "bytes" }, + ], + name: "relay", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [{ internalType: "bool", name: "_isProposeGuarded", type: "bool" }], + name: "setIsProposeGuarded", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint64", name: "newVoteExtension", type: "uint64" }, + ], + name: "setLateQuorumVoteExtension", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "uint256", + name: "newProposalThreshold", + type: "uint256", + }, + ], + name: "setProposalThreshold", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint224", name: "_amount", type: "uint224" }], + name: "setQuorum", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingDelay", type: "uint256" }, + ], + name: "setVotingDelay", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "newVotingPeriod", type: "uint256" }, + ], + name: "setVotingPeriod", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "_proposalId", type: "uint256" }], + name: "state", + outputs: [ + { internalType: "enum IGovernor.ProposalState", name: "", type: "uint8" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "_interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "timelock", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [{ internalType: "contract IERC5805", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract TimelockController", + name: "newTimelock", + type: "address", + }, + ], + name: "updateTimelock", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "version", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "proposalId", type: "uint256" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "voteWeightCast", + outputs: [{ internalType: "uint128", name: "", type: "uint128" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingDelay", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "votingPeriod", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { stateMutability: "payable", type: "receive" }, +] as const; diff --git a/apps/api/src/clients/zk/abi/index.ts b/apps/api/src/clients/zk/abi/index.ts new file mode 100644 index 000000000..42f08dce0 --- /dev/null +++ b/apps/api/src/clients/zk/abi/index.ts @@ -0,0 +1,2 @@ +export * from "./token"; +export * from "./governor"; diff --git a/apps/api/src/clients/zk/abi/token.ts b/apps/api/src/clients/zk/abi/token.ts new file mode 100644 index 000000000..ae8b5ea9c --- /dev/null +++ b/apps/api/src/clients/zk/abi/token.ts @@ -0,0 +1,547 @@ +export const TokenAbi = [ + { + inputs: [{ internalType: "uint256", name: "expiry", type: "uint256" }], + name: "DelegateSignatureExpired", + type: "error", + }, + { inputs: [], name: "DelegateSignatureIsInvalid", type: "error" }, + { inputs: [], name: "ERC6372InconsistentClock", type: "error" }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "owner", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "spender", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Approval", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegator", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "fromDelegate", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "toDelegate", + type: "address", + }, + ], + name: "DelegateChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "delegate", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "previousBalance", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "newBalance", + type: "uint256", + }, + ], + name: "DelegateVotesChanged", + type: "event", + }, + { anonymous: false, inputs: [], name: "EIP712DomainChanged", type: "event" }, + { + anonymous: false, + inputs: [ + { indexed: false, internalType: "uint8", name: "version", type: "uint8" }, + ], + name: "Initialized", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "bytes32", + name: "previousAdminRole", + type: "bytes32", + }, + { + indexed: true, + internalType: "bytes32", + name: "newAdminRole", + type: "bytes32", + }, + ], + name: "RoleAdminChanged", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleGranted", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "bytes32", name: "role", type: "bytes32" }, + { + indexed: true, + internalType: "address", + name: "account", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "sender", + type: "address", + }, + ], + name: "RoleRevoked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "from", type: "address" }, + { indexed: true, internalType: "address", name: "to", type: "address" }, + { + indexed: false, + internalType: "uint256", + name: "value", + type: "uint256", + }, + ], + name: "Transfer", + type: "event", + }, + { + inputs: [], + name: "BURNER_ADMIN_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "BURNER_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "CLOCK_MODE", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DEFAULT_ADMIN_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DELEGATION_TYPEHASH", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "DOMAIN_SEPARATOR", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "MINTER_ADMIN_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "MINTER_ROLE", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + ], + name: "allowance", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "approve", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_from", type: "address" }, + { internalType: "uint256", name: "_amount", type: "uint256" }, + ], + name: "burn", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint32", name: "pos", type: "uint32" }, + ], + name: "checkpoints", + outputs: [ + { + components: [ + { internalType: "uint32", name: "fromBlock", type: "uint32" }, + { internalType: "uint224", name: "votes", type: "uint224" }, + ], + internalType: "struct ERC20VotesUpgradeable.Checkpoint", + name: "", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "clock", + outputs: [{ internalType: "uint48", name: "", type: "uint48" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "decimals", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "subtractedValue", type: "uint256" }, + ], + name: "decreaseAllowance", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "delegatee", type: "address" }], + name: "delegate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "delegatee", type: "address" }, + { internalType: "uint256", name: "nonce", type: "uint256" }, + { internalType: "uint256", name: "expiry", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "delegateBySig", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_signer", type: "address" }, + { internalType: "address", name: "_delegatee", type: "address" }, + { internalType: "uint256", name: "_expiry", type: "uint256" }, + { internalType: "bytes", name: "_signature", type: "bytes" }, + ], + name: "delegateOnBehalf", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "delegates", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "eip712Domain", + outputs: [ + { internalType: "bytes1", name: "fields", type: "bytes1" }, + { internalType: "string", name: "name", type: "string" }, + { internalType: "string", name: "version", type: "string" }, + { internalType: "uint256", name: "chainId", type: "uint256" }, + { internalType: "address", name: "verifyingContract", type: "address" }, + { internalType: "bytes32", name: "salt", type: "bytes32" }, + { internalType: "uint256[]", name: "extensions", type: "uint256[]" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "uint256", name: "timepoint", type: "uint256" }], + name: "getPastTotalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + { internalType: "uint256", name: "timepoint", type: "uint256" }, + ], + name: "getPastVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "bytes32", name: "role", type: "bytes32" }], + name: "getRoleAdmin", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "getVotes", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "grantRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "hasRole", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "addedValue", type: "uint256" }, + ], + name: "increaseAllowance", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_admin", type: "address" }, + { internalType: "address", name: "_mintReceiver", type: "address" }, + { internalType: "uint256", name: "_mintAmount", type: "uint256" }, + ], + name: "initialize", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "initializeV2", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_to", type: "address" }, + { internalType: "uint256", name: "_amount", type: "uint256" }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "name", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "owner", type: "address" }], + name: "nonces", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [{ internalType: "address", name: "account", type: "address" }], + name: "numCheckpoints", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "address", name: "spender", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + ], + name: "permit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "renounceRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "bytes32", name: "role", type: "bytes32" }, + { internalType: "address", name: "account", type: "address" }, + ], + name: "revokeRole", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [{ internalType: "bytes4", name: "interfaceId", type: "bytes4" }], + name: "supportsInterface", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "symbol", + outputs: [{ internalType: "string", name: "", type: "string" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "totalSupply", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transferFrom", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, +] as const; diff --git a/apps/indexer/src/indexer/zk/client.ts b/apps/api/src/clients/zk/index.ts similarity index 92% rename from apps/indexer/src/indexer/zk/client.ts rename to apps/api/src/clients/zk/index.ts index e836f0664..c0e155700 100644 --- a/apps/indexer/src/indexer/zk/client.ts +++ b/apps/api/src/clients/zk/index.ts @@ -8,16 +8,16 @@ import { Transport, } from "viem"; -import { DAOClient } from "@/interfaces/client"; +import { DAOClient } from "@/clients"; import { GovernorBase } from "../governor.base"; import { GovernorAbi } from "./abi"; import { readContract } from "viem/actions"; export class ZKClient< - TTransport extends Transport = Transport, - TChain extends Chain = Chain, - TAccount extends Account | undefined = Account | undefined, - > + TTransport extends Transport = Transport, + TChain extends Chain = Chain, + TAccount extends Account | undefined = Account | undefined, +> extends GovernorBase implements DAOClient { diff --git a/apps/indexer/src/api/controllers/account-balance/historical.ts b/apps/api/src/controllers/account-balance/historical.ts similarity index 94% rename from apps/indexer/src/api/controllers/account-balance/historical.ts rename to apps/api/src/controllers/account-balance/historical.ts index be5ffd09a..f7594221e 100644 --- a/apps/indexer/src/api/controllers/account-balance/historical.ts +++ b/apps/api/src/controllers/account-balance/historical.ts @@ -1,12 +1,12 @@ import { OpenAPIHono as Hono, createRoute } from "@hono/zod-openapi"; -import { HistoricalBalancesService } from "@/api/services"; +import { HistoricalBalancesService } from "@/services"; import { HistoricalBalancesResponseMapper, HistoricalBalanceRequestParamsSchema, HistoricalBalanceRequestQuerySchema, HistoricalBalancesResponseSchema, -} from "@/api/mappers"; +} from "@/mappers"; export function historicalBalances( app: Hono, diff --git a/apps/indexer/src/api/controllers/account-balance/index.ts b/apps/api/src/controllers/account-balance/index.ts similarity index 100% rename from apps/indexer/src/api/controllers/account-balance/index.ts rename to apps/api/src/controllers/account-balance/index.ts diff --git a/apps/indexer/src/api/controllers/account-balance/interactions.ts b/apps/api/src/controllers/account-balance/interactions.ts similarity index 100% rename from apps/indexer/src/api/controllers/account-balance/interactions.ts rename to apps/api/src/controllers/account-balance/interactions.ts diff --git a/apps/indexer/src/api/controllers/account-balance/listing.ts b/apps/api/src/controllers/account-balance/listing.ts similarity index 96% rename from apps/indexer/src/api/controllers/account-balance/listing.ts rename to apps/api/src/controllers/account-balance/listing.ts index 868893f24..18f363adb 100644 --- a/apps/indexer/src/api/controllers/account-balance/listing.ts +++ b/apps/api/src/controllers/account-balance/listing.ts @@ -1,14 +1,14 @@ import { createRoute, OpenAPIHono as Hono, z } from "@hono/zod-openapi"; -import { AccountBalanceService } from "@/api/services"; +import { AccountBalanceService } from "@/services"; import { AccountBalancesRequestSchema, AccountBalancesResponseMapper, AccountBalancesResponseSchema, -} from "@/api/mappers"; +} from "@/mappers"; import { AccountBalanceResponseMapper, AccountBalanceResponseSchema, -} from "@/api/mappers"; +} from "@/mappers"; import { getAddress, isAddress } from "viem"; import { DaoIdEnum } from "@/lib/enums"; diff --git a/apps/indexer/src/api/controllers/account-balance/variations.ts b/apps/api/src/controllers/account-balance/variations.ts similarity index 97% rename from apps/indexer/src/api/controllers/account-balance/variations.ts rename to apps/api/src/controllers/account-balance/variations.ts index 8307bbae8..b64e13f91 100644 --- a/apps/indexer/src/api/controllers/account-balance/variations.ts +++ b/apps/api/src/controllers/account-balance/variations.ts @@ -7,8 +7,8 @@ import { AccountBalanceVariationsResponseSchema, AccountBalanceVariationsByAccountIdResponseMapper, AccountBalanceVariationsByAccountIdResponseSchema, -} from "@/api/mappers"; -import { BalanceVariationsService } from "@/api/services"; +} from "@/mappers"; +import { BalanceVariationsService } from "@/services"; export function accountBalanceVariations( app: Hono, diff --git a/apps/indexer/src/api/controllers/dao/index.ts b/apps/api/src/controllers/dao/index.ts similarity index 88% rename from apps/indexer/src/api/controllers/dao/index.ts rename to apps/api/src/controllers/dao/index.ts index e636b40e5..e71f864bf 100644 --- a/apps/indexer/src/api/controllers/dao/index.ts +++ b/apps/api/src/controllers/dao/index.ts @@ -1,6 +1,6 @@ import { OpenAPIHono as Hono, createRoute } from "@hono/zod-openapi"; -import { DaoService } from "@/api/services"; -import { DaoResponseSchema } from "@/api/mappers"; +import { DaoService } from "@/services"; +import { DaoResponseSchema } from "@/mappers"; export function dao(app: Hono, service: DaoService) { app.openapi( diff --git a/apps/indexer/src/api/controllers/delegation-percentage/index.ts b/apps/api/src/controllers/delegation-percentage/index.ts similarity index 92% rename from apps/indexer/src/api/controllers/delegation-percentage/index.ts rename to apps/api/src/controllers/delegation-percentage/index.ts index d2bd0d5e2..0a6af7d80 100644 --- a/apps/indexer/src/api/controllers/delegation-percentage/index.ts +++ b/apps/api/src/controllers/delegation-percentage/index.ts @@ -1,10 +1,10 @@ import { OpenAPIHono as Hono, createRoute } from "@hono/zod-openapi"; -import { DelegationPercentageService } from "@/api/services"; +import { DelegationPercentageService } from "@/services"; import { DelegationPercentageRequestSchema, DelegationPercentageResponseSchema, toApi, -} from "@/api/mappers/"; +} from "@/mappers/"; export function delegationPercentage( app: Hono, diff --git a/apps/indexer/src/api/controllers/delegations/delegations.ts b/apps/api/src/controllers/delegations/delegations.ts similarity index 90% rename from apps/indexer/src/api/controllers/delegations/delegations.ts rename to apps/api/src/controllers/delegations/delegations.ts index cb9d640ff..fa8512a77 100644 --- a/apps/indexer/src/api/controllers/delegations/delegations.ts +++ b/apps/api/src/controllers/delegations/delegations.ts @@ -4,8 +4,8 @@ import { DelegationsResponseSchema, delegationMapper, DelegationsRequestParamsSchema, -} from "@/api/mappers/delegations"; -import { DelegationsService } from "@/api/services/delegations/current"; +} from "@/mappers/delegations"; +import { DelegationsService } from "@/services/delegations/current"; export function delegations(app: Hono, service: DelegationsService) { app.openapi( diff --git a/apps/indexer/src/api/controllers/delegations/historical.ts b/apps/api/src/controllers/delegations/historical.ts similarity index 93% rename from apps/indexer/src/api/controllers/delegations/historical.ts rename to apps/api/src/controllers/delegations/historical.ts index 1c286d76d..d1c8b2109 100644 --- a/apps/indexer/src/api/controllers/delegations/historical.ts +++ b/apps/api/src/controllers/delegations/historical.ts @@ -5,8 +5,8 @@ import { HistoricalDelegationsRequestParamsSchema, HistoricalDelegationsRequestQuerySchema, DelegationsResponseSchema, -} from "@/api/mappers/delegations"; -import { HistoricalDelegationsService } from "@/api/services/delegations"; +} from "@/mappers/delegations"; +import { HistoricalDelegationsService } from "@/services/delegations"; export function historicalDelegations( app: Hono, diff --git a/apps/indexer/src/api/controllers/delegations/index.ts b/apps/api/src/controllers/delegations/index.ts similarity index 100% rename from apps/indexer/src/api/controllers/delegations/index.ts rename to apps/api/src/controllers/delegations/index.ts diff --git a/apps/indexer/src/api/controllers/governance-activity/controller.ts b/apps/api/src/controllers/governance-activity/controller.ts similarity index 100% rename from apps/indexer/src/api/controllers/governance-activity/controller.ts rename to apps/api/src/controllers/governance-activity/controller.ts diff --git a/apps/indexer/src/api/controllers/governance-activity/index.ts b/apps/api/src/controllers/governance-activity/index.ts similarity index 100% rename from apps/indexer/src/api/controllers/governance-activity/index.ts rename to apps/api/src/controllers/governance-activity/index.ts diff --git a/apps/indexer/src/api/controllers/governance-activity/types.ts b/apps/api/src/controllers/governance-activity/types.ts similarity index 100% rename from apps/indexer/src/api/controllers/governance-activity/types.ts rename to apps/api/src/controllers/governance-activity/types.ts diff --git a/apps/indexer/src/api/controllers/index.ts b/apps/api/src/controllers/index.ts similarity index 94% rename from apps/indexer/src/api/controllers/index.ts rename to apps/api/src/controllers/index.ts index bc0699329..5152abc5e 100644 --- a/apps/indexer/src/api/controllers/index.ts +++ b/apps/api/src/controllers/index.ts @@ -11,3 +11,4 @@ export * from "./dao"; export * from "./treasury"; export * from "./transfers"; export * from "./delegations"; +export * from "./votes"; diff --git a/apps/indexer/src/api/controllers/last-update/index.ts b/apps/api/src/controllers/last-update/index.ts similarity index 74% rename from apps/indexer/src/api/controllers/last-update/index.ts rename to apps/api/src/controllers/last-update/index.ts index 283657f2b..203b02054 100644 --- a/apps/indexer/src/api/controllers/last-update/index.ts +++ b/apps/api/src/controllers/last-update/index.ts @@ -1,10 +1,11 @@ import { OpenAPIHono as Hono, createRoute, z } from "@hono/zod-openapi"; -import { ChartType } from "@/api/mappers/"; -import { LastUpdateService } from "@/api/services"; -import { LastUpdateRepositoryImpl } from "@/api/repositories"; +import { ChartType } from "@/mappers/"; +import { LastUpdateService } from "@/services"; +import { LastUpdateRepositoryImpl } from "@/repositories"; +import { Drizzle } from "@/database"; -export function lastUpdate(app: Hono) { - const repository = new LastUpdateRepositoryImpl(); +export function lastUpdate(app: Hono, db: Drizzle) { + const repository = new LastUpdateRepositoryImpl(db); const service = new LastUpdateService(repository); app.openapi( createRoute({ diff --git a/apps/indexer/src/api/controllers/proposals/index.ts b/apps/api/src/controllers/proposals/index.ts similarity index 100% rename from apps/indexer/src/api/controllers/proposals/index.ts rename to apps/api/src/controllers/proposals/index.ts diff --git a/apps/indexer/src/api/controllers/proposals/proposals-activity.ts b/apps/api/src/controllers/proposals/proposals-activity.ts similarity index 90% rename from apps/indexer/src/api/controllers/proposals/proposals-activity.ts rename to apps/api/src/controllers/proposals/proposals-activity.ts index 2c8dd5474..a5bb6f3ed 100644 --- a/apps/indexer/src/api/controllers/proposals/proposals-activity.ts +++ b/apps/api/src/controllers/proposals/proposals-activity.ts @@ -2,15 +2,15 @@ import { OpenAPIHono as Hono, createRoute, z } from "@hono/zod-openapi"; import { getAddress, isAddress } from "viem"; import { DaoIdEnum } from "@/lib/enums"; -import { ProposalsActivityService } from "@/api/services"; -import { ProposalsActivityRepository, VoteFilter } from "@/api/repositories/"; +import { ProposalsActivityService } from "@/services"; +import { DrizzleProposalsActivityRepository, VoteFilter } from "@/repositories/"; import { CONTRACT_ADDRESSES } from "@/lib/constants"; -import { DAOClient } from "@/interfaces/client"; -import { ProposalActivityResponseSchema } from "@/api/mappers"; +import { DAOClient } from "@/clients"; +import { ProposalActivityResponseSchema } from "@/mappers"; export function proposalsActivity( app: Hono, - repository: ProposalsActivityRepository, + repository: DrizzleProposalsActivityRepository, daoId: DaoIdEnum, daoClient: DAOClient, ) { diff --git a/apps/indexer/src/api/controllers/proposals/proposals.ts b/apps/api/src/controllers/proposals/proposals.ts similarity index 53% rename from apps/indexer/src/api/controllers/proposals/proposals.ts rename to apps/api/src/controllers/proposals/proposals.ts index db54730a0..4cd4e5bb8 100644 --- a/apps/indexer/src/api/controllers/proposals/proposals.ts +++ b/apps/api/src/controllers/proposals/proposals.ts @@ -1,18 +1,14 @@ import { OpenAPIHono as Hono, createRoute, z } from "@hono/zod-openapi"; -import { ProposalsService } from "@/api/services"; +import { ProposalsService } from "@/services"; import { ProposalsResponseSchema, ProposalsRequestSchema, ProposalRequestSchema, ProposalResponseSchema, ProposalMapper, - VotersRequestSchema, - VotersResponseSchema, - VotesRequestSchema, - VotesResponseSchema, -} from "@/api/mappers"; -import { DAOClient } from "@/interfaces"; +} from "@/mappers"; +import { DAOClient } from "@/clients"; export function proposals( app: Hono, @@ -122,91 +118,4 @@ export function proposals( ); }, ); - - app.openapi( - createRoute({ - method: "get", - operationId: "proposalNonVoters", - path: "/proposals/{id}/non-voters", - summary: "Get a proposal non-voters", - description: - "Returns the active delegates that did not vote on a given proposal", - tags: ["proposals"], - request: { - params: z.object({ - id: z.string(), - }), - query: VotersRequestSchema, - }, - responses: { - 200: { - description: "Successfully retrieved proposal", - content: { - "application/json": { - schema: VotersResponseSchema, - }, - }, - }, - }, - }), - async (context) => { - const { id } = context.req.valid("param"); - const { skip, limit, orderDirection, addresses } = - context.req.valid("query"); - - const { totalCount, items } = await service.getProposalNonVoters( - id, - skip, - limit, - orderDirection, - addresses, - ); - return context.json({ totalCount, items }); - }, - ); - - app.openapi( - createRoute({ - method: "get", - operationId: "votes", - path: "/proposals/{id}/votes", - summary: "List of votes for a given proposal", - description: - "Returns a paginated list of votes cast on a specific proposal", - tags: ["proposals"], - request: { - params: z.object({ - id: z.string(), - }), - query: VotesRequestSchema, - }, - responses: { - 200: { - description: "Successfully retrieved votes", - content: { - "application/json": { - schema: VotesResponseSchema, - }, - }, - }, - }, - }), - async (context) => { - const { id } = context.req.valid("param"); - const { skip, limit, voterAddressIn, orderBy, orderDirection, support } = - context.req.valid("query"); - - const { totalCount, items } = await service.getVotes( - id, - skip, - limit, - orderBy, - orderDirection, - voterAddressIn, - support, - ); - - return context.json({ totalCount, items }); - }, - ); } diff --git a/apps/indexer/src/api/controllers/token-metrics/index.ts b/apps/api/src/controllers/token-metrics/index.ts similarity index 81% rename from apps/indexer/src/api/controllers/token-metrics/index.ts rename to apps/api/src/controllers/token-metrics/index.ts index 3c550d60a..ad7b3e305 100644 --- a/apps/indexer/src/api/controllers/token-metrics/index.ts +++ b/apps/api/src/controllers/token-metrics/index.ts @@ -1,11 +1,10 @@ import { OpenAPIHono as Hono, createRoute } from "@hono/zod-openapi"; -import { TokenMetricsService } from "@/api/services/token-metrics"; +import { TokenMetricsService } from "@/services/token-metrics"; import { TokenMetricsRequestSchema, TokenMetricsResponseSchema, toTokenMetricsApi, -} from "@/api/mappers/token-metrics"; -import { metricTypeArray } from "@/lib/constants"; +} from "@/mappers/token-metrics"; export function tokenMetrics(app: Hono, service: TokenMetricsService) { app.openapi( @@ -14,8 +13,7 @@ export function tokenMetrics(app: Hono, service: TokenMetricsService) { operationId: "tokenMetrics", path: "/token-metrics", summary: "Get token related metrics", - description: `Returns token related metrics for a single metric type. - Available types: ${metricTypeArray.join(", ")}`, + description: `Returns token related metrics for a single metric type.`, tags: ["metrics"], request: { query: TokenMetricsRequestSchema, diff --git a/apps/indexer/src/api/controllers/token/index.ts b/apps/api/src/controllers/token/index.ts similarity index 100% rename from apps/indexer/src/api/controllers/token/index.ts rename to apps/api/src/controllers/token/index.ts diff --git a/apps/indexer/src/api/controllers/token/token-distribution.ts b/apps/api/src/controllers/token/token-distribution.ts similarity index 99% rename from apps/indexer/src/api/controllers/token/token-distribution.ts rename to apps/api/src/controllers/token/token-distribution.ts index 1b76beb5b..5d09725dd 100644 --- a/apps/indexer/src/api/controllers/token/token-distribution.ts +++ b/apps/api/src/controllers/token/token-distribution.ts @@ -135,7 +135,7 @@ export function tokenDistribution( const changeRate = parseInt(oldValue) && (BigInt(currentValue) * parseEther("1")) / BigInt(oldValue) - - parseEther("1"); + parseEther("1"); /* eslint-enable */ return ctx.json( diff --git a/apps/indexer/src/api/controllers/token/token-historical-data.ts b/apps/api/src/controllers/token/token-historical-data.ts similarity index 98% rename from apps/indexer/src/api/controllers/token/token-historical-data.ts rename to apps/api/src/controllers/token/token-historical-data.ts index 844010d9f..cfa274ca3 100644 --- a/apps/indexer/src/api/controllers/token/token-historical-data.ts +++ b/apps/api/src/controllers/token/token-historical-data.ts @@ -3,7 +3,7 @@ import { OpenAPIHono as Hono, createRoute } from "@hono/zod-openapi"; import { TokenHistoricalPriceRequest, TokenHistoricalPriceResponse, -} from "@/api/mappers"; +} from "@/mappers"; export interface TokenHistoricalDataClient { getHistoricalTokenData( diff --git a/apps/indexer/src/api/controllers/token/token-properties.ts b/apps/api/src/controllers/token/token-properties.ts similarity index 93% rename from apps/indexer/src/api/controllers/token/token-properties.ts rename to apps/api/src/controllers/token/token-properties.ts index cfa61405a..88db476f0 100644 --- a/apps/indexer/src/api/controllers/token/token-properties.ts +++ b/apps/api/src/controllers/token/token-properties.ts @@ -1,8 +1,8 @@ import { OpenAPIHono as Hono, createRoute, z } from "@hono/zod-openapi"; import { DaoIdEnum } from "@/lib/enums"; -import { TokenService } from "@/api/services"; -import { TokenPropertiesResponseSchema, TokenMapper } from "@/api/mappers"; +import { TokenService } from "@/services"; +import { TokenPropertiesResponseSchema, TokenMapper } from "@/mappers"; import { CONTRACT_ADDRESSES } from "@/lib/constants"; interface TokenPriceClient { diff --git a/apps/indexer/src/api/controllers/transactions/index.ts b/apps/api/src/controllers/transactions/index.ts similarity index 95% rename from apps/indexer/src/api/controllers/transactions/index.ts rename to apps/api/src/controllers/transactions/index.ts index ce474f52b..3f1ffef47 100644 --- a/apps/indexer/src/api/controllers/transactions/index.ts +++ b/apps/api/src/controllers/transactions/index.ts @@ -1,10 +1,10 @@ import { OpenAPIHono as Hono, createRoute } from "@hono/zod-openapi"; -import { TransactionsService } from "@/api/services"; +import { TransactionsService } from "@/services"; import { TransactionsRequestSchema, TransactionsResponseSchema, -} from "@/api/mappers/"; +} from "@/mappers/"; export function transactions(app: Hono, service: TransactionsService) { app.openapi( diff --git a/apps/indexer/src/api/controllers/transfers/index.ts b/apps/api/src/controllers/transfers/index.ts similarity index 95% rename from apps/indexer/src/api/controllers/transfers/index.ts rename to apps/api/src/controllers/transfers/index.ts index 5993134d6..98053b89a 100644 --- a/apps/indexer/src/api/controllers/transfers/index.ts +++ b/apps/api/src/controllers/transfers/index.ts @@ -1,11 +1,11 @@ import { OpenAPIHono as Hono, createRoute } from "@hono/zod-openapi"; -import { TransfersService } from "@/api/services"; +import { TransfersService } from "@/services"; import { TransfersRequestRouteSchema, TransfersRequestQuerySchema, TransfersResponseSchema, -} from "@/api/mappers/"; +} from "@/mappers/"; export function transfers(app: Hono, service: TransfersService) { app.openapi( diff --git a/apps/indexer/src/api/controllers/treasury/index.ts b/apps/api/src/controllers/treasury/index.ts similarity index 97% rename from apps/indexer/src/api/controllers/treasury/index.ts rename to apps/api/src/controllers/treasury/index.ts index 607ee79d8..04715d772 100644 --- a/apps/indexer/src/api/controllers/treasury/index.ts +++ b/apps/api/src/controllers/treasury/index.ts @@ -1,10 +1,10 @@ import { OpenAPIHono as Hono, createRoute } from "@hono/zod-openapi"; -import { TreasuryService } from "@/api/services/treasury"; +import { TreasuryService } from "@/services/treasury"; import { TreasuryResponseSchema, TreasuryQuerySchema, -} from "@/api/mappers/treasury"; +} from "@/mappers/treasury"; export function treasury( app: Hono, diff --git a/apps/api/src/controllers/votes/index.ts b/apps/api/src/controllers/votes/index.ts new file mode 100644 index 000000000..54a3a71ed --- /dev/null +++ b/apps/api/src/controllers/votes/index.ts @@ -0,0 +1,147 @@ +import { OpenAPIHono as Hono, createRoute, z } from "@hono/zod-openapi"; + +import { VotesService } from "@/services"; +import { + VotersRequestSchema, + VotersResponseSchema, + VotesRequestSchema, + VotesResponseSchema, +} from "@/mappers"; + +export function votes(app: Hono, service: VotesService) { + app.openapi( + createRoute({ + method: "get", + operationId: "votesByProposalId", + path: "/proposals/{id}/votes", + summary: "List of votes for a given proposal", + description: + "Returns a paginated list of votes cast on a specific proposal", + tags: ["proposals"], + request: { + params: z.object({ + id: z.string(), + }), + query: VotesRequestSchema, + }, + responses: { + 200: { + description: "Successfully retrieved votes", + content: { + "application/json": { + schema: VotesResponseSchema, + }, + }, + }, + }, + }), + async (context) => { + const { id } = context.req.valid("param"); + const { + skip, + limit, + voterAddressIn, + orderBy, + orderDirection, + support, + fromDate, + toDate, + } = context.req.valid("query"); + + const { totalCount, items } = await service.getVotesByProposal( + id, + skip, + limit, + orderBy, + orderDirection, + voterAddressIn, + support, + fromDate, + toDate, + ); + + return context.json({ totalCount, items }); + }, + ); + + app.openapi( + createRoute({ + method: "get", + operationId: "votes", + path: "/votes", + summary: "Get all votes", + description: "Get all votes ordered by timestamp or voting power", + tags: ["votes"], + request: { + query: VotesRequestSchema, + }, + responses: { + 200: { + description: "Returns votes", + content: { + "application/json": { + schema: VotesResponseSchema, + }, + }, + }, + }, + }), + async (context) => { + const { limit, skip, orderBy, orderDirection, fromDate, toDate } = + context.req.valid("query"); + + const result = await service.getVotes({ + limit, + skip, + orderBy, + orderDirection, + fromDate, + toDate, + }); + + return context.json(VotesResponseSchema.parse(result)); + }, + ); + + app.openapi( + createRoute({ + method: "get", + operationId: "proposalNonVoters", + path: "/proposals/{id}/non-voters", + summary: "Get a proposal non-voters", + description: + "Returns the active delegates that did not vote on a given proposal", + tags: ["proposals"], + request: { + params: z.object({ + id: z.string(), + }), + query: VotersRequestSchema, + }, + responses: { + 200: { + description: "Successfully retrieved proposal", + content: { + "application/json": { + schema: VotersResponseSchema, + }, + }, + }, + }, + }), + async (context) => { + const { id } = context.req.valid("param"); + const { skip, limit, orderDirection, addresses } = + context.req.valid("query"); + + const { totalCount, items } = await service.getProposalNonVoters( + id, + skip, + limit, + orderDirection, + addresses, + ); + return context.json({ totalCount, items }); + }, + ); +} diff --git a/apps/indexer/src/api/controllers/voting-power/historical.ts b/apps/api/src/controllers/voting-power/historical.ts similarity index 97% rename from apps/indexer/src/api/controllers/voting-power/historical.ts rename to apps/api/src/controllers/voting-power/historical.ts index 25ac5987b..d551933c7 100644 --- a/apps/indexer/src/api/controllers/voting-power/historical.ts +++ b/apps/api/src/controllers/voting-power/historical.ts @@ -1,13 +1,13 @@ import { OpenAPIHono as Hono, createRoute } from "@hono/zod-openapi"; -import { VotingPowerService } from "@/api/services"; +import { VotingPowerService } from "@/services"; import { HistoricalVotingPowersResponseSchema, HistoricalVotingPowerRequestQuerySchema, HistoricalVotingPowersResponseMapper, HistoricalVotingPowerRequestParamsSchema, HistoricalVotingPowerGlobalQuerySchema, -} from "@/api/mappers"; +} from "@/mappers"; export function historicalVotingPower(app: Hono, service: VotingPowerService) { app.openapi( diff --git a/apps/indexer/src/api/controllers/voting-power/index.ts b/apps/api/src/controllers/voting-power/index.ts similarity index 100% rename from apps/indexer/src/api/controllers/voting-power/index.ts rename to apps/api/src/controllers/voting-power/index.ts diff --git a/apps/indexer/src/api/controllers/voting-power/listing.ts b/apps/api/src/controllers/voting-power/listing.ts similarity index 94% rename from apps/indexer/src/api/controllers/voting-power/listing.ts rename to apps/api/src/controllers/voting-power/listing.ts index 5f572d8d3..e67fb54fb 100644 --- a/apps/indexer/src/api/controllers/voting-power/listing.ts +++ b/apps/api/src/controllers/voting-power/listing.ts @@ -1,13 +1,13 @@ import { OpenAPIHono as Hono, createRoute, z } from "@hono/zod-openapi"; -import { VotingPowerService } from "@/api/services"; +import { VotingPowerService } from "@/services"; import { VotingPowersRequestSchema, VotingPowersResponseSchema, VotingPowersMapper, VotingPowerResponseSchema, -} from "@/api/mappers/"; +} from "@/mappers/"; import { getAddress, isAddress } from "viem"; -import { VotingPowerMapper } from "@/api/mappers/voting-power/variations"; +import { VotingPowerMapper } from "@/mappers/voting-power/variations"; export function votingPowers(app: Hono, service: VotingPowerService) { app.openapi( diff --git a/apps/indexer/src/api/controllers/voting-power/variations.ts b/apps/api/src/controllers/voting-power/variations.ts similarity index 97% rename from apps/indexer/src/api/controllers/voting-power/variations.ts rename to apps/api/src/controllers/voting-power/variations.ts index 791ec172d..2727b6c2f 100644 --- a/apps/indexer/src/api/controllers/voting-power/variations.ts +++ b/apps/api/src/controllers/voting-power/variations.ts @@ -1,6 +1,6 @@ import { OpenAPIHono as Hono, createRoute } from "@hono/zod-openapi"; -import { VotingPowerService } from "@/api/services"; +import { VotingPowerService } from "@/services"; import { VotingPowerVariationsByAccountIdRequestQuerySchema, VotingPowerVariationsByAccountIdResponseSchema, @@ -9,7 +9,7 @@ import { VotingPowerVariationsResponseMapper, VotingPowerVariationsRequestQuerySchema, VotingPowerVariationsByAccountIdRequestParamsSchema, -} from "@/api/mappers/"; +} from "@/mappers/"; export function votingPowerVariations(app: Hono, service: VotingPowerService) { app.openapi( diff --git a/apps/api/src/database/index.ts b/apps/api/src/database/index.ts new file mode 100644 index 000000000..faff6e375 --- /dev/null +++ b/apps/api/src/database/index.ts @@ -0,0 +1,32 @@ +import type * as schema from "./schema"; + +import type { NodePgDatabase } from "drizzle-orm/node-postgres"; +import type { PgliteDatabase } from "drizzle-orm/pglite"; + +/** + * Full Drizzle database type with write capabilities + * This follows Ponder's Drizzle type definition pattern from: + * node_modules/ponder/src/types/db.ts + * + * Supports: + * - NodePgDatabase: PostgreSQL via node-postgres driver + * - PgliteDatabase: PGlite embedded PostgreSQL + */ +export type Drizzle = + | NodePgDatabase + | PgliteDatabase; +/** + * Read-only Drizzle database type (used in Ponder API context) + * Omits write operations: insert, update, delete, transaction + */ +export type ReadonlyDrizzle = Omit< + Drizzle, + | "insert" + | "update" + | "delete" + | "transaction" + | "refreshMaterializedView" + | "_" +>; + +export * from "./schema"; diff --git a/apps/api/src/database/schema.ts b/apps/api/src/database/schema.ts new file mode 100644 index 000000000..309de651c --- /dev/null +++ b/apps/api/src/database/schema.ts @@ -0,0 +1,266 @@ +import { + pgTable, + index, + bigint, + pgEnum, + primaryKey, +} from "drizzle-orm/pg-core"; +import { relations } from "drizzle-orm"; +import { Address, zeroAddress } from "viem"; + +import { MetricTypesArray } from "@/lib/constants"; + +export const token = pgTable("token", (drizzle) => ({ + id: drizzle.text().primaryKey(), + name: drizzle.text(), + decimals: drizzle.integer().notNull(), + totalSupply: bigint({ mode: "bigint" }).notNull().default(0n), + delegatedSupply: bigint({ mode: "bigint" }).notNull().default(0n), + cexSupply: bigint({ mode: "bigint" }).notNull().default(0n), + dexSupply: bigint({ mode: "bigint" }).notNull().default(0n), + lendingSupply: bigint({ mode: "bigint" }).notNull().default(0n), + circulatingSupply: bigint({ mode: "bigint" }).notNull().default(0n), + treasury: bigint({ mode: "bigint" }).notNull().default(0n), +})); + +export const account = pgTable("account", (drizzle) => ({ + id: drizzle.text().primaryKey(), +})); + +export const accountBalance = pgTable( + "account_balance", + (drizzle) => ({ + accountId: drizzle.text("account_id").$type
().notNull(), + tokenId: drizzle.text("token_id").notNull(), + balance: bigint({ mode: "bigint" }).notNull(), + // This field represents for who the account is delegating their voting power to + delegate: drizzle.text().default(zeroAddress).notNull(), + }), + (table) => [ + primaryKey({ + columns: [table.accountId, table.tokenId], + }), + index().on(table.delegate), + ], +); + +export const accountPower = pgTable( + "account_power", + (drizzle) => ({ + accountId: drizzle.text("account_id").$type
().notNull(), + daoId: drizzle.text("dao_id").notNull(), + votingPower: bigint({ mode: "bigint" }).default(BigInt(0)).notNull(), + votesCount: drizzle.integer("votes_count").default(0).notNull(), + proposalsCount: drizzle.integer("proposals_count").default(0).notNull(), + delegationsCount: drizzle.integer("delegations_count").default(0).notNull(), + lastVoteTimestamp: drizzle + .bigint({ mode: "bigint" }) + .default(BigInt(0)) + .notNull(), + }), + (table) => [ + primaryKey({ + columns: [table.accountId], + }), + index().on(table.lastVoteTimestamp), + ], +); + +export const votingPowerHistory = pgTable( + "voting_power_history", + (drizzle) => ({ + transactionHash: drizzle.text("transaction_hash").notNull(), + daoId: drizzle.text("dao_id").notNull(), + accountId: drizzle.text("account_id").$type
().notNull(), + votingPower: bigint({ mode: "bigint" }).notNull(), + delta: bigint({ mode: "bigint" }).notNull(), + deltaMod: bigint({ mode: "bigint" }).notNull(), + timestamp: bigint({ mode: "bigint" }).notNull(), + logIndex: drizzle.integer("log_index").notNull(), + }), + (table) => [ + primaryKey({ + columns: [table.transactionHash, table.accountId, table.logIndex], + }), + ], +); + +export const balanceHistory = pgTable( + "balance_history", + (drizzle) => ({ + transactionHash: drizzle.text("transaction_hash").notNull(), + daoId: drizzle.text("dao_id").notNull(), + accountId: drizzle.text("account_id").$type
().notNull(), + balance: bigint({ mode: "bigint" }).notNull(), + delta: bigint({ mode: "bigint" }).notNull(), + deltaMod: bigint({ mode: "bigint" }).notNull(), + timestamp: bigint({ mode: "bigint" }).notNull(), + logIndex: drizzle.integer("log_index").notNull(), + }), + (table) => [ + primaryKey({ + columns: [table.transactionHash, table.accountId, table.logIndex], + }), + ], +); + +export const delegation = pgTable( + "delegations", + (drizzle) => ({ + transactionHash: drizzle.text("transaction_hash").notNull(), + daoId: drizzle.text("dao_id").notNull(), + delegateAccountId: drizzle + .text("delegate_account_id") + .$type
() + .notNull(), + delegatorAccountId: drizzle + .text("delegator_account_id") + .$type
() + .notNull(), + delegatedValue: bigint({ mode: "bigint" }).notNull().default(0n), + previousDelegate: drizzle.text("previous_delegate"), + timestamp: bigint({ mode: "bigint" }).notNull(), + logIndex: drizzle.integer("log_index").notNull(), + isCex: drizzle.boolean().notNull().default(false), + isDex: drizzle.boolean().notNull().default(false), + isLending: drizzle.boolean().notNull().default(false), + isTotal: drizzle.boolean().notNull().default(false), + }), + (table) => [ + primaryKey({ + columns: [ + table.transactionHash, + table.delegatorAccountId, + table.delegateAccountId, + ], + }), + index().on(table.transactionHash), + index().on(table.timestamp), + index().on(table.delegatorAccountId), + index().on(table.delegateAccountId), + index().on(table.delegatedValue), + ], +); + +export const transfer = pgTable( + "transfers", + (drizzle) => ({ + transactionHash: drizzle.text("transaction_hash").notNull(), + daoId: drizzle.text("dao_id").notNull(), + tokenId: drizzle.text("token_id").notNull(), + amount: bigint({ mode: "bigint" }).notNull(), + fromAccountId: drizzle.text("from_account_id").$type
().notNull(), + toAccountId: drizzle.text("to_account_id").$type
().notNull(), + timestamp: bigint({ mode: "bigint" }).notNull(), + logIndex: drizzle.integer("log_index").notNull(), + isCex: drizzle.boolean().notNull().default(false), + isDex: drizzle.boolean().notNull().default(false), + isLending: drizzle.boolean().notNull().default(false), + isTotal: drizzle.boolean().notNull().default(false), + }), + (table) => [ + primaryKey({ + columns: [table.transactionHash, table.fromAccountId, table.toAccountId], + }), + index().on(table.transactionHash), + index().on(table.timestamp), + index().on(table.fromAccountId), + index().on(table.toAccountId), + index().on(table.amount), + ], +); + +export const votesOnchain = pgTable( + "votes_onchain", + (drizzle) => ({ + txHash: drizzle.text("tx_hash").notNull(), + daoId: drizzle.text("dao_id").notNull(), + voterAccountId: drizzle.text("voter_account_id").$type
().notNull(), + proposalId: drizzle.text("proposal_id").notNull(), + support: drizzle.text().notNull(), + votingPower: bigint({ mode: "bigint" }).notNull(), + reason: drizzle.text(), + timestamp: bigint({ mode: "bigint" }).notNull(), + }), + (table) => [ + primaryKey({ + columns: [table.voterAccountId, table.proposalId], + }), + ], +); + +export const proposalsOnchain = pgTable( + "proposals_onchain", + (drizzle) => ({ + id: drizzle.text().primaryKey(), + txHash: drizzle.text("tx_hash").notNull(), + daoId: drizzle.text("dao_id").notNull(), + proposerAccountId: drizzle + .text("proposer_account_id") + .$type
() + .notNull(), + targets: drizzle.json().$type().notNull(), + values: drizzle.json().$type().notNull(), + signatures: drizzle.json().$type().notNull(), + calldatas: drizzle.json().$type().notNull(), + startBlock: drizzle.integer("start_block").notNull(), + endBlock: drizzle.integer("end_block").notNull(), + description: drizzle.text().notNull(), + timestamp: bigint({ mode: "bigint" }).notNull(), + endTimestamp: bigint({ mode: "bigint" }).notNull(), + status: drizzle.text().notNull(), + forVotes: bigint({ mode: "bigint" }).default(0n).notNull(), + againstVotes: bigint({ mode: "bigint" }).default(0n).notNull(), + abstainVotes: bigint({ mode: "bigint" }).default(0n).notNull(), + proposalType: drizzle.integer("proposal_type"), + }), + (table) => [index().on(table.proposerAccountId)], +); + +export const votesOnchainRelations = relations(votesOnchain, ({ one }) => ({ + proposal: one(proposalsOnchain, { + fields: [votesOnchain.proposalId], + references: [proposalsOnchain.id], + }), +})); + +export const metricType = pgEnum("metricType", MetricTypesArray); + +export const daoMetricsDayBucket = pgTable( + "dao_metrics_day_buckets", + (drizzle) => ({ + date: bigint({ mode: "bigint" }).notNull(), + daoId: drizzle.text("dao_id").notNull(), + tokenId: drizzle.text("token_id").notNull(), + metricType: metricType("metricType").notNull(), + open: bigint({ mode: "bigint" }).notNull(), + close: bigint({ mode: "bigint" }).notNull(), + low: bigint({ mode: "bigint" }).notNull(), + high: bigint({ mode: "bigint" }).notNull(), + average: bigint({ mode: "bigint" }).notNull(), + volume: bigint({ mode: "bigint" }).notNull(), + count: drizzle.integer().notNull(), + lastUpdate: bigint({ mode: "bigint" }).notNull(), + }), + (table) => [ + primaryKey({ + columns: [table.date, table.tokenId, table.metricType], + }), + ], +); + +export const transaction = pgTable("transaction", (drizzle) => ({ + transactionHash: drizzle.text("transaction_hash").primaryKey(), + fromAddress: drizzle.text("from_address"), + toAddress: drizzle.text("to_address"), + isCex: drizzle.boolean().notNull().default(false), + isDex: drizzle.boolean().notNull().default(false), + isLending: drizzle.boolean().notNull().default(false), + isTotal: drizzle.boolean().notNull().default(false), + timestamp: bigint({ mode: "bigint" }).notNull(), +})); + +export const tokenPrice = pgTable("token_price", (drizzle) => ({ + price: bigint({ mode: "bigint" }).notNull(), // price in ETH + timestamp: bigint({ mode: "bigint" }).primaryKey(), +})); diff --git a/apps/indexer/src/api/docs.ts b/apps/api/src/docs.ts similarity index 100% rename from apps/indexer/src/api/docs.ts rename to apps/api/src/docs.ts diff --git a/apps/api/src/env.ts b/apps/api/src/env.ts new file mode 100644 index 000000000..393683766 --- /dev/null +++ b/apps/api/src/env.ts @@ -0,0 +1,36 @@ +import { z } from "zod"; +import dotenv from "dotenv"; + +import { DaoIdEnum } from "@/lib/enums"; + +dotenv.config(); + +const envSchema = z.object({ + RPC_URL: z.string(), + DATABASE_URL: z + .string() + .transform((val) => `${val}?options=-c%20search_path%3Danticapture`), + DAO_ID: z.nativeEnum(DaoIdEnum), + CHAIN_ID: z.coerce.number(), + + // Treasury provider configuration + TREASURY_DATA_PROVIDER_ID: z + .enum(["DUNE", "DEFILLAMA", "COMPOUND"]) + .optional(), + TREASURY_DATA_PROVIDER_API_URL: z.string().optional(), + TREASURY_DATA_PROVIDER_API_KEY: z.string().optional(), + + COINGECKO_API_URL: z.string(), + COINGECKO_API_KEY: z.string(), + REDIS_URL: z.string().optional(), + PORT: z.coerce.number().default(42069), +}); + +const _env = envSchema.safeParse(process.env); + +if (_env.success === false) { + console.error("Invalid environment variables", _env.error.format()); + throw new Error("Invalid environment variables"); +} + +export const env = _env.data; diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts new file mode 100644 index 000000000..31ec1c905 --- /dev/null +++ b/apps/api/src/index.ts @@ -0,0 +1,232 @@ +import { OpenAPIHono as Hono } from "@hono/zod-openapi"; +import { drizzle } from "drizzle-orm/node-postgres"; +import { serve } from "@hono/node-server"; + +import { logger } from "hono/logger"; +import * as schema from "@/database/schema"; +import { fromZodError } from "zod-validation-error"; +import { createPublicClient, http } from "viem"; + +import { + accountBalanceVariations, + accountBalances, + accountInteractions, + dao, + delegationPercentage, + governanceActivity, + historicalBalances, + historicalVotingPower, + lastUpdate, + proposals, + proposalsActivity, + token, + tokenDistribution, + tokenHistoricalData, + transactions, + transfers, + tokenMetrics, + treasury, + votingPowerVariations, + votingPowers, + delegations, + historicalDelegations, + votes, +} from "@/controllers"; +import { docs } from "@/docs"; +import { env } from "@/env"; +import { DaoCache } from "@/cache/dao-cache"; +import { + AccountBalanceRepository, + AccountInteractionsRepository, + BalanceVariationsRepository, + DaoMetricsDayBucketRepository, + DrizzleProposalsActivityRepository, + DrizzleRepository, + HistoricalBalanceRepository, + NFTPriceRepository, + NounsVotingPowerRepository, + TokenRepository, + TransactionsRepository, + TransfersRepository, + TreasuryRepository, + VotingPowerRepository, + DelegationsRepository, + HistoricalDelegationsRepository, + VotesRepository, +} from "@/repositories"; +import { errorHandler } from "@/middlewares"; +import { getClient } from "@/lib/client"; +import { getChain } from "@/lib/utils"; +import { + AccountBalanceService, + BalanceVariationsService, + CoingeckoService, + DaoService, + DelegationPercentageService, + HistoricalBalancesService, + NFTPriceService, + ProposalsService, + TokenService, + TransactionsService, + TransfersService, + TokenMetricsService, + VotingPowerService, + createTreasuryService, + parseTreasuryProviderConfig, + HistoricalDelegationsService, + DelegationsService, + VotesService, +} from "@/services"; +import { CONTRACT_ADDRESSES } from "@/lib/constants"; +import { DaoIdEnum } from "@/lib/enums"; + +const app = new Hono({ + defaultHook: (result, c) => { + if (!result.success) { + const validationError = fromZodError(result.error); + return c.json( + { + error: "Validation Error", + message: validationError.message, + details: validationError.details, + }, + 400, + ); + } + }, +}); + +app.use(logger()); +app.onError(errorHandler); + +const chain = getChain(env.CHAIN_ID); +if (!chain) { + throw new Error(`Chain not found for chainId ${env.CHAIN_ID}`); +} +console.log("Connected to chain", chain.name); + +const client = createPublicClient({ + chain, + transport: http(env.RPC_URL), +}); + +const daoClient = getClient(env.DAO_ID, client); + +if (!daoClient) { + throw new Error(`Client not found for DAO ${env.DAO_ID}`); +} + +const pgClient = drizzle(env.DATABASE_URL, { schema, casing: "snake_case" }); + +const daoConfig = CONTRACT_ADDRESSES[env.DAO_ID]; +const { blockTime, tokenType } = daoConfig; +const optimisticProposalType = + "optimisticProposalType" in daoConfig + ? daoConfig.optimisticProposalType + : undefined; + +const repo = new DrizzleRepository(pgClient); +const votingPowerRepo = new VotingPowerRepository(pgClient); +const proposalsRepo = new DrizzleProposalsActivityRepository(pgClient); +const transactionsRepo = new TransactionsRepository(pgClient); +const daoMetricsDayBucketRepo = new DaoMetricsDayBucketRepository(pgClient); +const delegationPercentageService = new DelegationPercentageService( + daoMetricsDayBucketRepo, +); +const tokenMetricsService = new TokenMetricsService(daoMetricsDayBucketRepo); +const balanceVariationsRepo = new BalanceVariationsRepository(pgClient); +const historicalBalancesRepo = new HistoricalBalanceRepository(pgClient); +const accountBalanceRepo = new AccountBalanceRepository(pgClient); +const accountInteractionRepo = new AccountInteractionsRepository(pgClient); +const transactionsService = new TransactionsService(transactionsRepo); +const votingPowerService = new VotingPowerService( + env.DAO_ID === DaoIdEnum.NOUNS + ? new NounsVotingPowerRepository(pgClient) + : votingPowerRepo, + votingPowerRepo, +); +const daoCache = new DaoCache(); +const daoService = new DaoService(daoClient, daoCache, env.CHAIN_ID); +const balanceVariationsService = new BalanceVariationsService( + balanceVariationsRepo, + accountInteractionRepo, +); +const accountBalanceService = new AccountBalanceService(accountBalanceRepo); + +const tokenPriceClient = + env.DAO_ID === DaoIdEnum.NOUNS + ? new NFTPriceService( + new NFTPriceRepository(pgClient), + env.COINGECKO_API_URL, + env.COINGECKO_API_KEY, + ) + : new CoingeckoService( + env.COINGECKO_API_URL, + env.COINGECKO_API_KEY, + env.DAO_ID, + ); + +historicalDelegations( + app, + new HistoricalDelegationsService( + new HistoricalDelegationsRepository(pgClient), + ), +); + +// TODO: add support to partial delegations at some point +delegations(app, new DelegationsService(new DelegationsRepository(pgClient))); + +const treasuryService = createTreasuryService( + new TreasuryRepository(pgClient), + tokenPriceClient, + parseTreasuryProviderConfig( + env.TREASURY_DATA_PROVIDER_ID, + env.TREASURY_DATA_PROVIDER_API_URL, + env.TREASURY_DATA_PROVIDER_API_KEY, + ), +); +const decimals = CONTRACT_ADDRESSES[env.DAO_ID].token.decimals; + +treasury(app, treasuryService, decimals); +tokenHistoricalData(app, tokenPriceClient); +token( + app, + tokenPriceClient, + new TokenService(new TokenRepository(pgClient)), + env.DAO_ID, +); + +tokenDistribution(app, repo); +governanceActivity(app, repo, tokenType); +proposalsActivity(app, proposalsRepo, env.DAO_ID, daoClient); +proposals( + app, + new ProposalsService(repo, daoClient, optimisticProposalType), + daoClient, + blockTime, +); +historicalBalances(app, new HistoricalBalancesService(historicalBalancesRepo)); +transactions(app, transactionsService); +lastUpdate(app, pgClient); +delegationPercentage(app, delegationPercentageService); +historicalVotingPower(app, votingPowerService); +votingPowerVariations(app, votingPowerService); +votingPowers(app, votingPowerService); +accountBalanceVariations(app, balanceVariationsService); +accountBalances(app, env.DAO_ID, accountBalanceService); +accountInteractions(app, balanceVariationsService); +transfers(app, new TransfersService(new TransfersRepository(pgClient))); +votes(app, new VotesService(new VotesRepository(pgClient))); +dao(app, daoService); +docs(app); +tokenMetrics(app, tokenMetricsService); + +serve( + { + fetch: app.fetch, + port: env.PORT, + }, + (info) => { + console.log(`Server running at http://localhost:${info.port}`); + }, +); diff --git a/apps/api/src/lib/blockTime.ts b/apps/api/src/lib/blockTime.ts new file mode 100644 index 000000000..e765535e8 --- /dev/null +++ b/apps/api/src/lib/blockTime.ts @@ -0,0 +1,15 @@ +import { DaysEnum } from "./enums"; + +export function calculateHistoricalBlockNumber( + days: DaysEnum, + currentBlockNumber: number, + blockTime: number, +): number { + const blocksToGoBack = Math.floor(days / blockTime); + const historicalBlockNumber = Math.max( + 0, + currentBlockNumber - blocksToGoBack, + ); + + return historicalBlockNumber; +} diff --git a/apps/indexer/src/lib/client.ts b/apps/api/src/lib/client.ts similarity index 79% rename from apps/indexer/src/lib/client.ts rename to apps/api/src/lib/client.ts index a2070d4bf..5bc7beaa7 100644 --- a/apps/indexer/src/lib/client.ts +++ b/apps/api/src/lib/client.ts @@ -2,16 +2,18 @@ import { Chain, Account, Transport, Client } from "viem"; import { DaoIdEnum } from "./enums"; import { CONTRACT_ADDRESSES } from "./constants"; -import { UNIClient } from "@/indexer/uni/client"; -import { ENSClient } from "@/indexer/ens/client"; -import { OPClient } from "@/indexer/op"; -import { DAOClient } from "@/interfaces/client"; -import { GTCClient } from "@/indexer/gtc/client"; -import { Client as NounsClient } from "@/indexer/nouns/client"; -import { SCRClient } from "@/indexer/scr"; -import { COMPClient } from "@/indexer/comp"; -import { ObolClient } from "@/indexer/obol/client"; -import { ZKClient } from "@/indexer/zk"; +import { + UNIClient, + SCRClient, + COMPClient, + ObolClient, + ZKClient, + ENSClient, + OPClient, + GTCClient, + Client as NounsClient, + DAOClient, +} from "@/clients"; export function getClient< TTransport extends Transport = Transport, diff --git a/apps/api/src/lib/constants.ts b/apps/api/src/lib/constants.ts new file mode 100644 index 000000000..a10c402fc --- /dev/null +++ b/apps/api/src/lib/constants.ts @@ -0,0 +1,347 @@ +import { Address } from "viem"; + +import { DaoIdEnum } from "./enums"; + +export const CONTRACT_ADDRESSES = { + [DaoIdEnum.UNI]: { + blockTime: 12, + tokenType: "ERC20", + // https://etherscan.io/address/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 + token: { + address: "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", + decimals: 18, + startBlock: 10861674, + }, + // https://etherscan.io/address/0x408ED6354d4973f66138C91495F2f2FCbd8724C3 + governor: { + address: "0x408ED6354d4973f66138C91495F2f2FCbd8724C3", + startBlock: 13059157, + }, + }, + [DaoIdEnum.ENS]: { + blockTime: 12, + tokenType: "ERC20", + // https://etherscan.io/address/0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72 + token: { + address: "0xC18360217D8F7Ab5e7c516566761Ea12Ce7F9D72", + decimals: 18, + startBlock: 9380410, + }, + // https://etherscan.io/address/0x323a76393544d5ecca80cd6ef2a560c6a395b7e3 + governor: { + address: "0x323a76393544d5ecca80cd6ef2a560c6a395b7e3", + startBlock: 13533772, + }, + }, + [DaoIdEnum.ARB]: { + blockTime: 0.25, + // https://arbiscan.io/address/0x912CE59144191C1204E64559FE8253a0e49E6548 + tokenType: "ERC20", + token: { + address: "0x912CE59144191C1204E64559FE8253a0e49E6548", + decimals: 18, + startBlock: 70398200, + }, + }, + [DaoIdEnum.OP]: { + blockTime: 2, + tokenType: "ERC20", + optimisticProposalType: 2, + // https://optimistic.etherscan.io/token/0x4200000000000000000000000000000000000042 + token: { + address: "0x4200000000000000000000000000000000000042", + decimals: 18, + startBlock: 6490467, + }, + // https://optimistic.etherscan.io/address/0xcDF27F107725988f2261Ce2256bDfCdE8B382B10 + governor: { + address: "0xcDF27F107725988f2261Ce2256bDfCdE8B382B10", + startBlock: 71801427, + }, + }, + [DaoIdEnum.TEST]: { + blockTime: 12, + tokenType: "ERC20", + token: { + address: "0x244dE6b06E7087110b94Cde88A42d9aBA17efa52", + decimals: 18, + startBlock: 22635098, + }, + governor: { + address: "0x7c28FC9709650D49c8d0aED2f6ece6b191F192a9", + startBlock: 22635098, + }, + }, + [DaoIdEnum.GTC]: { + blockTime: 12, + // https://etherscan.io/address/0xDe30da39c46104798bB5aA3fe8B9e0e1F348163F + tokenType: "ERC20", + token: { + address: "0xDe30da39c46104798bB5aA3fe8B9e0e1F348163F", + decimals: 18, + startBlock: 12422079, + }, + // https://etherscan.io/address/0x9D4C63565D5618310271bF3F3c01b2954C1D1639 + governor: { + address: "0x9D4C63565D5618310271bF3F3c01b2954C1D1639", + startBlock: 17813942, + }, + // https://etherscan.io/address/0xDbD27635A534A3d3169Ef0498beB56Fb9c937489 + governorAlpha: { + address: "0xDbD27635A534A3d3169Ef0498beB56Fb9c937489", + startBlock: 12497481, + }, + }, + [DaoIdEnum.NOUNS]: { + blockTime: 12, + tokenType: "ERC721", + token: { + // https://etherscan.io/token/0x9C8fF314C9Bc7F6e59A9d9225Fb22946427eDC03 + address: "0x9C8fF314C9Bc7F6e59A9d9225Fb22946427eDC03", + decimals: 0, + startBlock: 12985438, + }, + governor: { + // https://etherscan.io/address/0x6f3e6272a167e8accb32072d08e0957f9c79223d + address: "0x6f3e6272a167e8accb32072d08e0957f9c79223d", + startBlock: 12985453, + }, + auction: { + // https://etherscan.io/address/0x830BD73E4184ceF73443C15111a1DF14e495C706 + address: "0x830BD73E4184ceF73443C15111a1DF14e495C706", + startBlock: 12985451, + }, + }, + [DaoIdEnum.SCR]: { + blockTime: 1.5, + // https://scrollscan.com/address/0xd29687c813D741E2F938F4aC377128810E217b1b + tokenType: "ERC20", + token: { + address: "0xd29687c813D741E2F938F4aC377128810E217b1b", + decimals: 18, + startBlock: 8949006, + }, + // https://scrollscan.com/address/0x2f3f2054776bd3c2fc30d750734a8f539bb214f0 + governor: { + address: "0x2f3f2054776bd3c2fc30d750734a8f539bb214f0", + startBlock: 8963441, + }, + }, + [DaoIdEnum.COMP]: { + blockTime: 12, + // https://etherscan.io/address/0xc00e94Cb662C3520282E6f5717214004A7f26888 + tokenType: "ERC20", + token: { + address: "0xc00e94Cb662C3520282E6f5717214004A7f26888", + decimals: 18, + startBlock: 9601359, + }, + // https://etherscan.io/address/0x309a862bbC1A00e45506cB8A802D1ff10004c8C0 + governor: { + address: "0x309a862bbC1A00e45506cB8A802D1ff10004c8C0", + startBlock: 21688680, + }, + }, + [DaoIdEnum.OBOL]: { + blockTime: 12, + tokenType: "ERC20", + // https://etherscan.io/address/0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7 + // Token created: Sep-19-2022 11:12:47 PM UTC + token: { + address: "0x0B010000b7624eb9B3DfBC279673C76E9D29D5F7", + decimals: 18, + startBlock: 15570746, + }, + // https://etherscan.io/address/0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c + // Governor created: Feb-19-2025 10:34:47 PM UTC + governor: { + address: "0xcB1622185A0c62A80494bEde05Ba95ef29Fbf85c", + startBlock: 21883431, + }, + }, + [DaoIdEnum.ZK]: { + blockTime: 1, + tokenType: "ERC20", + // https://explorer.zksync.io/address/0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E + token: { + address: "0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E", + decimals: 18, + startBlock: 34572100, + }, + // https://explorer.zksync.io/address/0xb83FF6501214ddF40C91C9565d095400f3F45746 + governor: { + address: "0xb83FF6501214ddF40C91C9565d095400f3F45746", + startBlock: 55519658, + }, + }, +} as const; + +export const TreasuryAddresses: Record> = { + [DaoIdEnum.UNI]: { + timelock: "0x1a9C8182C09F50C8318d769245beA52c32BE35BC", + treasuryVester1: "0x4750c43867EF5F89869132ecCF19B9b6C4286E1a", + treasuryVester2: "0xe3953D9d317B834592aB58AB2c7A6aD22b54075D", + treasuryVester3: "0x4b4e140D1f131fdaD6fb59C13AF796fD194e4135", + treasuryVester4: "0x3D30B1aB88D487B0F3061F40De76845Bec3F1e94", + }, + [DaoIdEnum.ENS]: { + timelock: "0xFe89cc7aBB2C4183683ab71653C4cdc9B02D44b7", + endaoment: "0x4F2083f5fBede34C2714aFfb3105539775f7FE64", + oldEthRegistrarController: "0x283Af0B28c62C092C9727F1Ee09c02CA627EB7F5", + ethRegistrarController: "0x253553366Da8546fC250F225fe3d25d0C782303b", + }, + [DaoIdEnum.ARB]: {}, + [DaoIdEnum.OP]: {}, + [DaoIdEnum.NOUNS]: { + timelock: "0xb1a32fc9f9d8b2cf86c068cae13108809547ef71", + auction: "0x830BD73E4184ceF73443C15111a1DF14e495C706", + }, + [DaoIdEnum.TEST]: {}, + [DaoIdEnum.GTC]: { + "Gitcoin Timelock": "0x57a8865cfB1eCEf7253c27da6B4BC3dAEE5Be518", + "Gitcoin CSDO": "0x931896A8A9313F622a2AFCA76d1471B97955e551", + "Gitcoin Fraud Detection & Defense": + "0xD4567069C5a1c1fc8261d8Ff5C0B1d98f069Cf47", + "Gitcoin Grants Matching Pool": + "0xde21F729137C5Af1b01d73aF1dC21eFfa2B8a0d6", + "Gitcoin Merch, Memes and Marketing": + "0xC23DA3Ca9300571B9CF43298228353cbb3E1b4c0", + "Gitcoin Timelock Transfer 1": "0x6EEdE31a2A15340342B4BCb3039447d457aC7C4b", + "Gitcoin Timelock Transfer 2": "0xeD95D629c4Db80060C59432e81254D256AEc97E2", + "Vesting Address GTC 1": "0x2AA5d15Eb36E5960d056e8FeA6E7BB3e2a06A351", + "Staking contract GTC": "0x0E3efD5BE54CC0f4C64e0D186b0af4b7F2A0e95F", + "OKX Ventures": "0xe527BbDE3654E9ba824f9B72DFF495eEe60fD366", + "Protocol Labs 1": "0x154855f5522f6B04ce654175368F428852DCd55D", + "Matt Solomon": "0x7aD3d9819B06E800F8A65f3440D599A23D6A0BDf", + "Arbitrum Bridge": "0xa3A7B6F88361F48403514059F1F16C8E78d60EeC", + "Optimism Bridge": "0x99C9fc46f92E8a1c0deC1b1747d010903E884bE1", + "Radicle Timelock": "0x8dA8f82d2BbDd896822de723F55D6EdF416130ba", + "Vesting Address GTC 3": "0x2CDE9919e81b20B4B33DD562a48a84b54C48F00C", + "deltajuliet.eth 1": "0x5b1ddBEC956Ed39e1aC92AE3c3D99295ddD59865", + "deltajuliet.eth 2": "0x407466C56B8488c4d99558633Ff1AC5D84400B46", + "deltajuliet.eth 3": "0x14b9F70C3d4B367D496F3771EdA7EFA65282e55D", + "deltajuliet.eth 4": "0x0dcFc9323539A6eC47f9BC0A96882070540bf950", + "deltajuliet.eth 5": "0x08f3FB287AEc4E06EFF8de37410eaF52B05c7f56", + "Gitcoin Timelock Transfer 5": "0x9E75c3BFb82cf701AC0A74d6C1607461Ec65EfF9", + "Old Address, Large GTC Transfers 1": + "0xF5A7bA226CB94D87C29aDD2b59aC960904a163F3", + "Old Address, Large GTC Transfers 2": + "0xeD865C87c3509e3A908655777B13f7313b2fc196", + "Old Address, Large GTC Transfers 3": + "0xDD6a165B9e05549640149dF108AC0aF8579B7005", + "Old Address, Large GTC Transfers 4": + "0xaD467E6039F0Ca383b5FFd60F1C7a890acaB4bE3", + "Old Address, Large GTC Transfers 5": + "0x44d4d830788cc6D4d72C78203F5918a3E2761691", + "Old Address, Large GTC Transfers 6": + "0x38661187CfD779bEa00e14Bc5b986CF0C717A39B", + "Old Address, Large GTC Transfers 7": + "0x34237F91D2Ce322f3572376b82472C7FA56D7595", + "Old Address, Large GTC Transfers 8": + "0x2083e7B107347AE4F5Cb6Ff35EC5DAcf03391c57", + "Old Address, Large GTC Transfers 9": + "0x183a1CaF6750CF88E45812FCE0110D59d71833e4", + "Old Address, Large GTC Transfers 10": + "0x11e06eF6e42306dc40D2754Ef2629fB011d80aE9", + }, + [DaoIdEnum.SCR]: { + "DAO Treasury": "0x4cb06982dD097633426cf32038D9f1182a9aDA0c", + "Foundation Treasury": "0xfF120e015777E9AA9F1417a4009a65d2EdA78C13", + "Ecosystem Treasury": "0xeE198F4a91E5b05022dc90535729B2545D3b03DF", + }, + [DaoIdEnum.COMP]: { + Timelock: "0x6d903f6003cca6255D85CcA4D3B5E5146dC33925", + Comptroller: "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B", + /// v2 markets + v2WBTC: "0xccF4429DB6322D5C611ee964527D42E5d685DD6a", + v2USDC: "0x39AA39c021dfbaE8faC545936693aC917d5E7563", + v2DAI: "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643", + v2USDT: "0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9", + v2ETH: "0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5", + v2UNI: "0x35A18000230DA775CAc24873d00Ff85BccdeD550", + v2BAT: "0x6C8c6b02E7b2BE14d4fA6022Dfd6d75921D90E4E", + v2LINK: "0xFAce851a4921ce59e912d19329929CE6da6EB0c7", + v2TUSD: "0x12392F67bdf24faE0AF363c24aC620a2f67DAd86", + v2AAVE: "0xe65cdB6479BaC1e22340E4E755fAE7E509EcD06c", + v2COMP: "0x70e36f6BF80a52b3B46b3aF8e106CC0ed743E8e4", + ///v3 markets + //Ethereum markets + mainnetETH: "0xA17581A9E3356d9A858b789D68B4d866e593aE94", + mainnetstETH: "0x3D0bb1ccaB520A66e607822fC55BC921738fAFE3", + mainnetUSDT: "0x3Afdc9BCA9213A35503b077a6072F3D0d5AB0840", + mainnetUSDS: "0x5D409e56D886231aDAf00c8775665AD0f9897b56", + mainnetUSDC: "0xc3d688B66703497DAA19211EEdff47f25384cdc3", + mainnetWBTC: "0xe85Dc543813B8c2CFEaAc371517b925a166a9293", + // Optimism markets + opETH: "0xE36A30D249f7761327fd973001A32010b521b6Fd", + opUSDT: "0x995E394b8B2437aC8Ce61Ee0bC610D617962B214", + opUSDC: "0x2e44e174f7D53F0212823acC11C01A11d58c5bCB", + // Unichain markets + uniUSDC: "0x2c7118c4C88B9841FCF839074c26Ae8f035f2921", + uniETH: "0x6C987dDE50dB1dcDd32Cd4175778C2a291978E2a", + // Polygon markets + polyUSDT0: "0xaeB318360f27748Acb200CE616E389A6C9409a07", + polyUSDC: "0xF25212E676D1F7F89Cd72fFEe66158f541246445", + // Ronin markets + ronWETH: "0x4006ed4097ee51c09a04c3b0951d28ccf19e6dfe", + ronRON: "0xc0Afdbd1cEB621Ef576BA969ce9D4ceF78Dbc0c0", + // Mantle markets + manUSDe: "0x606174f62cd968d8e684c645080fa694c1D7786E", + // Base markets + manUSDbC: "0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf", + manUSDC: "0xb125E6687d4313864e53df431d5425969c15Eb2F", + manAERO: "0x784efeB622244d2348d4F2522f8860B96fbEcE89", + manUSDS: "0x2c776041CCFe903071AF44aa147368a9c8EEA518", + manETH: "0x46e6b214b524310239732D51387075E0e70970bf", + // Arbitrum marketsVOTE + arbUSDT0: "0xd98Be00b5D27fc98112BdE293e487f8D4cA57d07", + arbUSDC: "0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf", + "arbUSDC.e": "0xA5EDBDD9646f8dFF606d7448e414884C7d905dCA", + arbETH: "0x6f7D514bbD4aFf3BcD1140B7344b32f063dEe486", + // Linea markets + linUSDC: "0x8D38A3d6B3c3B7d96D6536DA7Eef94A9d7dbC991", + linETH: "0x60F2058379716A64a7A5d29219397e79bC552194", + // Scroll markets + scrUSDC: "0xB2f97c1Bd3bf02f5e74d13f02E3e26F93D77CE44", + }, + [DaoIdEnum.OBOL]: { + timelock: "0xCdBf527842Ab04Da548d33EB09d03DB831381Fb0", + "Ecosystem Treasury 1": "0x42D201CC4d9C1e31c032397F54caCE2f48C1FA72", + "Ecosystem Treasury 2": "0x54076088bE86943e27B99120c5905AAD8A1bD166", + "Staking Rewards Reserve": "0x33f3D61415784A5899b733976b0c1F9176051569", + "OBOL Incentives Reserve": "0xdc8A309111aB0574CA51cA9C7Dd0152738e4c374", + "Protocol Revenue": "0xDe5aE4De36c966747Ea7DF13BD9589642e2B1D0d", + "Grant Program": "0xa59f60A7684A69E63c07bEC087cEC3D0607cd5cE", + "DV Labs Treasury 2": "0x6BeFB6484AA10187947Dda81fC01e495f7168dB4", + }, + [DaoIdEnum.ZK]: { + timelock: "0xe5d21A9179CA2E1F0F327d598D464CcF60d89c3d", + }, +}; + +export enum ProposalStatus { + PENDING = "PENDING", + ACTIVE = "ACTIVE", + CANCELED = "CANCELED", + DEFEATED = "DEFEATED", + SUCCEEDED = "SUCCEEDED", + QUEUED = "QUEUED", + EXPIRED = "EXPIRED", + EXECUTED = "EXECUTED", + NO_QUORUM = "NO_QUORUM", +} + +export enum MetricTypesEnum { + TOTAL_SUPPLY = "TOTAL_SUPPLY", + DELEGATED_SUPPLY = "DELEGATED_SUPPLY", + CEX_SUPPLY = "CEX_SUPPLY", + DEX_SUPPLY = "DEX_SUPPLY", + LENDING_SUPPLY = "LENDING_SUPPLY", + CIRCULATING_SUPPLY = "CIRCULATING_SUPPLY", + TREASURY = "TREASURY", +} + +export const MetricTypesArray = Object.values(MetricTypesEnum) as [ + string, + ...string[], +]; diff --git a/apps/indexer/tests/lib/date-helpers.test.ts b/apps/api/src/lib/date-helpers.test.ts similarity index 100% rename from apps/indexer/tests/lib/date-helpers.test.ts rename to apps/api/src/lib/date-helpers.test.ts diff --git a/apps/api/src/lib/date-helpers.ts b/apps/api/src/lib/date-helpers.ts new file mode 100644 index 000000000..f884e70a6 --- /dev/null +++ b/apps/api/src/lib/date-helpers.ts @@ -0,0 +1,62 @@ +/** + * Date and timestamp utilities for time-series data processing. + */ + +import { SECONDS_IN_DAY } from "./enums"; + +/** + * Truncate timestamp (seconds) to midnight UTC + */ +export const truncateTimestampToMidnight = (timestampSec: number): number => { + return Math.floor(timestampSec / SECONDS_IN_DAY) * SECONDS_IN_DAY; +}; + +/** + * Calculate cutoff timestamp for filtering data by days + */ +export const calculateCutoffTimestamp = (days: number): number => { + return Math.floor(Date.now() / 1000) - days * SECONDS_IN_DAY; +}; + +/** + * Normalize all timestamps in a Map to midnight UTC (seconds) + */ +export const normalizeMapTimestamps = ( + map: Map, +): Map => { + const normalized = new Map(); + map.forEach((value, ts) => { + normalized.set(truncateTimestampToMidnight(ts), value); + }); + return normalized; +}; + +/** + * Get effective start date, adjusting if no initial value exists. + * + * When querying time-series data with forward-fill, if there's no initial value + * before the requested start date, we should start from the first real data point + * to avoid returning zeros/nulls. + * + * @param params.referenceDate - Requested start date (after ?? startDate) + * @param params.datesFromDb - Array of timestamps from database + * @param params.hasInitialValue - Whether an initial value exists before referenceDate + * @returns Effective start date to use + */ +export function getEffectiveStartDate(params: { + referenceDate?: number; + datesFromDb: number[]; + hasInitialValue: boolean; +}): number | undefined { + const { referenceDate, datesFromDb, hasInitialValue } = params; + + if (!referenceDate) return undefined; + if (hasInitialValue || datesFromDb.length === 0) return referenceDate; + + const sortedDates = [...datesFromDb].sort((a, b) => a - b); + const firstRealDate = sortedDates[0]; + + return firstRealDate && referenceDate < firstRealDate + ? firstRealDate + : referenceDate; +} diff --git a/apps/api/src/lib/enums.ts b/apps/api/src/lib/enums.ts new file mode 100644 index 000000000..c090a553d --- /dev/null +++ b/apps/api/src/lib/enums.ts @@ -0,0 +1,29 @@ +export enum DaoIdEnum { + UNI = "UNI", + ENS = "ENS", + ARB = "ARB", + OP = "OP", + GTC = "GTC", + NOUNS = "NOUNS", + TEST = "TEST", + SCR = "SCR", + COMP = "COMP", + OBOL = "OBOL", + ZK = "ZK", +} + +export const SECONDS_IN_DAY = 24 * 60 * 60; + +/** + * Enum representing different time periods in seconds + * Used for filtering data over specific time ranges + */ +export enum DaysEnum { + "7d" = 7 * SECONDS_IN_DAY, + "30d" = 30 * SECONDS_IN_DAY, + "90d" = 90 * SECONDS_IN_DAY, + "180d" = 180 * SECONDS_IN_DAY, + "365d" = 365 * SECONDS_IN_DAY, +} + +export const DaysOpts = ["7d", "30d", "90d", "180d", "365d"] as const; diff --git a/apps/indexer/tests/lib/query-helpers.test.ts b/apps/api/src/lib/query-helpers.test.ts similarity index 100% rename from apps/indexer/tests/lib/query-helpers.test.ts rename to apps/api/src/lib/query-helpers.test.ts diff --git a/apps/api/src/lib/query-helpers.ts b/apps/api/src/lib/query-helpers.ts new file mode 100644 index 000000000..987cbbfa5 --- /dev/null +++ b/apps/api/src/lib/query-helpers.ts @@ -0,0 +1,104 @@ +/** + * Query helpers for pagination and data filtering in time-series APIs. + */ + +import { truncateTimestampToMidnight } from "./date-helpers"; + +/** + * Filter data by cutoff date with fallback to last value before cutoff. + * + * Returns items with date >= cutoffDate. If no items match, returns the last + * item before the cutoff as fallback (using getLastValueBefore). + * + * @param sortedData - Array sorted by date ascending, items must have `date` property + * @param cutoffDate - Minimum date (inclusive) + * @returns Filtered data, or last value before cutoff if filter returns empty + * + * @example + * const data = [{ date: 1, value: 10 }, { date: 5, value: 20 }]; + * const result = filterWithFallback(data, 3); + * // Result: [{ date: 5, value: 20 }] + * + * const result2 = filterWithFallback(data, 100); + * // Result: [{ date: 5, value: 20 }] (fallback to last before cutoff) + */ +export function filterWithFallback( + sortedData: T[], + cutoffDate: number, +): T[] { + const filtered = sortedData.filter((item) => item.date >= cutoffDate); + + if (filtered.length === 0 && sortedData.length > 0) { + const lastBefore = getLastValueBefore(sortedData, cutoffDate); + return lastBefore ? [lastBefore] : []; + } + + return filtered; +} + +/** + * Get the last value before a given date from sorted data. + * + * Useful for finding the initial value for forward-fill when the requested + * time range starts after the first available data point. + * + * @param sortedData - Array sorted by date ascending, items must have `date` property + * @param beforeDate - The cutoff date (exclusive) + * @returns The last item before the date, or undefined if none exists + * + * @example + * const data = [{ date: 1, value: 10 }, { date: 5, value: 20 }]; + * const result = getLastValueBefore(data, 3); + * // Result: { date: 1, value: 10 } + */ +export function getLastValueBefore( + sortedData: T[], + beforeDate: number, +): T | undefined { + for (let i = sortedData.length - 1; i >= 0; i--) { + const item = sortedData[i]; + if (item !== undefined && item.date < beforeDate) { + return item; + } + } + return undefined; +} + +/** + * Apply cursor-based pagination to time-series items. + * + * Filters items by after/before cursors and applies limit. + * Calculates hasNextPage based on whether more data exists. + * + * @param params.items - Array of items with date property + * @param params.after - Return items after this timestamp (exclusive) + * @param params.before - Return items before this timestamp (exclusive) + * @param params.limit - Maximum items to return + * @param params.endDate - If provided, hasNextPage uses simple length check; + * otherwise checks if last item reached today + * @returns Paginated items and hasNextPage flag + */ +export function applyCursorPagination(params: { + items: T[]; + skip?: number; + limit: number; + endDate?: number; +}): { items: T[]; hasNextPage: boolean } { + const { items: allItems, skip, limit, endDate } = params; + + if (skip !== undefined && skip > 0) { + const items = allItems.slice(skip, skip + limit); + const hasNextPage = allItems.length > skip + limit; + return { items, hasNextPage }; + } + + const items = allItems.slice(0, limit); + const today = truncateTimestampToMidnight(Math.floor(Date.now() / 1000)); + const lastItemDate = Number(items[items.length - 1]?.date ?? 0); + + const hasNextPage = endDate + ? allItems.length > limit + : allItems.length > limit && lastItemDate < today; + + return { items, hasNextPage }; +} diff --git a/apps/indexer/tests/lib/time-series.test.ts b/apps/api/src/lib/time-series.test.ts similarity index 100% rename from apps/indexer/tests/lib/time-series.test.ts rename to apps/api/src/lib/time-series.test.ts diff --git a/apps/api/src/lib/time-series.ts b/apps/api/src/lib/time-series.ts new file mode 100644 index 000000000..5776ca935 --- /dev/null +++ b/apps/api/src/lib/time-series.ts @@ -0,0 +1,105 @@ +/** + * Core time-series utilities for forward-fill and timeline generation. + * + * Forward-fill: Use the last known value for any missing data points. + */ + +import { SECONDS_IN_DAY } from "./enums"; +import { truncateTimestampToMidnight } from "./date-helpers"; + +/** + * Forward-fill sparse data across a master timeline. + * + * Works with any key type (number, bigint, string) and any value type. + * + * @param timeline - Sorted array of timestamps/keys + * @param sparseData - Map of key to value (may have gaps) + * @param initialValue - Optional initial value when no data exists before first entry + * @returns Map with values filled for all timeline keys + * + * @example + * // With numbers + * const filled = forwardFill([1000, 2000, 3000], new Map([[1000, 10]]), 0); + * // Result: Map { 1000 => 10, 2000 => 10, 3000 => 10 } + * + */ +export function forwardFill( + timeline: K[], + sparseData: Map, + initialValue?: V, +): Map { + const result = new Map(); + let lastKnownValue: V | undefined = initialValue; + + for (const key of timeline) { + if (sparseData.has(key)) { + lastKnownValue = sparseData.get(key); + } + + if (lastKnownValue !== undefined) { + result.set(key, lastKnownValue); + } + } + + return result; +} + +/** + * Create daily timeline from first timestamp to last timestamp (seconds). + * + * @param firstTimestamp - Start timestamp in seconds (will be truncated to midnight) + * @param lastTimestamp - End timestamp in seconds (will be truncated to midnight) + * @returns Array of daily timestamps (midnight UTC) in seconds + */ +export function createDailyTimeline( + firstTimestamp: number, + lastTimestamp?: number, +): number[] { + if (!lastTimestamp) { + lastTimestamp = truncateTimestampToMidnight(Math.floor(Date.now() / 1000)); + } + if (firstTimestamp > lastTimestamp) return []; + const startMidnight = truncateTimestampToMidnight(firstTimestamp); + const endMidnight = truncateTimestampToMidnight(lastTimestamp); + const totalDays = + Math.floor((endMidnight - startMidnight) / SECONDS_IN_DAY) + 1; + + return Array.from( + { length: totalDays }, + (_, i) => startMidnight + i * SECONDS_IN_DAY, + ); +} + +/** + * Generate ordered daily timeline from dates array. + * + * Creates a complete daily timeline from startDate (or first date in array) + * to endDate (or today), optionally reversed for descending order. + * + * @param params.datesFromDb - Array of timestamps from database (will be sorted) + * @param params.startDate - Optional start date override + * @param params.endDate - Optional end date (defaults to today) + * @param params.orderDirection - "asc" or "desc" ordering + * @returns Array of daily timestamps + */ +export function generateOrderedTimeline(params: { + datesFromDb: number[]; + startDate?: number; + endDate?: number; + orderDirection?: "asc" | "desc"; +}): number[] { + const { datesFromDb, startDate, endDate, orderDirection } = params; + + if (datesFromDb.length === 0 && !startDate) return []; + + const sortedDates = [...datesFromDb].sort((a, b) => a - b); + const firstDate = startDate ?? sortedDates[0]; + const lastDate = + endDate ?? truncateTimestampToMidnight(Math.floor(Date.now() / 1000)); + + if (!firstDate || !lastDate) return []; + + const timeline = createDailyTimeline(firstDate, lastDate); + if (orderDirection === "desc") timeline.reverse(); + return timeline; +} diff --git a/apps/api/src/lib/utils.ts b/apps/api/src/lib/utils.ts new file mode 100644 index 000000000..837c8d24c --- /dev/null +++ b/apps/api/src/lib/utils.ts @@ -0,0 +1,5 @@ +import * as chains from "viem/chains"; + +export function getChain(chainId: number): chains.Chain | undefined { + return Object.values(chains).find((chain) => chain.id === chainId); +} diff --git a/apps/indexer/src/api/mappers/account-balance/general.ts b/apps/api/src/mappers/account-balance/general.ts similarity index 86% rename from apps/indexer/src/api/mappers/account-balance/general.ts rename to apps/api/src/mappers/account-balance/general.ts index c3053ba1a..c82ca09c3 100644 --- a/apps/indexer/src/api/mappers/account-balance/general.ts +++ b/apps/api/src/mappers/account-balance/general.ts @@ -1,5 +1,5 @@ import { z } from "@hono/zod-openapi"; -import { accountBalance } from "ponder:schema"; +import { accountBalance } from "@/database"; import { Address, getAddress, isAddress } from "viem"; export const AccountBalancesRequestSchema = z.object({ @@ -23,10 +23,12 @@ export const AccountBalancesRequestSchema = z.object({ .string() .refine(isAddress, "Invalid address") .transform((addr) => [getAddress(addr)]), - z.array(z - .string() - .refine(isAddress, "Invalid addresses") - .transform((addr) => getAddress(addr))), + z.array( + z + .string() + .refine(isAddress, "Invalid addresses") + .transform((addr) => getAddress(addr)), + ), ]) .optional() .transform((val) => (val === undefined ? [] : val)), @@ -36,10 +38,11 @@ export const AccountBalancesRequestSchema = z.object({ .string() .refine(isAddress, "Invalid address") .transform((addr) => [getAddress(addr)]), - z.array(z - .string() - .refine(isAddress, "Invalid addresses") - .transform((addr) => getAddress(addr)), + z.array( + z + .string() + .refine(isAddress, "Invalid addresses") + .transform((addr) => getAddress(addr)), ), ]) .optional() diff --git a/apps/indexer/src/api/mappers/account-balance/historical.ts b/apps/api/src/mappers/account-balance/historical.ts similarity index 96% rename from apps/indexer/src/api/mappers/account-balance/historical.ts rename to apps/api/src/mappers/account-balance/historical.ts index 2b489e2cf..220d20d99 100644 --- a/apps/indexer/src/api/mappers/account-balance/historical.ts +++ b/apps/api/src/mappers/account-balance/historical.ts @@ -1,5 +1,5 @@ import { z } from "@hono/zod-openapi"; -import { balanceHistory } from "ponder:schema"; +import { balanceHistory } from "@/database"; import { getAddress, isAddress } from "viem"; import { DBTransfer } from "../transfers"; @@ -12,7 +12,7 @@ export const HistoricalBalanceRequestParamsSchema = z.object({ address: z .string() .refine((addr) => isAddress(addr)) - .transform((addr) => getAddress(addr)) + .transform((addr) => getAddress(addr)), }); export const HistoricalBalanceRequestQuerySchema = z.object({ diff --git a/apps/indexer/src/api/mappers/account-balance/index.ts b/apps/api/src/mappers/account-balance/index.ts similarity index 100% rename from apps/indexer/src/api/mappers/account-balance/index.ts rename to apps/api/src/mappers/account-balance/index.ts diff --git a/apps/indexer/src/api/mappers/account-balance/interactions.ts b/apps/api/src/mappers/account-balance/interactions.ts similarity index 98% rename from apps/indexer/src/api/mappers/account-balance/interactions.ts rename to apps/api/src/mappers/account-balance/interactions.ts index 60bd90f0d..31e05407f 100644 --- a/apps/indexer/src/api/mappers/account-balance/interactions.ts +++ b/apps/api/src/mappers/account-balance/interactions.ts @@ -7,7 +7,7 @@ export const AccountInteractionsParamsSchema = z.object({ address: z .string() .refine(isAddress, "Invalid address") - .transform((addr) => getAddress(addr)) + .transform((addr) => getAddress(addr)), }); export const AccountInteractionsQuerySchema = z.object({ diff --git a/apps/indexer/src/api/mappers/account-balance/variations.ts b/apps/api/src/mappers/account-balance/variations.ts similarity index 100% rename from apps/indexer/src/api/mappers/account-balance/variations.ts rename to apps/api/src/mappers/account-balance/variations.ts diff --git a/apps/indexer/src/api/mappers/constants.ts b/apps/api/src/mappers/constants.ts similarity index 100% rename from apps/indexer/src/api/mappers/constants.ts rename to apps/api/src/mappers/constants.ts diff --git a/apps/indexer/src/api/mappers/dao/index.ts b/apps/api/src/mappers/dao/index.ts similarity index 100% rename from apps/indexer/src/api/mappers/dao/index.ts rename to apps/api/src/mappers/dao/index.ts diff --git a/apps/indexer/src/api/mappers/delegation-percentage/index.ts b/apps/api/src/mappers/delegation-percentage/index.ts similarity index 96% rename from apps/indexer/src/api/mappers/delegation-percentage/index.ts rename to apps/api/src/mappers/delegation-percentage/index.ts index 31b4ace7e..7443f23b0 100644 --- a/apps/indexer/src/api/mappers/delegation-percentage/index.ts +++ b/apps/api/src/mappers/delegation-percentage/index.ts @@ -1,5 +1,8 @@ import { z } from "zod"; import { SECONDS_IN_DAY } from "@/lib/enums"; +import { daoMetricsDayBucket } from "@/database"; + +export type DBTokenMetric = typeof daoMetricsDayBucket.$inferSelect; // === ZOD SCHEMAS === diff --git a/apps/indexer/src/api/mappers/delegations/delegations.ts b/apps/api/src/mappers/delegations/delegations.ts similarity index 95% rename from apps/indexer/src/api/mappers/delegations/delegations.ts rename to apps/api/src/mappers/delegations/delegations.ts index 1f7e3ebc0..46393fd4b 100644 --- a/apps/indexer/src/api/mappers/delegations/delegations.ts +++ b/apps/api/src/mappers/delegations/delegations.ts @@ -1,7 +1,7 @@ import { z } from "@hono/zod-openapi"; import { getAddress, isAddress } from "viem"; import { DelegationItem, DelegationsResponse } from "./historical"; -import { delegation } from "ponder:schema"; +import { delegation } from "@/database"; export type DBDelegation = typeof delegation.$inferSelect; diff --git a/apps/indexer/src/api/mappers/delegations/historical.ts b/apps/api/src/mappers/delegations/historical.ts similarity index 100% rename from apps/indexer/src/api/mappers/delegations/historical.ts rename to apps/api/src/mappers/delegations/historical.ts diff --git a/apps/indexer/src/api/mappers/delegations/index.ts b/apps/api/src/mappers/delegations/index.ts similarity index 100% rename from apps/indexer/src/api/mappers/delegations/index.ts rename to apps/api/src/mappers/delegations/index.ts diff --git a/apps/indexer/src/api/mappers/index.ts b/apps/api/src/mappers/index.ts similarity index 94% rename from apps/indexer/src/api/mappers/index.ts rename to apps/api/src/mappers/index.ts index d8d47c88b..58b16b5a0 100644 --- a/apps/indexer/src/api/mappers/index.ts +++ b/apps/api/src/mappers/index.ts @@ -10,4 +10,5 @@ export * from "./shared"; export * from "./transactions"; export * from "./transfers"; export * from "./treasury"; +export * from "./votes"; export * from "./voting-power"; diff --git a/apps/indexer/src/api/mappers/last-update/index.ts b/apps/api/src/mappers/last-update/index.ts similarity index 100% rename from apps/indexer/src/api/mappers/last-update/index.ts rename to apps/api/src/mappers/last-update/index.ts diff --git a/apps/indexer/src/api/mappers/proposals/activity.ts b/apps/api/src/mappers/proposals/activity.ts similarity index 100% rename from apps/indexer/src/api/mappers/proposals/activity.ts rename to apps/api/src/mappers/proposals/activity.ts diff --git a/apps/indexer/src/api/mappers/proposals/index.ts b/apps/api/src/mappers/proposals/index.ts similarity index 76% rename from apps/indexer/src/api/mappers/proposals/index.ts rename to apps/api/src/mappers/proposals/index.ts index 54d435719..088e7ff64 100644 --- a/apps/indexer/src/api/mappers/proposals/index.ts +++ b/apps/api/src/mappers/proposals/index.ts @@ -1,4 +1,3 @@ export * from "./voters"; export * from "./proposals"; -export * from "./votes"; export * from "./activity"; diff --git a/apps/indexer/src/api/mappers/proposals/proposals.ts b/apps/api/src/mappers/proposals/proposals.ts similarity index 98% rename from apps/indexer/src/api/mappers/proposals/proposals.ts rename to apps/api/src/mappers/proposals/proposals.ts index edcc9ecd0..3d2930653 100644 --- a/apps/indexer/src/api/mappers/proposals/proposals.ts +++ b/apps/api/src/mappers/proposals/proposals.ts @@ -1,5 +1,5 @@ import { z } from "@hono/zod-openapi"; -import { proposalsOnchain } from "ponder:schema"; +import { proposalsOnchain } from "@/database"; export type DBProposal = typeof proposalsOnchain.$inferSelect; diff --git a/apps/indexer/src/api/mappers/proposals/voters.ts b/apps/api/src/mappers/proposals/voters.ts similarity index 100% rename from apps/indexer/src/api/mappers/proposals/voters.ts rename to apps/api/src/mappers/proposals/voters.ts diff --git a/apps/indexer/src/api/mappers/shared.ts b/apps/api/src/mappers/shared.ts similarity index 100% rename from apps/indexer/src/api/mappers/shared.ts rename to apps/api/src/mappers/shared.ts diff --git a/apps/indexer/src/api/mappers/token-metrics/index.ts b/apps/api/src/mappers/token-metrics/index.ts similarity index 100% rename from apps/indexer/src/api/mappers/token-metrics/index.ts rename to apps/api/src/mappers/token-metrics/index.ts diff --git a/apps/indexer/src/api/mappers/token/index.ts b/apps/api/src/mappers/token/index.ts similarity index 97% rename from apps/indexer/src/api/mappers/token/index.ts rename to apps/api/src/mappers/token/index.ts index c152b23cc..85eac7c54 100644 --- a/apps/indexer/src/api/mappers/token/index.ts +++ b/apps/api/src/mappers/token/index.ts @@ -1,5 +1,5 @@ import { z } from "@hono/zod-openapi"; -import { token } from "ponder:schema"; +import { token } from "@/database"; export const TokenHistoricalPriceRequest = z.object({ skip: z.coerce diff --git a/apps/indexer/src/api/mappers/transactions/index.ts b/apps/api/src/mappers/transactions/index.ts similarity index 99% rename from apps/indexer/src/api/mappers/transactions/index.ts rename to apps/api/src/mappers/transactions/index.ts index 4bb72e2de..527b29cec 100644 --- a/apps/indexer/src/api/mappers/transactions/index.ts +++ b/apps/api/src/mappers/transactions/index.ts @@ -1,7 +1,7 @@ import { getAddress, isAddress } from "viem"; import { z } from "@hono/zod-openapi"; -import { transaction } from "ponder:schema"; +import { transaction } from "@/database"; import { DBTransfer, diff --git a/apps/indexer/src/api/mappers/transfers/index.ts b/apps/api/src/mappers/transfers/index.ts similarity index 98% rename from apps/indexer/src/api/mappers/transfers/index.ts rename to apps/api/src/mappers/transfers/index.ts index 0eee20b7f..2e20cc1cb 100644 --- a/apps/indexer/src/api/mappers/transfers/index.ts +++ b/apps/api/src/mappers/transfers/index.ts @@ -1,6 +1,6 @@ import { z } from "@hono/zod-openapi"; -import { transfer } from "ponder:schema"; +import { transfer } from "@/database"; import { getAddress, isAddress } from "viem"; export type DBTransfer = typeof transfer.$inferSelect; diff --git a/apps/indexer/src/api/mappers/treasury/index.ts b/apps/api/src/mappers/treasury/index.ts similarity index 100% rename from apps/indexer/src/api/mappers/treasury/index.ts rename to apps/api/src/mappers/treasury/index.ts diff --git a/apps/indexer/src/api/mappers/proposals/votes.ts b/apps/api/src/mappers/votes/index.ts similarity index 75% rename from apps/indexer/src/api/mappers/proposals/votes.ts rename to apps/api/src/mappers/votes/index.ts index f27cd3f21..463d13234 100644 --- a/apps/indexer/src/api/mappers/proposals/votes.ts +++ b/apps/api/src/mappers/votes/index.ts @@ -1,5 +1,5 @@ import { z } from "@hono/zod-openapi"; -import { votesOnchain } from "ponder:schema"; +import { votesOnchain } from "@/database"; import { getAddress, isAddress } from "viem"; export type DBVote = typeof votesOnchain.$inferSelect; @@ -13,8 +13,6 @@ export const VotesRequestSchema = z.object({ .default(0), limit: z.coerce .number() - .int() - .min(1, "Limit must be a positive integer") .max(1000, "Limit cannot exceed 1000") .optional() .default(10), @@ -38,6 +36,8 @@ export const VotesRequestSchema = z.object({ .number() .transform((val) => String(val)) // Support for the vote like For, Against, Abstain .optional(), + fromDate: z.coerce.number().optional(), + toDate: z.coerce.number().optional(), }); export type VotesRequest = z.infer; @@ -48,8 +48,9 @@ export const VoteResponseSchema = z.object({ proposalId: z.string(), support: z.number(), votingPower: z.string(), - reason: z.string().nullable(), + reason: z.string().optional(), timestamp: z.number(), + proposalTitle: z.string(), }); export type VoteResponse = z.infer; @@ -60,17 +61,3 @@ export const VotesResponseSchema = z.object({ }); export type VotesResponse = z.infer; - -export const VotesMapper = { - toApi: (vote: DBVote): VoteResponse => { - return { - voterAddress: vote.voterAccountId, - transactionHash: vote.txHash, - proposalId: vote.proposalId, - support: Number(vote.support), - votingPower: vote.votingPower.toString(), - reason: vote.reason || null, - timestamp: Number(vote.timestamp), - }; - }, -}; diff --git a/apps/indexer/src/api/mappers/voting-power/historical.ts b/apps/api/src/mappers/voting-power/historical.ts similarity index 98% rename from apps/indexer/src/api/mappers/voting-power/historical.ts rename to apps/api/src/mappers/voting-power/historical.ts index 6f7b4e6f0..d708f18cf 100644 --- a/apps/indexer/src/api/mappers/voting-power/historical.ts +++ b/apps/api/src/mappers/voting-power/historical.ts @@ -1,5 +1,5 @@ import { z } from "@hono/zod-openapi"; -import { delegation, votingPowerHistory } from "ponder:schema"; +import { delegation, votingPowerHistory } from "@/database"; import { DBTransfer } from "../transfers"; import { getAddress, isAddress } from "viem"; diff --git a/apps/indexer/src/api/mappers/voting-power/index.ts b/apps/api/src/mappers/voting-power/index.ts similarity index 100% rename from apps/indexer/src/api/mappers/voting-power/index.ts rename to apps/api/src/mappers/voting-power/index.ts diff --git a/apps/indexer/src/api/mappers/voting-power/variations.ts b/apps/api/src/mappers/voting-power/variations.ts similarity index 99% rename from apps/indexer/src/api/mappers/voting-power/variations.ts rename to apps/api/src/mappers/voting-power/variations.ts index 141ee5122..b7cb6042b 100644 --- a/apps/indexer/src/api/mappers/voting-power/variations.ts +++ b/apps/api/src/mappers/voting-power/variations.ts @@ -1,6 +1,6 @@ import { z } from "@hono/zod-openapi"; import { Address, getAddress, isAddress } from "viem"; -import { accountPower } from "ponder:schema"; +import { accountPower } from "@/database"; import { PeriodResponseSchema, TimestampResponseMapper } from "../shared"; diff --git a/apps/indexer/src/api/middlewares/errorHandler.ts b/apps/api/src/middlewares/errorHandler.ts similarity index 100% rename from apps/indexer/src/api/middlewares/errorHandler.ts rename to apps/api/src/middlewares/errorHandler.ts diff --git a/apps/indexer/src/api/middlewares/index.ts b/apps/api/src/middlewares/index.ts similarity index 100% rename from apps/indexer/src/api/middlewares/index.ts rename to apps/api/src/middlewares/index.ts diff --git a/apps/indexer/src/api/repositories/account-balance/historical.ts b/apps/api/src/repositories/account-balance/historical.ts similarity index 88% rename from apps/indexer/src/api/repositories/account-balance/historical.ts rename to apps/api/src/repositories/account-balance/historical.ts index 5779ffbb9..fe0c763f1 100644 --- a/apps/indexer/src/api/repositories/account-balance/historical.ts +++ b/apps/api/src/repositories/account-balance/historical.ts @@ -1,11 +1,13 @@ import { Address } from "viem"; import { gte, and, lte, desc, eq, asc, sql } from "drizzle-orm"; -import { db } from "ponder:api"; +import { Drizzle } from "@/database"; -import { DBHistoricalBalanceWithRelations } from "@/api/mappers"; -import { balanceHistory, transfer } from "ponder:schema"; +import { DBHistoricalBalanceWithRelations } from "@/mappers"; +import { balanceHistory, transfer } from "@/database"; export class HistoricalBalanceRepository { + constructor(private readonly db: Drizzle) {} + async getHistoricalBalances( accountId: Address, skip: number, @@ -17,7 +19,7 @@ export class HistoricalBalanceRepository { fromDate?: number, toDate?: number, ): Promise { - const result = await db + const result = await this.db .select() .from(balanceHistory) .innerJoin( @@ -62,7 +64,7 @@ export class HistoricalBalanceRepository { minDelta?: string, maxDelta?: string, ): Promise { - return await db.$count( + return await this.db.$count( balanceHistory, and( eq(balanceHistory.accountId, accountId), diff --git a/apps/indexer/src/api/repositories/account-balance/index.ts b/apps/api/src/repositories/account-balance/index.ts similarity index 100% rename from apps/indexer/src/api/repositories/account-balance/index.ts rename to apps/api/src/repositories/account-balance/index.ts diff --git a/apps/indexer/src/api/repositories/account-balance/interactions.ts b/apps/api/src/repositories/account-balance/interactions.ts similarity index 89% rename from apps/indexer/src/api/repositories/account-balance/interactions.ts rename to apps/api/src/repositories/account-balance/interactions.ts index 3a48286bd..244207204 100644 --- a/apps/indexer/src/api/repositories/account-balance/interactions.ts +++ b/apps/api/src/repositories/account-balance/interactions.ts @@ -1,11 +1,13 @@ import { Address } from "viem"; -import { asc, desc, gte, sql, and, eq, or, gt, lt, lte } from "ponder"; -import { db } from "ponder:api"; -import { transfer, accountBalance } from "ponder:schema"; +import { asc, desc, gte, sql, and, eq, or, gt, lt, lte } from "drizzle-orm"; +import { Drizzle } from "@/database"; +import { transfer, accountBalance } from "@/database"; import { AccountInteractions, Filter } from "../../mappers"; export class AccountInteractionsRepository { + constructor(private readonly db: Drizzle) {} + async getAccountInteractions( accountId: Address, fromTimestamp: number | undefined, @@ -38,13 +40,13 @@ export class AccountInteractionsRepository { } // Aggregate outgoing transfers (negative amounts) - const scopedTransfers = db + const scopedTransfers = this.db .select() .from(transfer) .where(and(...transferCriteria)) .as("scoped_transfers"); - const transfersFrom = db + const transfersFrom = this.db .select({ accountId: scopedTransfers.fromAccountId, fromAmount: sql`-SUM(${transfer.amount})`.as("from_amount"), @@ -55,7 +57,7 @@ export class AccountInteractionsRepository { .as("transfers_from"); // Aggregate incoming transfers (positive amounts) - const transfersTo = db + const transfersTo = this.db .select({ accountId: scopedTransfers.toAccountId, toAmount: sql`SUM(${transfer.amount})`.as("to_amount"), @@ -66,7 +68,7 @@ export class AccountInteractionsRepository { .as("transfers_to"); // Combine both aggregations - const combined = db + const combined = this.db .select({ accountId: accountBalance.accountId, currentBalance: accountBalance.balance, @@ -97,7 +99,7 @@ export class AccountInteractionsRepository { ) .as("combined"); - const subquery = db + const subquery = this.db .select({ accountId: combined.accountId, currentBalance: combined.currentBalance, @@ -127,7 +129,7 @@ export class AccountInteractionsRepository { ? sql`${subquery.fromCount} + ${subquery.toCount}` : sql`ABS(${subquery.fromChange}) + ABS(${subquery.toChange})`; - const baseQuery = db + const baseQuery = this.db .select() .from(subquery) .where( @@ -142,7 +144,7 @@ export class AccountInteractionsRepository { ) .orderBy(orderDirectionFn(orderByField)); - const totalCountResult = await db + const totalCountResult = await this.db .select({ count: sql`COUNT(*)`.as("count"), }) @@ -170,9 +172,9 @@ export class AccountInteractionsRepository { transferCount: BigInt(transferCount), percentageChange: (currentBalance - BigInt(absoluteChange) ? Number( - (BigInt(absoluteChange) * 10000n) / - (currentBalance - BigInt(absoluteChange)), - ) / 100 + (BigInt(absoluteChange) * 10000n) / + (currentBalance - BigInt(absoluteChange)), + ) / 100 : 0 ).toString(), }), diff --git a/apps/indexer/src/api/repositories/account-balance/listing.ts b/apps/api/src/repositories/account-balance/listing.ts similarity index 88% rename from apps/indexer/src/api/repositories/account-balance/listing.ts rename to apps/api/src/repositories/account-balance/listing.ts index 892ae2fc1..478a7a025 100644 --- a/apps/indexer/src/api/repositories/account-balance/listing.ts +++ b/apps/api/src/repositories/account-balance/listing.ts @@ -1,4 +1,4 @@ -import { AmountFilter, DBAccountBalance } from "@/api/mappers"; +import { AmountFilter, DBAccountBalance } from "@/mappers"; import { and, asc, @@ -11,11 +11,13 @@ import { SQL, sql, } from "drizzle-orm"; -import { db } from "ponder:api"; -import { accountBalance } from "ponder:schema"; +import { Drizzle } from "@/database"; +import { accountBalance } from "@/database"; import { Address } from "viem"; export class AccountBalanceRepository { + constructor(private readonly db: Drizzle) {} + async getAccountBalances( skip: number, limit: number, @@ -36,7 +38,7 @@ export class AccountBalanceRepository { ); // Get total count with filters - const totalCount = await db + const totalCount = await this.db .select({ count: sql`COUNT(*)`.as("count"), }) @@ -44,7 +46,7 @@ export class AccountBalanceRepository { .where(filter); // Get paginated results - const page = await db + const page = await this.db .select() .from(accountBalance) .where(filter) @@ -65,7 +67,7 @@ export class AccountBalanceRepository { async getAccountBalance( accountId: Address, ): Promise { - const [result] = await db + const [result] = await this.db .select() .from(accountBalance) .where(eq(accountBalance.accountId, accountId)) diff --git a/apps/indexer/src/api/repositories/account-balance/variations.ts b/apps/api/src/repositories/account-balance/variations.ts similarity index 72% rename from apps/indexer/src/api/repositories/account-balance/variations.ts rename to apps/api/src/repositories/account-balance/variations.ts index c8d6356f8..f6416759a 100644 --- a/apps/indexer/src/api/repositories/account-balance/variations.ts +++ b/apps/api/src/repositories/account-balance/variations.ts @@ -1,10 +1,12 @@ -import { asc, desc, gte, sql, and, inArray, lte, or } from "ponder"; -import { db } from "ponder:api"; -import { accountBalance, transfer } from "ponder:schema"; -import { DBAccountBalanceVariation } from "@/api/mappers"; +import { asc, desc, gte, sql, and, inArray, lte, or } from "drizzle-orm"; +import { Drizzle } from "@/database"; +import { accountBalance, transfer } from "@/database"; +import { DBAccountBalanceVariation } from "@/mappers"; import { Address } from "viem"; export class BalanceVariationsRepository { + constructor(private readonly db: Drizzle) {} + async getAccountBalanceVariations( fromTimestamp: number | undefined, toTimestamp: number | undefined, @@ -19,8 +21,8 @@ export class BalanceVariationsRepository { limit, skip, orderDirection, - addresses - ) + addresses, + ); } async getAccountBalanceVariationsByAccountId( @@ -28,15 +30,22 @@ export class BalanceVariationsRepository { fromTimestamp: number | undefined, toTimestamp: number | undefined, ): Promise { - const [result] = await this.commonQuery(fromTimestamp, toTimestamp, 1, 0, "desc", [address]) - if (result) return result + const [result] = await this.commonQuery( + fromTimestamp, + toTimestamp, + 1, + 0, + "desc", + [address], + ); + if (result) return result; return { accountId: address, previousBalance: 0n, currentBalance: 0n, absoluteChange: 0n, percentageChange: "0", - } + }; } private async commonQuery( @@ -47,21 +56,28 @@ export class BalanceVariationsRepository { orderDirection: "asc" | "desc", addresses?: Address[], ): Promise { - const scopedTransfers = db + const scopedTransfers = this.db .select() .from(transfer) .where( and( - fromTimestamp ? gte(transfer.timestamp, BigInt(fromTimestamp)) : undefined, - toTimestamp ? lte(transfer.timestamp, BigInt(toTimestamp)) : undefined, - addresses ? or( - inArray(transfer.fromAccountId, addresses), - inArray(transfer.toAccountId, addresses), - ) : undefined, - )) + fromTimestamp + ? gte(transfer.timestamp, BigInt(fromTimestamp)) + : undefined, + toTimestamp + ? lte(transfer.timestamp, BigInt(toTimestamp)) + : undefined, + addresses + ? or( + inArray(transfer.fromAccountId, addresses), + inArray(transfer.toAccountId, addresses), + ) + : undefined, + ), + ) .as("scoped_transfers"); - const transfersFrom = db + const transfersFrom = this.db .select({ accountId: scopedTransfers.fromAccountId, fromAmount: sql`-SUM(${transfer.amount})`.as("from_amount"), @@ -70,7 +86,7 @@ export class BalanceVariationsRepository { .groupBy(scopedTransfers.fromAccountId) .as("transfers_from"); - const transfersTo = db + const transfersTo = this.db .select({ accountId: scopedTransfers.toAccountId, toAmount: sql`SUM(${transfer.amount})`.as("to_amount"), @@ -79,7 +95,7 @@ export class BalanceVariationsRepository { .groupBy(scopedTransfers.toAccountId) .as("transfers_to"); - const combined = db + const combined = this.db .select({ accountId: accountBalance.accountId, currentBalance: accountBalance.balance, @@ -104,7 +120,7 @@ export class BalanceVariationsRepository { ) .as("combined"); - const result = await db + const result = await this.db .select({ accountId: combined.accountId, currentBalance: combined.currentBalance, @@ -128,13 +144,13 @@ export class BalanceVariationsRepository { previousBalance: currentBalance - BigInt(absoluteChange), currentBalance: currentBalance, absoluteChange: BigInt(absoluteChange), - percentageChange: - (currentBalance - BigInt(absoluteChange) - ? Number( + percentageChange: (currentBalance - BigInt(absoluteChange) + ? Number( (BigInt(absoluteChange) * 10000n) / - (currentBalance - BigInt(absoluteChange)), + (currentBalance - BigInt(absoluteChange)), ) / 100 - : 0).toString(), + : 0 + ).toString(), })); } } diff --git a/apps/indexer/src/api/repositories/daoMetricsDayBucket/index.ts b/apps/api/src/repositories/daoMetricsDayBucket/index.ts similarity index 82% rename from apps/indexer/src/api/repositories/daoMetricsDayBucket/index.ts rename to apps/api/src/repositories/daoMetricsDayBucket/index.ts index e8a1ce495..5bd811746 100644 --- a/apps/indexer/src/api/repositories/daoMetricsDayBucket/index.ts +++ b/apps/api/src/repositories/daoMetricsDayBucket/index.ts @@ -1,8 +1,10 @@ -import { db } from "ponder:api"; -import { daoMetricsDayBucket } from "ponder:schema"; -import { and, gte, lte, desc, asc, eq, lt, inArray } from "ponder"; +import { Drizzle } from "@/database"; +import { daoMetricsDayBucket } from "@/database"; +import { and, gte, lte, desc, asc, eq, lt, inArray } from "drizzle-orm"; export class DaoMetricsDayBucketRepository { + constructor(private readonly db: Drizzle) {} + /** * Fetches metrics by type and date range * @param filters - Metric types, date range, and ordering filters @@ -26,7 +28,7 @@ export class DaoMetricsDayBucketRepository { conditions.push(lte(daoMetricsDayBucket.date, BigInt(endDate))); } - return db.query.daoMetricsDayBucket.findMany({ + return this.db.query.daoMetricsDayBucket.findMany({ where: and(...conditions), limit, orderBy: @@ -43,7 +45,7 @@ export class DaoMetricsDayBucketRepository { * @returns The most recent metric row or null if not found */ async getLastMetricBeforeDate(metricType: string, beforeDate: string) { - return db.query.daoMetricsDayBucket.findFirst({ + return this.db.query.daoMetricsDayBucket.findFirst({ where: and( lt(daoMetricsDayBucket.date, BigInt(beforeDate)), eq(daoMetricsDayBucket.metricType, metricType), diff --git a/apps/indexer/src/api/repositories/delegations/general.ts b/apps/api/src/repositories/delegations/general.ts similarity index 59% rename from apps/indexer/src/api/repositories/delegations/general.ts rename to apps/api/src/repositories/delegations/general.ts index 4bce9b7b3..ab9d543e6 100644 --- a/apps/indexer/src/api/repositories/delegations/general.ts +++ b/apps/api/src/repositories/delegations/general.ts @@ -1,12 +1,14 @@ -import { DBDelegation } from "@/api/mappers"; +import { DBDelegation } from "@/mappers"; import { desc, eq } from "drizzle-orm"; -import { db } from "ponder:api"; -import { delegation } from "ponder:schema"; +import { Drizzle } from "@/database"; +import { delegation } from "@/database"; import { Address } from "viem"; export class DelegationsRepository { + constructor(private readonly db: Drizzle) {} + async getDelegations(address: Address): Promise { - const result = await db.query.delegation.findMany({ + const result = await this.db.query.delegation.findMany({ where: eq(delegation.delegateAccountId, address), orderBy: [desc(delegation.timestamp), desc(delegation.logIndex)], }); diff --git a/apps/indexer/src/api/repositories/delegations/historical.ts b/apps/api/src/repositories/delegations/historical.ts similarity index 87% rename from apps/indexer/src/api/repositories/delegations/historical.ts rename to apps/api/src/repositories/delegations/historical.ts index fd2b54d79..a256ef53f 100644 --- a/apps/indexer/src/api/repositories/delegations/historical.ts +++ b/apps/api/src/repositories/delegations/historical.ts @@ -1,10 +1,12 @@ -import { DBDelegation } from "@/api/mappers"; +import { DBDelegation } from "@/mappers"; import { asc, desc, eq, gte, lte, SQL, inArray, and, sql } from "drizzle-orm"; -import { db } from "ponder:api"; -import { delegation } from "ponder:schema"; +import { Drizzle } from "@/database"; +import { delegation } from "@/database"; import { Address } from "viem"; export class HistoricalDelegationsRepository { + constructor(private readonly db: Drizzle) {} + async getHistoricalDelegations( // TODO: add support to partial delegations at some point address: Address, @@ -18,7 +20,7 @@ export class HistoricalDelegationsRepository { items: DBDelegation[]; totalCount: number; }> { - const baseQuery = db + const baseQuery = this.db .select() .from(delegation) .where(this.filterToSql(address, fromValue, toValue, delegateAddressIn)) @@ -28,7 +30,7 @@ export class HistoricalDelegationsRepository { : desc(delegation.timestamp), ); - const [totalCount] = await db + const [totalCount] = await this.db .select({ count: sql`COUNT(*)`.as("count"), }) diff --git a/apps/indexer/src/api/repositories/delegations/index.ts b/apps/api/src/repositories/delegations/index.ts similarity index 100% rename from apps/indexer/src/api/repositories/delegations/index.ts rename to apps/api/src/repositories/delegations/index.ts diff --git a/apps/api/src/repositories/drizzle/index.ts b/apps/api/src/repositories/drizzle/index.ts new file mode 100644 index 000000000..f8f38732a --- /dev/null +++ b/apps/api/src/repositories/drizzle/index.ts @@ -0,0 +1,188 @@ +import { + and, + lte, + asc, + desc, + eq, + gte, + gt, + inArray, + notInArray, + sql, + isNull, + count, + max, +} from "drizzle-orm"; +import { Drizzle } from "@/database"; +import { + accountPower, + proposalsOnchain, + votesOnchain, + votingPowerHistory, +} from "@/database"; +import { SQL } from "drizzle-orm"; +import { Address } from "viem"; + +import { + ActiveSupplyQueryResult, + AverageTurnoutCompareQueryResult, + ProposalsCompareQueryResult, + VotesCompareQueryResult, +} from "@/controllers"; +import { DaysEnum } from "@/lib/enums"; +import { DBProposal } from "@/mappers"; + +export class DrizzleRepository { + constructor(private readonly db: Drizzle) {} + + async getSupplyComparison(metricType: string, days: DaysEnum) { + const query = sql` + WITH old_data AS ( + SELECT db.average as old_amount + FROM dao_metrics_day_buckets db + WHERE db."metricType" = ${metricType} + AND db."date" <= ${this.now() - days} + ORDER BY db."date" desc LIMIT 1 + ), + current_data AS ( + SELECT db.average as current_amount + FROM dao_metrics_day_buckets db + WHERE db."metricType" = ${metricType} + ORDER BY db."date" DESC LIMIT 1 + ) + SELECT COALESCE(old_data.old_amount, 0) AS "oldValue", + COALESCE(current_data.current_amount, 0) AS "currentValue" + FROM current_data + LEFT JOIN old_data ON 1=1; + `; + + const result = await this.db.execute<{ + oldValue: string; + currentValue: string; + }>(query); + return result.rows[0]; + } + + async getActiveSupply(days: DaysEnum) { + const query = sql` + SELECT COALESCE(SUM(ap."voting_power"), 0) as "activeSupply" + FROM "account_power" ap + WHERE ap."last_vote_timestamp" >= ${this.now() - days} + `; + const result = await this.db.execute(query); + return result.rows[0]; + } + + async getProposalsCompare(days: DaysEnum) { + const query = sql` + WITH old_proposals AS ( + SELECT COUNT(*) AS "oldProposalsLaunched" + FROM "proposals_onchain" p + WHERE p.timestamp <= ${this.now() - days} + ), + current_proposals AS ( + SELECT COUNT(*) AS "currentProposalsLaunched" + FROM "proposals_onchain" p + ) + SELECT * FROM current_proposals + JOIN old_proposals ON 1=1; + `; + const result = await this.db.execute(query); + return result.rows[0]; + } + + async getVotesCompare(days: DaysEnum) { + const query = sql` + WITH old_votes AS ( + SELECT COUNT(*) AS "oldVotes" + FROM "votes_onchain" v + WHERE v.timestamp <= ${this.now() - days} + ), + current_votes AS ( + SELECT COUNT(*) AS "currentVotes" + FROM "votes_onchain" v + ) + SELECT * FROM current_votes + JOIN old_votes ON 1=1; + `; + const result = await this.db.execute(query); + return result.rows[0]; + } + + async getAverageTurnoutCompare(days: DaysEnum) { + const query = sql` + WITH old_average_turnout AS ( + SELECT COALESCE(AVG(${proposalsOnchain.forVotes} + ${proposalsOnchain.againstVotes} + ${proposalsOnchain.abstainVotes}), 0) AS "oldAverageTurnout" + FROM ${proposalsOnchain} + WHERE ${proposalsOnchain.timestamp} <= ${this.now() - days} + AND ${proposalsOnchain.status} != 'CANCELED' + ), + current_average_turnout AS ( + SELECT COALESCE(AVG(${proposalsOnchain.forVotes} + ${proposalsOnchain.againstVotes} + ${proposalsOnchain.abstainVotes}), 0) AS "currentAverageTurnout" + FROM ${proposalsOnchain} + WHERE ${proposalsOnchain.status} != 'CANCELED' AND ${proposalsOnchain.timestamp} >= ${this.now() - days} + ) + SELECT * FROM current_average_turnout + JOIN old_average_turnout ON 1=1; + `; + const result = + await this.db.execute(query); + return result.rows[0]; + } + + async getProposals( + skip: number, + limit: number, + orderDirection: "asc" | "desc", + status: string[] | undefined, + fromDate: number | undefined, + fromEndDate: number | undefined, + proposalTypeExclude?: number[], + ): Promise { + const whereClauses: SQL[] = []; + + if (status && status.length > 0) { + whereClauses.push(inArray(proposalsOnchain.status, status)); + } + + if (fromDate) { + whereClauses.push(gte(proposalsOnchain.timestamp, BigInt(fromDate))); + } + + if (fromEndDate) { + whereClauses.push( + gte(proposalsOnchain.endTimestamp, BigInt(fromEndDate)), + ); + } + if (proposalTypeExclude && proposalTypeExclude.length > 0) { + whereClauses.push( + notInArray(proposalsOnchain.proposalType, proposalTypeExclude), + ); + } + return await this.db + .select() + .from(proposalsOnchain) + .where(and(...whereClauses)) + .orderBy( + orderDirection === "asc" + ? asc(proposalsOnchain.timestamp) + : desc(proposalsOnchain.timestamp), + ) + .limit(limit) + .offset(skip); + } + + async getProposalById(proposalId: string): Promise { + return await this.db.query.proposalsOnchain.findFirst({ + where: eq(proposalsOnchain.id, proposalId), + }); + } + + async getProposalsCount(): Promise { + return this.db.$count(proposalsOnchain); + } + + now() { + return Math.floor(Date.now() / 1000); + } +} diff --git a/apps/indexer/src/api/repositories/index.ts b/apps/api/src/repositories/index.ts similarity index 93% rename from apps/indexer/src/api/repositories/index.ts rename to apps/api/src/repositories/index.ts index e67e189d2..5b314b78c 100644 --- a/apps/indexer/src/api/repositories/index.ts +++ b/apps/api/src/repositories/index.ts @@ -9,3 +9,4 @@ export * from "./account-balance"; export * from "./treasury/index"; export * from "./transfers"; export * from "./delegations"; +export * from "./votes"; diff --git a/apps/indexer/src/api/repositories/last-update/index.ts b/apps/api/src/repositories/last-update/index.ts similarity index 81% rename from apps/indexer/src/api/repositories/last-update/index.ts rename to apps/api/src/repositories/last-update/index.ts index fcf8ce9aa..4ee9244ea 100644 --- a/apps/indexer/src/api/repositories/last-update/index.ts +++ b/apps/api/src/repositories/last-update/index.ts @@ -1,8 +1,8 @@ -import { db } from "ponder:api"; -import { inArray } from "ponder"; -import { daoMetricsDayBucket } from "ponder:schema"; +import { Drizzle } from "@/database"; +import { inArray } from "drizzle-orm"; +import { daoMetricsDayBucket } from "@/database"; -import { ChartType } from "@/api/mappers/"; +import { ChartType } from "@/mappers/"; import { MetricTypesEnum } from "@/lib/constants"; export interface LastUpdateRepository { @@ -10,6 +10,8 @@ export interface LastUpdateRepository { } export class LastUpdateRepositoryImpl implements LastUpdateRepository { + constructor(private readonly db: Drizzle) {} + async getLastUpdate(chart: ChartType) { let metricsToCheck: MetricTypesEnum[] = []; @@ -36,7 +38,7 @@ export class LastUpdateRepositoryImpl implements LastUpdateRepository { break; } // Find the record with the greatest timestamp for the specified metrics - const lastUpdate = await db.query.daoMetricsDayBucket.findFirst({ + const lastUpdate = await this.db.query.daoMetricsDayBucket.findFirst({ columns: { lastUpdate: true, }, diff --git a/apps/indexer/src/api/repositories/proposals-activity/index.ts b/apps/api/src/repositories/proposals-activity/index.ts similarity index 85% rename from apps/indexer/src/api/repositories/proposals-activity/index.ts rename to apps/api/src/repositories/proposals-activity/index.ts index f35fd29ed..2d83d2b4a 100644 --- a/apps/indexer/src/api/repositories/proposals-activity/index.ts +++ b/apps/api/src/repositories/proposals-activity/index.ts @@ -1,8 +1,8 @@ import { Address } from "viem"; import { DaoIdEnum } from "@/lib/enums"; -import { asc, eq, sql } from "ponder"; -import { db } from "ponder:api"; -import { votesOnchain } from "ponder:schema"; +import { asc, eq, sql } from "drizzle-orm"; +import { Drizzle } from "@/database"; +import { votesOnchain } from "@/database"; export type DbProposal = { id: string; @@ -43,42 +43,14 @@ export enum VoteFilter { export type OrderByField = "votingPower" | "voteTiming" | "timestamp"; export type OrderDirection = "asc" | "desc"; -export interface ProposalsActivityRepository { - getFirstVoteTimestamp(address: Address): Promise; - - getProposals( - daoId: DaoIdEnum, - activityStart: number, - votingPeriodSeconds: number, - ): Promise; - - getUserVotes( - address: Address, - daoId: DaoIdEnum, - proposalIds: string[], - ): Promise; - - getProposalsWithVotesAndPagination( - address: Address, - activityStart: number, - votingPeriodSeconds: number, - skip: number, - limit: number, - orderBy: OrderByField, - orderDirection: OrderDirection, - userVoteFilter?: VoteFilter, - ): Promise<{ - proposals: DbProposalWithVote[]; - totalCount: number; - }>; -} - /* eslint-disable */ -export class DrizzleProposalsActivityRepository implements ProposalsActivityRepository { +export class DrizzleProposalsActivityRepository { + constructor(private readonly db: Drizzle) {} + /* eslint-enable */ async getFirstVoteTimestamp(address: Address): Promise { - const firstVote = await db.query.votesOnchain.findFirst({ + const firstVote = await this.db.query.votesOnchain.findFirst({ where: eq(votesOnchain.voterAccountId, address), columns: { timestamp: true, @@ -102,7 +74,7 @@ export class DrizzleProposalsActivityRepository implements ProposalsActivityRepo ORDER BY timestamp DESC `; - const result = await db.execute(query); + const result = await this.db.execute(query); return result.rows; } @@ -121,7 +93,7 @@ export class DrizzleProposalsActivityRepository implements ProposalsActivityRepo AND proposal_id IN (${sql.raw(proposalIds.map((id) => `'${id}'`).join(","))}) `; - const result = await db.execute(query); + const result = await this.db.execute(query); return result.rows; } @@ -195,7 +167,7 @@ export class DrizzleProposalsActivityRepository implements ProposalsActivityRepo `; const [result, countResult] = await Promise.all([ - db.execute<{ + this.db.execute<{ id: string; dao_id: string; proposer_account_id: string; @@ -216,7 +188,7 @@ export class DrizzleProposalsActivityRepository implements ProposalsActivityRepo reason: string | null; vote_timestamp: string | null; }>(query), - db.execute<{ total_count: string }>(countQuery), + this.db.execute<{ total_count: string }>(countQuery), ]); const totalCount = Number(countResult.rows[0]?.total_count || 0); diff --git a/apps/indexer/src/api/repositories/token/erc20.ts b/apps/api/src/repositories/token/erc20.ts similarity index 55% rename from apps/indexer/src/api/repositories/token/erc20.ts rename to apps/api/src/repositories/token/erc20.ts index bb37f46de..38aba1dc3 100644 --- a/apps/indexer/src/api/repositories/token/erc20.ts +++ b/apps/api/src/repositories/token/erc20.ts @@ -1,14 +1,16 @@ import { eq } from "drizzle-orm"; -import { db } from "ponder:api"; -import { token } from "ponder:schema"; -import { DBToken } from "@/api/mappers"; +import { Drizzle } from "@/database"; +import { token } from "@/database"; +import { DBToken } from "@/mappers"; import { DaoIdEnum } from "@/lib/enums"; export class TokenRepository { + constructor(private readonly db: Drizzle) {} + async getTokenPropertiesByName( tokenName: DaoIdEnum, ): Promise { - return await db.query.token.findFirst({ + return await this.db.query.token.findFirst({ where: eq(token.name, tokenName), }); } diff --git a/apps/indexer/src/api/repositories/token/index.ts b/apps/api/src/repositories/token/index.ts similarity index 100% rename from apps/indexer/src/api/repositories/token/index.ts rename to apps/api/src/repositories/token/index.ts diff --git a/apps/indexer/src/api/repositories/token/nft.ts b/apps/api/src/repositories/token/nft.ts similarity index 74% rename from apps/indexer/src/api/repositories/token/nft.ts rename to apps/api/src/repositories/token/nft.ts index f0ccefdff..a74fb3d3c 100644 --- a/apps/indexer/src/api/repositories/token/nft.ts +++ b/apps/api/src/repositories/token/nft.ts @@ -1,10 +1,12 @@ -import { db } from "ponder:api"; -import { tokenPrice } from "ponder:schema"; -import { desc, sql } from "ponder"; +import { Drizzle } from "@/database"; +import { tokenPrice } from "@/database"; +import { desc, sql } from "drizzle-orm"; -import { TokenHistoricalPriceResponse } from "@/api/mappers"; +import { TokenHistoricalPriceResponse } from "@/mappers"; export class NFTPriceRepository { + constructor(private readonly db: Drizzle) {} + /** * Repository for handling NFT price data and calculations. * Provides methods to retrieve historical NFT auction prices with rolling averages. @@ -13,7 +15,7 @@ export class NFTPriceRepository { limit: number, offset: number, ): Promise { - return await db + return await this.db .select({ price: sql` CAST( @@ -32,7 +34,7 @@ export class NFTPriceRepository { } async getTokenPrice(): Promise { - return (await db.query.tokenPrice.findFirst({ + return (await this.db.query.tokenPrice.findFirst({ orderBy: desc(tokenPrice.timestamp), }))!.price.toString(); } diff --git a/apps/indexer/src/api/repositories/transactions/index.ts b/apps/api/src/repositories/transactions/index.ts similarity index 97% rename from apps/indexer/src/api/repositories/transactions/index.ts rename to apps/api/src/repositories/transactions/index.ts index 96661090b..eebdce071 100644 --- a/apps/indexer/src/api/repositories/transactions/index.ts +++ b/apps/api/src/repositories/transactions/index.ts @@ -1,9 +1,11 @@ -import { DBTransaction, TransactionsRequest } from "@/api/mappers"; +import { DBTransaction, TransactionsRequest } from "@/mappers"; import { sql, eq, or, countDistinct, SQLChunk } from "drizzle-orm"; -import { db } from "ponder:api"; -import { delegation, transaction, transfer } from "ponder:schema"; +import { Drizzle } from "@/database"; +import { delegation, transaction, transfer } from "@/database"; export class TransactionsRepository { + constructor(private readonly db: Drizzle) {} + async getFilteredAggregateTransactions( filter: TransactionsRequest, ): Promise { @@ -84,7 +86,7 @@ export class TransactionsRepository { LEFT JOIN delegation_aggregates da ON da.transaction_hash = lt.transaction_hash ORDER BY lt.timestamp DESC; `; - const result = await db.execute(query); + const result = await this.db.execute(query); return result.rows; } @@ -95,7 +97,7 @@ export class TransactionsRepository { const { transfer: transferFilter, delegation: delegationFilter } = this.filterToSql(filter); - const query = await db + const query = await this.db .select({ count: countDistinct( sql`coalesce(${transfer.transactionHash}, ${delegation.transactionHash})`, diff --git a/apps/indexer/src/api/repositories/transfers/index.ts b/apps/api/src/repositories/transfers/index.ts similarity index 91% rename from apps/indexer/src/api/repositories/transfers/index.ts rename to apps/api/src/repositories/transfers/index.ts index c6336fec3..303ca3fbc 100644 --- a/apps/indexer/src/api/repositories/transfers/index.ts +++ b/apps/api/src/repositories/transfers/index.ts @@ -1,15 +1,17 @@ -import { db } from "ponder:api"; +import { Drizzle } from "@/database"; import { and, asc, desc, eq, gte, lte, or } from "drizzle-orm"; -import { transfer } from "ponder:schema"; +import { transfer } from "@/database"; -import { DBTransfer, TransfersRequest } from "@/api/mappers"; +import { DBTransfer, TransfersRequest } from "@/mappers"; export class TransfersRepository { + constructor(private readonly db: Drizzle) {} + async getTransfersCount(req: TransfersRequest): Promise { const addressQuery = this.buildAddressQuery(req); if (!addressQuery) return 0; - return await db.$count( + return await this.db.$count( transfer, and( addressQuery, @@ -31,7 +33,7 @@ export class TransfersRepository { const addressQuery = this.buildAddressQuery(req); if (!addressQuery) return []; - return await db.query.transfer.findMany({ + return await this.db.query.transfer.findMany({ where: (transfer, { gte, lte, and }) => and( addressQuery, diff --git a/apps/indexer/src/api/repositories/treasury/index.ts b/apps/api/src/repositories/treasury/index.ts similarity index 82% rename from apps/indexer/src/api/repositories/treasury/index.ts rename to apps/api/src/repositories/treasury/index.ts index d4bc4ae9f..dc1a14957 100644 --- a/apps/indexer/src/api/repositories/treasury/index.ts +++ b/apps/api/src/repositories/treasury/index.ts @@ -1,12 +1,14 @@ -import { db } from "ponder:api"; -import { daoMetricsDayBucket } from "ponder:schema"; -import { and, eq, gte, lte, desc } from "ponder"; +import { Drizzle } from "@/database"; +import { daoMetricsDayBucket } from "@/database"; +import { and, eq, gte, lte, desc } from "drizzle-orm"; import { MetricTypesEnum } from "@/lib/constants"; /** * Repository for treasury-related database queries. */ export class TreasuryRepository { + constructor(private readonly db: Drizzle) {} + /** * Fetch DAO token quantities from daoMetricsDayBucket table * @param cutoffTimestamp - The timestamp to filter the data @@ -15,7 +17,7 @@ export class TreasuryRepository { async getTokenQuantities( cutoffTimestamp: number, ): Promise> { - const results = await db.query.daoMetricsDayBucket.findMany({ + const results = await this.db.query.daoMetricsDayBucket.findMany({ columns: { date: true, close: true, @@ -45,7 +47,7 @@ export class TreasuryRepository { async getLastTokenQuantityBeforeDate( cutoffTimestamp: number, ): Promise { - const result = await db.query.daoMetricsDayBucket.findFirst({ + const result = await this.db.query.daoMetricsDayBucket.findFirst({ where: and( eq(daoMetricsDayBucket.metricType, MetricTypesEnum.TREASURY), lte(daoMetricsDayBucket.date, BigInt(cutoffTimestamp)), diff --git a/apps/api/src/repositories/votes/index.ts b/apps/api/src/repositories/votes/index.ts new file mode 100644 index 000000000..9545e9e18 --- /dev/null +++ b/apps/api/src/repositories/votes/index.ts @@ -0,0 +1,262 @@ +import { Drizzle } from "@/database"; +import { + and, + asc, + desc, + eq, + gte, + lte, + SQL, + inArray, + gt, + isNull, + max, + count, +} from "drizzle-orm"; +import { accountPower, votesOnchain, votingPowerHistory } from "@/database"; + +import { DBVote, VotesRequest } from "@/mappers"; +import { Address } from "viem"; + +export class VotesRepository { + constructor(private readonly db: Drizzle) {} + async getVotes(req: VotesRequest): Promise<{ + items: (DBVote & { description: string })[]; + totalCount: number; + }> { + const sortBy = + req.orderBy === "timestamp" + ? votesOnchain.timestamp + : votesOnchain.votingPower; + const orderBy = req.orderDirection === "desc" ? desc(sortBy) : asc(sortBy); + + const where = and( + req.fromDate + ? gte(votesOnchain.timestamp, BigInt(req.fromDate)) + : undefined, + req.toDate ? lte(votesOnchain.timestamp, BigInt(req.toDate)) : undefined, + ); + + const [items, totalCount] = await Promise.all([ + this.db.query.votesOnchain.findMany({ + where, + limit: req.limit, + offset: req.skip, + orderBy, + with: { + proposal: { + columns: { + description: true, + }, + }, + }, + }), + this.db.$count(votesOnchain, where), + ]); + return { + items: items.map((item) => ({ + ...item, + description: item.proposal.description, + })), + totalCount, + }; + } + + async getProposalNonVoters( + proposalId: string, + skip: number, + limit: number, + orderDirection: "asc" | "desc", + addresses?: Address[], + ): Promise<{ voter: Address; votingPower: bigint }[]> { + return await this.db + .select({ + voter: accountPower.accountId, + votingPower: accountPower.votingPower, + }) + .from(accountPower) + .leftJoin( + votesOnchain, + and( + eq(votesOnchain.proposalId, proposalId), + eq(votesOnchain.voterAccountId, accountPower.accountId), + ), + ) + .where( + and( + ...(addresses ? [inArray(accountPower.accountId, addresses)] : []), + gt(accountPower.votingPower, 0n), + isNull(votesOnchain.proposalId), // NULL means they didn't vote on this proposal + ), + ) + .orderBy( + orderDirection === "asc" + ? asc(accountPower.votingPower) + : desc(accountPower.votingPower), + ) + .limit(limit) + .offset(skip); + } + + async getProposalNonVotersCount(proposalId: string): Promise { + const countResult = await this.db + .select({ count: count(accountPower.accountId) }) + .from(accountPower) + .leftJoin( + votesOnchain, + and( + eq(votesOnchain.proposalId, proposalId), + eq(votesOnchain.voterAccountId, accountPower.accountId), + ), + ) + .where( + and(gt(accountPower.votingPower, 0n), isNull(votesOnchain.proposalId)), + ); + return countResult[0]?.count || 0; + } + + async getLastVotersTimestamp( + voters: Address[], + ): Promise> { + const timestamps = await this.db + .select({ + voterAccountId: votesOnchain.voterAccountId, + lastVoteTimestamp: max(votesOnchain.timestamp), + }) + .from(votesOnchain) + .where(inArray(votesOnchain.voterAccountId, voters)) + .groupBy(votesOnchain.voterAccountId) + .orderBy(desc(max(votesOnchain.timestamp))); + return timestamps.reduce( + (acc, { voterAccountId, lastVoteTimestamp }) => ({ + ...acc, + [voterAccountId]: lastVoteTimestamp, + }), + {}, + ); + } + + async getVotingPowerVariation( + voters: Address[], + comparisonTimestamp: number, + ): Promise> { + const currentPower = this.db.$with("current_power").as( + this.db + .selectDistinctOn([votingPowerHistory.accountId], { + accountId: votingPowerHistory.accountId, + votingPower: votingPowerHistory.votingPower, + }) + .from(votingPowerHistory) + .where(inArray(votingPowerHistory.accountId, voters)) + .orderBy( + votingPowerHistory.accountId, + desc(votingPowerHistory.timestamp), + ), + ); + + const oldPower = this.db.$with("old_power").as( + this.db + .selectDistinctOn([votingPowerHistory.accountId], { + accountId: votingPowerHistory.accountId, + votingPower: votingPowerHistory.votingPower, + }) + .from(votingPowerHistory) + .where( + and( + inArray(votingPowerHistory.accountId, voters), + lte(votingPowerHistory.timestamp, BigInt(comparisonTimestamp)), + ), + ) + .orderBy( + votingPowerHistory.accountId, + desc(votingPowerHistory.timestamp), + ), + ); + + const result = await this.db + .with(currentPower, oldPower) + .select({ + voterAccountId: currentPower.accountId, + currentVotingPower: currentPower.votingPower, + oldVotingPower: oldPower.votingPower, + }) + .from(currentPower) + .leftJoin(oldPower, eq(currentPower.accountId, oldPower.accountId)); + + return result.reduce( + (acc, { voterAccountId, oldVotingPower, currentVotingPower }) => ({ + ...acc, + [voterAccountId]: currentVotingPower - (oldVotingPower || 0n), + }), + {}, + ); + } + + async getVotesByProposalId( + proposalId: string, + skip: number, + limit: number, + orderBy: "timestamp" | "votingPower", + orderDirection: "asc" | "desc", + voterAddresses?: Address[], + support?: string, + fromDate?: number, + toDate?: number, + ): Promise<{ + items: (DBVote & { description: string })[]; + totalCount: number; + }> { + const whereClauses: SQL[] = [ + eq(votesOnchain.proposalId, proposalId), + ]; + + if (support !== undefined) { + whereClauses.push(eq(votesOnchain.support, support)); + } + + if (voterAddresses !== undefined && voterAddresses.length > 0) { + whereClauses.push(inArray(votesOnchain.voterAccountId, voterAddresses)); + } + + if (fromDate !== undefined) { + whereClauses.push(gte(votesOnchain.timestamp, BigInt(fromDate))); + } + + if (toDate !== undefined) { + whereClauses.push(lte(votesOnchain.timestamp, BigInt(toDate))); + } + + const orderByColumn = + orderBy === "votingPower" + ? votesOnchain.votingPower + : votesOnchain.timestamp; + const orderFn = orderDirection === "asc" ? asc : desc; + + const where = and(...whereClauses); + + const [queryItems, totalCount] = await Promise.all([ + this.db.query.votesOnchain.findMany({ + where, + limit, + offset: skip, + orderBy: orderFn(orderByColumn), + with: { + proposal: { + columns: { + description: true, + }, + }, + }, + }), + this.db.$count(votesOnchain, where), + ]); + + return { + items: queryItems.map((item) => ({ + ...item, + description: item.proposal.description, + })), + totalCount, + }; + } +} diff --git a/apps/indexer/src/api/repositories/voting-power/general.ts b/apps/api/src/repositories/voting-power/general.ts similarity index 84% rename from apps/indexer/src/api/repositories/voting-power/general.ts rename to apps/api/src/repositories/voting-power/general.ts index 3e6489069..afcceaaca 100644 --- a/apps/indexer/src/api/repositories/voting-power/general.ts +++ b/apps/api/src/repositories/voting-power/general.ts @@ -12,23 +12,25 @@ import { gte, lte, } from "drizzle-orm"; -import { db } from "ponder:api"; +import { Drizzle } from "@/database"; import { votingPowerHistory, delegation, transfer, accountPower, -} from "ponder:schema"; +} from "@/database"; import { AmountFilter, DBAccountPower, DBVotingPowerVariation, DBHistoricalVotingPowerWithRelations, -} from "@/api/mappers"; -import { PERCENTAGE_NO_BASELINE } from "@/api/mappers/constants"; +} from "@/mappers"; +import { PERCENTAGE_NO_BASELINE } from "@/mappers/constants"; export class VotingPowerRepository { + constructor(private readonly db: Drizzle) {} + async getHistoricalVotingPowerCount( accountId?: Address, minDelta?: string, @@ -36,7 +38,7 @@ export class VotingPowerRepository { fromDate?: number, toDate?: number, ): Promise { - return await db.$count( + return await this.db.$count( votingPowerHistory, and( accountId ? eq(votingPowerHistory.accountId, accountId) : undefined, @@ -65,7 +67,7 @@ export class VotingPowerRepository { fromDate?: number, toDate?: number, ): Promise { - const result = await db + const result = await this.db .select() .from(votingPowerHistory) .leftJoin( @@ -108,15 +110,15 @@ export class VotingPowerRepository { .orderBy( orderDirection === "asc" ? asc( - orderBy === "timestamp" - ? votingPowerHistory.timestamp - : votingPowerHistory.deltaMod, - ) + orderBy === "timestamp" + ? votingPowerHistory.timestamp + : votingPowerHistory.deltaMod, + ) : desc( - orderBy === "timestamp" - ? votingPowerHistory.timestamp - : votingPowerHistory.deltaMod, - ), + orderBy === "timestamp" + ? votingPowerHistory.timestamp + : votingPowerHistory.deltaMod, + ), ) .limit(limit) .offset(skip); @@ -125,12 +127,12 @@ export class VotingPowerRepository { ...row.voting_power_history, delegations: row.transfers && - row.transfers?.logIndex > (row.delegations?.logIndex || 0) + row.transfers?.logIndex > (row.delegations?.logIndex || 0) ? null : row.delegations, transfers: row.delegations && - row.delegations?.logIndex > (row.transfers?.logIndex || 0) + row.delegations?.logIndex > (row.transfers?.logIndex || 0) ? null : row.transfers, })); @@ -146,7 +148,7 @@ export class VotingPowerRepository { ): Promise { const orderDirectionFn = orderDirection === "asc" ? asc : desc; - const latestBeforeFrom = db + const latestBeforeFrom = this.db .select({ accountId: votingPowerHistory.accountId, votingPower: votingPowerHistory.votingPower, @@ -168,7 +170,7 @@ export class VotingPowerRepository { ) .as("latest_before_from"); - const latestBeforeTo = db + const latestBeforeTo = this.db .select({ accountId: votingPowerHistory.accountId, votingPower: votingPowerHistory.votingPower, @@ -190,7 +192,7 @@ export class VotingPowerRepository { ) .as("latest_before_to"); - return await db + return await this.db .select({ accountId: sql
`COALESCE(from_data.account_id, to_data.account_id)`, previousVotingPower: sql`COALESCE(from_data.voting_power, 0)`, @@ -224,7 +226,7 @@ export class VotingPowerRepository { startTimestamp: number | undefined, endTimestamp: number | undefined, ): Promise { - const history = db + const history = this.db .select({ accountId: votingPowerHistory.accountId, delta: votingPowerHistory.delta, @@ -244,7 +246,7 @@ export class VotingPowerRepository { ) .as("history"); - const [delta] = await db + const [delta] = await this.db .select({ accountId: history.accountId, absoluteChange: sql`SUM(${history.delta})`.as("agg_delta"), @@ -252,7 +254,7 @@ export class VotingPowerRepository { .from(history) .groupBy(history.accountId); - const [currentAccountPower] = await db + const [currentAccountPower] = await this.db .select({ currentVotingPower: accountPower.votingPower }) .from(accountPower) .where(eq(accountPower.accountId, accountId)); @@ -264,8 +266,8 @@ export class VotingPowerRepository { const oldVotingPower = currentVotingPower - numericAbsoluteChange; const percentageChange = oldVotingPower ? ( - Number((numericAbsoluteChange * 10000n) / oldVotingPower) / 100 - ).toFixed(2) + Number((numericAbsoluteChange * 10000n) / oldVotingPower) / 100 + ).toFixed(2) : "0"; return { @@ -290,7 +292,7 @@ export class VotingPowerRepository { ? accountPower.votingPower : accountPower.delegationsCount; - const items = await db + const items = await this.db .select() .from(accountPower) .where(this.filterToSql(addresses, amountFilter)) @@ -298,7 +300,7 @@ export class VotingPowerRepository { .offset(skip) .limit(limit); - const [totalCount] = await db + const [totalCount] = await this.db .select({ count: sql`COUNT(*)`.as("count"), }) @@ -314,28 +316,30 @@ export class VotingPowerRepository { async getVotingPowersByAccountId( accountId: Address, ): Promise { - const [result] = await db + const [result] = await this.db .select() .from(accountPower) .where(eq(accountPower.accountId, accountId)); - return result ? { - accountId: result.accountId, - votingPower: result.votingPower, - delegationsCount: result.delegationsCount, - votesCount: result.votesCount, - proposalsCount: result.proposalsCount, - daoId: result.daoId, - lastVoteTimestamp: result.lastVoteTimestamp, - } : { - accountId: accountId, - votingPower: 0n, - delegationsCount: 0, - votesCount: 0, - proposalsCount: 0, - daoId: "", - lastVoteTimestamp: 0n, - }; + return result + ? { + accountId: result.accountId, + votingPower: result.votingPower, + delegationsCount: result.delegationsCount, + votesCount: result.votesCount, + proposalsCount: result.proposalsCount, + daoId: result.daoId, + lastVoteTimestamp: result.lastVoteTimestamp, + } + : { + accountId: accountId, + votingPower: 0n, + delegationsCount: 0, + votesCount: 0, + proposalsCount: 0, + daoId: "", + lastVoteTimestamp: 0n, + }; } private filterToSql( diff --git a/apps/indexer/src/api/repositories/voting-power/index.ts b/apps/api/src/repositories/voting-power/index.ts similarity index 100% rename from apps/indexer/src/api/repositories/voting-power/index.ts rename to apps/api/src/repositories/voting-power/index.ts diff --git a/apps/indexer/src/api/repositories/voting-power/nouns.ts b/apps/api/src/repositories/voting-power/nouns.ts similarity index 92% rename from apps/indexer/src/api/repositories/voting-power/nouns.ts rename to apps/api/src/repositories/voting-power/nouns.ts index da6a3e6b0..782087377 100644 --- a/apps/indexer/src/api/repositories/voting-power/nouns.ts +++ b/apps/api/src/repositories/voting-power/nouns.ts @@ -1,11 +1,13 @@ import { Address } from "viem"; import { gte, and, lte, desc, eq, asc, sql } from "drizzle-orm"; -import { db } from "ponder:api"; -import { votingPowerHistory, delegation, transfer } from "ponder:schema"; +import { Drizzle } from "@/database"; +import { votingPowerHistory, delegation, transfer } from "@/database"; -import { DBHistoricalVotingPowerWithRelations } from "@/api/mappers"; +import { DBHistoricalVotingPowerWithRelations } from "@/mappers"; export class NounsVotingPowerRepository { + constructor(private readonly db: Drizzle) {} + async getHistoricalVotingPowerCount( accountId?: Address, minDelta?: string, @@ -13,7 +15,7 @@ export class NounsVotingPowerRepository { fromDate?: number, toDate?: number, ): Promise { - return await db.$count( + return await this.db.$count( votingPowerHistory, and( accountId ? eq(votingPowerHistory.accountId, accountId) : undefined, @@ -42,7 +44,7 @@ export class NounsVotingPowerRepository { fromDate?: number, toDate?: number, ): Promise { - const result = await db + const result = await this.db .select() .from(votingPowerHistory) .where( diff --git a/apps/indexer/src/api/services/account-balance/historical.ts b/apps/api/src/services/account-balance/historical.ts similarity index 95% rename from apps/indexer/src/api/services/account-balance/historical.ts rename to apps/api/src/services/account-balance/historical.ts index 6cad5728e..69e0d0a6e 100644 --- a/apps/indexer/src/api/services/account-balance/historical.ts +++ b/apps/api/src/services/account-balance/historical.ts @@ -1,6 +1,6 @@ import { Address } from "viem"; -import { DBHistoricalBalanceWithRelations } from "@/api/mappers"; +import { DBHistoricalBalanceWithRelations } from "@/mappers"; interface Repository { getHistoricalBalances( diff --git a/apps/indexer/src/api/services/account-balance/index.ts b/apps/api/src/services/account-balance/index.ts similarity index 100% rename from apps/indexer/src/api/services/account-balance/index.ts rename to apps/api/src/services/account-balance/index.ts diff --git a/apps/indexer/src/api/services/account-balance/listing.ts b/apps/api/src/services/account-balance/listing.ts similarity index 95% rename from apps/indexer/src/api/services/account-balance/listing.ts rename to apps/api/src/services/account-balance/listing.ts index 5a0f6c125..f8a1abd8a 100644 --- a/apps/indexer/src/api/services/account-balance/listing.ts +++ b/apps/api/src/services/account-balance/listing.ts @@ -1,4 +1,4 @@ -import { AmountFilter, DBAccountBalance } from "@/api/mappers"; +import { AmountFilter, DBAccountBalance } from "@/mappers"; import { TreasuryAddresses } from "@/lib/constants"; import { DaoIdEnum } from "@/lib/enums"; import { Address } from "viem"; diff --git a/apps/indexer/src/api/services/account-balance/variations.ts b/apps/api/src/services/account-balance/variations.ts similarity index 99% rename from apps/indexer/src/api/services/account-balance/variations.ts rename to apps/api/src/services/account-balance/variations.ts index 09bfbde74..d2b510134 100644 --- a/apps/indexer/src/api/services/account-balance/variations.ts +++ b/apps/api/src/services/account-balance/variations.ts @@ -2,7 +2,7 @@ import { DBAccountBalanceVariation, AccountInteractions, Filter, -} from "@/api/mappers"; +} from "@/mappers"; import { Address } from "viem"; interface AccountBalanceRepository { diff --git a/apps/indexer/src/api/services/coingecko/index.ts b/apps/api/src/services/coingecko/index.ts similarity index 93% rename from apps/indexer/src/api/services/coingecko/index.ts rename to apps/api/src/services/coingecko/index.ts index 1eaa22ca6..d591a1434 100644 --- a/apps/indexer/src/api/services/coingecko/index.ts +++ b/apps/api/src/services/coingecko/index.ts @@ -8,10 +8,9 @@ import { CoingeckoIdToAssetPlatformId, CoingeckoTokenIdEnum, } from "./types"; -import { DAYS_IN_YEAR } from "@/lib/constants"; import { DaoIdEnum } from "@/lib/enums"; -import { TokenHistoricalPriceResponse } from "@/api/mappers"; -import { PriceProvider } from "@/api/services/treasury/types"; +import { TokenHistoricalPriceResponse } from "@/mappers"; +import { PriceProvider } from "@/services/treasury/types"; import { truncateTimestampToMidnight } from "@/lib/date-helpers"; const createCoingeckoTokenPriceDataSchema = ( @@ -53,7 +52,7 @@ export class CoingeckoService implements PriceProvider { } async getHistoricalTokenData( - days: number = DAYS_IN_YEAR, + days: number = 365, ): Promise { const tokenId = CoingeckoTokenIdEnum[this.daoId]; diff --git a/apps/indexer/src/api/services/coingecko/types.ts b/apps/api/src/services/coingecko/types.ts similarity index 100% rename from apps/indexer/src/api/services/coingecko/types.ts rename to apps/api/src/services/coingecko/types.ts diff --git a/apps/indexer/src/api/services/dao/index.ts b/apps/api/src/services/dao/index.ts similarity index 88% rename from apps/indexer/src/api/services/dao/index.ts rename to apps/api/src/services/dao/index.ts index 6a5d92101..b591aee0e 100644 --- a/apps/indexer/src/api/services/dao/index.ts +++ b/apps/api/src/services/dao/index.ts @@ -1,6 +1,6 @@ -import { DAOClient } from "@/interfaces/client"; -import { DaoDataCache } from "@/api/cache/dao-cache.interface"; -import { DaoResponse } from "@/api/mappers"; +import { DAOClient } from "@/clients"; +import { DaoDataCache } from "@/cache/dao-cache.interface"; +import { DaoResponse } from "@/mappers"; export class DaoService { constructor( diff --git a/apps/indexer/src/api/services/delegation-percentage/delegation-percentage.service.test.ts b/apps/api/src/services/delegation-percentage/delegation-percentage.service.test.ts similarity index 97% rename from apps/indexer/src/api/services/delegation-percentage/delegation-percentage.service.test.ts rename to apps/api/src/services/delegation-percentage/delegation-percentage.service.test.ts index 0fe608a84..cecf85ada 100644 --- a/apps/indexer/src/api/services/delegation-percentage/delegation-percentage.service.test.ts +++ b/apps/api/src/services/delegation-percentage/delegation-percentage.service.test.ts @@ -1,25 +1,7 @@ import { DelegationPercentageService } from "./delegation-percentage"; -import { DaoMetricsDayBucketRepository } from "@/api/repositories/"; +import { DaoMetricsDayBucketRepository } from "@/repositories/"; import { MetricTypesEnum } from "@/lib/constants"; - -/** - * Type representing a DAO metric row from the database - * Used for type-safe mocking in tests - */ -export type DaoMetricRow = { - date: bigint; - daoId: string; - tokenId: string; - metricType: string; - open: bigint; - close: bigint; - low: bigint; - high: bigint; - average: bigint; - volume: bigint; - count: number; - lastUpdate: bigint; -}; +import { DBTokenMetric } from "@/mappers/delegation-percentage"; /** * Mock Factory Pattern for type-safe test data @@ -27,8 +9,8 @@ export type DaoMetricRow = { * Only requires specifying fields relevant to each test case */ const createMockRow = ( - overwrites: Partial = {}, -): DaoMetricRow => ({ + overwrites: Partial = {}, +): DBTokenMetric => ({ date: 0n, daoId: "uniswap", tokenId: "uni", @@ -46,13 +28,23 @@ const createMockRow = ( describe("DelegationPercentageService", () => { let service: DelegationPercentageService; - let mockRepository: jest.Mocked; + let mockRepository: jest.Mocked< + Pick< + DaoMetricsDayBucketRepository, + "getMetricsByDateRange" | "getLastMetricBeforeDate" + > + >; beforeEach(() => { mockRepository = { getMetricsByDateRange: jest.fn(), getLastMetricBeforeDate: jest.fn(), - } as jest.Mocked; + } as jest.Mocked< + Pick< + DaoMetricsDayBucketRepository, + "getMetricsByDateRange" | "getLastMetricBeforeDate" + > + >; service = new DelegationPercentageService(mockRepository); }); diff --git a/apps/indexer/src/api/services/delegation-percentage/delegation-percentage.test.ts b/apps/api/src/services/delegation-percentage/delegation-percentage.test.ts similarity index 97% rename from apps/indexer/src/api/services/delegation-percentage/delegation-percentage.test.ts rename to apps/api/src/services/delegation-percentage/delegation-percentage.test.ts index 0fe608a84..cecf85ada 100644 --- a/apps/indexer/src/api/services/delegation-percentage/delegation-percentage.test.ts +++ b/apps/api/src/services/delegation-percentage/delegation-percentage.test.ts @@ -1,25 +1,7 @@ import { DelegationPercentageService } from "./delegation-percentage"; -import { DaoMetricsDayBucketRepository } from "@/api/repositories/"; +import { DaoMetricsDayBucketRepository } from "@/repositories/"; import { MetricTypesEnum } from "@/lib/constants"; - -/** - * Type representing a DAO metric row from the database - * Used for type-safe mocking in tests - */ -export type DaoMetricRow = { - date: bigint; - daoId: string; - tokenId: string; - metricType: string; - open: bigint; - close: bigint; - low: bigint; - high: bigint; - average: bigint; - volume: bigint; - count: number; - lastUpdate: bigint; -}; +import { DBTokenMetric } from "@/mappers/delegation-percentage"; /** * Mock Factory Pattern for type-safe test data @@ -27,8 +9,8 @@ export type DaoMetricRow = { * Only requires specifying fields relevant to each test case */ const createMockRow = ( - overwrites: Partial = {}, -): DaoMetricRow => ({ + overwrites: Partial = {}, +): DBTokenMetric => ({ date: 0n, daoId: "uniswap", tokenId: "uni", @@ -46,13 +28,23 @@ const createMockRow = ( describe("DelegationPercentageService", () => { let service: DelegationPercentageService; - let mockRepository: jest.Mocked; + let mockRepository: jest.Mocked< + Pick< + DaoMetricsDayBucketRepository, + "getMetricsByDateRange" | "getLastMetricBeforeDate" + > + >; beforeEach(() => { mockRepository = { getMetricsByDateRange: jest.fn(), getLastMetricBeforeDate: jest.fn(), - } as jest.Mocked; + } as jest.Mocked< + Pick< + DaoMetricsDayBucketRepository, + "getMetricsByDateRange" | "getLastMetricBeforeDate" + > + >; service = new DelegationPercentageService(mockRepository); }); diff --git a/apps/indexer/src/api/services/delegation-percentage/delegation-percentage.ts b/apps/api/src/services/delegation-percentage/delegation-percentage.ts similarity index 93% rename from apps/indexer/src/api/services/delegation-percentage/delegation-percentage.ts rename to apps/api/src/services/delegation-percentage/delegation-percentage.ts index eade26b2b..ea0f2d0c4 100644 --- a/apps/indexer/src/api/services/delegation-percentage/delegation-percentage.ts +++ b/apps/api/src/services/delegation-percentage/delegation-percentage.ts @@ -30,12 +30,12 @@ import { MetricTypesEnum } from "@/lib/constants"; import { forwardFill, generateOrderedTimeline } from "@/lib/time-series"; import { applyCursorPagination } from "@/lib/query-helpers"; import { getEffectiveStartDate } from "@/lib/date-helpers"; -import { DaoMetricsDayBucketRepository } from "@/api/repositories/"; import { + DBTokenMetric, DelegationPercentageItem, DelegationPercentageQuery, normalizeTimestamp, -} from "@/api/mappers/"; +} from "@/mappers/"; /** * Service result type @@ -56,8 +56,23 @@ interface DateData { tokenId?: string; } +interface DelegationPercentageRepository { + getMetricsByDateRange(filters: { + metricTypes: string[]; + startDate?: string; + endDate?: string; + orderDirection: "asc" | "desc"; + limit: number; + }): Promise; + + getLastMetricBeforeDate( + metricType: string, + beforeDate: string, + ): Promise; +} + export class DelegationPercentageService { - constructor(private readonly repository: DaoMetricsDayBucketRepository) {} + constructor(private readonly repository: DelegationPercentageRepository) {} /** * Main method to get delegation percentage data with forward-fill and pagination @@ -190,11 +205,7 @@ export class DelegationPercentageService { * Organizes database rows into a map by date * Separates DELEGATED_SUPPLY and TOTAL_SUPPLY metrics */ - private organizeDateMap( - rows: Awaited< - ReturnType - >, - ): Map { + private organizeDateMap(rows: DBTokenMetric[]): Map { const dateMap = new Map(); rows.forEach((row) => { diff --git a/apps/indexer/src/api/services/delegation-percentage/index.ts b/apps/api/src/services/delegation-percentage/index.ts similarity index 100% rename from apps/indexer/src/api/services/delegation-percentage/index.ts rename to apps/api/src/services/delegation-percentage/index.ts diff --git a/apps/indexer/src/api/services/delegations/current.ts b/apps/api/src/services/delegations/current.ts similarity index 88% rename from apps/indexer/src/api/services/delegations/current.ts rename to apps/api/src/services/delegations/current.ts index 8bbacadc0..f387531cd 100644 --- a/apps/indexer/src/api/services/delegations/current.ts +++ b/apps/api/src/services/delegations/current.ts @@ -1,4 +1,4 @@ -import { DBDelegation } from "@/api/mappers"; +import { DBDelegation } from "@/mappers"; import { Address } from "viem"; interface Repository { diff --git a/apps/indexer/src/api/services/delegations/historical.ts b/apps/api/src/services/delegations/historical.ts similarity index 95% rename from apps/indexer/src/api/services/delegations/historical.ts rename to apps/api/src/services/delegations/historical.ts index dcdae728b..fa86e3a05 100644 --- a/apps/indexer/src/api/services/delegations/historical.ts +++ b/apps/api/src/services/delegations/historical.ts @@ -1,4 +1,4 @@ -import { DBDelegation } from "@/api/mappers"; +import { DBDelegation } from "@/mappers"; import { Address } from "viem"; interface Repository { diff --git a/apps/indexer/src/api/services/delegations/index.ts b/apps/api/src/services/delegations/index.ts similarity index 100% rename from apps/indexer/src/api/services/delegations/index.ts rename to apps/api/src/services/delegations/index.ts diff --git a/apps/indexer/src/api/services/dune/index.ts b/apps/api/src/services/dune/index.ts similarity index 100% rename from apps/indexer/src/api/services/dune/index.ts rename to apps/api/src/services/dune/index.ts diff --git a/apps/indexer/src/api/services/dune/service.ts b/apps/api/src/services/dune/service.ts similarity index 100% rename from apps/indexer/src/api/services/dune/service.ts rename to apps/api/src/services/dune/service.ts diff --git a/apps/indexer/src/api/services/index.ts b/apps/api/src/services/index.ts similarity index 95% rename from apps/indexer/src/api/services/index.ts rename to apps/api/src/services/index.ts index 591f473fb..4be736f8a 100644 --- a/apps/indexer/src/api/services/index.ts +++ b/apps/api/src/services/index.ts @@ -14,3 +14,4 @@ export * from "./dao"; export * from "./transfers"; export * from "./delegations"; export * from "./treasury"; +export * from "./votes"; diff --git a/apps/indexer/src/api/services/last-update/index.ts b/apps/api/src/services/last-update/index.ts similarity index 78% rename from apps/indexer/src/api/services/last-update/index.ts rename to apps/api/src/services/last-update/index.ts index 02a894033..6316b069f 100644 --- a/apps/indexer/src/api/services/last-update/index.ts +++ b/apps/api/src/services/last-update/index.ts @@ -1,5 +1,5 @@ -import { ChartType } from "@/api/mappers/"; -import { LastUpdateRepository } from "@/api/repositories/"; +import { ChartType } from "@/mappers/"; +import { LastUpdateRepository } from "@/repositories/"; export class LastUpdateService { constructor(private readonly repository: LastUpdateRepository) {} diff --git a/apps/indexer/src/api/services/nft-price/index.ts b/apps/api/src/services/nft-price/index.ts similarity index 96% rename from apps/indexer/src/api/services/nft-price/index.ts rename to apps/api/src/services/nft-price/index.ts index e73c13b94..1543021dd 100644 --- a/apps/indexer/src/api/services/nft-price/index.ts +++ b/apps/api/src/services/nft-price/index.ts @@ -1,8 +1,8 @@ import { formatEther } from "viem"; import axios, { AxiosInstance } from "axios"; -import { TokenHistoricalPriceResponse } from "@/api/mappers"; -import { PriceProvider } from "@/api/services/treasury/types"; +import { TokenHistoricalPriceResponse } from "@/mappers"; +import { PriceProvider } from "@/services/treasury/types"; import { forwardFill, createDailyTimeline } from "@/lib/time-series"; import { truncateTimestampToMidnight, diff --git a/apps/indexer/src/api/services/proposals-activity/index.ts b/apps/api/src/services/proposals-activity/index.ts similarity index 90% rename from apps/indexer/src/api/services/proposals-activity/index.ts rename to apps/api/src/services/proposals-activity/index.ts index 4de6b0a7a..d39ef8792 100644 --- a/apps/indexer/src/api/services/proposals-activity/index.ts +++ b/apps/api/src/services/proposals-activity/index.ts @@ -1,15 +1,15 @@ import { Address } from "viem"; import { DaoIdEnum } from "@/lib/enums"; import { - ProposalsActivityRepository, DbProposal, DbVote, OrderByField, OrderDirection, VoteFilter, -} from "@/api/repositories/"; -import { DAOClient } from "@/interfaces/client"; -import { DBProposal } from "@/api/mappers"; + DbProposalWithVote, +} from "@/repositories/"; +import { DAOClient } from "@/clients"; +import { DBProposal } from "@/mappers"; const FINAL_PROPOSAL_STATUSES = ["EXECUTED", "DEFEATED", "CANCELED", "EXPIRED"]; @@ -62,6 +62,36 @@ export interface DelegateProposalActivity { proposals: ProposalWithUserVote[]; } +export interface ProposalsActivityRepository { + getFirstVoteTimestamp(address: Address): Promise; + + getProposals( + daoId: DaoIdEnum, + activityStart: number, + votingPeriodSeconds: number, + ): Promise; + + getUserVotes( + address: Address, + daoId: DaoIdEnum, + proposalIds: string[], + ): Promise; + + getProposalsWithVotesAndPagination( + address: Address, + activityStart: number, + votingPeriodSeconds: number, + skip: number, + limit: number, + orderBy: OrderByField, + orderDirection: OrderDirection, + userVoteFilter?: VoteFilter, + ): Promise<{ + proposals: DbProposalWithVote[]; + totalCount: number; + }>; +} + export class ProposalsActivityService { constructor( private readonly repository: ProposalsActivityRepository, diff --git a/apps/indexer/src/api/services/proposals/index.ts b/apps/api/src/services/proposals/index.ts similarity index 52% rename from apps/indexer/src/api/services/proposals/index.ts rename to apps/api/src/services/proposals/index.ts index b9569f4bf..5d844ac0b 100644 --- a/apps/indexer/src/api/services/proposals/index.ts +++ b/apps/api/src/services/proposals/index.ts @@ -1,14 +1,6 @@ -import { - DBProposal, - ProposalsRequest, - VotersResponse, - VotesResponse, - DBVote, - VotesMapper, -} from "@/api/mappers"; -import { DAOClient } from "@/interfaces/client"; +import { DAOClient } from "@/clients"; +import { DBProposal, ProposalsRequest } from "@/mappers"; import { ProposalStatus } from "@/lib/constants"; -import { DaysEnum } from "@/lib/enums"; import { Address } from "viem"; interface ProposalsRepository { @@ -23,33 +15,6 @@ interface ProposalsRepository { ): Promise; getProposalsCount(): Promise; getProposalById(proposalId: string): Promise; - getProposalNonVoters( - proposalId: string, - skip: number, - limit: number, - orderDirection: "asc" | "desc", - addresses?: Address[], - ): Promise<{ voter: Address; votingPower: bigint }[]>; - getProposalNonVotersCount(proposalId: string): Promise; - getLastVotersTimestamp(voters: Address[]): Promise>; - getVotingPowerVariation( - voters: Address[], - comparisonTimestamp: number, - ): Promise>; - getVotes( - proposalId: string, - skip: number, - limit: number, - orderBy: "timestamp" | "votingPower", - orderDirection: "asc" | "desc", - voterAddressIn?: Address[], - support?: string, - ): Promise; - getVotesCount( - proposalId: string, - voterAddressIn?: Address[], - support?: string, - ): Promise; } export class ProposalsService { @@ -148,78 +113,4 @@ export class ProposalsService { return { ...proposal, status }; } - - /** - * Returns the delegates with active delegations that didn't vote on a given proposal - */ - async getProposalNonVoters( - proposalId: string, - skip: number = 0, - limit: number, - orderDirection: "asc" | "desc", - addresses?: Address[], - ): Promise { - const nonVoters = await this.proposalsRepo.getProposalNonVoters( - proposalId, - skip, - limit, - orderDirection, - addresses, - ); - - const _addresses = addresses ? addresses : nonVoters.map((v) => v.voter); - - const comparisonTimestamp = Math.floor(Date.now() / 1000 - DaysEnum["30d"]); - - const [lastVotersTimestamp, votingPowerVariation] = await Promise.all([ - this.proposalsRepo.getLastVotersTimestamp(_addresses), - this.proposalsRepo.getVotingPowerVariation( - _addresses, - comparisonTimestamp, - ), - ]); - - return { - totalCount: addresses - ? _addresses.length - : await this.proposalsRepo.getProposalNonVotersCount(proposalId), - items: nonVoters.map((v) => ({ - voter: v.voter, - votingPower: v.votingPower.toString(), - lastVoteTimestamp: Number(lastVotersTimestamp[v.voter] || 0), - votingPowerVariation: votingPowerVariation[v.voter]?.toString() || "0", - })), - }; - } - - /** - * Returns the list of votes for a given proposal - */ - async getVotes( - proposalId: string, - skip: number = 0, - limit: number = 10, - orderBy: "timestamp" | "votingPower" = "timestamp", - orderDirection: "asc" | "desc" = "desc", - voterAddressIn?: Address[], - support?: string, - ): Promise { - const [votes, totalCount] = await Promise.all([ - this.proposalsRepo.getVotes( - proposalId, - skip, - limit, - orderBy, - orderDirection, - voterAddressIn, - support, - ), - this.proposalsRepo.getVotesCount(proposalId, voterAddressIn, support), - ]); - - return { - totalCount, - items: votes.map(VotesMapper.toApi), - }; - } } diff --git a/apps/indexer/src/api/services/token-metrics/index.ts b/apps/api/src/services/token-metrics/index.ts similarity index 97% rename from apps/indexer/src/api/services/token-metrics/index.ts rename to apps/api/src/services/token-metrics/index.ts index b3332fe2e..98de1cb9b 100644 --- a/apps/indexer/src/api/services/token-metrics/index.ts +++ b/apps/api/src/services/token-metrics/index.ts @@ -28,8 +28,8 @@ import { normalizeMapTimestamps, getEffectiveStartDate, } from "@/lib/date-helpers"; -import { DaoMetricsDayBucketRepository } from "@/api/repositories/daoMetricsDayBucket"; -import { TokenMetricItem } from "@/api/mappers/token-metrics"; +import { DaoMetricsDayBucketRepository } from "@/repositories/daoMetricsDayBucket"; +import { TokenMetricItem } from "@/mappers/token-metrics"; import { MetricTypesEnum } from "@/lib/constants"; interface MetricData { diff --git a/apps/indexer/src/api/services/token/index.ts b/apps/api/src/services/token/index.ts similarity index 100% rename from apps/indexer/src/api/services/token/index.ts rename to apps/api/src/services/token/index.ts diff --git a/apps/indexer/src/api/services/token/token.ts b/apps/api/src/services/token/token.ts similarity index 90% rename from apps/indexer/src/api/services/token/token.ts rename to apps/api/src/services/token/token.ts index 4eb008b5b..eba08bb44 100644 --- a/apps/indexer/src/api/services/token/token.ts +++ b/apps/api/src/services/token/token.ts @@ -1,4 +1,4 @@ -import { DBToken } from "@/api/mappers"; +import { DBToken } from "@/mappers"; import { DaoIdEnum } from "@/lib/enums"; interface TokenRepository { diff --git a/apps/indexer/src/api/services/transactions/index.ts b/apps/api/src/services/transactions/index.ts similarity index 97% rename from apps/indexer/src/api/services/transactions/index.ts rename to apps/api/src/services/transactions/index.ts index ab7ddf300..151af5ddd 100644 --- a/apps/indexer/src/api/services/transactions/index.ts +++ b/apps/api/src/services/transactions/index.ts @@ -3,7 +3,7 @@ import { TransactionsResponse, TransactionMapper, DBTransaction, -} from "@/api/mappers/"; +} from "@/mappers/"; interface TransactionsRepository { getFilteredAggregateTransactions( diff --git a/apps/indexer/src/api/services/transfers/index.ts b/apps/api/src/services/transfers/index.ts similarity index 96% rename from apps/indexer/src/api/services/transfers/index.ts rename to apps/api/src/services/transfers/index.ts index 865388bfa..95f30cf1e 100644 --- a/apps/indexer/src/api/services/transfers/index.ts +++ b/apps/api/src/services/transfers/index.ts @@ -3,7 +3,7 @@ import { DBTransfer, TransfersResponse, TransferMapper, -} from "@/api/mappers"; +} from "@/mappers"; interface TransfersRepository { getTransfersCount(req: TransfersRequest): Promise; diff --git a/apps/indexer/src/api/services/treasury/index.ts b/apps/api/src/services/treasury/index.ts similarity index 100% rename from apps/indexer/src/api/services/treasury/index.ts rename to apps/api/src/services/treasury/index.ts diff --git a/apps/indexer/src/api/services/treasury/providers/compound-provider.ts b/apps/api/src/services/treasury/providers/compound-provider.ts similarity index 100% rename from apps/indexer/src/api/services/treasury/providers/compound-provider.ts rename to apps/api/src/services/treasury/providers/compound-provider.ts diff --git a/apps/indexer/src/api/services/treasury/providers/defillama-provider.ts b/apps/api/src/services/treasury/providers/defillama-provider.ts similarity index 100% rename from apps/indexer/src/api/services/treasury/providers/defillama-provider.ts rename to apps/api/src/services/treasury/providers/defillama-provider.ts diff --git a/apps/indexer/src/api/services/treasury/providers/dune-provider.ts b/apps/api/src/services/treasury/providers/dune-provider.ts similarity index 100% rename from apps/indexer/src/api/services/treasury/providers/dune-provider.ts rename to apps/api/src/services/treasury/providers/dune-provider.ts diff --git a/apps/indexer/src/api/services/treasury/providers/index.ts b/apps/api/src/services/treasury/providers/index.ts similarity index 100% rename from apps/indexer/src/api/services/treasury/providers/index.ts rename to apps/api/src/services/treasury/providers/index.ts diff --git a/apps/indexer/src/api/services/treasury/providers/provider-cache.ts b/apps/api/src/services/treasury/providers/provider-cache.ts similarity index 100% rename from apps/indexer/src/api/services/treasury/providers/provider-cache.ts rename to apps/api/src/services/treasury/providers/provider-cache.ts diff --git a/apps/indexer/src/api/services/treasury/providers/treasury-provider.interface.ts b/apps/api/src/services/treasury/providers/treasury-provider.interface.ts similarity index 100% rename from apps/indexer/src/api/services/treasury/providers/treasury-provider.interface.ts rename to apps/api/src/services/treasury/providers/treasury-provider.interface.ts diff --git a/apps/indexer/src/api/services/treasury/treasury-provider-factory.ts b/apps/api/src/services/treasury/treasury-provider-factory.ts similarity index 97% rename from apps/indexer/src/api/services/treasury/treasury-provider-factory.ts rename to apps/api/src/services/treasury/treasury-provider-factory.ts index 5007c33e4..edf815156 100644 --- a/apps/indexer/src/api/services/treasury/treasury-provider-factory.ts +++ b/apps/api/src/services/treasury/treasury-provider-factory.ts @@ -2,7 +2,7 @@ import axios from "axios"; import { DefiLlamaProvider } from "./providers/defillama-provider"; import { DuneProvider } from "./providers/dune-provider"; import { TreasuryService } from "./treasury.service"; -import { TreasuryRepository } from "@/api/repositories/treasury"; +import { TreasuryRepository } from "@/repositories/treasury"; import { PriceProvider } from "./types"; import { CompoundProvider, TreasuryProvider } from "./providers"; diff --git a/apps/indexer/src/api/services/treasury/treasury.service.ts b/apps/api/src/services/treasury/treasury.service.ts similarity index 98% rename from apps/indexer/src/api/services/treasury/treasury.service.ts rename to apps/api/src/services/treasury/treasury.service.ts index 084d6a2f7..7630bc6ab 100644 --- a/apps/indexer/src/api/services/treasury/treasury.service.ts +++ b/apps/api/src/services/treasury/treasury.service.ts @@ -1,7 +1,7 @@ import { formatUnits } from "viem"; import { TreasuryProvider } from "./providers"; import { PriceProvider } from "./types"; -import { TreasuryResponse } from "@/api/mappers/treasury"; +import { TreasuryResponse } from "@/mappers/treasury"; import { TreasuryRepository } from "../../repositories/treasury"; import { forwardFill, createDailyTimeline } from "@/lib/time-series"; import { diff --git a/apps/indexer/src/api/services/treasury/types.ts b/apps/api/src/services/treasury/types.ts similarity index 100% rename from apps/indexer/src/api/services/treasury/types.ts rename to apps/api/src/services/treasury/types.ts diff --git a/apps/api/src/services/votes/index.ts b/apps/api/src/services/votes/index.ts new file mode 100644 index 000000000..8775f8b5c --- /dev/null +++ b/apps/api/src/services/votes/index.ts @@ -0,0 +1,152 @@ +import { + VotesRequest, + DBVote, + VotesResponse, + VotesResponseSchema, + VotersResponse, +} from "@/mappers"; +import { DaysEnum } from "@/lib/enums"; +import { Address } from "viem"; + +interface VotesRepository { + getProposalNonVoters( + proposalId: string, + skip: number, + limit: number, + orderDirection: "asc" | "desc", + addresses?: Address[], + ): Promise<{ voter: Address; votingPower: bigint }[]>; + getProposalNonVotersCount(proposalId: string): Promise; + getVotes(req: VotesRequest): Promise<{ + items: (DBVote & { description: string })[]; + totalCount: number; + }>; + getVotesByProposalId( + proposalId: string, + skip: number, + limit: number, + orderBy: "timestamp" | "votingPower", + orderDirection: "asc" | "desc", + voterAddressIn?: Address[], + support?: string, + fromDate?: number, + toDate?: number, + ): Promise<{ + items: (DBVote & { description: string })[]; + totalCount: number; + }>; + + getLastVotersTimestamp(voters: Address[]): Promise>; + getVotingPowerVariation( + voters: Address[], + comparisonTimestamp: number, + ): Promise>; +} + +export class VotesService { + constructor(private votesRepository: VotesRepository) {} + async getVotes(params: VotesRequest): Promise { + const { items, totalCount } = await this.votesRepository.getVotes(params); + return VotesResponseSchema.parse({ + items: items.map((item) => ({ + voterAddress: item.voterAccountId, + transactionHash: item.txHash, + proposalId: item.proposalId, + support: Number(item.support), + votingPower: item.votingPower.toString(), + reason: item.reason ? item.reason : undefined, + timestamp: Number(item.timestamp), + proposalTitle: + item.description.split("\n")[0]?.replace(/^#+\s*/, "") || + "Untitled Proposal", + })), + totalCount, + }); + } + + /** + * Returns the delegates with active delegations that didn't vote on a given proposal + */ + async getProposalNonVoters( + proposalId: string, + skip: number = 0, + limit: number, + orderDirection: "asc" | "desc", + addresses?: Address[], + ): Promise { + const nonVoters = await this.votesRepository.getProposalNonVoters( + proposalId, + skip, + limit, + orderDirection, + addresses, + ); + + const _addresses = addresses ? addresses : nonVoters.map((v) => v.voter); + + const comparisonTimestamp = Math.floor(Date.now() / 1000 - DaysEnum["30d"]); + + const [lastVotersTimestamp, votingPowerVariation] = await Promise.all([ + this.votesRepository.getLastVotersTimestamp(_addresses), + this.votesRepository.getVotingPowerVariation( + _addresses, + comparisonTimestamp, + ), + ]); + + return { + totalCount: addresses + ? _addresses.length + : await this.votesRepository.getProposalNonVotersCount(proposalId), + items: nonVoters.map((v) => ({ + voter: v.voter, + votingPower: v.votingPower.toString(), + lastVoteTimestamp: Number(lastVotersTimestamp[v.voter] || 0), + votingPowerVariation: votingPowerVariation[v.voter]?.toString() || "0", + })), + }; + } + + /** + * Returns the list of votes for a given proposal + */ + async getVotesByProposal( + proposalId: string, + skip: number = 0, + limit: number = 10, + orderBy: "timestamp" | "votingPower" = "timestamp", + orderDirection: "asc" | "desc" = "desc", + voterAddressIn?: Address[], + support?: string, + fromDate?: number, + toDate?: number, + ): Promise { + const response = await this.votesRepository.getVotesByProposalId( + proposalId, + skip, + limit, + orderBy, + orderDirection, + voterAddressIn, + support, + fromDate, + toDate, + ); + + return VotesResponseSchema.parse({ + items: response.items.map((item) => ({ + voterAddress: item.voterAccountId, + transactionHash: item.txHash, + proposalId: item.proposalId, + support: Number(item.support), + votingPower: item.votingPower.toString(), + reason: item.reason ? item.reason : undefined, + timestamp: Number(item.timestamp), + proposalTitle: + item.description.split("\n")[0]?.replace(/^#+\s*/, "") || + "Untitled Proposal", + })), + totalCount: response.totalCount, + }); + } +} diff --git a/apps/indexer/src/api/services/voting-power/index.ts b/apps/api/src/services/voting-power/index.ts similarity index 99% rename from apps/indexer/src/api/services/voting-power/index.ts rename to apps/api/src/services/voting-power/index.ts index 4090dcfa0..7beb8caf4 100644 --- a/apps/indexer/src/api/services/voting-power/index.ts +++ b/apps/api/src/services/voting-power/index.ts @@ -5,7 +5,7 @@ import { DBVotingPowerVariation, AmountFilter, DBAccountPower, -} from "@/api/mappers"; +} from "@/mappers"; interface HistoricalVotingPowerRepository { getHistoricalVotingPowers( diff --git a/apps/indexer/src/api/services/voting-power/voting-power.ts b/apps/api/src/services/voting-power/voting-power.ts similarity index 96% rename from apps/indexer/src/api/services/voting-power/voting-power.ts rename to apps/api/src/services/voting-power/voting-power.ts index 2fe826fe9..c2dd2d5b7 100644 --- a/apps/indexer/src/api/services/voting-power/voting-power.ts +++ b/apps/api/src/services/voting-power/voting-power.ts @@ -1,6 +1,6 @@ import { Address } from "viem"; -import { DBVotingPowerVariation, DBAccountPower } from "@/api/mappers"; +import { DBVotingPowerVariation, DBAccountPower } from "@/mappers"; interface VotingPowerRepository { getVotingPowers( diff --git a/apps/api/tsconfig.json b/apps/api/tsconfig.json new file mode 100644 index 000000000..9306ab311 --- /dev/null +++ b/apps/api/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "strict": true, + "noUncheckedIndexedAccess": true, + "verbatimModuleSyntax": false, + "esModuleInterop": true, + "isolatedModules": true, + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "module": "ESNext", + "lib": ["ES2022"], + "target": "ES2022", + "skipLibCheck": true, + "paths": { + "@/*": ["./src/*"] + }, + "outDir": "./dist", + "moduleResolution": "node" + }, + "include": ["./**/*.ts"], + "exclude": ["node_modules", "test"] +} diff --git a/apps/api/tsup.config.ts b/apps/api/tsup.config.ts new file mode 100644 index 000000000..041729575 --- /dev/null +++ b/apps/api/tsup.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from "tsup"; + +export default defineConfig({ + entry: ["src/index.ts"], + format: ["esm"], + target: "es2022", + outDir: "dist", + clean: true, + external: [ + /^[a-z]/i, // Bare imports like 'dotenv', 'hono' + /^@[a-z]/i, // Scoped packages like '@hono/node-server' + ], +}); diff --git a/apps/dashboard/app/[daoId]/(secondary)/governance/proposal/[proposalId]/loading.tsx b/apps/dashboard/app/[daoId]/(secondary)/governance/proposal/[proposalId]/loading.tsx deleted file mode 100644 index 7db6a93c5..000000000 --- a/apps/dashboard/app/[daoId]/(secondary)/governance/proposal/[proposalId]/loading.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { ProposalSectionSkeleton } from "@/features/governance/components/proposal-overview/ProposalSectionSkeleton"; - -export default function Loading() { - return ( -
-
-
-
- -
-
-
-
- ); -} diff --git a/apps/dashboard/app/[daoId]/(secondary)/governance/proposal/[proposalId]/page.tsx b/apps/dashboard/app/[daoId]/(secondary)/governance/proposal/[proposalId]/page.tsx index 5c2437cbe..5539efbbc 100644 --- a/apps/dashboard/app/[daoId]/(secondary)/governance/proposal/[proposalId]/page.tsx +++ b/apps/dashboard/app/[daoId]/(secondary)/governance/proposal/[proposalId]/page.tsx @@ -68,8 +68,8 @@ export default function ProposalPage() {
- - + +
diff --git a/apps/dashboard/app/globals.css b/apps/dashboard/app/globals.css index 20d889353..18395bd93 100644 --- a/apps/dashboard/app/globals.css +++ b/apps/dashboard/app/globals.css @@ -41,6 +41,9 @@ --animate-accordion-up: accordion-up 0.2s ease-out; --animate-scroll-left: scroll-left 20s linear infinite; --animate-fade-in: fade-in 0.5s ease-in; + --animate-toast-slide-in: toast-slide-in 0.3s ease-out forwards; + --animate-toast-slide-out: toast-slide-out 0.2s ease-in forwards; + --animate-pulse-ring: pulse-ring 1.5s ease-out infinite; /* Shadow Styles */ --shadow-focus-ring: 0px 0px 0px 2px rgba(82, 82, 91, 0.3); @@ -233,6 +236,58 @@ transform: translateY(10px) scale(0.95); } } + + /* Toast animations - slide in from top */ + @keyframes toast-slide-in { + from { + opacity: 0; + transform: translateY(-100%); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + @keyframes toast-slide-out { + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(-100%); + } + } + + @keyframes pulse-ring { + 0% { + transform: scale(1); + opacity: 0.8; + } + 50% { + transform: scale(2); + opacity: 0; + } + 100% { + transform: scale(1); + opacity: 0; + } + } + + @keyframes pulse { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.5; + } + } +} + +.animate-pulse { + animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } /* diff --git a/apps/dashboard/features/alerts/components/AlertCard.tsx b/apps/dashboard/features/alerts/components/AlertCard.tsx index dfc55694a..4c7622028 100644 --- a/apps/dashboard/features/alerts/components/AlertCard.tsx +++ b/apps/dashboard/features/alerts/components/AlertCard.tsx @@ -24,7 +24,7 @@ export const AlertCard = ({
-
+
diff --git a/apps/dashboard/features/dao-overview/DaoOverviewSection.tsx b/apps/dashboard/features/dao-overview/DaoOverviewSection.tsx index 0ee46fd9c..19557edf2 100644 --- a/apps/dashboard/features/dao-overview/DaoOverviewSection.tsx +++ b/apps/dashboard/features/dao-overview/DaoOverviewSection.tsx @@ -23,6 +23,7 @@ import { MetricsCard } from "@/features/dao-overview/components/MetricsCard"; import { AttackProfitabilityChartCard } from "@/features/dao-overview/components/AttackProfitabilityChartCard"; import { useRouter } from "next/navigation"; import { apolloClient } from "@/shared/providers/GlobalProviders"; +import { OngoingProposalBanner } from "./components/OngoingProposalBanner"; export const DaoOverviewSection = ({ daoId }: { daoId: DaoIdEnum }) => { const router = useRouter(); @@ -70,6 +71,13 @@ export const DaoOverviewSection = ({ daoId }: { daoId: DaoIdEnum }) => {
+ + {daoConfig.governancePage && ( +
+ +
+ )} +
{ + const { data, loading } = useGetProposalsFromDaoQuery({ + variables: { + limit: 1, + status: ProposalStatus.ONGOING, + }, + context: { + headers: { + "anticapture-dao-id": daoId, + }, + }, + }); + + const hasOngoingProposal = + !loading && (data?.proposals?.items?.length ?? 0) > 0; + + if (!hasOngoingProposal) { + return null; + } + + return ( + } + text="This DAO has an ongoing proposal, cast your vote now." + storageKey={`banner-dismissed-${daoId}`} + link={{ + url: `/${daoId.toLowerCase()}/governance`, + text: "View proposals", + openInNewTab: false, + }} + /> + ); +}; diff --git a/apps/dashboard/features/governance/components/modals/VotingModal.tsx b/apps/dashboard/features/governance/components/modals/VotingModal.tsx index a637591ff..9751265cc 100644 --- a/apps/dashboard/features/governance/components/modals/VotingModal.tsx +++ b/apps/dashboard/features/governance/components/modals/VotingModal.tsx @@ -1,7 +1,7 @@ "use client"; -import { Button } from "@/shared/components"; -import { User2Icon, X } from "lucide-react"; +import { BadgeStatus, Button } from "@/shared/components"; +import { Check, User2Icon, X } from "lucide-react"; import { useEffect, useState } from "react"; import type { Query_Proposals_Items_Items } from "@anticapture/graphql-client/hooks"; @@ -33,26 +33,70 @@ export const VotingModal = ({ const [isLoading, setIsLoading] = useState(false); const [transactionhash, setTransactionhash] = useState(""); - const totalVotes = - Number(proposal?.forVotes) + - Number(proposal?.againstVotes) + - Number(proposal?.abstainVotes); + // Parse user's voting power to BigInt for calculations + const userVotingPowerBigInt = BigInt(votingPower || "0"); - const userReadableTotalVotes = formatNumberUserReadable( - Number(formatUnits(BigInt(totalVotes || 0), decimals)), + // Calculate base votes from proposal + const baseForVotes = BigInt(proposal?.forVotes || "0"); + const baseAgainstVotes = BigInt(proposal?.againstVotes || "0"); + const baseAbstainVotes = BigInt(proposal?.abstainVotes || "0"); + + // Calculate simulated votes based on user's selection + const simulatedForVotes = + vote === "for" ? baseForVotes + userVotingPowerBigInt : baseForVotes; + const simulatedAgainstVotes = + vote === "against" + ? baseAgainstVotes + userVotingPowerBigInt + : baseAgainstVotes; + const simulatedAbstainVotes = + vote === "abstain" + ? baseAbstainVotes + userVotingPowerBigInt + : baseAbstainVotes; + + // Calculate simulated total (includes user's voting power if any option is selected) + const simulatedTotalVotes = + simulatedForVotes + simulatedAgainstVotes + simulatedAbstainVotes; + + // Calculate simulated quorum votes (for + abstain only, against votes don't count toward quorum) + const simulatedQuorumVotes = simulatedForVotes + simulatedAbstainVotes; + + const userReadableQuorumVotes = formatNumberUserReadable( + Number(formatUnits(simulatedQuorumVotes || BigInt(0), decimals)), ); const userReadableQuorum = formatNumberUserReadable( Number(formatUnits(BigInt(proposal?.quorum || 0), decimals)), ); - const forPercentage = (Number(proposal?.forVotes) / Number(totalVotes)) * 100; + + // Calculate percentages based on simulated values + const forPercentage = + simulatedTotalVotes > BigInt(0) + ? (Number(simulatedForVotes) / Number(simulatedTotalVotes)) * 100 + : 0; const againstPercentage = - (Number(proposal?.againstVotes) / Number(totalVotes)) * 100; + simulatedTotalVotes > BigInt(0) + ? (Number(simulatedAgainstVotes) / Number(simulatedTotalVotes)) * 100 + : 0; const abstainPercentage = - (Number(proposal?.abstainVotes) / Number(totalVotes)) * 100; + simulatedTotalVotes > BigInt(0) + ? (Number(simulatedAbstainVotes) / Number(simulatedTotalVotes)) * 100 + : 0; + + const isQuorumReached = + Number(simulatedQuorumVotes) >= Number(proposal?.quorum || 0); const { address, chain } = useAccount(); const { data: walletClient } = useWalletClient(); + // Reset state when modal opens to prevent stale data from previous sessions + useEffect(() => { + if (isOpen) { + setVote(""); + setComment(""); + setIsLoading(false); + setTransactionhash(""); + } + }, [isOpen]); + // Prevent body scroll when modal is open useEffect(() => { if (isOpen) { @@ -84,10 +128,12 @@ export const VotingModal = ({ }; }, [isOpen, onClose]); - if (!isOpen) return null; - return ( -
+
{/* Backdrop with blur */}
{/* Modal content */} -
+
{/* Header */}
@@ -138,7 +188,7 @@ export const VotingModal = ({ -
+

Quorum

- {userReadableTotalVotes} / {userReadableQuorum} + {userReadableQuorumVotes} / {userReadableQuorum}

+ {isQuorumReached ? ( + + Reached + + ) : ( + Not Reached + )}
+
{/* Comment */} @@ -181,7 +239,7 @@ export const VotingModal = ({ Comment (optional)