@leofcoin/standards 0.2.8 → 0.2.10
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/exports/contract-creator.d.ts +1 -0
- package/exports/helpers.js +3 -3
- package/exports/lock.d.ts +37 -0
- package/exports/roles.d.ts +1 -0
- package/exports/staking.d.ts +14 -13
- package/exports/token-receiver.d.ts +6 -5
- package/exports/token-receiver.js +5 -5
- package/exports/token.d.ts +18 -19
- package/exports/token.js +39 -18
- package/exports/voting/private-voting.d.ts +1 -0
- package/package.json +7 -9
- package/src/helpers.ts +3 -3
- package/src/interfaces/i-token.ts +3 -0
- package/src/lock.ts +34 -33
- package/src/staking.ts +31 -30
- package/src/token-receiver.ts +13 -18
- package/src/token.ts +57 -37
- package/tsconfig.json +3 -2
package/exports/helpers.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// when state is stored it get encoded as a string to so we need to reformat balances back to
|
|
1
|
+
// when state is stored it get encoded as a string to so we need to reformat balances back to BigInt's
|
|
2
2
|
const restoreBalances = (balances) => {
|
|
3
3
|
const _balances = {};
|
|
4
4
|
for (const address in balances) {
|
|
5
|
-
_balances[address] =
|
|
5
|
+
_balances[address] = BigInt(balances[address]);
|
|
6
6
|
}
|
|
7
7
|
return _balances;
|
|
8
8
|
};
|
|
@@ -11,7 +11,7 @@ const restoreApprovals = (approvals) => {
|
|
|
11
11
|
for (const owner in approvals) {
|
|
12
12
|
_approvals[owner] = {};
|
|
13
13
|
for (const operator in approvals[owner]) {
|
|
14
|
-
_approvals[owner][operator] =
|
|
14
|
+
_approvals[owner][operator] = BigInt(approvals[owner][operator]);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
return _approvals;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/// <reference types="@leofcoin/types/global" />
|
|
2
|
+
import { RolesState } from './roles.js';
|
|
3
|
+
import { IVoting } from './voting/interfaces/i-voting.js';
|
|
4
|
+
import PublicVoting from './voting/public-voting.js';
|
|
5
|
+
export declare interface LockState extends RolesState {
|
|
6
|
+
holders: bigint;
|
|
7
|
+
balances: {
|
|
8
|
+
[address: address]: bigint;
|
|
9
|
+
};
|
|
10
|
+
totalSupply: bigint;
|
|
11
|
+
}
|
|
12
|
+
export default class Lock extends PublicVoting implements IVoting {
|
|
13
|
+
#private;
|
|
14
|
+
constructor(name: string, symbol: string, decimals?: number, state?: LockState);
|
|
15
|
+
/**
|
|
16
|
+
* @return {Object} {holders, balances, ...}
|
|
17
|
+
*/
|
|
18
|
+
get state(): LockState;
|
|
19
|
+
get totalSupply(): bigint;
|
|
20
|
+
get name(): string;
|
|
21
|
+
get symbol(): string;
|
|
22
|
+
get holders(): LockState['holders'];
|
|
23
|
+
get balances(): LockState['balances'];
|
|
24
|
+
get approvals(): {
|
|
25
|
+
[owner: string]: {
|
|
26
|
+
[operator: string]: bigint;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
get decimals(): number;
|
|
30
|
+
mint(to: address, amount: bigint): void;
|
|
31
|
+
burn(from: address, amount: bigint): void;
|
|
32
|
+
balance(): any;
|
|
33
|
+
balanceOf(address: address): bigint;
|
|
34
|
+
setApproval(operator: address, amount: bigint): void;
|
|
35
|
+
approved(owner: address, operator: address, amount: bigint): boolean;
|
|
36
|
+
transfer(from: address, to: address, amount: bigint): void;
|
|
37
|
+
}
|
package/exports/roles.d.ts
CHANGED
package/exports/staking.d.ts
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
|
+
/// <reference types="@leofcoin/types/global" />
|
|
1
2
|
import Roles, { RolesState } from './roles.js';
|
|
2
3
|
export declare interface TokenState extends RolesState {
|
|
3
|
-
holders:
|
|
4
|
+
holders: bigint;
|
|
4
5
|
balances: {
|
|
5
|
-
[address: address]:
|
|
6
|
+
[address: address]: bigint;
|
|
6
7
|
};
|
|
7
8
|
approvals: {
|
|
8
9
|
[owner: address]: {
|
|
9
|
-
[operator: address]:
|
|
10
|
+
[operator: address]: bigint;
|
|
10
11
|
};
|
|
11
12
|
};
|
|
12
|
-
totalSupply:
|
|
13
|
+
totalSupply: bigint;
|
|
13
14
|
}
|
|
14
|
-
export default class
|
|
15
|
+
export default class Staking extends Roles {
|
|
15
16
|
#private;
|
|
16
17
|
constructor(name: string, symbol: string, decimals?: number, state?: TokenState);
|
|
17
18
|
/**
|
|
18
19
|
* @return {Object} {holders, balances, ...}
|
|
19
20
|
*/
|
|
20
21
|
get state(): TokenState;
|
|
21
|
-
get totalSupply():
|
|
22
|
+
get totalSupply(): bigint;
|
|
22
23
|
get name(): string;
|
|
23
24
|
get symbol(): string;
|
|
24
25
|
get holders(): TokenState['holders'];
|
|
25
26
|
get balances(): TokenState['balances'];
|
|
26
27
|
get approvals(): {
|
|
27
28
|
[owner: string]: {
|
|
28
|
-
[operator: string]:
|
|
29
|
+
[operator: string]: bigint;
|
|
29
30
|
};
|
|
30
31
|
};
|
|
31
32
|
get decimals(): number;
|
|
32
|
-
mint(to: address, amount:
|
|
33
|
-
burn(from: address, amount:
|
|
33
|
+
mint(to: address, amount: bigint): void;
|
|
34
|
+
burn(from: address, amount: bigint): void;
|
|
34
35
|
balance(): any;
|
|
35
|
-
balanceOf(address: address):
|
|
36
|
-
setApproval(operator: address, amount:
|
|
37
|
-
approved(owner: address, operator: address, amount:
|
|
38
|
-
transfer(from: address, to: address, amount:
|
|
36
|
+
balanceOf(address: address): bigint;
|
|
37
|
+
setApproval(operator: address, amount: bigint): void;
|
|
38
|
+
approved(owner: address, operator: address, amount: bigint): boolean;
|
|
39
|
+
transfer(from: address, to: address, amount: bigint): void;
|
|
39
40
|
}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
+
/// <reference types="@leofcoin/types/global" />
|
|
1
2
|
import { IVoting } from './voting/interfaces/i-voting.js';
|
|
2
3
|
import PublicVoting, { PublicVotingState } from './voting/public-voting.js';
|
|
3
4
|
export interface TokenReceiverState extends PublicVotingState {
|
|
4
5
|
tokenToReceive: address;
|
|
5
6
|
tokenReceiver: address;
|
|
6
|
-
tokenAmountToReceive:
|
|
7
|
+
tokenAmountToReceive: bigint;
|
|
7
8
|
voteType: 'burn' | 'transfer';
|
|
8
9
|
}
|
|
9
10
|
export default class TokenReceiver extends PublicVoting implements IVoting {
|
|
10
11
|
#private;
|
|
11
|
-
constructor(tokenToReceive: address, tokenAmountToReceive:
|
|
12
|
+
constructor(tokenToReceive: address, tokenAmountToReceive: bigint, burns: boolean, state?: TokenReceiverState);
|
|
12
13
|
get tokenToReceive(): string;
|
|
13
|
-
get tokenAmountToReceive():
|
|
14
|
+
get tokenAmountToReceive(): bigint;
|
|
14
15
|
get tokenReceiver(): string;
|
|
15
16
|
get state(): {
|
|
16
17
|
tokenReceiver: string;
|
|
17
18
|
tokenToReceive: string;
|
|
18
|
-
tokenAmountToReceive:
|
|
19
|
+
tokenAmountToReceive: bigint;
|
|
19
20
|
voteType: "burn" | "transfer";
|
|
20
21
|
votes: {
|
|
21
22
|
[id: string]: import("./voting/types.js").Vote;
|
|
@@ -42,7 +43,7 @@ export default class TokenReceiver extends PublicVoting implements IVoting {
|
|
|
42
43
|
_burnTokenToReceive(): Promise<boolean>;
|
|
43
44
|
_canPay(): Promise<any>;
|
|
44
45
|
changeVoteType(type: TokenReceiverState['voteType']): Promise<void>;
|
|
45
|
-
getTokensOut(amount:
|
|
46
|
+
getTokensOut(amount: bigint, receiver: address): void;
|
|
46
47
|
changeTokenAmountToReceive(): void;
|
|
47
48
|
changeTokenToReceive(): Promise<void>;
|
|
48
49
|
}
|
|
@@ -12,13 +12,13 @@ class TokenReceiver extends PublicVoting {
|
|
|
12
12
|
if (state) {
|
|
13
13
|
this.#tokenReceiver = state.tokenReceiver;
|
|
14
14
|
this.#tokenToReceive = state.tokenToReceive;
|
|
15
|
-
this.#tokenAmountToReceive =
|
|
15
|
+
this.#tokenAmountToReceive = BigInt(state.tokenAmountToReceive);
|
|
16
16
|
this.#voteType = state.voteType;
|
|
17
17
|
}
|
|
18
18
|
else {
|
|
19
19
|
this.#tokenReceiver = msg.contract;
|
|
20
20
|
this.#tokenToReceive = tokenToReceive;
|
|
21
|
-
this.#tokenAmountToReceive =
|
|
21
|
+
this.#tokenAmountToReceive = BigInt(tokenAmountToReceive);
|
|
22
22
|
if (burns)
|
|
23
23
|
this.#voteType = 'burn';
|
|
24
24
|
}
|
|
@@ -43,7 +43,7 @@ class TokenReceiver extends PublicVoting {
|
|
|
43
43
|
}
|
|
44
44
|
async #canVote() {
|
|
45
45
|
const amount = (await msg.staticCall(this.#tokenToReceive, 'balanceOf', [msg.sender]));
|
|
46
|
-
return amount
|
|
46
|
+
return amount >= this.#tokenAmountToReceive;
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
49
|
* check if sender can pay
|
|
@@ -97,7 +97,7 @@ class TokenReceiver extends PublicVoting {
|
|
|
97
97
|
async changeVoteType(type) {
|
|
98
98
|
if (!this.#canVote())
|
|
99
99
|
throw new Error('not a allowed');
|
|
100
|
-
if (this.#voteType === 'transfer' && (await this.#balance())
|
|
100
|
+
if (this.#voteType === 'transfer' && (await this.#balance()) > 0n)
|
|
101
101
|
throw new Error('get tokens out first or they be lost forever');
|
|
102
102
|
else {
|
|
103
103
|
this.createVote(`change the token amount to receive`, `set tokenAmountToReceive`, new Date().getTime() + this.votingDuration, '#changeVoteType', [type]);
|
|
@@ -123,7 +123,7 @@ class TokenReceiver extends PublicVoting {
|
|
|
123
123
|
async changeTokenToReceive() {
|
|
124
124
|
if (!this.#canVote())
|
|
125
125
|
throw new Error('not a allowed');
|
|
126
|
-
if (
|
|
126
|
+
if ((await this.#balance()) > 0n && this.#voteType === 'transfer')
|
|
127
127
|
throw new Error('get tokens out first or they be lost forever');
|
|
128
128
|
else {
|
|
129
129
|
this.createVote(`change the token to receive`, `set tokenToReceive to a new address`, new Date().getTime() + this.votingDuration, '#changeTokenToReceive', []);
|
package/exports/token.d.ts
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
+
/// <reference types="@leofcoin/types/global" />
|
|
1
2
|
import Roles, { RolesState } from './roles.js';
|
|
2
3
|
export declare interface TokenState extends RolesState {
|
|
3
4
|
name: string;
|
|
4
5
|
symbol: string;
|
|
5
6
|
decimals: number;
|
|
6
|
-
holders:
|
|
7
|
+
holders: bigint;
|
|
7
8
|
balances: {
|
|
8
|
-
[address: address]:
|
|
9
|
+
[address: address]: bigint;
|
|
9
10
|
};
|
|
10
11
|
approvals: {
|
|
11
12
|
[owner: address]: {
|
|
12
|
-
[operator: address]:
|
|
13
|
+
[operator: address]: bigint;
|
|
13
14
|
};
|
|
14
15
|
};
|
|
15
|
-
totalSupply:
|
|
16
|
+
totalSupply: bigint;
|
|
17
|
+
maxSupply: bigint;
|
|
16
18
|
}
|
|
17
19
|
export default class Token extends Roles {
|
|
18
20
|
#private;
|
|
@@ -21,22 +23,19 @@ export default class Token extends Roles {
|
|
|
21
23
|
* @return {Object} {holders, balances, ...}
|
|
22
24
|
*/
|
|
23
25
|
get state(): TokenState;
|
|
24
|
-
get
|
|
25
|
-
get
|
|
26
|
-
get
|
|
26
|
+
get maxSupply(): TokenState['maxSupply'];
|
|
27
|
+
get totalSupply(): TokenState['totalSupply'];
|
|
28
|
+
get name(): TokenState['name'];
|
|
29
|
+
get symbol(): TokenState['symbol'];
|
|
27
30
|
get holders(): TokenState['holders'];
|
|
28
31
|
get balances(): TokenState['balances'];
|
|
29
|
-
get approvals():
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
get decimals(): number;
|
|
35
|
-
mint(to: address, amount: BigNumberish): void;
|
|
36
|
-
burn(from: address, amount: BigNumberish): void;
|
|
32
|
+
get approvals(): TokenState['approvals'];
|
|
33
|
+
get decimals(): TokenState['decimals'];
|
|
34
|
+
mint(to: address, amount: bigint): void;
|
|
35
|
+
burn(from: address, amount: bigint): void;
|
|
37
36
|
balance(): any;
|
|
38
|
-
balanceOf(address: address):
|
|
39
|
-
setApproval(operator: address, amount:
|
|
40
|
-
approved(owner: address, operator: address, amount:
|
|
41
|
-
transfer(from: address, to: address, amount:
|
|
37
|
+
balanceOf(address: address): bigint;
|
|
38
|
+
setApproval(operator: address, amount: bigint): void;
|
|
39
|
+
approved(owner: address, operator: address, amount: bigint): boolean;
|
|
40
|
+
transfer(from: address, to: address, amount: bigint): void;
|
|
42
41
|
}
|
package/exports/token.js
CHANGED
|
@@ -14,7 +14,7 @@ class Token extends Roles {
|
|
|
14
14
|
/**
|
|
15
15
|
* uint
|
|
16
16
|
*/
|
|
17
|
-
#holders =
|
|
17
|
+
#holders = BigInt(0);
|
|
18
18
|
/**
|
|
19
19
|
* Object => Object => uint
|
|
20
20
|
*/
|
|
@@ -24,9 +24,9 @@ class Token extends Roles {
|
|
|
24
24
|
*/
|
|
25
25
|
#approvals = {};
|
|
26
26
|
#decimals = 18;
|
|
27
|
-
#totalSupply =
|
|
27
|
+
#totalSupply = BigInt(0);
|
|
28
|
+
#maxSupply = BigInt(0);
|
|
28
29
|
#stakingContract;
|
|
29
|
-
// this.#privateField2 = 1
|
|
30
30
|
constructor(name, symbol, decimals = 18, state) {
|
|
31
31
|
if (!name)
|
|
32
32
|
throw new Error(`name undefined`);
|
|
@@ -36,11 +36,12 @@ class Token extends Roles {
|
|
|
36
36
|
if (state) {
|
|
37
37
|
this.#balances = restoreBalances(state.balances);
|
|
38
38
|
this.#approvals = restoreApprovals(state.approvals);
|
|
39
|
-
this.#holders =
|
|
40
|
-
this.#totalSupply =
|
|
39
|
+
this.#holders = BigInt(state.holders);
|
|
40
|
+
this.#totalSupply = BigInt(state.totalSupply);
|
|
41
41
|
this.#name = name;
|
|
42
42
|
this.#symbol = symbol;
|
|
43
43
|
this.#decimals = decimals;
|
|
44
|
+
this.#maxSupply = BigInt(state.maxSupply);
|
|
44
45
|
}
|
|
45
46
|
else {
|
|
46
47
|
this.#name = name;
|
|
@@ -51,6 +52,7 @@ class Token extends Roles {
|
|
|
51
52
|
// enables snapshotting
|
|
52
53
|
// needs dev attention so nothing breaks after snapshot happens
|
|
53
54
|
// iow everything that is not static needs to be included in the stateObject
|
|
55
|
+
// TODO: implement snapshotting test
|
|
54
56
|
/**
|
|
55
57
|
* @return {Object} {holders, balances, ...}
|
|
56
58
|
*/
|
|
@@ -63,9 +65,13 @@ class Token extends Roles {
|
|
|
63
65
|
holders: this.holders,
|
|
64
66
|
balances: this.balances,
|
|
65
67
|
approvals: { ...this.#approvals },
|
|
66
|
-
totalSupply: this.totalSupply
|
|
68
|
+
totalSupply: this.totalSupply,
|
|
69
|
+
maxSupply: this.#maxSupply
|
|
67
70
|
};
|
|
68
71
|
}
|
|
72
|
+
get maxSupply() {
|
|
73
|
+
return this.#maxSupply;
|
|
74
|
+
}
|
|
69
75
|
get totalSupply() {
|
|
70
76
|
return this.#totalSupply;
|
|
71
77
|
}
|
|
@@ -90,31 +96,46 @@ class Token extends Roles {
|
|
|
90
96
|
mint(to, amount) {
|
|
91
97
|
if (!this.hasRole(msg.sender, 'MINT'))
|
|
92
98
|
throw new Error('not allowed');
|
|
93
|
-
|
|
94
|
-
this.#
|
|
99
|
+
const supply = this.#totalSupply + amount;
|
|
100
|
+
if (this.#maxSupply === 0n) {
|
|
101
|
+
this.#totalSupply = supply;
|
|
102
|
+
this.#increaseBalance(to, amount);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
if (supply <= this.#maxSupply) {
|
|
106
|
+
this.#totalSupply = supply;
|
|
107
|
+
this.#increaseBalance(to, amount);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
throw new Error('amount exceeds max supply');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
95
113
|
}
|
|
96
114
|
burn(from, amount) {
|
|
97
115
|
if (!this.hasRole(msg.sender, 'BURN') || msg.sender !== from)
|
|
98
116
|
throw new Error('not allowed');
|
|
99
|
-
const total = this.#totalSupply
|
|
100
|
-
if (total
|
|
117
|
+
const total = this.#totalSupply - amount;
|
|
118
|
+
if (total >= 0) {
|
|
101
119
|
this.#totalSupply = total;
|
|
102
120
|
this.#decreaseBalance(from, amount);
|
|
103
121
|
}
|
|
122
|
+
else {
|
|
123
|
+
throw new Error('amount exceeds total supply');
|
|
124
|
+
}
|
|
104
125
|
}
|
|
105
126
|
#beforeTransfer(from, to, amount) {
|
|
106
127
|
if (!this.#balances[from] || this.#balances[from] < amount)
|
|
107
128
|
throw new Error('amount exceeds balance');
|
|
108
129
|
}
|
|
109
130
|
#updateHolders(address, previousBalance) {
|
|
110
|
-
if (this.#balances[address]
|
|
111
|
-
this.#holders
|
|
112
|
-
else if (this.#balances[address]
|
|
113
|
-
this.#holders
|
|
131
|
+
if (this.#balances[address] === 0n)
|
|
132
|
+
this.#holders - 1n;
|
|
133
|
+
else if (this.#balances[address] !== 0n && previousBalance === 0n)
|
|
134
|
+
this.#holders + 1n;
|
|
114
135
|
}
|
|
115
136
|
#increaseBalance(address, amount) {
|
|
116
137
|
if (!this.#balances[address])
|
|
117
|
-
this.#balances[address] =
|
|
138
|
+
this.#balances[address] = BigInt(0);
|
|
118
139
|
const previousBalance = this.#balances[address];
|
|
119
140
|
this.#balances[address] = this.#balances[address].add(amount);
|
|
120
141
|
this.#updateHolders(address, previousBalance);
|
|
@@ -134,14 +155,14 @@ class Token extends Roles {
|
|
|
134
155
|
const owner = msg.sender;
|
|
135
156
|
if (!this.#approvals[owner])
|
|
136
157
|
this.#approvals[owner] = {};
|
|
137
|
-
this.#approvals[owner][operator] =
|
|
158
|
+
this.#approvals[owner][operator] = BigInt(amount);
|
|
138
159
|
}
|
|
139
160
|
approved(owner, operator, amount) {
|
|
140
161
|
return this.#approvals[owner][operator] === amount;
|
|
141
162
|
}
|
|
142
163
|
transfer(from, to, amount) {
|
|
143
|
-
// TODO: is
|
|
144
|
-
amount =
|
|
164
|
+
// TODO: is bigint?
|
|
165
|
+
amount = BigInt(amount);
|
|
145
166
|
this.#beforeTransfer(from, to, amount);
|
|
146
167
|
this.#decreaseBalance(from, amount);
|
|
147
168
|
this.#increaseBalance(to, amount);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leofcoin/standards",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"description": "Contract standards",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "rollup -c",
|
|
51
|
-
"test": "
|
|
51
|
+
"test": "mocha --require ts-node/register test/**/*.ts"
|
|
52
52
|
},
|
|
53
53
|
"repository": {
|
|
54
54
|
"type": "git",
|
|
@@ -62,13 +62,11 @@
|
|
|
62
62
|
},
|
|
63
63
|
"homepage": "https://github.com/ArteonToken/standards#readme",
|
|
64
64
|
"devDependencies": {
|
|
65
|
-
"@leofcoin/
|
|
65
|
+
"@leofcoin/types": "^1.0.17",
|
|
66
66
|
"@rollup/plugin-typescript": "^11.1.6",
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"@changesets/cli": "^2.27.1",
|
|
72
|
-
"@ethersproject/bignumber": "^5.7.0"
|
|
67
|
+
"chai": "^5.1.1",
|
|
68
|
+
"mocha": "^10.7.3",
|
|
69
|
+
"rollup": "^4.22.1",
|
|
70
|
+
"tslib": "^2.7.0"
|
|
73
71
|
}
|
|
74
72
|
}
|
package/src/helpers.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// when state is stored it get encoded as a string to so we need to reformat balances back to
|
|
1
|
+
// when state is stored it get encoded as a string to so we need to reformat balances back to BigInt's
|
|
2
2
|
export const restoreBalances = (balances) => {
|
|
3
3
|
const _balances = {}
|
|
4
4
|
for (const address in balances) {
|
|
5
|
-
_balances[address] =
|
|
5
|
+
_balances[address] = BigInt(balances[address])
|
|
6
6
|
}
|
|
7
7
|
return _balances
|
|
8
8
|
}
|
|
@@ -12,7 +12,7 @@ export const restoreApprovals = (approvals) => {
|
|
|
12
12
|
for (const owner in approvals) {
|
|
13
13
|
_approvals[owner] = {}
|
|
14
14
|
for (const operator in approvals[owner]) {
|
|
15
|
-
_approvals[owner][operator] =
|
|
15
|
+
_approvals[owner][operator] = BigInt(approvals[owner][operator])
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
return _approvals
|
package/src/lock.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { restoreApprovals, restoreBalances } from './helpers.js'
|
|
2
2
|
import Roles, { RolesState } from './roles.js'
|
|
3
|
+
import { IVoting } from './voting/interfaces/i-voting.js'
|
|
4
|
+
import PublicVoting from './voting/public-voting.js'
|
|
3
5
|
|
|
4
6
|
export declare interface LockState extends RolesState {
|
|
5
|
-
holders:
|
|
6
|
-
balances: { [address: address]:
|
|
7
|
-
totalSupply:
|
|
7
|
+
holders: bigint
|
|
8
|
+
balances: { [address: address]: bigint }
|
|
9
|
+
totalSupply: bigint
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
export default class Lock extends PublicVoting {
|
|
12
|
+
export default class Lock extends PublicVoting implements IVoting {
|
|
11
13
|
/**
|
|
12
14
|
* string
|
|
13
15
|
*/
|
|
@@ -19,7 +21,7 @@ export default class Lock extends PublicVoting {
|
|
|
19
21
|
/**
|
|
20
22
|
* uint
|
|
21
23
|
*/
|
|
22
|
-
#holders:
|
|
24
|
+
#holders: bigint = BigInt(0)
|
|
23
25
|
/**
|
|
24
26
|
* Object => Object => uint
|
|
25
27
|
*/
|
|
@@ -27,16 +29,16 @@ export default class Lock extends PublicVoting {
|
|
|
27
29
|
/**
|
|
28
30
|
* Object => Object => uint
|
|
29
31
|
*/
|
|
30
|
-
#approvals: { [owner: string]: { [operator: string]:
|
|
32
|
+
#approvals: { [owner: string]: { [operator: string]: bigint } } = {}
|
|
31
33
|
|
|
32
34
|
#decimals = 18
|
|
33
35
|
|
|
34
|
-
#totalSupply:
|
|
36
|
+
#totalSupply: bigint = BigInt(0)
|
|
35
37
|
|
|
36
38
|
#stakingContract: address
|
|
37
39
|
|
|
38
40
|
// this.#privateField2 = 1
|
|
39
|
-
constructor(name: string, symbol: string, decimals: number = 18, state?:
|
|
41
|
+
constructor(name: string, symbol: string, decimals: number = 18, state?: LockState) {
|
|
40
42
|
if (!name) throw new Error(`name undefined`)
|
|
41
43
|
if (!symbol) throw new Error(`symbol undefined`)
|
|
42
44
|
|
|
@@ -45,8 +47,8 @@ export default class Lock extends PublicVoting {
|
|
|
45
47
|
if (state) {
|
|
46
48
|
this.#balances = restoreBalances(state.balances)
|
|
47
49
|
this.#approvals = restoreApprovals(state.approvals)
|
|
48
|
-
this.#holders =
|
|
49
|
-
this.#totalSupply =
|
|
50
|
+
this.#holders = BigInt(state.holders)
|
|
51
|
+
this.#totalSupply = BigInt(state.totalSupply)
|
|
50
52
|
} else {
|
|
51
53
|
this.#name = name
|
|
52
54
|
this.#symbol = symbol
|
|
@@ -60,7 +62,7 @@ export default class Lock extends PublicVoting {
|
|
|
60
62
|
/**
|
|
61
63
|
* @return {Object} {holders, balances, ...}
|
|
62
64
|
*/
|
|
63
|
-
get state():
|
|
65
|
+
get state(): LockState {
|
|
64
66
|
return {
|
|
65
67
|
...super.state,
|
|
66
68
|
holders: this.holders,
|
|
@@ -70,7 +72,7 @@ export default class Lock extends PublicVoting {
|
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
get totalSupply():
|
|
75
|
+
get totalSupply(): bigint {
|
|
74
76
|
return this.#totalSupply
|
|
75
77
|
}
|
|
76
78
|
|
|
@@ -82,11 +84,11 @@ export default class Lock extends PublicVoting {
|
|
|
82
84
|
return this.#symbol
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
get holders():
|
|
87
|
+
get holders(): LockState['holders'] {
|
|
86
88
|
return this.#holders
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
get balances():
|
|
91
|
+
get balances(): LockState['balances'] {
|
|
90
92
|
return { ...this.#balances }
|
|
91
93
|
}
|
|
92
94
|
|
|
@@ -98,41 +100,40 @@ export default class Lock extends PublicVoting {
|
|
|
98
100
|
return this.#decimals
|
|
99
101
|
}
|
|
100
102
|
|
|
101
|
-
mint(to: address, amount:
|
|
103
|
+
mint(to: address, amount: bigint) {
|
|
102
104
|
if (!this.hasRole(msg.sender, 'MINT')) throw new Error('not allowed')
|
|
103
105
|
|
|
104
|
-
this.#totalSupply = this.#totalSupply
|
|
106
|
+
this.#totalSupply = this.#totalSupply + amount
|
|
105
107
|
this.#increaseBalance(to, amount)
|
|
106
108
|
}
|
|
107
109
|
|
|
108
|
-
burn(from: address, amount:
|
|
110
|
+
burn(from: address, amount: bigint) {
|
|
109
111
|
if (!this.hasRole(msg.sender, 'BURN') || msg.sender !== from) throw new Error('not allowed')
|
|
110
|
-
const total = this.#totalSupply
|
|
111
|
-
if (total
|
|
112
|
+
const total = this.#totalSupply - amount
|
|
113
|
+
if (total > 0n) {
|
|
112
114
|
this.#totalSupply = total
|
|
113
115
|
this.#decreaseBalance(from, amount)
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
|
|
117
|
-
#beforeTransfer(from: address, to: address, amount:
|
|
119
|
+
#beforeTransfer(from: address, to: address, amount: bigint) {
|
|
118
120
|
if (!this.#balances[from] || this.#balances[from] < amount) throw new Error('amount exceeds balance')
|
|
119
121
|
}
|
|
120
122
|
|
|
121
|
-
#updateHolders(address: address, previousBalance:
|
|
122
|
-
if (this.#balances[address]
|
|
123
|
-
else if (this.#balances[address]
|
|
124
|
-
this.#holders.add(1)
|
|
123
|
+
#updateHolders(address: address, previousBalance: bigint) {
|
|
124
|
+
if (this.#balances[address] === 0n) this.#holders - 1n
|
|
125
|
+
else if (this.#balances[address] !== 0n && previousBalance === 0n) this.#holders + 1n
|
|
125
126
|
}
|
|
126
127
|
|
|
127
|
-
#increaseBalance(address: address, amount:
|
|
128
|
-
if (!this.#balances[address]) this.#balances[address] =
|
|
128
|
+
#increaseBalance(address: address, amount: bigint) {
|
|
129
|
+
if (!this.#balances[address]) this.#balances[address] = BigInt(0)
|
|
129
130
|
const previousBalance = this.#balances[address]
|
|
130
131
|
|
|
131
132
|
this.#balances[address] = this.#balances[address].add(amount)
|
|
132
133
|
this.#updateHolders(address, previousBalance)
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
#decreaseBalance(address: address, amount:
|
|
136
|
+
#decreaseBalance(address: address, amount: bigint) {
|
|
136
137
|
const previousBalance = this.#balances[address]
|
|
137
138
|
this.#balances[address] = this.#balances[address].sub(amount)
|
|
138
139
|
this.#updateHolders(address, previousBalance)
|
|
@@ -142,23 +143,23 @@ export default class Lock extends PublicVoting {
|
|
|
142
143
|
return this.#balances[msg.sender]
|
|
143
144
|
}
|
|
144
145
|
|
|
145
|
-
balanceOf(address: address):
|
|
146
|
+
balanceOf(address: address): bigint {
|
|
146
147
|
return this.#balances[address]
|
|
147
148
|
}
|
|
148
149
|
|
|
149
|
-
setApproval(operator: address, amount:
|
|
150
|
+
setApproval(operator: address, amount: bigint) {
|
|
150
151
|
const owner = msg.sender
|
|
151
152
|
if (!this.#approvals[owner]) this.#approvals[owner] = {}
|
|
152
|
-
this.#approvals[owner][operator] =
|
|
153
|
+
this.#approvals[owner][operator] = BigInt(amount)
|
|
153
154
|
}
|
|
154
155
|
|
|
155
|
-
approved(owner: address, operator: address, amount:
|
|
156
|
+
approved(owner: address, operator: address, amount: bigint): boolean {
|
|
156
157
|
return this.#approvals[owner][operator] === amount
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
transfer(from: address, to: address, amount:
|
|
160
|
+
transfer(from: address, to: address, amount: bigint) {
|
|
160
161
|
// TODO: is BigNumber?
|
|
161
|
-
amount =
|
|
162
|
+
amount = BigInt(amount)
|
|
162
163
|
this.#beforeTransfer(from, to, amount)
|
|
163
164
|
this.#decreaseBalance(from, amount)
|
|
164
165
|
this.#increaseBalance(to, amount)
|
package/src/staking.ts
CHANGED
|
@@ -2,13 +2,13 @@ import { restoreApprovals, restoreBalances } from './helpers.js'
|
|
|
2
2
|
import Roles, { RolesState } from './roles.js'
|
|
3
3
|
|
|
4
4
|
export declare interface TokenState extends RolesState {
|
|
5
|
-
holders:
|
|
6
|
-
balances: { [address: address]:
|
|
7
|
-
approvals: { [owner: address]: { [operator: address]:
|
|
8
|
-
totalSupply:
|
|
5
|
+
holders: bigint
|
|
6
|
+
balances: { [address: address]: bigint }
|
|
7
|
+
approvals: { [owner: address]: { [operator: address]: bigint } }
|
|
8
|
+
totalSupply: bigint
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export default class
|
|
11
|
+
export default class Staking extends Roles {
|
|
12
12
|
/**
|
|
13
13
|
* string
|
|
14
14
|
*/
|
|
@@ -20,7 +20,7 @@ export default class Token extends Roles {
|
|
|
20
20
|
/**
|
|
21
21
|
* uint
|
|
22
22
|
*/
|
|
23
|
-
#holders:
|
|
23
|
+
#holders: bigint = BigInt(0)
|
|
24
24
|
/**
|
|
25
25
|
* Object => Object => uint
|
|
26
26
|
*/
|
|
@@ -28,11 +28,13 @@ export default class Token extends Roles {
|
|
|
28
28
|
/**
|
|
29
29
|
* Object => Object => uint
|
|
30
30
|
*/
|
|
31
|
-
#approvals: { [owner: string]: { [operator: string]:
|
|
31
|
+
#approvals: { [owner: string]: { [operator: string]: bigint } } = {}
|
|
32
32
|
|
|
33
33
|
#decimals = 18
|
|
34
34
|
|
|
35
|
-
#totalSupply:
|
|
35
|
+
#totalSupply: bigint = BigInt(0)
|
|
36
|
+
|
|
37
|
+
#stakingContract: address
|
|
36
38
|
|
|
37
39
|
// this.#privateField2 = 1
|
|
38
40
|
constructor(name: string, symbol: string, decimals: number = 18, state?: TokenState) {
|
|
@@ -44,8 +46,8 @@ export default class Token extends Roles {
|
|
|
44
46
|
if (state) {
|
|
45
47
|
this.#balances = restoreBalances(state.balances)
|
|
46
48
|
this.#approvals = restoreApprovals(state.approvals)
|
|
47
|
-
this.#holders =
|
|
48
|
-
this.#totalSupply =
|
|
49
|
+
this.#holders = BigInt(state.holders)
|
|
50
|
+
this.#totalSupply = BigInt(state.totalSupply)
|
|
49
51
|
} else {
|
|
50
52
|
this.#name = name
|
|
51
53
|
this.#symbol = symbol
|
|
@@ -69,7 +71,7 @@ export default class Token extends Roles {
|
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
get totalSupply():
|
|
74
|
+
get totalSupply(): bigint {
|
|
73
75
|
return this.#totalSupply
|
|
74
76
|
}
|
|
75
77
|
|
|
@@ -97,41 +99,40 @@ export default class Token extends Roles {
|
|
|
97
99
|
return this.#decimals
|
|
98
100
|
}
|
|
99
101
|
|
|
100
|
-
mint(to: address, amount:
|
|
102
|
+
mint(to: address, amount: bigint) {
|
|
101
103
|
if (!this.hasRole(msg.sender, 'MINT')) throw new Error('not allowed')
|
|
102
104
|
|
|
103
|
-
this.#totalSupply = this.#totalSupply
|
|
105
|
+
this.#totalSupply = this.#totalSupply + amount
|
|
104
106
|
this.#increaseBalance(to, amount)
|
|
105
107
|
}
|
|
106
108
|
|
|
107
|
-
burn(from: address, amount:
|
|
109
|
+
burn(from: address, amount: bigint) {
|
|
108
110
|
if (!this.hasRole(msg.sender, 'BURN') || msg.sender !== from) throw new Error('not allowed')
|
|
109
|
-
const total = this.#totalSupply
|
|
110
|
-
if (total
|
|
111
|
+
const total = this.#totalSupply - amount
|
|
112
|
+
if (total > 0n) {
|
|
111
113
|
this.#totalSupply = total
|
|
112
114
|
this.#decreaseBalance(from, amount)
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
#beforeTransfer(from: address, to: address, amount:
|
|
118
|
+
#beforeTransfer(from: address, to: address, amount: bigint) {
|
|
117
119
|
if (!this.#balances[from] || this.#balances[from] < amount) throw new Error('amount exceeds balance')
|
|
118
120
|
}
|
|
119
121
|
|
|
120
|
-
#updateHolders(address: address, previousBalance:
|
|
121
|
-
if (this.#balances[address]
|
|
122
|
-
else if (this.#balances[address]
|
|
123
|
-
this.#holders.add(1)
|
|
122
|
+
#updateHolders(address: address, previousBalance: bigint) {
|
|
123
|
+
if (this.#balances[address] === 0n) this.#holders - 1n
|
|
124
|
+
else if (this.#balances[address] !== 0n && previousBalance === 0n) this.#holders + 1n
|
|
124
125
|
}
|
|
125
126
|
|
|
126
|
-
#increaseBalance(address: address, amount:
|
|
127
|
-
if (!this.#balances[address]) this.#balances[address] =
|
|
127
|
+
#increaseBalance(address: address, amount: bigint) {
|
|
128
|
+
if (!this.#balances[address]) this.#balances[address] = BigInt(0)
|
|
128
129
|
const previousBalance = this.#balances[address]
|
|
129
130
|
|
|
130
131
|
this.#balances[address] = this.#balances[address].add(amount)
|
|
131
132
|
this.#updateHolders(address, previousBalance)
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
#decreaseBalance(address: address, amount:
|
|
135
|
+
#decreaseBalance(address: address, amount: bigint) {
|
|
135
136
|
const previousBalance = this.#balances[address]
|
|
136
137
|
this.#balances[address] = this.#balances[address].sub(amount)
|
|
137
138
|
this.#updateHolders(address, previousBalance)
|
|
@@ -141,23 +142,23 @@ export default class Token extends Roles {
|
|
|
141
142
|
return this.#balances[msg.sender]
|
|
142
143
|
}
|
|
143
144
|
|
|
144
|
-
balanceOf(address: address):
|
|
145
|
+
balanceOf(address: address): bigint {
|
|
145
146
|
return this.#balances[address]
|
|
146
147
|
}
|
|
147
148
|
|
|
148
|
-
setApproval(operator: address, amount:
|
|
149
|
+
setApproval(operator: address, amount: bigint) {
|
|
149
150
|
const owner = msg.sender
|
|
150
151
|
if (!this.#approvals[owner]) this.#approvals[owner] = {}
|
|
151
|
-
this.#approvals[owner][operator] =
|
|
152
|
+
this.#approvals[owner][operator] = BigInt(amount)
|
|
152
153
|
}
|
|
153
154
|
|
|
154
|
-
approved(owner: address, operator: address, amount:
|
|
155
|
+
approved(owner: address, operator: address, amount: bigint): boolean {
|
|
155
156
|
return this.#approvals[owner][operator] === amount
|
|
156
157
|
}
|
|
157
158
|
|
|
158
|
-
transfer(from: address, to: address, amount:
|
|
159
|
+
transfer(from: address, to: address, amount: bigint) {
|
|
159
160
|
// TODO: is BigNumber?
|
|
160
|
-
amount =
|
|
161
|
+
amount = BigInt(amount)
|
|
161
162
|
this.#beforeTransfer(from, to, amount)
|
|
162
163
|
this.#decreaseBalance(from, amount)
|
|
163
164
|
this.#increaseBalance(to, amount)
|
package/src/token-receiver.ts
CHANGED
|
@@ -4,31 +4,26 @@ import PublicVoting, { PublicVotingState } from './voting/public-voting.js'
|
|
|
4
4
|
export interface TokenReceiverState extends PublicVotingState {
|
|
5
5
|
tokenToReceive: address
|
|
6
6
|
tokenReceiver: address
|
|
7
|
-
tokenAmountToReceive:
|
|
7
|
+
tokenAmountToReceive: bigint
|
|
8
8
|
voteType: 'burn' | 'transfer'
|
|
9
9
|
}
|
|
10
10
|
export default class TokenReceiver extends PublicVoting implements IVoting {
|
|
11
11
|
#tokenToReceive: address
|
|
12
|
-
#tokenAmountToReceive:
|
|
12
|
+
#tokenAmountToReceive: bigint
|
|
13
13
|
#tokenReceiver: address
|
|
14
14
|
#voteType: TokenReceiverState['voteType'] = 'transfer'
|
|
15
15
|
|
|
16
|
-
constructor(
|
|
17
|
-
tokenToReceive: address,
|
|
18
|
-
tokenAmountToReceive: typeof BigNumber,
|
|
19
|
-
burns: boolean,
|
|
20
|
-
state?: TokenReceiverState
|
|
21
|
-
) {
|
|
16
|
+
constructor(tokenToReceive: address, tokenAmountToReceive: bigint, burns: boolean, state?: TokenReceiverState) {
|
|
22
17
|
super(state)
|
|
23
18
|
if (state) {
|
|
24
19
|
this.#tokenReceiver = state.tokenReceiver
|
|
25
20
|
this.#tokenToReceive = state.tokenToReceive
|
|
26
|
-
this.#tokenAmountToReceive =
|
|
21
|
+
this.#tokenAmountToReceive = BigInt(state.tokenAmountToReceive)
|
|
27
22
|
this.#voteType = state.voteType
|
|
28
23
|
} else {
|
|
29
24
|
this.#tokenReceiver = msg.contract
|
|
30
25
|
this.#tokenToReceive = tokenToReceive
|
|
31
|
-
this.#tokenAmountToReceive =
|
|
26
|
+
this.#tokenAmountToReceive = BigInt(tokenAmountToReceive)
|
|
32
27
|
if (burns) this.#voteType = 'burn'
|
|
33
28
|
}
|
|
34
29
|
}
|
|
@@ -56,8 +51,8 @@ export default class TokenReceiver extends PublicVoting implements IVoting {
|
|
|
56
51
|
}
|
|
57
52
|
|
|
58
53
|
async #canVote() {
|
|
59
|
-
const amount = (await msg.staticCall(this.#tokenToReceive, 'balanceOf', [msg.sender])) as
|
|
60
|
-
return amount
|
|
54
|
+
const amount = (await msg.staticCall(this.#tokenToReceive, 'balanceOf', [msg.sender])) as bigint
|
|
55
|
+
return amount >= this.#tokenAmountToReceive
|
|
61
56
|
}
|
|
62
57
|
|
|
63
58
|
/**
|
|
@@ -106,7 +101,7 @@ export default class TokenReceiver extends PublicVoting implements IVoting {
|
|
|
106
101
|
this.#tokenToReceive = address
|
|
107
102
|
}
|
|
108
103
|
|
|
109
|
-
#changeTokenAmountToReceive(amount:
|
|
104
|
+
#changeTokenAmountToReceive(amount: bigint) {
|
|
110
105
|
this.#tokenAmountToReceive = amount
|
|
111
106
|
}
|
|
112
107
|
|
|
@@ -114,13 +109,13 @@ export default class TokenReceiver extends PublicVoting implements IVoting {
|
|
|
114
109
|
this.#voteType = type
|
|
115
110
|
}
|
|
116
111
|
|
|
117
|
-
#getTokensOut(amount:
|
|
112
|
+
#getTokensOut(amount: bigint, receiver: address) {
|
|
118
113
|
return msg.call(this.#tokenReceiver, 'transfer', [this.#tokenReceiver, receiver, amount])
|
|
119
114
|
}
|
|
120
115
|
|
|
121
116
|
async changeVoteType(type: TokenReceiverState['voteType']) {
|
|
122
117
|
if (!this.#canVote()) throw new Error('not a allowed')
|
|
123
|
-
if (this.#voteType === 'transfer' && (await this.#balance())
|
|
118
|
+
if (this.#voteType === 'transfer' && (await this.#balance()) > 0n)
|
|
124
119
|
throw new Error('get tokens out first or they be lost forever')
|
|
125
120
|
else {
|
|
126
121
|
this.createVote(
|
|
@@ -133,7 +128,7 @@ export default class TokenReceiver extends PublicVoting implements IVoting {
|
|
|
133
128
|
}
|
|
134
129
|
}
|
|
135
130
|
|
|
136
|
-
getTokensOut(amount:
|
|
131
|
+
getTokensOut(amount: bigint, receiver: address) {
|
|
137
132
|
if (!this.#canVote()) throw new Error('not a allowed')
|
|
138
133
|
else {
|
|
139
134
|
this.createVote(
|
|
@@ -159,13 +154,13 @@ export default class TokenReceiver extends PublicVoting implements IVoting {
|
|
|
159
154
|
}
|
|
160
155
|
}
|
|
161
156
|
|
|
162
|
-
#balance(): Promise<
|
|
157
|
+
#balance(): Promise<bigint> {
|
|
163
158
|
return msg.staticCall(this.#tokenToReceive, 'balanceOf', [this.#tokenReceiver])
|
|
164
159
|
}
|
|
165
160
|
|
|
166
161
|
async changeTokenToReceive() {
|
|
167
162
|
if (!this.#canVote()) throw new Error('not a allowed')
|
|
168
|
-
if (
|
|
163
|
+
if ((await this.#balance()) > 0n && this.#voteType === 'transfer')
|
|
169
164
|
throw new Error('get tokens out first or they be lost forever')
|
|
170
165
|
else {
|
|
171
166
|
this.createVote(
|
package/src/token.ts
CHANGED
|
@@ -5,10 +5,11 @@ export declare interface TokenState extends RolesState {
|
|
|
5
5
|
name: string
|
|
6
6
|
symbol: string
|
|
7
7
|
decimals: number
|
|
8
|
-
holders:
|
|
9
|
-
balances: { [address: address]:
|
|
10
|
-
approvals: { [owner: address]: { [operator: address]:
|
|
11
|
-
totalSupply:
|
|
8
|
+
holders: bigint
|
|
9
|
+
balances: { [address: address]: bigint }
|
|
10
|
+
approvals: { [owner: address]: { [operator: address]: bigint } }
|
|
11
|
+
totalSupply: bigint
|
|
12
|
+
maxSupply: bigint // 0 for unlimited
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export default class Token extends Roles {
|
|
@@ -23,7 +24,7 @@ export default class Token extends Roles {
|
|
|
23
24
|
/**
|
|
24
25
|
* uint
|
|
25
26
|
*/
|
|
26
|
-
#holders:
|
|
27
|
+
#holders: bigint = BigInt(0)
|
|
27
28
|
/**
|
|
28
29
|
* Object => Object => uint
|
|
29
30
|
*/
|
|
@@ -31,15 +32,16 @@ export default class Token extends Roles {
|
|
|
31
32
|
/**
|
|
32
33
|
* Object => Object => uint
|
|
33
34
|
*/
|
|
34
|
-
#approvals: { [owner: string]: { [operator: string]:
|
|
35
|
+
#approvals: { [owner: string]: { [operator: string]: bigint } } = {}
|
|
35
36
|
|
|
36
37
|
#decimals = 18
|
|
37
38
|
|
|
38
|
-
#totalSupply:
|
|
39
|
+
#totalSupply: bigint = BigInt(0)
|
|
40
|
+
|
|
41
|
+
#maxSupply: bigint = BigInt(0)
|
|
39
42
|
|
|
40
43
|
#stakingContract: address
|
|
41
44
|
|
|
42
|
-
// this.#privateField2 = 1
|
|
43
45
|
constructor(name: string, symbol: string, decimals: number = 18, state?: TokenState) {
|
|
44
46
|
if (!name) throw new Error(`name undefined`)
|
|
45
47
|
if (!symbol) throw new Error(`symbol undefined`)
|
|
@@ -49,11 +51,12 @@ export default class Token extends Roles {
|
|
|
49
51
|
if (state) {
|
|
50
52
|
this.#balances = restoreBalances(state.balances)
|
|
51
53
|
this.#approvals = restoreApprovals(state.approvals)
|
|
52
|
-
this.#holders =
|
|
53
|
-
this.#totalSupply =
|
|
54
|
+
this.#holders = BigInt(state.holders)
|
|
55
|
+
this.#totalSupply = BigInt(state.totalSupply)
|
|
54
56
|
this.#name = name
|
|
55
57
|
this.#symbol = symbol
|
|
56
58
|
this.#decimals = decimals
|
|
59
|
+
this.#maxSupply = BigInt(state.maxSupply)
|
|
57
60
|
} else {
|
|
58
61
|
this.#name = name
|
|
59
62
|
this.#symbol = symbol
|
|
@@ -64,6 +67,7 @@ export default class Token extends Roles {
|
|
|
64
67
|
// enables snapshotting
|
|
65
68
|
// needs dev attention so nothing breaks after snapshot happens
|
|
66
69
|
// iow everything that is not static needs to be included in the stateObject
|
|
70
|
+
// TODO: implement snapshotting test
|
|
67
71
|
/**
|
|
68
72
|
* @return {Object} {holders, balances, ...}
|
|
69
73
|
*/
|
|
@@ -76,19 +80,24 @@ export default class Token extends Roles {
|
|
|
76
80
|
holders: this.holders,
|
|
77
81
|
balances: this.balances,
|
|
78
82
|
approvals: { ...this.#approvals },
|
|
79
|
-
totalSupply: this.totalSupply
|
|
83
|
+
totalSupply: this.totalSupply,
|
|
84
|
+
maxSupply: this.#maxSupply
|
|
80
85
|
}
|
|
81
86
|
}
|
|
82
87
|
|
|
83
|
-
get
|
|
88
|
+
get maxSupply(): TokenState['maxSupply'] {
|
|
89
|
+
return this.#maxSupply
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
get totalSupply(): TokenState['totalSupply'] {
|
|
84
93
|
return this.#totalSupply
|
|
85
94
|
}
|
|
86
95
|
|
|
87
|
-
get name():
|
|
96
|
+
get name(): TokenState['name'] {
|
|
88
97
|
return this.#name
|
|
89
98
|
}
|
|
90
99
|
|
|
91
|
-
get symbol():
|
|
100
|
+
get symbol(): TokenState['symbol'] {
|
|
92
101
|
return this.#symbol
|
|
93
102
|
}
|
|
94
103
|
|
|
@@ -100,49 +109,60 @@ export default class Token extends Roles {
|
|
|
100
109
|
return { ...this.#balances }
|
|
101
110
|
}
|
|
102
111
|
|
|
103
|
-
get approvals() {
|
|
112
|
+
get approvals(): TokenState['approvals'] {
|
|
104
113
|
return this.#approvals
|
|
105
114
|
}
|
|
106
115
|
|
|
107
|
-
get decimals() {
|
|
116
|
+
get decimals(): TokenState['decimals'] {
|
|
108
117
|
return this.#decimals
|
|
109
118
|
}
|
|
110
119
|
|
|
111
|
-
mint(to: address, amount:
|
|
120
|
+
mint(to: address, amount: bigint) {
|
|
112
121
|
if (!this.hasRole(msg.sender, 'MINT')) throw new Error('not allowed')
|
|
113
122
|
|
|
114
|
-
|
|
115
|
-
this.#
|
|
123
|
+
const supply = this.#totalSupply + amount
|
|
124
|
+
if (this.#maxSupply === 0n) {
|
|
125
|
+
this.#totalSupply = supply
|
|
126
|
+
this.#increaseBalance(to, amount)
|
|
127
|
+
} else {
|
|
128
|
+
if (supply <= this.#maxSupply) {
|
|
129
|
+
this.#totalSupply = supply
|
|
130
|
+
this.#increaseBalance(to, amount)
|
|
131
|
+
} else {
|
|
132
|
+
throw new Error('amount exceeds max supply')
|
|
133
|
+
}
|
|
134
|
+
}
|
|
116
135
|
}
|
|
117
136
|
|
|
118
|
-
burn(from: address, amount:
|
|
137
|
+
burn(from: address, amount: bigint) {
|
|
119
138
|
if (!this.hasRole(msg.sender, 'BURN') || msg.sender !== from) throw new Error('not allowed')
|
|
120
|
-
const total = this.#totalSupply
|
|
121
|
-
if (total
|
|
139
|
+
const total = this.#totalSupply - amount
|
|
140
|
+
if (total >= 0) {
|
|
122
141
|
this.#totalSupply = total
|
|
123
142
|
this.#decreaseBalance(from, amount)
|
|
143
|
+
} else {
|
|
144
|
+
throw new Error('amount exceeds total supply')
|
|
124
145
|
}
|
|
125
146
|
}
|
|
126
147
|
|
|
127
|
-
#beforeTransfer(from: address, to: address, amount:
|
|
148
|
+
#beforeTransfer(from: address, to: address, amount: bigint) {
|
|
128
149
|
if (!this.#balances[from] || this.#balances[from] < amount) throw new Error('amount exceeds balance')
|
|
129
150
|
}
|
|
130
151
|
|
|
131
|
-
#updateHolders(address: address, previousBalance:
|
|
132
|
-
if (this.#balances[address]
|
|
133
|
-
else if (this.#balances[address]
|
|
134
|
-
this.#holders.add(1)
|
|
152
|
+
#updateHolders(address: address, previousBalance: bigint) {
|
|
153
|
+
if (this.#balances[address] === 0n) this.#holders - 1n
|
|
154
|
+
else if (this.#balances[address] !== 0n && previousBalance === 0n) this.#holders + 1n
|
|
135
155
|
}
|
|
136
156
|
|
|
137
|
-
#increaseBalance(address: address, amount:
|
|
138
|
-
if (!this.#balances[address]) this.#balances[address] =
|
|
157
|
+
#increaseBalance(address: address, amount: bigint) {
|
|
158
|
+
if (!this.#balances[address]) this.#balances[address] = BigInt(0)
|
|
139
159
|
const previousBalance = this.#balances[address]
|
|
140
160
|
|
|
141
161
|
this.#balances[address] = this.#balances[address].add(amount)
|
|
142
162
|
this.#updateHolders(address, previousBalance)
|
|
143
163
|
}
|
|
144
164
|
|
|
145
|
-
#decreaseBalance(address: address, amount:
|
|
165
|
+
#decreaseBalance(address: address, amount: bigint) {
|
|
146
166
|
const previousBalance = this.#balances[address]
|
|
147
167
|
this.#balances[address] = this.#balances[address].sub(amount)
|
|
148
168
|
this.#updateHolders(address, previousBalance)
|
|
@@ -152,23 +172,23 @@ export default class Token extends Roles {
|
|
|
152
172
|
return this.#balances[msg.sender]
|
|
153
173
|
}
|
|
154
174
|
|
|
155
|
-
balanceOf(address: address):
|
|
175
|
+
balanceOf(address: address): bigint {
|
|
156
176
|
return this.#balances[address]
|
|
157
177
|
}
|
|
158
178
|
|
|
159
|
-
setApproval(operator: address, amount:
|
|
179
|
+
setApproval(operator: address, amount: bigint) {
|
|
160
180
|
const owner = msg.sender
|
|
161
181
|
if (!this.#approvals[owner]) this.#approvals[owner] = {}
|
|
162
|
-
this.#approvals[owner][operator] =
|
|
182
|
+
this.#approvals[owner][operator] = BigInt(amount)
|
|
163
183
|
}
|
|
164
184
|
|
|
165
|
-
approved(owner: address, operator: address, amount:
|
|
185
|
+
approved(owner: address, operator: address, amount: bigint): boolean {
|
|
166
186
|
return this.#approvals[owner][operator] === amount
|
|
167
187
|
}
|
|
168
188
|
|
|
169
|
-
transfer(from: address, to: address, amount:
|
|
170
|
-
// TODO: is
|
|
171
|
-
amount =
|
|
189
|
+
transfer(from: address, to: address, amount: bigint) {
|
|
190
|
+
// TODO: is bigint?
|
|
191
|
+
amount = BigInt(amount)
|
|
172
192
|
this.#beforeTransfer(from, to, amount)
|
|
173
193
|
this.#decreaseBalance(from, amount)
|
|
174
194
|
this.#increaseBalance(to, amount)
|
package/tsconfig.json
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
"outDir": "./exports",
|
|
6
6
|
"moduleResolution": "NodeNext",
|
|
7
7
|
"declaration": true,
|
|
8
|
-
"declarationDir": "./exports"
|
|
8
|
+
"declarationDir": "./exports",
|
|
9
|
+
"types": ["@leofcoin/types/global"]
|
|
9
10
|
},
|
|
10
|
-
"include": ["./src/*"
|
|
11
|
+
"include": ["./src/*"]
|
|
11
12
|
}
|