@leofcoin/chain 1.3.9 → 1.3.11
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/demo/chain.browser.js +7663 -570
- package/demo/workers/machine-worker.js +28 -566
- package/dist/865.browser.js +10 -0
- package/dist/browser/workers/machine-worker.js +1 -1
- package/dist/chain.browser.js +66838 -0
- package/dist/chain.js +467 -283
- package/dist/generate-account.browser.js +50 -0
- package/dist/messages.browser.js +328 -0
- package/dist/module/chain.js +462 -279
- package/dist/module/workers/machine-worker.js +1 -1
- package/dist/multi-wallet.browser.js +15 -0
- package/dist/node.browser.js +9858 -0
- package/dist/pako.browser.js +6900 -0
- package/dist/peernet-swarm.browser.js +839 -0
- package/dist/storage.browser.js +3724 -0
- package/dist/workers/machine-worker.js +1 -1
- package/dist/wrtc.browser.js +28 -0
- package/package.json +4 -3
- package/rollup.config.js +17 -27
- package/src/chain.js +119 -253
- package/src/contract.js +51 -0
- package/src/machine.js +10 -5
- package/src/protocol.js +3 -0
- package/src/state.js +2 -2
- package/src/transaction.js +233 -0
- package/src/type.index.d.ts +21 -0
- package/test/chain.js +16 -14
- package/webpack.config.js +2 -1
package/dist/chain.js
CHANGED
|
@@ -5,10 +5,11 @@ var _BN = require('bn.js');
|
|
|
5
5
|
require('@ethersproject/bytes');
|
|
6
6
|
var logger = require('@ethersproject/logger');
|
|
7
7
|
require('@ethersproject/bignumber');
|
|
8
|
-
var
|
|
9
|
-
var
|
|
8
|
+
var crypto = require('crypto');
|
|
9
|
+
var path = require('path');
|
|
10
10
|
var EasyWorker = require('@vandeurenglenn/easy-worker');
|
|
11
11
|
var codecFormatInterface = require('@leofcoin/codec-format-interface');
|
|
12
|
+
var pako = require('pako');
|
|
12
13
|
var MultiWallet = require('@leofcoin/multi-wallet');
|
|
13
14
|
var index = require('@leofcoin/codec-format-interface/dist/index');
|
|
14
15
|
var bs32 = require('@vandeurenglenn/base32');
|
|
@@ -17,6 +18,7 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
17
18
|
|
|
18
19
|
var _BN__default = /*#__PURE__*/_interopDefaultLegacy(_BN);
|
|
19
20
|
var EasyWorker__default = /*#__PURE__*/_interopDefaultLegacy(EasyWorker);
|
|
21
|
+
var pako__default = /*#__PURE__*/_interopDefaultLegacy(pako);
|
|
20
22
|
var MultiWallet__default = /*#__PURE__*/_interopDefaultLegacy(MultiWallet);
|
|
21
23
|
var bs32__default = /*#__PURE__*/_interopDefaultLegacy(bs32);
|
|
22
24
|
|
|
@@ -24,17 +26,17 @@ var contractFactory$2 = "ihny2gqg6c6mwy5mhbrs5ulkkozsgwtk5vuz5krjidouy4mbwfdbjnb
|
|
|
24
26
|
var nativeToken$2 = "ihny2gqhoockyg7yg4n5bpxuldahfavpqnmpoe2bn4ivnxmk7redc2ltwkb";
|
|
25
27
|
var nameService$2 = "ihny2gqgztp3vj6qy7fgrfer7y5c5hxnp6imdz6v5spi4edkwtm5fkd5z2h";
|
|
26
28
|
var validators$2 = "ihny2gqh4e2pr4pbtpkamhj3htsvuoydy3wotaudoeaktgcdwmoij66pecp";
|
|
27
|
-
var addresses = {
|
|
29
|
+
var addresses$1 = {
|
|
28
30
|
contractFactory: contractFactory$2,
|
|
29
31
|
nativeToken: nativeToken$2,
|
|
30
32
|
nameService: nameService$2,
|
|
31
33
|
validators: validators$2
|
|
32
34
|
};
|
|
33
35
|
|
|
34
|
-
const contractFactory$1 = addresses.contractFactory;
|
|
35
|
-
const nameService$1 = addresses.nameService;
|
|
36
|
-
const nativeToken$1 = addresses.nativeToken;
|
|
37
|
-
const validators$1 = addresses.validators;
|
|
36
|
+
const contractFactory$1 = addresses$1.contractFactory;
|
|
37
|
+
const nameService$1 = addresses$1.nameService;
|
|
38
|
+
const nativeToken$1 = addresses$1.nativeToken;
|
|
39
|
+
const validators$1 = addresses$1.validators;
|
|
38
40
|
|
|
39
41
|
const version$1 = "bignumber/5.6.2";
|
|
40
42
|
|
|
@@ -134,7 +136,7 @@ message BlockMessage {
|
|
|
134
136
|
}
|
|
135
137
|
`;
|
|
136
138
|
|
|
137
|
-
class BlockMessage extends codecFormatInterface.FormatInterface {
|
|
139
|
+
class BlockMessage$1 extends codecFormatInterface.FormatInterface {
|
|
138
140
|
get keys() {
|
|
139
141
|
return ['index', 'previousHash', 'timestamp', 'reward', 'fees', 'transactions', 'validators']
|
|
140
142
|
}
|
|
@@ -251,7 +253,7 @@ class Machine {
|
|
|
251
253
|
};
|
|
252
254
|
pubsub.subscribe('machine.ready', machineReady);
|
|
253
255
|
|
|
254
|
-
this.worker = await new EasyWorker__default["default"](
|
|
256
|
+
this.worker = await new EasyWorker__default["default"](path.join(__dirname, './workers/machine-worker.js'), {serialization: 'advanced', type:'module'});
|
|
255
257
|
this.worker.onmessage(this.#onmessage.bind(this));
|
|
256
258
|
|
|
257
259
|
// const blocks = await blockStore.values()
|
|
@@ -278,7 +280,7 @@ class Machine {
|
|
|
278
280
|
async #runContract(contractMessage) {
|
|
279
281
|
const hash = await contractMessage.hash;
|
|
280
282
|
return new Promise((resolve, reject) => {
|
|
281
|
-
const id =
|
|
283
|
+
const id = crypto.randomBytes(20).toString('hex');
|
|
282
284
|
const onmessage = message => {
|
|
283
285
|
pubsub.unsubscribe(id, onmessage);
|
|
284
286
|
if (message?.error) reject(message.error);
|
|
@@ -298,29 +300,34 @@ class Machine {
|
|
|
298
300
|
|
|
299
301
|
}
|
|
300
302
|
|
|
303
|
+
/**
|
|
304
|
+
*
|
|
305
|
+
* @param {Address} contract
|
|
306
|
+
* @param {String} method
|
|
307
|
+
* @param {Array} parameters
|
|
308
|
+
* @returns Promise<message>
|
|
309
|
+
*/
|
|
301
310
|
async execute(contract, method, parameters) {
|
|
302
|
-
/** */
|
|
303
311
|
try {
|
|
304
312
|
if (contract === contractFactory$1 && method === 'registerContract') {
|
|
305
313
|
if (this.#contracts[parameters[0]]) throw new Error(`duplicate contract @${parameters[0]}`)
|
|
306
314
|
let message;
|
|
307
|
-
if (!contractStore.has(parameters[0])) {
|
|
315
|
+
if (!await contractStore.has(parameters[0])) {
|
|
308
316
|
message = await peernet.get(parameters[0], 'contract');
|
|
309
|
-
message = new ContractMessage(message);
|
|
317
|
+
message = await new ContractMessage(message);
|
|
310
318
|
await contractStore.put(await message.hash, message.encoded);
|
|
311
319
|
}
|
|
312
320
|
if (!message) {
|
|
313
321
|
message = await contractStore.get(parameters[0]);
|
|
314
|
-
message = new ContractMessage(message);
|
|
322
|
+
message = await new ContractMessage(message);
|
|
315
323
|
}
|
|
316
|
-
|
|
317
324
|
if (!this.#contracts[await message.hash]) await this.#runContract(message);
|
|
318
325
|
}
|
|
319
326
|
} catch (error) {
|
|
320
327
|
throw new Error(`contract deployment failed for ${parameters[0]}\n${error.message}`)
|
|
321
328
|
}
|
|
322
329
|
return new Promise((resolve, reject) => {
|
|
323
|
-
const id =
|
|
330
|
+
const id = crypto.randomBytes(20).toString('hex');
|
|
324
331
|
const onmessage = message => {
|
|
325
332
|
pubsub.unsubscribe(id, onmessage);
|
|
326
333
|
if (message?.error) reject(message.error);
|
|
@@ -350,7 +357,7 @@ class Machine {
|
|
|
350
357
|
|
|
351
358
|
get(contract, method, parameters) {
|
|
352
359
|
return new Promise((resolve, reject) => {
|
|
353
|
-
const id =
|
|
360
|
+
const id = crypto.randomBytes(20).toString();
|
|
354
361
|
const onmessage = message => {
|
|
355
362
|
pubsub.unsubscribe(id, onmessage);
|
|
356
363
|
resolve(message);
|
|
@@ -427,24 +434,397 @@ const calculateFee = async transaction => {
|
|
|
427
434
|
return Number.parseFloat(fee.toString()).toFixed(decimals)
|
|
428
435
|
};
|
|
429
436
|
|
|
437
|
+
class State {
|
|
438
|
+
constructor() {
|
|
439
|
+
// return this.#init()
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// async #init() {
|
|
443
|
+
// const state = await stateStore.get()
|
|
444
|
+
// for (const [key, value] of Object.entries(state)) {
|
|
445
|
+
//
|
|
446
|
+
// }
|
|
447
|
+
//
|
|
448
|
+
// return this
|
|
449
|
+
// }
|
|
450
|
+
|
|
451
|
+
async put(key, value, isCompressed = true) {
|
|
452
|
+
value = isCompressed ? value : await pako__default["default"].deflate(value);
|
|
453
|
+
await stateStore.put(key, value);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async get(key, isCompressed = true) {
|
|
457
|
+
const value = await stateStore.get(key);
|
|
458
|
+
return isCompressed = pako__default["default"].inflate(value)
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
updateState(block) {
|
|
462
|
+
// block.decoded.index
|
|
463
|
+
// this.#isUpdateNeeded()
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
class Protocol {
|
|
468
|
+
limit = 1800
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
class Transaction extends Protocol {
|
|
472
|
+
constructor() {
|
|
473
|
+
super();
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
*
|
|
478
|
+
* @param {Address[]} transactions
|
|
479
|
+
* @returns transactions to include
|
|
480
|
+
*/
|
|
481
|
+
async getTransactions (transactions) {
|
|
482
|
+
return new Promise(async (resolve, reject) => {
|
|
483
|
+
let size = 0;
|
|
484
|
+
const _transactions = [];
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
await Promise.all(transactions
|
|
488
|
+
.map(async tx => {
|
|
489
|
+
tx = await new TransactionMessage(tx);
|
|
490
|
+
size += tx.encoded.length;
|
|
491
|
+
if (!formatBytes(size).includes('MB') || formatBytes(size).includes('MB') && Number(formatBytes(size).split(' MB')[0]) <= 0.75) _transactions.push({...tx.decoded, hash: await tx.hash});
|
|
492
|
+
else resolve(_transactions);
|
|
493
|
+
}));
|
|
494
|
+
|
|
495
|
+
return resolve(_transactions)
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
*
|
|
502
|
+
* @param {Transaction[]} transactions An array containing Transactions
|
|
503
|
+
* @returns {TransactionMessage}
|
|
504
|
+
*/
|
|
505
|
+
async promiseTransactions(transactions) {
|
|
506
|
+
transactions = await Promise.all(transactions.map(tx => new TransactionMessage(tx)));
|
|
507
|
+
return transactions
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
*
|
|
512
|
+
* @param {Transaction[]} transactions An array containing Transactions
|
|
513
|
+
* @returns {Object} {transaction.decoded, transaction.hash}
|
|
514
|
+
*/
|
|
515
|
+
async promiseTransactionsContent(transactions) {
|
|
516
|
+
transactions = await Promise.all(transactions.map(tx => new Promise(async (resolve, reject) => {
|
|
517
|
+
resolve({ ...tx.decoded, hash: await tx.hash });
|
|
518
|
+
})));
|
|
519
|
+
|
|
520
|
+
return transactions
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* When a nonce isn't found for an address fallback to just checking the transactionnPoolStore
|
|
525
|
+
* @param {Address} address
|
|
526
|
+
* @returns {Number} nonce
|
|
527
|
+
*/
|
|
528
|
+
async #getNonceFallback(address) {
|
|
529
|
+
let transactions = await transactionPoolStore.values();
|
|
530
|
+
transactions = await this.promiseTransactions(transactions);
|
|
531
|
+
transactions = transactions.filter(tx => tx.decoded.from === address);
|
|
532
|
+
transactions = await this.promiseTransactionsContent(transactions);
|
|
533
|
+
|
|
534
|
+
if (this.lastBlock?.hash && transactions.length === 0 && this.lastBlock.hash !== '0x0') {
|
|
535
|
+
|
|
536
|
+
let block = await peernet.get(this.lastBlock.hash);
|
|
537
|
+
block = await new BlockMessage(block);
|
|
538
|
+
|
|
539
|
+
// for (let tx of block.decoded?.transactions) {
|
|
540
|
+
// tx = await peernet.get(tx, 'transaction')
|
|
541
|
+
// transactions.push(new TransactionMessage(tx))
|
|
542
|
+
// }
|
|
543
|
+
transactions = transactions.filter(tx => tx.from === address);
|
|
544
|
+
while (transactions.length === 0 && block.decoded.index !== 0 && block.decoded.previousHash !== '0x0') {
|
|
545
|
+
block = await blockStore.get(block.decoded.previousHash);
|
|
546
|
+
block = await new BlockMessage(block);
|
|
547
|
+
transactions = block.decoded.transactions.filter(tx => tx.from === address);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
}
|
|
551
|
+
if (transactions.length === 0) return 0
|
|
552
|
+
|
|
553
|
+
transactions = transactions.sort((a, b) => a.timestamp - b.timestamp);
|
|
554
|
+
return transactions[transactions.length - 1].nonce
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/**
|
|
558
|
+
* Get amount of transactions by address
|
|
559
|
+
* @param {Address} address The address to get the nonce for
|
|
560
|
+
* @returns {Number} nonce
|
|
561
|
+
*/
|
|
562
|
+
async getNonce(address) {
|
|
563
|
+
if (!await accountsStore.has(address)) {
|
|
564
|
+
const nonce = await this.#getNonceFallback(address);
|
|
565
|
+
await accountsStore.put(address, new TextEncoder().encode(String(nonce)));
|
|
566
|
+
}
|
|
567
|
+
// todo: are those in the pool in cluded also ? they need to be included!!!
|
|
568
|
+
let nonce = await accountsStore.get(address);
|
|
569
|
+
nonce = new TextDecoder().decode(nonce);
|
|
570
|
+
return Number(nonce)
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* whenever method = createContract params should hold the contract hash
|
|
575
|
+
*
|
|
576
|
+
* example: [hash]
|
|
577
|
+
* createTransaction('0x0', 'createContract', [hash])
|
|
578
|
+
*
|
|
579
|
+
* @param {String} to - the contract address for the contract to interact with
|
|
580
|
+
* @param {String} method - the method/function to run
|
|
581
|
+
* @param {Array} params - array of paramters to apply to the contract method
|
|
582
|
+
* @param {Number} nonce - total transaction count [optional]
|
|
583
|
+
*/
|
|
584
|
+
async createTransaction(to, method, parameters, nonce, signature) {
|
|
585
|
+
return this.createTransactionFrom(peernet.selectedAccount, to, method, parameters, nonce)
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
*
|
|
590
|
+
* @param {Transaction} transaction
|
|
591
|
+
* @param {String} transaction.from address
|
|
592
|
+
* @param {String} transaction.to address
|
|
593
|
+
* @param {Object} transaction.params {}
|
|
594
|
+
* @param {String} transaction.params.method get, call
|
|
595
|
+
* @param {Buffer} transaction.params.data
|
|
596
|
+
* @returns
|
|
597
|
+
*/
|
|
598
|
+
async createTransactionHash(transaction) {
|
|
599
|
+
// todo: validate
|
|
600
|
+
const peernetHash = await new index.CodecHash(transaction, {name: 'transaction-message'});
|
|
601
|
+
return peernetHash.digest
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* @param {Transaction} transaction
|
|
606
|
+
* @param {object} wallet any wallet/signer that supports sign(RAWtransaction)
|
|
607
|
+
*/
|
|
608
|
+
async #signTransaction (transaction, wallet) {
|
|
609
|
+
return wallet.sign(await this.createTransactionHash(transaction))
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
*
|
|
614
|
+
* @param {RawTransaction} transaction
|
|
615
|
+
* @param {Signer} signer
|
|
616
|
+
* @returns {Transaction} a signed transaction
|
|
617
|
+
*/
|
|
618
|
+
async signTransaction(transaction, signer) {
|
|
619
|
+
let identity = await walletStore.get('identity');
|
|
620
|
+
identity = JSON.parse(new TextDecoder().decode(identity));
|
|
621
|
+
const wallet = new MultiWallet__default["default"](peernet.network);
|
|
622
|
+
wallet.recover(identity.mnemonic);
|
|
623
|
+
const account = wallet.account(0).external(0);
|
|
624
|
+
transaction.signature = await this.#signTransaction(transaction, account);
|
|
625
|
+
transaction.signature = bs32__default["default"].encode(transaction.signature);
|
|
626
|
+
return transaction
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
*
|
|
631
|
+
* @param {Transaction} transaction
|
|
632
|
+
* @param {Address} transaction.from
|
|
633
|
+
* @param {Address} transaction.to
|
|
634
|
+
* @param {String} transaction.method
|
|
635
|
+
* @param {Array} transaction.params
|
|
636
|
+
* @param {Number} transaction.nonce
|
|
637
|
+
*
|
|
638
|
+
* @returns {RawTransaction} transaction
|
|
639
|
+
*/
|
|
640
|
+
async ensureNonce(transaction) {
|
|
641
|
+
if (!transaction.from) transaction.from = peernet.selectedAccount;
|
|
642
|
+
transaction.timestamp = Date.now();
|
|
643
|
+
|
|
644
|
+
if (transaction.nonce === undefined) {
|
|
645
|
+
transaction.nonce = await this.getNonce(transaction.from);
|
|
646
|
+
} else {
|
|
647
|
+
let nonce = await accountsStore.get(transaction.from);
|
|
648
|
+
nonce = new TextDecoder().decode(nonce);
|
|
649
|
+
if (transaction.nonce < nonce) throw new Error(`a transaction with a higher nonce already exists`)
|
|
650
|
+
if (transaction.nonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
|
|
651
|
+
}
|
|
652
|
+
return transaction
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* every tx done is trough contracts so no need for amount
|
|
657
|
+
* data is undefined when nothing is returned
|
|
658
|
+
* error is thrown on error so undefined data doesn't mean there is an error...
|
|
659
|
+
*
|
|
660
|
+
* @param {Address} from - the sender address
|
|
661
|
+
* @param {Address} to - the contract address for the contract to interact with
|
|
662
|
+
* @param {String} method - the method/function to run
|
|
663
|
+
* @param {Array} params - array of paramters to apply to the contract method
|
|
664
|
+
* @param {Number} nonce - total transaction count [optional]
|
|
665
|
+
*/
|
|
666
|
+
async createTransactionFrom(from, to, method, parameters, nonce) {
|
|
667
|
+
try {
|
|
668
|
+
const rawTransaction = await this.ensureNonce({from, to, nonce, method, params: parameters});
|
|
669
|
+
const transaction = await this.signTransaction(rawTransaction, from);
|
|
670
|
+
const message = await new TransactionMessage(transaction);
|
|
671
|
+
|
|
672
|
+
let data;
|
|
673
|
+
const wait = () => new Promise(async (resolve, reject) => {
|
|
674
|
+
if (pubsub.subscribers[`transaction.completed.${await message.hash}`]) {
|
|
675
|
+
const result = pubsub.subscribers[`transaction.completed.${await message.hash}`].value;
|
|
676
|
+
result.status === 'fulfilled' ? resolve(await result.hash) : reject({hash: await result.hash, error: result.error});
|
|
677
|
+
} else {
|
|
678
|
+
const completed = async result => {
|
|
679
|
+
result.status === 'fulfilled' ? resolve(await result.hash) : reject({hash: await result.hash, error: result.error});
|
|
680
|
+
|
|
681
|
+
setTimeout(async () => {
|
|
682
|
+
pubsub.unsubscribe(`transaction.completed.${await message.hash}`, completed);
|
|
683
|
+
}, 10_000);
|
|
684
|
+
};
|
|
685
|
+
pubsub.subscribe(`transaction.completed.${await message.hash}`, completed);
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
await transactionPoolStore.put(await message.hash, message.encoded);
|
|
689
|
+
peernet.publish('add-transaction', message.encoded);
|
|
690
|
+
return {hash: await message.hash, data, fee: await calculateFee(message.decoded), wait, message}
|
|
691
|
+
} catch (error) {
|
|
692
|
+
console.log(error);
|
|
693
|
+
throw error
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* @extends {Transaction}
|
|
700
|
+
*/
|
|
701
|
+
class Contract extends Transaction {
|
|
702
|
+
constructor() {
|
|
703
|
+
super();
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
*
|
|
708
|
+
* @param {Address} creator
|
|
709
|
+
* @param {String} contract
|
|
710
|
+
* @param {Array} constructorParameters
|
|
711
|
+
* @returns lib.createContractMessage
|
|
712
|
+
*/
|
|
713
|
+
async createContractMessage(creator, contract, constructorParameters = []) {
|
|
714
|
+
return createContractMessage(creator, contract, constructorParameters)
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
*
|
|
719
|
+
* @param {Address} creator
|
|
720
|
+
* @param {String} contract
|
|
721
|
+
* @param {Array} constructorParameters
|
|
722
|
+
* @returns {Address}
|
|
723
|
+
*/
|
|
724
|
+
async createContractAddress(creator, contract, constructorParameters = []) {
|
|
725
|
+
contract = await this.createContractMessage(creator, contract, constructorParameters);
|
|
726
|
+
return contract.hash
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
*
|
|
731
|
+
* @param {String} contract
|
|
732
|
+
* @param {Array} parameters
|
|
733
|
+
* @returns
|
|
734
|
+
*/
|
|
735
|
+
async deployContract(contract, constructorParameters = []) {
|
|
736
|
+
const message = await createContractMessage(peernet.selectedAccount, contract, constructorParameters);
|
|
737
|
+
try {
|
|
738
|
+
await contractStore.put(await message.hash, message.encoded);
|
|
739
|
+
} catch (error) {
|
|
740
|
+
throw error
|
|
741
|
+
}
|
|
742
|
+
return this.createTransactionFrom(peernet.selectedAccount, addresses.contractFactory, 'registerContract', [await message.hash])
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
}
|
|
746
|
+
|
|
430
747
|
globalThis.BigNumber = utils.BigNumber;
|
|
431
748
|
|
|
432
749
|
// check if browser or local
|
|
433
|
-
class Chain {
|
|
750
|
+
class Chain extends Contract {
|
|
751
|
+
/** {Address[]} */
|
|
434
752
|
#validators = []
|
|
753
|
+
/** {Block[]} */
|
|
435
754
|
#blocks = []
|
|
755
|
+
|
|
436
756
|
#machine
|
|
757
|
+
/** {Boolean} */
|
|
437
758
|
#runningEpoch = false
|
|
759
|
+
|
|
760
|
+
/** {Boolean} */
|
|
438
761
|
#chainSyncing = false
|
|
762
|
+
|
|
763
|
+
/** {Number} */
|
|
764
|
+
#totalSize = 0
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* {Block} {index, hash, previousHash}
|
|
768
|
+
*/
|
|
439
769
|
#lastBlock = {index: 0, hash: '0x0', previousHash: '0x0'}
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* amount the native token has been iteracted with
|
|
773
|
+
*/
|
|
774
|
+
#nativeCalls = 0
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* amount the native token has been iteracted with
|
|
778
|
+
*/
|
|
779
|
+
#nativeTransfers = 0
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* amount of native token burned
|
|
783
|
+
* {Number}
|
|
784
|
+
*/
|
|
785
|
+
#nativeBurns = 0
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* amount of native tokens minted
|
|
789
|
+
* {Number}
|
|
790
|
+
*/
|
|
791
|
+
#nativeMints = 0
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* total amount of transactions
|
|
795
|
+
* {Number}
|
|
796
|
+
*/
|
|
797
|
+
#totalTransactions = 0
|
|
798
|
+
|
|
440
799
|
#participants = []
|
|
441
800
|
#participating = false
|
|
442
801
|
#jail = []
|
|
443
802
|
|
|
444
803
|
constructor() {
|
|
804
|
+
super();
|
|
445
805
|
return this.#init()
|
|
446
806
|
}
|
|
447
807
|
|
|
808
|
+
get nativeMints() {
|
|
809
|
+
return this.#nativeMints
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
get nativeBurns() {
|
|
813
|
+
return this.#nativeBurns
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
get nativeTransfers() {
|
|
817
|
+
return this.#nativeTransfers
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
get totalTransactions() {
|
|
821
|
+
return this.#totalTransactions
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
get totalSize() {
|
|
825
|
+
return this.#totalSize
|
|
826
|
+
}
|
|
827
|
+
|
|
448
828
|
get lib() {
|
|
449
829
|
return lib
|
|
450
830
|
}
|
|
@@ -454,7 +834,7 @@ class Chain {
|
|
|
454
834
|
}
|
|
455
835
|
|
|
456
836
|
get nativeToken() {
|
|
457
|
-
return addresses.nativeToken
|
|
837
|
+
return addresses$1.nativeToken
|
|
458
838
|
}
|
|
459
839
|
|
|
460
840
|
get validators() {
|
|
@@ -474,10 +854,9 @@ class Chain {
|
|
|
474
854
|
async #runEpoch() {
|
|
475
855
|
this.#runningEpoch = true;
|
|
476
856
|
console.log('epoch');
|
|
477
|
-
const validators = await this.staticCall(addresses.validators, 'validators');
|
|
857
|
+
const validators = await this.staticCall(addresses$1.validators, 'validators');
|
|
478
858
|
console.log(validators);
|
|
479
859
|
if (!validators[peernet.selectedAccount]?.active) return
|
|
480
|
-
|
|
481
860
|
const start = Date.now();
|
|
482
861
|
try {
|
|
483
862
|
await this.#createBlock();
|
|
@@ -496,16 +875,16 @@ class Chain {
|
|
|
496
875
|
async #setup() {
|
|
497
876
|
|
|
498
877
|
const contracts = [{
|
|
499
|
-
address: addresses.contractFactory,
|
|
878
|
+
address: addresses$1.contractFactory,
|
|
500
879
|
message: contractFactoryMessage
|
|
501
880
|
}, {
|
|
502
|
-
address: addresses.nativeToken,
|
|
881
|
+
address: addresses$1.nativeToken,
|
|
503
882
|
message: nativeTokenMessage
|
|
504
883
|
}, {
|
|
505
|
-
address: addresses.validators,
|
|
884
|
+
address: addresses$1.validators,
|
|
506
885
|
message: validatorsMessage
|
|
507
886
|
}, {
|
|
508
|
-
address: addresses.nameService,
|
|
887
|
+
address: addresses$1.nameService,
|
|
509
888
|
message: nameServiceMessage
|
|
510
889
|
}];
|
|
511
890
|
|
|
@@ -563,7 +942,7 @@ class Chain {
|
|
|
563
942
|
|
|
564
943
|
if (latest.hash && latest.hash !== '0x0') {
|
|
565
944
|
latest = await peernet.get(latest.hash, block);
|
|
566
|
-
latest = await new BlockMessage(latest);
|
|
945
|
+
latest = await new BlockMessage$1(latest);
|
|
567
946
|
}
|
|
568
947
|
|
|
569
948
|
return latest
|
|
@@ -573,11 +952,13 @@ class Chain {
|
|
|
573
952
|
// this.node = await new Node()
|
|
574
953
|
this.#participants = [];
|
|
575
954
|
this.#participating = false;
|
|
576
|
-
const initialized = await contractStore.has(addresses.contractFactory);
|
|
955
|
+
const initialized = await contractStore.has(addresses$1.contractFactory);
|
|
577
956
|
if (!initialized) await this.#setup();
|
|
578
957
|
|
|
579
958
|
|
|
580
959
|
this.utils = { BigNumber: utils.BigNumber, formatUnits: utils.formatUnits, parseUnits: utils.parseUnits };
|
|
960
|
+
|
|
961
|
+
this.state = new State();
|
|
581
962
|
|
|
582
963
|
try {
|
|
583
964
|
let localBlock;
|
|
@@ -590,7 +971,7 @@ class Chain {
|
|
|
590
971
|
localBlock = new TextDecoder().decode(localBlock);
|
|
591
972
|
if (localBlock && localBlock !== '0x0') {
|
|
592
973
|
localBlock = await peernet.get(localBlock, 'block');
|
|
593
|
-
localBlock = await new BlockMessage(localBlock);
|
|
974
|
+
localBlock = await new BlockMessage$1(localBlock);
|
|
594
975
|
this.#lastBlock = {...localBlock.decoded, hash: await localBlock.hash};
|
|
595
976
|
} else {
|
|
596
977
|
const latestBlock = await this.#getLatestBlock();
|
|
@@ -661,16 +1042,6 @@ class Chain {
|
|
|
661
1042
|
|
|
662
1043
|
#epochTimeout
|
|
663
1044
|
|
|
664
|
-
async #addTransaction(transaction) {
|
|
665
|
-
try {
|
|
666
|
-
transaction = await new TransactionMessage(transaction);
|
|
667
|
-
const has = await transactionPoolStore.has(await transaction.hash);
|
|
668
|
-
if (!has) await transactionPoolStore.put(await transaction.hash, transaction.encoded);
|
|
669
|
-
if (this.#participating && !this.#runningEpoch) this.#runEpoch();
|
|
670
|
-
} catch {
|
|
671
|
-
throw new Error('invalid transaction')
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
1045
|
|
|
675
1046
|
async #lastBlockHandler() {
|
|
676
1047
|
return new peernet.protos['peernet-response']({response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index }})
|
|
@@ -679,9 +1050,10 @@ async #lastBlockHandler() {
|
|
|
679
1050
|
async resolveBlock(hash) {
|
|
680
1051
|
if (!hash) throw new Error(`expected hash, got: ${hash}`)
|
|
681
1052
|
let block = await peernet.get(hash, 'block');
|
|
682
|
-
block = await new BlockMessage(block);
|
|
1053
|
+
block = await new BlockMessage$1(block);
|
|
683
1054
|
if (!await peernet.has(hash, 'block')) await peernet.put(hash, block.encoded, 'block');
|
|
684
1055
|
const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
|
|
1056
|
+
this.#totalSize += size;
|
|
685
1057
|
block = {...block.decoded, hash};
|
|
686
1058
|
if (this.#blocks[block.index] && this.#blocks[block.index].hash !== block.hash) throw `invalid block ${hash} @${block.index}`
|
|
687
1059
|
this.#blocks[block.index] = block;
|
|
@@ -707,37 +1079,29 @@ async resolveBlock(hash) {
|
|
|
707
1079
|
}
|
|
708
1080
|
}
|
|
709
1081
|
|
|
1082
|
+
/**
|
|
1083
|
+
*
|
|
1084
|
+
* @param {Block[]} blocks
|
|
1085
|
+
*/
|
|
710
1086
|
async #loadBlocks(blocks) {
|
|
711
1087
|
for (const block of blocks) {
|
|
712
1088
|
if (block && !block.loaded) {
|
|
713
1089
|
for (const transaction of block.transactions) {
|
|
714
1090
|
try {
|
|
715
1091
|
await this.#machine.execute(transaction.to, transaction.method, transaction.params);
|
|
716
|
-
|
|
1092
|
+
if (transaction.to === nativeToken$1) {
|
|
1093
|
+
this.#nativeCalls += 1;
|
|
1094
|
+
if (transaction.method === 'burn') this.#nativeBurns += 1;
|
|
1095
|
+
if (transaction.method === 'mint') this.#nativeMints += 1;
|
|
1096
|
+
if (transaction.method === 'transfer') this.#nativeTransfers += 1;
|
|
1097
|
+
}
|
|
1098
|
+
this.#totalTransactions += 1;
|
|
717
1099
|
} catch (error) {
|
|
718
1100
|
console.log(error);
|
|
719
1101
|
}
|
|
720
1102
|
}
|
|
721
1103
|
this.#blocks[block.index].loaded = true;
|
|
722
|
-
|
|
723
|
-
// let message = await peernet.get(block.hash, 'block')
|
|
724
|
-
|
|
725
|
-
// const compressed = pako.deflate(message);
|
|
726
|
-
// const result = pako.inflate(compressed);
|
|
727
|
-
// console.log(result.length, compressed.length);
|
|
728
|
-
//
|
|
729
|
-
// console.log(result.length - compressed.length);
|
|
730
|
-
|
|
731
|
-
// message = new BlockMessage(message)
|
|
732
|
-
// for (const transaction of message.decoded.transactions) {
|
|
733
|
-
// try {
|
|
734
|
-
// await this.#machine.execute(transaction.to, transaction.method, transaction.params)
|
|
735
|
-
//
|
|
736
|
-
// } catch (e) {
|
|
737
|
-
// // console.log(e);
|
|
738
|
-
// }
|
|
739
|
-
// }
|
|
740
|
-
// block.loaded = true
|
|
1104
|
+
debug(`loaded block: ${block.hash} @${block.index}`);
|
|
741
1105
|
}
|
|
742
1106
|
}
|
|
743
1107
|
}
|
|
@@ -756,26 +1120,10 @@ async resolveBlock(hash) {
|
|
|
756
1120
|
|
|
757
1121
|
async #addBlock(block) {
|
|
758
1122
|
// console.log(block);
|
|
759
|
-
const blockMessage = await new BlockMessage(new Uint8Array(Object.values(block)));
|
|
760
|
-
// if (!Buffer.isBuffer(block)) block = Buffer.from(block, 'hex')
|
|
761
|
-
// const transactionJob = async transaction => {
|
|
762
|
-
// try {
|
|
763
|
-
// transaction = await transactionPoolStore.get(transaction)
|
|
764
|
-
// } catch (e) {
|
|
765
|
-
// try {
|
|
766
|
-
// transaction = await peernet.get(transaction, 'transaction')
|
|
767
|
-
// } catch (e) {
|
|
768
|
-
// console.warn(`couldn't resolve ${transaction}`);
|
|
769
|
-
// }
|
|
770
|
-
// }
|
|
771
|
-
// transaction = new TransactionMessage(transaction)
|
|
772
|
-
// return transaction
|
|
773
|
-
// }
|
|
1123
|
+
const blockMessage = await new BlockMessage$1(new Uint8Array(Object.values(block)));
|
|
774
1124
|
await Promise.all(blockMessage.decoded.transactions
|
|
775
1125
|
.map(async transaction => transactionPoolStore.delete(await transaction.hash)));
|
|
776
1126
|
const hash = await blockMessage.hash;
|
|
777
|
-
// let transactions = blockMessage.decoded.transactions.map(tx => transactionJob(tx))
|
|
778
|
-
// transactions = await Promise.all(transactions)
|
|
779
1127
|
|
|
780
1128
|
await blockStore.put(hash, blockMessage.encoded);
|
|
781
1129
|
|
|
@@ -818,6 +1166,7 @@ async resolveBlock(hash) {
|
|
|
818
1166
|
async #updateState(message) {
|
|
819
1167
|
const hash = await message.hash;
|
|
820
1168
|
this.#lastBlock = { hash, ...message.decoded };
|
|
1169
|
+
await this.state.updateState(message);
|
|
821
1170
|
await chainStore.put('lastBlock', hash);
|
|
822
1171
|
}
|
|
823
1172
|
|
|
@@ -831,14 +1180,8 @@ async resolveBlock(hash) {
|
|
|
831
1180
|
// peerReputation(peerId)
|
|
832
1181
|
// {bandwith: {up, down}, uptime}
|
|
833
1182
|
this.#participating = true;
|
|
834
|
-
if (!await this.staticCall(addresses.validators, 'has', [address])) await this.createTransactionFrom(address, addresses.validators, 'addValidator', [address]);
|
|
1183
|
+
if (!await this.staticCall(addresses$1.validators, 'has', [address])) await this.createTransactionFrom(address, addresses$1.validators, 'addValidator', [address]);
|
|
835
1184
|
if (await this.hasTransactionToHandle() && !this.#runningEpoch) await this.#runEpoch();
|
|
836
|
-
|
|
837
|
-
// const runEpoch = () => setTimeout(async () => {
|
|
838
|
-
// if (await this.hasTransactionToHandle() && !this.#runningEpoch) await this.#runEpoch()
|
|
839
|
-
// runEpoch()
|
|
840
|
-
// }, 5000)
|
|
841
|
-
// runEpoch()
|
|
842
1185
|
}
|
|
843
1186
|
|
|
844
1187
|
calculateFee(transaction) {
|
|
@@ -848,25 +1191,6 @@ async resolveBlock(hash) {
|
|
|
848
1191
|
return (transaction.encoded.length / 1024) / 1e-6
|
|
849
1192
|
}
|
|
850
1193
|
|
|
851
|
-
async getTransactions (transactions) {
|
|
852
|
-
return new Promise(async (resolve, reject) => {
|
|
853
|
-
let size = 0;
|
|
854
|
-
const _transactions = [];
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
await Promise.all(transactions
|
|
858
|
-
.map(async tx => {
|
|
859
|
-
tx = await new TransactionMessage(tx);
|
|
860
|
-
size += tx.encoded.length;
|
|
861
|
-
if (!formatBytes(size).includes('MB') || formatBytes(size).includes('MB') && Number(formatBytes(size).split(' MB')[0]) <= 0.75) _transactions.push({...tx.decoded, hash: await tx.hash});
|
|
862
|
-
else resolve(_transactions);
|
|
863
|
-
}));
|
|
864
|
-
|
|
865
|
-
return resolve(_transactions)
|
|
866
|
-
})
|
|
867
|
-
|
|
868
|
-
}
|
|
869
|
-
|
|
870
1194
|
// todo filter tx that need to wait on prev nonce
|
|
871
1195
|
async #createBlock(limit = 1800) {
|
|
872
1196
|
// vote for transactions
|
|
@@ -899,7 +1223,7 @@ async resolveBlock(hash) {
|
|
|
899
1223
|
}
|
|
900
1224
|
// don't add empty block
|
|
901
1225
|
if (block.transactions.length === 0) return
|
|
902
|
-
const validators = await this.staticCall(addresses.validators, 'validators');
|
|
1226
|
+
const validators = await this.staticCall(addresses$1.validators, 'validators');
|
|
903
1227
|
console.log({validators});
|
|
904
1228
|
// block.validators = Object.keys(block.validators).reduce((set, key) => {
|
|
905
1229
|
// if (block.validators[key].active) {
|
|
@@ -974,7 +1298,7 @@ async resolveBlock(hash) {
|
|
|
974
1298
|
.map(async transaction => transactionPoolStore.delete(await transaction.hash)));
|
|
975
1299
|
|
|
976
1300
|
|
|
977
|
-
let blockMessage = await new BlockMessage(block);
|
|
1301
|
+
let blockMessage = await new BlockMessage$1(block);
|
|
978
1302
|
const hash = await blockMessage.hash;
|
|
979
1303
|
|
|
980
1304
|
|
|
@@ -992,58 +1316,18 @@ async resolveBlock(hash) {
|
|
|
992
1316
|
// transactionStore.put(message.hash, message.encoded)
|
|
993
1317
|
}
|
|
994
1318
|
|
|
995
|
-
|
|
996
|
-
transactions = await Promise.all(transactions.map(tx => new TransactionMessage(tx)));
|
|
997
|
-
return transactions
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
async promiseTransactionsContent(transactions) {
|
|
1001
|
-
transactions = await Promise.all(transactions.map(tx => new Promise(async (resolve, reject) => {
|
|
1002
|
-
resolve({ ...tx.decoded, hash: await tx.hash });
|
|
1003
|
-
})));
|
|
1004
|
-
|
|
1005
|
-
return transactions
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
async #getNonceFallback(address) {
|
|
1009
|
-
let transactions = await transactionPoolStore.values();
|
|
1010
|
-
transactions = await this.promiseTransactions(transactions);
|
|
1011
|
-
transactions = transactions.filter(tx => tx.decoded.from === address);
|
|
1012
|
-
transactions = await this.promiseTransactionsContent(transactions);
|
|
1013
|
-
|
|
1014
|
-
if (this.lastBlock?.hash && transactions.length === 0 && this.lastBlock.hash !== '0x0') {
|
|
1015
|
-
|
|
1016
|
-
let block = await peernet.get(this.lastBlock.hash);
|
|
1017
|
-
block = await new BlockMessage(block);
|
|
1018
|
-
|
|
1019
|
-
// for (let tx of block.decoded?.transactions) {
|
|
1020
|
-
// tx = await peernet.get(tx, 'transaction')
|
|
1021
|
-
// transactions.push(new TransactionMessage(tx))
|
|
1022
|
-
// }
|
|
1023
|
-
transactions = transactions.filter(tx => tx.from === address);
|
|
1024
|
-
while (transactions.length === 0 && block.decoded.index !== 0 && block.decoded.previousHash !== '0x0') {
|
|
1025
|
-
block = await blockStore.get(block.decoded.previousHash);
|
|
1026
|
-
block = await new BlockMessage(block);
|
|
1027
|
-
transactions = block.decoded.transactions.filter(tx => tx.from === address);
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
}
|
|
1031
|
-
if (transactions.length === 0) return 0
|
|
1032
|
-
|
|
1033
|
-
transactions = transactions.sort((a, b) => a.timestamp - b.timestamp);
|
|
1034
|
-
return transactions[transactions.length - 1].nonce
|
|
1035
|
-
}
|
|
1319
|
+
|
|
1036
1320
|
|
|
1037
|
-
async
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
await
|
|
1321
|
+
async #addTransaction(transaction) {
|
|
1322
|
+
try {
|
|
1323
|
+
transaction = await new TransactionMessage(transaction);
|
|
1324
|
+
const has = await transactionPoolStore.has(await transaction.hash);
|
|
1325
|
+
if (!has) await transactionPoolStore.put(await transaction.hash, transaction.encoded);
|
|
1326
|
+
if (this.#participating && !this.#runningEpoch) this.#runEpoch();
|
|
1327
|
+
} catch {
|
|
1328
|
+
throw new Error('invalid transaction')
|
|
1041
1329
|
}
|
|
1042
|
-
let nonce = await accountsStore.get(address);
|
|
1043
|
-
nonce = new TextDecoder().decode(nonce);
|
|
1044
|
-
return Number(nonce)
|
|
1045
1330
|
}
|
|
1046
|
-
|
|
1047
1331
|
/**
|
|
1048
1332
|
* whenever method = createContract params should hold the contract hash
|
|
1049
1333
|
*
|
|
@@ -1055,146 +1339,31 @@ async resolveBlock(hash) {
|
|
|
1055
1339
|
* @param {Array} params - array of paramters to apply to the contract method
|
|
1056
1340
|
* @param {Number} nonce - total transaction count [optional]
|
|
1057
1341
|
*/
|
|
1058
|
-
|
|
1342
|
+
async createTransaction(to, method, parameters, nonce, signature) {
|
|
1059
1343
|
return this.createTransactionFrom(peernet.selectedAccount, to, method, parameters, nonce)
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
/**
|
|
1065
|
-
*
|
|
1066
|
-
* @param {Object} transaction {}
|
|
1067
|
-
* @param {String} transaction.from address
|
|
1068
|
-
* @param {String} transaction.to address
|
|
1069
|
-
* @param {Object} transaction.params {}
|
|
1070
|
-
* @param {String} transaction.params.method get, call
|
|
1071
|
-
* @param {Buffer} transaction.params.data
|
|
1072
|
-
* @returns
|
|
1073
|
-
*/
|
|
1074
|
-
async createTransactionHash(transaction) {
|
|
1075
|
-
// todo: validate
|
|
1076
|
-
const peernetHash = await new index.CodecHash(transaction, {name: 'transaction-message'});
|
|
1077
|
-
return peernetHash.digest
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
/**
|
|
1081
|
-
* @params {object} transaction -
|
|
1082
|
-
* @params {object} wallet - any wallet/signer that supports sign(RAWtransaction)
|
|
1083
|
-
*/
|
|
1084
|
-
async #signTransaction (transaction, wallet) {
|
|
1085
|
-
return wallet.sign(await this.createTransactionHash(transaction))
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
async signTransaction(transaction, signer) {
|
|
1089
|
-
let identity = await walletStore.get('identity');
|
|
1090
|
-
identity = JSON.parse(new TextDecoder().decode(identity));
|
|
1091
|
-
const wallet = new MultiWallet__default["default"](peernet.network);
|
|
1092
|
-
wallet.recover(identity.mnemonic);
|
|
1093
|
-
const account = wallet.account(0).external(0);
|
|
1094
|
-
transaction.signature = await this.#signTransaction(transaction, account);
|
|
1095
|
-
transaction.signature = bs32__default["default"].encode(transaction.signature);
|
|
1096
|
-
return transaction
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
/**
|
|
1100
|
-
*
|
|
1101
|
-
* @param {Object} transaction
|
|
1102
|
-
* @param {Address} transaction.from
|
|
1103
|
-
* @param {Address} transaction.to
|
|
1104
|
-
* @param {String} transaction.method
|
|
1105
|
-
* @param {Array} transaction.params
|
|
1106
|
-
* @param {Number} transaction.nonce
|
|
1107
|
-
*
|
|
1108
|
-
* @returns {Object} transaction
|
|
1109
|
-
*/
|
|
1110
|
-
async createRawTransaction(transaction) {
|
|
1111
|
-
if (!transaction.from) transaction.from = peernet.selectedAccount;
|
|
1112
|
-
transaction.timestamp = Date.now();
|
|
1113
|
-
|
|
1114
|
-
if (transaction.nonce === undefined) {
|
|
1115
|
-
transaction.nonce = await this.getNonce(transaction.from);
|
|
1116
|
-
} else {
|
|
1117
|
-
let nonce = await accountsStore.get(transaction.from);
|
|
1118
|
-
nonce = new TextDecoder().decode(nonce);
|
|
1119
|
-
if (transaction.nonce < nonce) throw new Error(`a transaction with a higher nonce already exists`)
|
|
1120
|
-
if (transaction.nonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
|
|
1121
|
-
}
|
|
1122
|
-
return transaction
|
|
1123
|
-
}
|
|
1344
|
+
}
|
|
1124
1345
|
/**
|
|
1125
1346
|
* every tx done is trough contracts so no need for amount
|
|
1126
1347
|
* data is undefined when nothing is returned
|
|
1127
1348
|
* error is thrown on error so undefined data doesn't mean there is an error...
|
|
1128
1349
|
*
|
|
1129
|
-
* @param {
|
|
1130
|
-
* @param {
|
|
1350
|
+
* @param {Address} from - the sender address
|
|
1351
|
+
* @param {Address} to - the contract address for the contract to interact with
|
|
1131
1352
|
* @param {String} method - the method/function to run
|
|
1132
1353
|
* @param {Array} params - array of paramters to apply to the contract method
|
|
1133
1354
|
* @param {Number} nonce - total transaction count [optional]
|
|
1134
1355
|
*/
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
const transaction = await this.signTransaction(rawTransaction, from);
|
|
1140
|
-
const message = await new TransactionMessage(transaction);
|
|
1141
|
-
|
|
1142
|
-
let data;
|
|
1143
|
-
// await transactionPoolStore.put(message.hash, new TextEncoder().encode(JSON.stringify({signature, message: message.encoded})))
|
|
1144
|
-
const wait = () => new Promise(async (resolve, reject) => {
|
|
1145
|
-
if (pubsub.subscribers[`transaction.completed.${await message.hash}`]) {
|
|
1146
|
-
const result = pubsub.subscribers[`transaction.completed.${await message.hash}`].value;
|
|
1147
|
-
result.status === 'fulfilled' ? resolve(await result.hash) : reject({hash: await result.hash, error: result.error});
|
|
1148
|
-
} else {
|
|
1149
|
-
const completed = async result => {
|
|
1150
|
-
result.status === 'fulfilled' ? resolve(await result.hash) : reject({hash: await result.hash, error: result.error});
|
|
1151
|
-
|
|
1152
|
-
setTimeout(async () => {
|
|
1153
|
-
pubsub.unsubscribe(`transaction.completed.${await message.hash}`, completed);
|
|
1154
|
-
}, 10_000);
|
|
1155
|
-
};
|
|
1156
|
-
pubsub.subscribe(`transaction.completed.${await message.hash}`, completed);
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
});
|
|
1161
|
-
|
|
1162
|
-
await transactionPoolStore.put(await message.hash, message.encoded);
|
|
1163
|
-
peernet.publish('add-transaction', message.encoded);
|
|
1164
|
-
this.#addTransaction(message.encoded);
|
|
1165
|
-
return {hash: await message.hash, data, fee: await calculateFee(message.decoded), wait}
|
|
1166
|
-
} catch (error) {
|
|
1167
|
-
console.log(error);
|
|
1168
|
-
throw error
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
|
-
async createContractMessage(creator, contract, constructorParameters = []) {
|
|
1174
|
-
return createContractMessage(creator, contract, constructorParameters)
|
|
1175
|
-
}
|
|
1176
|
-
|
|
1177
|
-
async createContractAddress(creator, contract, constructorParameters = []) {
|
|
1178
|
-
contract = await this.createContractMessage(creator, contract, constructorParameters);
|
|
1179
|
-
return contract.hash
|
|
1356
|
+
async createTransactionFrom(from, to, method, parameters, nonce) {
|
|
1357
|
+
const event = await super.createTransactionFrom(from, to, method, parameters, nonce);
|
|
1358
|
+
this.#addTransaction(event.message.encoded);
|
|
1359
|
+
return event
|
|
1180
1360
|
}
|
|
1181
1361
|
|
|
1182
1362
|
/**
|
|
1183
1363
|
*
|
|
1184
|
-
* @param {
|
|
1185
|
-
* @
|
|
1186
|
-
* @returns
|
|
1364
|
+
* @param {Address} sender
|
|
1365
|
+
* @returns {globalMessage}
|
|
1187
1366
|
*/
|
|
1188
|
-
async deployContract(contract, constructorParameters = []) {
|
|
1189
|
-
const message = await createContractMessage(peernet.selectedAccount, contract, constructorParameters);
|
|
1190
|
-
try {
|
|
1191
|
-
await contractStore.put(await message.hash, message.encoded);
|
|
1192
|
-
} catch (error) {
|
|
1193
|
-
throw error
|
|
1194
|
-
}
|
|
1195
|
-
return this.createTransactionFrom(peernet.selectedAccount, addresses.contractFactory, 'registerContract', [await message.hash])
|
|
1196
|
-
}
|
|
1197
|
-
|
|
1198
1367
|
#createMessage(sender = peernet.selectedAccount) {
|
|
1199
1368
|
return {
|
|
1200
1369
|
sender,
|
|
@@ -1205,12 +1374,27 @@ async #signTransaction (transaction, wallet) {
|
|
|
1205
1374
|
}
|
|
1206
1375
|
}
|
|
1207
1376
|
|
|
1377
|
+
/**
|
|
1378
|
+
*
|
|
1379
|
+
* @param {Address} sender
|
|
1380
|
+
* @param {Address} contract
|
|
1381
|
+
* @param {String} method
|
|
1382
|
+
* @param {Array} parameters
|
|
1383
|
+
* @returns
|
|
1384
|
+
*/
|
|
1208
1385
|
internalCall(sender, contract, method, parameters) {
|
|
1209
1386
|
globalThis.msg = this.#createMessage(sender);
|
|
1210
1387
|
|
|
1211
1388
|
return this.#machine.execute(contract, method, parameters)
|
|
1212
1389
|
}
|
|
1213
1390
|
|
|
1391
|
+
/**
|
|
1392
|
+
*
|
|
1393
|
+
* @param {Address} contract
|
|
1394
|
+
* @param {String} method
|
|
1395
|
+
* @param {Array} parameters
|
|
1396
|
+
* @returns
|
|
1397
|
+
*/
|
|
1214
1398
|
call(contract, method, parameters) {
|
|
1215
1399
|
globalThis.msg = this.#createMessage();
|
|
1216
1400
|
|
|
@@ -1235,19 +1419,19 @@ async #signTransaction (transaction, wallet) {
|
|
|
1235
1419
|
}
|
|
1236
1420
|
|
|
1237
1421
|
mint(to, amount) {
|
|
1238
|
-
return this.call(addresses.nativeToken, 'mint', [to, amount])
|
|
1422
|
+
return this.call(addresses$1.nativeToken, 'mint', [to, amount])
|
|
1239
1423
|
}
|
|
1240
1424
|
|
|
1241
1425
|
transfer(from, to, amount) {
|
|
1242
|
-
return this.call(addresses.nativeToken, 'transfer', [from, to, amount])
|
|
1426
|
+
return this.call(addresses$1.nativeToken, 'transfer', [from, to, amount])
|
|
1243
1427
|
}
|
|
1244
1428
|
|
|
1245
1429
|
get balances() {
|
|
1246
|
-
return this.staticCall(addresses.nativeToken, 'balances')
|
|
1430
|
+
return this.staticCall(addresses$1.nativeToken, 'balances')
|
|
1247
1431
|
}
|
|
1248
1432
|
|
|
1249
1433
|
get contracts() {
|
|
1250
|
-
return this.staticCall(addresses.contractFactory, 'contracts')
|
|
1434
|
+
return this.staticCall(addresses$1.contractFactory, 'contracts')
|
|
1251
1435
|
}
|
|
1252
1436
|
|
|
1253
1437
|
deleteAll() {
|
|
@@ -1264,7 +1448,7 @@ async #signTransaction (transaction, wallet) {
|
|
|
1264
1448
|
* @example chain.lookup('myCoolContractName') // qmqsfddfdgfg...
|
|
1265
1449
|
*/
|
|
1266
1450
|
lookup(name) {
|
|
1267
|
-
return this.call(addresses.nameService, 'lookup', [name])
|
|
1451
|
+
return this.call(addresses$1.nameService, 'lookup', [name])
|
|
1268
1452
|
}
|
|
1269
1453
|
}
|
|
1270
1454
|
|