From 604a98fc02d4b8755ed9ada0ad523ed6ae7e1b52 Mon Sep 17 00:00:00 2001 From: prego Date: Mon, 23 Oct 2023 11:52:52 +0200 Subject: [PATCH] add candidate number to subgraph --- packages/nouns-subgraph/schema.graphql | 6 +++ packages/nouns-subgraph/src/nouns-dao-data.ts | 2 + packages/nouns-subgraph/src/utils/helpers.ts | 11 ++++++ .../tests/nouns-dao-data.test.ts | 39 +++++++++++++++++++ 4 files changed, 58 insertions(+) diff --git a/packages/nouns-subgraph/schema.graphql b/packages/nouns-subgraph/schema.graphql index 119df4a00d..d441729b69 100644 --- a/packages/nouns-subgraph/schema.graphql +++ b/packages/nouns-subgraph/schema.graphql @@ -408,6 +408,9 @@ type Governance @entity { "The proposal ID from which vote snapshots are taken at vote start instead of proposal creation" voteSnapshotBlockSwitchProposalId: BigInt! + + "Number of candidates created" + candidates: BigInt! } type DynamicQuorumParams @entity { @@ -466,6 +469,9 @@ type ProposalCandidate @entity { "This candidate's versions" versions: [ProposalCandidateVersion!]! @derivedFrom(field: "proposal") + + "This candidate's number" + number: BigInt! } type ProposalCandidateVersion @entity(immutable: true) { diff --git a/packages/nouns-subgraph/src/nouns-dao-data.ts b/packages/nouns-subgraph/src/nouns-dao-data.ts index 9b8026f585..0aaa274d4d 100644 --- a/packages/nouns-subgraph/src/nouns-dao-data.ts +++ b/packages/nouns-subgraph/src/nouns-dao-data.ts @@ -11,6 +11,7 @@ import { import { ProposalCandidateContent, ProposalCandidateVersion } from './types/schema'; import { candidateID, + getCandidateIndex, getOrCreateCandidateFeedback, getOrCreateDelegate, getOrCreateProposalCandidate, @@ -33,6 +34,7 @@ export function handleProposalCandidateCreated(event: ProposalCandidateCreated): candidate.lastUpdatedTimestamp = event.block.timestamp; candidate.lastUpdatedBlock = event.block.number; candidate.canceled = false; + candidate.number = getCandidateIndex(); const version = captureProposalCandidateVersion( event.transaction.hash.toHexString(), diff --git a/packages/nouns-subgraph/src/utils/helpers.ts b/packages/nouns-subgraph/src/utils/helpers.ts index d870b3e6f6..2363c81497 100644 --- a/packages/nouns-subgraph/src/utils/helpers.ts +++ b/packages/nouns-subgraph/src/utils/helpers.ts @@ -138,6 +138,7 @@ export function getGovernanceEntity(): Governance { governance.delegatedVotes = BIGINT_ZERO; governance.proposalsQueued = BIGINT_ZERO; governance.voteSnapshotBlockSwitchProposalId = BIGINT_ZERO; + governance.candidates = BIGINT_ZERO; } return governance as Governance; @@ -177,7 +178,12 @@ export function getOrCreateProposalCandidate(id: string): ProposalCandidate { let candidate = ProposalCandidate.load(id); if (candidate == null) { candidate = new ProposalCandidate(id); + + const governance = getGovernanceEntity(); + governance.candidates = governance.candidates.plus(BIGINT_ONE); + governance.save(); } + return candidate; } @@ -233,6 +239,11 @@ export function getOrCreateFork(id: BigInt): Fork { return fork; } +export function getCandidateIndex(): BigInt { + const governance = getGovernanceEntity(); + return governance.candidates; +} + export function candidateID(proposer: Address, slug: string): string { return proposer.toHexString().concat('-').concat(slug); } diff --git a/packages/nouns-subgraph/tests/nouns-dao-data.test.ts b/packages/nouns-subgraph/tests/nouns-dao-data.test.ts index 5a41509d6b..abbcfa65d2 100644 --- a/packages/nouns-subgraph/tests/nouns-dao-data.test.ts +++ b/packages/nouns-subgraph/tests/nouns-dao-data.test.ts @@ -84,6 +84,7 @@ describe('nouns-dao-data', () => { assert.bytesEquals(txHash, candidate.createdTransactionHash); assert.bigIntEquals(blockTimestamp, candidate.createdTimestamp); assert.bigIntEquals(blockNumber, candidate.createdBlock); + assert.bigIntEquals(BigInt.fromI32(1), candidate.number); const version = ProposalCandidateVersion.load(candidate.latestVersion)!; assert.stringEquals(candidate.id, version.proposal); @@ -177,5 +178,43 @@ describe('nouns-dao-data', () => { ); assert.assertNull(signature); }); + + test('save a proposal candidade includes candidate index', () => { + const candidate = ProposalCandidate.load( + candidateProposer.toHexString().concat('-').concat(slug), + )!; + assert.stringEquals(candidateProposer.toHexString(), candidate.proposer.toHexString()); + assert.stringEquals(slug, candidate.slug); + assert.bytesEquals(txHash, candidate.createdTransactionHash); + assert.bigIntEquals(blockTimestamp, candidate.createdTimestamp); + assert.bigIntEquals(blockNumber, candidate.createdBlock); + assert.bigIntEquals(BigInt.fromI32(1), candidate.number); + + const newSlug = 'new slug'; + + // save new one + const event = createProposalCandidateCreatedEvent( + txHash, + logIndex, + blockTimestamp, + blockNumber, + candidateProposer, + targets, + values, + signatures, + calldatas, + description, + newSlug, + encodedProposalHash, + ); + + handleProposalCandidateCreated(event); + + const candidate2 = ProposalCandidate.load( + candidateProposer.toHexString().concat('-').concat(newSlug), + )!; + + assert.bigIntEquals(BigInt.fromI32(2), candidate2.number); + }); }); });