diff --git a/apps/ui/src/components/EditorVotingType.vue b/apps/ui/src/components/EditorVotingType.vue index 1a099e9cd..e16141d78 100644 --- a/apps/ui/src/components/EditorVotingType.vue +++ b/apps/ui/src/components/EditorVotingType.vue @@ -20,6 +20,11 @@ const VOTING_TYPES_INFO = computed(() => ({ approval: { label: 'Approval voting', description: 'Voters can select multiple choices, each choice receiving full voting power.' + }, + 'ranked-choice': { + label: 'Ranked choice voting', + description: + 'Each voter may select and rank any number of choices. Results are calculated by instant-runoff counting method.' } })); diff --git a/apps/ui/src/components/ProposalVoteRankedChoice.vue b/apps/ui/src/components/ProposalVoteRankedChoice.vue new file mode 100644 index 000000000..6a335ed05 --- /dev/null +++ b/apps/ui/src/components/ProposalVoteRankedChoice.vue @@ -0,0 +1,49 @@ + + + + + + + + + #{{ index + 1 }} + + {{ proposal.choices[element - 1] }} + + + + + + + + + + Vote + + + diff --git a/apps/ui/src/helpers/constants.ts b/apps/ui/src/helpers/constants.ts index 67407f1f3..28d6b3369 100644 --- a/apps/ui/src/helpers/constants.ts +++ b/apps/ui/src/helpers/constants.ts @@ -25,4 +25,9 @@ export const COINGECKO_BASE_ASSETS = { export const MAX_SYMBOL_LENGTH = 12; export const BASIC_CHOICES = ['For', 'Against', 'Abstain']; -export const SUPPORTED_VOTING_TYPES: VoteType[] = ['basic', 'single-choice', 'approval'] as const; +export const SUPPORTED_VOTING_TYPES: VoteType[] = [ + 'basic', + 'single-choice', + 'approval', + 'ranked-choice' +] as const; diff --git a/apps/ui/src/networks/offchain/constants.ts b/apps/ui/src/networks/offchain/constants.ts index de9f84955..45078f769 100644 --- a/apps/ui/src/networks/offchain/constants.ts +++ b/apps/ui/src/networks/offchain/constants.ts @@ -19,6 +19,6 @@ export const EDITOR_PROPOSAL_VALIDATION_VOTING_STRATEGIES = []; export const EDITOR_EXECUTION_STRATEGIES = []; export const EDITOR_SNAPSHOT_OFFSET = 4; export const EDITOR_APP_NAME = 'snapshot-v2'; -export const EDITOR_VOTING_TYPES = ['basic', 'single-choice', 'approval']; +export const EDITOR_VOTING_TYPES = ['basic', 'single-choice', 'approval', 'ranked-choice']; export const DEFAULT_VOTING_DELAY = 60 * 60 * 24 * 7; diff --git a/apps/ui/src/networks/offchain/helpers.ts b/apps/ui/src/networks/offchain/helpers.ts index 07d015a83..144fe4c6b 100644 --- a/apps/ui/src/networks/offchain/helpers.ts +++ b/apps/ui/src/networks/offchain/helpers.ts @@ -11,7 +11,7 @@ export function getSdkChoice(type: string, choice: Choice): number | number[] { return choice as number; } - if (type === 'approval') { + if (type === 'approval' || type === 'ranked-choice') { return choice as number[]; } diff --git a/apps/ui/src/views/Proposal.vue b/apps/ui/src/views/Proposal.vue index 2d8e3e7d9..fac132d99 100644 --- a/apps/ui/src/views/Proposal.vue +++ b/apps/ui/src/views/Proposal.vue @@ -190,6 +190,12 @@ watchEffect(() => { :sending-type="sendingType" @vote="handleVoteClick" /> + diff --git a/packages/sx.js/src/clients/offchain/ethereum-sig/index.ts b/packages/sx.js/src/clients/offchain/ethereum-sig/index.ts index 057b4200b..beebdcb86 100644 --- a/packages/sx.js/src/clients/offchain/ethereum-sig/index.ts +++ b/packages/sx.js/src/clients/offchain/ethereum-sig/index.ts @@ -5,6 +5,7 @@ import { basicVoteTypes, singleChoiceVoteTypes, approvalVoteTypes, + rankedChoiceVoteTypes, updateProposalTypes, cancelProposalTypes } from './types'; @@ -169,6 +170,7 @@ export class EthereumSig { let voteType = basicVoteTypes; if (data.type === 'single-choice') voteType = singleChoiceVoteTypes; if (data.type === 'approval') voteType = approvalVoteTypes; + if (data.type === 'ranked-choice') voteType = rankedChoiceVoteTypes; const signatureData = await this.sign(signer, message, voteType); diff --git a/packages/sx.js/src/clients/offchain/ethereum-sig/types.ts b/packages/sx.js/src/clients/offchain/ethereum-sig/types.ts index a032e5c91..dde902791 100644 --- a/packages/sx.js/src/clients/offchain/ethereum-sig/types.ts +++ b/packages/sx.js/src/clients/offchain/ethereum-sig/types.ts @@ -31,6 +31,8 @@ export const approvalVoteTypes = { ] }; +export const rankedChoiceVoteTypes = approvalVoteTypes; + export const proposeTypes = { Proposal: [ { name: 'from', type: 'address' },