@leofcoin/standards 0.2.4 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/exports/private-voting.js +16 -5
- package/exports/public-voting.js +42 -25
- package/exports/roles.js +1 -1
- package/exports/token-receiver.d.ts +3 -3
- package/exports/token-receiver.js +1 -0
- package/exports/token.d.ts +6 -9
- package/exports/token.js +1 -1
- package/exports/voting/private-voting.d.ts +4 -3
- package/exports/voting/public-voting.d.ts +7 -43
- package/exports/voting/voting.d.ts +43 -0
- package/package.json +1 -1
- package/src/decorators/time.ts +9 -0
- package/src/roles.ts +1 -1
- package/src/token-receiver.ts +2 -3
- package/src/token.ts +6 -7
- package/src/voting/interfaces/i-private-voting.ts +4 -0
- package/src/voting/private-voting.ts +17 -7
- package/src/voting/public-voting.ts +7 -109
- package/src/voting/voting.ts +122 -0
- package/tsconfig.json +1 -6
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import ContractCreator from './contract-creator.js';
|
|
2
|
+
|
|
3
|
+
class PrivateVoting extends ContractCreator {
|
|
2
4
|
#voters;
|
|
3
5
|
#votes;
|
|
4
6
|
#votingDisabled;
|
|
7
|
+
#votingDuration = 172800000;
|
|
5
8
|
constructor(state) {
|
|
9
|
+
super(state);
|
|
6
10
|
if (state) {
|
|
7
11
|
this.#voters = state.voters;
|
|
8
12
|
this.#votes = state.votes;
|
|
9
13
|
this.#votingDisabled = state.votingDisabled;
|
|
14
|
+
this.#votingDuration = state.votingDuration;
|
|
10
15
|
}
|
|
11
16
|
else {
|
|
12
17
|
this.#voters = [msg.sender];
|
|
@@ -25,7 +30,13 @@ class PrivateVoting {
|
|
|
25
30
|
*
|
|
26
31
|
*/
|
|
27
32
|
get state() {
|
|
28
|
-
return {
|
|
33
|
+
return {
|
|
34
|
+
...super.state,
|
|
35
|
+
voters: this.#voters,
|
|
36
|
+
votes: this.#votes,
|
|
37
|
+
votingDisabled: this.#votingDisabled,
|
|
38
|
+
votingDuration: this.#votingDuration
|
|
39
|
+
};
|
|
29
40
|
}
|
|
30
41
|
get inProgress() {
|
|
31
42
|
return Object.entries(this.#votes)
|
|
@@ -101,14 +112,14 @@ class PrivateVoting {
|
|
|
101
112
|
if (this.#voters.length === 1)
|
|
102
113
|
this.#disableVoting();
|
|
103
114
|
else {
|
|
104
|
-
this.createVote(`disable voting`, `Warning this disables all voting features forever`, new Date().getTime() +
|
|
115
|
+
this.createVote(`disable voting`, `Warning this disables all voting features forever`, new Date().getTime() + this.#votingDuration, '#disableVoting', []);
|
|
105
116
|
}
|
|
106
117
|
}
|
|
107
118
|
grantVotingPower(address, voteId) {
|
|
108
119
|
if (this.#voters.length === 1 && this.canVote(msg.sender))
|
|
109
120
|
this.#grantVotingPower(address);
|
|
110
121
|
else {
|
|
111
|
-
this.createVote(`grant voting power to ${address}`, `Should we grant ${address} voting power?`, new Date().getTime() +
|
|
122
|
+
this.createVote(`grant voting power to ${address}`, `Should we grant ${address} voting power?`, new Date().getTime() + this.#votingDuration, '#grantVotingPower', [address]);
|
|
112
123
|
}
|
|
113
124
|
}
|
|
114
125
|
revokeVotingPower(address, voteId) {
|
|
@@ -119,7 +130,7 @@ class PrivateVoting {
|
|
|
119
130
|
if (this.#voters.length === 1)
|
|
120
131
|
this.#revokeVotingPower(address);
|
|
121
132
|
else {
|
|
122
|
-
this.createVote(`revoke voting power for ${address}`, `Should we revoke ${address} it's voting power?`, new Date().getTime() +
|
|
133
|
+
this.createVote(`revoke voting power for ${address}`, `Should we revoke ${address} it's voting power?`, new Date().getTime() + this.#votingDuration, '#revokeVotingPower', [address]);
|
|
123
134
|
}
|
|
124
135
|
}
|
|
125
136
|
sync() {
|
package/exports/public-voting.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
#
|
|
6
|
-
#votingDisabled;
|
|
1
|
+
import ContractCreator from './contract-creator.js';
|
|
2
|
+
|
|
3
|
+
class Voting extends ContractCreator {
|
|
4
|
+
#votes = {};
|
|
5
|
+
#votingDisabled = false;
|
|
7
6
|
#votingDuration = 172800000;
|
|
8
7
|
constructor(state) {
|
|
8
|
+
super(state);
|
|
9
9
|
if (state) {
|
|
10
10
|
this.#votes = state.votes;
|
|
11
11
|
this.#votingDisabled = state.votingDisabled;
|
|
12
|
+
this.#votingDuration = state.votingDuration;
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
get votes() {
|
|
@@ -20,18 +21,25 @@ class PublicVoting {
|
|
|
20
21
|
get votingDisabled() {
|
|
21
22
|
return this.#votingDisabled;
|
|
22
23
|
}
|
|
23
|
-
/**
|
|
24
|
-
*
|
|
25
|
-
*/
|
|
26
24
|
get state() {
|
|
27
|
-
return {
|
|
25
|
+
return {
|
|
26
|
+
...super.state,
|
|
27
|
+
votes: this.#votes,
|
|
28
|
+
votingDisabled: this.#votingDisabled,
|
|
29
|
+
votingDuration: this.#votingDuration
|
|
30
|
+
};
|
|
28
31
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
#canVote() {
|
|
33
|
+
// @ts-expect-error
|
|
34
|
+
return this._canVote?.();
|
|
35
|
+
}
|
|
36
|
+
#beforeVote() {
|
|
37
|
+
// @ts-expect-error
|
|
38
|
+
return this._beforeVote?.();
|
|
39
|
+
}
|
|
40
|
+
#afterVote() {
|
|
41
|
+
// @ts-expect-error
|
|
42
|
+
return this._afterVote?.();
|
|
35
43
|
}
|
|
36
44
|
/**
|
|
37
45
|
* create vote
|
|
@@ -52,14 +60,6 @@ class PublicVoting {
|
|
|
52
60
|
args
|
|
53
61
|
};
|
|
54
62
|
}
|
|
55
|
-
#canVote() {
|
|
56
|
-
// @ts-expect-error
|
|
57
|
-
return this._canVote?.();
|
|
58
|
-
}
|
|
59
|
-
#beforeVote() {
|
|
60
|
-
// @ts-expect-error
|
|
61
|
-
return this._beforeVote?.();
|
|
62
|
-
}
|
|
63
63
|
#endVoting(voteId) {
|
|
64
64
|
let agree = Object.values(this.#votes[voteId].results).filter((result) => result === 1);
|
|
65
65
|
let disagree = Object.values(this.#votes[voteId].results).filter((result) => result === 0);
|
|
@@ -82,6 +82,14 @@ class PublicVoting {
|
|
|
82
82
|
throw new Error(`Not allowed to vote`);
|
|
83
83
|
await this.#beforeVote();
|
|
84
84
|
this.#votes[voteId][msg.sender] = vote;
|
|
85
|
+
await this.#afterVote();
|
|
86
|
+
}
|
|
87
|
+
get votesInProgress() {
|
|
88
|
+
return Object.entries(this.#votes)
|
|
89
|
+
.filter(([id, vote]) => !vote.finished)
|
|
90
|
+
.map(([id, vote]) => {
|
|
91
|
+
return { ...vote, id };
|
|
92
|
+
});
|
|
85
93
|
}
|
|
86
94
|
#disableVoting() {
|
|
87
95
|
this.#votingDisabled = true;
|
|
@@ -94,11 +102,20 @@ class PublicVoting {
|
|
|
94
102
|
}
|
|
95
103
|
}
|
|
96
104
|
_sync() {
|
|
97
|
-
for (const vote of this.
|
|
105
|
+
for (const vote of this.votesInProgress) {
|
|
98
106
|
if (vote.endTime < new Date().getTime())
|
|
99
107
|
this.#endVoting(vote.id);
|
|
100
108
|
}
|
|
101
109
|
}
|
|
102
110
|
}
|
|
103
111
|
|
|
112
|
+
/**
|
|
113
|
+
* allows everybody that has a balance greater or equeal then/to tokenAmountToReceive to vote
|
|
114
|
+
*/
|
|
115
|
+
class PublicVoting extends Voting {
|
|
116
|
+
constructor(state) {
|
|
117
|
+
super(state);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
104
121
|
export { PublicVoting as default };
|
package/exports/roles.js
CHANGED
|
@@ -15,7 +15,7 @@ class Roles extends ContractCreator {
|
|
|
15
15
|
// also allows roles to be loaded from the stateStore
|
|
16
16
|
// carefull when including the roles make sure to add the owner
|
|
17
17
|
// because no roles are granted by default when using custom roles
|
|
18
|
-
if (state
|
|
18
|
+
if (state?.roles) {
|
|
19
19
|
if (state.roles instanceof Object) {
|
|
20
20
|
this.#roles = { ...state.roles, ...this.#roles };
|
|
21
21
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { IPublicVoting } from './voting/interfaces/i-public-voting.js';
|
|
2
|
-
import PublicVoting from './voting/public-voting.js';
|
|
3
|
-
|
|
4
|
-
export interface TokenReceiverState extends VotingState {
|
|
2
|
+
import PublicVoting, { PublicVotingState } from './voting/public-voting.js';
|
|
3
|
+
export interface TokenReceiverState extends PublicVotingState {
|
|
5
4
|
tokenToReceive: address;
|
|
6
5
|
tokenReceiver: address;
|
|
7
6
|
tokenAmountToReceive: typeof BigNumber;
|
|
@@ -23,6 +22,7 @@ export default class TokenReceiver extends PublicVoting implements IPublicVoting
|
|
|
23
22
|
};
|
|
24
23
|
votingDisabled: boolean;
|
|
25
24
|
votingDuration: number;
|
|
25
|
+
contractCreator: string;
|
|
26
26
|
};
|
|
27
27
|
/**
|
|
28
28
|
* check if sender can pay
|
package/exports/token.d.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import Roles from './roles.js';
|
|
2
|
-
export declare
|
|
3
|
-
roles: {
|
|
4
|
-
[index: string]: address[];
|
|
5
|
-
};
|
|
1
|
+
import Roles, { RolesState } from './roles.js';
|
|
2
|
+
export declare interface TokenState extends RolesState {
|
|
6
3
|
holders: BigNumberish;
|
|
7
4
|
balances: {
|
|
8
5
|
[address: address]: BigNumberish;
|
|
@@ -13,19 +10,19 @@ export declare type TokenState = {
|
|
|
13
10
|
};
|
|
14
11
|
};
|
|
15
12
|
totalSupply: BigNumberish;
|
|
16
|
-
}
|
|
13
|
+
}
|
|
17
14
|
export default class Token extends Roles {
|
|
18
15
|
#private;
|
|
19
16
|
constructor(name: string, symbol: string, decimals?: number, state?: TokenState);
|
|
20
17
|
/**
|
|
21
18
|
* @return {Object} {holders, balances, ...}
|
|
22
19
|
*/
|
|
23
|
-
get state():
|
|
20
|
+
get state(): TokenState;
|
|
24
21
|
get totalSupply(): BigNumberish;
|
|
25
22
|
get name(): string;
|
|
26
23
|
get symbol(): string;
|
|
27
|
-
get holders():
|
|
28
|
-
get balances():
|
|
24
|
+
get holders(): TokenState['holders'];
|
|
25
|
+
get balances(): TokenState['balances'];
|
|
29
26
|
get approvals(): {
|
|
30
27
|
[owner: string]: {
|
|
31
28
|
[operator: string]: import("@ethersproject/bignumber").BigNumber;
|
package/exports/token.js
CHANGED
|
@@ -31,7 +31,7 @@ class Token extends Roles {
|
|
|
31
31
|
throw new Error(`name undefined`);
|
|
32
32
|
if (!symbol)
|
|
33
33
|
throw new Error(`symbol undefined`);
|
|
34
|
-
super(state
|
|
34
|
+
super(state);
|
|
35
35
|
if (state) {
|
|
36
36
|
this.#balances = restoreBalances(state.balances);
|
|
37
37
|
this.#approvals = restoreApprovals(state.approvals);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import ContractCreator, { ContractCreatorState } from '../contract-creator.js';
|
|
1
2
|
import { VoteResult, VoteView, VotingState } from './types.js';
|
|
2
|
-
export interface PrivateVotingState extends VotingState {
|
|
3
|
+
export interface PrivateVotingState extends VotingState, ContractCreatorState {
|
|
3
4
|
voters: any;
|
|
4
5
|
}
|
|
5
|
-
export default class PrivateVoting {
|
|
6
|
+
export default class PrivateVoting extends ContractCreator {
|
|
6
7
|
#private;
|
|
7
8
|
constructor(state: PrivateVotingState);
|
|
8
9
|
get votes(): {
|
|
@@ -13,7 +14,7 @@ export default class PrivateVoting {
|
|
|
13
14
|
/**
|
|
14
15
|
*
|
|
15
16
|
*/
|
|
16
|
-
get state():
|
|
17
|
+
get state(): PrivateVotingState;
|
|
17
18
|
get inProgress(): VoteView[];
|
|
18
19
|
/**
|
|
19
20
|
* create vote
|
|
@@ -1,47 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ContractCreatorState } from '../contract-creator.js';
|
|
2
|
+
import { VotingState } from './types.js';
|
|
3
|
+
import Voting from './voting.js';
|
|
4
|
+
export declare interface PublicVotingState extends VotingState, ContractCreatorState {
|
|
5
|
+
}
|
|
2
6
|
/**
|
|
3
7
|
* allows everybody that has a balance greater or equeal then/to tokenAmountToReceive to vote
|
|
4
8
|
*/
|
|
5
|
-
export default class PublicVoting {
|
|
6
|
-
|
|
7
|
-
constructor(state: VotingState);
|
|
8
|
-
get votes(): {
|
|
9
|
-
[x: string]: import("./types.js").Vote;
|
|
10
|
-
};
|
|
11
|
-
get votingDuration(): number;
|
|
12
|
-
get votingDisabled(): boolean;
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
15
|
-
*/
|
|
16
|
-
get state(): {
|
|
17
|
-
votes: {
|
|
18
|
-
[id: string]: import("./types.js").Vote;
|
|
19
|
-
};
|
|
20
|
-
votingDisabled: boolean;
|
|
21
|
-
votingDuration: number;
|
|
22
|
-
};
|
|
23
|
-
get inProgress(): {
|
|
24
|
-
id: string;
|
|
25
|
-
title: string;
|
|
26
|
-
method: string;
|
|
27
|
-
args: any[];
|
|
28
|
-
description: string;
|
|
29
|
-
endTime: number;
|
|
30
|
-
results?: {
|
|
31
|
-
[address: string]: VoteResult;
|
|
32
|
-
};
|
|
33
|
-
finished?: boolean;
|
|
34
|
-
enoughVotes?: boolean;
|
|
35
|
-
}[];
|
|
36
|
-
/**
|
|
37
|
-
* create vote
|
|
38
|
-
* @param {string} vote
|
|
39
|
-
* @param {string} description
|
|
40
|
-
* @param {number} endTime
|
|
41
|
-
* @param {string} method function to run when agree amount is bigger
|
|
42
|
-
*/
|
|
43
|
-
createVote(title: string, description: string, endTime: EpochTimeStamp, method: string, args?: any[]): void;
|
|
44
|
-
vote(voteId: string, vote: VoteResult): Promise<void>;
|
|
45
|
-
disableVoting(): void;
|
|
46
|
-
_sync(): void;
|
|
9
|
+
export default class PublicVoting extends Voting {
|
|
10
|
+
constructor(state: PublicVotingState);
|
|
47
11
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import ContractCreator from '../contract-creator.js';
|
|
2
|
+
import { Vote, VoteResult } from './types.js';
|
|
3
|
+
export default class Voting extends ContractCreator {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(state: any);
|
|
6
|
+
get votes(): {
|
|
7
|
+
[x: string]: Vote;
|
|
8
|
+
};
|
|
9
|
+
get votingDuration(): number;
|
|
10
|
+
get votingDisabled(): boolean;
|
|
11
|
+
get state(): {
|
|
12
|
+
votes: {
|
|
13
|
+
[id: string]: Vote;
|
|
14
|
+
};
|
|
15
|
+
votingDisabled: boolean;
|
|
16
|
+
votingDuration: number;
|
|
17
|
+
contractCreator: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* create vote
|
|
21
|
+
* @param {string} vote
|
|
22
|
+
* @param {string} description
|
|
23
|
+
* @param {number} endTime
|
|
24
|
+
* @param {string} method function to run when agree amount is bigger
|
|
25
|
+
*/
|
|
26
|
+
createVote(title: string, description: string, endTime: EpochTimeStamp, method: string, args?: any[]): void;
|
|
27
|
+
vote(voteId: string, vote: VoteResult): Promise<void>;
|
|
28
|
+
get votesInProgress(): {
|
|
29
|
+
id: string;
|
|
30
|
+
title: string;
|
|
31
|
+
method: string;
|
|
32
|
+
args: any[];
|
|
33
|
+
description: string;
|
|
34
|
+
endTime: number;
|
|
35
|
+
results?: {
|
|
36
|
+
[address: string]: VoteResult;
|
|
37
|
+
};
|
|
38
|
+
finished?: boolean;
|
|
39
|
+
enoughVotes?: boolean;
|
|
40
|
+
}[];
|
|
41
|
+
disableVoting(): void;
|
|
42
|
+
_sync(): void;
|
|
43
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function time(target, descriptor) {
|
|
2
|
+
console.log({ descriptor }, { target })
|
|
3
|
+
if (descriptor.kind !== 'method') throw new Error(`expected ${descriptor.name} to be a method`)
|
|
4
|
+
descriptor.addInitializer(function () {
|
|
5
|
+
pubsub.subscribe('time-interval', (value) => {
|
|
6
|
+
this.onTimeChange?.(value)
|
|
7
|
+
})
|
|
8
|
+
})
|
|
9
|
+
}
|
package/src/roles.ts
CHANGED
|
@@ -20,7 +20,7 @@ export default class Roles extends ContractCreator {
|
|
|
20
20
|
// also allows roles to be loaded from the stateStore
|
|
21
21
|
// carefull when including the roles make sure to add the owner
|
|
22
22
|
// because no roles are granted by default when using custom roles
|
|
23
|
-
if (state
|
|
23
|
+
if (state?.roles) {
|
|
24
24
|
if (state.roles instanceof Object) {
|
|
25
25
|
this.#roles = { ...state.roles, ...this.#roles }
|
|
26
26
|
} else {
|
package/src/token-receiver.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { IPublicVoting } from './voting/interfaces/i-public-voting.js'
|
|
2
|
-
import PublicVoting from './voting/public-voting.js'
|
|
3
|
-
import { VotingState } from './voting/types.js'
|
|
2
|
+
import PublicVoting, { PublicVotingState } from './voting/public-voting.js'
|
|
4
3
|
|
|
5
|
-
export interface TokenReceiverState extends
|
|
4
|
+
export interface TokenReceiverState extends PublicVotingState {
|
|
6
5
|
tokenToReceive: address
|
|
7
6
|
tokenReceiver: address
|
|
8
7
|
tokenAmountToReceive: typeof BigNumber
|
package/src/token.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { restoreApprovals, restoreBalances } from './helpers.js'
|
|
2
|
-
import Roles from './roles.js'
|
|
2
|
+
import Roles, { RolesState } from './roles.js'
|
|
3
3
|
|
|
4
|
-
export declare
|
|
5
|
-
roles: { [index: string]: address[] }
|
|
4
|
+
export declare interface TokenState extends RolesState {
|
|
6
5
|
holders: BigNumberish
|
|
7
6
|
balances: { [address: address]: BigNumberish }
|
|
8
7
|
approvals: { [owner: address]: { [operator: address]: BigNumberish } }
|
|
@@ -40,7 +39,7 @@ export default class Token extends Roles {
|
|
|
40
39
|
if (!name) throw new Error(`name undefined`)
|
|
41
40
|
if (!symbol) throw new Error(`symbol undefined`)
|
|
42
41
|
|
|
43
|
-
super(state
|
|
42
|
+
super(state)
|
|
44
43
|
|
|
45
44
|
if (state) {
|
|
46
45
|
this.#balances = restoreBalances(state.balances)
|
|
@@ -60,7 +59,7 @@ export default class Token extends Roles {
|
|
|
60
59
|
/**
|
|
61
60
|
* @return {Object} {holders, balances, ...}
|
|
62
61
|
*/
|
|
63
|
-
get state():
|
|
62
|
+
get state(): TokenState {
|
|
64
63
|
return {
|
|
65
64
|
...super.state,
|
|
66
65
|
holders: this.holders,
|
|
@@ -82,11 +81,11 @@ export default class Token extends Roles {
|
|
|
82
81
|
return this.#symbol
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
get holders():
|
|
84
|
+
get holders(): TokenState['holders'] {
|
|
86
85
|
return this.#holders
|
|
87
86
|
}
|
|
88
87
|
|
|
89
|
-
get balances():
|
|
88
|
+
get balances(): TokenState['balances'] {
|
|
90
89
|
return { ...this.#balances }
|
|
91
90
|
}
|
|
92
91
|
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
+
import ContractCreator, { ContractCreatorState } from '../contract-creator.js'
|
|
1
2
|
import { VoteResult, VoteView, VotingState } from './types.js'
|
|
2
3
|
|
|
3
|
-
export interface PrivateVotingState extends VotingState {
|
|
4
|
+
export interface PrivateVotingState extends VotingState, ContractCreatorState {
|
|
4
5
|
voters
|
|
5
6
|
}
|
|
6
7
|
|
|
7
|
-
export default class PrivateVoting {
|
|
8
|
+
export default class PrivateVoting extends ContractCreator {
|
|
8
9
|
#voters: PrivateVotingState['voters']
|
|
9
10
|
#votes: PrivateVotingState['votes']
|
|
10
11
|
#votingDisabled: boolean
|
|
12
|
+
#votingDuration: number = 172800000
|
|
11
13
|
|
|
12
14
|
constructor(state: PrivateVotingState) {
|
|
15
|
+
super(state)
|
|
13
16
|
if (state) {
|
|
14
17
|
this.#voters = state.voters
|
|
15
18
|
this.#votes = state.votes
|
|
16
19
|
this.#votingDisabled = state.votingDisabled
|
|
20
|
+
this.#votingDuration = state.votingDuration
|
|
17
21
|
} else {
|
|
18
22
|
this.#voters = [msg.sender]
|
|
19
23
|
}
|
|
@@ -34,8 +38,14 @@ export default class PrivateVoting {
|
|
|
34
38
|
/**
|
|
35
39
|
*
|
|
36
40
|
*/
|
|
37
|
-
get state():
|
|
38
|
-
return {
|
|
41
|
+
get state(): PrivateVotingState {
|
|
42
|
+
return {
|
|
43
|
+
...super.state,
|
|
44
|
+
voters: this.#voters,
|
|
45
|
+
votes: this.#votes,
|
|
46
|
+
votingDisabled: this.#votingDisabled,
|
|
47
|
+
votingDuration: this.#votingDuration
|
|
48
|
+
}
|
|
39
49
|
}
|
|
40
50
|
|
|
41
51
|
get inProgress(): VoteView[] {
|
|
@@ -116,7 +126,7 @@ export default class PrivateVoting {
|
|
|
116
126
|
this.createVote(
|
|
117
127
|
`disable voting`,
|
|
118
128
|
`Warning this disables all voting features forever`,
|
|
119
|
-
new Date().getTime() +
|
|
129
|
+
new Date().getTime() + this.#votingDuration,
|
|
120
130
|
'#disableVoting',
|
|
121
131
|
[]
|
|
122
132
|
)
|
|
@@ -129,7 +139,7 @@ export default class PrivateVoting {
|
|
|
129
139
|
this.createVote(
|
|
130
140
|
`grant voting power to ${address}`,
|
|
131
141
|
`Should we grant ${address} voting power?`,
|
|
132
|
-
new Date().getTime() +
|
|
142
|
+
new Date().getTime() + this.#votingDuration,
|
|
133
143
|
'#grantVotingPower',
|
|
134
144
|
[address]
|
|
135
145
|
)
|
|
@@ -145,7 +155,7 @@ export default class PrivateVoting {
|
|
|
145
155
|
this.createVote(
|
|
146
156
|
`revoke voting power for ${address}`,
|
|
147
157
|
`Should we revoke ${address} it's voting power?`,
|
|
148
|
-
new Date().getTime() +
|
|
158
|
+
new Date().getTime() + this.#votingDuration,
|
|
149
159
|
'#revokeVotingPower',
|
|
150
160
|
[address]
|
|
151
161
|
)
|
|
@@ -1,116 +1,14 @@
|
|
|
1
|
+
import ContractCreator, { ContractCreatorState } from '../contract-creator.js'
|
|
1
2
|
import { VotingState, VoteResult } from './types.js'
|
|
3
|
+
import Voting from './voting.js'
|
|
4
|
+
|
|
5
|
+
export declare interface PublicVotingState extends VotingState, ContractCreatorState {}
|
|
2
6
|
|
|
3
7
|
/**
|
|
4
8
|
* allows everybody that has a balance greater or equeal then/to tokenAmountToReceive to vote
|
|
5
9
|
*/
|
|
6
|
-
export default class PublicVoting {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
#votingDuration: number = 172800000
|
|
10
|
-
|
|
11
|
-
constructor(state: VotingState) {
|
|
12
|
-
if (state) {
|
|
13
|
-
this.#votes = state.votes
|
|
14
|
-
this.#votingDisabled = state.votingDisabled
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
get votes() {
|
|
19
|
-
return { ...this.#votes }
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
get votingDuration() {
|
|
23
|
-
return this.#votingDuration
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
get votingDisabled() {
|
|
27
|
-
return this.#votingDisabled
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
*
|
|
32
|
-
*/
|
|
33
|
-
get state() {
|
|
34
|
-
return { votes: this.#votes, votingDisabled: this.#votingDisabled, votingDuration: this.#votingDuration }
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
get inProgress() {
|
|
38
|
-
return Object.entries(this.#votes)
|
|
39
|
-
.filter(([id, vote]) => !vote.finished)
|
|
40
|
-
.map(([id, vote]) => {
|
|
41
|
-
return { ...vote, id }
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* create vote
|
|
46
|
-
* @param {string} vote
|
|
47
|
-
* @param {string} description
|
|
48
|
-
* @param {number} endTime
|
|
49
|
-
* @param {string} method function to run when agree amount is bigger
|
|
50
|
-
*/
|
|
51
|
-
|
|
52
|
-
createVote(title: string, description: string, endTime: EpochTimeStamp, method: string, args: any[] = []) {
|
|
53
|
-
if (!this.#canVote()) throw new Error(`Not allowed to create a vote`)
|
|
54
|
-
const id = crypto.randomUUID()
|
|
55
|
-
this.#votes[id] = {
|
|
56
|
-
title,
|
|
57
|
-
description,
|
|
58
|
-
method,
|
|
59
|
-
endTime,
|
|
60
|
-
args
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
#canVote() {
|
|
65
|
-
// @ts-expect-error
|
|
66
|
-
return this._canVote?.()
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
#beforeVote() {
|
|
70
|
-
// @ts-expect-error
|
|
71
|
-
return this._beforeVote?.()
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
#endVoting(voteId) {
|
|
75
|
-
let agree = Object.values(this.#votes[voteId].results).filter((result) => result === 1)
|
|
76
|
-
let disagree = Object.values(this.#votes[voteId].results).filter((result) => result === 0)
|
|
77
|
-
if (agree.length > disagree.length && this.#votes[voteId].enoughVotes)
|
|
78
|
-
this[this.#votes[voteId].method](...this.#votes[voteId].args)
|
|
79
|
-
this.#votes[voteId].finished = true
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
async vote(voteId: string, vote: VoteResult) {
|
|
83
|
-
vote = Number(vote) as VoteResult
|
|
84
|
-
if (vote !== 0 && vote !== 0.5 && vote !== 1) throw new Error(`invalid vote value ${vote}`)
|
|
85
|
-
if (!this.#votes[voteId]) throw new Error(`Nothing found for ${voteId}`)
|
|
86
|
-
const ended = new Date().getTime() > this.#votes[voteId].endTime
|
|
87
|
-
if (ended && !this.#votes[voteId].finished) this.#endVoting(voteId)
|
|
88
|
-
if (ended) throw new Error('voting already ended')
|
|
89
|
-
if (!this.#canVote()) throw new Error(`Not allowed to vote`)
|
|
90
|
-
await this.#beforeVote()
|
|
91
|
-
this.#votes[voteId][msg.sender] = vote
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
#disableVoting() {
|
|
95
|
-
this.#votingDisabled = true
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
disableVoting() {
|
|
99
|
-
if (!this.#canVote()) throw new Error('not a allowed')
|
|
100
|
-
else {
|
|
101
|
-
this.createVote(
|
|
102
|
-
`disable voting`,
|
|
103
|
-
`Warning this disables all voting features forever`,
|
|
104
|
-
new Date().getTime() + this.#votingDuration,
|
|
105
|
-
'#disableVoting',
|
|
106
|
-
[]
|
|
107
|
-
)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
_sync() {
|
|
112
|
-
for (const vote of this.inProgress) {
|
|
113
|
-
if (vote.endTime < new Date().getTime()) this.#endVoting(vote.id)
|
|
114
|
-
}
|
|
10
|
+
export default class PublicVoting extends Voting {
|
|
11
|
+
constructor(state: PublicVotingState) {
|
|
12
|
+
super(state)
|
|
115
13
|
}
|
|
116
14
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import ContractCreator, { ContractCreatorState } from '../contract-creator.js'
|
|
2
|
+
import { Vote, VoteResult, VoteView, VotingState } from './types.js'
|
|
3
|
+
export default class Voting extends ContractCreator {
|
|
4
|
+
#votes: VotingState['votes'] = {}
|
|
5
|
+
#votingDisabled: boolean = false
|
|
6
|
+
#votingDuration: number = 172800000
|
|
7
|
+
constructor(state) {
|
|
8
|
+
super(state)
|
|
9
|
+
if (state) {
|
|
10
|
+
this.#votes = state.votes
|
|
11
|
+
this.#votingDisabled = state.votingDisabled
|
|
12
|
+
this.#votingDuration = state.votingDuration
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
get votes() {
|
|
17
|
+
return { ...this.#votes }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
get votingDuration() {
|
|
21
|
+
return this.#votingDuration
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
get votingDisabled() {
|
|
25
|
+
return this.#votingDisabled
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get state() {
|
|
29
|
+
return {
|
|
30
|
+
...super.state,
|
|
31
|
+
votes: this.#votes,
|
|
32
|
+
votingDisabled: this.#votingDisabled,
|
|
33
|
+
votingDuration: this.#votingDuration
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#canVote() {
|
|
38
|
+
// @ts-expect-error
|
|
39
|
+
return this._canVote?.()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#beforeVote() {
|
|
43
|
+
// @ts-expect-error
|
|
44
|
+
return this._beforeVote?.()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#afterVote() {
|
|
48
|
+
// @ts-expect-error
|
|
49
|
+
return this._afterVote?.()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* create vote
|
|
54
|
+
* @param {string} vote
|
|
55
|
+
* @param {string} description
|
|
56
|
+
* @param {number} endTime
|
|
57
|
+
* @param {string} method function to run when agree amount is bigger
|
|
58
|
+
*/
|
|
59
|
+
createVote(title: string, description: string, endTime: EpochTimeStamp, method: string, args: any[] = []) {
|
|
60
|
+
if (!this.#canVote()) throw new Error(`Not allowed to create a vote`)
|
|
61
|
+
const id = crypto.randomUUID()
|
|
62
|
+
this.#votes[id] = {
|
|
63
|
+
title,
|
|
64
|
+
description,
|
|
65
|
+
method,
|
|
66
|
+
endTime,
|
|
67
|
+
args
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#endVoting(voteId) {
|
|
72
|
+
let agree = Object.values(this.#votes[voteId].results).filter((result) => result === 1)
|
|
73
|
+
let disagree = Object.values(this.#votes[voteId].results).filter((result) => result === 0)
|
|
74
|
+
if (agree.length > disagree.length && this.#votes[voteId].enoughVotes)
|
|
75
|
+
this[this.#votes[voteId].method](...this.#votes[voteId].args)
|
|
76
|
+
this.#votes[voteId].finished = true
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async vote(voteId: string, vote: VoteResult) {
|
|
80
|
+
vote = Number(vote) as VoteResult
|
|
81
|
+
if (vote !== 0 && vote !== 0.5 && vote !== 1) throw new Error(`invalid vote value ${vote}`)
|
|
82
|
+
if (!this.#votes[voteId]) throw new Error(`Nothing found for ${voteId}`)
|
|
83
|
+
const ended = new Date().getTime() > this.#votes[voteId].endTime
|
|
84
|
+
if (ended && !this.#votes[voteId].finished) this.#endVoting(voteId)
|
|
85
|
+
if (ended) throw new Error('voting already ended')
|
|
86
|
+
if (!this.#canVote()) throw new Error(`Not allowed to vote`)
|
|
87
|
+
await this.#beforeVote()
|
|
88
|
+
|
|
89
|
+
this.#votes[voteId][msg.sender] = vote
|
|
90
|
+
await this.#afterVote()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get votesInProgress() {
|
|
94
|
+
return Object.entries(this.#votes)
|
|
95
|
+
.filter(([id, vote]) => !vote.finished)
|
|
96
|
+
.map(([id, vote]) => {
|
|
97
|
+
return { ...vote, id }
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
#disableVoting() {
|
|
101
|
+
this.#votingDisabled = true
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
disableVoting() {
|
|
105
|
+
if (!this.#canVote()) throw new Error('not a allowed')
|
|
106
|
+
else {
|
|
107
|
+
this.createVote(
|
|
108
|
+
`disable voting`,
|
|
109
|
+
`Warning this disables all voting features forever`,
|
|
110
|
+
new Date().getTime() + this.#votingDuration,
|
|
111
|
+
'#disableVoting',
|
|
112
|
+
[]
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
_sync() {
|
|
118
|
+
for (const vote of this.votesInProgress) {
|
|
119
|
+
if (vote.endTime < new Date().getTime()) this.#endVoting(vote.id)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -7,10 +7,5 @@
|
|
|
7
7
|
"declaration": true,
|
|
8
8
|
"declarationDir": "./exports"
|
|
9
9
|
},
|
|
10
|
-
"include": [
|
|
11
|
-
"./src/*",
|
|
12
|
-
"./node_modules/@leofcoin/global-types/*",
|
|
13
|
-
"src/voting/private-voting.ts",
|
|
14
|
-
"src/voting/public-voting.ts"
|
|
15
|
-
]
|
|
10
|
+
"include": ["./src/*", "./node_modules/@leofcoin/global-types/*"]
|
|
16
11
|
}
|