@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.
@@ -1,12 +1,17 @@
1
- class PrivateVoting {
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 { voters: this.#voters, votes: this.#votes, votingDisabled: this.#votingDisabled };
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() + 172800000, '#disableVoting', []);
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() + 172800000, '#grantVotingPower', [address]);
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() + 172800000, '#revokeVotingPower', [address]);
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() {
@@ -1,14 +1,15 @@
1
- /**
2
- * allows everybody that has a balance greater or equeal then/to tokenAmountToReceive to vote
3
- */
4
- class PublicVoting {
5
- #votes;
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 { votes: this.#votes, votingDisabled: this.#votingDisabled, votingDuration: this.#votingDuration };
25
+ return {
26
+ ...super.state,
27
+ votes: this.#votes,
28
+ votingDisabled: this.#votingDisabled,
29
+ votingDuration: this.#votingDuration
30
+ };
28
31
  }
29
- get inProgress() {
30
- return Object.entries(this.#votes)
31
- .filter(([id, vote]) => !vote.finished)
32
- .map(([id, vote]) => {
33
- return { ...vote, id };
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.inProgress) {
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.roles) {
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
- import { VotingState } from './voting/types.js';
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
@@ -1,4 +1,5 @@
1
1
  import PublicVoting from './public-voting.js';
2
+ import './contract-creator.js';
2
3
 
3
4
  class TokenReceiver extends PublicVoting {
4
5
  #tokenToReceive;
@@ -1,8 +1,5 @@
1
- import Roles from './roles.js';
2
- export declare type TokenState = {
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?.roles);
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 { VotingState, VoteResult } from './types.js';
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
- #private;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leofcoin/standards",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Contract standards",
5
5
  "type": "module",
6
6
  "exports": {
@@ -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.roles) {
23
+ if (state?.roles) {
24
24
  if (state.roles instanceof Object) {
25
25
  this.#roles = { ...state.roles, ...this.#roles }
26
26
  } else {
@@ -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 VotingState {
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 type TokenState = {
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?.roles)
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
 
@@ -0,0 +1,4 @@
1
+ export interface IPublicVoting {
2
+ _canVote(): Promise<any>
3
+ _beforeVote(): Promise<any>
4
+ }
@@ -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 { voters: this.#voters, votes: this.#votes, votingDisabled: this.#votingDisabled }
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() + 172800000,
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() + 172800000,
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() + 172800000,
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
- #votes: VotingState['votes']
8
- #votingDisabled: boolean
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
  }