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' ; export function handleNewSetting ( event ) { 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 ) { 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 . originalCreator = event . transaction . from ; 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 ) { 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 ) { 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 ) { updateVoteState ( event . address , event . params . voteId ) ; } export function handleCancelVote ( event ) { updateVoteState ( event . address , event . params . voteId ) ; } export function handleExecuteVote ( event ) { 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 ) { updateVoteState ( event . address , event . params . voteId ) ; } export function handleChangeRepresentative ( event ) { const voter = loadOrCreateVoter ( event . address , event . params . voter ) ; voter . representative = event . params . representative ; voter . save ( ) ; } function isAccepted ( yeas , nays , totalPower , settingId , pctBase ) { const setting = SettingEntity . load ( settingId ) ! ; return hasReachedValuePct ( yeas , yeas . plus ( nays ) , setting . supportRequiredPct , pctBase ) && hasReachedValuePct ( yeas , totalPower , setting . minimumAcceptanceQuorumPct , pctBase ) ; } function hasReachedValuePct ( value , total , pct , pctBase ) { return total . notEqual ( BigInt . fromI32 ( 0 ) ) && ( value . times ( pctBase ) . div ( total ) ) . gt ( pct ) ; } export function loadOrCreateVoting ( votingAddress ) { 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 , voteId , voterAddress ) { 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 , voterAddress ) { 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 , voteId ) { 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 ) { 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 , voteId ) { return voting . toHexString ( ) + "-vote-" + voteId . toString ( ) ; } function buildVoterId ( voting , voter ) { return voting . toHexString ( ) + "-voter-" + voter . toHexString ( ) ; } function buildCastVoteId ( voting , voteId , voter ) { return buildVoteId ( voting , voteId ) + "-cast-" + voter . toHexString ( ) ; } function buildSettingId ( voting , settingId ) { return voting . toHexString ( ) + "-setting-" + settingId . toString ( ) ; } function castVoterState ( state ) { switch ( state ) { case 0 : return 'Absent' ; case 1 : return 'Yea' ; case 2 : return 'Nay' ; default : return 'Unknown' ; } } function castVoteStatus ( state ) { switch ( state ) { case 0 : return 'Scheduled' ; case 1 : return 'Challenged' ; case 2 : return 'Cancelled' ; case 3 : return 'Executed' ; default : return 'Unknown' ; } }