Skip to content
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

Voting connector: Support vote statuses #336

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/connect-voting/src/__test__/votes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@ describe('when connecting to a voting app', () => {
expect(vote.startDate).toEqual('1599675534')
})

test('should have a valid endDate', () => {
expect(vote.endDate).toEqual('1600280334')
})

test('should have not be accepted', () => {
expect(vote.isAccepted).toBe(false)
})

test('should have a valid status', () => {
expect(vote.status).toEqual('Rejected')
})

describe('when querying for the casts of a vote', () => {
let casts: Cast[]

Expand Down
2 changes: 2 additions & 0 deletions packages/connect-voting/src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './numbers'
export * from './time'
3 changes: 3 additions & 0 deletions packages/connect-voting/src/helpers/numbers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { BigNumber } from 'ethers'

export const bn = (x: string | number): BigNumber => BigNumber.from(x.toString())
4 changes: 4 additions & 0 deletions packages/connect-voting/src/helpers/time.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { BigNumber } from 'ethers'
import { bn } from './numbers'

export const currentTimestampEvm = (): BigNumber => bn(Math.floor(Date.now() / 1000))
19 changes: 19 additions & 0 deletions packages/connect-voting/src/models/Vote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { SubscriptionCallback, SubscriptionResult } from '@aragon/connect-types'
import { subscription } from '@aragon/connect-core'
import { IVotingConnector, VoteData } from '../types'
import Cast from './Cast'
import { bn, currentTimestampEvm } from '../helpers'

export default class Vote {
#connector: IVotingConnector
Expand All @@ -13,13 +14,15 @@ export default class Vote {
readonly executed: boolean
readonly executedAt: string
readonly startDate: string
readonly endDate: string
readonly snapshotBlock: string
readonly supportRequiredPct: string
readonly minAcceptQuorum: string
readonly yea: string
readonly nay: string
readonly votingPower: string
readonly script: string
readonly isAccepted: boolean

constructor(data: VoteData, connector: IVotingConnector) {
this.#connector = connector
Expand All @@ -31,13 +34,29 @@ export default class Vote {
this.executed = data.executed
this.executedAt = data.executedAt
this.startDate = data.startDate
this.endDate = data.endDate
this.snapshotBlock = data.snapshotBlock
this.supportRequiredPct = data.supportRequiredPct
this.minAcceptQuorum = data.minAcceptQuorum
this.yea = data.yea
this.nay = data.nay
this.votingPower = data.votingPower
this.script = data.script
this.isAccepted = data.isAccepted
}

get status(): string {
const currentTimestamp = currentTimestampEvm()

if (!this.executed) {
if (currentTimestamp.gte(bn(this.endDate))) {
return this.isAccepted ? "Accepted" : "Rejected"
}

return "Ongoing"
}

return "Executed"
}

async casts({ first = 1000, skip = 0 } = {}): Promise<Cast[]> {
Expand Down
4 changes: 4 additions & 0 deletions packages/connect-voting/src/thegraph/queries/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ export const ALL_VOTES = (type: string) => gql`
executed
executedAt
startDate
endDate
snapshotBlock
supportRequiredPct
minAcceptQuorum
yea
nay
votingPower
isAccepted
script
}
}
Expand All @@ -39,12 +41,14 @@ export const CASTS_FOR_VOTE = (type: string) => gql`
executed
executedAt
startDate
endDate
snapshotBlock
supportRequiredPct
minAcceptQuorum
yea
nay
votingPower
isAccepted
script
}
voter {
Expand Down
2 changes: 2 additions & 0 deletions packages/connect-voting/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ export interface VoteData {
executed: boolean
executedAt: string
startDate: string
endDate: string
snapshotBlock: string
supportRequiredPct: string
minAcceptQuorum: string
yea: string
nay: string
votingPower: string
script: string
isAccepted: boolean
}

export interface CastData {
Expand Down
2 changes: 2 additions & 0 deletions packages/connect-voting/subgraph/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type Vote @entity {
executed: Boolean!
executedAt: BigInt!
startDate: BigInt!
endDate: BigInt!
snapshotBlock: BigInt!
supportRequiredPct: BigInt!
minAcceptQuorum: BigInt!
Expand All @@ -16,6 +17,7 @@ type Vote @entity {
votingPower: BigInt!
script: String!
voteNum: BigInt!
isAccepted: Boolean!
castVotes: [Cast!] @derivedFrom(field: "vote")
}

Expand Down
13 changes: 12 additions & 1 deletion packages/connect-voting/subgraph/src/Voting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function handleStartVote(event: StartVoteEvent): void {
vote.metadata = event.params.metadata
vote.voteNum = event.params.voteId
vote.startDate = voteData.value2
vote.endDate = vote.startDate.plus(voting.voteTime())
vote.snapshotBlock = voteData.value3
vote.supportRequiredPct = voteData.value4
vote.minAcceptQuorum = voteData.value5
Expand All @@ -35,7 +36,7 @@ export function handleStartVote(event: StartVoteEvent): void {
vote.orgAddress = voting.kernel()
vote.executedAt = BigInt.fromI32(0)
vote.executed = false

vote.isAccepted = isAccepted(vote.yea, vote.nay, vote.votingPower, vote.supportRequiredPct, vote.minAcceptQuorum, voting.PCT_BASE())
vote.save()
}

Expand Down Expand Up @@ -118,6 +119,16 @@ export function updateVoteState(votingAddress: Address, voteId: BigInt): void {
const vote = VoteEntity.load(buildVoteEntityId(votingAddress, voteId))!
vote.yea = voteData.value6
vote.nay = voteData.value7
vote.isAccepted = isAccepted(vote.yea, vote.nay, vote.votingPower, vote.supportRequiredPct, vote.minAcceptQuorum, votingApp.PCT_BASE())

vote.save()
}

function isAccepted(yeas: BigInt, nays: BigInt, votingPower: BigInt, supportRequiredPct: BigInt, minimumAcceptanceQuorumPct: BigInt, pctBase: BigInt): boolean {
return hasReachedValuePct(yeas, yeas.plus(nays), supportRequiredPct, pctBase) &&
PJColombo marked this conversation as resolved.
Show resolved Hide resolved
hasReachedValuePct(yeas, votingPower, 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)
}