Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.
Open
Changes from all 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
80 changes: 80 additions & 0 deletions packages/connect-voting/src/models/Vote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ import { subscription } from '@aragon/connect-core'
import { IVotingConnector, VoteData } from '../types'
import Cast from './Cast'

export enum EVotingStatus {
Created = 'Created',
// TODO: no difference between started and ongoing.
Started = 'Started',
Ongoing = 'Ongoing',
// TODO: when would a voting status ever be ended, but not concluded?
// seems never? it should either be accepted / rejected / executed.
Ended = 'Ended',
Accepted = 'Accepted',
Rejected = 'Rejected',
Executed = 'Executed',
}

export default class Vote {
#connector: IVotingConnector

Expand Down Expand Up @@ -40,6 +53,73 @@ export default class Vote {
this.script = data.script
}

hasQuorumReached() {
// Assuming heavily this won't overflow. We should really type our data so everyone
// using / consuming the api knows what's what.
const yea = parseInt(this.yea);
const total = parseInt(this.votingPower);
// What format will it be in? like 10 to indicate 10% or 0.10 to indicate 10%?
// Assuming 0.10 = 10% for now.
const requiredMin = parseFloat(this.minAcceptQuorum);
const currentPositives = yea / total;
return currentPositives > requiredMin;
}

hasStarted() {
const startDate = parseInt(this.startDate) * 1000;
return new Date().getTime() >= startDate;
}

hasExecuted() {
return this.executed;
}

hasEnded() {
// TODO: Need to add a new field for ending date, seems to be missing right now
// and no way to determine when the vote ends for conclusion.
return this.executed;
}

isCreated() {
// If the object exists, its created.
return true;
}

isOngoing() {
return this.hasStarted() && (!this.hasEnded());
}

isAccepted() {
// Assuming heavily this won't overflow. We should really type our data so everyone
// using / consuming the api knows what's what.
const positives = parseInt(this.yea);
const total = parseInt(this.votingPower);

const positivePercent = positives / total;
const minSupport = parseFloat(this.supportRequiredPct);

const acceptable = positivePercent > minSupport;
return acceptable && this.hasQuorumReached();
}

isRejected() {
return !this.isAccepted();
}

get status(): EVotingStatus {
if (this.executed) {
return EVotingStatus.Executed
} else if (this.isAccepted()) {
return EVotingStatus.Accepted;
} else if (this.isRejected()) {
return EVotingStatus.Rejected;
} else if (this.hasStarted()) {
return EVotingStatus.Started;
} else {
return EVotingStatus.Created;
}
}

async casts({ first = 1000, skip = 0 } = {}): Promise<Cast[]> {
return this.#connector.castsForVote(this.id, first, skip)
}
Expand Down