@dedot/api 0.18.8 → 1.0.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.
Files changed (102) hide show
  1. package/chaintypes/substrate/consts.d.ts +2 -2
  2. package/chaintypes/substrate/consts.js +1 -0
  3. package/chaintypes/substrate/errors.d.ts +909 -909
  4. package/chaintypes/substrate/errors.js +1 -0
  5. package/chaintypes/substrate/events.d.ts +664 -664
  6. package/chaintypes/substrate/events.js +1 -0
  7. package/chaintypes/substrate/index.d.ts +13 -16
  8. package/chaintypes/substrate/index.js +1 -0
  9. package/chaintypes/substrate/json-rpc.d.ts +2 -2
  10. package/chaintypes/substrate/json-rpc.js +1 -0
  11. package/chaintypes/substrate/query.d.ts +509 -527
  12. package/chaintypes/substrate/query.js +1 -0
  13. package/chaintypes/substrate/runtime.d.ts +123 -123
  14. package/chaintypes/substrate/runtime.js +1 -0
  15. package/chaintypes/substrate/tx.d.ts +1311 -1311
  16. package/chaintypes/substrate/tx.js +1 -0
  17. package/chaintypes/substrate/types.js +1 -0
  18. package/chaintypes/substrate/view-functions.d.ts +2 -2
  19. package/chaintypes/substrate/view-functions.js +1 -0
  20. package/cjs/chaintypes/substrate/consts.js +1 -0
  21. package/cjs/chaintypes/substrate/errors.js +1 -0
  22. package/cjs/chaintypes/substrate/events.js +1 -0
  23. package/cjs/chaintypes/substrate/index.js +1 -0
  24. package/cjs/chaintypes/substrate/json-rpc.js +1 -0
  25. package/cjs/chaintypes/substrate/query.js +1 -0
  26. package/cjs/chaintypes/substrate/runtime.js +1 -0
  27. package/cjs/chaintypes/substrate/tx.js +1 -0
  28. package/cjs/chaintypes/substrate/types.js +1 -0
  29. package/cjs/chaintypes/substrate/view-functions.js +1 -0
  30. package/cjs/client/BaseSubstrateClient.js +45 -2
  31. package/cjs/client/DedotClient.js +356 -224
  32. package/cjs/client/LegacyClient.js +99 -23
  33. package/cjs/client/V2Client.js +316 -0
  34. package/cjs/client/explorer/LegacyBlockExplorer.js +263 -0
  35. package/cjs/client/explorer/V2BlockExplorer.js +74 -0
  36. package/cjs/client/explorer/index.js +18 -0
  37. package/cjs/client/utils.js +57 -0
  38. package/cjs/executor/EventExecutor.js +1 -0
  39. package/cjs/executor/RuntimeApiExecutor.js +49 -2
  40. package/cjs/executor/StorageQueryExecutor.js +114 -2
  41. package/cjs/executor/ViewFunctionExecutor.js +21 -2
  42. package/cjs/executor/v2/StorageQueryExecutorV2.js +7 -1
  43. package/cjs/executor/validation-helpers.js +181 -0
  44. package/cjs/extrinsic/submittable/BaseSubmittableExtrinsic.js +86 -2
  45. package/cjs/extrinsic/submittable/SubmittableExtrinsic.js +38 -16
  46. package/cjs/extrinsic/submittable/SubmittableExtrinsicV2.js +12 -2
  47. package/cjs/json-rpc/group/ChainHead/ChainHead.js +226 -21
  48. package/cjs/storage/QueryableStorage.js +1 -0
  49. package/client/BaseSubstrateClient.d.ts +34 -18
  50. package/client/BaseSubstrateClient.js +47 -4
  51. package/client/DedotClient.d.ts +346 -49
  52. package/client/DedotClient.js +356 -224
  53. package/client/LegacyClient.d.ts +22 -17
  54. package/client/LegacyClient.js +101 -25
  55. package/client/V2Client.d.ts +75 -0
  56. package/client/V2Client.js +312 -0
  57. package/client/explorer/LegacyBlockExplorer.d.ts +68 -0
  58. package/client/explorer/LegacyBlockExplorer.js +259 -0
  59. package/client/explorer/V2BlockExplorer.d.ts +40 -0
  60. package/client/explorer/V2BlockExplorer.js +70 -0
  61. package/client/explorer/index.d.ts +2 -0
  62. package/client/explorer/index.js +2 -0
  63. package/client/utils.d.ts +18 -0
  64. package/client/utils.js +52 -0
  65. package/executor/ConstantExecutor.d.ts +1 -2
  66. package/executor/ErrorExecutor.d.ts +2 -2
  67. package/executor/EventExecutor.d.ts +2 -2
  68. package/executor/EventExecutor.js +1 -0
  69. package/executor/Executor.d.ts +4 -5
  70. package/executor/RuntimeApiExecutor.d.ts +2 -2
  71. package/executor/RuntimeApiExecutor.js +27 -3
  72. package/executor/StorageQueryExecutor.d.ts +3 -2
  73. package/executor/StorageQueryExecutor.js +92 -3
  74. package/executor/TxExecutor.d.ts +2 -2
  75. package/executor/ViewFunctionExecutor.d.ts +2 -2
  76. package/executor/ViewFunctionExecutor.js +22 -3
  77. package/executor/v2/RuntimeApiExecutorV2.d.ts +2 -3
  78. package/executor/v2/StorageQueryExecutorV2.d.ts +3 -3
  79. package/executor/v2/StorageQueryExecutorV2.js +8 -2
  80. package/executor/v2/TxExecutorV2.d.ts +5 -5
  81. package/executor/v2/ViewFunctionExecutorV2.d.ts +2 -3
  82. package/executor/validation-helpers.d.ts +36 -0
  83. package/executor/validation-helpers.js +174 -0
  84. package/extrinsic/extensions/SignedExtension.d.ts +1 -1
  85. package/extrinsic/submittable/BaseSubmittableExtrinsic.d.ts +7 -3
  86. package/extrinsic/submittable/BaseSubmittableExtrinsic.js +64 -3
  87. package/extrinsic/submittable/SubmittableExtrinsic.d.ts +4 -1
  88. package/extrinsic/submittable/SubmittableExtrinsic.js +39 -17
  89. package/extrinsic/submittable/SubmittableExtrinsicV2.d.ts +6 -3
  90. package/extrinsic/submittable/SubmittableExtrinsicV2.js +13 -3
  91. package/json-rpc/JsonRpcClient.d.ts +6 -6
  92. package/json-rpc/group/Archive.d.ts +1 -1
  93. package/json-rpc/group/ChainHead/ChainHead.d.ts +18 -2
  94. package/json-rpc/group/ChainHead/ChainHead.js +226 -21
  95. package/json-rpc/group/ChainSpec.d.ts +3 -3
  96. package/json-rpc/group/Transaction.d.ts +1 -1
  97. package/json-rpc/group/TransactionWatch.d.ts +1 -1
  98. package/package.json +9 -9
  99. package/proxychain.d.ts +3 -4
  100. package/storage/NewStorageQuery.d.ts +3 -3
  101. package/storage/QueryableStorage.js +1 -0
  102. package/types.d.ts +94 -6
@@ -1,274 +1,406 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DedotClient = void 0;
4
- const codecs_1 = require("@dedot/codecs");
5
- const shape_1 = require("@dedot/shape");
6
- const utils_1 = require("@dedot/utils");
7
- const index_js_1 = require("../executor/index.js");
8
- const index_js_2 = require("../json-rpc/index.js");
9
- const proxychain_js_1 = require("../proxychain.js");
10
- const index_js_3 = require("../storage/index.js");
11
- const BaseSubstrateClient_js_1 = require("./BaseSubstrateClient.js");
4
+ const index_js_1 = require("../json-rpc/index.js");
5
+ const LegacyClient_js_1 = require("./LegacyClient.js");
6
+ const V2Client_js_1 = require("./V2Client.js");
12
7
  /**
13
8
  * @name DedotClient
14
- * @description New promised-based API Client for Polkadot & Substrate based on JSON-RPC V2
9
+ * @description The main entry point for interacting with PolkadotSDK-based blockchains.
15
10
  *
16
- * __Unstable, use with caution.__
11
+ * DedotClient is a facade that provides a unified API for both JSON-RPC v2 (default) and legacy
12
+ * JSON-RPC versions.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { DedotClient, WsProvider } from 'dedot';
17
+ * import type { PolkadotApi } from '@dedot/chaintypes/polkadot';
18
+ *
19
+ * // Create and connect to a Polkadot node
20
+ * const provider = new WsProvider('wss://rpc.polkadot.io');
21
+ * const client = await DedotClient.new<PolkadotApi>(provider);
22
+ *
23
+ * // Get the current best block
24
+ * const bestBlock = await client.block.best();
25
+ * console.log('Best block:', bestBlock.number, bestBlock.hash);
26
+ *
27
+ * // Subscribe to finalized blocks
28
+ * const unsub = client.block.finalized((block) => {
29
+ * console.log('Finalized:', block.number);
30
+ * });
31
+ *
32
+ * // Query on-chain storage
33
+ * const balance = await client.query.system.account('14...');
34
+ * console.log('Balance:', balance);
35
+ *
36
+ * // Subscribe to runtime upgrades
37
+ * const unsub = client.on('runtimeUpgraded', (version, block) => {
38
+ * console.log('Runtime upgraded to:', version.specVersion, 'at block:', block.number);
39
+ * });
40
+ *
41
+ * // Sending transactions
42
+ * await client.tx.balances.transferKeepAlive('15...', 1000000000000n)
43
+ * .signAndSend(signer)
44
+ * .untilFinalized();
45
+ *
46
+ * // Disconnect when done
47
+ * await client.disconnect();
48
+ * ```
49
+ *
50
+ * @template ChainApi - Chain-specific API type for type-safe interactions (defaults to SubstrateApi)
17
51
  */
18
- class DedotClient// prettier-end-here
19
- extends BaseSubstrateClient_js_1.BaseSubstrateClient {
20
- _chainHead;
21
- _chainSpec;
22
- _archive;
23
- _txBroadcaster;
52
+ class DedotClient {
53
+ #client;
54
+ /** The JSON-RPC version being used ('v2' or 'legacy') */
55
+ rpcVersion;
24
56
  /**
25
- * Use factory methods (`create`, `new`) to create `DedotClient` instances.
57
+ * Creates a new DedotClient instance.
58
+ *
59
+ * Use factory methods (`create`, `new`, `legacy`) for automatic connection.
26
60
  *
27
- * @param options
61
+ * @param options - Client configuration options or a JsonRpcProvider instance
28
62
  */
29
63
  constructor(options) {
30
- super('v2', options);
64
+ let rpcVersion = 'v2';
65
+ if (!(0, index_js_1.isJsonRpcProvider)(options)) {
66
+ if (options['rpcVersion'] === 'legacy') {
67
+ rpcVersion = 'legacy';
68
+ }
69
+ }
70
+ this.rpcVersion = rpcVersion;
71
+ if (this.rpcVersion === 'legacy') {
72
+ this.#client = new LegacyClient_js_1.LegacyClient(options);
73
+ }
74
+ else {
75
+ this.#client = new V2Client_js_1.V2Client(options);
76
+ }
31
77
  }
32
78
  /**
33
- * Factory method to create a new DedotClient instance
79
+ * Factory method to create and connect a new DedotClient instance.
34
80
  *
35
- * @param options
81
+ * @param options - Client configuration options or a JsonRpcProvider instance
82
+ * @returns A connected DedotClient instance
83
+ *
84
+ * @example
85
+ * ```typescript
86
+ * const client = await DedotClient.create<PolkadotApi>({
87
+ * provider: new WsProvider('wss://rpc.polkadot.io'),
88
+ * });
89
+ * ```
36
90
  */
37
91
  static async create(options) {
38
92
  return new DedotClient(options).connect();
39
93
  }
40
94
  /**
41
- * Alias for __DedotClient.create__
95
+ * Alias for `DedotClient.create`
42
96
  *
43
- * @param options
97
+ * @param options - Client configuration options or a JsonRpcProvider instance
98
+ * @returns A connected DedotClient instance
44
99
  */
45
100
  static async new(options) {
46
101
  return DedotClient.create(options);
47
102
  }
48
- get chainSpec() {
49
- return (0, BaseSubstrateClient_js_1.ensurePresence)(this._chainSpec);
103
+ /**
104
+ * Factory method to create a DedotClient using legacy JSON-RPC.
105
+ *
106
+ * This is a convenience method that automatically sets `rpcVersion: 'legacy'`.
107
+ *
108
+ * @param options - Client configuration options or a JsonRpcProvider instance
109
+ * @returns A connected DedotClient instance using legacy JSON-RPC
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const client = await DedotClient.legacy<PolkadotApi>({
114
+ * provider: new WsProvider('wss://rpc.polkadot.io'),
115
+ * });
116
+ * ```
117
+ */
118
+ static async legacy(options) {
119
+ return DedotClient.create((0, index_js_1.isJsonRpcProvider)(options) // --
120
+ ? { provider: options, rpcVersion: 'legacy' }
121
+ : { ...options, rpcVersion: 'legacy' });
122
+ }
123
+ /** The API configuration options */
124
+ get options() {
125
+ return this.#client.options;
126
+ }
127
+ /** Current connection status */
128
+ get status() {
129
+ return this.#client.status;
130
+ }
131
+ /** The underlying JSON-RPC provider */
132
+ get provider() {
133
+ return this.#client.provider;
134
+ }
135
+ /** Transaction builder for submitting extrinsics */
136
+ get tx() {
137
+ return this.#client.tx;
138
+ }
139
+ /** Raw JSON-RPC method access */
140
+ get rpc() {
141
+ return this.#client.rpc;
142
+ }
143
+ /** The genesis hash of the connected chain */
144
+ get genesisHash() {
145
+ return this.#client.genesisHash;
50
146
  }
51
- get chainHead() {
52
- return (0, BaseSubstrateClient_js_1.ensurePresence)(this._chainHead);
147
+ /** Current runtime version information */
148
+ get runtimeVersion() {
149
+ return this.#client.runtimeVersion;
53
150
  }
54
- async archive() {
55
- (0, utils_1.assert)(this._archive, 'Archive instance is not initialized');
56
- (0, utils_1.assert)(await this._archive.supported(), 'Archive JSON-RPC is not supported by the connected server');
57
- return this._archive;
151
+ /** The chain metadata */
152
+ get metadata() {
153
+ return this.#client.metadata;
58
154
  }
59
- get txBroadcaster() {
60
- this.chainHead; // Ensure chain head is initialized
61
- (0, utils_1.assert)(this._txBroadcaster, 'JSON-RPC method to broadcast transactions is not supported by the server/node.');
62
- return this._txBroadcaster;
155
+ /** Type registry for encoding/decoding chain types */
156
+ get registry() {
157
+ return this.#client.registry;
63
158
  }
64
- async #initializeTxBroadcaster(rpcMethods) {
65
- const tx = new index_js_2.Transaction(this, { rpcMethods });
66
- if (await tx.supported())
67
- return tx;
68
- const txWatch = new index_js_2.TransactionWatch(this, { rpcMethods });
69
- if (await txWatch.supported())
70
- return txWatch;
159
+ /**
160
+ * Access to pallet constants.
161
+ *
162
+ * @example
163
+ * ```typescript
164
+ * const existentialDeposit = client.consts.balances.existentialDeposit;
165
+ * const ss58Prefix = client.consts.system.ss58Prefix;
166
+ * ```
167
+ */
168
+ get consts() {
169
+ return this.#client.consts;
71
170
  }
72
171
  /**
73
- * Initialize APIs before usage
172
+ * Storage query interface for reading on-chain state.
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * // One-time query
177
+ * const account = await client.query.system.account(address);
178
+ *
179
+ * // Subscribe to storage changes
180
+ * const unsub = await client.query.system.number((blockNumber) => {
181
+ * console.log('Current block:', blockNumber);
182
+ * });
183
+ * ```
74
184
  */
75
- async doInitialize() {
76
- const rpcMethods = (await this.rpc.rpc_methods()).methods;
77
- this._chainHead = new index_js_2.ChainHead(this, { rpcMethods });
78
- this._chainSpec = new index_js_2.ChainSpec(this, { rpcMethods });
79
- // Always initialize Archive, but only set up fallback if supported
80
- this._archive = new index_js_2.Archive(this, { rpcMethods });
81
- // Set up ChainHead with Archive fallback only if Archive is supported
82
- if (await this._archive.supported()) {
83
- this._chainHead.withArchive(this._archive);
84
- }
85
- this._txBroadcaster = await this.#initializeTxBroadcaster(rpcMethods);
86
- // Fetching node information
87
- let [_, genesisHash] = await Promise.all([
88
- this.chainHead.follow(),
89
- this.chainSpec.genesisHash().catch(() => undefined),
90
- ]);
91
- this._genesisHash = genesisHash || (await this.#getGenesisHashFallback());
92
- this._runtimeVersion = await this.chainHead.bestRuntimeVersion();
93
- let metadata;
94
- if (await this.shouldPreloadMetadata()) {
95
- metadata = await this.fetchMetadata();
96
- }
97
- await this.setupMetadata(metadata);
98
- this.subscribeRuntimeUpgrades();
99
- // relegate events
100
- this.chainHead.on('newBlock', (...args) => this.emit('newBlock', ...args));
101
- this.chainHead.on('bestBlock', (...args) => this.emit('bestBlock', ...args));
102
- this.chainHead.on('finalizedBlock', (...args) => this.emit('finalizedBlock', ...args));
103
- this.chainHead.on('bestChainChanged', (...args) => this.emit('bestChainChanged', ...args));
185
+ get query() {
186
+ return this.#client.query;
104
187
  }
105
188
  /**
106
- * Ref: https://github.com/paritytech/polkadot-sdk/blob/bbd51ce867967f71657b901f1a956ad4f75d352e/substrate/frame/system/src/lib.rs#L909-L913
107
- * @private
189
+ * Runtime API call interface.
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * const rawMetadata = await client.call.metadata.metadataAtVersion(16);
194
+ * const version = await client.call.core.version();
195
+ * ```
108
196
  */
109
- async #getGenesisHashFallback() {
110
- const pallet = (0, utils_1.xxhashAsU8a)('System', 128);
111
- const item = (0, utils_1.xxhashAsU8a)('BlockHash', 128);
112
- const blockHeightAt0 = (0, utils_1.twox64Concat)(shape_1.u32.encode(0));
113
- const key = (0, utils_1.u8aToHex)((0, utils_1.concatU8a)(pallet, item, blockHeightAt0));
114
- const storageValue = await this.chainHead.storage([{ type: 'value', key }]);
115
- const rawGenesisHash = storageValue.at(0)?.value;
116
- (0, utils_1.assert)(rawGenesisHash, 'Genesis hash not found!');
117
- // Here we assume that in most case the hash is stored as a H256
118
- return codecs_1.$H256.tryDecode(rawGenesisHash);
119
- }
120
- subscribeRuntimeUpgrades() {
121
- this.chainHead.on('bestBlock', this.onRuntimeUpgrade);
122
- }
123
- onRuntimeUpgrade = async (block) => {
124
- const runtimeUpgraded = block.runtime && block.runtime.specVersion !== this._runtimeVersion?.specVersion;
125
- if (!runtimeUpgraded)
126
- return;
127
- this.startRuntimeUpgrade();
128
- this._runtimeVersion = block.runtime;
129
- const newMetadata = await this.fetchMetadata(undefined, this._runtimeVersion);
130
- await this.setupMetadata(newMetadata);
131
- this.emit('runtimeUpgraded', this._runtimeVersion);
132
- this.doneRuntimeUpgrade();
133
- };
134
- async beforeDisconnect() {
135
- await this.chainHead.unfollow();
136
- }
137
- onDisconnected = async () => {
138
- try {
139
- this.chainHead.unfollow().catch(utils_1.noop);
140
- }
141
- catch { }
142
- };
143
- cleanUp() {
144
- super.cleanUp();
145
- this._chainHead = undefined;
146
- this._chainSpec = undefined;
147
- this._archive = undefined;
148
- this._txBroadcaster = undefined;
197
+ get call() {
198
+ return this.#client.call;
149
199
  }
150
200
  /**
151
- * @description Clear local cache, API at-block cache, and ChainHead cache
152
- * @param keepMetadataCache Keep the metadata cache, only clear other caches.
201
+ * Event type definitions and utilities.
202
+ *
203
+ * @example
204
+ * ```typescript
205
+ * // Check if an event matches a specific type
206
+ * if (client.events.balances.Transfer.is(event)) {
207
+ * console.log('Transfer event:', event.data);
208
+ * }
209
+ * ```
153
210
  */
154
- async clearCache(keepMetadataCache = false) {
155
- await super.clearCache(keepMetadataCache);
156
- this._chainHead?.clearCache();
211
+ get events() {
212
+ return this.#client.events;
157
213
  }
158
- get query() {
159
- return (0, proxychain_js_1.newProxyChain)({
160
- executor: new index_js_1.StorageQueryExecutorV2(this, this.chainHead),
161
- });
214
+ /**
215
+ * Error type definitions and utilities.
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * // Check if an error matches a specific type
220
+ * if (client.errors.balances.InsufficientBalance.is(dispatchError)) {
221
+ * console.log('Insufficient balance error');
222
+ * }
223
+ * ```
224
+ */
225
+ get errors() {
226
+ return this.#client.errors;
162
227
  }
228
+ /**
229
+ * View functions interface (requires Metadata V16+).
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * // Call a view function
234
+ * const result = await client.view.voterList.scores(ALICE_ADDRESS);
235
+ * ```
236
+ */
163
237
  get view() {
164
- return (0, proxychain_js_1.newProxyChain)({
165
- executor: new index_js_1.ViewFunctionExecutorV2(this, this.chainHead),
166
- });
238
+ return this.#client.view;
167
239
  }
168
- get call() {
169
- return this.callAt();
240
+ /**
241
+ * Block explorer interface for accessing block data.
242
+ *
243
+ * Provides methods to get/subscribe to best and finalized blocks,
244
+ * as well as retrieve block headers and bodies.
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * // Get the current best block
249
+ * const bestBlock = await client.block.best();
250
+ * console.log('Best block:', bestBlock.number, bestBlock.hash);
251
+ *
252
+ * // Subscribe to finalized blocks
253
+ * const unsub = client.block.finalized((block) => {
254
+ * console.log('Finalized block:', block.number);
255
+ * });
256
+ *
257
+ * // Get block header and body
258
+ * const header = await client.block.header(blockHash);
259
+ * const body = await client.block.body(blockHash);
260
+ * ```
261
+ */
262
+ get block() {
263
+ return this.#client.block;
170
264
  }
171
- callAt(blockHash) {
172
- return (0, proxychain_js_1.newProxyChain)({
173
- executor: new index_js_1.RuntimeApiExecutorV2(this, this.chainHead, blockHash),
174
- });
265
+ /**
266
+ * Chain specification interface for accessing chain information.
267
+ *
268
+ * Provides methods to get chain name, genesis hash, and chain properties.
269
+ *
270
+ * @example
271
+ * ```typescript
272
+ * const chainName = await client.chainSpec.chainName();
273
+ * const genesisHash = await client.chainSpec.genesisHash();
274
+ * const properties = await client.chainSpec.properties();
275
+ *
276
+ * console.log(`Connected to ${chainName}`);
277
+ * console.log('Token symbol:', properties.tokenSymbol);
278
+ * console.log('Token decimals:', properties.tokenDecimals);
279
+ * ```
280
+ */
281
+ get chainSpec() {
282
+ return this.#client.chainSpec;
175
283
  }
176
- get tx() {
177
- return (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.TxExecutorV2(this) });
284
+ /**
285
+ * Establishes connection to the blockchain network.
286
+ *
287
+ * @returns This client instance for method chaining
288
+ */
289
+ async connect() {
290
+ await this.#client.connect();
291
+ return this;
178
292
  }
179
293
  /**
180
- * Get a new API instance at a specific block hash
181
- * Supports both pinned blocks (via ChainHead) and historical blocks (via Archive fallback)
294
+ * Closes the connection to the blockchain network.
295
+ */
296
+ async disconnect() {
297
+ await this.#client.disconnect();
298
+ }
299
+ /**
300
+ * Subscribe to client events.
182
301
  *
183
- * @param hash
302
+ * @param event - The event to listen for ('ready', 'connected', 'disconnected', 'reconnecting', 'runtimeUpgraded', 'error')
303
+ * @param handler - Callback function to handle the event
304
+ * @returns Unsubscribe function
184
305
  */
185
- async at(hash) {
186
- const cached = this._apiAtCache.get(hash);
187
- if (cached)
188
- return cached;
189
- let parentVersion;
190
- let parentHash;
191
- // Try to get block info from ChainHead first (for pinned blocks)
192
- const targetBlock = this.chainHead.findBlock(hash);
193
- if (targetBlock) {
194
- if (hash === this.genesisHash) {
195
- parentHash = hash;
196
- parentVersion = targetBlock.runtime;
197
- }
198
- else {
199
- parentHash = targetBlock.parent;
200
- const parentBlock = this.chainHead.findBlock(parentHash);
201
- parentVersion = parentBlock?.runtime;
202
- }
203
- // fallback to fetching on-chain runtime if we can't find it in the block
204
- if (!parentVersion) {
205
- parentVersion = this.toSubstrateRuntimeVersion(await this.callAt(parentHash).core.version());
206
- }
207
- }
208
- else {
209
- // Block not pinned, try via Archive fallback if supported
210
- if (this._archive && (await this._archive.supported())) {
211
- try {
212
- if (hash === this.genesisHash) {
213
- parentHash = hash;
214
- }
215
- else {
216
- const rawHeader = await this._archive.header(hash);
217
- (0, utils_1.assert)(rawHeader, `Header for block ${hash} not found`);
218
- const header = codecs_1.$Header.tryDecode(rawHeader);
219
- parentHash = header.parentHash;
220
- }
221
- // Fetch runtime version via Archive
222
- const runtimeRaw = await this._archive.call('Core_version', '0x', parentHash);
223
- (0, utils_1.assert)(runtimeRaw, 'Runtime Version Not Found');
224
- parentVersion = this.toSubstrateRuntimeVersion(codecs_1.$RuntimeVersion.tryDecode(runtimeRaw));
225
- }
226
- catch (error) {
227
- throw new utils_1.DedotError(`Unable to fetch runtime version for block ${hash}: ${error}`);
228
- }
229
- }
230
- else {
231
- throw new utils_1.DedotError('Block is not pinned and Archive JSON-RPC is not supported by the server/node!');
232
- }
233
- }
234
- let metadata = this.metadata;
235
- let registry = this.registry;
236
- if (parentVersion && parentVersion.specVersion !== this.runtimeVersion.specVersion) {
237
- const cachedMetadata = this.findMetadataInCache(parentVersion.specVersion);
238
- if (cachedMetadata) {
239
- metadata = cachedMetadata[0];
240
- registry = cachedMetadata[1];
241
- }
242
- else {
243
- metadata = await this.fetchMetadata(parentHash, parentVersion);
244
- registry = new codecs_1.PortableRegistry(metadata.latest, this.options.hasher);
245
- }
246
- }
247
- const api = {
248
- rpcVersion: 'v2',
249
- atBlockHash: hash,
250
- options: this.options,
251
- genesisHash: this.genesisHash,
252
- runtimeVersion: parentVersion,
253
- metadata,
254
- registry,
255
- rpc: this.rpc,
256
- };
257
- api.consts = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.ConstantExecutor(api) });
258
- api.events = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.EventExecutor(api) });
259
- api.errors = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.ErrorExecutor(api) });
260
- api.query = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.StorageQueryExecutorV2(api, this.chainHead) });
261
- api.call = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.RuntimeApiExecutorV2(api, this.chainHead) });
262
- api.view = (0, proxychain_js_1.newProxyChain)({ executor: new index_js_1.ViewFunctionExecutorV2(api, this.chainHead) });
263
- // @ts-ignore Add queryMulti implementation for at-block queries
264
- api.queryMulti = (queries) => {
265
- return this.internalQueryMulti(queries, undefined, hash);
266
- };
267
- this._apiAtCache.set(hash, api);
268
- return api;
269
- }
270
- getStorageQuery() {
271
- return new index_js_3.NewStorageQuery(this);
306
+ on(event, handler) {
307
+ return this.#client.on(event, handler);
308
+ }
309
+ /**
310
+ * Subscribe to a client event once.
311
+ *
312
+ * @param event - The event to listen for
313
+ * @param handler - Callback function to handle the event
314
+ * @returns Unsubscribe function
315
+ */
316
+ once(event, handler) {
317
+ return this.#client.once(event, handler);
318
+ }
319
+ /**
320
+ * Unsubscribe from client events.
321
+ *
322
+ * @param event - The event to unsubscribe from
323
+ * @param handler - The handler function to remove (optional, removes all handlers if not provided)
324
+ * @returns This client instance for method chaining
325
+ */
326
+ off(event, handler) {
327
+ this.#client.off(event, handler);
328
+ return this;
329
+ }
330
+ /**
331
+ * Get a client instance at a specific block hash.
332
+ *
333
+ * This allows querying historical state at a specific block.
334
+ *
335
+ * @template ChainApiAt - Chain API type for the historical state (defaults to ChainApi)
336
+ * @param hash - The block hash to query at
337
+ * @returns A client instance for querying state at the specified block
338
+ *
339
+ * @example
340
+ * ```typescript
341
+ * const clientAtBlock = await client.at('0x1234...');
342
+ * const historicalBalance = await clientAtBlock.query.system.account('14...');
343
+ * ```
344
+ */
345
+ at(hash) {
346
+ return this.#client.at(hash);
347
+ }
348
+ /**
349
+ * Get the current runtime version with metadata sync.
350
+ *
351
+ * Unlike the `runtimeVersion` getter, this method ensures the corresponding
352
+ * metadata for the runtime version is downloaded and set up. Useful for
353
+ * preparing for runtime upgrades.
354
+ *
355
+ * @returns The current runtime version
356
+ */
357
+ getRuntimeVersion() {
358
+ return this.#client.getRuntimeVersion();
359
+ }
360
+ /**
361
+ * Set or update the signer instance for signing transactions.
362
+ *
363
+ * @param signer - The signer instance (or undefined to clear)
364
+ */
365
+ setSigner(signer) {
366
+ this.#client.setSigner(signer);
367
+ }
368
+ queryMulti(queries, // --
369
+ callback) {
370
+ // @ts-ignore
371
+ return this.#client.queryMulti(queries, callback);
372
+ }
373
+ /**
374
+ * Broadcast a transaction to the network and track its status.
375
+ *
376
+ * @param tx - The transaction (hex string or Extrinsic instance)
377
+ * @param callback - Optional callback for transaction status updates
378
+ * @returns TxUnsub object with utility methods (`.untilFinalized()`, `.untilBestChainBlockIncluded()`)
379
+ *
380
+ * @example
381
+ * ```typescript
382
+ * // Wait for finalization
383
+ * const result = await client.sendTx(txHex).untilFinalized();
384
+ *
385
+ * // With status callback to track progress
386
+ * const unsub = await client.sendTx(txHex, (result) => {
387
+ * console.log('Status:', result.status);
388
+ * if (result.dispatchError) {
389
+ * console.error('Transaction failed:', result.dispatchError);
390
+ * }
391
+ * });
392
+ * ```
393
+ */
394
+ sendTx(tx, callback) {
395
+ return this.#client.sendTx(tx, callback);
396
+ }
397
+ /**
398
+ * Clear internal caches.
399
+ *
400
+ * @param keepMetadataCache - If true, preserves the metadata cache (default: false)
401
+ */
402
+ async clearCache(keepMetadataCache = false) {
403
+ await this.#client.clearCache(keepMetadataCache);
272
404
  }
273
405
  }
274
406
  exports.DedotClient = DedotClient;