temporibusunde
Version:
Access and interact with Aragon Organizations and their apps.
195 lines (169 loc) • 5.7 kB
text/typescript
import {
Address,
SubscriptionCallback,
SubscriptionResult,
} from '@aragon/connect-types'
import { subscription } from '@aragon/connect-core'
import { IDisputableVotingConnector, VoteData } from '../types'
import Setting from './Setting'
import CastVote from './CastVote'
import DisputableVoting from './DisputableVoting'
import CollateralRequirement from './CollateralRequirement'
import {
toMilliseconds,
bn,
formatBn,
PCT_BASE,
PCT_DECIMALS,
} from '../helpers'
export default class Vote {
#connector: IDisputableVotingConnector
readonly id: string
readonly votingId: string
readonly voteId: string
readonly creator: string
readonly duration: string
readonly context: string
readonly voteStatus: string
readonly actionId: string
readonly challengeId: string
readonly challenger: string
readonly challengeEndDate: string
readonly disputeId: string
readonly settingId: string
readonly startDate: string
readonly totalPower: string
readonly snapshotBlock: string
readonly yeas: string
readonly nays: string
readonly pausedAt: string
readonly pauseDuration: string
readonly quietEndingExtensionDuration: string
readonly quietEndingSnapshotSupport: string
readonly script: string
readonly settledAt: string
readonly executedAt: string
readonly isAccepted: boolean
readonly tokenDecimals: string
constructor(data: VoteData, connector: IDisputableVotingConnector) {
this.#connector = connector
this.id = data.id
this.votingId = data.votingId
this.voteId = data.voteId
this.duration = data.duration
this.creator = data.creator
this.context = data.context
this.voteStatus = data.status
this.actionId = data.actionId
this.challengeId = data.challengeId
this.challenger = data.challenger
this.challengeEndDate = data.challengeEndDate
this.disputeId = data.disputeId
this.settingId = data.settingId
this.startDate = data.startDate
this.totalPower = data.totalPower
this.snapshotBlock = data.snapshotBlock
this.yeas = data.yeas
this.nays = data.nays
this.pausedAt = data.pausedAt
this.pauseDuration = data.pauseDuration
this.quietEndingExtensionDuration = data.quietEndingExtensionDuration
this.quietEndingSnapshotSupport = data.quietEndingSnapshotSupport
this.script = data.script
this.settledAt = data.settledAt
this.executedAt = data.executedAt
this.isAccepted = data.isAccepted
this.tokenDecimals = data.tokenDecimals
}
get hasEnded(): boolean {
return this.voteStatus === 'Cancelled' || (
this.voteStatus !== 'Challenged' &&
this.voteStatus !== 'Disputed' &&
Date.now() >= toMilliseconds(this.endDate)
)
}
get endDate(): string {
const originalEndDate = bn(this.startDate).add(bn(this.duration))
const endDateAfterPause = originalEndDate.add(bn(this.pauseDuration))
return endDateAfterPause.add(bn(this.quietEndingExtensionDuration)).toString()
}
get yeasPct(): string {
return this._votingPowerPct(this.yeas)
}
get naysPct(): string {
return this._votingPowerPct(this.nays)
}
get formattedYeas(): string {
return formatBn(this.yeas, this.tokenDecimals)
}
get formattedYeasPct(): string {
return formatBn(this.yeasPct, PCT_DECIMALS)
}
get formattedNays(): string {
return formatBn(this.nays, this.tokenDecimals)
}
get formattedNaysPct(): string {
return formatBn(this.naysPct, PCT_DECIMALS)
}
get formattedTotalPower(): string {
return formatBn(this.totalPower, this.tokenDecimals)
}
get status(): string {
if (this.hasEnded && this.voteStatus === 'Scheduled') {
return this.isAccepted ? 'Accepted' : 'Rejected'
}
return this.voteStatus
}
castVoteId(voterAddress: Address): string {
return `${this.id}-cast-${voterAddress.toLowerCase()}`
}
async castVote(voterAddress: Address): Promise<CastVote | null> {
return this.#connector.castVote(this.castVoteId(voterAddress))
}
onCastVote(
voterAddress: Address,
callback?: SubscriptionCallback<CastVote | null>
): SubscriptionResult<CastVote | null> {
return subscription<CastVote | null>(callback, (callback) =>
this.#connector.onCastVote(this.castVoteId(voterAddress), callback)
)
}
async castVotes({ first = 1000, skip = 0 } = {}): Promise<CastVote[]> {
return this.#connector.castVotes(this.id, first, skip)
}
onCastVotes(
{ first = 1000, skip = 0 } = {},
callback?: SubscriptionCallback<CastVote[]>
): SubscriptionResult<CastVote[]> {
return subscription<CastVote[]>(callback, (callback) =>
this.#connector.onCastVotes(this.id, first, skip, callback)
)
}
async collateralRequirement(): Promise<CollateralRequirement> {
return this.#connector.collateralRequirement(this.id)
}
onCollateralRequirement(
callback?: SubscriptionCallback<CollateralRequirement>
): SubscriptionResult<CollateralRequirement> {
return subscription<CollateralRequirement>(callback, (callback) =>
this.#connector.onCollateralRequirement(this.id, callback)
)
}
async setting(): Promise<Setting> {
return this.#connector.setting(this.settingId)
}
onSetting(
callback?: SubscriptionCallback<Setting>
): SubscriptionResult<Setting> {
return subscription<Setting>(callback, (callback) =>
this.#connector.onSetting(this.settingId, callback)
)
}
_disputableVoting(): DisputableVoting {
return new DisputableVoting(this.#connector, this.votingId)
}
_votingPowerPct(num: string): string {
const totalPower = bn(this.totalPower)
return bn(num).mul(PCT_BASE).div(totalPower).toString()
}
}