@leofcoin/standards 0.2.16 → 0.3.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.
Files changed (61) hide show
  1. package/.gitattributes +2 -2
  2. package/.github/workflows/test.yml +33 -0
  3. package/.prettierrc +8 -8
  4. package/CHANGELOG.md +16 -3
  5. package/LICENSE +21 -21
  6. package/README.md +25 -23
  7. package/exports/helpers.js +1 -1
  8. package/exports/i-public-voting.js +1 -0
  9. package/exports/index.d.ts +2 -1
  10. package/exports/index.js +2 -3
  11. package/exports/meta-D7uruGOw.js +28 -0
  12. package/exports/meta.d.ts +11 -0
  13. package/exports/private-voting.js +104 -11
  14. package/exports/public-voting.js +103 -4
  15. package/exports/roles.d.ts +5 -10
  16. package/exports/roles.js +7 -8
  17. package/exports/token-receiver.d.ts +5 -7
  18. package/exports/token-receiver.js +25 -14
  19. package/exports/token.d.ts +14 -27
  20. package/exports/token.js +14 -48
  21. package/exports/types.d.ts +21 -0
  22. package/exports/voting/private-voting.d.ts +109 -11
  23. package/exports/voting/public-voting.d.ts +45 -8
  24. package/exports/voting/types.d.ts +11 -7
  25. package/package.json +10 -18
  26. package/rollup.config.js +28 -28
  27. package/src/helpers.ts +19 -19
  28. package/src/index.ts +8 -7
  29. package/src/meta.ts +31 -0
  30. package/src/roles.ts +88 -89
  31. package/src/token-receiver.ts +196 -175
  32. package/src/token.ts +162 -198
  33. package/src/types.ts +15 -0
  34. package/src/voting/interfaces/i-public-voting.ts +4 -0
  35. package/src/voting/private-voting.ts +187 -69
  36. package/src/voting/public-voting.ts +134 -14
  37. package/src/voting/types.ts +30 -24
  38. package/test/helpers.js +51 -0
  39. package/test/public-voting.js +365 -6
  40. package/test/roles.js +186 -0
  41. package/test/token.js +211 -0
  42. package/tsconfig.json +16 -12
  43. package/.changeset/README.md +0 -8
  44. package/.changeset/config.json +0 -11
  45. package/exports/contract-creator.d.ts +0 -11
  46. package/exports/contract-creator.js +0 -20
  47. package/exports/decorators/time.d.ts +0 -1
  48. package/exports/interfaces/i-token.d.ts +0 -10
  49. package/exports/lock.d.ts +0 -37
  50. package/exports/staking.d.ts +0 -40
  51. package/exports/voting/interfaces/i-voting.d.ts +0 -6
  52. package/exports/voting/voting.d.ts +0 -38
  53. package/exports/voting-C0KVNQO3.js +0 -112
  54. package/exports/voting-xYjJlN2h.js +0 -112
  55. package/src/contract-creator.ts +0 -24
  56. package/src/decorators/time.ts +0 -9
  57. package/src/interfaces/i-token.ts +0 -10
  58. package/src/lock.ts +0 -167
  59. package/src/staking.ts +0 -166
  60. package/src/voting/interfaces/i-voting.ts +0 -7
  61. package/src/voting/voting.ts +0 -123
package/src/meta.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { MetaState } from './types.js'
2
+
3
+ export default class Meta {
4
+ #creator: address
5
+ #createdAt: bigint = BigInt(Date.now())
6
+
7
+ constructor(state?: MetaState) {
8
+ if (state) {
9
+ this.#creator = state.creator
10
+ this.#createdAt = state.createdAt
11
+ } else {
12
+ this.#creator = msg.sender
13
+ this.#createdAt = BigInt(Date.now())
14
+ }
15
+ }
16
+
17
+ /**
18
+ * get state object for snapshotting
19
+ */
20
+ get state(): {} {
21
+ return { creator: this.#creator, createdAt: this.#createdAt }
22
+ }
23
+
24
+ get creator(): address {
25
+ return this.#creator
26
+ }
27
+
28
+ get createdAt(): bigint {
29
+ return this.#createdAt
30
+ }
31
+ }
package/src/roles.ts CHANGED
@@ -1,89 +1,88 @@
1
- import ContractCreator, { ContractCreatorState } from './contract-creator.js'
2
-
3
- export interface RolesState extends ContractCreatorState {
4
- roles: { [index: string]: address[] }
5
- }
6
-
7
- export default class Roles extends ContractCreator {
8
- /**
9
- * Object => Array
10
- */
11
- #roles = {
12
- OWNER: [],
13
- MINT: [],
14
- BURN: []
15
- }
16
-
17
- constructor(state) {
18
- super(state)
19
- // allow devs to set their own roles but always keep the default ones included
20
- // also allows roles to be loaded from the stateStore
21
- // carefull when including the roles make sure to add the owner
22
- // because no roles are granted by default when using custom roles
23
- if (state?.roles) {
24
- if (state.roles instanceof Object) {
25
- this.#roles = { ...state.roles, ...this.#roles }
26
- } else {
27
- throw new TypeError(`expected roles to be an object`)
28
- }
29
- } else {
30
- // no roles given so fallback to default to the msg sender
31
- this.#grantRole(msg.sender, 'OWNER')
32
- }
33
- }
34
-
35
- /**
36
- *
37
- */
38
- get state(): RolesState {
39
- return { ...super.state, roles: this.roles }
40
- }
41
-
42
- get roles(): {} {
43
- return { ...this.#roles }
44
- }
45
- /**
46
- * @param {address} address
47
- * @param {string} role
48
- * @returns true | false
49
- */
50
- hasRole(address: address, role: string): boolean {
51
- return this.#roles[role] ? this.#roles[role].includes(address) : false
52
- }
53
-
54
- /**
55
- * @private
56
- * @param {address} address address to grant the role to
57
- * @param {string} role role to give
58
- */
59
- #grantRole(address: address, role: string): void {
60
- if (this.hasRole(address, role)) throw new Error(`${role} role already granted for ${address}`)
61
-
62
- this.#roles[role].push(address)
63
- }
64
-
65
- /**
66
- * remove role for address
67
- * @private
68
- * @param {address} address address to revoke role from
69
- * @param {string} role role to evoke
70
- */
71
- #revokeRole(address: address, role: string) {
72
- if (!this.hasRole(address, role)) throw new Error(`${role} role already revoked for ${address}`)
73
- if (role === 'OWNER' && this.#roles[role].length === 1) throw new Error(`atleast one owner is needed!`)
74
-
75
- this.#roles[role].splice(this.#roles[role].indexOf(address))
76
- }
77
-
78
- grantRole(address: address, role: string) {
79
- if (!this.hasRole(address, 'OWNER')) throw new Error('Not allowed')
80
-
81
- this.#grantRole(address, role)
82
- }
83
-
84
- revokeRole(address: address, role: string) {
85
- if (!this.hasRole(address, 'OWNER')) throw new Error('Not allowed')
86
-
87
- this.#revokeRole(address, role)
88
- }
89
- }
1
+ import Meta from './meta.js'
2
+ import { RolesState } from './types.js'
3
+
4
+ export default class Roles extends Meta {
5
+ /**
6
+ * Object => Array
7
+ */
8
+ #roles: { [index: string]: address[] } = {
9
+ OWNER: [],
10
+ MINT: [],
11
+ BURN: []
12
+ }
13
+
14
+ constructor(state?: RolesState) {
15
+ super(state)
16
+ if (state?.roles) {
17
+ if (state.roles instanceof Object) {
18
+ this.#roles = { ...state.roles }
19
+ } else {
20
+ throw new TypeError(`expected roles to be an object`)
21
+ }
22
+ } else {
23
+ // no roles given so fallback to default to the msg sender
24
+ this.#grantRole(msg.sender, 'OWNER')
25
+ }
26
+ }
27
+
28
+ /**
29
+ *
30
+ */
31
+ get state(): {} {
32
+ return {
33
+ ...super.state,
34
+ roles: this.roles
35
+ }
36
+ }
37
+
38
+ get roles(): {} {
39
+ return { ...this.#roles }
40
+ }
41
+ /**
42
+ * @param {address} address
43
+ * @param {string} role
44
+ * @returns true | false
45
+ */
46
+ hasRole(address: address, role: string): boolean {
47
+ return this.#roles[role] ? this.#roles[role].includes(address) : false
48
+ }
49
+
50
+ /**
51
+ * @private
52
+ * @param {address} address address to grant the role to
53
+ * @param {string} role role to give
54
+ */
55
+ #grantRole(address: address, role: string): void {
56
+ if (this.hasRole(address, role))
57
+ throw new Error(`${role} role already granted for ${address}`)
58
+
59
+ this.#roles[role].push(address)
60
+ }
61
+
62
+ /**
63
+ * remove role for address
64
+ * @private
65
+ * @param {address} address address to revoke role from
66
+ * @param {string} role role to evoke
67
+ */
68
+ #revokeRole(address: address, role: string) {
69
+ if (!this.hasRole(address, role))
70
+ throw new Error(`${role} role already revoked for ${address}`)
71
+ if (role === 'OWNER' && this.#roles[role].length === 1)
72
+ throw new Error(`atleast one owner is needed!`)
73
+
74
+ this.#roles[role].splice(this.#roles[role].indexOf(address))
75
+ }
76
+
77
+ grantRole(address: address, role: string) {
78
+ if (!this.hasRole(address, 'OWNER')) throw new Error('Not allowed')
79
+
80
+ this.#grantRole(address, role)
81
+ }
82
+
83
+ revokeRole(address: address, role: string) {
84
+ if (!this.hasRole(address, 'OWNER')) throw new Error('Not allowed')
85
+
86
+ this.#revokeRole(address, role)
87
+ }
88
+ }
@@ -1,175 +1,196 @@
1
- import { IVoting } from './voting/interfaces/i-voting.js'
2
- import PublicVoting, { PublicVotingState } from './voting/public-voting.js'
3
-
4
- export interface TokenReceiverState extends PublicVotingState {
5
- tokenToReceive: address
6
- tokenReceiver: address
7
- tokenAmountToReceive: bigint
8
- voteType: 'burn' | 'transfer'
9
- }
10
- export default class TokenReceiver extends PublicVoting implements IVoting {
11
- #tokenToReceive: address
12
- #tokenAmountToReceive: bigint
13
- #tokenReceiver: address
14
- #voteType: TokenReceiverState['voteType'] = 'transfer'
15
-
16
- constructor(tokenToReceive: address, tokenAmountToReceive: bigint, burns: boolean, state?: TokenReceiverState) {
17
- super(state)
18
- if (state) {
19
- this.#tokenReceiver = state.tokenReceiver
20
- this.#tokenToReceive = state.tokenToReceive
21
- this.#tokenAmountToReceive = BigInt(state.tokenAmountToReceive)
22
- this.#voteType = state.voteType
23
- } else {
24
- this.#tokenReceiver = msg.contract
25
- this.#tokenToReceive = tokenToReceive
26
- this.#tokenAmountToReceive = BigInt(tokenAmountToReceive)
27
- if (burns) this.#voteType = 'burn'
28
- }
29
- }
30
-
31
- get tokenToReceive() {
32
- return this.#tokenToReceive
33
- }
34
-
35
- get tokenAmountToReceive() {
36
- return this.#tokenAmountToReceive
37
- }
38
-
39
- get tokenReceiver() {
40
- return this.#tokenReceiver
41
- }
42
-
43
- get state() {
44
- return {
45
- ...super.state,
46
- tokenReceiver: this.#tokenReceiver,
47
- tokenToReceive: this.#tokenToReceive,
48
- tokenAmountToReceive: this.#tokenAmountToReceive,
49
- voteType: this.#voteType
50
- }
51
- }
52
-
53
- async #canVote() {
54
- const amount = (await msg.staticCall(this.#tokenToReceive, 'balanceOf', [msg.sender])) as bigint
55
- return amount >= this.#tokenAmountToReceive
56
- }
57
-
58
- /**
59
- * check if sender can pay
60
- * @returns {boolean} promise
61
- */
62
- async _canVote(): Promise<boolean> {
63
- return this.#canVote()
64
- }
65
-
66
- async #beforeVote(): Promise<any> {
67
- if (this.#voteType === 'burn') return msg.staticCall(this.tokenToReceive, 'burn', [this.tokenAmountToReceive])
68
- return msg.staticCall(this.tokenToReceive, 'transfer', [msg.sender, this.tokenReceiver, this.tokenAmountToReceive])
69
- }
70
-
71
- async _beforeVote(): Promise<any> {
72
- return this.#beforeVote()
73
- }
74
-
75
- /**
76
- * check if sender can pay
77
- * @returns {boolean} promise
78
- */
79
- async _payTokenToReceive(): Promise<boolean> {
80
- return msg.staticCall(this.#tokenToReceive, 'transfer', [
81
- msg.sender,
82
- this.#tokenReceiver,
83
- this.#tokenAmountToReceive
84
- ])
85
- }
86
-
87
- /**
88
- * check if sender can pay
89
- * @returns {boolean} promise
90
- */
91
- async _burnTokenToReceive(): Promise<boolean> {
92
- return msg.staticCall(this.#tokenToReceive, 'burn', [this.#tokenAmountToReceive])
93
- }
94
-
95
- async _canPay() {
96
- const amount = await msg.call(this.#tokenToReceive, 'balance', [])
97
- return amount.gte(this.tokenAmountToReceive)
98
- }
99
-
100
- #changeTokenToReceive(address: address) {
101
- this.#tokenToReceive = address
102
- }
103
-
104
- #changeTokenAmountToReceive(amount: bigint) {
105
- this.#tokenAmountToReceive = amount
106
- }
107
-
108
- #changeVoteType(type: TokenReceiverState['voteType']) {
109
- this.#voteType = type
110
- }
111
-
112
- #getTokensOut(amount: bigint, receiver: address) {
113
- return msg.call(this.#tokenReceiver, 'transfer', [this.#tokenReceiver, receiver, amount])
114
- }
115
-
116
- async changeVoteType(type: TokenReceiverState['voteType']) {
117
- if (!this.#canVote()) throw new Error('not a allowed')
118
- if (this.#voteType === 'transfer' && (await this.#balance()) > 0n)
119
- throw new Error('get tokens out first or they be lost forever')
120
- else {
121
- this.createVote(
122
- `change the token amount to receive`,
123
- `set tokenAmountToReceive`,
124
- new Date().getTime() + this.votingDuration,
125
- '#changeVoteType',
126
- [type]
127
- )
128
- }
129
- }
130
-
131
- getTokensOut(amount: bigint, receiver: address) {
132
- if (!this.#canVote()) throw new Error('not a allowed')
133
- else {
134
- this.createVote(
135
- `withdraw all tokens`,
136
- `withdraw all tokens to ${receiver}`,
137
- new Date().getTime() + this.votingDuration,
138
- '#getTokensOut',
139
- [amount, receiver]
140
- )
141
- }
142
- }
143
-
144
- changeTokenAmountToReceive() {
145
- if (!this.#canVote()) throw new Error('not a allowed')
146
- else {
147
- this.createVote(
148
- `change the token amount to receive`,
149
- `set tokenAmountToReceive`,
150
- new Date().getTime() + this.votingDuration,
151
- '#changeTokenAmountToReceive',
152
- []
153
- )
154
- }
155
- }
156
-
157
- #balance(): Promise<bigint> {
158
- return msg.staticCall(this.#tokenToReceive, 'balanceOf', [this.#tokenReceiver])
159
- }
160
-
161
- async changeTokenToReceive() {
162
- if (!this.#canVote()) throw new Error('not a allowed')
163
- if ((await this.#balance()) > 0n && this.#voteType === 'transfer')
164
- throw new Error('get tokens out first or they be lost forever')
165
- else {
166
- this.createVote(
167
- `change the token to receive`,
168
- `set tokenToReceive to a new address`,
169
- new Date().getTime() + this.votingDuration,
170
- '#changeTokenToReceive',
171
- []
172
- )
173
- }
174
- }
175
- }
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 {
6
+ tokenToReceive: address
7
+ tokenReceiver: address
8
+ tokenAmountToReceive: bigint
9
+ voteType: 'burn' | 'transfer'
10
+ }
11
+ export default class TokenReceiver
12
+ extends PublicVoting
13
+ implements IPublicVoting
14
+ {
15
+ #tokenToReceive: address
16
+ #tokenAmountToReceive: bigint
17
+ #tokenReceiver: address
18
+ #voteType: TokenReceiverState['voteType'] = 'transfer'
19
+
20
+ constructor(
21
+ tokenToReceive: address,
22
+ tokenAmountToReceive: bigint,
23
+ burns: boolean,
24
+ state?: TokenReceiverState
25
+ ) {
26
+ super(state)
27
+ if (state) {
28
+ this.#tokenReceiver = state.tokenReceiver
29
+ this.#tokenToReceive = state.tokenToReceive
30
+ this.#tokenAmountToReceive = BigInt(state.tokenAmountToReceive)
31
+ this.#voteType = state.voteType
32
+ } else {
33
+ this.#tokenReceiver = msg.contract
34
+ this.#tokenToReceive = tokenToReceive
35
+ this.#tokenAmountToReceive = BigInt(tokenAmountToReceive)
36
+ if (burns) this.#voteType = 'burn'
37
+ }
38
+ }
39
+
40
+ get tokenToReceive() {
41
+ return this.#tokenToReceive
42
+ }
43
+
44
+ get tokenAmountToReceive() {
45
+ return this.#tokenAmountToReceive
46
+ }
47
+
48
+ get tokenReceiver() {
49
+ return this.#tokenReceiver
50
+ }
51
+
52
+ get state() {
53
+ return {
54
+ ...super.state,
55
+ tokenReceiver: this.#tokenReceiver,
56
+ tokenToReceive: this.#tokenToReceive,
57
+ tokenAmountToReceive: this.#tokenAmountToReceive,
58
+ voteType: this.#voteType
59
+ }
60
+ }
61
+
62
+ async #canVote() {
63
+ const amount = (await msg.staticCall(this.#tokenToReceive, 'balanceOf', [
64
+ msg.sender
65
+ ])) as bigint
66
+ return amount >= this.#tokenAmountToReceive
67
+ }
68
+
69
+ /**
70
+ * check if sender can pay
71
+ * @returns {boolean} promise
72
+ */
73
+ async _canVote(): Promise<boolean> {
74
+ return this.#canVote()
75
+ }
76
+
77
+ async #beforeVote(): Promise<any> {
78
+ if (this.#voteType === 'burn')
79
+ return msg.staticCall(this.tokenToReceive, 'burn', [
80
+ this.tokenAmountToReceive
81
+ ])
82
+ return msg.staticCall(this.tokenToReceive, 'transfer', [
83
+ msg.sender,
84
+ this.tokenReceiver,
85
+ this.tokenAmountToReceive
86
+ ])
87
+ }
88
+
89
+ async _beforeVote(): Promise<any> {
90
+ await this.#beforeVote()
91
+ }
92
+
93
+ /**
94
+ * check if sender can pay
95
+ * @returns {boolean} promise
96
+ */
97
+ async _payTokenToReceive(): Promise<boolean> {
98
+ return msg.staticCall(this.#tokenToReceive, 'transfer', [
99
+ msg.sender,
100
+ this.#tokenReceiver,
101
+ this.#tokenAmountToReceive
102
+ ])
103
+ }
104
+
105
+ /**
106
+ * check if sender can pay
107
+ * @returns {boolean} promise
108
+ */
109
+ async _burnTokenToReceive(): Promise<boolean> {
110
+ return msg.staticCall(this.#tokenToReceive, 'burn', [
111
+ this.#tokenAmountToReceive
112
+ ])
113
+ }
114
+
115
+ #changeTokenToReceive(address: address) {
116
+ this.#tokenToReceive = address
117
+ }
118
+
119
+ #changeTokenAmountToReceive(amount: bigint) {
120
+ this.#tokenAmountToReceive = amount
121
+ }
122
+
123
+ #changeVoteType(type: TokenReceiverState['voteType']) {
124
+ this.#voteType = type
125
+ }
126
+
127
+ #getTokensOut(amount: bigint, receiver: address) {
128
+ return msg.call(this.#tokenReceiver, 'transfer', [
129
+ this.#tokenReceiver,
130
+ receiver,
131
+ amount
132
+ ])
133
+ }
134
+
135
+ async changeVoteType(type: TokenReceiverState['voteType']) {
136
+ if (!this.#canVote()) throw new Error('not a allowed')
137
+ if (this.#voteType === 'transfer' && (await this.#balance()) > 0n)
138
+ throw new Error('get tokens out first or they be lost forever')
139
+ else {
140
+ this.createVote(
141
+ `change the token amount to receive`,
142
+ `set tokenAmountToReceive`,
143
+ new Date().getTime() + this.votingDuration,
144
+ '#changeVoteType',
145
+ [type]
146
+ )
147
+ }
148
+ }
149
+
150
+ getTokensOut(amount: bigint, receiver: address) {
151
+ if (!this.#canVote()) throw new Error('not a allowed')
152
+ else {
153
+ this.createVote(
154
+ `withdraw all tokens`,
155
+ `withdraw all tokens to ${receiver}`,
156
+ new Date().getTime() + this.votingDuration,
157
+ '#getTokensOut',
158
+ [amount, receiver]
159
+ )
160
+ }
161
+ }
162
+
163
+ changeTokenAmountToReceive() {
164
+ if (!this.#canVote()) throw new Error('not a allowed')
165
+ else {
166
+ this.createVote(
167
+ `change the token amount to receive`,
168
+ `set tokenAmountToReceive`,
169
+ new Date().getTime() + this.votingDuration,
170
+ '#changeTokenAmountToReceive',
171
+ []
172
+ )
173
+ }
174
+ }
175
+
176
+ #balance(): Promise<bigint> {
177
+ return msg.staticCall(this.#tokenToReceive, 'balanceOf', [
178
+ this.#tokenReceiver
179
+ ])
180
+ }
181
+
182
+ async changeTokenToReceive() {
183
+ if (!this.#canVote()) throw new Error('not a allowed')
184
+ if ((await this.#balance()) !== 0n && this.#voteType === 'transfer')
185
+ throw new Error('get tokens out first or they be lost forever')
186
+ else {
187
+ this.createVote(
188
+ `change the token to receive`,
189
+ `set tokenToReceive to a new address`,
190
+ new Date().getTime() + this.votingDuration,
191
+ '#changeTokenToReceive',
192
+ []
193
+ )
194
+ }
195
+ }
196
+ }