@dedot/api 0.15.3-next.65898ecf.10 → 0.16.1-next.dd70d277.9

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.
Files changed (38) hide show
  1. package/chaintypes/substrate/consts.js +0 -1
  2. package/chaintypes/substrate/errors.js +0 -1
  3. package/chaintypes/substrate/events.js +0 -1
  4. package/chaintypes/substrate/json-rpc.js +0 -1
  5. package/chaintypes/substrate/query.js +0 -1
  6. package/chaintypes/substrate/runtime.js +0 -1
  7. package/chaintypes/substrate/tx.js +0 -1
  8. package/chaintypes/substrate/types.js +0 -1
  9. package/chaintypes/substrate/view-functions.js +0 -1
  10. package/cjs/chaintypes/substrate/consts.js +0 -1
  11. package/cjs/chaintypes/substrate/errors.js +0 -1
  12. package/cjs/chaintypes/substrate/events.js +0 -1
  13. package/cjs/chaintypes/substrate/json-rpc.js +0 -1
  14. package/cjs/chaintypes/substrate/query.js +0 -1
  15. package/cjs/chaintypes/substrate/runtime.js +0 -1
  16. package/cjs/chaintypes/substrate/tx.js +0 -1
  17. package/cjs/chaintypes/substrate/types.js +0 -1
  18. package/cjs/chaintypes/substrate/view-functions.js +0 -1
  19. package/cjs/client/BaseSubstrateClient.js +12 -3
  20. package/cjs/client/DedotClient.js +13 -6
  21. package/cjs/client/LegacyClient.js +4 -5
  22. package/cjs/extrinsic/extensions/known/index.js +0 -11
  23. package/cjs/json-rpc/group/Archive.js +15 -9
  24. package/cjs/json-rpc/group/ChainHead/ChainHead.js +34 -13
  25. package/client/BaseSubstrateClient.d.ts +7 -5
  26. package/client/BaseSubstrateClient.js +13 -4
  27. package/client/DedotClient.d.ts +5 -0
  28. package/client/DedotClient.js +13 -6
  29. package/client/LegacyClient.js +4 -5
  30. package/executor/Executor.d.ts +1 -1
  31. package/extrinsic/extensions/known/index.js +0 -11
  32. package/json-rpc/group/Archive.js +16 -10
  33. package/json-rpc/group/ChainHead/ChainHead.d.ts +11 -0
  34. package/json-rpc/group/ChainHead/ChainHead.js +35 -14
  35. package/package.json +9 -9
  36. package/storage/BaseStorageQuery.d.ts +1 -1
  37. package/storage/NewStorageQuery.d.ts +1 -1
  38. package/types.d.ts +2 -2
@@ -1,2 +1 @@
1
- // Generated by dedot cli
2
1
  export {};
@@ -1,2 +1 @@
1
- // Generated by dedot cli
2
1
  export {};
@@ -1,2 +1 @@
1
- // Generated by dedot cli
2
1
  export {};
@@ -1,2 +1 @@
1
- // Generated by dedot cli
2
1
  export {};
@@ -1,2 +1 @@
1
- // Generated by dedot cli
2
1
  export {};
@@ -1,2 +1 @@
1
- // Generated by dedot cli
2
1
  export {};
@@ -1,2 +1 @@
1
- // Generated by dedot cli
2
1
  export {};
@@ -1,2 +1 @@
1
- // Generated by dedot cli
2
1
  export {};
@@ -1,2 +1 @@
1
- // Generated by dedot cli
2
1
  export {};
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
- // Generated by dedot cli
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
- // Generated by dedot cli
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
- // Generated by dedot cli
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
- // Generated by dedot cli
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
- // Generated by dedot cli
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
- // Generated by dedot cli
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
- // Generated by dedot cli
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
- // Generated by dedot cli
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,3 +1,2 @@
1
1
  "use strict";
2
- // Generated by dedot cli
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -10,6 +10,8 @@ const proxychain_js_1 = require("../proxychain.js");
10
10
  const index_js_3 = require("../storage/index.js");
11
11
  const SUPPORTED_METADATA_VERSIONS = [16, 15, 14];
12
12
  const MetadataApiHash = (0, utils_1.calcRuntimeApiHash)('Metadata'); // 0x37e397fc7c91f5e4
13
+ const API_AT_CACHE_CAPACITY = 64;
14
+ const API_AT_CACHE_TTL = 300_000; // 5 minutes
13
15
  const MESSAGE = 'Make sure to call `.connect()` method first before using the API interfaces.';
14
16
  function ensurePresence(value) {
15
17
  return (0, utils_1.ensurePresence)(value, MESSAGE);
@@ -28,10 +30,12 @@ class BaseSubstrateClient extends index_js_2.JsonRpcClient {
28
30
  _runtimeVersion;
29
31
  _localCache;
30
32
  _runtimeUpgrading;
33
+ _apiAtCache;
31
34
  constructor(rpcVersion, options) {
32
35
  super(options);
33
36
  this.rpcVersion = rpcVersion;
34
37
  this._options = this.normalizeOptions(options);
38
+ this._apiAtCache = new utils_1.LRUCache(API_AT_CACHE_CAPACITY, API_AT_CACHE_TTL);
35
39
  }
36
40
  /// --- Internal logics
37
41
  normalizeOptions(options) {
@@ -189,12 +193,17 @@ class BaseSubstrateClient extends index_js_2.JsonRpcClient {
189
193
  this._genesisHash = undefined;
190
194
  this._runtimeVersion = undefined;
191
195
  this._localCache = undefined;
196
+ this._apiAtCache.clear();
192
197
  }
193
198
  /**
194
- * @description Clear local cache
199
+ * @description Clear local cache and API at-block cache
200
+ * @param keepMetadataCache Keep the metadata cache, only clear other caches.
195
201
  */
196
- async clearCache() {
197
- await this._localCache?.clear();
202
+ async clearCache(keepMetadataCache = false) {
203
+ if (!keepMetadataCache) {
204
+ await this._localCache?.clear();
205
+ }
206
+ this._apiAtCache.clear();
198
207
  }
199
208
  async doConnect() {
200
209
  // @ts-ignore
@@ -21,7 +21,6 @@ class DedotClient// prettier-end-here
21
21
  _chainSpec;
22
22
  _archive;
23
23
  _txBroadcaster;
24
- #apiAtCache = {};
25
24
  /**
26
25
  * Use factory methods (`create`, `new`) to create `DedotClient` instances.
27
26
  *
@@ -147,7 +146,14 @@ class DedotClient// prettier-end-here
147
146
  this._chainSpec = undefined;
148
147
  this._archive = undefined;
149
148
  this._txBroadcaster = undefined;
150
- this.#apiAtCache = {};
149
+ }
150
+ /**
151
+ * @description Clear local cache, API at-block cache, and ChainHead cache
152
+ * @param keepMetadataCache Keep the metadata cache, only clear other caches.
153
+ */
154
+ async clearCache(keepMetadataCache = false) {
155
+ await super.clearCache(keepMetadataCache);
156
+ this._chainHead?.clearCache();
151
157
  }
152
158
  get query() {
153
159
  return (0, proxychain_js_1.newProxyChain)({
@@ -177,8 +183,9 @@ class DedotClient// prettier-end-here
177
183
  * @param hash
178
184
  */
179
185
  async at(hash) {
180
- if (this.#apiAtCache[hash])
181
- return this.#apiAtCache[hash];
186
+ const cached = this._apiAtCache.get(hash);
187
+ if (cached)
188
+ return cached;
182
189
  let targetVersion;
183
190
  // Try to get block info from ChainHead first (for pinned blocks)
184
191
  const targetBlock = this.chainHead.findBlock(hash);
@@ -192,10 +199,10 @@ class DedotClient// prettier-end-here
192
199
  else {
193
200
  // Block not pinned, try via Archive fallback if supported
194
201
  if (this._archive && (await this._archive.supported())) {
195
- console.warn(`Block ${hash} is not pinned, using Archive for historical access`);
196
202
  try {
197
203
  // Fetch runtime version via Archive
198
204
  const runtimeRaw = await this._archive.call('Core_version', '0x', hash);
205
+ (0, utils_1.assert)(runtimeRaw, 'Runtime Version Not Found');
199
206
  targetVersion = this.toSubstrateRuntimeVersion(codecs_1.$RuntimeVersion.tryDecode(runtimeRaw));
200
207
  }
201
208
  catch (error) {
@@ -228,7 +235,7 @@ class DedotClient// prettier-end-here
228
235
  api.query = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.StorageQueryExecutorV2(api, this.chainHead) });
229
236
  api.call = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.RuntimeApiExecutorV2(api, this.chainHead) });
230
237
  api.view = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.ViewFunctionExecutorV2(api, this.chainHead) });
231
- this.#apiAtCache[hash] = api;
238
+ this._apiAtCache.set(hash, api);
232
239
  return api;
233
240
  }
234
241
  getStorageQuery() {
@@ -49,7 +49,6 @@ class LegacyClient// prettier-end-here
49
49
  extends BaseSubstrateClient_js_1.BaseSubstrateClient {
50
50
  #runtimeSubscriptionUnsub;
51
51
  #healthTimer;
52
- #apiAtCache = {};
53
52
  /**
54
53
  * Use factory methods (`create`, `new`) to create `Dedot` instances.
55
54
  *
@@ -96,7 +95,6 @@ class LegacyClient// prettier-end-here
96
95
  }
97
96
  cleanUp() {
98
97
  super.cleanUp();
99
- this.#apiAtCache = {};
100
98
  this.#healthTimer = undefined;
101
99
  this.#runtimeSubscriptionUnsub = undefined;
102
100
  }
@@ -232,8 +230,9 @@ class LegacyClient// prettier-end-here
232
230
  * @param hash
233
231
  */
234
232
  async at(hash) {
235
- if (this.#apiAtCache[hash])
236
- return this.#apiAtCache[hash];
233
+ const cached = this._apiAtCache.get(hash);
234
+ if (cached)
235
+ return cached;
237
236
  const targetVersion = await this.#getRuntimeVersion(hash);
238
237
  let metadata = this.metadata;
239
238
  let registry = this.registry;
@@ -256,7 +255,7 @@ class LegacyClient// prettier-end-here
256
255
  api.call = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.RuntimeApiExecutor(api) });
257
256
  api.events = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.EventExecutor(api) });
258
257
  api.errors = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.ErrorExecutor(api) });
259
- this.#apiAtCache[hash] = api;
258
+ this._apiAtCache.set(hash, api);
260
259
  return api;
261
260
  }
262
261
  getStorageQuery() {
@@ -1,15 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * Known signed extensions that require external input.
4
- *
5
- * Note: Extensions that don't require external input are automatically handled by FallbackSignedExtension:
6
- * - CheckNonZeroSender
7
- * - CheckWeight
8
- * - PrevalidateAttests
9
- * - StorageWeightReclaim
10
- *
11
- * These extensions have empty struct or tuple types and don't need explicit implementation.
12
- */
13
2
  Object.defineProperty(exports, "__esModule", { value: true });
14
3
  exports.knownSignedExtensions = void 0;
15
4
  const ChargeAssetTxPayment_js_1 = require("./ChargeAssetTxPayment.js");
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Archive = void 0;
4
4
  const utils_1 = require("@dedot/utils");
5
5
  const JsonRpcGroup_js_1 = require("./JsonRpcGroup.js");
6
+ const ARCHIVE_CACHE_CAPACITY = 256;
7
+ const ARCHIVE_CACHE_TTL = 60_000; // 1 minutes - archive data is immutable
6
8
  /**
7
9
  * @name Archive
8
10
  * Archive JSON-RPC methods for accessing historical blockchain data.
@@ -16,7 +18,7 @@ class Archive extends JsonRpcGroup_js_1.JsonRpcGroup {
16
18
  #cache;
17
19
  constructor(client, options) {
18
20
  super(client, { prefix: 'archive', supportedVersions: ['unstable', 'v1'], ...options });
19
- this.#cache = new Map();
21
+ this.#cache = new utils_1.LRUCache(ARCHIVE_CACHE_CAPACITY, ARCHIVE_CACHE_TTL);
20
22
  }
21
23
  /**
22
24
  * Retrieves the body (list of transactions) of a given block.
@@ -38,8 +40,9 @@ class Archive extends JsonRpcGroup_js_1.JsonRpcGroup {
38
40
  async body(hash) {
39
41
  const blockHash = hash || (await this.finalizedHash());
40
42
  const cacheKey = `${blockHash}::body`;
41
- if (this.#cache.has(cacheKey)) {
42
- return this.#cache.get(cacheKey);
43
+ const cached = this.#cache.get(cacheKey);
44
+ if (cached !== null) {
45
+ return cached;
43
46
  }
44
47
  const result = await this.send('body', blockHash);
45
48
  this.#cache.set(cacheKey, result);
@@ -77,8 +80,9 @@ class Archive extends JsonRpcGroup_js_1.JsonRpcGroup {
77
80
  async header(hash) {
78
81
  const blockHash = hash || (await this.finalizedHash());
79
82
  const cacheKey = `${blockHash}::header`;
80
- if (this.#cache.has(cacheKey)) {
81
- return this.#cache.get(cacheKey);
83
+ const cached = this.#cache.get(cacheKey);
84
+ if (cached !== null) {
85
+ return cached;
82
86
  }
83
87
  const result = await this.send('header', blockHash);
84
88
  this.#cache.set(cacheKey, result);
@@ -141,8 +145,9 @@ class Archive extends JsonRpcGroup_js_1.JsonRpcGroup {
141
145
  async call(func, params, hash) {
142
146
  const blockHash = hash || (await this.finalizedHash());
143
147
  const cacheKey = `${blockHash}::call::${func}::${params}`;
144
- if (this.#cache.has(cacheKey)) {
145
- return this.#cache.get(cacheKey);
148
+ const cached = this.#cache.get(cacheKey);
149
+ if (cached !== null) {
150
+ return cached;
146
151
  }
147
152
  const result = await this.send('call', blockHash, func, params);
148
153
  if (!result.success) {
@@ -189,8 +194,9 @@ class Archive extends JsonRpcGroup_js_1.JsonRpcGroup {
189
194
  // Generate cache key
190
195
  const cacheKey = `${blockHash}::storage::${JSON.stringify(items)}::${childTrie ?? null}`;
191
196
  // Check cache
192
- if (this.#cache.has(cacheKey)) {
193
- return resolve(this.#cache.get(cacheKey));
197
+ const cached = this.#cache.get(cacheKey);
198
+ if (cached !== null) {
199
+ return resolve(cached);
194
200
  }
195
201
  this.#storageSubscription(items, childTrie || null, (event) => {
196
202
  switch (event.event) {
@@ -7,6 +7,8 @@ const JsonRpcGroup_js_1 = require("../JsonRpcGroup.js");
7
7
  const BlockUsage_js_1 = require("./BlockUsage.js");
8
8
  const error_js_1 = require("./error.js");
9
9
  exports.MIN_FINALIZED_QUEUE_SIZE = 10; // finalized queue size
10
+ const CHAINHEAD_CACHE_CAPACITY = 256;
11
+ const CHAINHEAD_CACHE_TTL = 30_000; // 30 seconds
10
12
  class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
11
13
  #unsub;
12
14
  #subscriptionId;
@@ -43,7 +45,7 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
43
45
  this.#followResponseQueue = new utils_1.AsyncQueue();
44
46
  this.#retryQueue = new utils_1.AsyncQueue();
45
47
  this.#blockUsage = new BlockUsage_js_1.BlockUsage();
46
- this.#cache = new Map();
48
+ this.#cache = new utils_1.LRUCache(CHAINHEAD_CACHE_CAPACITY, CHAINHEAD_CACHE_TTL);
47
49
  // This helps us to not accidentally putting too much stress on the JSON-RPC server, especially smoldot/light-client
48
50
  this.#operationQueue = new utils_1.ThrottleQueue(this.#__unsafe__isSmoldot() ? 25 : 250);
49
51
  }
@@ -245,8 +247,10 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
245
247
  if (!this.isPinned(hash))
246
248
  return;
247
249
  delete this.#pinnedBlocks[hash];
248
- // clear cache
249
- Array.from(this.#cache.keys())
250
+ // Clear cache entries related to the pruned block
251
+ // Filter and remove only cache entries for this specific block
252
+ this.#cache
253
+ .keys()
250
254
  .filter((key) => key.startsWith(`${hash}::`))
251
255
  .forEach((key) => this.#cache.delete(key));
252
256
  });
@@ -394,7 +398,6 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
394
398
  catch (error) {
395
399
  if (error instanceof error_js_1.ChainHeadBlockNotPinnedError && this.#archive) {
396
400
  const errorHash = error.hash;
397
- console.warn(`Block ${errorHash} not pinned in ChainHead, falling back to Archive`);
398
401
  return await fallback(this.#archive, errorHash);
399
402
  }
400
403
  throw error;
@@ -454,7 +457,7 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
454
457
  this.#followResponseQueue.clear();
455
458
  this.#retryQueue.clear();
456
459
  this.#blockUsage.clear();
457
- this.#cache.clear();
460
+ this.clearCache();
458
461
  this.#operationQueue.cancel();
459
462
  }
460
463
  async #ensureFollowed() {
@@ -532,8 +535,9 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
532
535
  const operation = async () => {
533
536
  const atHash = this.#ensurePinnedHash(at);
534
537
  const cacheKey = `${atHash}::body`;
535
- if (this.#cache.has(cacheKey)) {
536
- return this.#cache.get(cacheKey);
538
+ const cached = this.#cache.get(cacheKey);
539
+ if (cached) {
540
+ return cached;
537
541
  }
538
542
  const bodyOperation = async () => {
539
543
  await this.#ensureFollowed();
@@ -571,8 +575,9 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
571
575
  const operation = async () => {
572
576
  const atHash = this.#ensurePinnedHash(at);
573
577
  const cacheKey = `${atHash}::call::${func}::${params}`;
574
- if (this.#cache.has(cacheKey)) {
575
- return this.#cache.get(cacheKey);
578
+ const cached = this.#cache.get(cacheKey);
579
+ if (cached) {
580
+ return cached;
576
581
  }
577
582
  const callOperation = async () => {
578
583
  await this.#ensureFollowed();
@@ -603,8 +608,9 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
603
608
  const operation = async () => {
604
609
  const hash = this.#ensurePinnedHash(at);
605
610
  const cacheKey = `${hash}::header`;
606
- if (this.#cache.has(cacheKey)) {
607
- return this.#cache.get(cacheKey);
611
+ const cached = this.#cache.get(cacheKey);
612
+ if (cached) {
613
+ return cached;
608
614
  }
609
615
  const resp = await this.#getHeader(hash);
610
616
  this.#cache.set(cacheKey, resp);
@@ -627,8 +633,9 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
627
633
  try {
628
634
  // JSON.stringify(items) might get big, we probably should do a twox hashing in such case
629
635
  const cacheKey = `${hash}::storage::${JSON.stringify(items)}::${childTrie ?? null}`;
630
- if (this.#cache.has(cacheKey)) {
631
- return this.#cache.get(cacheKey);
636
+ const cached = this.#cache.get(cacheKey);
637
+ if (cached) {
638
+ return cached;
632
639
  }
633
640
  this.#blockUsage.use(hash);
634
641
  let results = [];
@@ -713,5 +720,19 @@ class ChainHead extends JsonRpcGroup_js_1.JsonRpcGroup {
713
720
  // @ts-ignore a trick internally to check whether a provider is using smoldot connection
714
721
  return typeof this.client.provider['chain'] === 'function';
715
722
  }
723
+ /**
724
+ * Clears the internal cache used for storing query results (both chainHead & archive instances)
725
+ * This can be useful for memory management or when you want to force fresh data retrieval.
726
+ *
727
+ * @example
728
+ * ```typescript
729
+ * // Clear all cached results
730
+ * chainHead.clearCache();
731
+ * ```
732
+ */
733
+ clearCache() {
734
+ this.#cache.clear();
735
+ this.#archive?.clearCache();
736
+ }
716
737
  }
717
738
  exports.ChainHead = ChainHead;
@@ -2,7 +2,7 @@ import { BlockHash, Hash, Metadata, PortableRegistry, RuntimeVersion } from '@de
2
2
  import type { JsonRpcProvider } from '@dedot/providers';
3
3
  import { type IStorage } from '@dedot/storage';
4
4
  import { Callback, GenericStorageQuery, GenericSubstrateApi, InjectedSigner, Query, QueryFnResult, RpcVersion, Unsub, VersionedGenericSubstrateApi } from '@dedot/types';
5
- import { Deferred } from '@dedot/utils';
5
+ import { Deferred, LRUCache } from '@dedot/utils';
6
6
  import type { SubstrateApi } from '../chaintypes/index.js';
7
7
  import { JsonRpcClient } from '../json-rpc/index.js';
8
8
  import { BaseStorageQuery } from '../storage/index.js';
@@ -15,12 +15,13 @@ export declare function ensurePresence<T>(value: T): NonNullable<T>;
15
15
  export declare abstract class BaseSubstrateClient<Rv extends RpcVersion, ChainApi extends VersionedGenericSubstrateApi = SubstrateApi, Events extends string = ApiEvent> extends JsonRpcClient<ChainApi, Events> implements ISubstrateClient<ChainApi[Rv], Events> {
16
16
  rpcVersion: RpcVersion;
17
17
  protected _options: ApiOptions;
18
- protected _registry?: PortableRegistry<ChainApi[Rv]>;
18
+ protected _registry?: PortableRegistry<ChainApi[Rv]['types']>;
19
19
  protected _metadata?: Metadata;
20
20
  protected _genesisHash?: Hash;
21
21
  protected _runtimeVersion?: SubstrateRuntimeVersion;
22
22
  protected _localCache?: IStorage;
23
23
  protected _runtimeUpgrading?: Deferred<void>;
24
+ protected _apiAtCache: LRUCache;
24
25
  protected constructor(rpcVersion: RpcVersion, options: JsonRpcClientOptions | JsonRpcProvider);
25
26
  protected normalizeOptions(options: ApiOptions | JsonRpcProvider): ApiOptions;
26
27
  protected initializeLocalCache(): Promise<void>;
@@ -37,9 +38,10 @@ export declare abstract class BaseSubstrateClient<Rv extends RpcVersion, ChainAp
37
38
  protected fetchMetadata(hash?: BlockHash, runtime?: SubstrateRuntimeVersion): Promise<Metadata>;
38
39
  protected cleanUp(): void;
39
40
  /**
40
- * @description Clear local cache
41
+ * @description Clear local cache and API at-block cache
42
+ * @param keepMetadataCache Keep the metadata cache, only clear other caches.
41
43
  */
42
- clearCache(): Promise<void>;
44
+ clearCache(keepMetadataCache?: boolean): Promise<void>;
43
45
  protected doConnect(): Promise<this>;
44
46
  protected onConnected: () => Promise<void>;
45
47
  protected onDisconnected: () => Promise<void>;
@@ -61,7 +63,7 @@ export declare abstract class BaseSubstrateClient<Rv extends RpcVersion, ChainAp
61
63
  disconnect(): Promise<void>;
62
64
  get options(): ApiOptions;
63
65
  get metadata(): Metadata;
64
- get registry(): PortableRegistry<ChainApi[Rv]>;
66
+ get registry(): PortableRegistry<ChainApi[Rv]['types']>;
65
67
  get genesisHash(): Hash;
66
68
  get runtimeVersion(): SubstrateRuntimeVersion;
67
69
  getRuntimeVersion(): Promise<SubstrateRuntimeVersion>;
@@ -1,12 +1,14 @@
1
1
  import { $Metadata, PortableRegistry } from '@dedot/codecs';
2
2
  import { LocalStorage } from '@dedot/storage';
3
- import { calcRuntimeApiHash, deferred, ensurePresence as _ensurePresence, u8aToHex } from '@dedot/utils';
3
+ import { calcRuntimeApiHash, deferred, ensurePresence as _ensurePresence, u8aToHex, LRUCache, } from '@dedot/utils';
4
4
  import { ConstantExecutor, ErrorExecutor, EventExecutor } from '../executor/index.js';
5
5
  import { isJsonRpcProvider, JsonRpcClient } from '../json-rpc/index.js';
6
6
  import { newProxyChain } from '../proxychain.js';
7
7
  import { QueryableStorage } from '../storage/index.js';
8
8
  const SUPPORTED_METADATA_VERSIONS = [16, 15, 14];
9
9
  const MetadataApiHash = calcRuntimeApiHash('Metadata'); // 0x37e397fc7c91f5e4
10
+ const API_AT_CACHE_CAPACITY = 64;
11
+ const API_AT_CACHE_TTL = 300_000; // 5 minutes
10
12
  const MESSAGE = 'Make sure to call `.connect()` method first before using the API interfaces.';
11
13
  export function ensurePresence(value) {
12
14
  return _ensurePresence(value, MESSAGE);
@@ -24,10 +26,12 @@ export class BaseSubstrateClient extends JsonRpcClient {
24
26
  _runtimeVersion;
25
27
  _localCache;
26
28
  _runtimeUpgrading;
29
+ _apiAtCache;
27
30
  constructor(rpcVersion, options) {
28
31
  super(options);
29
32
  this.rpcVersion = rpcVersion;
30
33
  this._options = this.normalizeOptions(options);
34
+ this._apiAtCache = new LRUCache(API_AT_CACHE_CAPACITY, API_AT_CACHE_TTL);
31
35
  }
32
36
  /// --- Internal logics
33
37
  normalizeOptions(options) {
@@ -185,12 +189,17 @@ export class BaseSubstrateClient extends JsonRpcClient {
185
189
  this._genesisHash = undefined;
186
190
  this._runtimeVersion = undefined;
187
191
  this._localCache = undefined;
192
+ this._apiAtCache.clear();
188
193
  }
189
194
  /**
190
- * @description Clear local cache
195
+ * @description Clear local cache and API at-block cache
196
+ * @param keepMetadataCache Keep the metadata cache, only clear other caches.
191
197
  */
192
- async clearCache() {
193
- await this._localCache?.clear();
198
+ async clearCache(keepMetadataCache = false) {
199
+ if (!keepMetadataCache) {
200
+ await this._localCache?.clear();
201
+ }
202
+ this._apiAtCache.clear();
194
203
  }
195
204
  async doConnect() {
196
205
  // @ts-ignore
@@ -50,6 +50,11 @@ export declare class DedotClient<ChainApi extends VersionedGenericSubstrateApi =
50
50
  protected beforeDisconnect(): Promise<void>;
51
51
  protected onDisconnected: () => Promise<void>;
52
52
  protected cleanUp(): void;
53
+ /**
54
+ * @description Clear local cache, API at-block cache, and ChainHead cache
55
+ * @param keepMetadataCache Keep the metadata cache, only clear other caches.
56
+ */
57
+ clearCache(keepMetadataCache?: boolean): Promise<void>;
53
58
  get query(): ChainApi[RpcV2]['query'];
54
59
  get view(): ChainApi[RpcV2]['view'];
55
60
  get call(): ChainApi[RpcV2]['call'];
@@ -18,7 +18,6 @@ export class DedotClient// prettier-end-here
18
18
  _chainSpec;
19
19
  _archive;
20
20
  _txBroadcaster;
21
- #apiAtCache = {};
22
21
  /**
23
22
  * Use factory methods (`create`, `new`) to create `DedotClient` instances.
24
23
  *
@@ -144,7 +143,14 @@ export class DedotClient// prettier-end-here
144
143
  this._chainSpec = undefined;
145
144
  this._archive = undefined;
146
145
  this._txBroadcaster = undefined;
147
- this.#apiAtCache = {};
146
+ }
147
+ /**
148
+ * @description Clear local cache, API at-block cache, and ChainHead cache
149
+ * @param keepMetadataCache Keep the metadata cache, only clear other caches.
150
+ */
151
+ async clearCache(keepMetadataCache = false) {
152
+ await super.clearCache(keepMetadataCache);
153
+ this._chainHead?.clearCache();
148
154
  }
149
155
  get query() {
150
156
  return newProxyChain({
@@ -174,8 +180,9 @@ export class DedotClient// prettier-end-here
174
180
  * @param hash
175
181
  */
176
182
  async at(hash) {
177
- if (this.#apiAtCache[hash])
178
- return this.#apiAtCache[hash];
183
+ const cached = this._apiAtCache.get(hash);
184
+ if (cached)
185
+ return cached;
179
186
  let targetVersion;
180
187
  // Try to get block info from ChainHead first (for pinned blocks)
181
188
  const targetBlock = this.chainHead.findBlock(hash);
@@ -189,10 +196,10 @@ export class DedotClient// prettier-end-here
189
196
  else {
190
197
  // Block not pinned, try via Archive fallback if supported
191
198
  if (this._archive && (await this._archive.supported())) {
192
- console.warn(`Block ${hash} is not pinned, using Archive for historical access`);
193
199
  try {
194
200
  // Fetch runtime version via Archive
195
201
  const runtimeRaw = await this._archive.call('Core_version', '0x', hash);
202
+ assert(runtimeRaw, 'Runtime Version Not Found');
196
203
  targetVersion = this.toSubstrateRuntimeVersion($RuntimeVersion.tryDecode(runtimeRaw));
197
204
  }
198
205
  catch (error) {
@@ -225,7 +232,7 @@ export class DedotClient// prettier-end-here
225
232
  api.query = newProxyChain({ executor: new StorageQueryExecutorV2(api, this.chainHead) });
226
233
  api.call = newProxyChain({ executor: new RuntimeApiExecutorV2(api, this.chainHead) });
227
234
  api.view = newProxyChain({ executor: new ViewFunctionExecutorV2(api, this.chainHead) });
228
- this.#apiAtCache[hash] = api;
235
+ this._apiAtCache.set(hash, api);
229
236
  return api;
230
237
  }
231
238
  getStorageQuery() {
@@ -46,7 +46,6 @@ export class LegacyClient// prettier-end-here
46
46
  extends BaseSubstrateClient {
47
47
  #runtimeSubscriptionUnsub;
48
48
  #healthTimer;
49
- #apiAtCache = {};
50
49
  /**
51
50
  * Use factory methods (`create`, `new`) to create `Dedot` instances.
52
51
  *
@@ -93,7 +92,6 @@ export class LegacyClient// prettier-end-here
93
92
  }
94
93
  cleanUp() {
95
94
  super.cleanUp();
96
- this.#apiAtCache = {};
97
95
  this.#healthTimer = undefined;
98
96
  this.#runtimeSubscriptionUnsub = undefined;
99
97
  }
@@ -229,8 +227,9 @@ export class LegacyClient// prettier-end-here
229
227
  * @param hash
230
228
  */
231
229
  async at(hash) {
232
- if (this.#apiAtCache[hash])
233
- return this.#apiAtCache[hash];
230
+ const cached = this._apiAtCache.get(hash);
231
+ if (cached)
232
+ return cached;
234
233
  const targetVersion = await this.#getRuntimeVersion(hash);
235
234
  let metadata = this.metadata;
236
235
  let registry = this.registry;
@@ -253,7 +252,7 @@ export class LegacyClient// prettier-end-here
253
252
  api.call = newProxyChain({ executor: new RuntimeApiExecutor(api) });
254
253
  api.events = newProxyChain({ executor: new EventExecutor(api) });
255
254
  api.errors = newProxyChain({ executor: new ErrorExecutor(api) });
256
- this.#apiAtCache[hash] = api;
255
+ this._apiAtCache.set(hash, api);
257
256
  return api;
258
257
  }
259
258
  getStorageQuery() {
@@ -16,7 +16,7 @@ export declare abstract class Executor<ChainApi extends GenericSubstrateApi = Ge
16
16
  readonly client: ISubstrateClientAt<ChainApi> | ISubstrateClient<ChainApi, any>;
17
17
  constructor(client: ISubstrateClientAt<ChainApi> | ISubstrateClient<ChainApi, any>, atBlockHash?: BlockHash);
18
18
  get atBlockHash(): any;
19
- get registry(): import("@dedot/codecs").PortableRegistry<ChainApi>;
19
+ get registry(): import("@dedot/codecs").PortableRegistry<ChainApi["types"]>;
20
20
  get metadata(): {
21
21
  types: {
22
22
  id: number;
@@ -1,14 +1,3 @@
1
- /**
2
- * Known signed extensions that require external input.
3
- *
4
- * Note: Extensions that don't require external input are automatically handled by FallbackSignedExtension:
5
- * - CheckNonZeroSender
6
- * - CheckWeight
7
- * - PrevalidateAttests
8
- * - StorageWeightReclaim
9
- *
10
- * These extensions have empty struct or tuple types and don't need explicit implementation.
11
- */
12
1
  import { ChargeAssetTxPayment } from './ChargeAssetTxPayment.js';
13
2
  import { ChargeTransactionPayment } from './ChargeTransactionPayment.js';
14
3
  import { CheckGenesis } from './CheckGenesis.js';
@@ -1,5 +1,7 @@
1
- import { DedotError } from '@dedot/utils';
1
+ import { DedotError, LRUCache } from '@dedot/utils';
2
2
  import { JsonRpcGroup } from './JsonRpcGroup.js';
3
+ const ARCHIVE_CACHE_CAPACITY = 256;
4
+ const ARCHIVE_CACHE_TTL = 60_000; // 1 minutes - archive data is immutable
3
5
  /**
4
6
  * @name Archive
5
7
  * Archive JSON-RPC methods for accessing historical blockchain data.
@@ -13,7 +15,7 @@ export class Archive extends JsonRpcGroup {
13
15
  #cache;
14
16
  constructor(client, options) {
15
17
  super(client, { prefix: 'archive', supportedVersions: ['unstable', 'v1'], ...options });
16
- this.#cache = new Map();
18
+ this.#cache = new LRUCache(ARCHIVE_CACHE_CAPACITY, ARCHIVE_CACHE_TTL);
17
19
  }
18
20
  /**
19
21
  * Retrieves the body (list of transactions) of a given block.
@@ -35,8 +37,9 @@ export class Archive extends JsonRpcGroup {
35
37
  async body(hash) {
36
38
  const blockHash = hash || (await this.finalizedHash());
37
39
  const cacheKey = `${blockHash}::body`;
38
- if (this.#cache.has(cacheKey)) {
39
- return this.#cache.get(cacheKey);
40
+ const cached = this.#cache.get(cacheKey);
41
+ if (cached !== null) {
42
+ return cached;
40
43
  }
41
44
  const result = await this.send('body', blockHash);
42
45
  this.#cache.set(cacheKey, result);
@@ -74,8 +77,9 @@ export class Archive extends JsonRpcGroup {
74
77
  async header(hash) {
75
78
  const blockHash = hash || (await this.finalizedHash());
76
79
  const cacheKey = `${blockHash}::header`;
77
- if (this.#cache.has(cacheKey)) {
78
- return this.#cache.get(cacheKey);
80
+ const cached = this.#cache.get(cacheKey);
81
+ if (cached !== null) {
82
+ return cached;
79
83
  }
80
84
  const result = await this.send('header', blockHash);
81
85
  this.#cache.set(cacheKey, result);
@@ -138,8 +142,9 @@ export class Archive extends JsonRpcGroup {
138
142
  async call(func, params, hash) {
139
143
  const blockHash = hash || (await this.finalizedHash());
140
144
  const cacheKey = `${blockHash}::call::${func}::${params}`;
141
- if (this.#cache.has(cacheKey)) {
142
- return this.#cache.get(cacheKey);
145
+ const cached = this.#cache.get(cacheKey);
146
+ if (cached !== null) {
147
+ return cached;
143
148
  }
144
149
  const result = await this.send('call', blockHash, func, params);
145
150
  if (!result.success) {
@@ -186,8 +191,9 @@ export class Archive extends JsonRpcGroup {
186
191
  // Generate cache key
187
192
  const cacheKey = `${blockHash}::storage::${JSON.stringify(items)}::${childTrie ?? null}`;
188
193
  // Check cache
189
- if (this.#cache.has(cacheKey)) {
190
- return resolve(this.#cache.get(cacheKey));
194
+ const cached = this.#cache.get(cacheKey);
195
+ if (cached !== null) {
196
+ return resolve(cached);
191
197
  }
192
198
  this.#storageSubscription(items, childTrie || null, (event) => {
193
199
  switch (event.event) {
@@ -77,4 +77,15 @@ export declare class ChainHead extends JsonRpcGroup<ChainHeadEvent> {
77
77
  * @protected
78
78
  */
79
79
  protected unpin(hashes: BlockHash | BlockHash[]): Promise<void>;
80
+ /**
81
+ * Clears the internal cache used for storing query results (both chainHead & archive instances)
82
+ * This can be useful for memory management or when you want to force fresh data retrieval.
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * // Clear all cached results
87
+ * chainHead.clearCache();
88
+ * ```
89
+ */
90
+ clearCache(): void;
80
91
  }
@@ -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;
@@ -40,7 +42,7 @@ export class ChainHead extends JsonRpcGroup {
40
42
  this.#followResponseQueue = new AsyncQueue();
41
43
  this.#retryQueue = new AsyncQueue();
42
44
  this.#blockUsage = new BlockUsage();
43
- this.#cache = new Map();
45
+ this.#cache = new LRUCache(CHAINHEAD_CACHE_CAPACITY, CHAINHEAD_CACHE_TTL);
44
46
  // This helps us to not accidentally putting too much stress on the JSON-RPC server, especially smoldot/light-client
45
47
  this.#operationQueue = new ThrottleQueue(this.#__unsafe__isSmoldot() ? 25 : 250);
46
48
  }
@@ -242,8 +244,10 @@ export class ChainHead extends JsonRpcGroup {
242
244
  if (!this.isPinned(hash))
243
245
  return;
244
246
  delete this.#pinnedBlocks[hash];
245
- // clear cache
246
- Array.from(this.#cache.keys())
247
+ // Clear cache entries related to the pruned block
248
+ // Filter and remove only cache entries for this specific block
249
+ this.#cache
250
+ .keys()
247
251
  .filter((key) => key.startsWith(`${hash}::`))
248
252
  .forEach((key) => this.#cache.delete(key));
249
253
  });
@@ -391,7 +395,6 @@ export class ChainHead extends JsonRpcGroup {
391
395
  catch (error) {
392
396
  if (error instanceof ChainHeadBlockNotPinnedError && this.#archive) {
393
397
  const errorHash = error.hash;
394
- console.warn(`Block ${errorHash} not pinned in ChainHead, falling back to Archive`);
395
398
  return await fallback(this.#archive, errorHash);
396
399
  }
397
400
  throw error;
@@ -451,7 +454,7 @@ export class ChainHead extends JsonRpcGroup {
451
454
  this.#followResponseQueue.clear();
452
455
  this.#retryQueue.clear();
453
456
  this.#blockUsage.clear();
454
- this.#cache.clear();
457
+ this.clearCache();
455
458
  this.#operationQueue.cancel();
456
459
  }
457
460
  async #ensureFollowed() {
@@ -529,8 +532,9 @@ export class ChainHead extends JsonRpcGroup {
529
532
  const operation = async () => {
530
533
  const atHash = this.#ensurePinnedHash(at);
531
534
  const cacheKey = `${atHash}::body`;
532
- if (this.#cache.has(cacheKey)) {
533
- return this.#cache.get(cacheKey);
535
+ const cached = this.#cache.get(cacheKey);
536
+ if (cached) {
537
+ return cached;
534
538
  }
535
539
  const bodyOperation = async () => {
536
540
  await this.#ensureFollowed();
@@ -568,8 +572,9 @@ export class ChainHead extends JsonRpcGroup {
568
572
  const operation = async () => {
569
573
  const atHash = this.#ensurePinnedHash(at);
570
574
  const cacheKey = `${atHash}::call::${func}::${params}`;
571
- if (this.#cache.has(cacheKey)) {
572
- return this.#cache.get(cacheKey);
575
+ const cached = this.#cache.get(cacheKey);
576
+ if (cached) {
577
+ return cached;
573
578
  }
574
579
  const callOperation = async () => {
575
580
  await this.#ensureFollowed();
@@ -600,8 +605,9 @@ export class ChainHead extends JsonRpcGroup {
600
605
  const operation = async () => {
601
606
  const hash = this.#ensurePinnedHash(at);
602
607
  const cacheKey = `${hash}::header`;
603
- if (this.#cache.has(cacheKey)) {
604
- return this.#cache.get(cacheKey);
608
+ const cached = this.#cache.get(cacheKey);
609
+ if (cached) {
610
+ return cached;
605
611
  }
606
612
  const resp = await this.#getHeader(hash);
607
613
  this.#cache.set(cacheKey, resp);
@@ -624,8 +630,9 @@ export class ChainHead extends JsonRpcGroup {
624
630
  try {
625
631
  // JSON.stringify(items) might get big, we probably should do a twox hashing in such case
626
632
  const cacheKey = `${hash}::storage::${JSON.stringify(items)}::${childTrie ?? null}`;
627
- if (this.#cache.has(cacheKey)) {
628
- return this.#cache.get(cacheKey);
633
+ const cached = this.#cache.get(cacheKey);
634
+ if (cached) {
635
+ return cached;
629
636
  }
630
637
  this.#blockUsage.use(hash);
631
638
  let results = [];
@@ -710,4 +717,18 @@ export class ChainHead extends JsonRpcGroup {
710
717
  // @ts-ignore a trick internally to check whether a provider is using smoldot connection
711
718
  return typeof this.client.provider['chain'] === 'function';
712
719
  }
720
+ /**
721
+ * Clears the internal cache used for storing query results (both chainHead & archive instances)
722
+ * This can be useful for memory management or when you want to force fresh data retrieval.
723
+ *
724
+ * @example
725
+ * ```typescript
726
+ * // Clear all cached results
727
+ * chainHead.clearCache();
728
+ * ```
729
+ */
730
+ clearCache() {
731
+ this.#cache.clear();
732
+ this.#archive?.clearCache();
733
+ }
713
734
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dedot/api",
3
- "version": "0.15.3-next.65898ecf.10+65898ecf",
3
+ "version": "0.16.1-next.dd70d277.9+dd70d277",
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.15.3-next.65898ecf.10+65898ecf",
17
- "@dedot/providers": "0.15.3-next.65898ecf.10+65898ecf",
18
- "@dedot/runtime-specs": "0.15.3-next.65898ecf.10+65898ecf",
19
- "@dedot/shape": "0.15.3-next.65898ecf.10+65898ecf",
20
- "@dedot/storage": "0.15.3-next.65898ecf.10+65898ecf",
21
- "@dedot/types": "0.15.3-next.65898ecf.10+65898ecf",
22
- "@dedot/utils": "0.15.3-next.65898ecf.10+65898ecf"
16
+ "@dedot/codecs": "0.16.1-next.dd70d277.9+dd70d277",
17
+ "@dedot/providers": "0.16.1-next.dd70d277.9+dd70d277",
18
+ "@dedot/runtime-specs": "0.16.1-next.dd70d277.9+dd70d277",
19
+ "@dedot/shape": "0.16.1-next.dd70d277.9+dd70d277",
20
+ "@dedot/storage": "0.16.1-next.dd70d277.9+dd70d277",
21
+ "@dedot/types": "0.16.1-next.dd70d277.9+dd70d277",
22
+ "@dedot/utils": "0.16.1-next.dd70d277.9+dd70d277"
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": "65898ecf2226162fc6632d3f4f64ad5fe1179643",
51
+ "gitHead": "dd70d2772f30eaa72ec9f61d1af9597211c364c5",
52
52
  "module": "./index.js",
53
53
  "types": "./index.d.ts"
54
54
  }
@@ -1,6 +1,6 @@
1
- import { ISubstrateClient, ISubstrateClientAt } from '@dedot/api/types';
2
1
  import { BlockHash, StorageData, StorageKey } from '@dedot/codecs';
3
2
  import type { Callback, Unsub } from '@dedot/types';
3
+ import { ISubstrateClient, ISubstrateClientAt } from '../types.js';
4
4
  /**
5
5
  * @name BaseStorageQuery
6
6
  * @description
@@ -1,6 +1,6 @@
1
- import { DedotClient } from '@dedot/api/client';
2
1
  import { BlockHash, StorageData, StorageKey } from '@dedot/codecs';
3
2
  import type { Callback, Unsub } from '@dedot/types';
3
+ import { DedotClient } from '../client/DedotClient.js';
4
4
  import { BaseStorageQuery } from './BaseStorageQuery.js';
5
5
  /**
6
6
  * @name NewStorageQuery
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;
@@ -91,7 +91,7 @@ export interface IGenericSubstrateClient<ChainApi extends GenericSubstrateApi =
91
91
  genesisHash: Hash;
92
92
  runtimeVersion: SubstrateRuntimeVersion;
93
93
  metadata: Metadata;
94
- registry: PortableRegistry<ChainApi>;
94
+ registry: PortableRegistry<ChainApi['types']>;
95
95
  rpc: ChainApi['rpc'];
96
96
  consts: ChainApi['consts'];
97
97
  query: ChainApi['query'];