@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/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);
@@ -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 = node_crypto.randomBytes(20).toString('hex');
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 = node_crypto.randomBytes(20).toString();
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
- console.log(`loaded block: ${block.hash} @${block.index}`);
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
- async promiseTransactions(transactions) {
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 getNonce(address) {
1038
- if (!await accountsStore.has(address)) {
1039
- const nonce = await this.#getNonceFallback(address);
1040
- await accountsStore.put(address, new TextEncoder().encode(String(nonce)));
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
- async createTransaction(to, method, parameters, nonce, signature) {
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 {String} from - the sender address
1130
- * @param {String} to - the contract address for the contract to interact with
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
- async createTransactionFrom(from, to, method, parameters, nonce) {
1136
- try {
1137
-
1138
- const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params: parameters});
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 {String} contract
1185
- * @param {Array} parameters
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