@dedot/api 0.9.2 → 0.9.4

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.
@@ -410,7 +410,7 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
410
410
  }
411
411
  catch (e) {
412
412
  if (e instanceof error_js_1.ChainHeadError && e.retryStrategy) {
413
- return this.#retryOperation(e.retryStrategy, operation);
413
+ return await this.#retryOperation(e.retryStrategy, operation);
414
414
  }
415
415
  throw e;
416
416
  }
@@ -437,7 +437,7 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
437
437
  catch (e) {
438
438
  // retry again until success, TODO we might need to limit the number of retries
439
439
  if (e instanceof error_js_1.ChainHeadError && e.retryStrategy) {
440
- return this.#retryOperation(e.retryStrategy, retry);
440
+ return await this.#retryOperation(e.retryStrategy, retry);
441
441
  }
442
442
  throw e;
443
443
  }
@@ -550,19 +550,33 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
550
550
  return this.#cache.get(cacheKey);
551
551
  }
552
552
  this.#blockUsage.use(hash);
553
- const results = [];
554
- let queryItems = items;
555
- while (queryItems.length > 0) {
556
- const [newBatch, newDiscardedItems] = await this.#getStorage(queryItems, childTrie ?? null, hash);
557
- results.push(...newBatch);
558
- queryItems = newDiscardedItems;
553
+ let results = [];
554
+ // @ts-ignore a trick internally to check whether a provider is using smoldot connection
555
+ const isSmoldot = typeof this.client.provider['chain'] === 'function';
556
+ if (isSmoldot) {
557
+ const fetchItem = async (item) => {
558
+ const [batch, newDiscardedItems] = await this.#getStorage([item], childTrie ?? null, hash);
559
+ if (newDiscardedItems.length > 0) {
560
+ return fetchItem(item);
561
+ }
562
+ return batch;
563
+ };
564
+ results = (await Promise.all(items.map((one) => fetchItem(one)))).flat();
565
+ }
566
+ else {
567
+ let queryItems = items;
568
+ while (queryItems.length > 0) {
569
+ const [newBatch, newDiscardedItems] = await this.#getStorage(queryItems, childTrie ?? null, hash);
570
+ results.push(...newBatch);
571
+ queryItems = newDiscardedItems;
572
+ }
559
573
  }
560
574
  this.#cache.set(cacheKey, results);
561
575
  return results;
562
576
  }
563
577
  catch (e) {
564
578
  if (e instanceof error_js_1.ChainHeadBlockPrunedError && shouldRetryOnPrunedBlock) {
565
- return this.storage(items, childTrie);
579
+ return await this.storage(items, childTrie);
566
580
  }
567
581
  throw e;
568
582
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NewStorageQuery = void 0;
4
+ const utils_1 = require("@dedot/utils");
4
5
  const BaseStorageQuery_js_1 = require("./BaseStorageQuery.js");
5
6
  /**
6
7
  * @name NewStorageQuery
@@ -51,6 +52,11 @@ class NewStorageQuery extends BaseStorageQuery_js_1.BaseStorageQuery {
51
52
  const best = await this.client.chainHead.bestBlock();
52
53
  // Track the latest changes for each key
53
54
  const latestChanges = {};
55
+ // Using a queue here to make sure we don't accidentally
56
+ // put a pressure the json-rpc server in-case new blocks stack up too fast
57
+ // in case we send a lot of requests at the same time
58
+ // or the block time is small enough with elastic scaling
59
+ const pullQueue = new utils_1.AsyncQueue();
54
60
  // Function to pull storage values and call the callback if there are changes
55
61
  const pull = async ({ hash }) => {
56
62
  // Query storage using ChainHead API
@@ -76,9 +82,12 @@ class NewStorageQuery extends BaseStorageQuery_js_1.BaseStorageQuery {
76
82
  // Initial pull
77
83
  await pull(best);
78
84
  // Subscribe to best block events
79
- const unsub = this.client.on('bestBlock', pull);
85
+ const unsub = this.client.on('bestBlock', (block) => {
86
+ pullQueue.enqueue(() => pull(block)).catch(console.error);
87
+ });
80
88
  return async () => {
81
89
  unsub();
90
+ pullQueue.cancel();
82
91
  };
83
92
  }
84
93
  }
@@ -407,7 +407,7 @@ export class ChainHead extends JsonRpcGroup {
407
407
  }
408
408
  catch (e) {
409
409
  if (e instanceof ChainHeadError && e.retryStrategy) {
410
- return this.#retryOperation(e.retryStrategy, operation);
410
+ return await this.#retryOperation(e.retryStrategy, operation);
411
411
  }
412
412
  throw e;
413
413
  }
@@ -434,7 +434,7 @@ export class ChainHead extends JsonRpcGroup {
434
434
  catch (e) {
435
435
  // retry again until success, TODO we might need to limit the number of retries
436
436
  if (e instanceof ChainHeadError && e.retryStrategy) {
437
- return this.#retryOperation(e.retryStrategy, retry);
437
+ return await this.#retryOperation(e.retryStrategy, retry);
438
438
  }
439
439
  throw e;
440
440
  }
@@ -547,19 +547,33 @@ export class ChainHead extends JsonRpcGroup {
547
547
  return this.#cache.get(cacheKey);
548
548
  }
549
549
  this.#blockUsage.use(hash);
550
- const results = [];
551
- let queryItems = items;
552
- while (queryItems.length > 0) {
553
- const [newBatch, newDiscardedItems] = await this.#getStorage(queryItems, childTrie ?? null, hash);
554
- results.push(...newBatch);
555
- queryItems = newDiscardedItems;
550
+ let results = [];
551
+ // @ts-ignore a trick internally to check whether a provider is using smoldot connection
552
+ const isSmoldot = typeof this.client.provider['chain'] === 'function';
553
+ if (isSmoldot) {
554
+ const fetchItem = async (item) => {
555
+ const [batch, newDiscardedItems] = await this.#getStorage([item], childTrie ?? null, hash);
556
+ if (newDiscardedItems.length > 0) {
557
+ return fetchItem(item);
558
+ }
559
+ return batch;
560
+ };
561
+ results = (await Promise.all(items.map((one) => fetchItem(one)))).flat();
562
+ }
563
+ else {
564
+ let queryItems = items;
565
+ while (queryItems.length > 0) {
566
+ const [newBatch, newDiscardedItems] = await this.#getStorage(queryItems, childTrie ?? null, hash);
567
+ results.push(...newBatch);
568
+ queryItems = newDiscardedItems;
569
+ }
556
570
  }
557
571
  this.#cache.set(cacheKey, results);
558
572
  return results;
559
573
  }
560
574
  catch (e) {
561
575
  if (e instanceof ChainHeadBlockPrunedError && shouldRetryOnPrunedBlock) {
562
- return this.storage(items, childTrie);
576
+ return await this.storage(items, childTrie);
563
577
  }
564
578
  throw e;
565
579
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dedot/api",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "description": "A delightful JavaScript/TypeScript client for Polkadot & Substrate",
5
5
  "author": "Thang X. Vu <thang@dedot.dev>",
6
6
  "homepage": "https://dedot.dev",
@@ -13,13 +13,13 @@
13
13
  "type": "module",
14
14
  "sideEffects": false,
15
15
  "dependencies": {
16
- "@dedot/codecs": "0.9.2",
17
- "@dedot/providers": "0.9.2",
18
- "@dedot/runtime-specs": "0.9.2",
19
- "@dedot/shape": "0.9.2",
20
- "@dedot/storage": "0.9.2",
21
- "@dedot/types": "0.9.2",
22
- "@dedot/utils": "0.9.2"
16
+ "@dedot/codecs": "0.9.4",
17
+ "@dedot/providers": "0.9.4",
18
+ "@dedot/runtime-specs": "0.9.4",
19
+ "@dedot/shape": "0.9.4",
20
+ "@dedot/storage": "0.9.4",
21
+ "@dedot/types": "0.9.4",
22
+ "@dedot/utils": "0.9.4"
23
23
  },
24
24
  "scripts": {
25
25
  "build": "tsc --project tsconfig.build.json && tsc --project tsconfig.build.cjs.json",
@@ -48,7 +48,7 @@
48
48
  "node": ">=18"
49
49
  },
50
50
  "license": "Apache-2.0",
51
- "gitHead": "b28ae48371785d44bf734cf45a5b8d0716d9bd70",
51
+ "gitHead": "1deabbf35425a688e76f1612210bcda3f7bedba3",
52
52
  "module": "./index.js",
53
53
  "types": "./index.d.ts"
54
54
  }
@@ -1,3 +1,4 @@
1
+ import { AsyncQueue } from '@dedot/utils';
1
2
  import { BaseStorageQuery } from './BaseStorageQuery.js';
2
3
  /**
3
4
  * @name NewStorageQuery
@@ -48,6 +49,11 @@ export class NewStorageQuery extends BaseStorageQuery {
48
49
  const best = await this.client.chainHead.bestBlock();
49
50
  // Track the latest changes for each key
50
51
  const latestChanges = {};
52
+ // Using a queue here to make sure we don't accidentally
53
+ // put a pressure the json-rpc server in-case new blocks stack up too fast
54
+ // in case we send a lot of requests at the same time
55
+ // or the block time is small enough with elastic scaling
56
+ const pullQueue = new AsyncQueue();
51
57
  // Function to pull storage values and call the callback if there are changes
52
58
  const pull = async ({ hash }) => {
53
59
  // Query storage using ChainHead API
@@ -73,9 +79,12 @@ export class NewStorageQuery extends BaseStorageQuery {
73
79
  // Initial pull
74
80
  await pull(best);
75
81
  // Subscribe to best block events
76
- const unsub = this.client.on('bestBlock', pull);
82
+ const unsub = this.client.on('bestBlock', (block) => {
83
+ pullQueue.enqueue(() => pull(block)).catch(console.error);
84
+ });
77
85
  return async () => {
78
86
  unsub();
87
+ pullQueue.cancel();
79
88
  };
80
89
  }
81
90
  }