@leofcoin/chain 1.4.75 → 1.4.77

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.
@@ -1818,7 +1818,33 @@ class Machine {
1818
1818
  }
1819
1819
  }
1820
1820
 
1821
- const queue = new PQueue({ concurrency: 1, throwOnTimeout: true });
1821
+ class Jobber {
1822
+ timeout;
1823
+ busy = false;
1824
+ stop;
1825
+ constructor(timeout) {
1826
+ this.timeout = timeout;
1827
+ }
1828
+ add(fn) {
1829
+ this.busy = true;
1830
+ return new Promise(async (resolve, reject) => {
1831
+ const timeout = setTimeout(() => {
1832
+ reject('timeout');
1833
+ }, this.timeout);
1834
+ this.stop = () => {
1835
+ clearTimeout(timeout);
1836
+ this.busy = false;
1837
+ resolve('stopped');
1838
+ };
1839
+ const result = await fn();
1840
+ clearTimeout(timeout);
1841
+ this.busy = false;
1842
+ resolve(result);
1843
+ });
1844
+ }
1845
+ }
1846
+
1847
+ new PQueue({ concurrency: 1, throwOnTimeout: true });
1822
1848
  class State extends Contract {
1823
1849
  #resolveErrored;
1824
1850
  #lastResolvedTime;
@@ -1832,9 +1858,16 @@ class State extends Contract {
1832
1858
  #chainSyncing = false;
1833
1859
  #lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
1834
1860
  #blocks = [];
1835
- #knownBlocks = [];
1861
+ knownBlocks = [];
1836
1862
  #totalSize = 0;
1837
1863
  #machine;
1864
+ #loaded = false;
1865
+ get loaded() {
1866
+ return this.#loaded;
1867
+ }
1868
+ get resolving() {
1869
+ return this.#resolving;
1870
+ }
1838
1871
  /**
1839
1872
  * amount the native token has been iteracted with
1840
1873
  */
@@ -1889,6 +1922,7 @@ class State extends Contract {
1889
1922
  super();
1890
1923
  }
1891
1924
  async init() {
1925
+ this.jobber = new Jobber(30_000);
1892
1926
  if (super.init)
1893
1927
  await super.init();
1894
1928
  await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler.bind(this));
@@ -1961,18 +1995,28 @@ class State extends Contract {
1961
1995
  return;
1962
1996
  }
1963
1997
  }
1964
- const block = await this.getAndPutBlock(hash);
1965
- index = block.decoded.index;
1966
- const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
1967
- this.#totalSize += size;
1968
- this.#blocks[index] = { hash, ...block.decoded };
1969
- this.#blockHashMap.set(hash, index);
1970
- globalThis.debug(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
1971
- this.#lastResolved = this.#blocks[index];
1972
- this.#lastResolvedTime = Date.now();
1998
+ try {
1999
+ const block = await this.getAndPutBlock(hash);
2000
+ index = block.decoded.index;
2001
+ const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
2002
+ this.#totalSize += size;
2003
+ this.#blocks[index] = { hash, ...block.decoded };
2004
+ this.#blockHashMap.set(hash, index);
2005
+ globalThis.debug(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
2006
+ globalThis.pubsub.publish('block-resolved', { hash, index });
2007
+ this.#lastResolved = this.#blocks[index];
2008
+ this.#lastResolvedTime = Date.now();
2009
+ }
2010
+ catch (error) {
2011
+ this.#resolving = false;
2012
+ this.#chainSyncing = false;
2013
+ throw new Error('resolve error');
2014
+ }
1973
2015
  return;
1974
2016
  }
1975
2017
  async resolveBlock(hash) {
2018
+ if (this.#resolveErrorCount === 3)
2019
+ this.#resolveErrorCount = 0;
1976
2020
  if (!hash)
1977
2021
  throw new Error(`expected hash, got: ${hash}`);
1978
2022
  if (hash === '0x0')
@@ -1980,19 +2024,36 @@ class State extends Contract {
1980
2024
  if (this.#resolving)
1981
2025
  return 'already resolving';
1982
2026
  this.#resolving = true;
1983
- await queue.add(() => this.#resolveBlock(hash));
1984
- this.#resolving = false;
1985
- if (!this.#blockHashMap.has(this.#lastResolved.previousHash) && this.#lastResolved.previousHash !== '0x0')
1986
- return this.resolveBlock(this.#lastResolved.previousHash);
1987
- return;
2027
+ try {
2028
+ await this.jobber.add(() => this.#resolveBlock(hash));
2029
+ this.#resolving = false;
2030
+ if (!this.#blockHashMap.has(this.#lastResolved.previousHash) && this.#lastResolved.previousHash !== '0x0')
2031
+ return this.resolveBlock(this.#lastResolved.previousHash);
2032
+ }
2033
+ catch (error) {
2034
+ this.#resolveErrorCount += 1;
2035
+ if (this.#resolveErrorCount < 3)
2036
+ return this.resolveBlock(hash);
2037
+ else
2038
+ throw new Error('resolve errored');
2039
+ }
1988
2040
  }
1989
2041
  async resolveBlocks() {
2042
+ try {
2043
+ if (this.jobber.busy && this.jobber.stop) {
2044
+ await this.jobber.stop();
2045
+ }
2046
+ }
2047
+ catch (error) {
2048
+ console.error(error);
2049
+ }
1990
2050
  try {
1991
2051
  const localBlock = await globalThis.chainStore.get('lastBlock');
1992
2052
  const hash = new TextDecoder().decode(localBlock);
1993
- if (hash && hash !== '0x0')
2053
+ if (hash && hash !== '0x0') {
1994
2054
  await this.resolveBlock(hash);
1995
- this.#lastBlock = this.#blocks[this.#blocks.length - 1];
2055
+ this.#lastBlock = this.#blocks[this.#blocks.length - 1];
2056
+ }
1996
2057
  }
1997
2058
  catch {
1998
2059
  this.#resolveErrored = true;
@@ -2005,7 +2066,15 @@ class State extends Contract {
2005
2066
  if (!this.shouldSync) {
2006
2067
  return;
2007
2068
  }
2008
- await queue.clear();
2069
+ try {
2070
+ if (this.jobber.busy && this.jobber.stop) {
2071
+ await this.jobber.stop();
2072
+ }
2073
+ }
2074
+ catch (error) {
2075
+ console.error(error);
2076
+ }
2077
+ // await queue.clear()
2009
2078
  this.#chainSyncing = true;
2010
2079
  if (!lastBlock)
2011
2080
  lastBlock = await this.#getLatestBlock();
@@ -2033,9 +2102,9 @@ class State extends Contract {
2033
2102
  }
2034
2103
  async #syncChain(lastBlock) {
2035
2104
  try {
2036
- if (this.#knownBlocks?.length === Number(lastBlock.index) + 1) {
2105
+ if (this.knownBlocks?.length === Number(lastBlock.index) + 1) {
2037
2106
  let promises = [];
2038
- promises = await Promise.allSettled(this.#knownBlocks.map(async (address) => {
2107
+ promises = await Promise.allSettled(this.knownBlocks.map(async (address) => {
2039
2108
  const has = await globalThis.peernet.has(address, 'block');
2040
2109
  return { has, address };
2041
2110
  }));
@@ -2067,15 +2136,16 @@ class State extends Contract {
2067
2136
  let node = await globalThis.peernet.prepareMessage(data);
2068
2137
  for (const peer of globalThis.peernet?.connections) {
2069
2138
  if (peer.connected && peer.version === this.version) {
2070
- promises.push(async () => {
2139
+ const task = async () => {
2071
2140
  try {
2072
2141
  const result = await peer.request(node.encoded);
2073
- return { result, peer };
2142
+ return { result: Uint8Array.from(Object.values(result)), peer };
2074
2143
  }
2075
2144
  catch (error) {
2076
2145
  throw error;
2077
2146
  }
2078
- });
2147
+ };
2148
+ promises.push(task());
2079
2149
  }
2080
2150
  }
2081
2151
  promises = await this.promiseRequests(promises);
@@ -2096,7 +2166,7 @@ class State extends Contract {
2096
2166
  let node = await globalThis.peernet.prepareMessage(data);
2097
2167
  let message = await peer.request(node);
2098
2168
  message = await new globalThis.peernet.protos['peernet-response'](message);
2099
- this.#knownBlocks = message.decoded.response;
2169
+ this.knownBlocks = message.decoded.response;
2100
2170
  }
2101
2171
  }
2102
2172
  return latest;
@@ -2109,6 +2179,8 @@ class State extends Contract {
2109
2179
  let poolTransactionKeys = await globalThis.transactionPoolStore.keys();
2110
2180
  for (const block of blocks) {
2111
2181
  if (block && !block.loaded) {
2182
+ if (block.index === 0)
2183
+ this.#loaded = true;
2112
2184
  for (const transaction of block.transactions) {
2113
2185
  if (poolTransactionKeys.includes(transaction.hash))
2114
2186
  await globalThis.transactionPoolStore.delete(transaction.hash);
@@ -2132,6 +2204,7 @@ class State extends Contract {
2132
2204
  }
2133
2205
  this.#blocks[block.index].loaded = true;
2134
2206
  globalThis.debug(`loaded block: ${block.hash} @${block.index}`);
2207
+ globalThis.pubsub.publish('block-loaded', { ...block });
2135
2208
  }
2136
2209
  }
2137
2210
  return true;
@@ -2147,7 +2220,8 @@ class State extends Contract {
2147
2220
  clearTimeout(timeout);
2148
2221
  if (promises.length > 0) {
2149
2222
  promises = promises.map(async ({ value }) => {
2150
- const node = await new globalThis.peernet.protos['peernet-response'](value);
2223
+ console.log(value);
2224
+ const node = await new globalThis.peernet.protos['peernet-response'](value.result);
2151
2225
  return { value: node.decoded.response, peer: value.peer };
2152
2226
  });
2153
2227
  promises = await Promise.all(promises);
@@ -2325,8 +2399,8 @@ class Chain extends State {
2325
2399
  return;
2326
2400
  const lastBlock = await this.#makeRequest(peer, 'lastBlock');
2327
2401
  if (Object.keys(lastBlock).length > 0) {
2328
- if (!this.lastBlock || !this.blocks[this.blocks.length - 1].loaded || lastBlock && lastBlock.index > this.lastBlock?.index) {
2329
- // this.#knownBlocks = await this.#makeRequest(peer, 'knownBlocks')
2402
+ if (!this.lastBlock || !this.blocks[this.blocks.length - 1]?.loaded || lastBlock && lastBlock.index > this.lastBlock?.index || !this.loaded && !this.resolving) {
2403
+ this.knownBlocks = await this.#makeRequest(peer, 'knownBlocks');
2330
2404
  await this.syncChain(lastBlock);
2331
2405
  // if (await this.hasTransactionToHandle() && this.#participating) this.#runEpoch()
2332
2406
  }
package/exports/chain.js CHANGED
@@ -444,7 +444,33 @@ class Machine {
444
444
  }
445
445
  }
446
446
 
447
- const queue = new PQueue({ concurrency: 1, throwOnTimeout: true });
447
+ class Jobber {
448
+ timeout;
449
+ busy = false;
450
+ stop;
451
+ constructor(timeout) {
452
+ this.timeout = timeout;
453
+ }
454
+ add(fn) {
455
+ this.busy = true;
456
+ return new Promise(async (resolve, reject) => {
457
+ const timeout = setTimeout(() => {
458
+ reject('timeout');
459
+ }, this.timeout);
460
+ this.stop = () => {
461
+ clearTimeout(timeout);
462
+ this.busy = false;
463
+ resolve('stopped');
464
+ };
465
+ const result = await fn();
466
+ clearTimeout(timeout);
467
+ this.busy = false;
468
+ resolve(result);
469
+ });
470
+ }
471
+ }
472
+
473
+ new PQueue({ concurrency: 1, throwOnTimeout: true });
448
474
  class State extends Contract {
449
475
  #resolveErrored;
450
476
  #lastResolvedTime;
@@ -458,9 +484,16 @@ class State extends Contract {
458
484
  #chainSyncing = false;
459
485
  #lastBlock = { index: 0, hash: '0x0', previousHash: '0x0' };
460
486
  #blocks = [];
461
- #knownBlocks = [];
487
+ knownBlocks = [];
462
488
  #totalSize = 0;
463
489
  #machine;
490
+ #loaded = false;
491
+ get loaded() {
492
+ return this.#loaded;
493
+ }
494
+ get resolving() {
495
+ return this.#resolving;
496
+ }
464
497
  /**
465
498
  * amount the native token has been iteracted with
466
499
  */
@@ -515,6 +548,7 @@ class State extends Contract {
515
548
  super();
516
549
  }
517
550
  async init() {
551
+ this.jobber = new Jobber(30_000);
518
552
  if (super.init)
519
553
  await super.init();
520
554
  await globalThis.peernet.addRequestHandler('lastBlock', this.#lastBlockHandler.bind(this));
@@ -587,18 +621,28 @@ class State extends Contract {
587
621
  return;
588
622
  }
589
623
  }
590
- const block = await this.getAndPutBlock(hash);
591
- index = block.decoded.index;
592
- const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
593
- this.#totalSize += size;
594
- this.#blocks[index] = { hash, ...block.decoded };
595
- this.#blockHashMap.set(hash, index);
596
- globalThis.debug(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
597
- this.#lastResolved = this.#blocks[index];
598
- this.#lastResolvedTime = Date.now();
624
+ try {
625
+ const block = await this.getAndPutBlock(hash);
626
+ index = block.decoded.index;
627
+ const size = block.encoded.length > 0 ? block.encoded.length : block.encoded.byteLength;
628
+ this.#totalSize += size;
629
+ this.#blocks[index] = { hash, ...block.decoded };
630
+ this.#blockHashMap.set(hash, index);
631
+ globalThis.debug(`resolved block: ${hash} @${index} ${formatBytes(size)}`);
632
+ globalThis.pubsub.publish('block-resolved', { hash, index });
633
+ this.#lastResolved = this.#blocks[index];
634
+ this.#lastResolvedTime = Date.now();
635
+ }
636
+ catch (error) {
637
+ this.#resolving = false;
638
+ this.#chainSyncing = false;
639
+ throw new Error('resolve error');
640
+ }
599
641
  return;
600
642
  }
601
643
  async resolveBlock(hash) {
644
+ if (this.#resolveErrorCount === 3)
645
+ this.#resolveErrorCount = 0;
602
646
  if (!hash)
603
647
  throw new Error(`expected hash, got: ${hash}`);
604
648
  if (hash === '0x0')
@@ -606,19 +650,36 @@ class State extends Contract {
606
650
  if (this.#resolving)
607
651
  return 'already resolving';
608
652
  this.#resolving = true;
609
- await queue.add(() => this.#resolveBlock(hash));
610
- this.#resolving = false;
611
- if (!this.#blockHashMap.has(this.#lastResolved.previousHash) && this.#lastResolved.previousHash !== '0x0')
612
- return this.resolveBlock(this.#lastResolved.previousHash);
613
- return;
653
+ try {
654
+ await this.jobber.add(() => this.#resolveBlock(hash));
655
+ this.#resolving = false;
656
+ if (!this.#blockHashMap.has(this.#lastResolved.previousHash) && this.#lastResolved.previousHash !== '0x0')
657
+ return this.resolveBlock(this.#lastResolved.previousHash);
658
+ }
659
+ catch (error) {
660
+ this.#resolveErrorCount += 1;
661
+ if (this.#resolveErrorCount < 3)
662
+ return this.resolveBlock(hash);
663
+ else
664
+ throw new Error('resolve errored');
665
+ }
614
666
  }
615
667
  async resolveBlocks() {
668
+ try {
669
+ if (this.jobber.busy && this.jobber.stop) {
670
+ await this.jobber.stop();
671
+ }
672
+ }
673
+ catch (error) {
674
+ console.error(error);
675
+ }
616
676
  try {
617
677
  const localBlock = await globalThis.chainStore.get('lastBlock');
618
678
  const hash = new TextDecoder().decode(localBlock);
619
- if (hash && hash !== '0x0')
679
+ if (hash && hash !== '0x0') {
620
680
  await this.resolveBlock(hash);
621
- this.#lastBlock = this.#blocks[this.#blocks.length - 1];
681
+ this.#lastBlock = this.#blocks[this.#blocks.length - 1];
682
+ }
622
683
  }
623
684
  catch {
624
685
  this.#resolveErrored = true;
@@ -631,7 +692,15 @@ class State extends Contract {
631
692
  if (!this.shouldSync) {
632
693
  return;
633
694
  }
634
- await queue.clear();
695
+ try {
696
+ if (this.jobber.busy && this.jobber.stop) {
697
+ await this.jobber.stop();
698
+ }
699
+ }
700
+ catch (error) {
701
+ console.error(error);
702
+ }
703
+ // await queue.clear()
635
704
  this.#chainSyncing = true;
636
705
  if (!lastBlock)
637
706
  lastBlock = await this.#getLatestBlock();
@@ -659,9 +728,9 @@ class State extends Contract {
659
728
  }
660
729
  async #syncChain(lastBlock) {
661
730
  try {
662
- if (this.#knownBlocks?.length === Number(lastBlock.index) + 1) {
731
+ if (this.knownBlocks?.length === Number(lastBlock.index) + 1) {
663
732
  let promises = [];
664
- promises = await Promise.allSettled(this.#knownBlocks.map(async (address) => {
733
+ promises = await Promise.allSettled(this.knownBlocks.map(async (address) => {
665
734
  const has = await globalThis.peernet.has(address, 'block');
666
735
  return { has, address };
667
736
  }));
@@ -693,15 +762,16 @@ class State extends Contract {
693
762
  let node = await globalThis.peernet.prepareMessage(data);
694
763
  for (const peer of globalThis.peernet?.connections) {
695
764
  if (peer.connected && peer.version === this.version) {
696
- promises.push(async () => {
765
+ const task = async () => {
697
766
  try {
698
767
  const result = await peer.request(node.encoded);
699
- return { result, peer };
768
+ return { result: Uint8Array.from(Object.values(result)), peer };
700
769
  }
701
770
  catch (error) {
702
771
  throw error;
703
772
  }
704
- });
773
+ };
774
+ promises.push(task());
705
775
  }
706
776
  }
707
777
  promises = await this.promiseRequests(promises);
@@ -722,7 +792,7 @@ class State extends Contract {
722
792
  let node = await globalThis.peernet.prepareMessage(data);
723
793
  let message = await peer.request(node);
724
794
  message = await new globalThis.peernet.protos['peernet-response'](message);
725
- this.#knownBlocks = message.decoded.response;
795
+ this.knownBlocks = message.decoded.response;
726
796
  }
727
797
  }
728
798
  return latest;
@@ -735,6 +805,8 @@ class State extends Contract {
735
805
  let poolTransactionKeys = await globalThis.transactionPoolStore.keys();
736
806
  for (const block of blocks) {
737
807
  if (block && !block.loaded) {
808
+ if (block.index === 0)
809
+ this.#loaded = true;
738
810
  for (const transaction of block.transactions) {
739
811
  if (poolTransactionKeys.includes(transaction.hash))
740
812
  await globalThis.transactionPoolStore.delete(transaction.hash);
@@ -758,6 +830,7 @@ class State extends Contract {
758
830
  }
759
831
  this.#blocks[block.index].loaded = true;
760
832
  globalThis.debug(`loaded block: ${block.hash} @${block.index}`);
833
+ globalThis.pubsub.publish('block-loaded', { ...block });
761
834
  }
762
835
  }
763
836
  return true;
@@ -773,7 +846,8 @@ class State extends Contract {
773
846
  clearTimeout(timeout);
774
847
  if (promises.length > 0) {
775
848
  promises = promises.map(async ({ value }) => {
776
- const node = await new globalThis.peernet.protos['peernet-response'](value);
849
+ console.log(value);
850
+ const node = await new globalThis.peernet.protos['peernet-response'](value.result);
777
851
  return { value: node.decoded.response, peer: value.peer };
778
852
  });
779
853
  promises = await Promise.all(promises);
@@ -951,8 +1025,8 @@ class Chain extends State {
951
1025
  return;
952
1026
  const lastBlock = await this.#makeRequest(peer, 'lastBlock');
953
1027
  if (Object.keys(lastBlock).length > 0) {
954
- if (!this.lastBlock || !this.blocks[this.blocks.length - 1].loaded || lastBlock && lastBlock.index > this.lastBlock?.index) {
955
- // this.#knownBlocks = await this.#makeRequest(peer, 'knownBlocks')
1028
+ if (!this.lastBlock || !this.blocks[this.blocks.length - 1]?.loaded || lastBlock && lastBlock.index > this.lastBlock?.index || !this.loaded && !this.resolving) {
1029
+ this.knownBlocks = await this.#makeRequest(peer, 'knownBlocks');
956
1030
  await this.syncChain(lastBlock);
957
1031
  // if (await this.hasTransactionToHandle() && this.#participating) this.#runEpoch()
958
1032
  }
@@ -0,0 +1,7 @@
1
+ export default class Jobber {
2
+ timeout: EpochTimeStamp;
3
+ busy: boolean;
4
+ stop: Function;
5
+ constructor(timeout: any);
6
+ add(fn: any): Promise<unknown>;
7
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leofcoin/chain",
3
- "version": "1.4.75",
3
+ "version": "1.4.77",
4
4
  "description": "Official javascript implementation",
5
5
  "exports": {
6
6
  "./node": "./exports/node.js",
@@ -1,3 +0,0 @@
1
- export default class SyncJob {
2
- constructor();
3
- }