From 5536bdf79fae62cbdf962334fcdbd5bdcf42f69f Mon Sep 17 00:00:00 2001 From: emmdim Date: Fri, 6 Oct 2023 18:01:06 +0200 Subject: [PATCH] * Temporarily adds approve inside setTally method * Improves app proposal statuses * Corrects canPrpoposaleBeapprovbed --- packages/js-client/src/internal/interfaces.ts | 3 +- .../js-client/src/internal/modules/methods.ts | 18 ++- packages/js-client/src/internal/utils.ts | 121 +++++++++--------- 3 files changed, 75 insertions(+), 67 deletions(-) diff --git a/packages/js-client/src/internal/interfaces.ts b/packages/js-client/src/internal/interfaces.ts index fe432cbc..85ac9a5d 100644 --- a/packages/js-client/src/internal/interfaces.ts +++ b/packages/js-client/src/internal/interfaces.ts @@ -72,7 +72,8 @@ export interface IOffchainVotingClientMethods { ): Promise; setTally( pluginAddress: string, - proposalId: number + proposalId: number, + tryExecution?: boolean ): AsyncGenerator; approveTally( proposalId: string, diff --git a/packages/js-client/src/internal/modules/methods.ts b/packages/js-client/src/internal/modules/methods.ts index c0613d38..87847dd7 100644 --- a/packages/js-client/src/internal/modules/methods.ts +++ b/packages/js-client/src/internal/modules/methods.ts @@ -47,6 +47,7 @@ import { hexToBytes, } from '@aragon/sdk-common'; import { isAddress } from '@ethersproject/address'; +import { ContractTransaction } from '@ethersproject/contracts'; import { VocdoniVoting__factory } from '@vocdoni/offchain-voting-ethers'; import { ErrElectionNotFound } from '@vocdoni/sdk'; import axios from 'axios'; @@ -270,7 +271,6 @@ export class OffchainVotingClientMethods pluginSettings.daoTokenAddress as string ); - // TODO return toNewProposal( proposalId, daoName, @@ -428,7 +428,8 @@ export class OffchainVotingClientMethods */ public async *setTally( pluginAddress: string, - proposalId: number + proposalId: number, + tryExecution = false ): AsyncGenerator { const signer = this.web3.getConnectedSigner(); @@ -445,10 +446,15 @@ export class OffchainVotingClientMethods const vochainProposal = await this.vocdoniSDK.fetchElection( proposalFromSC.vochainProposalId ); - const tx = await gaslessVotingContract.setTally( - proposalId, - vochainResultsToSCResults(vochainProposal) - ); + let tx: ContractTransaction; + if (proposalFromSC.tally.length === 0) { + tx = await gaslessVotingContract.setTally( + proposalId, + vochainResultsToSCResults(vochainProposal) + ); + } else { + tx = await gaslessVotingContract.approveTally(proposalId, tryExecution); + } yield { key: SetTallyStep.EXECUTING, diff --git a/packages/js-client/src/internal/utils.ts b/packages/js-client/src/internal/utils.ts index 4703f260..9947821c 100644 --- a/packages/js-client/src/internal/utils.ts +++ b/packages/js-client/src/internal/utils.ts @@ -24,13 +24,7 @@ import { Result } from '@ethersproject/abi'; import { BigNumber, BigNumberish } from '@ethersproject/bignumber'; import { AddressZero } from '@ethersproject/constants'; import { VocdoniVoting } from '@vocdoni/offchain-voting-ethers'; -import { - ElectionStatus, - IChoice, - IQuestion, - PublishedElection, - Token, -} from '@vocdoni/sdk'; +import { IChoice, IQuestion, PublishedElection, Token } from '@vocdoni/sdk'; import Big from 'big.js'; import { formatUnits as ethersFormatUnits } from 'ethers/lib/utils'; @@ -157,9 +151,7 @@ export function toGaslessVotingProposal( ): GaslessVotingProposalFromSC { return { executed: proposal.executed, - // TODO FIX - // approvers: proposal.approvals, - approvers: [], + approvers: proposal.approvers, vochainProposalId: proposal.vochainProposalId, parameters: proposalParamsfromContract(proposal.parameters), allowFailureMap: proposal.allowFailureMap.toNumber(), @@ -194,8 +186,8 @@ export function canProposalBeApproved( supportThreshold: number | undefined, missingParticipation: number | undefined, totalVotingWeight: bigint, - usedVotingWeight: bigint, - tokenDecimals: number + usedVotingWeight: bigint + // tokenDecimals: number ): boolean { if ( missingParticipation === undefined || @@ -206,19 +198,28 @@ export function canProposalBeApproved( } // those who didn't vote (this is NOT voting abstain) - const absentee = formatUnits( - totalVotingWeight - usedVotingWeight, - tokenDecimals - ); + // const absentee = formatUnits( + // totalVotingWeight - usedVotingWeight, + // tokenDecimals + // ); if (results.yes === BigInt(0)) return false; - + Big.DP = 2; return ( // participation reached missingParticipation === 0 && // support threshold met even if absentees show up and all vote against, still cannot change outcome - results.yes / (results.yes + results.no + BigInt(absentee)) > - supportThreshold + Big(results.yes.toString()) + .div( + Big( + BigInt( + results.yes + results.no + totalVotingWeight - usedVotingWeight + ).toString() + ) + ) + .gte(supportThreshold) + // (results.yes + results.no + (totalVotingWeight - usedVotingWeight)) > + // supportThreshold ); } @@ -229,53 +230,53 @@ export function computeProposalStatus( endDate: Date ): ProposalStatus { const now = new Date(); - if (executed) { - return ProposalStatus.EXECUTED; - } if (startDate >= now) { return ProposalStatus.PENDING; } - if (earlyExecutable) { - return ProposalStatus.SUCCEEDED; - } if (endDate >= now) { return ProposalStatus.ACTIVE; } + if (executed) { + return ProposalStatus.EXECUTED; + } + if (earlyExecutable) { + return ProposalStatus.SUCCEEDED; + } return ProposalStatus.DEFEATED; } -export function vochainStatusToProposalStatus( - vochainStatus: ElectionStatus, - finalResults: boolean, - executed: boolean, - canProposalBeApproved: boolean -): ProposalStatus { - //TODO probably need to check also the state of the contract - if ([ElectionStatus.UPCOMING, ElectionStatus.PAUSED].includes(vochainStatus)) - return ProposalStatus.PENDING; - if (ElectionStatus.ONGOING === vochainStatus) return ProposalStatus.ACTIVE; - // if ([].includes[vochainStatus]) - if (ElectionStatus.RESULTS) { - if (executed) return ProposalStatus.EXECUTED; - else if (finalResults) { - return canProposalBeApproved - ? ProposalStatus.SUCCEEDED - : ProposalStatus.DEFEATED; - } else { - //TODO decide how to handle this cases - return ProposalStatus.PENDING; - } - } - // TODO decide how to handle this cases - if ( - [ElectionStatus.CANCELED, ElectionStatus.PROCESS_UNKNOWN].includes( - vochainStatus - ) - ) - return ProposalStatus.PENDING; - // TODO decide which is the generic one - return ProposalStatus.PENDING; -} +// export function vochainStatusToProposalStatus( +// vochainStatus: ElectionStatus, +// finalResults: boolean, +// executed: boolean, +// canProposalBeApproved: boolean +// ): ProposalStatus { +// //TODO probably need to check also the state of the contract +// if ([ElectionStatus.UPCOMING, ElectionStatus.PAUSED].includes(vochainStatus)) +// return ProposalStatus.PENDING; +// if (ElectionStatus.ONGOING === vochainStatus) return ProposalStatus.ACTIVE; +// // if ([].includes[vochainStatus]) +// if (ElectionStatus.RESULTS) { +// if (executed) return ProposalStatus.EXECUTED; +// else if (finalResults) { +// return canProposalBeApproved +// ? ProposalStatus.SUCCEEDED +// : ProposalStatus.DEFEATED; +// } else { +// //TODO decide how to handle this cases +// return ProposalStatus.PENDING; +// } +// } +// // TODO decide how to handle this cases +// if ( +// [ElectionStatus.CANCELED, ElectionStatus.PROCESS_UNKNOWN].includes( +// vochainStatus +// ) +// ) +// return ProposalStatus.PENDING; +// // TODO decide which is the generic one +// return ProposalStatus.PENDING; +// } export function toNewProposal( SCproposalID: number, @@ -301,10 +302,10 @@ export function toNewProposal( const canBeApproved = canProposalBeApproved( result, settings.supportThreshold, - participation.minPart, + participation.missingPart, vochainProposal.census.weight || BigInt(0), - totalUsedWeight, - census3Token.decimals + totalUsedWeight + // census3Token.decimals ); const startDate = new Date(SCProposal.parameters.startDate); const endDate = new Date(SCProposal.parameters.endDate);