@dedot/api 1.1.1 → 1.3.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/cjs/client/BaseSubstrateClient.js +13 -2
- package/cjs/client/DedotClient.js +47 -19
- package/cjs/client/V2Client.js +4 -0
- package/cjs/extrinsic/extensions/known/CheckMortality.js +12 -4
- package/cjs/extrinsic/submittable/SubmittableExtrinsic.js +2 -8
- package/cjs/extrinsic/submittable/SubmittableExtrinsicV2.js +2 -8
- package/cjs/extrinsic/submittable/utils.js +36 -1
- package/client/BaseSubstrateClient.d.ts +2 -2
- package/client/BaseSubstrateClient.js +13 -2
- package/client/DedotClient.d.ts +27 -13
- package/client/DedotClient.js +47 -19
- package/client/LegacyClient.d.ts +2 -2
- package/client/V2Client.d.ts +2 -2
- package/client/V2Client.js +5 -1
- package/extrinsic/extensions/known/CheckMortality.js +12 -4
- package/extrinsic/submittable/SubmittableExtrinsic.d.ts +2 -2
- package/extrinsic/submittable/SubmittableExtrinsic.js +3 -9
- package/extrinsic/submittable/SubmittableExtrinsicV2.d.ts +1 -1
- package/extrinsic/submittable/SubmittableExtrinsicV2.js +4 -10
- package/extrinsic/submittable/utils.d.ts +14 -2
- package/extrinsic/submittable/utils.js +34 -0
- package/package.json +9 -9
- package/types.d.ts +17 -9
|
@@ -257,15 +257,26 @@ class BaseSubstrateClient extends index_js_2.JsonRpcClient {
|
|
|
257
257
|
this.on('connected', this.onConnected);
|
|
258
258
|
// @ts-ignore
|
|
259
259
|
this.on('disconnected', this.onDisconnected);
|
|
260
|
-
return new Promise((resolve) => {
|
|
260
|
+
return new Promise((resolve, reject) => {
|
|
261
|
+
// @ts-ignore
|
|
262
|
+
const offError = this.on('error', (err) => {
|
|
263
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
264
|
+
});
|
|
261
265
|
// @ts-ignore
|
|
262
266
|
this.once('ready', () => {
|
|
267
|
+
offError();
|
|
263
268
|
resolve(this);
|
|
264
269
|
});
|
|
265
270
|
});
|
|
266
271
|
}
|
|
267
272
|
onConnected = async () => {
|
|
268
|
-
|
|
273
|
+
try {
|
|
274
|
+
await this.initialize();
|
|
275
|
+
}
|
|
276
|
+
catch (e) {
|
|
277
|
+
// @ts-ignore — surface init failure so the pending connect() promise can reject
|
|
278
|
+
this.emit('error', e);
|
|
279
|
+
}
|
|
269
280
|
};
|
|
270
281
|
onDisconnected = async () => { };
|
|
271
282
|
async initialize() {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DedotClient = void 0;
|
|
4
|
+
const utils_1 = require("@dedot/utils");
|
|
4
5
|
const index_js_1 = require("../json-rpc/index.js");
|
|
5
6
|
const LegacyClient_js_1 = require("./LegacyClient.js");
|
|
6
7
|
const V2Client_js_1 = require("./V2Client.js");
|
|
@@ -51,7 +52,12 @@ const V2Client_js_1 = require("./V2Client.js");
|
|
|
51
52
|
*/
|
|
52
53
|
class DedotClient {
|
|
53
54
|
#client;
|
|
54
|
-
|
|
55
|
+
#pendingOptions;
|
|
56
|
+
/**
|
|
57
|
+
* The JSON-RPC version being used ('v2' or 'legacy').
|
|
58
|
+
*
|
|
59
|
+
* In auto-detect mode (no `rpcVersion` option), this is resolved during `connect()`.
|
|
60
|
+
*/
|
|
55
61
|
rpcVersion;
|
|
56
62
|
/**
|
|
57
63
|
* Creates a new DedotClient instance.
|
|
@@ -61,18 +67,14 @@ class DedotClient {
|
|
|
61
67
|
* @param options - Client configuration options or a JsonRpcProvider instance
|
|
62
68
|
*/
|
|
63
69
|
constructor(options) {
|
|
64
|
-
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
this.rpcVersion = rpcVersion;
|
|
71
|
-
if (this.rpcVersion === 'legacy') {
|
|
72
|
-
this.#client = new LegacyClient_js_1.LegacyClient(options);
|
|
70
|
+
const explicitVersion = (0, index_js_1.isJsonRpcProvider)(options) ? undefined : options.rpcVersion;
|
|
71
|
+
if (explicitVersion) {
|
|
72
|
+
this.rpcVersion = explicitVersion;
|
|
73
|
+
this.#client =
|
|
74
|
+
explicitVersion === 'legacy' ? new LegacyClient_js_1.LegacyClient(options) : new V2Client_js_1.V2Client(options);
|
|
73
75
|
}
|
|
74
76
|
else {
|
|
75
|
-
this.#
|
|
77
|
+
this.#pendingOptions = options;
|
|
76
78
|
}
|
|
77
79
|
}
|
|
78
80
|
/**
|
|
@@ -284,10 +286,34 @@ class DedotClient {
|
|
|
284
286
|
/**
|
|
285
287
|
* Establishes connection to the blockchain network.
|
|
286
288
|
*
|
|
289
|
+
* When `rpcVersion` was not specified, this tries JSON-RPC v2 first and
|
|
290
|
+
* transparently falls back to legacy if the node does not support v2.
|
|
291
|
+
*
|
|
287
292
|
* @returns This client instance for method chaining
|
|
288
293
|
*/
|
|
289
294
|
async connect() {
|
|
290
|
-
|
|
295
|
+
if (this.#client) {
|
|
296
|
+
await this.#client.connect();
|
|
297
|
+
return this;
|
|
298
|
+
}
|
|
299
|
+
const options = this.#pendingOptions;
|
|
300
|
+
this.#pendingOptions = undefined;
|
|
301
|
+
const v2 = new V2Client_js_1.V2Client(options);
|
|
302
|
+
try {
|
|
303
|
+
await v2.connect();
|
|
304
|
+
this.#client = v2;
|
|
305
|
+
this.rpcVersion = 'v2';
|
|
306
|
+
}
|
|
307
|
+
catch (e) {
|
|
308
|
+
if (!(e instanceof utils_1.JsonRpcV2NotSupportedError))
|
|
309
|
+
throw e;
|
|
310
|
+
console.warn('JSON-RPC v2 is not supported by the connected node, falling back to legacy JSON-RPC.');
|
|
311
|
+
await v2.disconnect().catch(utils_1.noop);
|
|
312
|
+
const legacy = new LegacyClient_js_1.LegacyClient(options);
|
|
313
|
+
await legacy.connect();
|
|
314
|
+
this.#client = legacy;
|
|
315
|
+
this.rpcVersion = 'legacy';
|
|
316
|
+
}
|
|
291
317
|
return this;
|
|
292
318
|
}
|
|
293
319
|
/**
|
|
@@ -395,25 +421,27 @@ class DedotClient {
|
|
|
395
421
|
return this.#client.sendTx(tx, callback);
|
|
396
422
|
}
|
|
397
423
|
/**
|
|
398
|
-
* Convert a
|
|
424
|
+
* Convert a transaction input into a submittable extrinsic
|
|
399
425
|
* with `sign`, `signAndSend`, `send`, and `paymentInfo` methods.
|
|
400
426
|
*
|
|
401
|
-
* @param tx - A hex-encoded
|
|
427
|
+
* @param tx - A hex-encoded extrinsic or runtime call, a Uint8Array of encoded bytes,
|
|
428
|
+
* an Extrinsic instance, or an IRuntimeTxCall object.
|
|
429
|
+
* For HexString/Uint8Array, it first tries to decode as a full extrinsic;
|
|
430
|
+
* if that fails, it falls back to decoding as a raw runtime call.
|
|
402
431
|
* @returns A submittable extrinsic instance
|
|
403
432
|
*
|
|
404
433
|
* @example
|
|
405
434
|
* ```typescript
|
|
406
|
-
* //
|
|
435
|
+
* // From a raw hex extrinsic
|
|
407
436
|
* const submittable = client.toTx(rawTxHex);
|
|
408
437
|
*
|
|
438
|
+
* // From a runtime call object
|
|
439
|
+
* const submittable = client.toTx({ pallet: 'Balances', palletCall: { name: 'TransferKeepAlive', params: { dest, value } } });
|
|
440
|
+
*
|
|
409
441
|
* // Sign and send
|
|
410
442
|
* const unsub = await submittable.signAndSend(alice, (result) => {
|
|
411
443
|
* console.log('Status:', result.status);
|
|
412
444
|
* });
|
|
413
|
-
*
|
|
414
|
-
* // Or query payment info
|
|
415
|
-
* const paymentInfo = await submittable.paymentInfo(alice);
|
|
416
|
-
* console.log('Estimated fee:', paymentInfo.partialFee);
|
|
417
445
|
* ```
|
|
418
446
|
*/
|
|
419
447
|
toTx(tx) {
|
package/cjs/client/V2Client.js
CHANGED
|
@@ -78,6 +78,10 @@ class V2Client// prettier-end-here
|
|
|
78
78
|
const shouldInitialize = !this._genesisHash;
|
|
79
79
|
if (shouldInitialize) {
|
|
80
80
|
const rpcMethods = (await this.rpc.rpc_methods()).methods;
|
|
81
|
+
if (!rpcMethods.some((m) => m.startsWith('chainHead_'))) {
|
|
82
|
+
throw new utils_1.JsonRpcV2NotSupportedError('The connected node does not support JSON-RPC v2 (no chainHead_* methods). ' +
|
|
83
|
+
'Omit `rpcVersion` to auto-detect, or pass `rpcVersion: "legacy"`.');
|
|
84
|
+
}
|
|
81
85
|
this._chainHead = new index_js_2.ChainHead(this, { rpcMethods });
|
|
82
86
|
this._chainSpec = new index_js_2.ChainSpec(this, { rpcMethods });
|
|
83
87
|
// Always initialize Archive, but only set up fallback if supported
|
|
@@ -13,9 +13,17 @@ exports.MORTAL_PERIOD = 12 * 60 * 1000;
|
|
|
13
13
|
class CheckMortality extends SignedExtension_js_1.SignedExtension {
|
|
14
14
|
#signingHeader;
|
|
15
15
|
async init() {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
const mortality = this.payloadOptions.mortality;
|
|
17
|
+
if (mortality?.type === 'Immortal') {
|
|
18
|
+
this.data = { type: 'Immortal' };
|
|
19
|
+
this.additionalSigned = this.client.genesisHash;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.#signingHeader = await this.#getSigningHeader();
|
|
23
|
+
const period = mortality?.type === 'Mortal' ? BigInt(mortality.period) : this.#calculateMortalLength();
|
|
24
|
+
this.data = { period, current: BigInt(this.#signingHeader.number) };
|
|
25
|
+
this.additionalSigned = this.#signingHeader.hash;
|
|
26
|
+
}
|
|
19
27
|
}
|
|
20
28
|
async fromPayload(payload) {
|
|
21
29
|
const { era, blockHash, blockNumber } = payload;
|
|
@@ -88,7 +96,7 @@ class CheckMortality extends SignedExtension_js_1.SignedExtension {
|
|
|
88
96
|
return {
|
|
89
97
|
era: (0, utils_1.u8aToHex)(this.$Data.tryEncode(this.data)),
|
|
90
98
|
blockHash: this.additionalSigned,
|
|
91
|
-
blockNumber: (0, utils_1.numberToHex)(this.#signingHeader
|
|
99
|
+
blockNumber: (0, utils_1.numberToHex)(this.#signingHeader?.number ?? 0),
|
|
92
100
|
};
|
|
93
101
|
}
|
|
94
102
|
}
|
|
@@ -11,14 +11,8 @@ const utils_js_1 = require("./utils.js");
|
|
|
11
11
|
*/
|
|
12
12
|
class SubmittableExtrinsic extends BaseSubmittableExtrinsic_js_1.BaseSubmittableExtrinsic {
|
|
13
13
|
static fromTx(client, tx) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
extrinsic = client.registry.$Extrinsic.tryDecode(tx);
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
extrinsic = tx;
|
|
20
|
-
}
|
|
21
|
-
return new SubmittableExtrinsic(client, extrinsic.call, extrinsic.preamble);
|
|
14
|
+
const { call, preamble } = (0, utils_js_1.resolveCallAndPreamble)(client.registry, tx);
|
|
15
|
+
return new SubmittableExtrinsic(client, call, preamble);
|
|
22
16
|
}
|
|
23
17
|
async dryRun(account, optionsOrHash) {
|
|
24
18
|
const dryRunFn = this.client.rpc.system_dryRun;
|
|
@@ -17,14 +17,8 @@ class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic_js_1.BaseSubmittab
|
|
|
17
17
|
this.client = client;
|
|
18
18
|
}
|
|
19
19
|
static fromTx(client, tx) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
extrinsic = client.registry.$Extrinsic.tryDecode(tx);
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
extrinsic = tx;
|
|
26
|
-
}
|
|
27
|
-
return new SubmittableExtrinsicV2(client, extrinsic.call, extrinsic.preamble);
|
|
20
|
+
const { call, preamble } = (0, utils_js_1.resolveCallAndPreamble)(client.registry, tx);
|
|
21
|
+
return new SubmittableExtrinsicV2(client, call, preamble);
|
|
28
22
|
}
|
|
29
23
|
async #send(callback) {
|
|
30
24
|
const api = this.client;
|
|
@@ -1,8 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.txDefer = exports.toTxStatus = exports.signRawMessage = exports.isKeyringPair = void 0;
|
|
3
|
+
exports.txDefer = exports.toTxStatus = exports.signRawMessage = exports.isKeyringPair = exports.resolveCallAndPreamble = void 0;
|
|
4
|
+
const codecs_1 = require("@dedot/codecs");
|
|
4
5
|
const utils_1 = require("@dedot/utils");
|
|
5
6
|
const errors_js_1 = require("./errors.js");
|
|
7
|
+
/**
|
|
8
|
+
* Check if a value is an IRuntimeTxCall object (has a 'pallet' property).
|
|
9
|
+
*/
|
|
10
|
+
function isRuntimeTxCall(tx) {
|
|
11
|
+
return typeof tx === 'object' && tx !== null && 'pallet' in tx;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve a transaction input into a call and optional preamble.
|
|
15
|
+
*
|
|
16
|
+
* Supports:
|
|
17
|
+
* - `Extrinsic` instance: extract call + preamble
|
|
18
|
+
* - `IRuntimeTxCall` object: use directly as call, no preamble
|
|
19
|
+
* - `HexString` or `Uint8Array`: try decode as extrinsic first, fallback to runtime call
|
|
20
|
+
*/
|
|
21
|
+
function resolveCallAndPreamble(registry, tx) {
|
|
22
|
+
if (tx instanceof codecs_1.Extrinsic) {
|
|
23
|
+
return { call: tx.call, preamble: tx.preamble };
|
|
24
|
+
}
|
|
25
|
+
if (isRuntimeTxCall(tx)) {
|
|
26
|
+
return { call: tx };
|
|
27
|
+
}
|
|
28
|
+
// HexString or Uint8Array: try extrinsic decode first, fallback to runtime call
|
|
29
|
+
try {
|
|
30
|
+
const extrinsic = registry.$Extrinsic.tryDecode(tx);
|
|
31
|
+
return { call: extrinsic.call, preamble: extrinsic.preamble };
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
const { callTypeId } = registry.metadata.extrinsic;
|
|
35
|
+
const $RuntimeCall = registry.findCodec(callTypeId);
|
|
36
|
+
const call = $RuntimeCall.tryDecode(tx);
|
|
37
|
+
return { call };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.resolveCallAndPreamble = resolveCallAndPreamble;
|
|
6
41
|
function isKeyringPair(account) {
|
|
7
42
|
return (0, utils_1.isFunction)(account.sign);
|
|
8
43
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BlockHash, Extrinsic, Hash, Metadata, PortableRegistry, RuntimeVersion } from '@dedot/codecs';
|
|
2
2
|
import { type JsonRpcProvider } from '@dedot/providers';
|
|
3
3
|
import { type IStorage } from '@dedot/storage';
|
|
4
|
-
import { Callback, ChainSubmittableExtrinsic, GenericStorageQuery, GenericSubstrateApi, InjectedSigner, ISubmittableResult, Query, QueryFnResult, RpcVersion, TxUnsub, Unsub } from '@dedot/types';
|
|
4
|
+
import { Callback, ChainSubmittableExtrinsic, GenericStorageQuery, GenericSubstrateApi, InjectedSigner, IRuntimeTxCall, ISubmittableResult, Query, QueryFnResult, RpcVersion, TxUnsub, Unsub } from '@dedot/types';
|
|
5
5
|
import { Deferred, HexString, LRUCache } from '@dedot/utils';
|
|
6
6
|
import type { SubstrateApi } from '../chaintypes/index.js';
|
|
7
7
|
import { JsonRpcClient } from '../json-rpc/index.js';
|
|
@@ -133,7 +133,7 @@ export declare abstract class BaseSubstrateClient<ChainApi extends GenericSubstr
|
|
|
133
133
|
}>): Promise<Unsub>;
|
|
134
134
|
protected getStorageQuery(): BaseStorageQuery;
|
|
135
135
|
sendTx(tx: HexString | Extrinsic, callback?: Callback<ISubmittableResult<ChainApi['types']['EventRecord']>>): TxUnsub;
|
|
136
|
-
toTx(tx: HexString | Extrinsic): ChainSubmittableExtrinsic<ChainApi>;
|
|
136
|
+
toTx(tx: HexString | Uint8Array | Extrinsic | IRuntimeTxCall): ChainSubmittableExtrinsic<ChainApi>;
|
|
137
137
|
get chainSpec(): IChainSpec;
|
|
138
138
|
on<Event extends Events = Events>(event: Event, handler: EventHandlerFn<Event>): () => void;
|
|
139
139
|
}
|
|
@@ -253,15 +253,26 @@ export class BaseSubstrateClient extends JsonRpcClient {
|
|
|
253
253
|
this.on('connected', this.onConnected);
|
|
254
254
|
// @ts-ignore
|
|
255
255
|
this.on('disconnected', this.onDisconnected);
|
|
256
|
-
return new Promise((resolve) => {
|
|
256
|
+
return new Promise((resolve, reject) => {
|
|
257
|
+
// @ts-ignore
|
|
258
|
+
const offError = this.on('error', (err) => {
|
|
259
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
260
|
+
});
|
|
257
261
|
// @ts-ignore
|
|
258
262
|
this.once('ready', () => {
|
|
263
|
+
offError();
|
|
259
264
|
resolve(this);
|
|
260
265
|
});
|
|
261
266
|
});
|
|
262
267
|
}
|
|
263
268
|
onConnected = async () => {
|
|
264
|
-
|
|
269
|
+
try {
|
|
270
|
+
await this.initialize();
|
|
271
|
+
}
|
|
272
|
+
catch (e) {
|
|
273
|
+
// @ts-ignore — surface init failure so the pending connect() promise can reject
|
|
274
|
+
this.emit('error', e);
|
|
275
|
+
}
|
|
265
276
|
};
|
|
266
277
|
onDisconnected = async () => { };
|
|
267
278
|
async initialize() {
|
package/client/DedotClient.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Extrinsic, Metadata, PortableRegistry } from '@dedot/codecs';
|
|
2
2
|
import { ConnectionStatus, JsonRpcProvider } from '@dedot/providers';
|
|
3
|
-
import { Callback, ChainSubmittableExtrinsic, GenericStorageQuery, GenericSubstrateApi, InjectedSigner, ISubmittableResult, Query, QueryFnResult, RpcVersion, TxUnsub, Unsub } from '@dedot/types';
|
|
3
|
+
import { Callback, ChainSubmittableExtrinsic, GenericStorageQuery, GenericSubstrateApi, InjectedSigner, IRuntimeTxCall, ISubmittableResult, Query, QueryFnResult, RpcVersion, TxUnsub, Unsub } from '@dedot/types';
|
|
4
4
|
import { HexString } from '@dedot/utils';
|
|
5
5
|
import { SubstrateApi } from '../chaintypes/index.js';
|
|
6
6
|
import { ApiEvent, ApiOptions, BlockExplorer, ISubstrateClient, ISubstrateClientAt, SubstrateRuntimeVersion, IChainSpec, type EventHandlerFn } from '../types.js';
|
|
@@ -9,9 +9,14 @@ import { ApiEvent, ApiOptions, BlockExplorer, ISubstrateClient, ISubstrateClient
|
|
|
9
9
|
*/
|
|
10
10
|
export type ClientOptions = ApiOptions & {
|
|
11
11
|
/**
|
|
12
|
-
* The JSON-RPC version to use
|
|
13
|
-
*
|
|
14
|
-
* -
|
|
12
|
+
* The JSON-RPC version to use.
|
|
13
|
+
*
|
|
14
|
+
* - _unset_ (default): auto-detect. Try JSON-RPC v2 first and transparently fall back
|
|
15
|
+
* to legacy if the connected node does not expose v2 methods (no `chainHead_*`).
|
|
16
|
+
* After `connect()` resolves, `client.rpcVersion` reflects the version that was picked.
|
|
17
|
+
* - `'v2'`: force JSON-RPC v2. Throws `JsonRpcV2NotSupportedError` during `connect()`
|
|
18
|
+
* if the node does not support v2.
|
|
19
|
+
* - `'legacy'`: force legacy JSON-RPC.
|
|
15
20
|
*/
|
|
16
21
|
rpcVersion?: RpcVersion;
|
|
17
22
|
};
|
|
@@ -62,7 +67,11 @@ export type ClientOptions = ApiOptions & {
|
|
|
62
67
|
*/
|
|
63
68
|
export declare class DedotClient<ChainApi extends GenericSubstrateApi = SubstrateApi> implements ISubstrateClient<ChainApi, ApiEvent> {
|
|
64
69
|
#private;
|
|
65
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* The JSON-RPC version being used ('v2' or 'legacy').
|
|
72
|
+
*
|
|
73
|
+
* In auto-detect mode (no `rpcVersion` option), this is resolved during `connect()`.
|
|
74
|
+
*/
|
|
66
75
|
rpcVersion: RpcVersion;
|
|
67
76
|
/**
|
|
68
77
|
* Creates a new DedotClient instance.
|
|
@@ -239,6 +248,9 @@ export declare class DedotClient<ChainApi extends GenericSubstrateApi = Substrat
|
|
|
239
248
|
/**
|
|
240
249
|
* Establishes connection to the blockchain network.
|
|
241
250
|
*
|
|
251
|
+
* When `rpcVersion` was not specified, this tries JSON-RPC v2 first and
|
|
252
|
+
* transparently falls back to legacy if the node does not support v2.
|
|
253
|
+
*
|
|
242
254
|
* @returns This client instance for method chaining
|
|
243
255
|
*/
|
|
244
256
|
connect(): Promise<this>;
|
|
@@ -360,28 +372,30 @@ export declare class DedotClient<ChainApi extends GenericSubstrateApi = Substrat
|
|
|
360
372
|
*/
|
|
361
373
|
sendTx(tx: HexString | Extrinsic, callback?: Callback<ISubmittableResult<ChainApi['types']['EventRecord']>>): TxUnsub;
|
|
362
374
|
/**
|
|
363
|
-
* Convert a
|
|
375
|
+
* Convert a transaction input into a submittable extrinsic
|
|
364
376
|
* with `sign`, `signAndSend`, `send`, and `paymentInfo` methods.
|
|
365
377
|
*
|
|
366
|
-
* @param tx - A hex-encoded
|
|
378
|
+
* @param tx - A hex-encoded extrinsic or runtime call, a Uint8Array of encoded bytes,
|
|
379
|
+
* an Extrinsic instance, or an IRuntimeTxCall object.
|
|
380
|
+
* For HexString/Uint8Array, it first tries to decode as a full extrinsic;
|
|
381
|
+
* if that fails, it falls back to decoding as a raw runtime call.
|
|
367
382
|
* @returns A submittable extrinsic instance
|
|
368
383
|
*
|
|
369
384
|
* @example
|
|
370
385
|
* ```typescript
|
|
371
|
-
* //
|
|
386
|
+
* // From a raw hex extrinsic
|
|
372
387
|
* const submittable = client.toTx(rawTxHex);
|
|
373
388
|
*
|
|
389
|
+
* // From a runtime call object
|
|
390
|
+
* const submittable = client.toTx({ pallet: 'Balances', palletCall: { name: 'TransferKeepAlive', params: { dest, value } } });
|
|
391
|
+
*
|
|
374
392
|
* // Sign and send
|
|
375
393
|
* const unsub = await submittable.signAndSend(alice, (result) => {
|
|
376
394
|
* console.log('Status:', result.status);
|
|
377
395
|
* });
|
|
378
|
-
*
|
|
379
|
-
* // Or query payment info
|
|
380
|
-
* const paymentInfo = await submittable.paymentInfo(alice);
|
|
381
|
-
* console.log('Estimated fee:', paymentInfo.partialFee);
|
|
382
396
|
* ```
|
|
383
397
|
*/
|
|
384
|
-
toTx(tx: HexString | Extrinsic): ChainSubmittableExtrinsic<ChainApi>;
|
|
398
|
+
toTx(tx: HexString | Uint8Array | Extrinsic | IRuntimeTxCall): ChainSubmittableExtrinsic<ChainApi>;
|
|
385
399
|
/**
|
|
386
400
|
* Clear internal caches.
|
|
387
401
|
*
|
package/client/DedotClient.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JsonRpcV2NotSupportedError, noop } from '@dedot/utils';
|
|
1
2
|
import { isJsonRpcProvider } from '../json-rpc/index.js';
|
|
2
3
|
import { LegacyClient } from './LegacyClient.js';
|
|
3
4
|
import { V2Client } from './V2Client.js';
|
|
@@ -48,7 +49,12 @@ import { V2Client } from './V2Client.js';
|
|
|
48
49
|
*/
|
|
49
50
|
export class DedotClient {
|
|
50
51
|
#client;
|
|
51
|
-
|
|
52
|
+
#pendingOptions;
|
|
53
|
+
/**
|
|
54
|
+
* The JSON-RPC version being used ('v2' or 'legacy').
|
|
55
|
+
*
|
|
56
|
+
* In auto-detect mode (no `rpcVersion` option), this is resolved during `connect()`.
|
|
57
|
+
*/
|
|
52
58
|
rpcVersion;
|
|
53
59
|
/**
|
|
54
60
|
* Creates a new DedotClient instance.
|
|
@@ -58,18 +64,14 @@ export class DedotClient {
|
|
|
58
64
|
* @param options - Client configuration options or a JsonRpcProvider instance
|
|
59
65
|
*/
|
|
60
66
|
constructor(options) {
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
this.rpcVersion = rpcVersion;
|
|
68
|
-
if (this.rpcVersion === 'legacy') {
|
|
69
|
-
this.#client = new LegacyClient(options);
|
|
67
|
+
const explicitVersion = isJsonRpcProvider(options) ? undefined : options.rpcVersion;
|
|
68
|
+
if (explicitVersion) {
|
|
69
|
+
this.rpcVersion = explicitVersion;
|
|
70
|
+
this.#client =
|
|
71
|
+
explicitVersion === 'legacy' ? new LegacyClient(options) : new V2Client(options);
|
|
70
72
|
}
|
|
71
73
|
else {
|
|
72
|
-
this.#
|
|
74
|
+
this.#pendingOptions = options;
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
/**
|
|
@@ -281,10 +283,34 @@ export class DedotClient {
|
|
|
281
283
|
/**
|
|
282
284
|
* Establishes connection to the blockchain network.
|
|
283
285
|
*
|
|
286
|
+
* When `rpcVersion` was not specified, this tries JSON-RPC v2 first and
|
|
287
|
+
* transparently falls back to legacy if the node does not support v2.
|
|
288
|
+
*
|
|
284
289
|
* @returns This client instance for method chaining
|
|
285
290
|
*/
|
|
286
291
|
async connect() {
|
|
287
|
-
|
|
292
|
+
if (this.#client) {
|
|
293
|
+
await this.#client.connect();
|
|
294
|
+
return this;
|
|
295
|
+
}
|
|
296
|
+
const options = this.#pendingOptions;
|
|
297
|
+
this.#pendingOptions = undefined;
|
|
298
|
+
const v2 = new V2Client(options);
|
|
299
|
+
try {
|
|
300
|
+
await v2.connect();
|
|
301
|
+
this.#client = v2;
|
|
302
|
+
this.rpcVersion = 'v2';
|
|
303
|
+
}
|
|
304
|
+
catch (e) {
|
|
305
|
+
if (!(e instanceof JsonRpcV2NotSupportedError))
|
|
306
|
+
throw e;
|
|
307
|
+
console.warn('JSON-RPC v2 is not supported by the connected node, falling back to legacy JSON-RPC.');
|
|
308
|
+
await v2.disconnect().catch(noop);
|
|
309
|
+
const legacy = new LegacyClient(options);
|
|
310
|
+
await legacy.connect();
|
|
311
|
+
this.#client = legacy;
|
|
312
|
+
this.rpcVersion = 'legacy';
|
|
313
|
+
}
|
|
288
314
|
return this;
|
|
289
315
|
}
|
|
290
316
|
/**
|
|
@@ -392,25 +418,27 @@ export class DedotClient {
|
|
|
392
418
|
return this.#client.sendTx(tx, callback);
|
|
393
419
|
}
|
|
394
420
|
/**
|
|
395
|
-
* Convert a
|
|
421
|
+
* Convert a transaction input into a submittable extrinsic
|
|
396
422
|
* with `sign`, `signAndSend`, `send`, and `paymentInfo` methods.
|
|
397
423
|
*
|
|
398
|
-
* @param tx - A hex-encoded
|
|
424
|
+
* @param tx - A hex-encoded extrinsic or runtime call, a Uint8Array of encoded bytes,
|
|
425
|
+
* an Extrinsic instance, or an IRuntimeTxCall object.
|
|
426
|
+
* For HexString/Uint8Array, it first tries to decode as a full extrinsic;
|
|
427
|
+
* if that fails, it falls back to decoding as a raw runtime call.
|
|
399
428
|
* @returns A submittable extrinsic instance
|
|
400
429
|
*
|
|
401
430
|
* @example
|
|
402
431
|
* ```typescript
|
|
403
|
-
* //
|
|
432
|
+
* // From a raw hex extrinsic
|
|
404
433
|
* const submittable = client.toTx(rawTxHex);
|
|
405
434
|
*
|
|
435
|
+
* // From a runtime call object
|
|
436
|
+
* const submittable = client.toTx({ pallet: 'Balances', palletCall: { name: 'TransferKeepAlive', params: { dest, value } } });
|
|
437
|
+
*
|
|
406
438
|
* // Sign and send
|
|
407
439
|
* const unsub = await submittable.signAndSend(alice, (result) => {
|
|
408
440
|
* console.log('Status:', result.status);
|
|
409
441
|
* });
|
|
410
|
-
*
|
|
411
|
-
* // Or query payment info
|
|
412
|
-
* const paymentInfo = await submittable.paymentInfo(alice);
|
|
413
|
-
* console.log('Estimated fee:', paymentInfo.partialFee);
|
|
414
442
|
* ```
|
|
415
443
|
*/
|
|
416
444
|
toTx(tx) {
|
package/client/LegacyClient.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BlockHash, type Extrinsic, Metadata } from '@dedot/codecs';
|
|
2
2
|
import type { JsonRpcProvider } from '@dedot/providers';
|
|
3
|
-
import { Callback, ChainSubmittableExtrinsic, GenericSubstrateApi, ISubmittableResult, TxUnsub } from '@dedot/types';
|
|
3
|
+
import { Callback, ChainSubmittableExtrinsic, GenericSubstrateApi, IRuntimeTxCall, ISubmittableResult, TxUnsub } from '@dedot/types';
|
|
4
4
|
import { HexString } from '@dedot/utils';
|
|
5
5
|
import type { SubstrateApi } from '../chaintypes/index.js';
|
|
6
6
|
import { BaseStorageQuery } from '../storage/index.js';
|
|
@@ -137,5 +137,5 @@ export declare class LegacyClient<ChainApi extends GenericSubstrateApi = Substra
|
|
|
137
137
|
at<ChainApiAt extends GenericSubstrateApi = ChainApi>(hash: BlockHash): Promise<ISubstrateClientAt<ChainApiAt>>;
|
|
138
138
|
protected getStorageQuery(): BaseStorageQuery;
|
|
139
139
|
sendTx(tx: HexString | Extrinsic, callback?: Callback<ISubmittableResult<ChainApi['types']['EventRecord']>>): TxUnsub;
|
|
140
|
-
toTx(tx: HexString | Extrinsic): ChainSubmittableExtrinsic<ChainApi>;
|
|
140
|
+
toTx(tx: HexString | Uint8Array | Extrinsic | IRuntimeTxCall): ChainSubmittableExtrinsic<ChainApi>;
|
|
141
141
|
}
|
package/client/V2Client.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BlockHash, type Extrinsic, Metadata } from '@dedot/codecs';
|
|
2
2
|
import type { JsonRpcProvider } from '@dedot/providers';
|
|
3
|
-
import { Callback, ChainSubmittableExtrinsic, GenericSubstrateApi, ISubmittableResult, TxUnsub } from '@dedot/types';
|
|
3
|
+
import { Callback, ChainSubmittableExtrinsic, GenericSubstrateApi, IRuntimeTxCall, ISubmittableResult, TxUnsub } from '@dedot/types';
|
|
4
4
|
import { HexString } from '@dedot/utils';
|
|
5
5
|
import type { SubstrateApi } from '../chaintypes/index.js';
|
|
6
6
|
import { Archive, ChainHead, ChainSpec, PinnedBlock } from '../json-rpc/index.js';
|
|
@@ -72,5 +72,5 @@ export declare class V2Client<ChainApi extends GenericSubstrateApi = SubstrateAp
|
|
|
72
72
|
at<ChainApiAt extends GenericSubstrateApi = ChainApi>(hash: BlockHash): Promise<ISubstrateClientAt<ChainApiAt>>;
|
|
73
73
|
protected getStorageQuery(): BaseStorageQuery;
|
|
74
74
|
sendTx(tx: HexString | Extrinsic, callback?: Callback<ISubmittableResult<ChainApi['types']['EventRecord']>>): TxUnsub;
|
|
75
|
-
toTx(tx: HexString | Extrinsic): ChainSubmittableExtrinsic<ChainApi>;
|
|
75
|
+
toTx(tx: HexString | Uint8Array | Extrinsic | IRuntimeTxCall): ChainSubmittableExtrinsic<ChainApi>;
|
|
76
76
|
}
|
package/client/V2Client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { $H256, $Header, $RuntimeVersion, PortableRegistry, } from '@dedot/codecs';
|
|
2
2
|
import { u32 } from '@dedot/shape';
|
|
3
|
-
import { assert, concatU8a, DedotError, twox64Concat, u8aToHex, xxhashAsU8a } from '@dedot/utils';
|
|
3
|
+
import { assert, concatU8a, DedotError, JsonRpcV2NotSupportedError, twox64Concat, u8aToHex, xxhashAsU8a, } from '@dedot/utils';
|
|
4
4
|
import { ConstantExecutor, ErrorExecutor, EventExecutor, RuntimeApiExecutorV2, StorageQueryExecutorV2, TxExecutorV2, ViewFunctionExecutorV2, } from '../executor/index.js';
|
|
5
5
|
import { SubmittableExtrinsicV2 } from '../extrinsic/submittable/SubmittableExtrinsicV2.js';
|
|
6
6
|
import { Archive, ChainHead, ChainSpec, Transaction, TransactionWatch } from '../json-rpc/index.js';
|
|
@@ -75,6 +75,10 @@ export class V2Client// prettier-end-here
|
|
|
75
75
|
const shouldInitialize = !this._genesisHash;
|
|
76
76
|
if (shouldInitialize) {
|
|
77
77
|
const rpcMethods = (await this.rpc.rpc_methods()).methods;
|
|
78
|
+
if (!rpcMethods.some((m) => m.startsWith('chainHead_'))) {
|
|
79
|
+
throw new JsonRpcV2NotSupportedError('The connected node does not support JSON-RPC v2 (no chainHead_* methods). ' +
|
|
80
|
+
'Omit `rpcVersion` to auto-detect, or pass `rpcVersion: "legacy"`.');
|
|
81
|
+
}
|
|
78
82
|
this._chainHead = new ChainHead(this, { rpcMethods });
|
|
79
83
|
this._chainSpec = new ChainSpec(this, { rpcMethods });
|
|
80
84
|
// Always initialize Archive, but only set up fallback if supported
|
|
@@ -10,9 +10,17 @@ export const MORTAL_PERIOD = 12 * 60 * 1000;
|
|
|
10
10
|
export class CheckMortality extends SignedExtension {
|
|
11
11
|
#signingHeader;
|
|
12
12
|
async init() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const mortality = this.payloadOptions.mortality;
|
|
14
|
+
if (mortality?.type === 'Immortal') {
|
|
15
|
+
this.data = { type: 'Immortal' };
|
|
16
|
+
this.additionalSigned = this.client.genesisHash;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
this.#signingHeader = await this.#getSigningHeader();
|
|
20
|
+
const period = mortality?.type === 'Mortal' ? BigInt(mortality.period) : this.#calculateMortalLength();
|
|
21
|
+
this.data = { period, current: BigInt(this.#signingHeader.number) };
|
|
22
|
+
this.additionalSigned = this.#signingHeader.hash;
|
|
23
|
+
}
|
|
16
24
|
}
|
|
17
25
|
async fromPayload(payload) {
|
|
18
26
|
const { era, blockHash, blockNumber } = payload;
|
|
@@ -85,7 +93,7 @@ export class CheckMortality extends SignedExtension {
|
|
|
85
93
|
return {
|
|
86
94
|
era: u8aToHex(this.$Data.tryEncode(this.data)),
|
|
87
95
|
blockHash: this.additionalSigned,
|
|
88
|
-
blockNumber: numberToHex(this.#signingHeader
|
|
96
|
+
blockNumber: numberToHex(this.#signingHeader?.number ?? 0),
|
|
89
97
|
};
|
|
90
98
|
}
|
|
91
99
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BlockHash, Extrinsic } from '@dedot/codecs';
|
|
2
|
-
import { AddressOrPair, Callback, DryRunResult, ISubmittableExtrinsicLegacy, ISubmittableResult, SignerOptions, TxHash, TxUnsub } from '@dedot/types';
|
|
2
|
+
import { AddressOrPair, Callback, DryRunResult, IRuntimeTxCall, ISubmittableExtrinsicLegacy, ISubmittableResult, SignerOptions, TxHash, TxUnsub } from '@dedot/types';
|
|
3
3
|
import { HexString } from '@dedot/utils';
|
|
4
4
|
import { LegacyClient } from '../../client/LegacyClient.js';
|
|
5
5
|
import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
|
|
@@ -8,7 +8,7 @@ import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
|
|
|
8
8
|
* @description A wrapper around an Extrinsic that exposes methods to sign, send, and other utility around Extrinsic.
|
|
9
9
|
*/
|
|
10
10
|
export declare class SubmittableExtrinsic extends BaseSubmittableExtrinsic implements ISubmittableExtrinsicLegacy {
|
|
11
|
-
static fromTx(client: LegacyClient<any>, tx: HexString | Extrinsic): SubmittableExtrinsic;
|
|
11
|
+
static fromTx(client: LegacyClient<any>, tx: HexString | Uint8Array | Extrinsic | IRuntimeTxCall): SubmittableExtrinsic;
|
|
12
12
|
dryRun(account: AddressOrPair, optionsOrHash?: Partial<SignerOptions> | BlockHash): Promise<DryRunResult>;
|
|
13
13
|
send(): TxHash;
|
|
14
14
|
send(callback: Callback<ISubmittableResult>): TxUnsub;
|
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
import { assert, isHex, noop } from '@dedot/utils';
|
|
2
2
|
import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
|
|
3
3
|
import { SubmittableResult } from './SubmittableResult.js';
|
|
4
|
-
import { toTxStatus, txDefer } from './utils.js';
|
|
4
|
+
import { resolveCallAndPreamble, toTxStatus, txDefer } from './utils.js';
|
|
5
5
|
/**
|
|
6
6
|
* @name SubmittableExtrinsic
|
|
7
7
|
* @description A wrapper around an Extrinsic that exposes methods to sign, send, and other utility around Extrinsic.
|
|
8
8
|
*/
|
|
9
9
|
export class SubmittableExtrinsic extends BaseSubmittableExtrinsic {
|
|
10
10
|
static fromTx(client, tx) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
extrinsic = client.registry.$Extrinsic.tryDecode(tx);
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
extrinsic = tx;
|
|
17
|
-
}
|
|
18
|
-
return new SubmittableExtrinsic(client, extrinsic.call, extrinsic.preamble);
|
|
11
|
+
const { call, preamble } = resolveCallAndPreamble(client.registry, tx);
|
|
12
|
+
return new SubmittableExtrinsic(client, call, preamble);
|
|
19
13
|
}
|
|
20
14
|
async dryRun(account, optionsOrHash) {
|
|
21
15
|
const dryRunFn = this.client.rpc.system_dryRun;
|
|
@@ -11,7 +11,7 @@ export declare class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic {
|
|
|
11
11
|
#private;
|
|
12
12
|
client: V2Client<any>;
|
|
13
13
|
constructor(client: V2Client<any>, call: IRuntimeTxCall, preamble?: Preamble);
|
|
14
|
-
static fromTx(client: V2Client<any>, tx: HexString | Extrinsic): SubmittableExtrinsicV2;
|
|
14
|
+
static fromTx(client: V2Client<any>, tx: HexString | Uint8Array | Extrinsic | IRuntimeTxCall): SubmittableExtrinsicV2;
|
|
15
15
|
send(): TxHash;
|
|
16
16
|
send(callback: Callback<ISubmittableResult>): TxUnsub;
|
|
17
17
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { AsyncQueue,
|
|
1
|
+
import { AsyncQueue, noop, waitFor } from '@dedot/utils';
|
|
2
2
|
import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
|
|
3
3
|
import { SubmittableResult } from './SubmittableResult.js';
|
|
4
4
|
import { InvalidTxError } from './errors.js';
|
|
5
|
-
import { txDefer } from './utils.js';
|
|
5
|
+
import { resolveCallAndPreamble, txDefer } from './utils.js';
|
|
6
6
|
/**
|
|
7
7
|
* @name SubmittableExtrinsicV2
|
|
8
8
|
* @description Submittable extrinsic based on JSON-RPC v2
|
|
@@ -14,14 +14,8 @@ export class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic {
|
|
|
14
14
|
this.client = client;
|
|
15
15
|
}
|
|
16
16
|
static fromTx(client, tx) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
extrinsic = client.registry.$Extrinsic.tryDecode(tx);
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
extrinsic = tx;
|
|
23
|
-
}
|
|
24
|
-
return new SubmittableExtrinsicV2(client, extrinsic.call, extrinsic.preamble);
|
|
17
|
+
const { call, preamble } = resolveCallAndPreamble(client.registry, tx);
|
|
18
|
+
return new SubmittableExtrinsicV2(client, call, preamble);
|
|
25
19
|
}
|
|
26
20
|
async #send(callback) {
|
|
27
21
|
const api = this.client;
|
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
import { TransactionStatus } from '@dedot/codecs';
|
|
2
|
-
import { AddressOrPair, IKeyringPair, ISubmittableResult, TxStatus, Unsub } from '@dedot/types';
|
|
1
|
+
import { Extrinsic, Preamble, PortableRegistry, TransactionStatus } from '@dedot/codecs';
|
|
2
|
+
import { AddressOrPair, IKeyringPair, IRuntimeTxCall, ISubmittableResult, TxStatus, Unsub } from '@dedot/types';
|
|
3
3
|
import { Deferred, HexString } from '@dedot/utils';
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a transaction input into a call and optional preamble.
|
|
6
|
+
*
|
|
7
|
+
* Supports:
|
|
8
|
+
* - `Extrinsic` instance: extract call + preamble
|
|
9
|
+
* - `IRuntimeTxCall` object: use directly as call, no preamble
|
|
10
|
+
* - `HexString` or `Uint8Array`: try decode as extrinsic first, fallback to runtime call
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveCallAndPreamble(registry: PortableRegistry, tx: HexString | Uint8Array | Extrinsic | IRuntimeTxCall): {
|
|
13
|
+
call: IRuntimeTxCall;
|
|
14
|
+
preamble?: Preamble;
|
|
15
|
+
};
|
|
4
16
|
export declare function isKeyringPair(account: AddressOrPair): account is IKeyringPair;
|
|
5
17
|
/**
|
|
6
18
|
* Sign a raw message
|
|
@@ -1,5 +1,39 @@
|
|
|
1
|
+
import { Extrinsic } from '@dedot/codecs';
|
|
1
2
|
import { assert, blake2AsU8a, deferred, hexToU8a, isFunction } from '@dedot/utils';
|
|
2
3
|
import { RejectedTxError } from './errors.js';
|
|
4
|
+
/**
|
|
5
|
+
* Check if a value is an IRuntimeTxCall object (has a 'pallet' property).
|
|
6
|
+
*/
|
|
7
|
+
function isRuntimeTxCall(tx) {
|
|
8
|
+
return typeof tx === 'object' && tx !== null && 'pallet' in tx;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a transaction input into a call and optional preamble.
|
|
12
|
+
*
|
|
13
|
+
* Supports:
|
|
14
|
+
* - `Extrinsic` instance: extract call + preamble
|
|
15
|
+
* - `IRuntimeTxCall` object: use directly as call, no preamble
|
|
16
|
+
* - `HexString` or `Uint8Array`: try decode as extrinsic first, fallback to runtime call
|
|
17
|
+
*/
|
|
18
|
+
export function resolveCallAndPreamble(registry, tx) {
|
|
19
|
+
if (tx instanceof Extrinsic) {
|
|
20
|
+
return { call: tx.call, preamble: tx.preamble };
|
|
21
|
+
}
|
|
22
|
+
if (isRuntimeTxCall(tx)) {
|
|
23
|
+
return { call: tx };
|
|
24
|
+
}
|
|
25
|
+
// HexString or Uint8Array: try extrinsic decode first, fallback to runtime call
|
|
26
|
+
try {
|
|
27
|
+
const extrinsic = registry.$Extrinsic.tryDecode(tx);
|
|
28
|
+
return { call: extrinsic.call, preamble: extrinsic.preamble };
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
const { callTypeId } = registry.metadata.extrinsic;
|
|
32
|
+
const $RuntimeCall = registry.findCodec(callTypeId);
|
|
33
|
+
const call = $RuntimeCall.tryDecode(tx);
|
|
34
|
+
return { call };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
3
37
|
export function isKeyringPair(account) {
|
|
4
38
|
return isFunction(account.sign);
|
|
5
39
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dedot/api",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.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": "^1.
|
|
17
|
-
"@dedot/providers": "^1.
|
|
18
|
-
"@dedot/runtime-specs": "^1.
|
|
19
|
-
"@dedot/shape": "^1.
|
|
20
|
-
"@dedot/storage": "^1.
|
|
21
|
-
"@dedot/types": "^1.
|
|
22
|
-
"@dedot/utils": "^1.
|
|
16
|
+
"@dedot/codecs": "^1.3.0",
|
|
17
|
+
"@dedot/providers": "^1.3.0",
|
|
18
|
+
"@dedot/runtime-specs": "^1.3.0",
|
|
19
|
+
"@dedot/shape": "^1.3.0",
|
|
20
|
+
"@dedot/storage": "^1.3.0",
|
|
21
|
+
"@dedot/types": "^1.3.0",
|
|
22
|
+
"@dedot/utils": "^1.3.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": "1179ba75b371517a21eb1162881e6e4c655514a0",
|
|
52
52
|
"module": "./index.js",
|
|
53
53
|
"types": "./index.d.ts"
|
|
54
54
|
}
|
package/types.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { BlockHash, Extrinsic, Hash, Header, Metadata, PortableRegistry } from '
|
|
|
2
2
|
import type { ConnectionStatus, JsonRpcProvider, ProviderEvent } from '@dedot/providers';
|
|
3
3
|
import type { AnyShape } from '@dedot/shape';
|
|
4
4
|
import type { IStorage } from '@dedot/storage';
|
|
5
|
-
import { Callback, ChainSubmittableExtrinsic, GenericStorageQuery, GenericSubstrateApi, InjectedSigner, ISubmittableResult, Query, QueryFnResult, RpcVersion, RuntimeApiName, RuntimeApiSpec, TxUnsub, Unsub } from '@dedot/types';
|
|
5
|
+
import { Callback, ChainSubmittableExtrinsic, GenericStorageQuery, GenericSubstrateApi, InjectedSigner, IRuntimeTxCall, ISubmittableResult, Query, QueryFnResult, RpcVersion, RuntimeApiName, RuntimeApiSpec, TxUnsub, Unsub } from '@dedot/types';
|
|
6
6
|
import { Properties } from '@dedot/types/json-rpc';
|
|
7
7
|
import type { HashFn, HexString, IEventEmitter } from '@dedot/utils';
|
|
8
8
|
import type { SubstrateApi } from './chaintypes/index.js';
|
|
@@ -226,28 +226,36 @@ Events extends string = ApiEvent> extends IJsonRpcClient<ChainApi, Events>, IGen
|
|
|
226
226
|
*/
|
|
227
227
|
sendTx(tx: HexString | Extrinsic, callback?: Callback<ISubmittableResult<ChainApi['types']['EventRecord']>>): TxUnsub;
|
|
228
228
|
/**
|
|
229
|
-
* Convert a
|
|
229
|
+
* Convert a transaction input into a submittable extrinsic
|
|
230
230
|
* with `sign`, `signAndSend`, `send`, and `paymentInfo` methods.
|
|
231
231
|
*
|
|
232
|
-
* @param tx - A hex-encoded
|
|
232
|
+
* @param tx - A hex-encoded extrinsic or runtime call, a Uint8Array of encoded bytes,
|
|
233
|
+
* an Extrinsic instance, or an IRuntimeTxCall object.
|
|
234
|
+
* For HexString/Uint8Array, it first tries to decode as a full extrinsic;
|
|
235
|
+
* if that fails, it falls back to decoding as a raw runtime call.
|
|
233
236
|
* @returns A submittable extrinsic instance
|
|
234
237
|
*
|
|
235
238
|
* @example
|
|
236
239
|
* ```typescript
|
|
237
|
-
* //
|
|
240
|
+
* // From a raw hex extrinsic
|
|
238
241
|
* const submittable = client.toTx(rawTxHex);
|
|
239
242
|
*
|
|
243
|
+
* // From a runtime call hex (encoded call data)
|
|
244
|
+
* const submittable = client.toTx(runtimeCallHex);
|
|
245
|
+
*
|
|
246
|
+
* // From a Uint8Array
|
|
247
|
+
* const submittable = client.toTx(callBytes);
|
|
248
|
+
*
|
|
249
|
+
* // From a runtime call object
|
|
250
|
+
* const submittable = client.toTx({ pallet: 'Balances', palletCall: { name: 'TransferKeepAlive', params: { dest, value } } });
|
|
251
|
+
*
|
|
240
252
|
* // Sign and send
|
|
241
253
|
* const unsub = await submittable.signAndSend(alice, (result) => {
|
|
242
254
|
* console.log('Status:', result.status);
|
|
243
255
|
* });
|
|
244
|
-
*
|
|
245
|
-
* // Or query payment info
|
|
246
|
-
* const paymentInfo = await submittable.paymentInfo(alice);
|
|
247
|
-
* console.log('Estimated fee:', paymentInfo.partialFee);
|
|
248
256
|
* ```
|
|
249
257
|
*/
|
|
250
|
-
toTx(tx: HexString | Extrinsic): ChainSubmittableExtrinsic<ChainApi>;
|
|
258
|
+
toTx(tx: HexString | Uint8Array | Extrinsic | IRuntimeTxCall): ChainSubmittableExtrinsic<ChainApi>;
|
|
251
259
|
/**
|
|
252
260
|
* Query multiple storage items in a single call or subscribe to multiple storage items
|
|
253
261
|
*
|