@leofcoin/standards 0.2.4 → 0.2.5

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,24 @@ 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
+ votingDisabled: this.#votingDisabled,
28
+ votingDuration: this.#votingDuration
29
+ };
28
30
  }
29
- get inProgress() {
30
- return Object.entries(this.#votes)
31
- .filter(([id, vote]) => !vote.finished)
32
- .map(([id, vote]) => {
33
- return { ...vote, id };
34
- });
31
+ #canVote() {
32
+ // @ts-expect-error
33
+ return this._canVote?.();
34
+ }
35
+ #beforeVote() {
36
+ // @ts-expect-error
37
+ return this._beforeVote?.();
38
+ }
39
+ #afterVote() {
40
+ // @ts-expect-error
41
+ return this._afterVote?.();
35
42
  }
36
43
  /**
37
44
  * create vote
@@ -52,14 +59,6 @@ class PublicVoting {
52
59
  args
53
60
  };
54
61
  }
55
- #canVote() {
56
- // @ts-expect-error
57
- return this._canVote?.();
58
- }
59
- #beforeVote() {
60
- // @ts-expect-error
61
- return this._beforeVote?.();
62
- }
63
62
  #endVoting(voteId) {
64
63
  let agree = Object.values(this.#votes[voteId].results).filter((result) => result === 1);
65
64
  let disagree = Object.values(this.#votes[voteId].results).filter((result) => result === 0);
@@ -82,6 +81,14 @@ class PublicVoting {
82
81
  throw new Error(`Not allowed to vote`);
83
82
  await this.#beforeVote();
84
83
  this.#votes[voteId][msg.sender] = vote;
84
+ await this.#afterVote();
85
+ }
86
+ get votesInProgress() {
87
+ return Object.entries(this.#votes)
88
+ .filter(([id, vote]) => !vote.finished)
89
+ .map(([id, vote]) => {
90
+ return { ...vote, id };
91
+ });
85
92
  }
86
93
  #disableVoting() {
87
94
  this.#votingDisabled = true;
@@ -94,11 +101,20 @@ class PublicVoting {
94
101
  }
95
102
  }
96
103
  _sync() {
97
- for (const vote of this.inProgress) {
104
+ for (const vote of this.votesInProgress) {
98
105
  if (vote.endTime < new Date().getTime())
99
106
  this.#endVoting(vote.id);
100
107
  }
101
108
  }
102
109
  }
103
110
 
111
+ /**
112
+ * allows everybody that has a balance greater or equeal then/to tokenAmountToReceive to vote
113
+ */
114
+ class PublicVoting extends Voting {
115
+ constructor(state) {
116
+ super(state);
117
+ }
118
+ }
119
+
104
120
  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;
@@ -18,11 +17,9 @@ export default class TokenReceiver extends PublicVoting implements IPublicVoting
18
17
  tokenToReceive: string;
19
18
  tokenAmountToReceive: import("@ethersproject/bignumber").BigNumber;
20
19
  voteType: "burn" | "transfer";
21
- votes: {
22
- [id: string]: import("./voting/types.js").Vote;
23
- };
24
20
  votingDisabled: boolean;
25
21
  votingDuration: number;
22
+ contractCreator: string;
26
23
  };
27
24
  /**
28
25
  * 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,40 @@
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
+ votingDisabled: boolean;
13
+ votingDuration: number;
14
+ contractCreator: string;
15
+ };
16
+ /**
17
+ * create vote
18
+ * @param {string} vote
19
+ * @param {string} description
20
+ * @param {number} endTime
21
+ * @param {string} method function to run when agree amount is bigger
22
+ */
23
+ createVote(title: string, description: string, endTime: EpochTimeStamp, method: string, args?: any[]): void;
24
+ vote(voteId: string, vote: VoteResult): Promise<void>;
25
+ get votesInProgress(): {
26
+ id: string;
27
+ title: string;
28
+ method: string;
29
+ args: any[];
30
+ description: string;
31
+ endTime: number;
32
+ results?: {
33
+ [address: string]: VoteResult;
34
+ };
35
+ finished?: boolean;
36
+ enoughVotes?: boolean;
37
+ }[];
38
+ disableVoting(): void;
39
+ _sync(): void;
40
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leofcoin/standards",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
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,121 @@
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
+ votingDisabled: this.#votingDisabled,
32
+ votingDuration: this.#votingDuration
33
+ }
34
+ }
35
+
36
+ #canVote() {
37
+ // @ts-expect-error
38
+ return this._canVote?.()
39
+ }
40
+
41
+ #beforeVote() {
42
+ // @ts-expect-error
43
+ return this._beforeVote?.()
44
+ }
45
+
46
+ #afterVote() {
47
+ // @ts-expect-error
48
+ return this._afterVote?.()
49
+ }
50
+
51
+ /**
52
+ * create vote
53
+ * @param {string} vote
54
+ * @param {string} description
55
+ * @param {number} endTime
56
+ * @param {string} method function to run when agree amount is bigger
57
+ */
58
+ createVote(title: string, description: string, endTime: EpochTimeStamp, method: string, args: any[] = []) {
59
+ if (!this.#canVote()) throw new Error(`Not allowed to create a vote`)
60
+ const id = crypto.randomUUID()
61
+ this.#votes[id] = {
62
+ title,
63
+ description,
64
+ method,
65
+ endTime,
66
+ args
67
+ }
68
+ }
69
+
70
+ #endVoting(voteId) {
71
+ let agree = Object.values(this.#votes[voteId].results).filter((result) => result === 1)
72
+ let disagree = Object.values(this.#votes[voteId].results).filter((result) => result === 0)
73
+ if (agree.length > disagree.length && this.#votes[voteId].enoughVotes)
74
+ this[this.#votes[voteId].method](...this.#votes[voteId].args)
75
+ this.#votes[voteId].finished = true
76
+ }
77
+
78
+ async vote(voteId: string, vote: VoteResult) {
79
+ vote = Number(vote) as VoteResult
80
+ if (vote !== 0 && vote !== 0.5 && vote !== 1) throw new Error(`invalid vote value ${vote}`)
81
+ if (!this.#votes[voteId]) throw new Error(`Nothing found for ${voteId}`)
82
+ const ended = new Date().getTime() > this.#votes[voteId].endTime
83
+ if (ended && !this.#votes[voteId].finished) this.#endVoting(voteId)
84
+ if (ended) throw new Error('voting already ended')
85
+ if (!this.#canVote()) throw new Error(`Not allowed to vote`)
86
+ await this.#beforeVote()
87
+
88
+ this.#votes[voteId][msg.sender] = vote
89
+ await this.#afterVote()
90
+ }
91
+
92
+ get votesInProgress() {
93
+ return Object.entries(this.#votes)
94
+ .filter(([id, vote]) => !vote.finished)
95
+ .map(([id, vote]) => {
96
+ return { ...vote, id }
97
+ })
98
+ }
99
+ #disableVoting() {
100
+ this.#votingDisabled = true
101
+ }
102
+
103
+ disableVoting() {
104
+ if (!this.#canVote()) throw new Error('not a allowed')
105
+ else {
106
+ this.createVote(
107
+ `disable voting`,
108
+ `Warning this disables all voting features forever`,
109
+ new Date().getTime() + this.#votingDuration,
110
+ '#disableVoting',
111
+ []
112
+ )
113
+ }
114
+ }
115
+
116
+ _sync() {
117
+ for (const vote of this.votesInProgress) {
118
+ if (vote.endTime < new Date().getTime()) this.#endVoting(vote.id)
119
+ }
120
+ }
121
+ }
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
  }