@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.
@@ -3,10 +3,11 @@ import _BN from 'bn.js';
3
3
  import '@ethersproject/bytes';
4
4
  import { Logger } from '@ethersproject/logger';
5
5
  import '@ethersproject/bignumber';
6
- import { randomBytes } from 'node:crypto';
7
- import { join } from 'node:path';
6
+ import { randomBytes } from 'crypto';
7
+ import { join } from 'path';
8
8
  import EasyWorker from '@vandeurenglenn/easy-worker';
9
9
  import { FormatInterface } from '@leofcoin/codec-format-interface';
10
+ import pako from 'pako';
10
11
  import MultiWallet from '@leofcoin/multi-wallet';
11
12
  import { CodecHash } from '@leofcoin/codec-format-interface/dist/index';
12
13
  import bs32 from '@vandeurenglenn/base32';
@@ -15,17 +16,17 @@ var contractFactory$2 = "ihny2gqg6c6mwy5mhbrs5ulkkozsgwtk5vuz5krjidouy4mbwfdbjnb
15
16
  var nativeToken$2 = "ihny2gqhoockyg7yg4n5bpxuldahfavpqnmpoe2bn4ivnxmk7redc2ltwkb";
16
17
  var nameService$2 = "ihny2gqgztp3vj6qy7fgrfer7y5c5hxnp6imdz6v5spi4edkwtm5fkd5z2h";
17
18
  var validators$2 = "ihny2gqh4e2pr4pbtpkamhj3htsvuoydy3wotaudoeaktgcdwmoij66pecp";
18
- var addresses = {
19
+ var addresses$1 = {
19
20
  contractFactory: contractFactory$2,
20
21
  nativeToken: nativeToken$2,
21
22
  nameService: nameService$2,
22
23
  validators: validators$2
23
24
  };
24
25
 
25
- const contractFactory$1 = addresses.contractFactory;
26
- const nameService$1 = addresses.nameService;
27
- const nativeToken$1 = addresses.nativeToken;
28
- const validators$1 = addresses.validators;
26
+ const contractFactory$1 = addresses$1.contractFactory;
27
+ const nameService$1 = addresses$1.nameService;
28
+ const nativeToken$1 = addresses$1.nativeToken;
29
+ const validators$1 = addresses$1.validators;
29
30
 
30
31
  const version$1 = "bignumber/5.6.2";
31
32
 
@@ -125,7 +126,7 @@ message BlockMessage {
125
126
  }
126
127
  `;
127
128
 
128
- class BlockMessage extends FormatInterface {
129
+ class BlockMessage$1 extends FormatInterface {
129
130
  get keys() {
130
131
  return ['index', 'previousHash', 'timestamp', 'reward', 'fees', 'transactions', 'validators']
131
132
  }
@@ -289,22 +290,27 @@ class Machine {
289
290
 
290
291
  }
291
292
 
293
+ /**
294
+ *
295
+ * @param {Address} contract
296
+ * @param {String} method
297
+ * @param {Array} parameters
298
+ * @returns Promise<message>
299
+ */
292
300
  async execute(contract, method, parameters) {
293
- /** */
294
301
  try {
295
302
  if (contract === contractFactory$1 && method === 'registerContract') {
296
303
  if (this.#contracts[parameters[0]]) throw new Error(`duplicate contract @${parameters[0]}`)
297
304
  let message;
298
- if (!contractStore.has(parameters[0])) {
305
+ if (!await contractStore.has(parameters[0])) {
299
306
  message = await peernet.get(parameters[0], 'contract');
300
- message = new ContractMessage(message);
307
+ message = await new ContractMessage(message);
301
308
  await contractStore.put(await message.hash, message.encoded);
302
309
  }
303
310
  if (!message) {
304
311
  message = await contractStore.get(parameters[0]);
305
- message = new ContractMessage(message);
312
+ message = await new ContractMessage(message);
306
313
  }
307
-
308
314
  if (!this.#contracts[await message.hash]) await this.#runContract(message);
309
315
  }
310
316
  } catch (error) {
@@ -418,24 +424,397 @@ const calculateFee = async transaction => {
418
424
  return Number.parseFloat(fee.toString()).toFixed(decimals)
419
425
  };
420
426
 
427
+ class State {
428
+ constructor() {
429
+ // return this.#init()
430
+ }
431
+
432
+ // async #init() {
433
+ // const state = await stateStore.get()
434
+ // for (const [key, value] of Object.entries(state)) {
435
+ //
436
+ // }
437
+ //
438
+ // return this
439
+ // }
440
+
441
+ async put(key, value, isCompressed = true) {
442
+ value = isCompressed ? value : await pako.deflate(value);
443
+ await stateStore.put(key, value);
444
+ }
445
+
446
+ async get(key, isCompressed = true) {
447
+ const value = await stateStore.get(key);
448
+ return isCompressed = pako.inflate(value)
449
+ }
450
+
451
+ updateState(block) {
452
+ // block.decoded.index
453
+ // this.#isUpdateNeeded()
454
+ }
455
+ }
456
+
457
+ class Protocol {
458
+ limit = 1800
459
+ }
460
+
461
+ class Transaction extends Protocol {
462
+ constructor() {
463
+ super();
464
+ }
465
+
466
+ /**
467
+ *
468
+ * @param {Address[]} transactions
469
+ * @returns transactions to include
470
+ */
471
+ async getTransactions (transactions) {
472
+ return new Promise(async (resolve, reject) => {
473
+ let size = 0;
474
+ const _transactions = [];
475
+
476
+
477
+ await Promise.all(transactions
478
+ .map(async tx => {
479
+ tx = await new TransactionMessage(tx);
480
+ size += tx.encoded.length;
481
+ 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});
482
+ else resolve(_transactions);
483
+ }));
484
+
485
+ return resolve(_transactions)
486
+ })
487
+
488
+ }
489
+
490
+ /**
491
+ *
492
+ * @param {Transaction[]} transactions An array containing Transactions
493
+ * @returns {TransactionMessage}
494
+ */
495
+ async promiseTransactions(transactions) {
496
+ transactions = await Promise.all(transactions.map(tx => new TransactionMessage(tx)));
497
+ return transactions
498
+ }
499
+
500
+ /**
501
+ *
502
+ * @param {Transaction[]} transactions An array containing Transactions
503
+ * @returns {Object} {transaction.decoded, transaction.hash}
504
+ */
505
+ async promiseTransactionsContent(transactions) {
506
+ transactions = await Promise.all(transactions.map(tx => new Promise(async (resolve, reject) => {
507
+ resolve({ ...tx.decoded, hash: await tx.hash });
508
+ })));
509
+
510
+ return transactions
511
+ }
512
+
513
+ /**
514
+ * When a nonce isn't found for an address fallback to just checking the transactionnPoolStore
515
+ * @param {Address} address
516
+ * @returns {Number} nonce
517
+ */
518
+ async #getNonceFallback(address) {
519
+ let transactions = await transactionPoolStore.values();
520
+ transactions = await this.promiseTransactions(transactions);
521
+ transactions = transactions.filter(tx => tx.decoded.from === address);
522
+ transactions = await this.promiseTransactionsContent(transactions);
523
+
524
+ if (this.lastBlock?.hash && transactions.length === 0 && this.lastBlock.hash !== '0x0') {
525
+
526
+ let block = await peernet.get(this.lastBlock.hash);
527
+ block = await new BlockMessage(block);
528
+
529
+ // for (let tx of block.decoded?.transactions) {
530
+ // tx = await peernet.get(tx, 'transaction')
531
+ // transactions.push(new TransactionMessage(tx))
532
+ // }
533
+ transactions = transactions.filter(tx => tx.from === address);
534
+ while (transactions.length === 0 && block.decoded.index !== 0 && block.decoded.previousHash !== '0x0') {
535
+ block = await blockStore.get(block.decoded.previousHash);
536
+ block = await new BlockMessage(block);
537
+ transactions = block.decoded.transactions.filter(tx => tx.from === address);
538
+ }
539
+
540
+ }
541
+ if (transactions.length === 0) return 0
542
+
543
+ transactions = transactions.sort((a, b) => a.timestamp - b.timestamp);
544
+ return transactions[transactions.length - 1].nonce
545
+ }
546
+
547
+ /**
548
+ * Get amount of transactions by address
549
+ * @param {Address} address The address to get the nonce for
550
+ * @returns {Number} nonce
551
+ */
552
+ async getNonce(address) {
553
+ if (!await accountsStore.has(address)) {
554
+ const nonce = await this.#getNonceFallback(address);
555
+ await accountsStore.put(address, new TextEncoder().encode(String(nonce)));
556
+ }
557
+ // todo: are those in the pool in cluded also ? they need to be included!!!
558
+ let nonce = await accountsStore.get(address);
559
+ nonce = new TextDecoder().decode(nonce);
560
+ return Number(nonce)
561
+ }
562
+
563
+ /**
564
+ * whenever method = createContract params should hold the contract hash
565
+ *
566
+ * example: [hash]
567
+ * createTransaction('0x0', 'createContract', [hash])
568
+ *
569
+ * @param {String} to - the contract address for the contract to interact with
570
+ * @param {String} method - the method/function to run
571
+ * @param {Array} params - array of paramters to apply to the contract method
572
+ * @param {Number} nonce - total transaction count [optional]
573
+ */
574
+ async createTransaction(to, method, parameters, nonce, signature) {
575
+ return this.createTransactionFrom(peernet.selectedAccount, to, method, parameters, nonce)
576
+ }
577
+
578
+ /**
579
+ *
580
+ * @param {Transaction} transaction
581
+ * @param {String} transaction.from address
582
+ * @param {String} transaction.to address
583
+ * @param {Object} transaction.params {}
584
+ * @param {String} transaction.params.method get, call
585
+ * @param {Buffer} transaction.params.data
586
+ * @returns
587
+ */
588
+ async createTransactionHash(transaction) {
589
+ // todo: validate
590
+ const peernetHash = await new CodecHash(transaction, {name: 'transaction-message'});
591
+ return peernetHash.digest
592
+ }
593
+
594
+ /**
595
+ * @param {Transaction} transaction
596
+ * @param {object} wallet any wallet/signer that supports sign(RAWtransaction)
597
+ */
598
+ async #signTransaction (transaction, wallet) {
599
+ return wallet.sign(await this.createTransactionHash(transaction))
600
+ }
601
+
602
+ /**
603
+ *
604
+ * @param {RawTransaction} transaction
605
+ * @param {Signer} signer
606
+ * @returns {Transaction} a signed transaction
607
+ */
608
+ async signTransaction(transaction, signer) {
609
+ let identity = await walletStore.get('identity');
610
+ identity = JSON.parse(new TextDecoder().decode(identity));
611
+ const wallet = new MultiWallet(peernet.network);
612
+ wallet.recover(identity.mnemonic);
613
+ const account = wallet.account(0).external(0);
614
+ transaction.signature = await this.#signTransaction(transaction, account);
615
+ transaction.signature = bs32.encode(transaction.signature);
616
+ return transaction
617
+ }
618
+
619
+ /**
620
+ *
621
+ * @param {Transaction} transaction
622
+ * @param {Address} transaction.from
623
+ * @param {Address} transaction.to
624
+ * @param {String} transaction.method
625
+ * @param {Array} transaction.params
626
+ * @param {Number} transaction.nonce
627
+ *
628
+ * @returns {RawTransaction} transaction
629
+ */
630
+ async ensureNonce(transaction) {
631
+ if (!transaction.from) transaction.from = peernet.selectedAccount;
632
+ transaction.timestamp = Date.now();
633
+
634
+ if (transaction.nonce === undefined) {
635
+ transaction.nonce = await this.getNonce(transaction.from);
636
+ } else {
637
+ let nonce = await accountsStore.get(transaction.from);
638
+ nonce = new TextDecoder().decode(nonce);
639
+ if (transaction.nonce < nonce) throw new Error(`a transaction with a higher nonce already exists`)
640
+ if (transaction.nonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
641
+ }
642
+ return transaction
643
+ }
644
+
645
+ /**
646
+ * every tx done is trough contracts so no need for amount
647
+ * data is undefined when nothing is returned
648
+ * error is thrown on error so undefined data doesn't mean there is an error...
649
+ *
650
+ * @param {Address} from - the sender address
651
+ * @param {Address} to - the contract address for the contract to interact with
652
+ * @param {String} method - the method/function to run
653
+ * @param {Array} params - array of paramters to apply to the contract method
654
+ * @param {Number} nonce - total transaction count [optional]
655
+ */
656
+ async createTransactionFrom(from, to, method, parameters, nonce) {
657
+ try {
658
+ const rawTransaction = await this.ensureNonce({from, to, nonce, method, params: parameters});
659
+ const transaction = await this.signTransaction(rawTransaction, from);
660
+ const message = await new TransactionMessage(transaction);
661
+
662
+ let data;
663
+ const wait = () => new Promise(async (resolve, reject) => {
664
+ if (pubsub.subscribers[`transaction.completed.${await message.hash}`]) {
665
+ const result = pubsub.subscribers[`transaction.completed.${await message.hash}`].value;
666
+ result.status === 'fulfilled' ? resolve(await result.hash) : reject({hash: await result.hash, error: result.error});
667
+ } else {
668
+ const completed = async result => {
669
+ result.status === 'fulfilled' ? resolve(await result.hash) : reject({hash: await result.hash, error: result.error});
670
+
671
+ setTimeout(async () => {
672
+ pubsub.unsubscribe(`transaction.completed.${await message.hash}`, completed);
673
+ }, 10_000);
674
+ };
675
+ pubsub.subscribe(`transaction.completed.${await message.hash}`, completed);
676
+ }
677
+ });
678
+ await transactionPoolStore.put(await message.hash, message.encoded);
679
+ peernet.publish('add-transaction', message.encoded);
680
+ return {hash: await message.hash, data, fee: await calculateFee(message.decoded), wait, message}
681
+ } catch (error) {
682
+ console.log(error);
683
+ throw error
684
+ }
685
+ }
686
+ }
687
+
688
+ /**
689
+ * @extends {Transaction}
690
+ */
691
+ class Contract extends Transaction {
692
+ constructor() {
693
+ super();
694
+ }
695
+
696
+ /**
697
+ *
698
+ * @param {Address} creator
699
+ * @param {String} contract
700
+ * @param {Array} constructorParameters
701
+ * @returns lib.createContractMessage
702
+ */
703
+ async createContractMessage(creator, contract, constructorParameters = []) {
704
+ return createContractMessage(creator, contract, constructorParameters)
705
+ }
706
+
707
+ /**
708
+ *
709
+ * @param {Address} creator
710
+ * @param {String} contract
711
+ * @param {Array} constructorParameters
712
+ * @returns {Address}
713
+ */
714
+ async createContractAddress(creator, contract, constructorParameters = []) {
715
+ contract = await this.createContractMessage(creator, contract, constructorParameters);
716
+ return contract.hash
717
+ }
718
+
719
+ /**
720
+ *
721
+ * @param {String} contract
722
+ * @param {Array} parameters
723
+ * @returns
724
+ */
725
+ async deployContract(contract, constructorParameters = []) {
726
+ const message = await createContractMessage(peernet.selectedAccount, contract, constructorParameters);
727
+ try {
728
+ await contractStore.put(await message.hash, message.encoded);
729
+ } catch (error) {
730
+ throw error
731
+ }
732
+ return this.createTransactionFrom(peernet.selectedAccount, addresses.contractFactory, 'registerContract', [await message.hash])
733
+ }
734
+
735
+ }
736
+
421
737
  globalThis.BigNumber = BigNumber;
422
738
 
423
739
  // check if browser or local
424
- class Chain {
740
+ class Chain extends Contract {
741
+ /** {Address[]} */
425
742
  #validators = []
743
+ /** {Block[]} */
426
744
  #blocks = []
745
+
427
746
  #machine
747
+ /** {Boolean} */
428
748
  #runningEpoch = false
749
+
750
+ /** {Boolean} */
429
751
  #chainSyncing = false
752
+
753
+ /** {Number} */
754
+ #totalSize = 0
755
+
756
+ /**
757
+ * {Block} {index, hash, previousHash}
758
+ */
430
759
  #lastBlock = {index: 0, hash: '0x0', previousHash: '0x0'}
760
+
761
+ /**
762
+ * amount the native token has been iteracted with
763
+ */
764
+ #nativeCalls = 0
765
+
766
+ /**
767
+ * amount the native token has been iteracted with
768
+ */
769
+ #nativeTransfers = 0
770
+
771
+ /**
772
+ * amount of native token burned
773
+ * {Number}
774
+ */
775
+ #nativeBurns = 0
776
+
777
+ /**
778
+ * amount of native tokens minted
779
+ * {Number}
780
+ */
781
+ #nativeMints = 0
782
+
783
+ /**
784
+ * total amount of transactions
785
+ * {Number}
786
+ */
787
+ #totalTransactions = 0
788
+
431
789
  #participants = []
432
790
  #participating = false
433
791
  #jail = []
434
792
 
435
793
  constructor() {
794
+ super();
436
795
  return this.#init()
437
796
  }
438
797
 
798
+ get nativeMints() {
799
+ return this.#nativeMints
800
+ }
801
+
802
+ get nativeBurns() {
803
+ return this.#nativeBurns
804
+ }
805
+
806
+ get nativeTransfers() {
807
+ return this.#nativeTransfers
808
+ }
809
+
810
+ get totalTransactions() {
811
+ return this.#totalTransactions
812
+ }
813
+
814
+ get totalSize() {
815
+ return this.#totalSize
816
+ }
817
+
439
818
  get lib() {
440
819
  return lib
441
820
  }
@@ -445,7 +824,7 @@ class Chain {
445
824
  }
446
825
 
447
826
  get nativeToken() {
448
- return addresses.nativeToken
827
+ return addresses$1.nativeToken
449
828
  }
450
829
 
451
830
  get validators() {
@@ -465,10 +844,9 @@ class Chain {
465
844
  async #runEpoch() {
466
845
  this.#runningEpoch = true;
467
846
  console.log('epoch');
468
- const validators = await this.staticCall(addresses.validators, 'validators');
847
+ const validators = await this.staticCall(addresses$1.validators, 'validators');
469
848
  console.log(validators);
470
849
  if (!validators[peernet.selectedAccount]?.active) return
471
-
472
850
  const start = Date.now();
473
851
  try {
474
852
  await this.#createBlock();
@@ -487,16 +865,16 @@ class Chain {
487
865
  async #setup() {
488
866
 
489
867
  const contracts = [{
490
- address: addresses.contractFactory,
868
+ address: addresses$1.contractFactory,
491
869
  message: contractFactoryMessage
492
870
  }, {
493
- address: addresses.nativeToken,
871
+ address: addresses$1.nativeToken,
494
872
  message: nativeTokenMessage
495
873
  }, {
496
- address: addresses.validators,
874
+ address: addresses$1.validators,
497
875
  message: validatorsMessage
498
876
  }, {
499
- address: addresses.nameService,
877
+ address: addresses$1.nameService,
500
878
  message: nameServiceMessage
501
879
  }];
502
880
 
@@ -554,7 +932,7 @@ class Chain {
554
932
 
555
933
  if (latest.hash && latest.hash !== '0x0') {
556
934
  latest = await peernet.get(latest.hash, block);
557
- latest = await new BlockMessage(latest);
935
+ latest = await new BlockMessage$1(latest);
558
936
  }
559
937
 
560
938
  return latest
@@ -564,11 +942,13 @@ class Chain {
564
942
  // this.node = await new Node()
565
943
  this.#participants = [];
566
944
  this.#participating = false;
567
- const initialized = await contractStore.has(addresses.contractFactory);
945
+ const initialized = await contractStore.has(addresses$1.contractFactory);
568
946
  if (!initialized) await this.#setup();
569
947
 
570
948
 
571
949
  this.utils = { BigNumber, formatUnits, parseUnits };
950
+
951
+ this.state = new State();
572
952
 
573
953
  try {
574
954
  let localBlock;
@@ -581,7 +961,7 @@ class Chain {
581
961
  localBlock = new TextDecoder().decode(localBlock);
582
962
  if (localBlock && localBlock !== '0x0') {
583
963
  localBlock = await peernet.get(localBlock, 'block');
584
- localBlock = await new BlockMessage(localBlock);
964
+ localBlock = await new BlockMessage$1(localBlock);
585
965
  this.#lastBlock = {...localBlock.decoded, hash: await localBlock.hash};
586
966
  } else {
587
967
  const latestBlock = await this.#getLatestBlock();
@@ -652,16 +1032,6 @@ class Chain {
652
1032
 
653
1033
  #epochTimeout
654
1034
 
655
- async #addTransaction(transaction) {
656
- try {
657
- transaction = await new TransactionMessage(transaction);
658
- const has = await transactionPoolStore.has(await transaction.hash);
659
- if (!has) await transactionPoolStore.put(await transaction.hash, transaction.encoded);
660
- if (this.#participating && !this.#runningEpoch) this.#runEpoch();
661
- } catch {
662
- throw new Error('invalid transaction')
663
- }
664
- }
665
1035
 
666
1036
  async #lastBlockHandler() {
667
1037
  return new peernet.protos['peernet-response']({response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index }})
@@ -670,9 +1040,10 @@ async #lastBlockHandler() {
670
1040
  async resolveBlock(hash) {
671
1041
  if (!hash) throw new Error(`expected hash, got: ${hash}`)
672
1042
  let block = await peernet.get(hash, 'block');
673
- block = await new BlockMessage(block);
1043
+ block = await new BlockMessage$1(block);
674
1044
  if (!await peernet.has(hash, 'block')) await peernet.put(hash, block.encoded, 'block');
675
1045
  const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
1046
+ this.#totalSize += size;
676
1047
  block = {...block.decoded, hash};
677
1048
  if (this.#blocks[block.index] && this.#blocks[block.index].hash !== block.hash) throw `invalid block ${hash} @${block.index}`
678
1049
  this.#blocks[block.index] = block;
@@ -698,37 +1069,29 @@ async resolveBlock(hash) {
698
1069
  }
699
1070
  }
700
1071
 
1072
+ /**
1073
+ *
1074
+ * @param {Block[]} blocks
1075
+ */
701
1076
  async #loadBlocks(blocks) {
702
1077
  for (const block of blocks) {
703
1078
  if (block && !block.loaded) {
704
1079
  for (const transaction of block.transactions) {
705
1080
  try {
706
1081
  await this.#machine.execute(transaction.to, transaction.method, transaction.params);
707
-
1082
+ if (transaction.to === nativeToken$1) {
1083
+ this.#nativeCalls += 1;
1084
+ if (transaction.method === 'burn') this.#nativeBurns += 1;
1085
+ if (transaction.method === 'mint') this.#nativeMints += 1;
1086
+ if (transaction.method === 'transfer') this.#nativeTransfers += 1;
1087
+ }
1088
+ this.#totalTransactions += 1;
708
1089
  } catch (error) {
709
1090
  console.log(error);
710
1091
  }
711
1092
  }
712
1093
  this.#blocks[block.index].loaded = true;
713
- console.log(`loaded block: ${block.hash} @${block.index}`);
714
- // let message = await peernet.get(block.hash, 'block')
715
-
716
- // const compressed = pako.deflate(message);
717
- // const result = pako.inflate(compressed);
718
- // console.log(result.length, compressed.length);
719
- //
720
- // console.log(result.length - compressed.length);
721
-
722
- // message = new BlockMessage(message)
723
- // for (const transaction of message.decoded.transactions) {
724
- // try {
725
- // await this.#machine.execute(transaction.to, transaction.method, transaction.params)
726
- //
727
- // } catch (e) {
728
- // // console.log(e);
729
- // }
730
- // }
731
- // block.loaded = true
1094
+ debug(`loaded block: ${block.hash} @${block.index}`);
732
1095
  }
733
1096
  }
734
1097
  }
@@ -747,26 +1110,10 @@ async resolveBlock(hash) {
747
1110
 
748
1111
  async #addBlock(block) {
749
1112
  // console.log(block);
750
- const blockMessage = await new BlockMessage(new Uint8Array(Object.values(block)));
751
- // if (!Buffer.isBuffer(block)) block = Buffer.from(block, 'hex')
752
- // const transactionJob = async transaction => {
753
- // try {
754
- // transaction = await transactionPoolStore.get(transaction)
755
- // } catch (e) {
756
- // try {
757
- // transaction = await peernet.get(transaction, 'transaction')
758
- // } catch (e) {
759
- // console.warn(`couldn't resolve ${transaction}`);
760
- // }
761
- // }
762
- // transaction = new TransactionMessage(transaction)
763
- // return transaction
764
- // }
1113
+ const blockMessage = await new BlockMessage$1(new Uint8Array(Object.values(block)));
765
1114
  await Promise.all(blockMessage.decoded.transactions
766
1115
  .map(async transaction => transactionPoolStore.delete(await transaction.hash)));
767
1116
  const hash = await blockMessage.hash;
768
- // let transactions = blockMessage.decoded.transactions.map(tx => transactionJob(tx))
769
- // transactions = await Promise.all(transactions)
770
1117
 
771
1118
  await blockStore.put(hash, blockMessage.encoded);
772
1119
 
@@ -809,6 +1156,7 @@ async resolveBlock(hash) {
809
1156
  async #updateState(message) {
810
1157
  const hash = await message.hash;
811
1158
  this.#lastBlock = { hash, ...message.decoded };
1159
+ await this.state.updateState(message);
812
1160
  await chainStore.put('lastBlock', hash);
813
1161
  }
814
1162
 
@@ -822,14 +1170,8 @@ async resolveBlock(hash) {
822
1170
  // peerReputation(peerId)
823
1171
  // {bandwith: {up, down}, uptime}
824
1172
  this.#participating = true;
825
- if (!await this.staticCall(addresses.validators, 'has', [address])) await this.createTransactionFrom(address, addresses.validators, 'addValidator', [address]);
1173
+ if (!await this.staticCall(addresses$1.validators, 'has', [address])) await this.createTransactionFrom(address, addresses$1.validators, 'addValidator', [address]);
826
1174
  if (await this.hasTransactionToHandle() && !this.#runningEpoch) await this.#runEpoch();
827
-
828
- // const runEpoch = () => setTimeout(async () => {
829
- // if (await this.hasTransactionToHandle() && !this.#runningEpoch) await this.#runEpoch()
830
- // runEpoch()
831
- // }, 5000)
832
- // runEpoch()
833
1175
  }
834
1176
 
835
1177
  calculateFee(transaction) {
@@ -839,25 +1181,6 @@ async resolveBlock(hash) {
839
1181
  return (transaction.encoded.length / 1024) / 1e-6
840
1182
  }
841
1183
 
842
- async getTransactions (transactions) {
843
- return new Promise(async (resolve, reject) => {
844
- let size = 0;
845
- const _transactions = [];
846
-
847
-
848
- await Promise.all(transactions
849
- .map(async tx => {
850
- tx = await new TransactionMessage(tx);
851
- size += tx.encoded.length;
852
- 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});
853
- else resolve(_transactions);
854
- }));
855
-
856
- return resolve(_transactions)
857
- })
858
-
859
- }
860
-
861
1184
  // todo filter tx that need to wait on prev nonce
862
1185
  async #createBlock(limit = 1800) {
863
1186
  // vote for transactions
@@ -890,7 +1213,7 @@ async resolveBlock(hash) {
890
1213
  }
891
1214
  // don't add empty block
892
1215
  if (block.transactions.length === 0) return
893
- const validators = await this.staticCall(addresses.validators, 'validators');
1216
+ const validators = await this.staticCall(addresses$1.validators, 'validators');
894
1217
  console.log({validators});
895
1218
  // block.validators = Object.keys(block.validators).reduce((set, key) => {
896
1219
  // if (block.validators[key].active) {
@@ -965,7 +1288,7 @@ async resolveBlock(hash) {
965
1288
  .map(async transaction => transactionPoolStore.delete(await transaction.hash)));
966
1289
 
967
1290
 
968
- let blockMessage = await new BlockMessage(block);
1291
+ let blockMessage = await new BlockMessage$1(block);
969
1292
  const hash = await blockMessage.hash;
970
1293
 
971
1294
 
@@ -983,58 +1306,18 @@ async resolveBlock(hash) {
983
1306
  // transactionStore.put(message.hash, message.encoded)
984
1307
  }
985
1308
 
986
- async promiseTransactions(transactions) {
987
- transactions = await Promise.all(transactions.map(tx => new TransactionMessage(tx)));
988
- return transactions
989
- }
990
-
991
- async promiseTransactionsContent(transactions) {
992
- transactions = await Promise.all(transactions.map(tx => new Promise(async (resolve, reject) => {
993
- resolve({ ...tx.decoded, hash: await tx.hash });
994
- })));
995
-
996
- return transactions
997
- }
998
-
999
- async #getNonceFallback(address) {
1000
- let transactions = await transactionPoolStore.values();
1001
- transactions = await this.promiseTransactions(transactions);
1002
- transactions = transactions.filter(tx => tx.decoded.from === address);
1003
- transactions = await this.promiseTransactionsContent(transactions);
1004
-
1005
- if (this.lastBlock?.hash && transactions.length === 0 && this.lastBlock.hash !== '0x0') {
1006
-
1007
- let block = await peernet.get(this.lastBlock.hash);
1008
- block = await new BlockMessage(block);
1009
-
1010
- // for (let tx of block.decoded?.transactions) {
1011
- // tx = await peernet.get(tx, 'transaction')
1012
- // transactions.push(new TransactionMessage(tx))
1013
- // }
1014
- transactions = transactions.filter(tx => tx.from === address);
1015
- while (transactions.length === 0 && block.decoded.index !== 0 && block.decoded.previousHash !== '0x0') {
1016
- block = await blockStore.get(block.decoded.previousHash);
1017
- block = await new BlockMessage(block);
1018
- transactions = block.decoded.transactions.filter(tx => tx.from === address);
1019
- }
1020
-
1021
- }
1022
- if (transactions.length === 0) return 0
1023
-
1024
- transactions = transactions.sort((a, b) => a.timestamp - b.timestamp);
1025
- return transactions[transactions.length - 1].nonce
1026
- }
1309
+
1027
1310
 
1028
- async getNonce(address) {
1029
- if (!await accountsStore.has(address)) {
1030
- const nonce = await this.#getNonceFallback(address);
1031
- await accountsStore.put(address, new TextEncoder().encode(String(nonce)));
1311
+ async #addTransaction(transaction) {
1312
+ try {
1313
+ transaction = await new TransactionMessage(transaction);
1314
+ const has = await transactionPoolStore.has(await transaction.hash);
1315
+ if (!has) await transactionPoolStore.put(await transaction.hash, transaction.encoded);
1316
+ if (this.#participating && !this.#runningEpoch) this.#runEpoch();
1317
+ } catch {
1318
+ throw new Error('invalid transaction')
1032
1319
  }
1033
- let nonce = await accountsStore.get(address);
1034
- nonce = new TextDecoder().decode(nonce);
1035
- return Number(nonce)
1036
1320
  }
1037
-
1038
1321
  /**
1039
1322
  * whenever method = createContract params should hold the contract hash
1040
1323
  *
@@ -1046,146 +1329,31 @@ async resolveBlock(hash) {
1046
1329
  * @param {Array} params - array of paramters to apply to the contract method
1047
1330
  * @param {Number} nonce - total transaction count [optional]
1048
1331
  */
1049
- async createTransaction(to, method, parameters, nonce, signature) {
1332
+ async createTransaction(to, method, parameters, nonce, signature) {
1050
1333
  return this.createTransactionFrom(peernet.selectedAccount, to, method, parameters, nonce)
1051
- }
1052
-
1053
-
1054
-
1055
- /**
1056
- *
1057
- * @param {Object} transaction {}
1058
- * @param {String} transaction.from address
1059
- * @param {String} transaction.to address
1060
- * @param {Object} transaction.params {}
1061
- * @param {String} transaction.params.method get, call
1062
- * @param {Buffer} transaction.params.data
1063
- * @returns
1064
- */
1065
- async createTransactionHash(transaction) {
1066
- // todo: validate
1067
- const peernetHash = await new CodecHash(transaction, {name: 'transaction-message'});
1068
- return peernetHash.digest
1069
- }
1070
-
1071
- /**
1072
- * @params {object} transaction -
1073
- * @params {object} wallet - any wallet/signer that supports sign(RAWtransaction)
1074
- */
1075
- async #signTransaction (transaction, wallet) {
1076
- return wallet.sign(await this.createTransactionHash(transaction))
1077
- }
1078
-
1079
- async signTransaction(transaction, signer) {
1080
- let identity = await walletStore.get('identity');
1081
- identity = JSON.parse(new TextDecoder().decode(identity));
1082
- const wallet = new MultiWallet(peernet.network);
1083
- wallet.recover(identity.mnemonic);
1084
- const account = wallet.account(0).external(0);
1085
- transaction.signature = await this.#signTransaction(transaction, account);
1086
- transaction.signature = bs32.encode(transaction.signature);
1087
- return transaction
1088
- }
1089
-
1090
- /**
1091
- *
1092
- * @param {Object} transaction
1093
- * @param {Address} transaction.from
1094
- * @param {Address} transaction.to
1095
- * @param {String} transaction.method
1096
- * @param {Array} transaction.params
1097
- * @param {Number} transaction.nonce
1098
- *
1099
- * @returns {Object} transaction
1100
- */
1101
- async createRawTransaction(transaction) {
1102
- if (!transaction.from) transaction.from = peernet.selectedAccount;
1103
- transaction.timestamp = Date.now();
1104
-
1105
- if (transaction.nonce === undefined) {
1106
- transaction.nonce = await this.getNonce(transaction.from);
1107
- } else {
1108
- let nonce = await accountsStore.get(transaction.from);
1109
- nonce = new TextDecoder().decode(nonce);
1110
- if (transaction.nonce < nonce) throw new Error(`a transaction with a higher nonce already exists`)
1111
- if (transaction.nonce === nonce) throw new Error(`a transaction with the same nonce already exists`)
1112
- }
1113
- return transaction
1114
- }
1334
+ }
1115
1335
  /**
1116
1336
  * every tx done is trough contracts so no need for amount
1117
1337
  * data is undefined when nothing is returned
1118
1338
  * error is thrown on error so undefined data doesn't mean there is an error...
1119
1339
  *
1120
- * @param {String} from - the sender address
1121
- * @param {String} to - the contract address for the contract to interact with
1340
+ * @param {Address} from - the sender address
1341
+ * @param {Address} to - the contract address for the contract to interact with
1122
1342
  * @param {String} method - the method/function to run
1123
1343
  * @param {Array} params - array of paramters to apply to the contract method
1124
1344
  * @param {Number} nonce - total transaction count [optional]
1125
1345
  */
1126
- async createTransactionFrom(from, to, method, parameters, nonce) {
1127
- try {
1128
-
1129
- const rawTransaction = await this.createRawTransaction({from, to, nonce, method, params: parameters});
1130
- const transaction = await this.signTransaction(rawTransaction, from);
1131
- const message = await new TransactionMessage(transaction);
1132
-
1133
- let data;
1134
- // await transactionPoolStore.put(message.hash, new TextEncoder().encode(JSON.stringify({signature, message: message.encoded})))
1135
- const wait = () => new Promise(async (resolve, reject) => {
1136
- if (pubsub.subscribers[`transaction.completed.${await message.hash}`]) {
1137
- const result = pubsub.subscribers[`transaction.completed.${await message.hash}`].value;
1138
- result.status === 'fulfilled' ? resolve(await result.hash) : reject({hash: await result.hash, error: result.error});
1139
- } else {
1140
- const completed = async result => {
1141
- result.status === 'fulfilled' ? resolve(await result.hash) : reject({hash: await result.hash, error: result.error});
1142
-
1143
- setTimeout(async () => {
1144
- pubsub.unsubscribe(`transaction.completed.${await message.hash}`, completed);
1145
- }, 10_000);
1146
- };
1147
- pubsub.subscribe(`transaction.completed.${await message.hash}`, completed);
1148
- }
1149
-
1150
-
1151
- });
1152
-
1153
- await transactionPoolStore.put(await message.hash, message.encoded);
1154
- peernet.publish('add-transaction', message.encoded);
1155
- this.#addTransaction(message.encoded);
1156
- return {hash: await message.hash, data, fee: await calculateFee(message.decoded), wait}
1157
- } catch (error) {
1158
- console.log(error);
1159
- throw error
1160
- }
1161
-
1162
- }
1163
-
1164
- async createContractMessage(creator, contract, constructorParameters = []) {
1165
- return createContractMessage(creator, contract, constructorParameters)
1166
- }
1167
-
1168
- async createContractAddress(creator, contract, constructorParameters = []) {
1169
- contract = await this.createContractMessage(creator, contract, constructorParameters);
1170
- return contract.hash
1346
+ async createTransactionFrom(from, to, method, parameters, nonce) {
1347
+ const event = await super.createTransactionFrom(from, to, method, parameters, nonce);
1348
+ this.#addTransaction(event.message.encoded);
1349
+ return event
1171
1350
  }
1172
1351
 
1173
1352
  /**
1174
1353
  *
1175
- * @param {String} contract
1176
- * @param {Array} parameters
1177
- * @returns
1354
+ * @param {Address} sender
1355
+ * @returns {globalMessage}
1178
1356
  */
1179
- async deployContract(contract, constructorParameters = []) {
1180
- const message = await createContractMessage(peernet.selectedAccount, contract, constructorParameters);
1181
- try {
1182
- await contractStore.put(await message.hash, message.encoded);
1183
- } catch (error) {
1184
- throw error
1185
- }
1186
- return this.createTransactionFrom(peernet.selectedAccount, addresses.contractFactory, 'registerContract', [await message.hash])
1187
- }
1188
-
1189
1357
  #createMessage(sender = peernet.selectedAccount) {
1190
1358
  return {
1191
1359
  sender,
@@ -1196,12 +1364,27 @@ async #signTransaction (transaction, wallet) {
1196
1364
  }
1197
1365
  }
1198
1366
 
1367
+ /**
1368
+ *
1369
+ * @param {Address} sender
1370
+ * @param {Address} contract
1371
+ * @param {String} method
1372
+ * @param {Array} parameters
1373
+ * @returns
1374
+ */
1199
1375
  internalCall(sender, contract, method, parameters) {
1200
1376
  globalThis.msg = this.#createMessage(sender);
1201
1377
 
1202
1378
  return this.#machine.execute(contract, method, parameters)
1203
1379
  }
1204
1380
 
1381
+ /**
1382
+ *
1383
+ * @param {Address} contract
1384
+ * @param {String} method
1385
+ * @param {Array} parameters
1386
+ * @returns
1387
+ */
1205
1388
  call(contract, method, parameters) {
1206
1389
  globalThis.msg = this.#createMessage();
1207
1390
 
@@ -1226,19 +1409,19 @@ async #signTransaction (transaction, wallet) {
1226
1409
  }
1227
1410
 
1228
1411
  mint(to, amount) {
1229
- return this.call(addresses.nativeToken, 'mint', [to, amount])
1412
+ return this.call(addresses$1.nativeToken, 'mint', [to, amount])
1230
1413
  }
1231
1414
 
1232
1415
  transfer(from, to, amount) {
1233
- return this.call(addresses.nativeToken, 'transfer', [from, to, amount])
1416
+ return this.call(addresses$1.nativeToken, 'transfer', [from, to, amount])
1234
1417
  }
1235
1418
 
1236
1419
  get balances() {
1237
- return this.staticCall(addresses.nativeToken, 'balances')
1420
+ return this.staticCall(addresses$1.nativeToken, 'balances')
1238
1421
  }
1239
1422
 
1240
1423
  get contracts() {
1241
- return this.staticCall(addresses.contractFactory, 'contracts')
1424
+ return this.staticCall(addresses$1.contractFactory, 'contracts')
1242
1425
  }
1243
1426
 
1244
1427
  deleteAll() {
@@ -1255,7 +1438,7 @@ async #signTransaction (transaction, wallet) {
1255
1438
  * @example chain.lookup('myCoolContractName') // qmqsfddfdgfg...
1256
1439
  */
1257
1440
  lookup(name) {
1258
- return this.call(addresses.nameService, 'lookup', [name])
1441
+ return this.call(addresses$1.nameService, 'lookup', [name])
1259
1442
  }
1260
1443
  }
1261
1444