quasvel
Version:
Access and interact with Aragon Organizations and their apps.
253 lines (218 loc) • 9.45 kB
text/typescript
import { BigInt, Address } from '@graphprotocol/graph-ts'
import { ERC20 as ERC20Contract } from '../generated/templates/DisputableVoting/ERC20'
import { Agreement as AgreementContract } from '../generated/templates/Agreement/Agreement'
import {
DisputableVoting as DisputableVotingEntity,
Setting as SettingEntity,
Vote as VoteEntity,
CastVote as CastVoteEntity,
Voter as VoterEntity,
ERC20 as ERC20Entity
} from '../generated/schema'
import {
DisputableVoting as VotingContract,
NewSetting as NewSettingEvent,
StartVote as StartVoteEvent,
CastVote as CastVoteEvent,
PauseVote as PauseVoteEvent,
ResumeVote as ResumeVoteEvent,
CancelVote as CancelVoteEvent,
ExecuteVote as ExecuteVoteEvent,
QuietEndingExtendVote as QuietEndingExtendVoteEvent,
ChangeRepresentative as ChangeRepresentativeEvent
} from '../generated/templates/DisputableVoting/DisputableVoting'
/* eslint-disable @typescript-eslint/no-use-before-define */
export function handleNewSetting(event: NewSettingEvent): void {
const votingApp = VotingContract.bind(event.address)
const settingData = votingApp.getSetting(event.params.settingId)
const voting = loadOrCreateVoting(event.address)
const currentSettingId = buildSettingId(event.address, event.params.settingId)
const setting = new SettingEntity(currentSettingId)
setting.voting = event.address.toHexString()
setting.settingId = event.params.settingId
setting.voteTime = settingData.value0
setting.supportRequiredPct = settingData.value1
setting.minimumAcceptanceQuorumPct = settingData.value2
setting.delegatedVotingPeriod = settingData.value3
setting.quietEndingPeriod = settingData.value4
setting.quietEndingExtension = settingData.value5
setting.executionDelay = settingData.value6
setting.createdAt = event.block.timestamp
setting.save()
voting.setting = currentSettingId
voting.save()
}
export function handleStartVote(event: StartVoteEvent): void {
const voteId = buildVoteId(event.address, event.params.voteId)
const voting = loadOrCreateVoting(event.address)
const votingApp = VotingContract.bind(event.address)
const vote = new VoteEntity(voteId)
const voteData = votingApp.getVote(event.params.voteId)
vote.voting = event.address.toHexString()
vote.voteId = event.params.voteId
vote.creator = event.params.creator
vote.context = event.params.context.toString()
vote.yeas = voteData.value0
vote.nays = voteData.value1
vote.totalPower = voteData.value2
vote.startDate = voteData.value3
vote.snapshotBlock = voteData.value4
vote.status = castVoteStatus(voteData.value5)
vote.setting = buildSettingId(event.address, voteData.value6)
vote.actionId = voteData.value7
vote.challengeId = BigInt.fromI32(0)
vote.challenger = Address.fromString('0x0000000000000000000000000000000000000000')
vote.challengeEndDate = BigInt.fromI32(0)
vote.pausedAt = voteData.value8
vote.pauseDuration = voteData.value9
vote.quietEndingExtensionDuration = voteData.value10
vote.quietEndingSnapshotSupport = castVoterState(voteData.value11)
vote.script = event.params.executionScript
vote.settledAt = BigInt.fromI32(0)
vote.disputedAt = BigInt.fromI32(0)
vote.executedAt = BigInt.fromI32(0)
vote.isAccepted = isAccepted(vote.yeas, vote.nays, vote.totalPower, vote.setting, votingApp.PCT_BASE())
vote.collateralRequirement = voting.collateralRequirement
vote.save()
}
export function handleCastVote(event: CastVoteEvent): void {
updateVoteState(event.address, event.params.voteId)
const voter = loadOrCreateVoter(event.address, event.params.voter)
voter.save()
const votingApp = VotingContract.bind(event.address)
const vote = VoteEntity.load(buildVoteId(event.address, event.params.voteId))!
const miniMeToken = ERC20Contract.bind(votingApp.token())
const stake = miniMeToken.balanceOfAt(event.params.voter, vote.snapshotBlock)
const castVote = loadOrCreateCastVote(event.address, event.params.voteId, event.params.voter)
castVote.voter = voter.id
castVote.stake = stake
castVote.supports = event.params.supports
castVote.createdAt = event.block.timestamp
castVote.caster = event.params.caster
castVote.save()
}
export function handlePauseVote(event: PauseVoteEvent): void {
updateVoteState(event.address, event.params.voteId)
const votingApp = VotingContract.bind(event.address)
const agreementApp = AgreementContract.bind(votingApp.getAgreement())
const challengeData = agreementApp.getChallenge(event.params.challengeId)
const vote = VoteEntity.load(buildVoteId(event.address, event.params.voteId))!
vote.challenger = challengeData.value1
vote.challengeId = event.params.challengeId
vote.challengeEndDate = challengeData.value2
vote.save()
}
export function handleResumeVote(event: ResumeVoteEvent): void {
updateVoteState(event.address, event.params.voteId)
}
export function handleCancelVote(event: CancelVoteEvent): void {
updateVoteState(event.address, event.params.voteId)
}
export function handleExecuteVote(event: ExecuteVoteEvent): void {
updateVoteState(event.address, event.params.voteId)
const vote = VoteEntity.load(buildVoteId(event.address, event.params.voteId))!
vote.executedAt = event.block.timestamp
vote.save()
}
export function handleQuietEndingExtendVote(event: QuietEndingExtendVoteEvent): void {
updateVoteState(event.address, event.params.voteId)
}
export function handleChangeRepresentative(event: ChangeRepresentativeEvent): void {
const voter = loadOrCreateVoter(event.address, event.params.voter)
voter.representative = event.params.representative
voter.save()
}
function isAccepted(yeas: BigInt, nays: BigInt, totalPower: BigInt, settingId: string, pctBase: BigInt): boolean {
const setting = SettingEntity.load(settingId)!
return hasReachedValuePct(yeas, yeas.plus(nays), setting.supportRequiredPct, pctBase) &&
hasReachedValuePct(yeas, totalPower, setting.minimumAcceptanceQuorumPct, pctBase)
}
function hasReachedValuePct(value: BigInt, total: BigInt, pct: BigInt, pctBase: BigInt): boolean {
return total.notEqual(BigInt.fromI32(0)) && (value.times(pctBase).div(total)).gt(pct)
}
export function loadOrCreateVoting(votingAddress: Address): DisputableVotingEntity {
let voting = DisputableVotingEntity.load(votingAddress.toHexString())
if (voting === null) {
const votingApp = VotingContract.bind(votingAddress)
voting = new DisputableVotingEntity(votingAddress.toHexString())
voting.dao = votingApp.kernel()
voting.agreement = votingApp.getAgreement()
voting.token = buildERC20(votingApp.token())
}
return voting!
}
function loadOrCreateCastVote(votingAddress: Address, voteId: BigInt, voterAddress: Address): CastVoteEntity {
const castVoteId = buildCastVoteId(votingAddress, voteId, voterAddress)
let castVote = CastVoteEntity.load(castVoteId)
if (castVote === null) {
castVote = new CastVoteEntity(castVoteId)
castVote.vote = buildVoteId(votingAddress, voteId)
}
return castVote!
}
function loadOrCreateVoter(votingAddress: Address, voterAddress: Address): VoterEntity {
const voterId = buildVoterId(votingAddress, voterAddress)
let voter = VoterEntity.load(voterId)
if (voter === null) {
voter = new VoterEntity(voterId)
voter.voting = votingAddress.toHexString()
voter.address = voterAddress
}
return voter!
}
export function updateVoteState(votingAddress: Address, voteId: BigInt): void {
const votingApp = VotingContract.bind(votingAddress)
const voteData = votingApp.getVote(voteId)
const vote = VoteEntity.load(buildVoteId(votingAddress, voteId))!
vote.yeas = voteData.value0
vote.nays = voteData.value1
vote.status = vote.status == 'Settled' ? 'Settled' : castVoteStatus(voteData.value5)
vote.pausedAt = voteData.value8
vote.pauseDuration = voteData.value9
vote.quietEndingExtensionDuration = voteData.value10
vote.quietEndingSnapshotSupport = castVoterState(voteData.value11)
vote.isAccepted = isAccepted(vote.yeas, vote.nays, vote.totalPower, vote.setting, votingApp.PCT_BASE())
vote.save()
}
export function buildERC20(address: Address): string {
const id = address.toHexString()
let token = ERC20Entity.load(id)
if (token === null) {
const tokenContract = ERC20Contract.bind(address)
token = new ERC20Entity(id)
token.name = tokenContract.name()
token.symbol = tokenContract.symbol()
token.decimals = tokenContract.decimals()
token.save()
}
return token.id
}
export function buildVoteId(voting: Address, voteId: BigInt): string {
return voting.toHexString() + "-vote-" + voteId.toString()
}
function buildVoterId(voting: Address, voter: Address): string {
return voting.toHexString() + "-voter-" + voter.toHexString()
}
function buildCastVoteId(voting: Address, voteId: BigInt, voter: Address): string {
return buildVoteId(voting, voteId) + "-cast-" + voter.toHexString()
}
function buildSettingId(voting: Address, settingId: BigInt): string {
return voting.toHexString() + "-setting-" + settingId.toString()
}
function castVoterState(state: i32): string {
switch (state) {
case 0: return 'Absent'
case 1: return 'Yea'
case 2: return 'Nay'
default: return 'Unknown'
}
}
function castVoteStatus(state: i32): string {
switch (state) {
case 0: return 'Scheduled'
case 1: return 'Challenged'
case 2: return 'Cancelled'
case 3: return 'Executed'
default: return 'Unknown'
}
}