@leofcoin/chain 1.3.10 → 1.3.12

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/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 node_crypto = require('node:crypto');
9
- var node_path = require('node:path');
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"](node_path.join(__dirname, './workers/machine-worker.js'), {serialization: 'advanced', type:'module'});
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 = node_crypto.randomBytes(20).toString('hex');
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);
@@ -319,14 +321,13 @@ class Machine {
319
321
  message = await contractStore.get(parameters[0]);
320
322
  message = await new ContractMessage(message);
321
323
  }
322
- console.log(message);
323
324
  if (!this.#contracts[await message.hash]) await this.#runContract(message);
324
325
  }
325
326
  } catch (error) {
326
327
  throw new Error(`contract deployment failed for ${parameters[0]}\n${error.message}`)
327
328
  }
328
329
  return new Promise((resolve, reject) => {
329
- const id = node_crypto.randomBytes(20).toString('hex');
330
+ const id = crypto.randomBytes(20).toString('hex');
330
331
  const onmessage = message => {
331
332
  pubsub.unsubscribe(id, onmessage);
332
333
  if (message?.error) reject(message.error);
@@ -356,7 +357,7 @@ class Machine {
356
357
 
357
358
  get(contract, method, parameters) {
358
359
  return new Promise((resolve, reject) => {
359
- const id = node_crypto.randomBytes(20).toString();
360
+ const id = crypto.randomBytes(20).toString();
360
361
  const onmessage = message => {
361
362
  pubsub.unsubscribe(id, onmessage);
362
363
  resolve(message);
@@ -433,24 +434,401 @@ const calculateFee = async transaction => {
433
434
  return Number.parseFloat(fee.toString()).toFixed(decimals)
434
435
  };
435
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
+
436
747
  globalThis.BigNumber = utils.BigNumber;
437
748
 
438
749
  // check if browser or local
439
- class Chain {
750
+ class Chain extends Contract {
751
+ /** {Address[]} */
440
752
  #validators = []
753
+ /** {Block[]} */
441
754
  #blocks = []
755
+
442
756
  #machine
757
+ /** {Boolean} */
443
758
  #runningEpoch = false
759
+
760
+ /** {Boolean} */
444
761
  #chainSyncing = false
762
+
763
+ /** {Number} */
764
+ #totalSize = 0
765
+
766
+ /**
767
+ * {Block} {index, hash, previousHash}
768
+ */
445
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
+
446
799
  #participants = []
447
800
  #participating = false
448
801
  #jail = []
449
802
 
450
803
  constructor() {
804
+ super();
451
805
  return this.#init()
452
806
  }
453
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 nativeCalls() {
825
+ return this.#nativeCalls
826
+ }
827
+
828
+ get totalSize() {
829
+ return this.#totalSize
830
+ }
831
+
454
832
  get lib() {
455
833
  return lib
456
834
  }
@@ -460,7 +838,7 @@ class Chain {
460
838
  }
461
839
 
462
840
  get nativeToken() {
463
- return addresses.nativeToken
841
+ return addresses$1.nativeToken
464
842
  }
465
843
 
466
844
  get validators() {
@@ -480,10 +858,9 @@ class Chain {
480
858
  async #runEpoch() {
481
859
  this.#runningEpoch = true;
482
860
  console.log('epoch');
483
- const validators = await this.staticCall(addresses.validators, 'validators');
861
+ const validators = await this.staticCall(addresses$1.validators, 'validators');
484
862
  console.log(validators);
485
863
  if (!validators[peernet.selectedAccount]?.active) return
486
- debug(`validator ${peernet.selectedAccount} active`);
487
864
  const start = Date.now();
488
865
  try {
489
866
  await this.#createBlock();
@@ -502,16 +879,16 @@ class Chain {
502
879
  async #setup() {
503
880
 
504
881
  const contracts = [{
505
- address: addresses.contractFactory,
882
+ address: addresses$1.contractFactory,
506
883
  message: contractFactoryMessage
507
884
  }, {
508
- address: addresses.nativeToken,
885
+ address: addresses$1.nativeToken,
509
886
  message: nativeTokenMessage
510
887
  }, {
511
- address: addresses.validators,
888
+ address: addresses$1.validators,
512
889
  message: validatorsMessage
513
890
  }, {
514
- address: addresses.nameService,
891
+ address: addresses$1.nameService,
515
892
  message: nameServiceMessage
516
893
  }];
517
894
 
@@ -569,7 +946,7 @@ class Chain {
569
946
 
570
947
  if (latest.hash && latest.hash !== '0x0') {
571
948
  latest = await peernet.get(latest.hash, block);
572
- latest = await new BlockMessage(latest);
949
+ latest = await new BlockMessage$1(latest);
573
950
  }
574
951
 
575
952
  return latest
@@ -579,11 +956,13 @@ class Chain {
579
956
  // this.node = await new Node()
580
957
  this.#participants = [];
581
958
  this.#participating = false;
582
- const initialized = await contractStore.has(addresses.contractFactory);
959
+ const initialized = await contractStore.has(addresses$1.contractFactory);
583
960
  if (!initialized) await this.#setup();
584
961
 
585
962
 
586
963
  this.utils = { BigNumber: utils.BigNumber, formatUnits: utils.formatUnits, parseUnits: utils.parseUnits };
964
+
965
+ this.state = new State();
587
966
 
588
967
  try {
589
968
  let localBlock;
@@ -596,7 +975,7 @@ class Chain {
596
975
  localBlock = new TextDecoder().decode(localBlock);
597
976
  if (localBlock && localBlock !== '0x0') {
598
977
  localBlock = await peernet.get(localBlock, 'block');
599
- localBlock = await new BlockMessage(localBlock);
978
+ localBlock = await new BlockMessage$1(localBlock);
600
979
  this.#lastBlock = {...localBlock.decoded, hash: await localBlock.hash};
601
980
  } else {
602
981
  const latestBlock = await this.#getLatestBlock();
@@ -667,16 +1046,6 @@ class Chain {
667
1046
 
668
1047
  #epochTimeout
669
1048
 
670
- async #addTransaction(transaction) {
671
- try {
672
- transaction = await new TransactionMessage(transaction);
673
- const has = await transactionPoolStore.has(await transaction.hash);
674
- if (!has) await transactionPoolStore.put(await transaction.hash, transaction.encoded);
675
- if (this.#participating && !this.#runningEpoch) this.#runEpoch();
676
- } catch {
677
- throw new Error('invalid transaction')
678
- }
679
- }
680
1049
 
681
1050
  async #lastBlockHandler() {
682
1051
  return new peernet.protos['peernet-response']({response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index }})
@@ -685,9 +1054,10 @@ async #lastBlockHandler() {
685
1054
  async resolveBlock(hash) {
686
1055
  if (!hash) throw new Error(`expected hash, got: ${hash}`)
687
1056
  let block = await peernet.get(hash, 'block');
688
- block = await new BlockMessage(block);
1057
+ block = await new BlockMessage$1(block);
689
1058
  if (!await peernet.has(hash, 'block')) await peernet.put(hash, block.encoded, 'block');
690
1059
  const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
1060
+ this.#totalSize += size;
691
1061
  block = {...block.decoded, hash};
692
1062
  if (this.#blocks[block.index] && this.#blocks[block.index].hash !== block.hash) throw `invalid block ${hash} @${block.index}`
693
1063
  this.#blocks[block.index] = block;
@@ -713,51 +1083,40 @@ async resolveBlock(hash) {
713
1083
  }
714
1084
  }
715
1085
 
1086
+ /**
1087
+ *
1088
+ * @param {Block[]} blocks
1089
+ */
716
1090
  async #loadBlocks(blocks) {
717
1091
  for (const block of blocks) {
718
1092
  if (block && !block.loaded) {
719
1093
  for (const transaction of block.transactions) {
720
1094
  try {
721
1095
  await this.#machine.execute(transaction.to, transaction.method, transaction.params);
722
-
1096
+ if (transaction.to === nativeToken$1) {
1097
+ this.#nativeCalls += 1;
1098
+ if (transaction.method === 'burn') this.#nativeBurns += 1;
1099
+ if (transaction.method === 'mint') this.#nativeMints += 1;
1100
+ if (transaction.method === 'transfer') this.#nativeTransfers += 1;
1101
+ }
1102
+ this.#totalTransactions += 1;
723
1103
  } catch (error) {
724
1104
  console.log(error);
725
1105
  }
726
1106
  }
727
1107
  this.#blocks[block.index].loaded = true;
728
- console.log(`loaded block: ${block.hash} @${block.index}`);
729
- // let message = await peernet.get(block.hash, 'block')
730
-
731
- // const compressed = pako.deflate(message);
732
- // const result = pako.inflate(compressed);
733
- // console.log(result.length, compressed.length);
734
- //
735
- // console.log(result.length - compressed.length);
736
-
737
- // message = new BlockMessage(message)
738
- // for (const transaction of message.decoded.transactions) {
739
- // try {
740
- // await this.#machine.execute(transaction.to, transaction.method, transaction.params)
741
- //
742
- // } catch (e) {
743
- // // console.log(e);
744
- // }
745
- // }
746
- // block.loaded = true
1108
+ debug(`loaded block: ${block.hash} @${block.index}`);
747
1109
  }
748
1110
  }
749
1111
  }
750
1112
 
751
1113
  async #executeTransaction({hash, from, to, method, params, nonce}) {
752
- console.log(hash, from);
753
1114
  try {
754
1115
  let result = await this.#machine.execute(to, method, params, from, nonce);
755
1116
  // if (!result) result = this.#machine.state
756
- console.log({result});
757
1117
  pubsub.publish(`transaction.completed.${hash}`, {status: 'fulfilled', hash});
758
1118
  return result || 'no state change'
759
1119
  } catch (error) {
760
- console.log(error);
761
1120
  pubsub.publish(`transaction.completed.${hash}`, {status: 'fail', hash, error: error});
762
1121
  throw error
763
1122
  }
@@ -765,26 +1124,10 @@ async resolveBlock(hash) {
765
1124
 
766
1125
  async #addBlock(block) {
767
1126
  // console.log(block);
768
- const blockMessage = await new BlockMessage(new Uint8Array(Object.values(block)));
769
- // if (!Buffer.isBuffer(block)) block = Buffer.from(block, 'hex')
770
- // const transactionJob = async transaction => {
771
- // try {
772
- // transaction = await transactionPoolStore.get(transaction)
773
- // } catch (e) {
774
- // try {
775
- // transaction = await peernet.get(transaction, 'transaction')
776
- // } catch (e) {
777
- // console.warn(`couldn't resolve ${transaction}`);
778
- // }
779
- // }
780
- // transaction = new TransactionMessage(transaction)
781
- // return transaction
782
- // }
1127
+ const blockMessage = await new BlockMessage$1(new Uint8Array(Object.values(block)));
783
1128
  await Promise.all(blockMessage.decoded.transactions
784
1129
  .map(async transaction => transactionPoolStore.delete(await transaction.hash)));
785
1130
  const hash = await blockMessage.hash;
786
- // let transactions = blockMessage.decoded.transactions.map(tx => transactionJob(tx))
787
- // transactions = await Promise.all(transactions)
788
1131
 
789
1132
  await blockStore.put(hash, blockMessage.encoded);
790
1133
 
@@ -827,6 +1170,7 @@ async resolveBlock(hash) {
827
1170
  async #updateState(message) {
828
1171
  const hash = await message.hash;
829
1172
  this.#lastBlock = { hash, ...message.decoded };
1173
+ await this.state.updateState(message);
830
1174
  await chainStore.put('lastBlock', hash);
831
1175
  }
832
1176
 
@@ -840,14 +1184,8 @@ async resolveBlock(hash) {
840
1184
  // peerReputation(peerId)
841
1185
  // {bandwith: {up, down}, uptime}
842
1186
  this.#participating = true;
843
- if (!await this.staticCall(addresses.validators, 'has', [address])) await this.createTransactionFrom(address, addresses.validators, 'addValidator', [address]);
1187
+ if (!await this.staticCall(addresses$1.validators, 'has', [address])) await this.createTransactionFrom(address, addresses$1.validators, 'addValidator', [address]);
844
1188
  if (await this.hasTransactionToHandle() && !this.#runningEpoch) await this.#runEpoch();
845
-
846
- // const runEpoch = () => setTimeout(async () => {
847
- // if (await this.hasTransactionToHandle() && !this.#runningEpoch) await this.#runEpoch()
848
- // runEpoch()
849
- // }, 5000)
850
- // runEpoch()
851
1189
  }
852
1190
 
853
1191
  calculateFee(transaction) {
@@ -857,25 +1195,6 @@ async resolveBlock(hash) {
857
1195
  return (transaction.encoded.length / 1024) / 1e-6
858
1196
  }
859
1197
 
860
- async getTransactions (transactions) {
861
- return new Promise(async (resolve, reject) => {
862
- let size = 0;
863
- const _transactions = [];
864
-
865
-
866
- await Promise.all(transactions
867
- .map(async tx => {
868
- tx = await new TransactionMessage(tx);
869
- size += tx.encoded.length;
870
- 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});
871
- else resolve(_transactions);
872
- }));
873
-
874
- return resolve(_transactions)
875
- })
876
-
877
- }
878
-
879
1198
  // todo filter tx that need to wait on prev nonce
880
1199
  async #createBlock(limit = 1800) {
881
1200
  // vote for transactions
@@ -893,7 +1212,7 @@ async resolveBlock(hash) {
893
1212
 
894
1213
  // exclude failing tx
895
1214
  transactions = await this.getTransactions(transactions.slice(0, transactions.length < 1800 ? transactions.length : 1800));
896
- console.log(transactions);
1215
+
897
1216
  transactions = transactions.sort((a, b) => a.nonce - b.nonce);
898
1217
  for (let transaction of transactions) {
899
1218
  try {
@@ -901,15 +1220,14 @@ console.log(transactions);
901
1220
  block.transactions.push(transaction);
902
1221
  block.fees += Number(calculateFee(transaction));
903
1222
  await accountsStore.put(transaction.from, new TextEncoder().encode(String(transaction.nonce)));
904
- } catch (error) {
905
- console.log(error);
1223
+ } catch {
906
1224
  transaction = await new TransactionMessage(transaction);
907
1225
  await transactionPoolStore.delete(await transaction.hash);
908
1226
  }
909
1227
  }
910
1228
  // don't add empty block
911
1229
  if (block.transactions.length === 0) return
912
- const validators = await this.staticCall(addresses.validators, 'validators');
1230
+ const validators = await this.staticCall(addresses$1.validators, 'validators');
913
1231
  console.log({validators});
914
1232
  // block.validators = Object.keys(block.validators).reduce((set, key) => {
915
1233
  // if (block.validators[key].active) {
@@ -984,7 +1302,7 @@ console.log(transactions);
984
1302
  .map(async transaction => transactionPoolStore.delete(await transaction.hash)));
985
1303
 
986
1304
 
987
- let blockMessage = await new BlockMessage(block);
1305
+ let blockMessage = await new BlockMessage$1(block);
988
1306
  const hash = await blockMessage.hash;
989
1307
 
990
1308
 
@@ -1002,58 +1320,18 @@ console.log(transactions);
1002
1320
  // transactionStore.put(message.hash, message.encoded)
1003
1321
  }
1004
1322
 
1005
- async promiseTransactions(transactions) {
1006
- transactions = await Promise.all(transactions.map(tx => new TransactionMessage(tx)));
1007
- return transactions
1008
- }
1009
-
1010
- async promiseTransactionsContent(transactions) {
1011
- transactions = await Promise.all(transactions.map(tx => new Promise(async (resolve, reject) => {
1012
- resolve({ ...tx.decoded, hash: await tx.hash });
1013
- })));
1014
-
1015
- return transactions
1016
- }
1017
-
1018
- async #getNonceFallback(address) {
1019
- let transactions = await transactionPoolStore.values();
1020
- transactions = await this.promiseTransactions(transactions);
1021
- transactions = transactions.filter(tx => tx.decoded.from === address);
1022
- transactions = await this.promiseTransactionsContent(transactions);
1023
-
1024
- if (this.lastBlock?.hash && transactions.length === 0 && this.lastBlock.hash !== '0x0') {
1025
-
1026
- let block = await peernet.get(this.lastBlock.hash);
1027
- block = await new BlockMessage(block);
1028
-
1029
- // for (let tx of block.decoded?.transactions) {
1030
- // tx = await peernet.get(tx, 'transaction')
1031
- // transactions.push(new TransactionMessage(tx))
1032
- // }
1033
- transactions = transactions.filter(tx => tx.from === address);
1034
- while (transactions.length === 0 && block.decoded.index !== 0 && block.decoded.previousHash !== '0x0') {
1035
- block = await blockStore.get(block.decoded.previousHash);
1036
- block = await new BlockMessage(block);
1037
- transactions = block.decoded.transactions.filter(tx => tx.from === address);
1038
- }
1039
-
1040
- }
1041
- if (transactions.length === 0) return 0
1042
-
1043
- transactions = transactions.sort((a, b) => a.timestamp - b.timestamp);
1044
- return transactions[transactions.length - 1].nonce
1045
- }
1323
+
1046
1324
 
1047
- async getNonce(address) {
1048
- if (!await accountsStore.has(address)) {
1049
- const nonce = await this.#getNonceFallback(address);
1050
- await accountsStore.put(address, new TextEncoder().encode(String(nonce)));
1325
+ async #addTransaction(transaction) {
1326
+ try {
1327
+ transaction = await new TransactionMessage(transaction);
1328
+ const has = await transactionPoolStore.has(await transaction.hash);
1329
+ if (!has) await transactionPoolStore.put(await transaction.hash, transaction.encoded);
1330
+ if (this.#participating && !this.#runningEpoch) this.#runEpoch();
1331
+ } catch {
1332
+ throw new Error('invalid transaction')
1051
1333
  }
1052
- let nonce = await accountsStore.get(address);
1053
- nonce = new TextDecoder().decode(nonce);
1054
- return Number(nonce)
1055
1334
  }
1056
-
1057
1335
  /**
1058
1336
  * whenever method = createContract params should hold the contract hash
1059
1337
  *
@@ -1065,72 +1343,9 @@ console.log(transactions);
1065
1343
  * @param {Array} params - array of paramters to apply to the contract method
1066
1344
  * @param {Number} nonce - total transaction count [optional]
1067
1345
  */
1068
- async createTransaction(to, method, parameters, nonce, signature) {
1346
+ async createTransaction(to, method, parameters, nonce, signature) {
1069
1347
  return this.createTransactionFrom(peernet.selectedAccount, to, method, parameters, nonce)
1070
- }
1071
-
1072
-
1073
-
1074
- /**
1075
- *
1076
- * @param {Transaction} transaction
1077
- * @param {String} transaction.from address
1078
- * @param {String} transaction.to address
1079
- * @param {Object} transaction.params {}
1080
- * @param {String} transaction.params.method get, call
1081
- * @param {Buffer} transaction.params.data
1082
- * @returns
1083
- */
1084
- async createTransactionHash(transaction) {
1085
- // todo: validate
1086
- const peernetHash = await new index.CodecHash(transaction, {name: 'transaction-message'});
1087
- return peernetHash.digest
1088
- }
1089
-
1090
- /**
1091
- * @param {Transaction} transaction
1092
- * @param {object} wallet any wallet/signer that supports sign(RAWtransaction)
1093
- */
1094
- async #signTransaction (transaction, wallet) {
1095
- return wallet.sign(await this.createTransactionHash(transaction))
1096
- }
1097
-
1098
- async signTransaction(transaction, signer) {
1099
- let identity = await walletStore.get('identity');
1100
- identity = JSON.parse(new TextDecoder().decode(identity));
1101
- const wallet = new MultiWallet__default["default"](peernet.network);
1102
- wallet.recover(identity.mnemonic);
1103
- const account = wallet.account(0).external(0);
1104
- transaction.signature = await this.#signTransaction(transaction, account);
1105
- transaction.signature = bs32__default["default"].encode(transaction.signature);
1106
- return transaction
1107
- }
1108
-
1109
- /**
1110
- *
1111
- * @param {Transaction} transaction
1112
- * @param {Address} transaction.from
1113
- * @param {Address} transaction.to
1114
- * @param {String} transaction.method
1115
- * @param {Array} transaction.params
1116
- * @param {Number} transaction.nonce
1117
- *
1118
- * @returns {RawTransaction} transaction
1119
- */
1120
- async createRawTransaction(transaction) {
1121
- if (!transaction.from) transaction.from = peernet.selectedAccount;
1122
- transaction.timestamp = Date.now();
1123
-
1124
- if (transaction.nonce === undefined) {
1125
- transaction.nonce = await this.getNonce(transaction.from);
1126
- } else {
1127
- let nonce = await accountsStore.get(transaction.from);
1128
- nonce = new TextDecoder().decode(nonce);
1129
- if (transaction.nonce < nonce) throw new Error(`a transaction with a higher nonce already exists`)
1130
- if (transaction.nonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
1131
- }
1132
- return transaction
1133
- }
1348
+ }
1134
1349
  /**
1135
1350
  * every tx done is trough contracts so no need for amount
1136
1351
  * data is undefined when nothing is returned
@@ -1142,83 +1357,10 @@ async #signTransaction (transaction, wallet) {
1142
1357
  * @param {Array} params - array of paramters to apply to the contract method
1143
1358
  * @param {Number} nonce - total transaction count [optional]
1144
1359
  */
1145
- async createTransactionFrom(from, to, method, parameters, nonce) {
1146
-
1147
- try {
1148
-
1149
- const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params: parameters});
1150
- const transaction = await this.signTransaction(rawTransaction, from);
1151
- const message = await new TransactionMessage(transaction);
1152
-
1153
- let data;
1154
- // await transactionPoolStore.put(message.hash, new TextEncoder().encode(JSON.stringify({signature, message: message.encoded})))
1155
- const wait = () => new Promise(async (resolve, reject) => {
1156
- if (pubsub.subscribers[`transaction.completed.${await message.hash}`]) {
1157
- const result = pubsub.subscribers[`transaction.completed.${await message.hash}`].value;
1158
- result.status === 'fulfilled' ? resolve(await result.hash) : reject({hash: await result.hash, error: result.error});
1159
- } else {
1160
- const completed = async result => {
1161
- result.status === 'fulfilled' ? resolve(await result.hash) : reject({hash: await result.hash, error: result.error});
1162
-
1163
- setTimeout(async () => {
1164
- pubsub.unsubscribe(`transaction.completed.${await message.hash}`, completed);
1165
- }, 10_000);
1166
- };
1167
- pubsub.subscribe(`transaction.completed.${await message.hash}`, completed);
1168
- }
1169
-
1170
-
1171
- });
1172
-
1173
- await transactionPoolStore.put(await message.hash, message.encoded);
1174
- peernet.publish('add-transaction', message.encoded);
1175
- this.#addTransaction(message.encoded);
1176
- debug('creating tx');
1177
- return {hash: await message.hash, data, fee: await calculateFee(message.decoded), wait}
1178
- } catch (error) {
1179
- console.log(error);
1180
- throw error
1181
- }
1182
-
1183
- }
1184
-
1185
- /**
1186
- *
1187
- * @param {Address} creator
1188
- * @param {String} contract
1189
- * @param {Array} constructorParameters
1190
- * @returns lib.createContractMessage
1191
- */
1192
- async createContractMessage(creator, contract, constructorParameters = []) {
1193
- return createContractMessage(creator, contract, constructorParameters)
1194
- }
1195
-
1196
- /**
1197
- *
1198
- * @param {Address} creator
1199
- * @param {String} contract
1200
- * @param {Array} constructorParameters
1201
- * @returns {Address}
1202
- */
1203
- async createContractAddress(creator, contract, constructorParameters = []) {
1204
- contract = await this.createContractMessage(creator, contract, constructorParameters);
1205
- return contract.hash
1206
- }
1207
-
1208
- /**
1209
- *
1210
- * @param {String} contract
1211
- * @param {Array} parameters
1212
- * @returns
1213
- */
1214
- async deployContract(contract, constructorParameters = []) {
1215
- const message = await createContractMessage(peernet.selectedAccount, contract, constructorParameters);
1216
- try {
1217
- await contractStore.put(await message.hash, message.encoded);
1218
- } catch (error) {
1219
- throw error
1220
- }
1221
- return this.createTransactionFrom(peernet.selectedAccount, addresses.contractFactory, 'registerContract', [await message.hash])
1360
+ async createTransactionFrom(from, to, method, parameters, nonce) {
1361
+ const event = await super.createTransactionFrom(from, to, method, parameters, nonce);
1362
+ this.#addTransaction(event.message.encoded);
1363
+ return event
1222
1364
  }
1223
1365
 
1224
1366
  /**
@@ -1281,19 +1423,19 @@ async #signTransaction (transaction, wallet) {
1281
1423
  }
1282
1424
 
1283
1425
  mint(to, amount) {
1284
- return this.call(addresses.nativeToken, 'mint', [to, amount])
1426
+ return this.call(addresses$1.nativeToken, 'mint', [to, amount])
1285
1427
  }
1286
1428
 
1287
1429
  transfer(from, to, amount) {
1288
- return this.call(addresses.nativeToken, 'transfer', [from, to, amount])
1430
+ return this.call(addresses$1.nativeToken, 'transfer', [from, to, amount])
1289
1431
  }
1290
1432
 
1291
1433
  get balances() {
1292
- return this.staticCall(addresses.nativeToken, 'balances')
1434
+ return this.staticCall(addresses$1.nativeToken, 'balances')
1293
1435
  }
1294
1436
 
1295
1437
  get contracts() {
1296
- return this.staticCall(addresses.contractFactory, 'contracts')
1438
+ return this.staticCall(addresses$1.contractFactory, 'contracts')
1297
1439
  }
1298
1440
 
1299
1441
  deleteAll() {
@@ -1310,7 +1452,7 @@ async #signTransaction (transaction, wallet) {
1310
1452
  * @example chain.lookup('myCoolContractName') // qmqsfddfdgfg...
1311
1453
  */
1312
1454
  lookup(name) {
1313
- return this.call(addresses.nameService, 'lookup', [name])
1455
+ return this.call(addresses$1.nameService, 'lookup', [name])
1314
1456
  }
1315
1457
  }
1316
1458