@dedot/api 0.15.2 → 0.16.0
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/chaintypes/substrate/index.d.ts +21 -1
- package/cjs/client/BaseSubstrateClient.js +12 -3
- package/cjs/client/DedotClient.js +51 -11
- package/cjs/client/LegacyClient.js +4 -5
- package/cjs/executor/Executor.js +1 -0
- package/cjs/executor/v2/StorageQueryExecutorV2.js +1 -3
- package/cjs/executor/v2/TxExecutorV2.js +5 -3
- package/cjs/json-rpc/group/Archive.js +232 -0
- package/cjs/json-rpc/group/ChainHead/ChainHead.js +149 -52
- package/cjs/json-rpc/group/ChainHead/error.js +5 -0
- package/cjs/json-rpc/group/index.js +1 -0
- package/cjs/json-rpc/subscriptionsInfo.js +4 -0
- package/cjs/storage/LegacyStorageQuery.js +5 -0
- package/cjs/storage/NewStorageQuery.js +5 -0
- package/client/BaseSubstrateClient.d.ts +8 -6
- package/client/BaseSubstrateClient.js +13 -4
- package/client/DedotClient.d.ts +11 -4
- package/client/DedotClient.js +54 -14
- package/client/LegacyClient.d.ts +2 -2
- package/client/LegacyClient.js +4 -5
- package/executor/Executor.d.ts +5 -5
- package/executor/Executor.js +1 -0
- package/executor/StorageQueryExecutor.d.ts +2 -2
- package/executor/v2/RuntimeApiExecutorV2.d.ts +2 -2
- package/executor/v2/StorageQueryExecutorV2.d.ts +4 -4
- package/executor/v2/StorageQueryExecutorV2.js +1 -3
- package/executor/v2/TxExecutorV2.d.ts +2 -1
- package/executor/v2/TxExecutorV2.js +5 -3
- package/executor/v2/ViewFunctionExecutorV2.d.ts +2 -2
- package/extrinsic/extensions/SignedExtension.d.ts +3 -3
- package/extrinsic/submittable/BaseSubmittableExtrinsic.d.ts +2 -2
- package/extrinsic/submittable/SubmittableExtrinsicV2.d.ts +2 -2
- package/json-rpc/group/Archive.d.ts +134 -0
- package/json-rpc/group/Archive.js +228 -0
- package/json-rpc/group/ChainHead/ChainHead.d.ts +21 -0
- package/json-rpc/group/ChainHead/ChainHead.js +150 -53
- package/json-rpc/group/ChainHead/error.d.ts +3 -0
- package/json-rpc/group/ChainHead/error.js +5 -0
- package/json-rpc/group/index.d.ts +1 -0
- package/json-rpc/group/index.js +1 -0
- package/json-rpc/subscriptionsInfo.js +4 -0
- package/package.json +9 -9
- package/storage/BaseStorageQuery.d.ts +5 -6
- package/storage/LegacyStorageQuery.d.ts +4 -3
- package/storage/LegacyStorageQuery.js +5 -0
- package/storage/NewStorageQuery.d.ts +4 -3
- package/storage/NewStorageQuery.js +5 -0
- package/storage/QueryableStorage.d.ts +2 -2
- package/types.d.ts +11 -6
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { $Header } from '@dedot/codecs';
|
|
2
|
-
import { assert, AsyncQueue, deferred, ensurePresence, noop, ThrottleQueue, waitFor, } from '@dedot/utils';
|
|
2
|
+
import { assert, AsyncQueue, deferred, ensurePresence, noop, ThrottleQueue, waitFor, LRUCache, } from '@dedot/utils';
|
|
3
3
|
import { JsonRpcGroup } from '../JsonRpcGroup.js';
|
|
4
4
|
import { BlockUsage } from './BlockUsage.js';
|
|
5
5
|
import { ChainHeadBlockNotPinnedError, ChainHeadBlockPrunedError, ChainHeadError, ChainHeadLimitReachedError, ChainHeadOperationError, ChainHeadOperationInaccessibleError, ChainHeadStopError, RetryStrategy, } from './error.js';
|
|
6
6
|
export const MIN_FINALIZED_QUEUE_SIZE = 10; // finalized queue size
|
|
7
|
+
const CHAINHEAD_CACHE_CAPACITY = 256;
|
|
8
|
+
const CHAINHEAD_CACHE_TTL = 30_000; // 30 seconds
|
|
7
9
|
export class ChainHead extends JsonRpcGroup {
|
|
8
10
|
#unsub;
|
|
9
11
|
#subscriptionId;
|
|
@@ -20,6 +22,17 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
20
22
|
#blockUsage;
|
|
21
23
|
#cache;
|
|
22
24
|
#operationQueue;
|
|
25
|
+
/**
|
|
26
|
+
* Archive instance used as fallback when ChainHead blocks are not pinned.
|
|
27
|
+
*
|
|
28
|
+
* When ChainHead operations fail with ChainHeadBlockNotPinnedError, the system
|
|
29
|
+
* automatically attempts the same operation using the Archive API. This provides
|
|
30
|
+
* seamless access to historical blockchain data even when blocks are no longer
|
|
31
|
+
* maintained in the ChainHead's pinned block set.
|
|
32
|
+
*
|
|
33
|
+
* @private
|
|
34
|
+
*/
|
|
35
|
+
#archive;
|
|
23
36
|
constructor(client, options) {
|
|
24
37
|
super(client, { prefix: 'chainHead', supportedVersions: ['unstable', 'v1'], ...options });
|
|
25
38
|
this.#handlers = {};
|
|
@@ -29,10 +42,22 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
29
42
|
this.#followResponseQueue = new AsyncQueue();
|
|
30
43
|
this.#retryQueue = new AsyncQueue();
|
|
31
44
|
this.#blockUsage = new BlockUsage();
|
|
32
|
-
this.#cache = new
|
|
45
|
+
this.#cache = new LRUCache(CHAINHEAD_CACHE_CAPACITY, CHAINHEAD_CACHE_TTL);
|
|
33
46
|
// This helps us to not accidentally putting too much stress on the JSON-RPC server, especially smoldot/light-client
|
|
34
47
|
this.#operationQueue = new ThrottleQueue(this.#__unsafe__isSmoldot() ? 25 : 250);
|
|
35
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Attach an Archive instance as fallback for operations that fail due to unpinned blocks.
|
|
51
|
+
* When a ChainHeadBlockNotPinnedError occurs, the operation will automatically fallback
|
|
52
|
+
* to the Archive API to attempt to retrieve the data from historical blocks.
|
|
53
|
+
*
|
|
54
|
+
* @param archive - Archive instance to use as fallback
|
|
55
|
+
* @returns this ChainHead instance for method chaining
|
|
56
|
+
*/
|
|
57
|
+
withArchive(archive) {
|
|
58
|
+
this.#archive = archive;
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
36
61
|
async runtimeVersion() {
|
|
37
62
|
await this.#ensureFollowed();
|
|
38
63
|
return this.#finalizedRuntime;
|
|
@@ -219,8 +244,9 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
219
244
|
if (!this.isPinned(hash))
|
|
220
245
|
return;
|
|
221
246
|
delete this.#pinnedBlocks[hash];
|
|
222
|
-
//
|
|
223
|
-
|
|
247
|
+
// Clear cache entries related to the pruned block
|
|
248
|
+
// Filter and remove only cache entries for this specific block
|
|
249
|
+
this.#cache.keys()
|
|
224
250
|
.filter((key) => key.startsWith(`${hash}::`))
|
|
225
251
|
.forEach((key) => this.#cache.delete(key));
|
|
226
252
|
});
|
|
@@ -341,11 +367,38 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
341
367
|
return hash;
|
|
342
368
|
}
|
|
343
369
|
else {
|
|
344
|
-
throw new ChainHeadBlockNotPinnedError(`Block hash ${hash} is not pinned
|
|
370
|
+
throw new ChainHeadBlockNotPinnedError(`Block hash ${hash} is not pinned`, hash);
|
|
345
371
|
}
|
|
346
372
|
}
|
|
347
373
|
return ensurePresence(this.#bestHash || this.#finalizedHash);
|
|
348
374
|
}
|
|
375
|
+
/**
|
|
376
|
+
* Executes a ChainHead operation with automatic Archive fallback.
|
|
377
|
+
*
|
|
378
|
+
* This method first attempts the primary ChainHead operation. If it fails with
|
|
379
|
+
* ChainHeadBlockNotPinnedError (indicating the block is no longer pinned), and
|
|
380
|
+
* an Archive instance is available, it automatically retries the operation using
|
|
381
|
+
* the Archive API.
|
|
382
|
+
*
|
|
383
|
+
* @param operation - Primary ChainHead operation to attempt
|
|
384
|
+
* @param fallback - Archive operation to fallback to
|
|
385
|
+
* @param hash - Block hash being accessed (for logging)
|
|
386
|
+
* @returns Result from either ChainHead or Archive operation
|
|
387
|
+
* @throws Original error if not a pinning error or no Archive available
|
|
388
|
+
* @private
|
|
389
|
+
*/
|
|
390
|
+
async #tryWithArchive(operation, fallback) {
|
|
391
|
+
try {
|
|
392
|
+
return await operation();
|
|
393
|
+
}
|
|
394
|
+
catch (error) {
|
|
395
|
+
if (error instanceof ChainHeadBlockNotPinnedError && this.#archive) {
|
|
396
|
+
const errorHash = error.hash;
|
|
397
|
+
return await fallback(this.#archive, errorHash);
|
|
398
|
+
}
|
|
399
|
+
throw error;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
349
402
|
#getOperationHandler(result) {
|
|
350
403
|
const handler = this.#handlers[result.operationId];
|
|
351
404
|
if (handler)
|
|
@@ -400,7 +453,7 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
400
453
|
this.#followResponseQueue.clear();
|
|
401
454
|
this.#retryQueue.clear();
|
|
402
455
|
this.#blockUsage.clear();
|
|
403
|
-
this
|
|
456
|
+
this.clearCache();
|
|
404
457
|
this.#operationQueue.cancel();
|
|
405
458
|
}
|
|
406
459
|
async #ensureFollowed() {
|
|
@@ -475,21 +528,32 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
475
528
|
async body(at) {
|
|
476
529
|
await this.#ensureFollowed();
|
|
477
530
|
const shouldRetryOnPrunedBlock = !at;
|
|
478
|
-
|
|
531
|
+
const operation = async () => {
|
|
479
532
|
const atHash = this.#ensurePinnedHash(at);
|
|
480
533
|
const cacheKey = `${atHash}::body`;
|
|
481
|
-
|
|
482
|
-
|
|
534
|
+
const cached = this.#cache.get(cacheKey);
|
|
535
|
+
if (cached) {
|
|
536
|
+
return cached;
|
|
483
537
|
}
|
|
484
|
-
const
|
|
538
|
+
const bodyOperation = async () => {
|
|
485
539
|
await this.#ensureFollowed();
|
|
486
540
|
const hash = this.#ensurePinnedHash(atHash);
|
|
487
541
|
const resp = await this.send('body', this.#subscriptionId, hash);
|
|
488
542
|
return this.#awaitOperation(resp, hash);
|
|
489
543
|
};
|
|
490
|
-
const resp = await this.#operationQueue.add(() => this.#performOperationWithRetry(
|
|
544
|
+
const resp = await this.#operationQueue.add(() => this.#performOperationWithRetry(bodyOperation, atHash));
|
|
491
545
|
this.#cache.set(cacheKey, resp);
|
|
492
546
|
return resp;
|
|
547
|
+
};
|
|
548
|
+
const fallback = async (archive, hash) => {
|
|
549
|
+
const result = await archive.body(hash);
|
|
550
|
+
if (result === undefined) {
|
|
551
|
+
throw new ChainHeadOperationError(`Block ${hash} not found in Archive`);
|
|
552
|
+
}
|
|
553
|
+
return result;
|
|
554
|
+
};
|
|
555
|
+
try {
|
|
556
|
+
return await this.#tryWithArchive(operation, fallback);
|
|
493
557
|
}
|
|
494
558
|
catch (e) {
|
|
495
559
|
if (e instanceof ChainHeadBlockPrunedError && shouldRetryOnPrunedBlock) {
|
|
@@ -504,21 +568,26 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
504
568
|
async call(func, params = '0x', at) {
|
|
505
569
|
await this.#ensureFollowed();
|
|
506
570
|
const shouldRetryOnPrunedBlock = !at;
|
|
507
|
-
|
|
571
|
+
const operation = async () => {
|
|
508
572
|
const atHash = this.#ensurePinnedHash(at);
|
|
509
573
|
const cacheKey = `${atHash}::call::${func}::${params}`;
|
|
510
|
-
|
|
511
|
-
|
|
574
|
+
const cached = this.#cache.get(cacheKey);
|
|
575
|
+
if (cached) {
|
|
576
|
+
return cached;
|
|
512
577
|
}
|
|
513
|
-
const
|
|
578
|
+
const callOperation = async () => {
|
|
514
579
|
await this.#ensureFollowed();
|
|
515
580
|
const hash = this.#ensurePinnedHash(atHash);
|
|
516
581
|
const resp = await this.send('call', this.#subscriptionId, hash, func, params);
|
|
517
582
|
return this.#awaitOperation(resp, hash);
|
|
518
583
|
};
|
|
519
|
-
const resp = await this.#operationQueue.add(() => this.#performOperationWithRetry(
|
|
584
|
+
const resp = await this.#operationQueue.add(() => this.#performOperationWithRetry(callOperation, atHash));
|
|
520
585
|
this.#cache.set(cacheKey, resp);
|
|
521
586
|
return resp;
|
|
587
|
+
};
|
|
588
|
+
const fallback = (archive, hash) => archive.call(func, params, hash);
|
|
589
|
+
try {
|
|
590
|
+
return await this.#tryWithArchive(operation, fallback);
|
|
522
591
|
}
|
|
523
592
|
catch (e) {
|
|
524
593
|
if (e instanceof ChainHeadBlockPrunedError && shouldRetryOnPrunedBlock) {
|
|
@@ -532,14 +601,19 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
532
601
|
*/
|
|
533
602
|
async header(at) {
|
|
534
603
|
await this.#ensureFollowed();
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
604
|
+
const operation = async () => {
|
|
605
|
+
const hash = this.#ensurePinnedHash(at);
|
|
606
|
+
const cacheKey = `${hash}::header`;
|
|
607
|
+
const cached = this.#cache.get(cacheKey);
|
|
608
|
+
if (cached) {
|
|
609
|
+
return cached;
|
|
610
|
+
}
|
|
611
|
+
const resp = await this.#getHeader(hash);
|
|
612
|
+
this.#cache.set(cacheKey, resp);
|
|
613
|
+
return resp;
|
|
614
|
+
};
|
|
615
|
+
const fallback = (archive, errorHash) => archive.header(errorHash);
|
|
616
|
+
return await this.#tryWithArchive(operation, fallback);
|
|
543
617
|
}
|
|
544
618
|
async #getHeader(at) {
|
|
545
619
|
return await this.send('header', this.#subscriptionId, at);
|
|
@@ -550,35 +624,47 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
550
624
|
async storage(items, childTrie, at) {
|
|
551
625
|
await this.#ensureFollowed();
|
|
552
626
|
const shouldRetryOnPrunedBlock = !at;
|
|
553
|
-
const
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
627
|
+
const operation = async () => {
|
|
628
|
+
const hash = this.#ensurePinnedHash(at);
|
|
629
|
+
try {
|
|
630
|
+
// JSON.stringify(items) might get big, we probably should do a twox hashing in such case
|
|
631
|
+
const cacheKey = `${hash}::storage::${JSON.stringify(items)}::${childTrie ?? null}`;
|
|
632
|
+
const cached = this.#cache.get(cacheKey);
|
|
633
|
+
if (cached) {
|
|
634
|
+
return cached;
|
|
635
|
+
}
|
|
636
|
+
this.#blockUsage.use(hash);
|
|
637
|
+
let results = [];
|
|
638
|
+
if (this.#__unsafe__isSmoldot()) {
|
|
639
|
+
const fetchItem = async (item) => {
|
|
640
|
+
const [batch, newDiscardedItems] = await this.#getStorage([item], childTrie ?? null, hash);
|
|
641
|
+
if (newDiscardedItems.length > 0) {
|
|
642
|
+
return fetchItem(item);
|
|
643
|
+
}
|
|
644
|
+
return batch;
|
|
645
|
+
};
|
|
646
|
+
results = (await Promise.all(items.map((one) => fetchItem(one)))).flat();
|
|
647
|
+
}
|
|
648
|
+
else {
|
|
649
|
+
let queryItems = items;
|
|
650
|
+
while (queryItems.length > 0) {
|
|
651
|
+
const [newBatch, newDiscardedItems] = await this.#getStorage(queryItems, childTrie ?? null, hash);
|
|
652
|
+
results.push(...newBatch);
|
|
653
|
+
queryItems = newDiscardedItems;
|
|
567
654
|
}
|
|
568
|
-
return batch;
|
|
569
|
-
};
|
|
570
|
-
results = (await Promise.all(items.map((one) => fetchItem(one)))).flat();
|
|
571
|
-
}
|
|
572
|
-
else {
|
|
573
|
-
let queryItems = items;
|
|
574
|
-
while (queryItems.length > 0) {
|
|
575
|
-
const [newBatch, newDiscardedItems] = await this.#getStorage(queryItems, childTrie ?? null, hash);
|
|
576
|
-
results.push(...newBatch);
|
|
577
|
-
queryItems = newDiscardedItems;
|
|
578
655
|
}
|
|
656
|
+
this.#cache.set(cacheKey, results);
|
|
657
|
+
return results;
|
|
658
|
+
}
|
|
659
|
+
finally {
|
|
660
|
+
this.#blockUsage.release(hash);
|
|
579
661
|
}
|
|
580
|
-
|
|
581
|
-
|
|
662
|
+
};
|
|
663
|
+
const fallback = (archive, hash) => {
|
|
664
|
+
return archive.storage(items, childTrie, hash);
|
|
665
|
+
};
|
|
666
|
+
try {
|
|
667
|
+
return await this.#tryWithArchive(operation, fallback);
|
|
582
668
|
}
|
|
583
669
|
catch (e) {
|
|
584
670
|
if (e instanceof ChainHeadBlockPrunedError && shouldRetryOnPrunedBlock) {
|
|
@@ -586,9 +672,6 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
586
672
|
}
|
|
587
673
|
throw e;
|
|
588
674
|
}
|
|
589
|
-
finally {
|
|
590
|
-
this.#blockUsage.release(hash);
|
|
591
|
-
}
|
|
592
675
|
}
|
|
593
676
|
async #getStorage(items, childTrie, at) {
|
|
594
677
|
const operation = () => this.#getStorageOperation(items, childTrie, this.#ensurePinnedHash(at));
|
|
@@ -633,4 +716,18 @@ export class ChainHead extends JsonRpcGroup {
|
|
|
633
716
|
// @ts-ignore a trick internally to check whether a provider is using smoldot connection
|
|
634
717
|
return typeof this.client.provider['chain'] === 'function';
|
|
635
718
|
}
|
|
719
|
+
/**
|
|
720
|
+
* Clears the internal cache used for storing query results (both chainHead & archive instances)
|
|
721
|
+
* This can be useful for memory management or when you want to force fresh data retrieval.
|
|
722
|
+
*
|
|
723
|
+
* @example
|
|
724
|
+
* ```typescript
|
|
725
|
+
* // Clear all cached results
|
|
726
|
+
* chainHead.clearCache();
|
|
727
|
+
* ```
|
|
728
|
+
*/
|
|
729
|
+
clearCache() {
|
|
730
|
+
this.#cache.clear();
|
|
731
|
+
this.#archive?.clearCache();
|
|
732
|
+
}
|
|
636
733
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BlockHash } from '@dedot/codecs';
|
|
1
2
|
import { DedotError } from '@dedot/utils';
|
|
2
3
|
export declare enum RetryStrategy {
|
|
3
4
|
NOW = "NOW",// Retry immediately
|
|
@@ -49,6 +50,8 @@ export declare class ChainHeadInvalidRuntimeError extends ChainHeadError {
|
|
|
49
50
|
}
|
|
50
51
|
export declare class ChainHeadBlockNotPinnedError extends ChainHeadError {
|
|
51
52
|
name: string;
|
|
53
|
+
hash: BlockHash;
|
|
54
|
+
constructor(message: string, hash: BlockHash | string);
|
|
52
55
|
}
|
|
53
56
|
export declare class ChainHeadBlockPrunedError extends ChainHeadError {
|
|
54
57
|
name: string;
|
|
@@ -50,6 +50,11 @@ export class ChainHeadInvalidRuntimeError extends ChainHeadError {
|
|
|
50
50
|
}
|
|
51
51
|
export class ChainHeadBlockNotPinnedError extends ChainHeadError {
|
|
52
52
|
name = 'ChainHeadBlockNotPinnedError';
|
|
53
|
+
hash;
|
|
54
|
+
constructor(message, hash) {
|
|
55
|
+
super(message);
|
|
56
|
+
this.hash = hash;
|
|
57
|
+
}
|
|
53
58
|
}
|
|
54
59
|
export class ChainHeadBlockPrunedError extends ChainHeadError {
|
|
55
60
|
name = 'ChainHeadBlockPrunedError';
|
package/json-rpc/group/index.js
CHANGED
|
@@ -14,4 +14,8 @@ export const subscriptionsInfo = {
|
|
|
14
14
|
'transactionWatch_unstable_unwatch',
|
|
15
15
|
],
|
|
16
16
|
transactionWatch_v1_submitAndWatch: ['transactionWatch_v1_watchEvent', 'transactionWatch_v1_unwatch'],
|
|
17
|
+
archive_v1_storage: ['archive_v1_storageEvent', 'archive_v1_stopStorage'],
|
|
18
|
+
archive_v1_storageDiff: ['archive_v1_storageDiffEvent', 'archive_v1_stopStorageDiff'],
|
|
19
|
+
archive_unstable_storage: ['archive_unstable_storageEvent', 'archive_unstable_stopStorage'],
|
|
20
|
+
archive_unstable_storageDiff: ['archive_unstable_storageDiffEvent', 'archive_unstable_stopStorageDiff'],
|
|
17
21
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dedot/api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
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.
|
|
17
|
-
"@dedot/providers": "0.
|
|
18
|
-
"@dedot/runtime-specs": "0.
|
|
19
|
-
"@dedot/shape": "0.
|
|
20
|
-
"@dedot/storage": "0.
|
|
21
|
-
"@dedot/types": "0.
|
|
22
|
-
"@dedot/utils": "0.
|
|
16
|
+
"@dedot/codecs": "0.16.0",
|
|
17
|
+
"@dedot/providers": "0.16.0",
|
|
18
|
+
"@dedot/runtime-specs": "0.16.0",
|
|
19
|
+
"@dedot/shape": "0.16.0",
|
|
20
|
+
"@dedot/storage": "0.16.0",
|
|
21
|
+
"@dedot/types": "0.16.0",
|
|
22
|
+
"@dedot/utils": "0.16.0"
|
|
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": "3e78a8eebb8977de0c5fb956154e5b09c4448f31",
|
|
52
52
|
"module": "./index.js",
|
|
53
53
|
"types": "./index.d.ts"
|
|
54
54
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BlockHash, StorageData, StorageKey } from '@dedot/codecs';
|
|
2
|
-
import type { Callback,
|
|
3
|
-
import
|
|
4
|
-
import { BaseSubstrateClient } from '../client/BaseSubstrateClient.js';
|
|
2
|
+
import type { Callback, Unsub } from '@dedot/types';
|
|
3
|
+
import { ISubstrateClient, ISubstrateClientAt } from '../types.js';
|
|
5
4
|
/**
|
|
6
5
|
* @name BaseStorageQuery
|
|
7
6
|
* @description
|
|
@@ -16,12 +15,12 @@ import { BaseSubstrateClient } from '../client/BaseSubstrateClient.js';
|
|
|
16
15
|
* This abstraction eliminates code duplication between different client implementations
|
|
17
16
|
* and provides a consistent interface for storage operations.
|
|
18
17
|
*/
|
|
19
|
-
export declare abstract class BaseStorageQuery
|
|
20
|
-
protected client:
|
|
18
|
+
export declare abstract class BaseStorageQuery {
|
|
19
|
+
protected client: ISubstrateClientAt<any> | ISubstrateClient<any, any>;
|
|
21
20
|
/**
|
|
22
21
|
* @param client - The substrate client instance
|
|
23
22
|
*/
|
|
24
|
-
constructor(client:
|
|
23
|
+
protected constructor(client: ISubstrateClientAt<any> | ISubstrateClient<any, any>);
|
|
25
24
|
/**
|
|
26
25
|
* Query multiple storage items in a single call
|
|
27
26
|
*
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BlockHash, StorageData, StorageKey } from '@dedot/codecs';
|
|
2
|
-
import type { Callback,
|
|
3
|
-
import type { SubstrateApi } from '../chaintypes/index.js';
|
|
2
|
+
import type { Callback, Unsub } from '@dedot/types';
|
|
4
3
|
import { LegacyClient } from '../client/LegacyClient.js';
|
|
5
4
|
import { BaseStorageQuery } from './BaseStorageQuery.js';
|
|
6
5
|
/**
|
|
@@ -15,7 +14,9 @@ import { BaseStorageQuery } from './BaseStorageQuery.js';
|
|
|
15
14
|
* - Subscriptions using state_subscribeStorage
|
|
16
15
|
* - Efficient change tracking for subscriptions
|
|
17
16
|
*/
|
|
18
|
-
export declare class LegacyStorageQuery
|
|
17
|
+
export declare class LegacyStorageQuery extends BaseStorageQuery {
|
|
18
|
+
protected client: LegacyClient<any>;
|
|
19
|
+
constructor(client: LegacyClient<any>);
|
|
19
20
|
/**
|
|
20
21
|
* Query multiple storage items in a single call using state_queryStorageAt
|
|
21
22
|
*
|
|
@@ -12,6 +12,11 @@ import { BaseStorageQuery } from './BaseStorageQuery.js';
|
|
|
12
12
|
* - Efficient change tracking for subscriptions
|
|
13
13
|
*/
|
|
14
14
|
export class LegacyStorageQuery extends BaseStorageQuery {
|
|
15
|
+
client;
|
|
16
|
+
constructor(client) {
|
|
17
|
+
super(client);
|
|
18
|
+
this.client = client;
|
|
19
|
+
}
|
|
15
20
|
/**
|
|
16
21
|
* Query multiple storage items in a single call using state_queryStorageAt
|
|
17
22
|
*
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BlockHash, StorageData, StorageKey } from '@dedot/codecs';
|
|
2
|
-
import type { Callback,
|
|
3
|
-
import type { SubstrateApi } from '../chaintypes/index.js';
|
|
2
|
+
import type { Callback, Unsub } from '@dedot/types';
|
|
4
3
|
import { DedotClient } from '../client/DedotClient.js';
|
|
5
4
|
import { BaseStorageQuery } from './BaseStorageQuery.js';
|
|
6
5
|
/**
|
|
@@ -15,7 +14,9 @@ import { BaseStorageQuery } from './BaseStorageQuery.js';
|
|
|
15
14
|
* - Subscriptions using chainHead 'bestBlock' events
|
|
16
15
|
* - Efficient change detection for subscriptions
|
|
17
16
|
*/
|
|
18
|
-
export declare class NewStorageQuery
|
|
17
|
+
export declare class NewStorageQuery extends BaseStorageQuery {
|
|
18
|
+
protected client: DedotClient<any>;
|
|
19
|
+
constructor(client: DedotClient<any>);
|
|
19
20
|
/**
|
|
20
21
|
* Query multiple storage items in a single call using chainHead_storage
|
|
21
22
|
*
|
|
@@ -13,6 +13,11 @@ import { BaseStorageQuery } from './BaseStorageQuery.js';
|
|
|
13
13
|
* - Efficient change detection for subscriptions
|
|
14
14
|
*/
|
|
15
15
|
export class NewStorageQuery extends BaseStorageQuery {
|
|
16
|
+
client;
|
|
17
|
+
constructor(client) {
|
|
18
|
+
super(client);
|
|
19
|
+
this.client = client;
|
|
20
|
+
}
|
|
16
21
|
/**
|
|
17
22
|
* Query multiple storage items in a single call using chainHead_storage
|
|
18
23
|
*
|
|
@@ -5,12 +5,12 @@ import { PortableRegistry, PalletDefLatest, StorageDataLike, StorageEntryLatest,
|
|
|
5
5
|
*/
|
|
6
6
|
export declare class QueryableStorage {
|
|
7
7
|
#private;
|
|
8
|
-
readonly registry: PortableRegistry
|
|
8
|
+
readonly registry: PortableRegistry<any>;
|
|
9
9
|
readonly palletName: string;
|
|
10
10
|
readonly storageItem: string;
|
|
11
11
|
readonly pallet: PalletDefLatest;
|
|
12
12
|
readonly storageEntry: StorageEntryLatest;
|
|
13
|
-
constructor(registry: PortableRegistry
|
|
13
|
+
constructor(registry: PortableRegistry<any>, palletName: string, storageItem: string);
|
|
14
14
|
get prefixKey(): PrefixedStorageKey;
|
|
15
15
|
get prefixKeyAsU8a(): Uint8Array;
|
|
16
16
|
/**
|
package/types.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ChainHeadEvent } from '@dedot/api/json-rpc';
|
|
2
1
|
import { BlockHash, Hash, Metadata, PortableRegistry } from '@dedot/codecs';
|
|
3
2
|
import type { ConnectionStatus, JsonRpcProvider, ProviderEvent } from '@dedot/providers';
|
|
4
3
|
import type { AnyShape } from '@dedot/shape';
|
|
@@ -6,6 +5,7 @@ import type { IStorage } from '@dedot/storage';
|
|
|
6
5
|
import type { Callback, GenericStorageQuery, GenericSubstrateApi, InjectedSigner, Query, QueryFnResult, RpcVersion, RuntimeApiName, RuntimeApiSpec, Unsub } from '@dedot/types';
|
|
7
6
|
import type { HashFn, HexString, IEventEmitter } from '@dedot/utils';
|
|
8
7
|
import type { AnySignedExtension } from './extrinsic/index.js';
|
|
8
|
+
import type { ChainHeadEvent } from './json-rpc/index.js';
|
|
9
9
|
export type MetadataKey = `RAW_META/${string}`;
|
|
10
10
|
export type SubscribeMethod = string;
|
|
11
11
|
export type UnsubscribeMethod = string;
|
|
@@ -83,16 +83,15 @@ export interface IJsonRpcClient<ChainApi extends GenericSubstrateApi = GenericSu
|
|
|
83
83
|
rpc: ChainApi['rpc'];
|
|
84
84
|
}
|
|
85
85
|
/**
|
|
86
|
-
*
|
|
86
|
+
* @internal
|
|
87
87
|
*/
|
|
88
|
-
export interface
|
|
89
|
-
atBlockHash?: BlockHash;
|
|
88
|
+
export interface IGenericSubstrateClient<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> {
|
|
90
89
|
rpcVersion: RpcVersion;
|
|
91
90
|
options: ApiOptions;
|
|
92
91
|
genesisHash: Hash;
|
|
93
92
|
runtimeVersion: SubstrateRuntimeVersion;
|
|
94
93
|
metadata: Metadata;
|
|
95
|
-
registry: PortableRegistry
|
|
94
|
+
registry: PortableRegistry<ChainApi>;
|
|
96
95
|
rpc: ChainApi['rpc'];
|
|
97
96
|
consts: ChainApi['consts'];
|
|
98
97
|
query: ChainApi['query'];
|
|
@@ -101,10 +100,16 @@ export interface ISubstrateClientAt<ChainApi extends GenericSubstrateApi = Gener
|
|
|
101
100
|
errors: ChainApi['errors'];
|
|
102
101
|
view: ChainApi['view'];
|
|
103
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* A generic interface for Substrate clients at a specific block
|
|
105
|
+
*/
|
|
106
|
+
export interface ISubstrateClientAt<ChainApi extends GenericSubstrateApi = GenericSubstrateApi> extends IGenericSubstrateClient<ChainApi> {
|
|
107
|
+
atBlockHash: BlockHash;
|
|
108
|
+
}
|
|
104
109
|
/**
|
|
105
110
|
* A generic interface for Substrate clients
|
|
106
111
|
*/
|
|
107
|
-
export interface ISubstrateClient<ChainApi extends GenericSubstrateApi = GenericSubstrateApi, Events extends string = ApiEvent> extends IJsonRpcClient<ChainApi, Events>,
|
|
112
|
+
export interface ISubstrateClient<ChainApi extends GenericSubstrateApi = GenericSubstrateApi, Events extends string = ApiEvent> extends IJsonRpcClient<ChainApi, Events>, IGenericSubstrateClient<ChainApi> {
|
|
108
113
|
options: ApiOptions;
|
|
109
114
|
tx: ChainApi['tx'];
|
|
110
115
|
at<ChainApiAt extends GenericSubstrateApi = ChainApi>(hash: BlockHash): Promise<ISubstrateClientAt<ChainApiAt>>;
|