Skip to content

Commit

Permalink
Accurate proposal status
Browse files Browse the repository at this point in the history
  • Loading branch information
brickpop committed Mar 1, 2024
1 parent 1f96191 commit 5dfb90d
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 20 deletions.
63 changes: 44 additions & 19 deletions plugins/tokenVoting/components/proposal/header.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { AlertInline, Button, Tag } from "@aragon/ods";
import { Proposal } from "@/plugins/tokenVoting/utils/types";
import { Proposal, VotingMode } from "@/plugins/tokenVoting/utils/types";
import { AlertVariant } from "@aragon/ods";
import { Else, ElseIf, If, Then } from "@/components/if";
import { AddressText } from "@/components/text/address";
import { PleaseWaitSpinner } from "@/components/please-wait";
import dayjs from "dayjs";

const RATIO_BASE = 1_000_000;
const DEFAULT_PROPOSAL_TITLE = "(No proposal title)";

interface ProposalHeaderProps {
proposalNumber: number;
proposal: Proposal;
tokenSupply: bigint;
userVote: number | undefined;
canVote: boolean;
canExecute: boolean;
Expand All @@ -22,6 +24,7 @@ interface ProposalHeaderProps {
const ProposalHeader: React.FC<ProposalHeaderProps> = ({
proposalNumber,
proposal,
tokenSupply,
userVote,
canVote,
canExecute,
Expand All @@ -30,7 +33,7 @@ const ProposalHeader: React.FC<ProposalHeaderProps> = ({
onExecute,
}) => {
const userVoteInfo = getUserVoteVariant(userVote);
const proposalVariant = getProposalStatusVariant(proposal);
const proposalVariant = getProposalStatusVariant(proposal, tokenSupply);
const ended = proposal.parameters.endDate <= Date.now() / 1000;

return (
Expand Down Expand Up @@ -125,23 +128,45 @@ const ProposalHeader: React.FC<ProposalHeaderProps> = ({
);
};

const getProposalStatusVariant = (proposal: Proposal) => {
return {
variant: proposal?.active
? "info"
: proposal?.executed
? "primary"
: proposal?.tally?.no >= proposal?.tally?.yes
? "critical"
: ("success" as AlertVariant),
label: proposal?.active
? "Active"
: proposal?.executed
? "Executed"
: proposal?.tally?.no >= proposal?.tally?.yes
? "Defeated"
: "Executable",
};
const getProposalStatusVariant = (proposal: Proposal, tokenSupply: bigint) => {
// Terminal cases
if (!proposal?.tally) return { variant: "info", label: "" };
else if (proposal.executed) return { variant: "primary", label: "Executed" };

const yesNoVotes = proposal.tally.no + proposal.tally.yes;
if (!yesNoVotes) return { variant: "info", label: "" };

const totalVotes = proposal.tally.abstain + yesNoVotes;
const supportThreshold = proposal.parameters.supportThreshold;

if (!proposal.active) {
// Defeated or executable?
if (totalVotes < proposal.parameters.minVotingPower) {
return { variant: "critical", label: "Low turnout" };
}

const totalYesNo = proposal.tally.yes + proposal.tally.no;
const finalRatio = (BigInt(RATIO_BASE) * proposal.tally.yes) / totalYesNo;

if (finalRatio > BigInt(supportThreshold)) {
return { variant: "success", label: "Executable" };
}
return { variant: "critical", label: "Defeated" };
}

// Active or early execution?
const noVotesWorstCase =
tokenSupply - proposal.tally.yes - proposal.tally.abstain;
const totalYesNoWc = proposal.tally.yes + noVotesWorstCase;

if (proposal.parameters.votingMode == VotingMode.EarlyExecution) {
const currentRatio =
(BigInt(RATIO_BASE) * proposal.tally.yes) / totalYesNoWc;
if (currentRatio > BigInt(supportThreshold)) {
return { variant: "success", label: "Executable" };
}
}
return { variant: "info", label: "Active" };
};

const getUserVoteVariant = (userVote?: number) => {
Expand Down
3 changes: 3 additions & 0 deletions plugins/tokenVoting/pages/proposal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Else, If, Then } from "@/components/if";
import { PleaseWaitSpinner } from "@/components/please-wait";
import { useSkipFirstRender } from "@/hooks/useSkipFirstRender";
import { useProposalVoting } from "../hooks/useProposalVoting";
import { useVotingToken } from "../hooks/useVotingToken";
import { useProposalExecute } from "../hooks/useProposalExecute";

type BottomSection = "description" | "votes";
Expand All @@ -26,6 +27,7 @@ export default function ProposalDetail({ id: proposalId }: { id: string }) {
proposalId,
true
);
const { tokenSupply } = useVotingToken();
const {
voteProposal,
votingStatus,
Expand Down Expand Up @@ -109,6 +111,7 @@ export default function ProposalDetail({ id: proposalId }: { id: string }) {
<ProposalHeader
proposalNumber={Number(proposalId) + 1}
proposal={proposal}
tokenSupply={tokenSupply || BigInt("0")}
userVote={votedOption}
transactionConfirming={showTransactionConfirming}
canVote={!!userCanVote}
Expand Down
2 changes: 1 addition & 1 deletion plugins/tokenVoting/utils/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type ProposalInputs = {
proposalId: bigint;
};

enum VotingMode {
export enum VotingMode {
Standard,
EarlyExecution,
VoteReplacement,
Expand Down

0 comments on commit 5dfb90d

Please sign in to comment.