@dedot/api 0.9.1 → 0.9.3

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.
@@ -360,7 +360,17 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
360
360
  if (!runtimeEvent)
361
361
  return;
362
362
  if (runtimeEvent.type == 'valid') {
363
- return runtimeEvent.spec;
363
+ const newRuntimeVersion = runtimeEvent.spec;
364
+ // fix inconsistent type of returned apis
365
+ // in some network endpoints this newRuntimeVersion.apis is an array (maybe using an old version of the sdk)
366
+ // here we convert it to a map format for consistency.
367
+ if (Array.isArray(newRuntimeVersion.apis)) {
368
+ newRuntimeVersion.apis = newRuntimeVersion.apis.reduce((o, [name, version]) => {
369
+ o[name] = version;
370
+ return o;
371
+ }, {});
372
+ }
373
+ return newRuntimeVersion;
364
374
  }
365
375
  // If the runtime is invalid,
366
376
  // we safely return an undefined runtime for now
@@ -400,7 +410,7 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
400
410
  }
401
411
  catch (e) {
402
412
  if (e instanceof error_js_1.ChainHeadError && e.retryStrategy) {
403
- return this.#retryOperation(e.retryStrategy, operation);
413
+ return await this.#retryOperation(e.retryStrategy, operation);
404
414
  }
405
415
  throw e;
406
416
  }
@@ -427,7 +437,7 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
427
437
  catch (e) {
428
438
  // retry again until success, TODO we might need to limit the number of retries
429
439
  if (e instanceof error_js_1.ChainHeadError && e.retryStrategy) {
430
- return this.#retryOperation(e.retryStrategy, retry);
440
+ return await this.#retryOperation(e.retryStrategy, retry);
431
441
  }
432
442
  throw e;
433
443
  }
@@ -540,19 +550,36 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
540
550
  return this.#cache.get(cacheKey);
541
551
  }
542
552
  this.#blockUsage.use(hash);
543
- const results = [];
544
- let queryItems = items;
545
- while (queryItems.length > 0) {
546
- const [newBatch, newDiscardedItems] = await this.#getStorage(queryItems, childTrie ?? null, hash);
547
- results.push(...newBatch);
548
- 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 [newBatch, newDiscardedItems] = await this.#getStorage([item], childTrie ?? null, hash);
559
+ if (newDiscardedItems.length > 0) {
560
+ return fetchItem(item);
561
+ }
562
+ if (newBatch.length === 0) {
563
+ return { key: item.key, value: undefined };
564
+ }
565
+ return newBatch[0];
566
+ };
567
+ results = await Promise.all(items.map((one) => fetchItem(one)));
568
+ }
569
+ else {
570
+ let queryItems = items;
571
+ while (queryItems.length > 0) {
572
+ const [newBatch, newDiscardedItems] = await this.#getStorage(queryItems, childTrie ?? null, hash);
573
+ results.push(...newBatch);
574
+ queryItems = newDiscardedItems;
575
+ }
549
576
  }
550
577
  this.#cache.set(cacheKey, results);
551
578
  return results;
552
579
  }
553
580
  catch (e) {
554
581
  if (e instanceof error_js_1.ChainHeadBlockPrunedError && shouldRetryOnPrunedBlock) {
555
- return this.storage(items, childTrie);
582
+ return await this.storage(items, childTrie);
556
583
  }
557
584
  throw e;
558
585
  }
@@ -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
  }
@@ -357,7 +357,17 @@ export class ChainHead extends JsonRpcGroup {
357
357
  if (!runtimeEvent)
358
358
  return;
359
359
  if (runtimeEvent.type == 'valid') {
360
- return runtimeEvent.spec;
360
+ const newRuntimeVersion = runtimeEvent.spec;
361
+ // fix inconsistent type of returned apis
362
+ // in some network endpoints this newRuntimeVersion.apis is an array (maybe using an old version of the sdk)
363
+ // here we convert it to a map format for consistency.
364
+ if (Array.isArray(newRuntimeVersion.apis)) {
365
+ newRuntimeVersion.apis = newRuntimeVersion.apis.reduce((o, [name, version]) => {
366
+ o[name] = version;
367
+ return o;
368
+ }, {});
369
+ }
370
+ return newRuntimeVersion;
361
371
  }
362
372
  // If the runtime is invalid,
363
373
  // we safely return an undefined runtime for now
@@ -397,7 +407,7 @@ export class ChainHead extends JsonRpcGroup {
397
407
  }
398
408
  catch (e) {
399
409
  if (e instanceof ChainHeadError && e.retryStrategy) {
400
- return this.#retryOperation(e.retryStrategy, operation);
410
+ return await this.#retryOperation(e.retryStrategy, operation);
401
411
  }
402
412
  throw e;
403
413
  }
@@ -424,7 +434,7 @@ export class ChainHead extends JsonRpcGroup {
424
434
  catch (e) {
425
435
  // retry again until success, TODO we might need to limit the number of retries
426
436
  if (e instanceof ChainHeadError && e.retryStrategy) {
427
- return this.#retryOperation(e.retryStrategy, retry);
437
+ return await this.#retryOperation(e.retryStrategy, retry);
428
438
  }
429
439
  throw e;
430
440
  }
@@ -537,19 +547,36 @@ export class ChainHead extends JsonRpcGroup {
537
547
  return this.#cache.get(cacheKey);
538
548
  }
539
549
  this.#blockUsage.use(hash);
540
- const results = [];
541
- let queryItems = items;
542
- while (queryItems.length > 0) {
543
- const [newBatch, newDiscardedItems] = await this.#getStorage(queryItems, childTrie ?? null, hash);
544
- results.push(...newBatch);
545
- 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 [newBatch, newDiscardedItems] = await this.#getStorage([item], childTrie ?? null, hash);
556
+ if (newDiscardedItems.length > 0) {
557
+ return fetchItem(item);
558
+ }
559
+ if (newBatch.length === 0) {
560
+ return { key: item.key, value: undefined };
561
+ }
562
+ return newBatch[0];
563
+ };
564
+ results = await Promise.all(items.map((one) => fetchItem(one)));
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
+ }
546
573
  }
547
574
  this.#cache.set(cacheKey, results);
548
575
  return results;
549
576
  }
550
577
  catch (e) {
551
578
  if (e instanceof ChainHeadBlockPrunedError && shouldRetryOnPrunedBlock) {
552
- return this.storage(items, childTrie);
579
+ return await this.storage(items, childTrie);
553
580
  }
554
581
  throw e;
555
582
  }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@dedot/api",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "A delightful JavaScript/TypeScript client for Polkadot & Substrate",
5
- "author": "Thang X. Vu <thang@coongcrafts.io>",
6
- "homepage": "https://github.com/dedotdev/dedot/tree/main/packages/api",
5
+ "author": "Thang X. Vu <thang@dedot.dev>",
6
+ "homepage": "https://dedot.dev",
7
7
  "repository": {
8
8
  "directory": "packages/api",
9
9
  "type": "git",
@@ -13,13 +13,13 @@
13
13
  "type": "module",
14
14
  "sideEffects": false,
15
15
  "dependencies": {
16
- "@dedot/codecs": "0.9.1",
17
- "@dedot/providers": "0.9.1",
18
- "@dedot/runtime-specs": "0.9.1",
19
- "@dedot/shape": "0.9.1",
20
- "@dedot/storage": "0.9.1",
21
- "@dedot/types": "0.9.1",
22
- "@dedot/utils": "0.9.1"
16
+ "@dedot/codecs": "0.9.3",
17
+ "@dedot/providers": "0.9.3",
18
+ "@dedot/runtime-specs": "0.9.3",
19
+ "@dedot/shape": "0.9.3",
20
+ "@dedot/storage": "0.9.3",
21
+ "@dedot/types": "0.9.3",
22
+ "@dedot/utils": "0.9.3"
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": "9329cadcd2062d0f10dc1d8f700d8ade25214199",
51
+ "gitHead": "206c4999865cddbd1078bf5b059c7b49822e20d0",
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
  }