-
Notifications
You must be signed in to change notification settings - Fork 6
/
quadratic.ts
142 lines (128 loc) · 3.7 KB
/
quadratic.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import chalk from 'chalk';
import { Wallet } from '@ethersproject/wallet';
import { IVoteType, OffchainCensus, UnpublishedElection, WeightedCensus } from '@vocdoni/sdk';
import { getRandomVoters } from './utils/utils';
import { createElection, executeElection } from './utils/election-process';
/**
* Example of quadratic voting election
*
* https://developer.vocdoni.io/protocol/ballot#quadratic-voting
*/
/**
* Set the total number of random voters.
*/
const VOTERS_NUM = 10;
/**
* Define the exponent for quadratic voting calculation. In the context of quadratic voting, this value
* is usually set to 2. This exponent determines the cost of a vote. For example, if a voter assigns 2 credits to an option,
* the cost of that vote would be 2^2 = 4.
*/
const COST_EXPONENT = 2;
/**
* Defines the total amount of credits available to each voter for casting their votes.
* In this example, every voter is assumed to have an equal amount of credits. However, in a different scenario,
* each voter could be allotted a varying number of credits depending on their weight in a weighted census.
*/
const CREDITS = 14;
/**
* An array representing a single voter's allocation of credits towards various options.
*
* For example, the array [1, 0, 3, 2] signifies:
*
* - `1` credit assigned to option 0,
* - `0` credit assigned to option 1,
* - `3` credit assigned to option 2,
* - `2` credit assigned to option 3,
*
* The cost of these votes in a quadratic voting system would be:
*
* ```
* 1^2 = 1 (Cost for option 0)
* 0^2 = 0 (Cost for option 1)
* 3^2 = 9 (Cost for option 2)
* 2^2 = 4 (Cost for option 3)
* Total = 14 (Total cost of votes)
* ```
*
* The total cost of the votes must not exceed the total `CREDITS` available to the voter.
*
* Given these parameters, an election involving 10 voters would yield the following results:
*
* ```
* [[ 10, 0, 30, 20 ]]
* ```
*/
const VOTE_ARRAY = [1, 0, 3, 2];
/**
* Must be 0 for quadratic elections
*/
const MAX_VALUE = 0;
/**
* Have to be the choices length
*/
const MAX_COUNT = 4;
/**
* An example configuration for setting up a quadratic voting system.
*/
const VOTE_OPTIONS: IVoteType = {
maxValue: MAX_VALUE,
maxCount: MAX_COUNT,
uniqueChoices: false,
costFromWeight: true, // This will set that the weight on a weighted census is actually the credits available
costExponent: COST_EXPONENT,
};
const _createElection = (census: OffchainCensus): UnpublishedElection => {
const election = createElection(
census,
VOTE_OPTIONS,
'Quadratic vote election',
'What NGO have to receive the credits?'
);
election.addQuestion("Select NGO's", 'Quadratic vote example', [
{
title: 'Greenpeace',
value: 0,
},
{
title: 'Red Cross',
value: 1,
},
{
title: 'MSF',
value: 2,
},
{
title: 'Amnesty',
value: 3,
},
]);
return election;
};
async function main() {
console.log('Creating census with some random wallets...');
const participants: Wallet[] = getRandomVoters(VOTERS_NUM);
const census = new WeightedCensus();
census.add(
participants.map((participant, index) => ({
key: participant.address,
weight: BigInt(CREDITS),
}))
);
console.log('Creating election...');
const election = _createElection(census);
await executeElection(election, participants, VOTE_ARRAY);
console.log(
'Expected results: ',
VOTE_ARRAY.map((value, i) => [String(value * VOTERS_NUM)])
);
console.log(chalk.yellow('This results only work if the VOTE_ARRAY is the same for all voters'));
}
main()
.then(() => {
console.log(chalk.green('Done ✅'));
process.exit(0);
})
.catch((err) => {
console.error(chalk.red(err));
process.exit(1);
});