@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.
- package/.gitattributes +2 -2
- package/.github/workflows/test.yml +33 -0
- package/.prettierrc +8 -8
- package/CHANGELOG.md +16 -3
- package/LICENSE +21 -21
- package/README.md +25 -23
- package/exports/helpers.js +1 -1
- package/exports/i-public-voting.js +1 -0
- package/exports/index.d.ts +2 -1
- package/exports/index.js +2 -3
- package/exports/meta-D7uruGOw.js +28 -0
- package/exports/meta.d.ts +11 -0
- package/exports/private-voting.js +104 -11
- package/exports/public-voting.js +103 -4
- package/exports/roles.d.ts +5 -10
- package/exports/roles.js +7 -8
- package/exports/token-receiver.d.ts +5 -7
- package/exports/token-receiver.js +25 -14
- package/exports/token.d.ts +14 -27
- package/exports/token.js +14 -48
- package/exports/types.d.ts +21 -0
- package/exports/voting/private-voting.d.ts +109 -11
- package/exports/voting/public-voting.d.ts +45 -8
- package/exports/voting/types.d.ts +11 -7
- package/package.json +10 -18
- package/rollup.config.js +28 -28
- package/src/helpers.ts +19 -19
- package/src/index.ts +8 -7
- package/src/meta.ts +31 -0
- package/src/roles.ts +88 -89
- package/src/token-receiver.ts +196 -175
- package/src/token.ts +162 -198
- package/src/types.ts +15 -0
- package/src/voting/interfaces/i-public-voting.ts +4 -0
- package/src/voting/private-voting.ts +187 -69
- package/src/voting/public-voting.ts +134 -14
- package/src/voting/types.ts +30 -24
- package/test/helpers.js +51 -0
- package/test/public-voting.js +365 -6
- package/test/roles.js +186 -0
- package/test/token.js +211 -0
- package/tsconfig.json +16 -12
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/exports/contract-creator.d.ts +0 -11
- package/exports/contract-creator.js +0 -20
- package/exports/decorators/time.d.ts +0 -1
- package/exports/interfaces/i-token.d.ts +0 -10
- package/exports/lock.d.ts +0 -37
- package/exports/staking.d.ts +0 -40
- package/exports/voting/interfaces/i-voting.d.ts +0 -6
- package/exports/voting/voting.d.ts +0 -38
- package/exports/voting-C0KVNQO3.js +0 -112
- package/exports/voting-xYjJlN2h.js +0 -112
- package/src/contract-creator.ts +0 -24
- package/src/decorators/time.ts +0 -9
- package/src/interfaces/i-token.ts +0 -10
- package/src/lock.ts +0 -167
- package/src/staking.ts +0 -166
- package/src/voting/interfaces/i-voting.ts +0 -7
- 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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
get
|
|
39
|
-
return { ...
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
*
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
+
}
|
package/src/token-receiver.ts
CHANGED
|
@@ -1,175 +1,196 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import PublicVoting
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
async
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
else {
|
|
166
|
-
this.createVote(
|
|
167
|
-
`change the token to receive`,
|
|
168
|
-
`set
|
|
169
|
-
new Date().getTime() + this.votingDuration,
|
|
170
|
-
'#
|
|
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
|
+
}
|