@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
|
-
|
|
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
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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',
|
|
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
|
-
|
|
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
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
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.
|
|
3
|
+
"version": "0.9.3",
|
|
4
4
|
"description": "A delightful JavaScript/TypeScript client for Polkadot & Substrate",
|
|
5
|
-
"author": "Thang X. Vu <thang@
|
|
6
|
-
"homepage": "https://
|
|
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.
|
|
17
|
-
"@dedot/providers": "0.9.
|
|
18
|
-
"@dedot/runtime-specs": "0.9.
|
|
19
|
-
"@dedot/shape": "0.9.
|
|
20
|
-
"@dedot/storage": "0.9.
|
|
21
|
-
"@dedot/types": "0.9.
|
|
22
|
-
"@dedot/utils": "0.9.
|
|
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": "
|
|
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',
|
|
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
|
}
|