@leofcoin/chain 1.3.3 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/workers/machine-worker.js +0 -13
- package/dist/chain.js +155 -133
- package/dist/contracts/factory.js +1 -1
- package/dist/contracts/{nameService.js → name-service.js} +1 -1
- package/dist/contracts/native-token.js +1 -0
- package/dist/contracts/validators.js +1 -1
- package/dist/module/chain.js +152 -130
- package/dist/module/workers/machine-worker.js +0 -6
- package/dist/standards/token.js +1 -1
- package/dist/workers/machine-worker.js +1 -1
- package/package.json +20 -2
- package/rollup.config.js +4 -4
- package/src/chain.js +122 -104
- package/src/contracts/factory.js +58 -15
- package/src/contracts/{nameService.js → name-service.js} +3 -5
- package/src/contracts/{nativeToken.js → native-token.js} +2 -2
- package/src/contracts/{powerToken.js → power-token.js} +1 -1
- package/src/contracts/proxies/{factoryProxy.js → factory-proxy.js} +1 -1
- package/src/contracts/proxies/{nameServiceProxy.js → name-service-proxy.js} +1 -1
- package/src/contracts/proxies/{nativeTokenProxy.js → native-token-proxy.js} +1 -1
- package/src/contracts/proxies/{validatorsProxy.js → validators-proxy.js} +1 -1
- package/src/contracts/proxies/{votingProxy.js → voting-proxy.js} +1 -1
- package/src/contracts/{proxyManager.js → proxy-manager.js} +1 -1
- package/src/contracts/validators.js +35 -25
- package/src/fee/config.js +1 -1
- package/src/machine.js +30 -26
- package/src/standards/{proxyManager.js → proxy-manager.js} +0 -0
- package/src/standards/{Proxy.js → proxy.js} +4 -8
- package/src/standards/roles.js +7 -5
- package/src/standards/token.js +2 -2
- package/src/standards/voting.js +1 -0
- package/src/transactions/transaction.js +1 -3
- package/src/transactions/validator.js +1 -1
- package/src/typer.js +1 -1
- package/dist/865.browser.js +0 -10
- package/dist/chain.browser.js +0 -59745
- package/dist/contracts/nativeToken.js +0 -1
- package/dist/generate-account.browser.js +0 -50
- package/dist/messages.browser.js +0 -328
- package/dist/multi-wallet.browser.js +0 -15
- package/dist/node.browser.js +0 -9858
- package/dist/pako.browser.js +0 -6900
- package/dist/peernet-swarm.browser.js +0 -839
- package/dist/storage.browser.js +0 -3724
- package/dist/wrtc.browser.js +0 -28
- package/src/standards/Voting.js +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class Roles{#roles={IMPLEMENTATION_MANAGER:[],OWNER:[],MINT:[],BURN:[]};constructor(roles){if(roles){if(!(roles instanceof Object))throw new TypeError("expected roles to be an object");this.#roles={...roles,...this.#roles}}else this.#grantRole(msg.sender,"OWNER"),this.#grantRole(msg.sender,"IMPLEMENTATION_MANAGER")}get state(){return{roles:this.roles}}get roles(){return{...this.#roles}}hasRole(address,role){return!!this.#roles[role]&&this.#roles[role].includes(address)}#grantRole(address,role){if(this.hasRole(address,role))throw new Error(`${role} role already granted for ${address}`);this.#roles[role].push(address)}#revokeRole(address,role){if(!this.hasRole(address,role))throw new Error(`${role} role already revoked for ${address}`);if("OWNER"===role&&1===this.#roles[role].length)throw new Error("atleast one owner is needed!");this.#roles[role].splice(this.#roles[role].indexOf(address))}grantRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#grantRole(address,role)}revokeRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#revokeRole(address,role)}}class Token extends Roles{#name;#symbol;#holders=0;#balances={};#approvals={};#decimals=18;#totalSupply=BigNumber.from(0);constructor(name,symbol,decimals=18,state){if(!name)throw new Error("name undefined");if(!symbol)throw new Error("symbol undefined");super(state?.roles),this.#name=name,this.#symbol=symbol,this.#decimals=decimals}get state(){return{...super.state,holders:this.holders,balances:this.balances,approvals:{...this.#approvals},totalSupply:this.totalSupply}}get totalSupply(){return this.#totalSupply}get name(){return this.#name}get symbol(){return this.#symbol}get holders(){return this.#holders}get balances(){return{...this.#balances}}mint(to,amount){if(!this.hasRole(msg.sender,"MINT"))throw new Error("not allowed");this.#totalSupply=this.#totalSupply.add(amount),this.#increaseBalance(to,amount)}burn(from,amount){if(!this.hasRole(msg.sender,"BURN"))throw new Error("not allowed");this.#totalSupply=this.#totalSupply.sub(amount),this.#decreaseBalance(from,amount)}#beforeTransfer(from,to,amount){if(!this.#balances[from]||this.#balances[from]<amount)throw new Error("amount exceeds balance")}#updateHolders(address,previousBalance){"0x00"===this.#balances[address].toHexString()?this.#holders-=1:"0x00"!==this.#balances[address].toHexString()&&"0x00"===previousBalance.toHexString()&&(this.#holders+=1)}#increaseBalance(address,amount){this.#balances[address]||(this.#balances[address]=BigNumber.from(0));const previousBalance=this.#balances[address];this.#balances[address]=this.#balances[address].add(amount),this.#updateHolders(address,previousBalance)}#decreaseBalance(address,amount){const previousBalance=this.#balances[address];this.#balances[address]=this.#balances[address].sub(amount),this.#updateHolders(address,previousBalance)}balanceOf(address){return this.#balances[address]}setApproval(operator,amount){const owner=globalThis.msg.sender;this.#approvals[owner]||(this.#approvals[owner]={}),this.#approvals[owner][operator]=amount}approved(owner,operator,amount){return this.#approvals[owner][operator]===amount}transfer(from,to,amount){amount=BigNumber.from(amount),this.#beforeTransfer(from,to,amount),this.#decreaseBalance(from,amount),this.#increaseBalance(to,amount)}}class ArtOnline extends Token{constructor(state){super("ArtOnline","ART",18,state)}}export{ArtOnline as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class Validators{#name="ArtOnlineValidators";#totalValidators=0;#validators={};#
|
|
1
|
+
class Roles{#roles={IMPLEMENTATION_MANAGER:[],OWNER:[],MINT:[],BURN:[]};constructor(roles){if(roles){if(!(roles instanceof Object))throw new TypeError("expected roles to be an object");this.#roles={...roles,...this.#roles}}else this.#grantRole(msg.sender,"OWNER"),this.#grantRole(msg.sender,"IMPLEMENTATION_MANAGER")}get state(){return{roles:this.roles}}get roles(){return{...this.#roles}}hasRole(address,role){return!!this.#roles[role]&&this.#roles[role].includes(address)}#grantRole(address,role){if(this.hasRole(address,role))throw new Error(`${role} role already granted for ${address}`);this.#roles[role].push(address)}#revokeRole(address,role){if(!this.hasRole(address,role))throw new Error(`${role} role already revoked for ${address}`);if("OWNER"===role&&1===this.#roles[role].length)throw new Error("atleast one owner is needed!");this.#roles[role].splice(this.#roles[role].indexOf(address))}grantRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#grantRole(address,role)}revokeRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#revokeRole(address,role)}}class Validators extends Roles{#name="ArtOnlineValidators";#totalValidators=0;#activeValidators=0;#validators={};#currency;#minimumBalance;get state(){return{...super.state,minimumBalance:this.#minimumBalance,currency:this.#currency,totalValidators:this.#totalValidators,activeValidators:this.#activeValidators,validators:this.#validators}}constructor(tokenAddress,state){super(state?.roles),state?(this.#minimumBalance=state.minimumBalance,this.#currency=state.currency,this.#totalValidators=state.totalValidators,this.#activeValidators=state.activeValidators,this.#validators=state.validators):(this.#minimumBalance=5e4,this.#currency=tokenAddress,this.#totalValidators+=1,this.#activeValidators+=1,this.#validators[msg.sender]={firstSeen:Date.now(),lastSeen:Date.now(),active:!0})}get name(){return this.#name}get currency(){return this.#currency}get validators(){return{...this.#validators}}get totalValidators(){return this.#totalValidators}get minimumBalance(){return this.#minimumBalance}changeCurrency(currency){if(!this.hasRole(msg.sender,"OWNER"))throw new Error("not an owner");this.#currency=currency}has(validator){return Boolean(void 0!==this.#validators[validator])}#isAllowed(address){if(msg.sender!==address&&!this.hasRole(msg.sender,"OWNER"))throw new Error("sender is not the validator or owner");return!0}async addValidator(validator){if(this.#isAllowed(validator),this.has(validator))throw new Error("already a validator");const balance=await msg.staticCall(this.currency,"balanceOf",[validator]);if(balance<this.minimumBalance)throw new Error(`balance to low! got: ${balance} need: ${this.#minimumBalance}`);this.#totalValidators+=1,this.#activeValidators+=1,this.#validators[validator]={firstSeen:Date.now(),lastSeen:Date.now(),active:!0}}removeValidator(validator){if(this.#isAllowed(validator),!this.has(validator))throw new Error("validator not found");this.#totalValidators-=1,this.#validators[validator].active&&(this.#activeValidators-=1),delete this.#validators[validator]}async updateValidator(validator,active){if(this.#isAllowed(validator),!this.has(validator))throw new Error("validator not found");const balance=await msg.staticCall(this.currency,"balanceOf",[validator]);if(balance<this.minimumBalance&&active)throw new Error(`balance to low! got: ${balance} need: ${this.#minimumBalance}`);if(this.#validators[validator].active===active)throw new Error("already "+(active?"activated":"deactivated"));active?this.#activeValidators+=1:this.#activeValidators-=1,this.#validators[validator].active=active}}export{Validators as default};
|
package/dist/module/chain.js
CHANGED
|
@@ -3,8 +3,8 @@ import _BN from 'bn.js';
|
|
|
3
3
|
import '@ethersproject/bytes';
|
|
4
4
|
import { Logger } from '@ethersproject/logger';
|
|
5
5
|
import '@ethersproject/bignumber';
|
|
6
|
-
import { randomBytes } from 'crypto';
|
|
7
|
-
import { join } from 'path';
|
|
6
|
+
import { randomBytes } from 'node:crypto';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
8
|
import EasyWorker from '@vandeurenglenn/easy-worker';
|
|
9
9
|
import { FormatInterface } from '@leofcoin/codec-format-interface';
|
|
10
10
|
import MultiWallet from '@leofcoin/multi-wallet';
|
|
@@ -69,26 +69,31 @@ class Machine {
|
|
|
69
69
|
|
|
70
70
|
async #onmessage(data) {
|
|
71
71
|
switch (data.type) {
|
|
72
|
-
case 'contractError':
|
|
72
|
+
case 'contractError': {
|
|
73
73
|
console.warn(`removing contract ${await data.hash}`);
|
|
74
74
|
await contractStore.delete(await data.hash);
|
|
75
75
|
break
|
|
76
|
+
}
|
|
76
77
|
|
|
77
|
-
case 'executionError':
|
|
78
|
+
case 'executionError': {
|
|
78
79
|
// console.warn(`error executing transaction ${data.message}`);
|
|
79
80
|
pubsub.publish(data.id, {error: data.message});
|
|
80
81
|
break
|
|
82
|
+
}
|
|
81
83
|
|
|
82
|
-
case 'debug':
|
|
83
|
-
data.messages
|
|
84
|
+
case 'debug': {
|
|
85
|
+
for (const message of data.messages) debug(message);
|
|
84
86
|
break
|
|
85
|
-
|
|
87
|
+
}
|
|
88
|
+
case 'machine-ready': {
|
|
86
89
|
this.lastBlock = data.lastBlock;
|
|
87
90
|
pubsub.publish('machine.ready', true);
|
|
88
91
|
break
|
|
89
|
-
|
|
92
|
+
}
|
|
93
|
+
case 'response': {
|
|
90
94
|
pubsub.publish(data.id, data.value);
|
|
91
95
|
break
|
|
96
|
+
}
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
}
|
|
@@ -124,19 +129,19 @@ class Machine {
|
|
|
124
129
|
}
|
|
125
130
|
|
|
126
131
|
async #runContract(contractMessage) {
|
|
127
|
-
const
|
|
132
|
+
const parameters = contractMessage.decoded.constructorParameters;
|
|
128
133
|
try {
|
|
129
134
|
|
|
130
|
-
const
|
|
131
|
-
const Contract =
|
|
135
|
+
const function_ = new Function(contractMessage.decoded.contract);
|
|
136
|
+
const Contract = function_();
|
|
132
137
|
|
|
133
138
|
globalThis.msg = this.#createMessage(contractMessage.decoded.creator);
|
|
134
139
|
// globalThis.msg = {sender: contractMessage.decoded.creator}
|
|
135
|
-
this.#contracts[await contractMessage.hash] = await new Contract(...
|
|
140
|
+
this.#contracts[await contractMessage.hash] = await new Contract(...parameters);
|
|
136
141
|
debug(`loaded contract: ${await contractMessage.hash}`);
|
|
137
142
|
debug(`size: ${formatBytes(contractMessage.encoded.length)}`);
|
|
138
|
-
} catch (
|
|
139
|
-
console.log(
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.log(error);
|
|
140
145
|
console.warn(`removing contract ${await contractMessage.hash}`);
|
|
141
146
|
await contractStore.delete(await contractMessage.hash, contractMessage.encoded);
|
|
142
147
|
}
|
|
@@ -145,15 +150,14 @@ class Machine {
|
|
|
145
150
|
* @params {ContractMessage} - contractMessage
|
|
146
151
|
*/
|
|
147
152
|
async addContract(contractMessage) {
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
throw new Error('duplicate contract')
|
|
153
|
+
if (await contractStore.has(await contractMessage.hash)) throw new Error('duplicate contract')
|
|
154
|
+
|
|
155
|
+
await contractStore.put(await contractMessage.hash, contractMessage.encoded);
|
|
156
|
+
await this.#runContract(contractMessage);
|
|
157
|
+
return contractMessage.hash
|
|
154
158
|
}
|
|
155
159
|
|
|
156
|
-
async execute(contract, method,
|
|
160
|
+
async execute(contract, method, parameters) {
|
|
157
161
|
return new Promise((resolve, reject) => {
|
|
158
162
|
const id = randomBytes(20).toString('hex');
|
|
159
163
|
const message = message => {
|
|
@@ -167,22 +171,22 @@ class Machine {
|
|
|
167
171
|
input: {
|
|
168
172
|
contract,
|
|
169
173
|
method,
|
|
170
|
-
params
|
|
174
|
+
params: parameters
|
|
171
175
|
}
|
|
172
176
|
});
|
|
173
177
|
})
|
|
174
178
|
|
|
175
179
|
}
|
|
176
180
|
|
|
177
|
-
addJob(contract, method,
|
|
181
|
+
addJob(contract, method, parameters, from, nonce) {
|
|
178
182
|
if (!this.#nonces[from]) this.#nonces[from] = nonce;
|
|
179
|
-
if (nonce === this.#nonces[from] + 1) return this.#contracts[contract][method](...
|
|
183
|
+
if (nonce === this.#nonces[from] + 1) return this.#contracts[contract][method](...parameters)
|
|
180
184
|
// return setTimeout(() => {
|
|
181
185
|
// return this.addJob(contract, method, params, from, nonce)
|
|
182
186
|
// }, 50)
|
|
183
187
|
}
|
|
184
188
|
|
|
185
|
-
get(contract, method,
|
|
189
|
+
get(contract, method, parameters) {
|
|
186
190
|
return new Promise((resolve, reject) => {
|
|
187
191
|
const id = randomBytes(20).toString();
|
|
188
192
|
const message = message => {
|
|
@@ -195,7 +199,7 @@ class Machine {
|
|
|
195
199
|
input: {
|
|
196
200
|
contract,
|
|
197
201
|
method,
|
|
198
|
-
params
|
|
202
|
+
params: parameters
|
|
199
203
|
}
|
|
200
204
|
});
|
|
201
205
|
})
|
|
@@ -404,8 +408,10 @@ class Chain {
|
|
|
404
408
|
#blocks = []
|
|
405
409
|
#machine
|
|
406
410
|
#runningEpoch = false
|
|
411
|
+
#chainSyncing = false
|
|
407
412
|
#lastBlock = {index: 0, hash: '0x0', previousHash: '0x0'}
|
|
408
|
-
|
|
413
|
+
#participants = []
|
|
414
|
+
#participating = false
|
|
409
415
|
#jail = []
|
|
410
416
|
|
|
411
417
|
constructor() {
|
|
@@ -445,14 +451,14 @@ class Chain {
|
|
|
445
451
|
console.log(validators);
|
|
446
452
|
if (!validators[peernet.selectedAccount]?.active) return
|
|
447
453
|
|
|
448
|
-
const start =
|
|
454
|
+
const start = Date.now();
|
|
449
455
|
try {
|
|
450
456
|
await this.#createBlock();
|
|
451
|
-
} catch (
|
|
452
|
-
console.error(
|
|
457
|
+
} catch (error) {
|
|
458
|
+
console.error(error);
|
|
453
459
|
}
|
|
454
460
|
|
|
455
|
-
const end =
|
|
461
|
+
const end = Date.now();
|
|
456
462
|
console.log(((end - start) / 1000) + ' s');
|
|
457
463
|
|
|
458
464
|
if (await this.hasTransactionToHandle()) return this.#runEpoch()
|
|
@@ -489,7 +495,7 @@ class Chain {
|
|
|
489
495
|
const timeout = setTimeout(() => {
|
|
490
496
|
resolve([{index: 0, hash: '0x0'}]);
|
|
491
497
|
debug('sync timed out');
|
|
492
|
-
},
|
|
498
|
+
}, 10_000);
|
|
493
499
|
|
|
494
500
|
promises = await Promise.allSettled(promises);
|
|
495
501
|
promises = promises.filter(({status}) => status === 'fulfilled');
|
|
@@ -503,11 +509,11 @@ class Chain {
|
|
|
503
509
|
|
|
504
510
|
}
|
|
505
511
|
|
|
506
|
-
|
|
507
|
-
return this.#
|
|
512
|
+
getLatestBlock() {
|
|
513
|
+
return this.#getLatestBlock()
|
|
508
514
|
}
|
|
509
515
|
|
|
510
|
-
async #
|
|
516
|
+
async #getLatestBlock() {
|
|
511
517
|
let promises = [];
|
|
512
518
|
|
|
513
519
|
let data = await new peernet.protos['peernet-request']({request: 'lastBlock'});
|
|
@@ -519,26 +525,27 @@ class Chain {
|
|
|
519
525
|
} else if (!peer.connected || peer.readyState !== 'open') ;
|
|
520
526
|
}
|
|
521
527
|
promises = await this.promiseRequests(promises);
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
return set
|
|
529
|
-
}, {index: 0, hash: '0x0'});
|
|
530
|
-
// get lastblock
|
|
531
|
-
if (promises.hash && promises.hash !== '0x0') {
|
|
532
|
-
await peernet.get(promises.hash);
|
|
528
|
+
let latest = {index: 0, hash: '0x0'};
|
|
529
|
+
|
|
530
|
+
for (const value of promises) {
|
|
531
|
+
if (value.index > latest.index) {
|
|
532
|
+
latest.index = value.index;
|
|
533
|
+
latest.hash = value.hash;
|
|
533
534
|
}
|
|
534
|
-
|
|
535
|
-
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
if (latest.hash && latest.hash !== '0x0') {
|
|
538
|
+
let latestBlock = await peernet.get(latest.hash, block);
|
|
539
|
+
latestBlock = await new BlockMessage(latestBlock);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
return latestBlock
|
|
536
543
|
}
|
|
537
544
|
|
|
538
545
|
async #init() {
|
|
539
546
|
// this.node = await new Node()
|
|
540
|
-
this
|
|
541
|
-
this
|
|
547
|
+
this.#participants = [];
|
|
548
|
+
this.#participating = false;
|
|
542
549
|
const initialized = await contractStore.has(addresses.contractFactory);
|
|
543
550
|
if (!initialized) await this.#setup();
|
|
544
551
|
|
|
@@ -549,7 +556,7 @@ class Chain {
|
|
|
549
556
|
let localBlock;
|
|
550
557
|
try {
|
|
551
558
|
localBlock = await chainStore.get('lastBlock');
|
|
552
|
-
} catch
|
|
559
|
+
} catch{
|
|
553
560
|
await chainStore.put('lastBlock', '0x0');
|
|
554
561
|
localBlock = await chainStore.get('lastBlock');
|
|
555
562
|
}
|
|
@@ -559,13 +566,11 @@ class Chain {
|
|
|
559
566
|
localBlock = await new BlockMessage(localBlock);
|
|
560
567
|
this.#lastBlock = {...localBlock.decoded, hash: await localBlock.hash};
|
|
561
568
|
} else {
|
|
562
|
-
await this.#
|
|
569
|
+
const latestBlock = await this.#getLatestBlock();
|
|
570
|
+
await this.#syncChain(latestBlock);
|
|
563
571
|
}
|
|
564
|
-
} catch (
|
|
565
|
-
console.log({e});
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
// this.#setup()
|
|
572
|
+
} catch (error) {
|
|
573
|
+
console.log({e: error});
|
|
569
574
|
}
|
|
570
575
|
|
|
571
576
|
await peernet.addRequestHandler('bw-request-message', () => {
|
|
@@ -587,9 +592,6 @@ class Chain {
|
|
|
587
592
|
// load local blocks
|
|
588
593
|
await this.resolveBlocks();
|
|
589
594
|
this.#machine = await new Machine(this.#blocks);
|
|
590
|
-
// for (const block of this.#blocks) {
|
|
591
|
-
// block.loaded = true
|
|
592
|
-
// }
|
|
593
595
|
await this.#loadBlocks(this.#blocks);
|
|
594
596
|
return this
|
|
595
597
|
}
|
|
@@ -601,29 +603,33 @@ class Chain {
|
|
|
601
603
|
this.#jail.push(validatorInfo.address);
|
|
602
604
|
}
|
|
603
605
|
|
|
604
|
-
async #
|
|
605
|
-
|
|
606
|
-
node = await peernet.prepareMessage(node);
|
|
607
|
-
let response = await peer.request(node.encoded);
|
|
608
|
-
response = await new globalThis.peernet.protos['peernet-response'](response);
|
|
609
|
-
let lastBlock = response.decoded.response;
|
|
606
|
+
async #syncChain(lastBlock) {
|
|
607
|
+
if (this.#chainSyncing) return
|
|
610
608
|
|
|
611
609
|
if (!this.lastBlock || Number(this.lastBlock.index) < Number(lastBlock.index)) {
|
|
612
|
-
|
|
610
|
+
this.#chainSyncing = true;
|
|
611
|
+
// TODO: check if valid
|
|
613
612
|
const localIndex = this.lastBlock ? this.lastBlock.index : 0;
|
|
614
613
|
const index = lastBlock.index;
|
|
615
614
|
await this.resolveBlock(lastBlock.hash);
|
|
616
|
-
let blocksSynced = localIndex > 0 ? localIndex > index ? localIndex - index : index - localIndex : index;
|
|
615
|
+
let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index - localIndex) : index;
|
|
617
616
|
debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
|
|
618
617
|
|
|
619
618
|
this.#blocks.length;
|
|
620
|
-
const start =
|
|
619
|
+
const start = this.#blocks.length - blocksSynced;
|
|
621
620
|
await this.#loadBlocks(this.blocks.slice(start));
|
|
622
|
-
this.#
|
|
623
|
-
|
|
624
|
-
await blockStore.put(await message.hash, message.encoded);
|
|
625
|
-
await chainStore.put('lastBlock', this.lastBlock.hash);
|
|
621
|
+
await this.#updateState(this.#blocks[this.#blocks.length - 1]);
|
|
622
|
+
this.#chainSyncing = false;
|
|
626
623
|
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
async #peerConnected(peer) {
|
|
627
|
+
let node = await new peernet.protos['peernet-request']({request: 'lastBlock'});
|
|
628
|
+
node = await peernet.prepareMessage(node);
|
|
629
|
+
let response = await peer.request(node.encoded);
|
|
630
|
+
response = await new globalThis.peernet.protos['peernet-response'](response);
|
|
631
|
+
let lastBlock = response.decoded.response;
|
|
632
|
+
this.#syncChain(lastBlock);
|
|
627
633
|
}
|
|
628
634
|
|
|
629
635
|
#epochTimeout
|
|
@@ -633,9 +639,9 @@ class Chain {
|
|
|
633
639
|
transaction = await new TransactionMessage(transaction);
|
|
634
640
|
const has = await transactionPoolStore.has(await transaction.hash);
|
|
635
641
|
if (!has) await transactionPoolStore.put(await transaction.hash, transaction.encoded);
|
|
636
|
-
if (this
|
|
637
|
-
} catch
|
|
638
|
-
throw Error('invalid transaction')
|
|
642
|
+
if (this.#participating && !this.#runningEpoch) this.#runEpoch();
|
|
643
|
+
} catch {
|
|
644
|
+
throw new Error('invalid transaction')
|
|
639
645
|
}
|
|
640
646
|
}
|
|
641
647
|
|
|
@@ -648,7 +654,7 @@ async resolveBlock(hash) {
|
|
|
648
654
|
let block = await peernet.get(hash, 'block');
|
|
649
655
|
block = await new BlockMessage(block);
|
|
650
656
|
if (!await peernet.has(hash, 'block')) await peernet.put(hash, block.encoded, 'block');
|
|
651
|
-
const size = block.encoded.length
|
|
657
|
+
const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
|
|
652
658
|
block = {...block.decoded, hash};
|
|
653
659
|
if (this.#blocks[block.index] && this.#blocks[block.index].hash !== block.hash) throw `invalid block ${hash} @${block.index}`
|
|
654
660
|
this.#blocks[block.index] = block;
|
|
@@ -667,7 +673,7 @@ async resolveBlock(hash) {
|
|
|
667
673
|
await this.resolveBlock(hash);
|
|
668
674
|
this.#lastBlock = this.#blocks[this.#blocks.length - 1];
|
|
669
675
|
|
|
670
|
-
} catch
|
|
676
|
+
} catch {
|
|
671
677
|
await chainStore.put('lastBlock', new TextEncoder().encode('0x0'));
|
|
672
678
|
return this.resolveBlocks()
|
|
673
679
|
// console.log(e);
|
|
@@ -681,8 +687,8 @@ async resolveBlock(hash) {
|
|
|
681
687
|
try {
|
|
682
688
|
await this.#machine.execute(transaction.to, transaction.method, transaction.params);
|
|
683
689
|
|
|
684
|
-
} catch (
|
|
685
|
-
console.log(
|
|
690
|
+
} catch (error) {
|
|
691
|
+
console.log(error);
|
|
686
692
|
}
|
|
687
693
|
}
|
|
688
694
|
this.#blocks[block.index].loaded = true;
|
|
@@ -714,10 +720,10 @@ async resolveBlock(hash) {
|
|
|
714
720
|
let result = await this.#machine.execute(to, method, params, from, nonce);
|
|
715
721
|
// if (!result) result = this.#machine.state
|
|
716
722
|
pubsub.publish(`transaction.completed.${hash}`, {status: 'fulfilled', hash});
|
|
717
|
-
return result
|
|
718
|
-
} catch (
|
|
719
|
-
pubsub.publish(`transaction.completed.${hash}`, {status: 'fail', hash, error:
|
|
720
|
-
throw
|
|
723
|
+
return result || 'no state change'
|
|
724
|
+
} catch (error) {
|
|
725
|
+
pubsub.publish(`transaction.completed.${hash}`, {status: 'fail', hash, error: error});
|
|
726
|
+
throw error
|
|
721
727
|
}
|
|
722
728
|
}
|
|
723
729
|
|
|
@@ -754,11 +760,15 @@ async resolveBlock(hash) {
|
|
|
754
760
|
// await transactionStore.put(transaction.hash, transaction.encoded)
|
|
755
761
|
const index = contracts.indexOf(transaction.to);
|
|
756
762
|
if (index === -1) contracts.push(transaction.to);
|
|
763
|
+
// Todo: go trough all accounts
|
|
757
764
|
promises.push(this.#executeTransaction(transaction));
|
|
765
|
+
|
|
758
766
|
}
|
|
759
767
|
try {
|
|
760
768
|
promises = await Promise.allSettled(promises);
|
|
761
769
|
for (let transaction of blockMessage.decoded.transactions) {
|
|
770
|
+
pubsub.publish('transaction-processed', transaction);
|
|
771
|
+
if (transaction.to === peernet.selectedAccount) pubsub.publish('account-transaction-processed', transaction);
|
|
762
772
|
await accountsStore.put(transaction.from, String(transaction.nonce));
|
|
763
773
|
}
|
|
764
774
|
|
|
@@ -771,8 +781,9 @@ async resolveBlock(hash) {
|
|
|
771
781
|
|
|
772
782
|
|
|
773
783
|
pubsub.publish('block-processed', blockMessage.decoded);
|
|
774
|
-
|
|
775
|
-
|
|
784
|
+
|
|
785
|
+
} catch (error) {
|
|
786
|
+
console.log({e: error});
|
|
776
787
|
}
|
|
777
788
|
|
|
778
789
|
}
|
|
@@ -792,7 +803,7 @@ async resolveBlock(hash) {
|
|
|
792
803
|
// introduce peer-reputation
|
|
793
804
|
// peerReputation(peerId)
|
|
794
805
|
// {bandwith: {up, down}, uptime}
|
|
795
|
-
this
|
|
806
|
+
this.#participating = true;
|
|
796
807
|
if (!await this.staticCall(addresses.validators, 'has', [address])) await this.createTransactionFrom(address, addresses.validators, 'addValidator', [address]);
|
|
797
808
|
if (await this.hasTransactionToHandle() && !this.#runningEpoch) await this.#runEpoch();
|
|
798
809
|
|
|
@@ -854,7 +865,7 @@ async resolveBlock(hash) {
|
|
|
854
865
|
block.transactions.push(transaction);
|
|
855
866
|
block.fees += Number(calculateFee(transaction));
|
|
856
867
|
await accountsStore.put(transaction.from, new TextEncoder().encode(String(transaction.nonce)));
|
|
857
|
-
} catch
|
|
868
|
+
} catch {
|
|
858
869
|
transaction = await new TransactionMessage(transaction);
|
|
859
870
|
await transactionPoolStore.delete(await transaction.hash);
|
|
860
871
|
}
|
|
@@ -887,9 +898,7 @@ async resolveBlock(hash) {
|
|
|
887
898
|
address: validator,
|
|
888
899
|
bw: bw.up + bw.down
|
|
889
900
|
});
|
|
890
|
-
} catch
|
|
891
|
-
|
|
892
|
-
}
|
|
901
|
+
} catch{}
|
|
893
902
|
|
|
894
903
|
} else if (peernet.selectedAccount === validator) {
|
|
895
904
|
block.validators.push({
|
|
@@ -917,17 +926,17 @@ async resolveBlock(hash) {
|
|
|
917
926
|
else block.index += 1;
|
|
918
927
|
|
|
919
928
|
block.previousHash = this.lastBlock?.hash || '0x0';
|
|
920
|
-
block.timestamp =
|
|
929
|
+
block.timestamp = Date.now();
|
|
921
930
|
|
|
922
931
|
const parts = String(block.fees).split('.');
|
|
923
932
|
let decimals = 0;
|
|
924
933
|
if (parts[1]) {
|
|
925
934
|
const potentional = parts[1].split('e');
|
|
926
|
-
if (potentional[0]
|
|
927
|
-
parts[1] = potentional[0];
|
|
928
|
-
decimals = Number(potentional[1]?.replace(/\-|\+/g, '')) + Number(potentional[0].length);
|
|
929
|
-
} else {
|
|
935
|
+
if (potentional[0] === parts[1]) {
|
|
930
936
|
decimals = parts[1].length;
|
|
937
|
+
} else {
|
|
938
|
+
parts[1] = potentional[0];
|
|
939
|
+
decimals = Number(potentional[1]?.replace(/[+-]/g, '')) + Number(potentional[0].length);
|
|
931
940
|
}
|
|
932
941
|
|
|
933
942
|
}
|
|
@@ -947,9 +956,10 @@ async resolveBlock(hash) {
|
|
|
947
956
|
debug(`created block: ${hash}`);
|
|
948
957
|
|
|
949
958
|
peernet.publish('add-block', blockMessage.encoded);
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
959
|
+
pubsub.publish('add-block', blockMessage.decoded);
|
|
960
|
+
} catch (error) {
|
|
961
|
+
console.log(error);
|
|
962
|
+
throw new Error(`invalid block ${block}`)
|
|
953
963
|
}
|
|
954
964
|
// data = await this.#machine.execute(to, method, params)
|
|
955
965
|
// transactionStore.put(message.hash, message.encoded)
|
|
@@ -1018,8 +1028,8 @@ async resolveBlock(hash) {
|
|
|
1018
1028
|
* @param {Array} params - array of paramters to apply to the contract method
|
|
1019
1029
|
* @param {Number} nonce - total transaction count [optional]
|
|
1020
1030
|
*/
|
|
1021
|
-
async createTransaction(to, method,
|
|
1022
|
-
return this.createTransactionFrom(peernet.selectedAccount, to, method,
|
|
1031
|
+
async createTransaction(to, method, parameters, nonce, signature) {
|
|
1032
|
+
return this.createTransactionFrom(peernet.selectedAccount, to, method, parameters, nonce)
|
|
1023
1033
|
}
|
|
1024
1034
|
|
|
1025
1035
|
|
|
@@ -1079,8 +1089,8 @@ async #signTransaction (transaction, wallet) {
|
|
|
1079
1089
|
} else {
|
|
1080
1090
|
let nonce = await accountsStore.get(transaction.from);
|
|
1081
1091
|
nonce = new TextDecoder().decode(nonce);
|
|
1082
|
-
if (transaction.nonce < nonce) throw Error(`a transaction with a higher nonce already exists`)
|
|
1083
|
-
if (transaction.nonce === nonce) throw Error(`a transaction with the same nonce already exists`)
|
|
1092
|
+
if (transaction.nonce < nonce) throw new Error(`a transaction with a higher nonce already exists`)
|
|
1093
|
+
if (transaction.nonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
|
|
1084
1094
|
}
|
|
1085
1095
|
return transaction
|
|
1086
1096
|
}
|
|
@@ -1095,10 +1105,10 @@ async #signTransaction (transaction, wallet) {
|
|
|
1095
1105
|
* @param {Array} params - array of paramters to apply to the contract method
|
|
1096
1106
|
* @param {Number} nonce - total transaction count [optional]
|
|
1097
1107
|
*/
|
|
1098
|
-
async createTransactionFrom(from, to, method,
|
|
1108
|
+
async createTransactionFrom(from, to, method, parameters, nonce) {
|
|
1099
1109
|
try {
|
|
1100
1110
|
|
|
1101
|
-
const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params});
|
|
1111
|
+
const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params: parameters});
|
|
1102
1112
|
const transaction = await this.signTransaction(rawTransaction, from);
|
|
1103
1113
|
const message = await new TransactionMessage(transaction);
|
|
1104
1114
|
|
|
@@ -1114,7 +1124,7 @@ async #signTransaction (transaction, wallet) {
|
|
|
1114
1124
|
|
|
1115
1125
|
setTimeout(async () => {
|
|
1116
1126
|
pubsub.unsubscribe(`transaction.completed.${await message.hash}`, completed);
|
|
1117
|
-
},
|
|
1127
|
+
}, 10_000);
|
|
1118
1128
|
};
|
|
1119
1129
|
pubsub.subscribe(`transaction.completed.${await message.hash}`, completed);
|
|
1120
1130
|
}
|
|
@@ -1126,9 +1136,9 @@ async #signTransaction (transaction, wallet) {
|
|
|
1126
1136
|
peernet.publish('add-transaction', message.encoded);
|
|
1127
1137
|
this.#addTransaction(message.encoded);
|
|
1128
1138
|
return {hash: await message.hash, data, fee: await calculateFee(message.decoded), wait}
|
|
1129
|
-
} catch (
|
|
1130
|
-
console.log(
|
|
1131
|
-
throw
|
|
1139
|
+
} catch (error) {
|
|
1140
|
+
console.log(error);
|
|
1141
|
+
throw error
|
|
1132
1142
|
}
|
|
1133
1143
|
|
|
1134
1144
|
}
|
|
@@ -1143,20 +1153,19 @@ async #signTransaction (transaction, wallet) {
|
|
|
1143
1153
|
}
|
|
1144
1154
|
|
|
1145
1155
|
/**
|
|
1146
|
-
*
|
|
1147
|
-
* @param {String} contract
|
|
1156
|
+
*
|
|
1157
|
+
* @param {String} contract
|
|
1158
|
+
* @param {Array} parameters
|
|
1159
|
+
* @returns
|
|
1148
1160
|
*/
|
|
1149
|
-
async deployContract(contract,
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
const hash = await this.createContractAddress(creator, contract, params);
|
|
1153
|
-
console.log(hash);
|
|
1161
|
+
async deployContract(contract, parameters = []) {
|
|
1162
|
+
const message = await createContractMessage(peernet.selectedAccount, contract, parameters);
|
|
1154
1163
|
try {
|
|
1155
|
-
|
|
1156
|
-
} catch (
|
|
1157
|
-
throw
|
|
1164
|
+
await this.#machine.addContract(message);
|
|
1165
|
+
} catch (error) {
|
|
1166
|
+
throw error
|
|
1158
1167
|
}
|
|
1159
|
-
return this
|
|
1168
|
+
return this.createTransactionFrom(peernet.selectedAccount, addresses.contractFactory, 'registerContract', [await message.hash])
|
|
1160
1169
|
}
|
|
1161
1170
|
|
|
1162
1171
|
#createMessage(sender = peernet.selectedAccount) {
|
|
@@ -1169,33 +1178,33 @@ console.log(hash);
|
|
|
1169
1178
|
}
|
|
1170
1179
|
}
|
|
1171
1180
|
|
|
1172
|
-
internalCall(sender, contract, method,
|
|
1181
|
+
internalCall(sender, contract, method, parameters) {
|
|
1173
1182
|
globalThis.msg = this.#createMessage(sender);
|
|
1174
1183
|
|
|
1175
|
-
return this.#machine.execute(contract, method,
|
|
1184
|
+
return this.#machine.execute(contract, method, parameters)
|
|
1176
1185
|
}
|
|
1177
1186
|
|
|
1178
|
-
call(contract, method,
|
|
1187
|
+
call(contract, method, parameters) {
|
|
1179
1188
|
globalThis.msg = this.#createMessage();
|
|
1180
1189
|
|
|
1181
|
-
return this.#machine.execute(contract, method,
|
|
1190
|
+
return this.#machine.execute(contract, method, parameters)
|
|
1182
1191
|
}
|
|
1183
1192
|
|
|
1184
|
-
staticCall(contract, method,
|
|
1193
|
+
staticCall(contract, method, parameters) {
|
|
1185
1194
|
globalThis.msg = this.#createMessage();
|
|
1186
|
-
return this.#machine.get(contract, method,
|
|
1195
|
+
return this.#machine.get(contract, method, parameters)
|
|
1187
1196
|
}
|
|
1188
1197
|
|
|
1189
|
-
delegate(contract, method,
|
|
1198
|
+
delegate(contract, method, parameters) {
|
|
1190
1199
|
globalThis.msg = this.#createMessage();
|
|
1191
1200
|
|
|
1192
|
-
return this.#machine.execute(contract, method,
|
|
1201
|
+
return this.#machine.execute(contract, method, parameters)
|
|
1193
1202
|
}
|
|
1194
1203
|
|
|
1195
|
-
staticDelegate(contract, method,
|
|
1204
|
+
staticDelegate(contract, method, parameters) {
|
|
1196
1205
|
globalThis.msg = this.#createMessage();
|
|
1197
1206
|
|
|
1198
|
-
return this.#machine.get(contract, method,
|
|
1207
|
+
return this.#machine.get(contract, method, parameters)
|
|
1199
1208
|
}
|
|
1200
1209
|
|
|
1201
1210
|
mint(to, amount) {
|
|
@@ -1210,6 +1219,19 @@ console.log(hash);
|
|
|
1210
1219
|
return this.staticCall(addresses.nativeToken, 'balances')
|
|
1211
1220
|
}
|
|
1212
1221
|
|
|
1222
|
+
get contracts() {
|
|
1223
|
+
return this.staticCall(addresses.contractFactory, 'contracts')
|
|
1224
|
+
}
|
|
1225
|
+
/**
|
|
1226
|
+
*
|
|
1227
|
+
* @param {Address} address old contract address
|
|
1228
|
+
* @param {Address} newAddress new contract address
|
|
1229
|
+
* @returns
|
|
1230
|
+
*/
|
|
1231
|
+
async updateImplementation(address, newAddress) {
|
|
1232
|
+
return this.call(addresses.contractFactory, 'updateImplementation', [address, newAddress])
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1213
1235
|
deleteAll() {
|
|
1214
1236
|
return this.#machine.deleteAll()
|
|
1215
1237
|
}
|
|
@@ -388,10 +388,6 @@ globalThis.BigNumber = BigNumber;
|
|
|
388
388
|
globalThis.peernet = globalThis.peernet || {};
|
|
389
389
|
globalThis.contracts = {};
|
|
390
390
|
|
|
391
|
-
const unique = arr => arr.filter((el, pos, arr) => {
|
|
392
|
-
return arr.indexOf(el) == pos;
|
|
393
|
-
});
|
|
394
|
-
|
|
395
391
|
const get = (contract, method, params) => {
|
|
396
392
|
let result;
|
|
397
393
|
if (params?.length > 0) {
|
|
@@ -576,5 +572,3 @@ const tasks = async (e) => {
|
|
|
576
572
|
};
|
|
577
573
|
|
|
578
574
|
worker.onmessage(data => tasks(data));
|
|
579
|
-
|
|
580
|
-
export { unique };
|
package/dist/standards/token.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class
|
|
1
|
+
class Roles{#roles={IMPLEMENTATION_MANAGER:[],OWNER:[],MINT:[],BURN:[]};constructor(roles){if(roles){if(!(roles instanceof Object))throw new TypeError("expected roles to be an object");this.#roles={...roles,...this.#roles}}else this.#grantRole(msg.sender,"OWNER"),this.#grantRole(msg.sender,"IMPLEMENTATION_MANAGER")}get state(){return{roles:this.roles}}get roles(){return{...this.#roles}}hasRole(address,role){return!!this.#roles[role]&&this.#roles[role].includes(address)}#grantRole(address,role){if(this.hasRole(address,role))throw new Error(`${role} role already granted for ${address}`);this.#roles[role].push(address)}#revokeRole(address,role){if(!this.hasRole(address,role))throw new Error(`${role} role already revoked for ${address}`);if("OWNER"===role&&1===this.#roles[role].length)throw new Error("atleast one owner is needed!");this.#roles[role].splice(this.#roles[role].indexOf(address))}grantRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#grantRole(address,role)}revokeRole(address,role){if(!this.hasRole(address,"OWNER"))throw new Error("Not allowed");this.#revokeRole(address,role)}}class Token extends Roles{#name;#symbol;#holders=0;#balances={};#approvals={};#decimals=18;#totalSupply=BigNumber.from(0);constructor(name,symbol,decimals=18,state){if(!name)throw new Error("name undefined");if(!symbol)throw new Error("symbol undefined");super(state?.roles),this.#name=name,this.#symbol=symbol,this.#decimals=decimals}get state(){return{...super.state,holders:this.holders,balances:this.balances,approvals:{...this.#approvals},totalSupply:this.totalSupply}}get totalSupply(){return this.#totalSupply}get name(){return this.#name}get symbol(){return this.#symbol}get holders(){return this.#holders}get balances(){return{...this.#balances}}mint(to,amount){if(!this.hasRole(msg.sender,"MINT"))throw new Error("not allowed");this.#totalSupply=this.#totalSupply.add(amount),this.#increaseBalance(to,amount)}burn(from,amount){if(!this.hasRole(msg.sender,"BURN"))throw new Error("not allowed");this.#totalSupply=this.#totalSupply.sub(amount),this.#decreaseBalance(from,amount)}#beforeTransfer(from,to,amount){if(!this.#balances[from]||this.#balances[from]<amount)throw new Error("amount exceeds balance")}#updateHolders(address,previousBalance){"0x00"===this.#balances[address].toHexString()?this.#holders-=1:"0x00"!==this.#balances[address].toHexString()&&"0x00"===previousBalance.toHexString()&&(this.#holders+=1)}#increaseBalance(address,amount){this.#balances[address]||(this.#balances[address]=BigNumber.from(0));const previousBalance=this.#balances[address];this.#balances[address]=this.#balances[address].add(amount),this.#updateHolders(address,previousBalance)}#decreaseBalance(address,amount){const previousBalance=this.#balances[address];this.#balances[address]=this.#balances[address].sub(amount),this.#updateHolders(address,previousBalance)}balanceOf(address){return this.#balances[address]}setApproval(operator,amount){const owner=globalThis.msg.sender;this.#approvals[owner]||(this.#approvals[owner]={}),this.#approvals[owner][operator]=amount}approved(owner,operator,amount){return this.#approvals[owner][operator]===amount}transfer(from,to,amount){amount=BigNumber.from(amount),this.#beforeTransfer(from,to,amount),this.#decreaseBalance(from,amount),this.#increaseBalance(to,amount)}}export{Token as default};
|