-
Notifications
You must be signed in to change notification settings - Fork 4
feat(treasury): index governor votes and tallies #175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a6a6ff3
5f5dc62
2180a42
d39ea1a
7a2ab6d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,154 @@ | ||
| import { TreasuryProposal } from "../types/schema"; | ||
| import { ProposalCreated } from "../types/Treasury/LivepeerGovernor"; | ||
| import { BigDecimal, BigInt, ethereum, log } from "@graphprotocol/graph-ts"; | ||
|
|
||
| import { | ||
| convertToDecimal, | ||
| createOrLoadRound, | ||
| createOrLoadTransactionFromEvent, | ||
| createOrUpdateLivepeerAccount, | ||
| getBlockNum, | ||
| makeEventId, | ||
| ZERO_BD, | ||
| } from "../../utils/helpers"; | ||
| import { | ||
| TreasuryProposal, | ||
| TreasuryVote, | ||
| TreasuryVoteEvent, | ||
| } from "../types/schema"; | ||
| import { | ||
| ProposalCreated, | ||
| VoteCast, | ||
| VoteCastWithParams, | ||
| } from "../types/Treasury/LivepeerGovernor"; | ||
|
|
||
| // Workaround: Graph entities store enums as strings (no string enums in AS/codegen). | ||
| namespace TreasurySupport { | ||
| export const Against = "Against"; | ||
| export const For = "For"; | ||
| export const Abstain = "Abstain"; | ||
| } | ||
|
|
||
| export function proposalCreated(event: ProposalCreated): void { | ||
| const p = event.params; | ||
| const proposer = createOrUpdateLivepeerAccount( | ||
| p.proposer.toHex(), | ||
| event.block.timestamp.toI32() | ||
| ); | ||
|
|
||
| const proposal = new TreasuryProposal(p.proposalId.toString()); | ||
| proposal.proposer = p.proposer.toHex(); | ||
| proposal.proposer = proposer.id; | ||
| proposal.targets = p.targets.map<string>((t) => t.toHex()); | ||
| proposal.values = p.values; | ||
| proposal.calldatas = p.calldatas; | ||
| proposal.voteStart = p.voteStart; | ||
| proposal.voteEnd = p.voteEnd; | ||
| proposal.description = p.description; | ||
| proposal.forVotes = ZERO_BD; | ||
| proposal.againstVotes = ZERO_BD; | ||
| proposal.abstainVotes = ZERO_BD; | ||
| proposal.totalVotes = ZERO_BD; | ||
| proposal.save(); | ||
| } | ||
|
|
||
| export function voteCast(event: VoteCast): void { | ||
| handleVote( | ||
| event, | ||
| event.params.proposalId, | ||
| event.params.voter.toHex(), | ||
| event.params.support, | ||
| event.params.weight, | ||
| event.params.reason | ||
| ); | ||
| } | ||
|
|
||
| export function voteCastWithParams(event: VoteCastWithParams): void { | ||
| handleVote( | ||
| event, | ||
| event.params.proposalId, | ||
| event.params.voter.toHex(), | ||
| event.params.support, | ||
| event.params.weight, | ||
| event.params.reason | ||
| ); | ||
| } | ||
|
|
||
| function handleVote( | ||
| event: ethereum.Event, | ||
| proposalId: BigInt, | ||
| voter: string, | ||
| support: i32, | ||
| weightRaw: BigInt, | ||
| reason: string | ||
| ): void { | ||
| const proposal = TreasuryProposal.load(proposalId.toString()); | ||
|
|
||
| if (!proposal) { | ||
| log.error("Treasury vote for unknown proposal {}", [proposalId.toString()]); | ||
| return; | ||
| } | ||
|
|
||
| const supportLabelValue = supportFromValue(support); | ||
| if (supportLabelValue == null) { | ||
| return; | ||
| } | ||
| const supportLabel = supportLabelValue as string; | ||
|
|
||
| const account = createOrUpdateLivepeerAccount( | ||
| voter, | ||
| event.block.timestamp.toI32() | ||
| ); | ||
| const round = createOrLoadRound(getBlockNum()); | ||
| const transaction = createOrLoadTransactionFromEvent(event); | ||
| const voteId = proposal.id.concat("-").concat(voter); | ||
| let vote = TreasuryVote.load(voteId); | ||
| const weight = convertToDecimal(weightRaw); | ||
|
|
||
| if (!vote) { | ||
| vote = new TreasuryVote(voteId); | ||
| vote.proposal = proposal.id; | ||
| vote.voter = account.id; | ||
| } | ||
|
|
||
| vote.support = supportLabel; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure we should be using the string here, and instead should use the generated enum type ( This would also mean we can tweak
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jmulq I looked into this while working on the PR. Per the Graph docs on enums https://thegraph.com/docs/en/subgraphs/guides/enums/, enum fields in mappings are set using their string values, and the generated AssemblyScript entities expose them as I might be missing something, but if not, would d39ea1a be an acceptable workaround for now?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey @rickstaa - apologies for the confusion. I've been developing in subtreams world recently and wrongly said we can use the generated types. These aren't available in the handlers as you correctly mentioned. There are similar workaround to yours in this example repo - https://github.com/chidubemokeke/Subgraph-Tutorial-Enums/tree/main. However, I am happy for it to be the original block of code as well. Whatever you guys find easier to reason about. |
||
| vote.weight = weight; | ||
| vote.reason = reason.length > 0 ? reason : null; | ||
| vote.save(); | ||
|
|
||
| increaseProposalTotals(proposal, supportLabel, weight); | ||
|
|
||
| proposal.save(); | ||
|
|
||
| const voteEvent = new TreasuryVoteEvent( | ||
| makeEventId(event.transaction.hash, event.logIndex) | ||
| ); | ||
| voteEvent.transaction = transaction.id; | ||
| voteEvent.timestamp = event.block.timestamp.toI32(); | ||
| voteEvent.round = round.id; | ||
| voteEvent.voter = account.id; | ||
| voteEvent.proposal = proposal.id; | ||
| voteEvent.support = supportLabel; | ||
| voteEvent.weight = weight; | ||
| voteEvent.reason = reason.length > 0 ? reason : null; | ||
| voteEvent.save(); | ||
| } | ||
|
|
||
| function supportFromValue(value: i32): string | null { | ||
| if (value == 0) return TreasurySupport.Against; | ||
| if (value == 1) return TreasurySupport.For; | ||
| if (value == 2) return TreasurySupport.Abstain; | ||
| return null; | ||
| } | ||
|
|
||
| function increaseProposalTotals( | ||
| proposal: TreasuryProposal, | ||
| support: string, | ||
| weight: BigDecimal | ||
| ): void { | ||
| if (support == TreasurySupport.For) { | ||
| proposal.forVotes = proposal.forVotes.plus(weight); | ||
| } else if (support == TreasurySupport.Against) { | ||
| proposal.againstVotes = proposal.againstVotes.plus(weight); | ||
| } else { | ||
| proposal.abstainVotes = proposal.abstainVotes.plus(weight); | ||
| } | ||
| proposal.totalVotes = proposal.totalVotes.plus(weight); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.