@leofcoin/chain 1.5.24 → 1.5.26

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/exports/chain.js CHANGED
@@ -12,7 +12,7 @@ const requestTimeout = 30000;
12
12
  const syncTimeout = 30000;
13
13
  class Protocol {
14
14
  constructor() {
15
- this.resolveTimeout = 30000;
15
+ this.resolveTimeout = 10000;
16
16
  }
17
17
  get limit() {
18
18
  return limit;
@@ -41,11 +41,11 @@ class Transaction extends Protocol {
41
41
  return new Promise(async (resolve, reject) => {
42
42
  let size = 0;
43
43
  const _transactions = [];
44
- await Promise.all(transactions
45
- .map(async (tx) => {
44
+ await Promise.all(transactions.map(async (tx) => {
46
45
  tx = await new TransactionMessage(tx);
47
46
  size += tx.encoded.length;
48
- if (!formatBytes(size).includes('MB') || formatBytes(size).includes('MB') && Number(formatBytes(size).split(' MB')[0]) <= 0.75)
47
+ if (!formatBytes(size).includes('MB') ||
48
+ (formatBytes(size).includes('MB') && Number(formatBytes(size).split(' MB')[0]) <= 0.75))
49
49
  _transactions.push({ ...tx.decoded, hash: await tx.hash() });
50
50
  else
51
51
  resolve(_transactions);
@@ -59,7 +59,7 @@ class Transaction extends Protocol {
59
59
  * @returns {TransactionMessage}
60
60
  */
61
61
  async promiseTransactions(transactions) {
62
- transactions = await Promise.all(transactions.map(tx => new TransactionMessage(tx.encoded || tx)));
62
+ transactions = await Promise.all(transactions.map((tx) => new TransactionMessage(tx.encoded || tx)));
63
63
  return transactions;
64
64
  }
65
65
  /**
@@ -68,7 +68,7 @@ class Transaction extends Protocol {
68
68
  * @returns {Object} {transaction.decoded, transaction.hash}
69
69
  */
70
70
  async promiseTransactionsContent(transactions) {
71
- transactions = await Promise.all(transactions.map(tx => new Promise(async (resolve, reject) => {
71
+ transactions = await Promise.all(transactions.map((tx) => new Promise(async (resolve, reject) => {
72
72
  resolve({ ...tx.decoded, hash: await tx.hash() });
73
73
  })));
74
74
  return transactions;
@@ -81,7 +81,7 @@ class Transaction extends Protocol {
81
81
  async #getNonceFallback(address) {
82
82
  let transactions = await globalThis.transactionPoolStore.values();
83
83
  transactions = await this.promiseTransactions(transactions);
84
- transactions = transactions.filter(tx => tx.decoded.from === address);
84
+ transactions = transactions.filter((tx) => tx.decoded.from === address);
85
85
  transactions = await this.promiseTransactionsContent(transactions);
86
86
  // @ts-ignore
87
87
  if (this.lastBlock?.hash && transactions.length === 0 && this.lastBlock.hash !== '0x0') {
@@ -92,11 +92,11 @@ class Transaction extends Protocol {
92
92
  // tx = await peernet.get(tx, 'transaction')
93
93
  // transactions.push(new TransactionMessage(tx))
94
94
  // }
95
- transactions = transactions.filter(tx => tx.from === address);
95
+ transactions = transactions.filter((tx) => tx.from === address);
96
96
  while (transactions.length === 0 && block.decoded.index !== 0 && block.decoded.previousHash !== '0x0') {
97
97
  block = await globalThis.blockStore.get(block.decoded.previousHash);
98
98
  block = await new BlockMessage(block);
99
- transactions = block.decoded.transactions.filter(tx => tx.from === address);
99
+ transactions = block.decoded.transactions.filter((tx) => tx.from === address);
100
100
  }
101
101
  }
102
102
  if (transactions.length === 0)
@@ -110,7 +110,7 @@ class Transaction extends Protocol {
110
110
  * @returns {Number} nonce
111
111
  */
112
112
  async getNonce(address) {
113
- if (!await globalThis.accountsStore.has(address)) {
113
+ if (!(await globalThis.accountsStore.has(address))) {
114
114
  const nonce = await this.#getNonceFallback(address);
115
115
  await globalThis.accountsStore.put(address, new TextEncoder().encode(String(nonce)));
116
116
  }
@@ -119,7 +119,7 @@ class Transaction extends Protocol {
119
119
  nonce = new TextDecoder().decode(nonce);
120
120
  let transactions = await globalThis.transactionPoolStore.values();
121
121
  transactions = await this.promiseTransactions(transactions);
122
- transactions = transactions.filter(tx => tx.decoded.from === address);
122
+ transactions = transactions.filter((tx) => tx.decoded.from === address);
123
123
  transactions = await this.promiseTransactionsContent(transactions);
124
124
  for (const transaction of transactions) {
125
125
  if (transaction.nonce > nonce)
@@ -136,7 +136,7 @@ class Transaction extends Protocol {
136
136
  throw new Error(`a transaction with the same nonce already exists`);
137
137
  let transactions = await globalThis.transactionPoolStore.values();
138
138
  transactions = await this.promiseTransactions(transactions);
139
- transactions = transactions.filter(tx => tx.decoded.from === address);
139
+ transactions = transactions.filter((tx) => tx.decoded.from === address);
140
140
  for (const transaction of transactions) {
141
141
  if (transaction.decoded.nonce > nonce)
142
142
  throw new Error(`a transaction with a higher nonce already exists`);
@@ -215,8 +215,7 @@ class Contract extends Transaction {
215
215
  constructor() {
216
216
  super();
217
217
  }
218
- async init() {
219
- }
218
+ async init() { }
220
219
  /**
221
220
  *
222
221
  * @param {Address} creator
@@ -335,7 +334,10 @@ class Machine {
335
334
  // browser env
336
335
  pre = './';
337
336
  }
338
- this.worker = await new EasyWorker(pre + 'workers/machine-worker.js', { serialization: 'advanced', type: 'module' });
337
+ this.worker = await new EasyWorker(pre + 'workers/machine-worker.js', {
338
+ serialization: 'advanced',
339
+ type: 'module'
340
+ });
339
341
  this.worker.onmessage(this.#onmessage.bind(this));
340
342
  // const blocks = await blockStore.values()
341
343
  const contracts = await Promise.all([
@@ -361,7 +363,7 @@ class Machine {
361
363
  return new Promise((resolve, reject) => {
362
364
  // @ts-ignore
363
365
  const id = randombytes(20).toString('hex');
364
- const onmessage = message => {
366
+ const onmessage = (message) => {
365
367
  pubsub.unsubscribe(id, onmessage);
366
368
  if (message?.error)
367
369
  reject(message.error);
@@ -393,7 +395,7 @@ class Machine {
393
395
  if (await this.has(parameters[0]))
394
396
  throw new Error(`duplicate contract @${parameters[0]}`);
395
397
  let message;
396
- if (!await globalThis.contractStore.has(parameters[0])) {
398
+ if (!(await globalThis.contractStore.has(parameters[0]))) {
397
399
  message = await peernet.get(parameters[0], 'contract');
398
400
  message = await new ContractMessage(message);
399
401
  await globalThis.contractStore.put(await message.hash(), message.encoded);
@@ -402,7 +404,7 @@ class Machine {
402
404
  message = await globalThis.contractStore.get(parameters[0]);
403
405
  message = await new ContractMessage(message);
404
406
  }
405
- if (!await this.has(await message.hash()))
407
+ if (!(await this.has(await message.hash())))
406
408
  await this.#runContract(message);
407
409
  }
408
410
  }
@@ -412,7 +414,7 @@ class Machine {
412
414
  return new Promise((resolve, reject) => {
413
415
  // @ts-ignore
414
416
  const id = randombytes(20).toString('hex');
415
- const onmessage = message => {
417
+ const onmessage = (message) => {
416
418
  pubsub.unsubscribe(id, onmessage);
417
419
  if (message?.error)
418
420
  reject(new ExecutionError(message.error));
@@ -434,7 +436,7 @@ class Machine {
434
436
  get(contract, method, parameters) {
435
437
  return new Promise((resolve, reject) => {
436
438
  const id = randombytes(20).toString();
437
- const onmessage = message => {
439
+ const onmessage = (message) => {
438
440
  pubsub.unsubscribe(id, onmessage);
439
441
  resolve(message);
440
442
  };
@@ -454,7 +456,7 @@ class Machine {
454
456
  return new Promise((resolve, reject) => {
455
457
  // @ts-ignore
456
458
  const id = randombytes(20).toString('hex');
457
- const onmessage = message => {
459
+ const onmessage = (message) => {
458
460
  pubsub.unsubscribe(id, onmessage);
459
461
  if (message?.error)
460
462
  reject(message.error);
@@ -480,7 +482,7 @@ class Machine {
480
482
  */
481
483
  async deleteAll() {
482
484
  let hashes = await globalThis.contractStore.keys();
483
- hashes = Object.keys(hashes).map(hash => this.delete(hash));
485
+ hashes = Object.keys(hashes).map((hash) => this.delete(hash));
484
486
  return Promise.all(hashes);
485
487
  }
486
488
  }
@@ -496,7 +498,7 @@ class Jobber {
496
498
  const timeout = setTimeout(() => {
497
499
  reject('timeout');
498
500
  }, this.timeout);
499
- this.stop = () => {
501
+ this.destroy = () => {
500
502
  clearTimeout(timeout);
501
503
  this.busy = false;
502
504
  resolve('stopped');
@@ -508,6 +510,7 @@ class Jobber {
508
510
  resolve(result);
509
511
  }
510
512
  catch (error) {
513
+ clearTimeout(timeout);
511
514
  reject(error);
512
515
  }
513
516
  });
@@ -521,6 +524,7 @@ class State extends Contract {
521
524
  #resolving;
522
525
  #resolveErrorCount;
523
526
  #syncState;
527
+ #chainState;
524
528
  #lastBlockInQue;
525
529
  #syncErrorCount;
526
530
  #blockHashMap;
@@ -530,6 +534,12 @@ class State extends Contract {
530
534
  #totalSize;
531
535
  #machine;
532
536
  #loaded;
537
+ get state() {
538
+ return {
539
+ sync: this.#syncState,
540
+ chain: this.#chainState
541
+ };
542
+ }
533
543
  get blockHashMap() {
534
544
  return this.#blockHashMap.entries();
535
545
  }
@@ -591,8 +601,10 @@ class State extends Contract {
591
601
  }
592
602
  constructor() {
593
603
  super();
604
+ this.#lastResolvedTime = 0;
594
605
  this.#resolving = false;
595
606
  this.#resolveErrorCount = 0;
607
+ this.#chainState = 'loading';
596
608
  this.#syncErrorCount = 0;
597
609
  this.#blockHashMap = new Map();
598
610
  this.#chainSyncing = false;
@@ -624,12 +636,28 @@ class State extends Contract {
624
636
  * {Number}
625
637
  */
626
638
  this.#totalTransactions = 0;
639
+ this.#chainStateHandler = () => {
640
+ return new globalThis.peernet.protos['peernet-response']({
641
+ response: this.#chainState
642
+ });
643
+ };
644
+ this.#lastBlockHandler = async () => {
645
+ return new globalThis.peernet.protos['peernet-response']({
646
+ response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index }
647
+ });
648
+ };
649
+ this.#knownBlocksHandler = async () => {
650
+ return new globalThis.peernet.protos['peernet-response']({
651
+ response: { blocks: this.#blocks.map((block) => block.hash) }
652
+ });
653
+ };
627
654
  this.#loadBlockTransactions = (transactions) => Promise.all(transactions.map((transaction) => new TransactionMessage(transaction)));
628
655
  this.#getLastTransactions = async () => {
629
- let lastTransactions = (await Promise.all(this.#blocks.filter(block => block.loaded).slice(-128)
630
- .map(block => this.#loadBlockTransactions(block.transactions))))
631
- .reduce((all, transactions) => [...all, ...transactions], []);
632
- return Promise.all(lastTransactions.map(transaction => transaction.hash()));
656
+ let lastTransactions = (await Promise.all(this.#blocks
657
+ .filter((block) => block.loaded)
658
+ .slice(-128)
659
+ .map((block) => this.#loadBlockTransactions(block.transactions)))).reduce((all, transactions) => [...all, ...transactions], []);
660
+ return Promise.all(lastTransactions.map((transaction) => transaction.hash()));
633
661
  };
634
662
  }
635
663
  async clearPool() {
@@ -644,12 +672,16 @@ class State extends Contract {
644
672
  await globalThis.blockStore.clear();
645
673
  await globalThis.transactionPoolStore.clear();
646
674
  }
675
+ #chainStateHandler;
676
+ #lastBlockHandler;
677
+ #knownBlocksHandler;
647
678
  async init() {
648
- this.jobber = new Jobber(30000);
679
+ this.jobber = new Jobber(this.resolveTimeout);
649
680
  if (super.init)
650
681
  await super.init();
651
- await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler.bind(this));
652
- await globalThis.peernet.addRequestHandler('knownBlocks', this.#knownBlocksHandler.bind(this));
682
+ await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler);
683
+ await globalThis.peernet.addRequestHandler('knownBlocks', this.#knownBlocksHandler);
684
+ await globalThis.peernet.addRequestHandler('chainState', this.#chainStateHandler);
653
685
  try {
654
686
  let localBlock;
655
687
  try {
@@ -663,7 +695,10 @@ class State extends Contract {
663
695
  if (localBlock && localBlock !== '0x0') {
664
696
  localBlock = await globalThis.peernet.get(localBlock, 'block');
665
697
  localBlock = await new BlockMessage(localBlock);
666
- this.#lastBlock = { ...localBlock.decoded, hash: await localBlock.hash() };
698
+ this.#lastBlock = {
699
+ ...localBlock.decoded,
700
+ hash: await localBlock.hash()
701
+ };
667
702
  }
668
703
  else {
669
704
  if (globalThis.peernet?.connections.length > 0) {
@@ -704,12 +739,6 @@ class State extends Contract {
704
739
  await globalThis.chainStore.put('lastBlock', hash);
705
740
  globalThis.pubsub.publish('lastBlock', this.#lastBlock);
706
741
  }
707
- async #lastBlockHandler() {
708
- return new globalThis.peernet.protos['peernet-response']({ response: { hash: this.#lastBlock?.hash, index: this.#lastBlock?.index } });
709
- }
710
- async #knownBlocksHandler() {
711
- return new globalThis.peernet.protos['peernet-response']({ response: { blocks: this.#blocks.map((block) => block.hash) } });
712
- }
713
742
  getLatestBlock() {
714
743
  // @ts-ignore
715
744
  return this.#getLatestBlock();
@@ -722,7 +751,7 @@ class State extends Contract {
722
751
  const { index } = block.decoded;
723
752
  if (this.#blocks[index - 1] && this.#blocks[index - 1].hash !== block.hash)
724
753
  throw `invalid block ${hash} @${index}`;
725
- if (!await globalThis.peernet.has(hash))
754
+ if (!(await globalThis.peernet.has(hash)))
726
755
  await globalThis.peernet.put(hash, block.encoded, 'block');
727
756
  }
728
757
  return block;
@@ -750,8 +779,6 @@ class State extends Contract {
750
779
  this.#lastResolvedTime = Date.now();
751
780
  }
752
781
  catch (error) {
753
- this.#resolving = false;
754
- this.#chainSyncing = false;
755
782
  throw new ResolveError(`block: ${hash}@${index}`);
756
783
  }
757
784
  return;
@@ -764,6 +791,8 @@ class State extends Contract {
764
791
  if (this.#resolving)
765
792
  return 'already resolving';
766
793
  this.#resolving = true;
794
+ if (this.jobber.busy && this.jobber.destroy)
795
+ await this.jobber.destroy();
767
796
  try {
768
797
  await this.jobber.add(() => this.#resolveBlock(hash));
769
798
  this.#resolving = false;
@@ -773,6 +802,7 @@ class State extends Contract {
773
802
  catch (error) {
774
803
  console.log({ error });
775
804
  this.#resolveErrorCount += 1;
805
+ this.#resolving = false;
776
806
  if (this.#resolveErrorCount < 3)
777
807
  return this.resolveBlock(hash);
778
808
  this.#resolveErrorCount = 0;
@@ -781,8 +811,8 @@ class State extends Contract {
781
811
  }
782
812
  async resolveBlocks() {
783
813
  try {
784
- if (this.jobber.busy && this.jobber.stop) {
785
- await this.jobber.stop();
814
+ if (this.jobber.busy && this.jobber.destroy) {
815
+ await this.jobber.destroy();
786
816
  }
787
817
  }
788
818
  catch (error) {
@@ -798,10 +828,10 @@ class State extends Contract {
798
828
  }
799
829
  catch (error) {
800
830
  console.log(error);
831
+ this.#chainSyncing = false;
832
+ this.#syncState = 'errored';
801
833
  this.#resolveErrored = true;
802
- this.#resolveErrorCount += 1;
803
- this.#resolving = false;
804
- this.restoreChain();
834
+ return this.restoreChain();
805
835
  // console.log(e);
806
836
  }
807
837
  }
@@ -819,23 +849,24 @@ class State extends Contract {
819
849
  this.#resolveErrored = true;
820
850
  this.#resolveErrorCount += 1;
821
851
  this.#resolving = false;
822
- this.restoreChain();
852
+ return this.restoreChain();
823
853
  // console.log(e);
824
854
  }
825
855
  }
856
+ destroyResolveJob() { }
826
857
  async syncChain(lastBlock) {
827
- if (!this.shouldSync) {
858
+ if (!this.shouldSync)
828
859
  return;
829
- }
860
+ this.#syncState;
861
+ this.#chainSyncing = true;
830
862
  try {
831
- if (this.jobber.busy && this.jobber.stop) {
832
- await this.jobber.stop();
863
+ if (this.jobber.busy && this.jobber.destroy) {
864
+ await this.jobber.destroy();
833
865
  }
834
866
  }
835
867
  catch (error) {
836
868
  console.error(error);
837
869
  }
838
- this.#chainSyncing = true;
839
870
  if (!lastBlock)
840
871
  lastBlock = await this.#getLatestBlock();
841
872
  console.log('starting sync');
@@ -850,7 +881,8 @@ class State extends Contract {
850
881
  return this.syncChain(lastBlock);
851
882
  this.#syncErrorCount = 0;
852
883
  this.#chainSyncing = false;
853
- return 'errored';
884
+ this.#syncState = 'errored';
885
+ return this.#syncState;
854
886
  }
855
887
  if (lastBlock.index === this.#lastBlockInQue?.index)
856
888
  this.#lastBlockInQue = undefined;
@@ -858,7 +890,8 @@ class State extends Contract {
858
890
  this.#chainSyncing = false;
859
891
  if (this.#lastBlockInQue)
860
892
  return this.syncChain(this.#lastBlockInQue);
861
- return 'synced';
893
+ this.#syncState = 'synced';
894
+ return this.#syncState;
862
895
  }
863
896
  async #syncChain(lastBlock) {
864
897
  try {
@@ -879,7 +912,7 @@ class State extends Contract {
879
912
  console.log('ok');
880
913
  let blocksSynced = localIndex > 0 ? (localIndex > index ? localIndex - index : index + -localIndex) : index;
881
914
  globalThis.debug(`synced ${blocksSynced} ${blocksSynced > 1 ? 'blocks' : 'block'}`);
882
- const start = (this.#blocks.length - blocksSynced);
915
+ const start = this.#blocks.length - blocksSynced;
883
916
  if (this.#machine)
884
917
  await this.#loadBlocks(this.blocks.slice(start));
885
918
  await this.updateState(new BlockMessage(this.#blocks[this.#blocks.length - 1]));
@@ -892,7 +925,9 @@ class State extends Contract {
892
925
  }
893
926
  async #getLatestBlock() {
894
927
  let promises = [];
895
- let data = await new globalThis.peernet.protos['peernet-request']({ request: 'lastBlock' });
928
+ let data = await new globalThis.peernet.protos['peernet-request']({
929
+ request: 'lastBlock'
930
+ });
896
931
  let node = await globalThis.peernet.prepareMessage(data);
897
932
  for (const peer of globalThis.peernet?.connections) {
898
933
  // @ts-ignore
@@ -924,7 +959,9 @@ class State extends Contract {
924
959
  latest = { ...message.decoded, hash };
925
960
  const peer = promises[0].peer;
926
961
  if (peer.connected && peer.version === this.version) {
927
- let data = await new globalThis.peernet.protos['peernet-request']({ request: 'knownBlocks' });
962
+ let data = await new globalThis.peernet.protos['peernet-request']({
963
+ request: 'knownBlocks'
964
+ });
928
965
  let node = await globalThis.peernet.prepareMessage(data);
929
966
  let message = await peer.request(node);
930
967
  message = await new globalThis.peernet.protos['peernet-response'](message);
@@ -940,6 +977,7 @@ class State extends Contract {
940
977
  * @param {Block[]} blocks
941
978
  */
942
979
  async #loadBlocks(blocks) {
980
+ this.#chainState = 'loading';
943
981
  let poolTransactionKeys = await globalThis.transactionPoolStore.keys();
944
982
  for (const block of blocks) {
945
983
  if (block && !block.loaded) {
@@ -992,6 +1030,7 @@ class State extends Contract {
992
1030
  globalThis.pubsub.publish('block-loaded', { ...block });
993
1031
  }
994
1032
  }
1033
+ this.#chainState = 'loaded';
995
1034
  return true;
996
1035
  }
997
1036
  promiseRequests(promises) {
@@ -1022,9 +1061,12 @@ class State extends Contract {
1022
1061
  return true;
1023
1062
  }
1024
1063
  get shouldSync() {
1025
- if (this.canSync ||
1026
- this.#resolveErrored ||
1027
- !this.canSync && this.#lastResolvedTime + this.resolveTimeout > new Date().getTime())
1064
+ if (this.#chainSyncing)
1065
+ return false;
1066
+ if (this.#resolveErrored ||
1067
+ this.#syncState === 'errored' ||
1068
+ this.#syncState === 'connectionless' ||
1069
+ (!this.canSync && this.#lastResolvedTime + this.resolveTimeout > Date.now()))
1028
1070
  return true;
1029
1071
  return false;
1030
1072
  }
@@ -1044,7 +1086,7 @@ class VersionControl extends State {
1044
1086
  super();
1045
1087
  }
1046
1088
  async init() {
1047
- super.init && await super.init();
1089
+ super.init && (await super.init());
1048
1090
  console.log('init');
1049
1091
  try {
1050
1092
  const version = await globalThis.chainStore.get('version');
@@ -1126,29 +1168,34 @@ class Chain extends VersionControl {
1126
1168
  console.error(error);
1127
1169
  }
1128
1170
  const end = Date.now();
1129
- console.log(((end - start) / 1000) + ' s');
1171
+ console.log((end - start) / 1000 + ' s');
1130
1172
  if (await this.hasTransactionToHandle())
1131
1173
  return this.#runEpoch();
1132
1174
  this.#runningEpoch = false;
1133
1175
  // if (await this.hasTransactionToHandle() && !this.#runningEpoch) return this.#runEpoch()
1134
1176
  }
1135
1177
  async #setup() {
1136
- const contracts = [{
1178
+ const contracts = [
1179
+ {
1137
1180
  address: addresses.contractFactory,
1138
1181
  message: contractFactoryMessage
1139
- }, {
1182
+ },
1183
+ {
1140
1184
  address: addresses.nativeToken,
1141
1185
  message: nativeTokenMessage
1142
- }, {
1186
+ },
1187
+ {
1143
1188
  address: addresses.validators,
1144
1189
  message: validatorsMessage
1145
- }, {
1190
+ },
1191
+ {
1146
1192
  address: addresses.nameService,
1147
1193
  message: nameServiceMessage
1148
- }];
1194
+ }
1195
+ ];
1149
1196
  await Promise.all(contracts.map(async ({ address, message }) => {
1150
1197
  // @ts-ignore
1151
- message = await new ContractMessage(Uint8Array.from(message.split(',').map(string => Number(string))));
1198
+ message = await new ContractMessage(Uint8Array.from(message.split(',').map((string) => Number(string))));
1152
1199
  // @ts-ignore
1153
1200
  await globalThis.contractStore.put(address, message.encoded);
1154
1201
  }));
@@ -1170,7 +1217,7 @@ class Chain extends VersionControl {
1170
1217
  return new BWMessage(globalThis.peernet.client.bw) || { up: 0, down: 0 };
1171
1218
  });
1172
1219
  // await globalThis.peernet.addRequestHandler('peerId', () => {
1173
- // let node =
1220
+ // let node =
1174
1221
  // globalThis.peernet.protos['peernet-response']({response: node.encoded})
1175
1222
  // })
1176
1223
  await globalThis.peernet.addRequestHandler('transactionPool', this.#transactionPoolHandler.bind(this));
@@ -1207,31 +1254,36 @@ class Chain extends VersionControl {
1207
1254
  response = await new globalThis.peernet.protos['peernet-response'](new Uint8Array(Object.values(response)));
1208
1255
  return response.decoded.response;
1209
1256
  }
1257
+ async getPeerTransactionPool(peer) {
1258
+ const transactionsInPool = await this.#makeRequest(peer, 'transactionPool');
1259
+ // todo iterate vs getting all keys?
1260
+ const transactions = await globalThis.transactionPoolStore.keys();
1261
+ const transactionsToGet = [];
1262
+ for (const key of transactionsInPool) {
1263
+ !transactions.includes(key) &&
1264
+ !ignorelist.includes(key) &&
1265
+ transactionsToGet.push(transactionPoolStore.put(key, await peernet.get(key, 'transaction')));
1266
+ }
1267
+ return Promise.all(transactionsToGet);
1268
+ }
1210
1269
  async #peerConnected(peer) {
1211
1270
  // todo handle version changes
1212
1271
  // for now just do nothing if version doesn't match
1213
1272
  if (!peer.version || peer.version !== this.version)
1214
1273
  return;
1215
1274
  const lastBlock = await this.#makeRequest(peer, 'lastBlock');
1216
- let transactionsInPool = await this.#makeRequest(peer, 'transactionPool');
1217
- const transactions = await globalThis.transactionPoolStore.keys();
1218
- const transactionsToGet = [];
1219
- for (const key of transactionsInPool) {
1220
- if (!transactions.includes(key) && !ignorelist.includes(key))
1221
- transactionsToGet.push(transactionPoolStore.put(key, (await peernet.get(key, 'transaction'))));
1222
- }
1223
- await Promise.all(transactionsToGet);
1275
+ const higherThenCurrentLocal = lastBlock.index > this.lastBlock?.index;
1276
+ const peerTransactionPool = (higherThenCurrentLocal && (await this.getPeerTransactionPool(peer))) || [];
1224
1277
  if (Object.keys(lastBlock).length > 0) {
1225
- if (!this.lastBlock || !this.blocks[this.blocks.length - 1]?.loaded || lastBlock && lastBlock.index > this.lastBlock?.index || !this.loaded && !this.resolving) {
1278
+ if (!this.lastBlock || higherThenCurrentLocal) {
1226
1279
  this.knownBlocks = await this.#makeRequest(peer, 'knownBlocks');
1227
1280
  await this.syncChain(lastBlock);
1228
- // if (await this.hasTransactionToHandle() && this.#participating) this.#runEpoch()
1229
1281
  }
1230
1282
  else if (!this.knownBlocks)
1231
1283
  this.knownBlocks = await this.#makeRequest(peer, 'knownBlocks');
1232
1284
  }
1233
- if (this.#participating)
1234
- this.#runEpoch();
1285
+ if (this.#participating && peerTransactionPool.length > 0)
1286
+ return this.#runEpoch();
1235
1287
  }
1236
1288
  #epochTimeout;
1237
1289
  async #transactionPoolHandler() {
@@ -1310,7 +1362,7 @@ class Chain extends VersionControl {
1310
1362
  // peerReputation(peerId)
1311
1363
  // {bandwith: {up, down}, uptime}
1312
1364
  this.#participating = true;
1313
- if (!await this.staticCall(addresses.validators, 'has', [address])) {
1365
+ if (!(await this.staticCall(addresses.validators, 'has', [address]))) {
1314
1366
  const rawTransaction = {
1315
1367
  from: address,
1316
1368
  to: addresses.validators,
@@ -1322,13 +1374,13 @@ class Chain extends VersionControl {
1322
1374
  const transaction = await signTransaction(rawTransaction, globalThis.peernet.identity);
1323
1375
  await this.sendTransaction(transaction);
1324
1376
  }
1325
- if (await this.hasTransactionToHandle() && !this.#runningEpoch && this.#participating)
1377
+ if ((await this.hasTransactionToHandle()) && !this.#runningEpoch && this.#participating)
1326
1378
  await this.#runEpoch();
1327
1379
  }
1328
1380
  // todo filter tx that need to wait on prev nonce
1329
1381
  async #createBlock(limit = this.transactionLimit) {
1330
1382
  // vote for transactions
1331
- if (await globalThis.transactionPoolStore.size() === 0)
1383
+ if ((await globalThis.transactionPoolStore.size()) === 0)
1332
1384
  return;
1333
1385
  let transactions = await globalThis.transactionPoolStore.values(this.transactionLimit);
1334
1386
  for (const hash of await globalThis.transactionPoolStore.keys()) {
@@ -1421,7 +1473,7 @@ class Chain extends VersionControl {
1421
1473
  }
1422
1474
  }
1423
1475
  }
1424
- block.validators = block.validators.map(validator => {
1476
+ block.validators = block.validators.map((validator) => {
1425
1477
  validator.reward = block.fees;
1426
1478
  validator.reward = validator.reward.add(block.reward);
1427
1479
  validator.reward = validator.reward.div(block.validators.length);
@@ -1439,8 +1491,7 @@ class Chain extends VersionControl {
1439
1491
  // block.reward = block.reward.toString()
1440
1492
  // block.fees = block.fees.toString()
1441
1493
  try {
1442
- block.transactions = await Promise.all(block.transactions
1443
- .map(async (transaction) => {
1494
+ block.transactions = await Promise.all(block.transactions.map(async (transaction) => {
1444
1495
  await globalThis.transactionPoolStore.delete(await transaction.hash());
1445
1496
  return transaction.decoded;
1446
1497
  }));
@@ -1,4 +1,4 @@
1
- import Transaction from "./transaction.js";
1
+ import Transaction from './transaction.js';
2
2
  import type MultiWallet from '@leofcoin/multi-wallet';
3
3
  /**
4
4
  * @extends {Transaction}
@@ -1,7 +1,7 @@
1
1
  export default class Jobber {
2
2
  timeout: EpochTimeStamp;
3
3
  busy: boolean;
4
- stop: Function;
4
+ destroy: Function;
5
5
  constructor(timeout: any);
6
6
  add(fn: any): Promise<unknown>;
7
7
  }
package/exports/node.js CHANGED
@@ -16,7 +16,9 @@ class Node {
16
16
  stars: networks.leofcoin.peach.stars,
17
17
  autoStart: false
18
18
  }, password) {
19
- this.#node = globalThis.Peernet ? await new globalThis.Peernet(config, password) : await new Peernet(config, password);
19
+ this.#node = globalThis.Peernet
20
+ ? await new globalThis.Peernet(config, password)
21
+ : await new Peernet(config, password);
20
22
  await nodeConfig(config);
21
23
  globalThis.pubsub.subscribe('chain:ready', async () => {
22
24
  // when autostart is false the node will only be started after the chain is ready (this is here so we can just use node for communication)
@@ -4,10 +4,15 @@ import Machine from './machine.js';
4
4
  import Jobber from './jobs/jobber.js';
5
5
  import { BlockHash } from './types.js';
6
6
  declare type SyncState = 'syncing' | 'synced' | 'errored' | 'connectionless';
7
+ declare type ChainState = 'loading' | 'loaded';
7
8
  export default class State extends Contract {
8
9
  #private;
9
10
  knownBlocks: BlockHash[];
10
11
  jobber: Jobber;
12
+ get state(): {
13
+ sync: SyncState;
14
+ chain: ChainState;
15
+ };
11
16
  get blockHashMap(): IterableIterator<[any, any]>;
12
17
  get loaded(): boolean;
13
18
  get resolving(): boolean;
@@ -35,8 +40,9 @@ export default class State extends Contract {
35
40
  getLatestBlock(): Promise<BlockMessage['decoded']>;
36
41
  getAndPutBlock(hash: string): Promise<BlockMessage>;
37
42
  resolveBlock(hash: any): any;
38
- resolveBlocks(): Promise<void>;
39
- restoreChain(): Promise<void>;
43
+ resolveBlocks(): Promise<any>;
44
+ restoreChain(): any;
45
+ destroyResolveJob(): void;
40
46
  syncChain(lastBlock?: any): Promise<SyncState>;
41
47
  promiseRequests(promises: any): Promise<unknown>;
42
48
  get canSync(): boolean;