@leofcoin/standards 0.1.8 → 0.2.1

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.
@@ -0,0 +1,8 @@
1
+ # Changesets
2
+
3
+ Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
+ with multi-package repos, or single-package repos to help you version and publish your code. You can
5
+ find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
+
7
+ We have a quick list of common questions to get you started engaging with this project in
8
+ [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
3
+ "changelog": "@changesets/cli/changelog",
4
+ "commit": true,
5
+ "fixed": [],
6
+ "linked": [],
7
+ "access": "public",
8
+ "baseBranch": "main",
9
+ "updateInternalDependencies": "patch",
10
+ "ignore": []
11
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @leofcoin/standards
2
+
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 6073f7d: interface/public-voting -> interfaces/i-public-voting
8
+
9
+ ## 0.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Add voting & tokenReceiver
package/README.md CHANGED
@@ -1,21 +1,23 @@
1
1
  # standards
2
+
2
3
  > Contract standards
3
4
 
4
5
  standards used in leofcoin chain kinda like erc20's but the native coin included
5
6
 
6
7
  ## install
8
+
7
9
  ```sh
8
10
  npm i @leofcoin/standards
9
11
  ```
10
12
 
11
13
  ## usage
14
+
12
15
  ```js
13
- import {Token} from '@leofcoin/standards'
16
+ import { Token } from '@leofcoin/standards'
14
17
 
15
18
  class myCoolToken extends Token {
16
- constructor() {
17
- super('myCoolToken', 'MCT', 18, state?)
19
+ constructor(state) {
20
+ super('myCoolToken', 'MCT', 18, state)
18
21
  }
19
22
  }
20
23
  ```
21
-
@@ -1,13 +1,11 @@
1
- import TokenReceiver from './token-receiver.js';
2
-
3
1
  /**
4
2
  * allows everybody that has a balance greater or equeal then/to tokenAmountToReceive to vote
5
3
  */
6
- class PublicVoting extends TokenReceiver {
4
+ class PublicVoting {
7
5
  #votes;
8
6
  #votingDisabled;
9
- constructor(tokenToReceive, tokenAmountToReceive, state) {
10
- super(tokenToReceive, tokenAmountToReceive, state);
7
+ #votingDuration = 172800000;
8
+ constructor(state) {
11
9
  if (state) {
12
10
  this.#votes = state.votes;
13
11
  this.#votingDisabled = state.votingDisabled;
@@ -16,6 +14,9 @@ class PublicVoting extends TokenReceiver {
16
14
  get votes() {
17
15
  return { ...this.#votes };
18
16
  }
17
+ get votingDuration() {
18
+ return this.#votingDuration;
19
+ }
19
20
  get votingDisabled() {
20
21
  return this.#votingDisabled;
21
22
  }
@@ -23,7 +24,7 @@ class PublicVoting extends TokenReceiver {
23
24
  *
24
25
  */
25
26
  get state() {
26
- return { ...super.state, votes: this.#votes, votingDisabled: this.#votingDisabled };
27
+ return { votes: this.#votes, votingDisabled: this.#votingDisabled, votingDuration: this.#votingDuration };
27
28
  }
28
29
  get inProgress() {
29
30
  return Object.entries(this.#votes)
@@ -40,7 +41,7 @@ class PublicVoting extends TokenReceiver {
40
41
  * @param {string} method function to run when agree amount is bigger
41
42
  */
42
43
  createVote(title, description, endTime, method, args = []) {
43
- if (!this.canVote(msg.sender))
44
+ if (!this.#canVote())
44
45
  throw new Error(`Not allowed to create a vote`);
45
46
  const id = crypto.randomUUID();
46
47
  this.#votes[id] = {
@@ -51,8 +52,13 @@ class PublicVoting extends TokenReceiver {
51
52
  args
52
53
  };
53
54
  }
54
- canVote(address) {
55
- return this.canPay();
55
+ #canVote() {
56
+ // @ts-expect-error
57
+ return this._canVote?.();
58
+ }
59
+ #beforeVote() {
60
+ // @ts-expect-error
61
+ return this._beforeVote?.();
56
62
  }
57
63
  #endVoting(voteId) {
58
64
  let agree = Object.values(this.#votes[voteId].results).filter((result) => result === 1);
@@ -72,22 +78,22 @@ class PublicVoting extends TokenReceiver {
72
78
  this.#endVoting(voteId);
73
79
  if (ended)
74
80
  throw new Error('voting already ended');
75
- if (!this.canVote(msg.sender))
81
+ if (!this.#canVote())
76
82
  throw new Error(`Not allowed to vote`);
77
- await msg.staticCall(this.tokenToReceive, 'burn', [this.tokenAmountToReceive]);
83
+ await this.#beforeVote();
78
84
  this.#votes[voteId][msg.sender] = vote;
79
85
  }
80
86
  #disableVoting() {
81
87
  this.#votingDisabled = true;
82
88
  }
83
89
  disableVoting() {
84
- if (!this.canVote(msg.sender))
90
+ if (!this.#canVote())
85
91
  throw new Error('not a allowed');
86
92
  else {
87
- this.createVote(`disable voting`, `Warning this disables all voting features forever`, new Date().getTime() + 172800000, '#disableVoting', []);
93
+ this.createVote(`disable voting`, `Warning this disables all voting features forever`, new Date().getTime() + this.#votingDuration, '#disableVoting', []);
88
94
  }
89
95
  }
90
- sync() {
96
+ _sync() {
91
97
  for (const vote of this.inProgress) {
92
98
  if (vote.endTime < new Date().getTime())
93
99
  this.#endVoting(vote.id);
@@ -1,19 +1,47 @@
1
- export interface TokenReceiverState {
1
+ import { IPublicVoting } from './voting/interfaces/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
5
  tokenToReceive: address;
6
+ tokenReceiver: address;
3
7
  tokenAmountToReceive: typeof BigNumber;
8
+ voteType: 'burn' | 'transfer';
4
9
  }
5
- export default class TokenReceiver {
10
+ export default class TokenReceiver extends PublicVoting implements IPublicVoting {
6
11
  #private;
7
- constructor(tokenToReceive: address, tokenAmountToReceive: typeof BigNumber, state: TokenReceiverState);
12
+ constructor(tokenToReceive: address, tokenAmountToReceive: typeof BigNumber, burns: boolean, state?: TokenReceiverState);
8
13
  get tokenToReceive(): string;
9
14
  get tokenAmountToReceive(): import("@ethersproject/bignumber").BigNumber;
15
+ get tokenReceiver(): string;
10
16
  get state(): {
17
+ tokenReceiver: string;
11
18
  tokenToReceive: string;
12
19
  tokenAmountToReceive: import("@ethersproject/bignumber").BigNumber;
20
+ voteType: "burn" | "transfer";
21
+ votes: {
22
+ [id: string]: import("./voting/types.js").Vote;
23
+ };
24
+ votingDisabled: boolean;
25
+ votingDuration: number;
13
26
  };
14
27
  /**
15
28
  * check if sender can pay
16
29
  * @returns {boolean} promise
17
30
  */
18
- canPay(): Promise<boolean>;
31
+ _canVote(): Promise<boolean>;
32
+ _beforeVote(): Promise<any>;
33
+ /**
34
+ * check if sender can pay
35
+ * @returns {boolean} promise
36
+ */
37
+ _payTokenToReceive(): Promise<boolean>;
38
+ /**
39
+ * check if sender can pay
40
+ * @returns {boolean} promise
41
+ */
42
+ _burnTokenToReceive(): Promise<boolean>;
43
+ changeVoteType(type: TokenReceiverState['voteType']): Promise<void>;
44
+ getTokensOut(amount: typeof BigNumber, receiver: address): void;
45
+ changeTokenAmountToReceive(): void;
46
+ changeTokenToReceive(): Promise<void>;
19
47
  }
@@ -1,14 +1,24 @@
1
- class TokenReceiver {
1
+ import PublicVoting from './public-voting.js';
2
+
3
+ class TokenReceiver extends PublicVoting {
2
4
  #tokenToReceive;
3
5
  #tokenAmountToReceive;
4
- constructor(tokenToReceive, tokenAmountToReceive, state) {
6
+ #tokenReceiver;
7
+ #voteType = 'transfer';
8
+ constructor(tokenToReceive, tokenAmountToReceive, burns, state) {
9
+ super(state);
5
10
  if (state) {
11
+ this.#tokenReceiver = state.tokenReceiver;
6
12
  this.#tokenToReceive = state.tokenToReceive;
7
13
  this.#tokenAmountToReceive = BigNumber['from'](state.tokenAmountToReceive);
14
+ this.#voteType = state.voteType;
8
15
  }
9
16
  else {
17
+ this.#tokenReceiver = msg.contract;
10
18
  this.#tokenToReceive = tokenToReceive;
11
19
  this.#tokenAmountToReceive = BigNumber['from'](tokenAmountToReceive);
20
+ if (burns)
21
+ this.#voteType = 'burn';
12
22
  }
13
23
  }
14
24
  get tokenToReceive() {
@@ -17,19 +27,101 @@ class TokenReceiver {
17
27
  get tokenAmountToReceive() {
18
28
  return this.#tokenAmountToReceive;
19
29
  }
30
+ get tokenReceiver() {
31
+ return this.#tokenReceiver;
32
+ }
20
33
  get state() {
21
34
  return {
35
+ ...super.state,
36
+ tokenReceiver: this.#tokenReceiver,
22
37
  tokenToReceive: this.#tokenToReceive,
23
- tokenAmountToReceive: this.#tokenAmountToReceive
38
+ tokenAmountToReceive: this.#tokenAmountToReceive,
39
+ voteType: this.#voteType
24
40
  };
25
41
  }
42
+ async #canVote() {
43
+ const amount = (await msg.staticCall(this.#tokenToReceive, 'balanceOf', [msg.sender]));
44
+ return amount.gte(this.#tokenAmountToReceive);
45
+ }
26
46
  /**
27
47
  * check if sender can pay
28
48
  * @returns {boolean} promise
29
49
  */
30
- async canPay() {
31
- const amount = (await msg.staticCall(this.#tokenToReceive, 'balanceOf', [msg.sender]));
32
- return amount.gte(this.#tokenAmountToReceive);
50
+ async _canVote() {
51
+ return this.#canVote();
52
+ }
53
+ async #beforeVote() {
54
+ if (this.#voteType === 'burn')
55
+ return msg.staticCall(this.tokenToReceive, 'burn', [this.tokenAmountToReceive]);
56
+ return msg.staticCall(this.tokenToReceive, 'transfer', [msg.sender, this.tokenReceiver, this.tokenAmountToReceive]);
57
+ }
58
+ async _beforeVote() {
59
+ await this.#beforeVote();
60
+ }
61
+ /**
62
+ * check if sender can pay
63
+ * @returns {boolean} promise
64
+ */
65
+ async _payTokenToReceive() {
66
+ return msg.staticCall(this.#tokenToReceive, 'transfer', [
67
+ msg.sender,
68
+ this.#tokenReceiver,
69
+ this.#tokenAmountToReceive
70
+ ]);
71
+ }
72
+ /**
73
+ * check if sender can pay
74
+ * @returns {boolean} promise
75
+ */
76
+ async _burnTokenToReceive() {
77
+ return msg.staticCall(this.#tokenToReceive, 'burn', [this.#tokenAmountToReceive]);
78
+ }
79
+ #changeTokenToReceive(address) {
80
+ this.#tokenToReceive = address;
81
+ }
82
+ #changeTokenAmountToReceive(amount) {
83
+ this.#tokenAmountToReceive = amount;
84
+ }
85
+ #changeVoteType(type) {
86
+ this.#voteType = type;
87
+ }
88
+ #getTokensOut(amount, receiver) {
89
+ return msg.call(this.#tokenReceiver, 'transfer', [this.#tokenReceiver, receiver, amount]);
90
+ }
91
+ async changeVoteType(type) {
92
+ if (!this.#canVote())
93
+ throw new Error('not a allowed');
94
+ if (this.#voteType === 'transfer' && (await this.#balance()).gt(0))
95
+ throw new Error('get tokens out first or they be lost forever');
96
+ else {
97
+ this.createVote(`change the token amount to receive`, `set tokenAmountToReceive`, new Date().getTime() + this.votingDuration, '#changeVoteType', [type]);
98
+ }
99
+ }
100
+ getTokensOut(amount, receiver) {
101
+ if (!this.#canVote())
102
+ throw new Error('not a allowed');
103
+ else {
104
+ this.createVote(`withdraw all tokens`, `withdraw all tokens to ${receiver}`, new Date().getTime() + this.votingDuration, '#getTokensOut', [amount, receiver]);
105
+ }
106
+ }
107
+ changeTokenAmountToReceive() {
108
+ if (!this.#canVote())
109
+ throw new Error('not a allowed');
110
+ else {
111
+ this.createVote(`change the token amount to receive`, `set tokenAmountToReceive`, new Date().getTime() + this.votingDuration, '#changeTokenAmountToReceive', []);
112
+ }
113
+ }
114
+ #balance() {
115
+ return msg.staticCall(this.#tokenToReceive, 'balanceOf', [this.#tokenReceiver]);
116
+ }
117
+ async changeTokenToReceive() {
118
+ if (!this.#canVote())
119
+ throw new Error('not a allowed');
120
+ if (!(await this.#balance()).eq(0) && this.#voteType === 'transfer')
121
+ throw new Error('get tokens out first or they be lost forever');
122
+ else {
123
+ this.createVote(`change the token to receive`, `set tokenToReceive to a new address`, new Date().getTime() + this.votingDuration, '#changeTokenToReceive', []);
124
+ }
33
125
  }
34
126
  }
35
127
 
@@ -26,9 +26,15 @@ export default class Token extends Roles {
26
26
  get symbol(): string;
27
27
  get holders(): {};
28
28
  get balances(): {};
29
+ get approvals(): {
30
+ [owner: string]: {
31
+ [operator: string]: import("@ethersproject/bignumber").BigNumber;
32
+ };
33
+ };
29
34
  get decimals(): number;
30
35
  mint(to: address, amount: BigNumberish): void;
31
36
  burn(from: address, amount: BigNumberish): void;
37
+ balance(): any;
32
38
  balanceOf(address: address): BigNumberish;
33
39
  setApproval(operator: address, amount: BigNumberish): void;
34
40
  approved(owner: address, operator: address, amount: BigNumberish): boolean;
package/exports/token.js CHANGED
@@ -73,6 +73,9 @@ class Token extends Roles {
73
73
  get balances() {
74
74
  return { ...this.#balances };
75
75
  }
76
+ get approvals() {
77
+ return this.#approvals;
78
+ }
76
79
  get decimals() {
77
80
  return this.#decimals;
78
81
  }
@@ -110,6 +113,9 @@ class Token extends Roles {
110
113
  this.#balances[address] = this.#balances[address].sub(amount);
111
114
  this.#updateHolders(address, previousBalance);
112
115
  }
116
+ balance() {
117
+ return this.#balances[msg.sender];
118
+ }
113
119
  balanceOf(address) {
114
120
  return this.#balances[address];
115
121
  }
@@ -0,0 +1,4 @@
1
+ export interface IPublicVoting {
2
+ _canVote(): Promise<any>;
3
+ _beforeVote(): Promise<any>;
4
+ }
@@ -1,116 +1,14 @@
1
- export type VoteResult = 0 | 0.5 | 1;
2
- export type Vote = {
3
- title: string;
4
- method: string;
5
- args: any[];
6
- description: string;
7
- endTime: EpochTimeStamp;
8
- results?: {
9
- [address: address]: VoteResult;
10
- };
11
- finished?: boolean;
12
- enoughVotes?: boolean;
13
- };
14
- export type PrivateVotingState = {
15
- voters: address[];
16
- votes: {
17
- [id: string]: Vote;
18
- };
19
- votingDisabled: boolean;
20
- };
21
- export interface VoteView extends Vote {
22
- id: string;
1
+ import { VoteResult, VoteView, VotingState } from './types.js';
2
+ export interface PrivateVotingState extends VotingState {
3
+ voters: any;
23
4
  }
24
5
  export default class PrivateVoting {
25
6
  #private;
26
7
  constructor(state: PrivateVotingState);
27
8
  get votes(): {
28
- [x: string]: Vote;
29
- };
30
- get voters(): {
31
- [x: number]: string;
32
- length: number;
33
- toString(): string;
34
- toLocaleString(): string;
35
- pop(): string;
36
- push(...items: string[]): number;
37
- concat(...items: ConcatArray<string>[]): string[];
38
- concat(...items: (string | ConcatArray<string>)[]): string[];
39
- join(separator?: string): string;
40
- reverse(): string[];
41
- shift(): string;
42
- slice(start?: number, end?: number): string[];
43
- sort(compareFn?: (a: string, b: string) => number): string[];
44
- splice(start: number, deleteCount?: number): string[];
45
- splice(start: number, deleteCount: number, ...items: string[]): string[];
46
- unshift(...items: string[]): number;
47
- indexOf(searchElement: string, fromIndex?: number): number;
48
- lastIndexOf(searchElement: string, fromIndex?: number): number;
49
- every<S extends string>(predicate: (value: string, index: number, array: string[]) => value is S, thisArg?: any): this is S[];
50
- every(predicate: (value: string, index: number, array: string[]) => unknown, thisArg?: any): boolean;
51
- some(predicate: (value: string, index: number, array: string[]) => unknown, thisArg?: any): boolean;
52
- forEach(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void;
53
- map<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any): U[];
54
- filter<S_1 extends string>(predicate: (value: string, index: number, array: string[]) => value is S_1, thisArg?: any): S_1[];
55
- filter(predicate: (value: string, index: number, array: string[]) => unknown, thisArg?: any): string[];
56
- reduce(callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string;
57
- reduce(callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string;
58
- reduce<U_1>(callbackfn: (previousValue: U_1, currentValue: string, currentIndex: number, array: string[]) => U_1, initialValue: U_1): U_1;
59
- reduceRight(callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string;
60
- reduceRight(callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string;
61
- reduceRight<U_2>(callbackfn: (previousValue: U_2, currentValue: string, currentIndex: number, array: string[]) => U_2, initialValue: U_2): U_2;
62
- find<S_2 extends string>(predicate: (value: string, index: number, obj: string[]) => value is S_2, thisArg?: any): S_2;
63
- find(predicate: (value: string, index: number, obj: string[]) => unknown, thisArg?: any): string;
64
- findIndex(predicate: (value: string, index: number, obj: string[]) => unknown, thisArg?: any): number;
65
- fill(value: string, start?: number, end?: number): string[];
66
- copyWithin(target: number, start: number, end?: number): string[];
67
- entries(): IterableIterator<[number, string]>;
68
- keys(): IterableIterator<number>;
69
- values(): IterableIterator<string>;
70
- includes(searchElement: string, fromIndex?: number): boolean;
71
- flatMap<U_3, This = undefined>(callback: (this: This, value: string, index: number, array: string[]) => U_3 | readonly U_3[], thisArg?: This): U_3[];
72
- flat<A, D extends number = 1>(this: A, depth?: D): FlatArray<A, D>[];
73
- at(index: number): string;
74
- [Symbol.iterator](): IterableIterator<string>;
75
- [Symbol.unscopables]: {
76
- [x: number]: boolean;
77
- length?: boolean;
78
- toString?: boolean;
79
- toLocaleString?: boolean;
80
- pop?: boolean;
81
- push?: boolean;
82
- concat?: boolean;
83
- join?: boolean;
84
- reverse?: boolean;
85
- shift?: boolean;
86
- slice?: boolean;
87
- sort?: boolean;
88
- splice?: boolean;
89
- unshift?: boolean;
90
- indexOf?: boolean;
91
- lastIndexOf?: boolean;
92
- every?: boolean;
93
- some?: boolean;
94
- forEach?: boolean;
95
- map?: boolean;
96
- filter?: boolean;
97
- reduce?: boolean;
98
- reduceRight?: boolean;
99
- find?: boolean;
100
- findIndex?: boolean;
101
- fill?: boolean;
102
- copyWithin?: boolean;
103
- entries?: boolean;
104
- keys?: boolean;
105
- values?: boolean;
106
- includes?: boolean;
107
- flatMap?: boolean;
108
- flat?: boolean;
109
- at?: boolean;
110
- [Symbol.iterator]?: boolean;
111
- readonly [Symbol.unscopables]?: boolean;
112
- };
9
+ [x: string]: import("./types.js").Vote;
113
10
  };
11
+ get voters(): any;
114
12
  get votingDisabled(): boolean;
115
13
  /**
116
14
  *
@@ -125,7 +23,7 @@ export default class PrivateVoting {
125
23
  * @param {string} method function to run when agree amount is bigger
126
24
  */
127
25
  createVote(title: string, description: string, endTime: EpochTimeStamp, method: string, args?: any[]): void;
128
- canVote(address: address): boolean;
26
+ canVote(address: address): any;
129
27
  vote(voteId: string, vote: VoteResult): void;
130
28
  disableVoting(): void;
131
29
  grantVotingPower(address: address, voteId: string): void;
@@ -1,41 +1,38 @@
1
- import TokenReceiver, { TokenReceiverState } from '../token-receiver.js';
2
- export type VoteResult = 0 | 0.5 | 1;
3
- export type PublicVote = {
4
- title: string;
5
- method: string;
6
- args: any[];
7
- description: string;
8
- endTime: EpochTimeStamp;
9
- results?: {
10
- [address: address]: VoteResult;
11
- };
12
- finished?: boolean;
13
- enoughVotes?: boolean;
14
- };
15
- export interface PublicVotingState extends TokenReceiverState {
16
- votes: {
17
- [id: string]: PublicVote;
18
- };
19
- votingDisabled: boolean;
20
- }
21
- export interface VoteView extends PublicVote {
22
- id: string;
23
- }
1
+ import { VotingState, VoteResult } from './types.js';
24
2
  /**
25
3
  * allows everybody that has a balance greater or equeal then/to tokenAmountToReceive to vote
26
4
  */
27
- export default class PublicVoting extends TokenReceiver {
5
+ export default class PublicVoting {
28
6
  #private;
29
- constructor(tokenToReceive: address, tokenAmountToReceive: typeof BigNumber, state: PublicVotingState);
7
+ constructor(state: VotingState);
30
8
  get votes(): {
31
- [x: string]: PublicVote;
9
+ [x: string]: import("./types.js").Vote;
32
10
  };
11
+ get votingDuration(): number;
33
12
  get votingDisabled(): boolean;
34
13
  /**
35
14
  *
36
15
  */
37
- get state(): PublicVotingState;
38
- get inProgress(): VoteView[];
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
+ }[];
39
36
  /**
40
37
  * create vote
41
38
  * @param {string} vote
@@ -44,8 +41,7 @@ export default class PublicVoting extends TokenReceiver {
44
41
  * @param {string} method function to run when agree amount is bigger
45
42
  */
46
43
  createVote(title: string, description: string, endTime: EpochTimeStamp, method: string, args?: any[]): void;
47
- canVote(address: address): Promise<boolean>;
48
44
  vote(voteId: string, vote: VoteResult): Promise<void>;
49
45
  disableVoting(): void;
50
- sync(): void;
46
+ _sync(): void;
51
47
  }
@@ -0,0 +1,23 @@
1
+ export type VoteResult = 0 | 0.5 | 1;
2
+ export type Vote = {
3
+ title: string;
4
+ method: string;
5
+ args: any[];
6
+ description: string;
7
+ endTime: EpochTimeStamp;
8
+ results?: {
9
+ [address: string]: VoteResult;
10
+ };
11
+ finished?: boolean;
12
+ enoughVotes?: boolean;
13
+ };
14
+ export interface VotingState {
15
+ votes: {
16
+ [id: string]: Vote;
17
+ };
18
+ votingDisabled: boolean;
19
+ votingDuration: number;
20
+ }
21
+ export interface VoteView extends Vote {
22
+ id: string;
23
+ }
package/package.json CHANGED
@@ -1,65 +1,71 @@
1
- {
2
- "name": "@leofcoin/standards",
3
- "version": "0.1.8",
4
- "description": "Contract standards",
5
- "type": "module",
6
- "exports": {
7
- ".": {
8
- "import": "./exports/index.js",
9
- "types": "./exports/index.d.ts"
10
- },
11
- "./token": {
12
- "import": "./exports/token.js",
13
- "types": "./exports/token.d.ts"
14
- },
15
- "./roles": {
16
- "import": "./exports/roles.js",
17
- "types": "./exports/roles.d.ts"
18
- },
19
- "./public-voting": {
20
- "import": "./exports/public-voting.js",
21
- "types": "./exports/public-voting.d.ts"
22
- },
23
- "./private-voting": {
24
- "import": "./exports/private-voting.js",
25
- "types": "./exports/private-voting.d.ts"
26
- },
27
- "./token-receiver": {
28
- "import": "./exports/token-receiver.js",
29
- "types": "./exports/token-receiver.d.ts"
30
- },
31
- "./helpers": {
32
- "import": "./exports/helpers.js",
33
- "types": "./exports/helpers.d.ts"
34
- },
35
- "./token.js": "./exports/token.js",
36
- "./roles.js": "./exports/roles.js",
37
- "./public-voting.js": "./exports/public-voting.js",
38
- "./private-voting.js": "./exports/private-voting.js",
39
- "./helpers.js": "./exports/helpers.js"
40
- },
41
- "scripts": {
42
- "build": "rollup -c",
43
- "test": "echo \"Error: no test specified\" && exit 1"
44
- },
45
- "repository": {
46
- "type": "git",
47
- "url": "git+https://github.com/ArteonToken/standards.git"
48
- },
49
- "keywords": [],
50
- "author": "",
51
- "license": "MIT",
52
- "bugs": {
53
- "url": "https://github.com/ArteonToken/standards/issues"
54
- },
55
- "homepage": "https://github.com/ArteonToken/standards#readme",
56
- "devDependencies": {
57
- "@leofcoin/global-types": "^1.0.0",
58
- "@rollup/plugin-typescript": "^11.0.0",
59
- "rollup": "^3.17.1",
60
- "tslib": "^2.5.0"
61
- },
62
- "dependencies": {
63
- "@ethersproject/bignumber": "^5.7.0"
64
- }
65
- }
1
+ {
2
+ "name": "@leofcoin/standards",
3
+ "version": "0.2.1",
4
+ "description": "Contract standards",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./exports/index.js",
9
+ "types": "./exports/index.d.ts"
10
+ },
11
+ "./token": {
12
+ "import": "./exports/token.js",
13
+ "types": "./exports/token.d.ts"
14
+ },
15
+ "./roles": {
16
+ "import": "./exports/roles.js",
17
+ "types": "./exports/roles.d.ts"
18
+ },
19
+ "./public-voting": {
20
+ "import": "./exports/public-voting.js",
21
+ "types": "./exports/public-voting.d.ts"
22
+ },
23
+ "./private-voting": {
24
+ "import": "./exports/private-voting.js",
25
+ "types": "./exports/private-voting.d.ts"
26
+ },
27
+ "./token-receiver": {
28
+ "import": "./exports/token-receiver.js",
29
+ "types": "./exports/token-receiver.d.ts"
30
+ },
31
+ "./interfaces/i-public-voting": {
32
+ "import": "./exports/i-public-voting.js",
33
+ "types": "./exports/i-public-voting.d.ts"
34
+ },
35
+ "./helpers": {
36
+ "import": "./exports/helpers.js",
37
+ "types": "./exports/helpers.d.ts"
38
+ },
39
+ "./token.js": "./exports/token.js",
40
+ "./roles.js": "./exports/roles.js",
41
+ "./public-voting.js": "./exports/public-voting.js",
42
+ "./interfaces/i-public-voting.js": "./exports/i-public-voting.js",
43
+ "./private-voting.js": "./exports/private-voting.js",
44
+ "./helpers.js": "./exports/helpers.js"
45
+ },
46
+ "scripts": {
47
+ "build": "rollup -c",
48
+ "test": "echo \"Error: no test specified\" && exit 1"
49
+ },
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/ArteonToken/standards.git"
53
+ },
54
+ "keywords": [],
55
+ "author": "",
56
+ "license": "MIT",
57
+ "bugs": {
58
+ "url": "https://github.com/ArteonToken/standards/issues"
59
+ },
60
+ "homepage": "https://github.com/ArteonToken/standards#readme",
61
+ "devDependencies": {
62
+ "@leofcoin/global-types": "^1.0.0",
63
+ "@rollup/plugin-typescript": "^11.1.6",
64
+ "rollup": "^4.12.0",
65
+ "tslib": "^2.5.0"
66
+ },
67
+ "dependencies": {
68
+ "@changesets/cli": "^2.27.1",
69
+ "@ethersproject/bignumber": "^5.7.0"
70
+ }
71
+ }
package/rollup.config.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import typescript from '@rollup/plugin-typescript'
2
- import tsConfig from './tsconfig.json' assert { type: 'json' }
3
2
  import { execSync } from 'child_process'
4
3
 
5
4
  // const templates = (await readdir('./src/templates')).map(path => join('./src/templates', path))
@@ -15,6 +14,7 @@ export default [
15
14
  'src/token.ts',
16
15
  'src/roles.ts',
17
16
  'src/voting/public-voting.ts',
17
+ 'src/voting/interfaces/i-public-voting.ts',
18
18
  'src/voting/private-voting.ts',
19
19
  'src/helpers.ts',
20
20
  'src/token-receiver.ts'
@@ -23,6 +23,6 @@ export default [
23
23
  dir: './exports',
24
24
  format: 'es'
25
25
  },
26
- plugins: [typescript(tsConfig)]
26
+ plugins: [typescript()]
27
27
  }
28
28
  ]
@@ -1,17 +1,36 @@
1
- export interface TokenReceiverState {
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
+
5
+ export interface TokenReceiverState extends VotingState {
2
6
  tokenToReceive: address
7
+ tokenReceiver: address
3
8
  tokenAmountToReceive: typeof BigNumber
9
+ voteType: 'burn' | 'transfer'
4
10
  }
5
- export default class TokenReceiver {
11
+ export default class TokenReceiver extends PublicVoting implements IPublicVoting {
6
12
  #tokenToReceive: address
7
13
  #tokenAmountToReceive: typeof BigNumber
8
- constructor(tokenToReceive: address, tokenAmountToReceive: typeof BigNumber, state: TokenReceiverState) {
14
+ #tokenReceiver: address
15
+ #voteType: TokenReceiverState['voteType'] = 'transfer'
16
+
17
+ constructor(
18
+ tokenToReceive: address,
19
+ tokenAmountToReceive: typeof BigNumber,
20
+ burns: boolean,
21
+ state?: TokenReceiverState
22
+ ) {
23
+ super(state)
9
24
  if (state) {
25
+ this.#tokenReceiver = state.tokenReceiver
10
26
  this.#tokenToReceive = state.tokenToReceive
11
27
  this.#tokenAmountToReceive = BigNumber['from'](state.tokenAmountToReceive)
28
+ this.#voteType = state.voteType
12
29
  } else {
30
+ this.#tokenReceiver = msg.contract
13
31
  this.#tokenToReceive = tokenToReceive
14
32
  this.#tokenAmountToReceive = BigNumber['from'](tokenAmountToReceive)
33
+ if (burns) this.#voteType = 'burn'
15
34
  }
16
35
  }
17
36
 
@@ -23,19 +42,135 @@ export default class TokenReceiver {
23
42
  return this.#tokenAmountToReceive
24
43
  }
25
44
 
45
+ get tokenReceiver() {
46
+ return this.#tokenReceiver
47
+ }
48
+
26
49
  get state() {
27
50
  return {
51
+ ...super.state,
52
+ tokenReceiver: this.#tokenReceiver,
28
53
  tokenToReceive: this.#tokenToReceive,
29
- tokenAmountToReceive: this.#tokenAmountToReceive
54
+ tokenAmountToReceive: this.#tokenAmountToReceive,
55
+ voteType: this.#voteType
30
56
  }
31
57
  }
32
58
 
59
+ async #canVote() {
60
+ const amount = (await msg.staticCall(this.#tokenToReceive, 'balanceOf', [msg.sender])) as typeof BigNumber
61
+ return amount.gte(this.#tokenAmountToReceive)
62
+ }
63
+
33
64
  /**
34
65
  * check if sender can pay
35
66
  * @returns {boolean} promise
36
67
  */
37
- async canPay(): Promise<boolean> {
38
- const amount = (await msg.staticCall(this.#tokenToReceive, 'balanceOf', [msg.sender])) as typeof BigNumber
39
- return amount.gte(this.#tokenAmountToReceive)
68
+ async _canVote(): Promise<boolean> {
69
+ return this.#canVote()
70
+ }
71
+
72
+ async #beforeVote(): Promise<any> {
73
+ if (this.#voteType === 'burn') return msg.staticCall(this.tokenToReceive, 'burn', [this.tokenAmountToReceive])
74
+ return msg.staticCall(this.tokenToReceive, 'transfer', [msg.sender, this.tokenReceiver, this.tokenAmountToReceive])
75
+ }
76
+
77
+ async _beforeVote(): Promise<any> {
78
+ await this.#beforeVote()
79
+ }
80
+
81
+ /**
82
+ * check if sender can pay
83
+ * @returns {boolean} promise
84
+ */
85
+ async _payTokenToReceive(): Promise<boolean> {
86
+ return msg.staticCall(this.#tokenToReceive, 'transfer', [
87
+ msg.sender,
88
+ this.#tokenReceiver,
89
+ this.#tokenAmountToReceive
90
+ ])
91
+ }
92
+
93
+ /**
94
+ * check if sender can pay
95
+ * @returns {boolean} promise
96
+ */
97
+ async _burnTokenToReceive(): Promise<boolean> {
98
+ return msg.staticCall(this.#tokenToReceive, 'burn', [this.#tokenAmountToReceive])
99
+ }
100
+
101
+ #changeTokenToReceive(address: address) {
102
+ this.#tokenToReceive = address
103
+ }
104
+
105
+ #changeTokenAmountToReceive(amount: typeof BigNumber) {
106
+ this.#tokenAmountToReceive = amount
107
+ }
108
+
109
+ #changeVoteType(type: TokenReceiverState['voteType']) {
110
+ this.#voteType = type
111
+ }
112
+
113
+ #getTokensOut(amount: typeof BigNumber, receiver: address) {
114
+ return msg.call(this.#tokenReceiver, 'transfer', [this.#tokenReceiver, receiver, amount])
115
+ }
116
+
117
+ async changeVoteType(type: TokenReceiverState['voteType']) {
118
+ if (!this.#canVote()) throw new Error('not a allowed')
119
+ if (this.#voteType === 'transfer' && (await this.#balance()).gt(0))
120
+ throw new Error('get tokens out first or they be lost forever')
121
+ else {
122
+ this.createVote(
123
+ `change the token amount to receive`,
124
+ `set tokenAmountToReceive`,
125
+ new Date().getTime() + this.votingDuration,
126
+ '#changeVoteType',
127
+ [type]
128
+ )
129
+ }
130
+ }
131
+
132
+ getTokensOut(amount: typeof BigNumber, receiver: address) {
133
+ if (!this.#canVote()) throw new Error('not a allowed')
134
+ else {
135
+ this.createVote(
136
+ `withdraw all tokens`,
137
+ `withdraw all tokens to ${receiver}`,
138
+ new Date().getTime() + this.votingDuration,
139
+ '#getTokensOut',
140
+ [amount, receiver]
141
+ )
142
+ }
143
+ }
144
+
145
+ changeTokenAmountToReceive() {
146
+ if (!this.#canVote()) throw new Error('not a allowed')
147
+ else {
148
+ this.createVote(
149
+ `change the token amount to receive`,
150
+ `set tokenAmountToReceive`,
151
+ new Date().getTime() + this.votingDuration,
152
+ '#changeTokenAmountToReceive',
153
+ []
154
+ )
155
+ }
156
+ }
157
+
158
+ #balance(): Promise<typeof BigNumber> {
159
+ return msg.staticCall(this.#tokenToReceive, 'balanceOf', [this.#tokenReceiver])
160
+ }
161
+
162
+ async changeTokenToReceive() {
163
+ if (!this.#canVote()) throw new Error('not a allowed')
164
+ if (!(await this.#balance()).eq(0) && this.#voteType === 'transfer')
165
+ throw new Error('get tokens out first or they be lost forever')
166
+ else {
167
+ this.createVote(
168
+ `change the token to receive`,
169
+ `set tokenToReceive to a new address`,
170
+ new Date().getTime() + this.votingDuration,
171
+ '#changeTokenToReceive',
172
+ []
173
+ )
174
+ }
40
175
  }
41
176
  }
package/src/token.ts CHANGED
@@ -90,6 +90,10 @@ export default class Token extends Roles {
90
90
  return { ...this.#balances }
91
91
  }
92
92
 
93
+ get approvals() {
94
+ return this.#approvals
95
+ }
96
+
93
97
  get decimals() {
94
98
  return this.#decimals
95
99
  }
@@ -132,6 +136,10 @@ export default class Token extends Roles {
132
136
  this.#updateHolders(address, previousBalance)
133
137
  }
134
138
 
139
+ balance() {
140
+ return this.#balances[msg.sender]
141
+ }
142
+
135
143
  balanceOf(address: address): BigNumberish {
136
144
  return this.#balances[address]
137
145
  }
@@ -0,0 +1,4 @@
1
+ export interface IPublicVoting {
2
+ _canVote(): Promise<any>
3
+ _beforeVote(): Promise<any>
4
+ }
@@ -1,25 +1,7 @@
1
- export type VoteResult = 0 | 0.5 | 1
2
-
3
- export type Vote = {
4
- title: string
5
- method: string
6
- args: any[]
7
- description: string
8
- endTime: EpochTimeStamp
9
- results?: { [address: address]: VoteResult }
10
- finished?: boolean
11
- enoughVotes?: boolean
12
- }
1
+ import { VoteResult, VoteView, VotingState } from './types.js'
13
2
 
14
- export type PrivateVotingState = {
15
- voters: address[]
16
- votes: {
17
- [id: string]: Vote
18
- }
19
- votingDisabled: boolean
20
- }
21
- export interface VoteView extends Vote {
22
- id: string
3
+ export interface PrivateVotingState extends VotingState {
4
+ voters
23
5
  }
24
6
 
25
7
  export default class PrivateVoting {
@@ -1,38 +1,14 @@
1
- import TokenReceiver, { TokenReceiverState } from '../token-receiver.js'
2
- import PrivateVoting from './private-voting.js'
3
-
4
- export type VoteResult = 0 | 0.5 | 1
5
-
6
- export type PublicVote = {
7
- title: string
8
- method: string
9
- args: any[]
10
- description: string
11
- endTime: EpochTimeStamp
12
- results?: { [address: address]: VoteResult }
13
- finished?: boolean
14
- enoughVotes?: boolean
15
- }
16
-
17
- export interface PublicVotingState extends TokenReceiverState {
18
- votes: {
19
- [id: string]: PublicVote
20
- }
21
- votingDisabled: boolean
22
- }
23
- export interface VoteView extends PublicVote {
24
- id: string
25
- }
1
+ import { VotingState, VoteResult } from './types.js'
26
2
 
27
3
  /**
28
4
  * allows everybody that has a balance greater or equeal then/to tokenAmountToReceive to vote
29
5
  */
30
- export default class PublicVoting extends TokenReceiver {
31
- #votes: PublicVotingState['votes']
6
+ export default class PublicVoting {
7
+ #votes: VotingState['votes']
32
8
  #votingDisabled: boolean
9
+ #votingDuration: number = 172800000
33
10
 
34
- constructor(tokenToReceive: address, tokenAmountToReceive: typeof BigNumber, state: PublicVotingState) {
35
- super(tokenToReceive, tokenAmountToReceive, state)
11
+ constructor(state: VotingState) {
36
12
  if (state) {
37
13
  this.#votes = state.votes
38
14
  this.#votingDisabled = state.votingDisabled
@@ -43,6 +19,10 @@ export default class PublicVoting extends TokenReceiver {
43
19
  return { ...this.#votes }
44
20
  }
45
21
 
22
+ get votingDuration() {
23
+ return this.#votingDuration
24
+ }
25
+
46
26
  get votingDisabled() {
47
27
  return this.#votingDisabled
48
28
  }
@@ -50,11 +30,11 @@ export default class PublicVoting extends TokenReceiver {
50
30
  /**
51
31
  *
52
32
  */
53
- get state(): PublicVotingState {
54
- return { ...super.state, votes: this.#votes, votingDisabled: this.#votingDisabled }
33
+ get state() {
34
+ return { votes: this.#votes, votingDisabled: this.#votingDisabled, votingDuration: this.#votingDuration }
55
35
  }
56
36
 
57
- get inProgress(): VoteView[] {
37
+ get inProgress() {
58
38
  return Object.entries(this.#votes)
59
39
  .filter(([id, vote]) => !vote.finished)
60
40
  .map(([id, vote]) => {
@@ -70,7 +50,7 @@ export default class PublicVoting extends TokenReceiver {
70
50
  */
71
51
 
72
52
  createVote(title: string, description: string, endTime: EpochTimeStamp, method: string, args: any[] = []) {
73
- if (!this.canVote(msg.sender)) throw new Error(`Not allowed to create a vote`)
53
+ if (!this.#canVote()) throw new Error(`Not allowed to create a vote`)
74
54
  const id = crypto.randomUUID()
75
55
  this.#votes[id] = {
76
56
  title,
@@ -81,8 +61,14 @@ export default class PublicVoting extends TokenReceiver {
81
61
  }
82
62
  }
83
63
 
84
- canVote(address: address) {
85
- return this.canPay()
64
+ #canVote() {
65
+ // @ts-expect-error
66
+ return this._canVote?.()
67
+ }
68
+
69
+ #beforeVote() {
70
+ // @ts-expect-error
71
+ return this._beforeVote?.()
86
72
  }
87
73
 
88
74
  #endVoting(voteId) {
@@ -100,8 +86,8 @@ export default class PublicVoting extends TokenReceiver {
100
86
  const ended = new Date().getTime() > this.#votes[voteId].endTime
101
87
  if (ended && !this.#votes[voteId].finished) this.#endVoting(voteId)
102
88
  if (ended) throw new Error('voting already ended')
103
- if (!this.canVote(msg.sender)) throw new Error(`Not allowed to vote`)
104
- await msg.staticCall(this.tokenToReceive, 'burn', [this.tokenAmountToReceive])
89
+ if (!this.#canVote()) throw new Error(`Not allowed to vote`)
90
+ await this.#beforeVote()
105
91
  this.#votes[voteId][msg.sender] = vote
106
92
  }
107
93
 
@@ -110,19 +96,19 @@ export default class PublicVoting extends TokenReceiver {
110
96
  }
111
97
 
112
98
  disableVoting() {
113
- if (!this.canVote(msg.sender)) throw new Error('not a allowed')
99
+ if (!this.#canVote()) throw new Error('not a allowed')
114
100
  else {
115
101
  this.createVote(
116
102
  `disable voting`,
117
103
  `Warning this disables all voting features forever`,
118
- new Date().getTime() + 172800000,
104
+ new Date().getTime() + this.#votingDuration,
119
105
  '#disableVoting',
120
106
  []
121
107
  )
122
108
  }
123
109
  }
124
110
 
125
- sync() {
111
+ _sync() {
126
112
  for (const vote of this.inProgress) {
127
113
  if (vote.endTime < new Date().getTime()) this.#endVoting(vote.id)
128
114
  }
@@ -0,0 +1,24 @@
1
+ export type VoteResult = 0 | 0.5 | 1
2
+
3
+ export type Vote = {
4
+ title: string
5
+ method: string
6
+ args: any[]
7
+ description: string
8
+ endTime: EpochTimeStamp
9
+ results?: { [address: string]: VoteResult }
10
+ finished?: boolean
11
+ enoughVotes?: boolean
12
+ }
13
+
14
+ export interface VotingState {
15
+ votes: {
16
+ [id: string]: Vote
17
+ }
18
+ votingDisabled: boolean
19
+ votingDuration: number
20
+ }
21
+
22
+ export interface VoteView extends Vote {
23
+ id: string
24
+ }
@@ -0,0 +1,6 @@
1
+ import Voting from './../exports/public-voting.js'
2
+
3
+ const voting = new Voting('0x0', '1000')
4
+
5
+ console.log(voting)
6
+ console.log(voting.votingDuration)