@dedot/api 1.1.1 → 1.2.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.
@@ -395,25 +395,27 @@ class DedotClient {
395
395
  return this.#client.sendTx(tx, callback);
396
396
  }
397
397
  /**
398
- * Convert a raw hex-encoded transaction or an Extrinsic instance into a submittable extrinsic
398
+ * Convert a transaction input into a submittable extrinsic
399
399
  * with `sign`, `signAndSend`, `send`, and `paymentInfo` methods.
400
400
  *
401
- * @param tx - A hex-encoded transaction string or an Extrinsic instance
401
+ * @param tx - A hex-encoded extrinsic or runtime call, a Uint8Array of encoded bytes,
402
+ * an Extrinsic instance, or an IRuntimeTxCall object.
403
+ * For HexString/Uint8Array, it first tries to decode as a full extrinsic;
404
+ * if that fails, it falls back to decoding as a raw runtime call.
402
405
  * @returns A submittable extrinsic instance
403
406
  *
404
407
  * @example
405
408
  * ```typescript
406
- * // Convert a raw hex transaction to a submittable extrinsic
409
+ * // From a raw hex extrinsic
407
410
  * const submittable = client.toTx(rawTxHex);
408
411
  *
412
+ * // From a runtime call object
413
+ * const submittable = client.toTx({ pallet: 'Balances', palletCall: { name: 'TransferKeepAlive', params: { dest, value } } });
414
+ *
409
415
  * // Sign and send
410
416
  * const unsub = await submittable.signAndSend(alice, (result) => {
411
417
  * console.log('Status:', result.status);
412
418
  * });
413
- *
414
- * // Or query payment info
415
- * const paymentInfo = await submittable.paymentInfo(alice);
416
- * console.log('Estimated fee:', paymentInfo.partialFee);
417
419
  * ```
418
420
  */
419
421
  toTx(tx) {
@@ -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
- this.#signingHeader = await this.#getSigningHeader();
17
- this.data = { period: this.#calculateMortalLength(), current: BigInt(this.#signingHeader.number) };
18
- this.additionalSigned = this.#signingHeader.hash;
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.number),
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
- let extrinsic;
15
- if ((0, utils_1.isHex)(tx)) {
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
- let extrinsic;
21
- if ((0, utils_1.isHex)(tx)) {
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
  }
@@ -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';
@@ -360,28 +360,30 @@ export declare class DedotClient<ChainApi extends GenericSubstrateApi = Substrat
360
360
  */
361
361
  sendTx(tx: HexString | Extrinsic, callback?: Callback<ISubmittableResult<ChainApi['types']['EventRecord']>>): TxUnsub;
362
362
  /**
363
- * Convert a raw hex-encoded transaction or an Extrinsic instance into a submittable extrinsic
363
+ * Convert a transaction input into a submittable extrinsic
364
364
  * with `sign`, `signAndSend`, `send`, and `paymentInfo` methods.
365
365
  *
366
- * @param tx - A hex-encoded transaction string or an Extrinsic instance
366
+ * @param tx - A hex-encoded extrinsic or runtime call, a Uint8Array of encoded bytes,
367
+ * an Extrinsic instance, or an IRuntimeTxCall object.
368
+ * For HexString/Uint8Array, it first tries to decode as a full extrinsic;
369
+ * if that fails, it falls back to decoding as a raw runtime call.
367
370
  * @returns A submittable extrinsic instance
368
371
  *
369
372
  * @example
370
373
  * ```typescript
371
- * // Convert a raw hex transaction to a submittable extrinsic
374
+ * // From a raw hex extrinsic
372
375
  * const submittable = client.toTx(rawTxHex);
373
376
  *
377
+ * // From a runtime call object
378
+ * const submittable = client.toTx({ pallet: 'Balances', palletCall: { name: 'TransferKeepAlive', params: { dest, value } } });
379
+ *
374
380
  * // Sign and send
375
381
  * const unsub = await submittable.signAndSend(alice, (result) => {
376
382
  * console.log('Status:', result.status);
377
383
  * });
378
- *
379
- * // Or query payment info
380
- * const paymentInfo = await submittable.paymentInfo(alice);
381
- * console.log('Estimated fee:', paymentInfo.partialFee);
382
384
  * ```
383
385
  */
384
- toTx(tx: HexString | Extrinsic): ChainSubmittableExtrinsic<ChainApi>;
386
+ toTx(tx: HexString | Uint8Array | Extrinsic | IRuntimeTxCall): ChainSubmittableExtrinsic<ChainApi>;
385
387
  /**
386
388
  * Clear internal caches.
387
389
  *
@@ -392,25 +392,27 @@ export class DedotClient {
392
392
  return this.#client.sendTx(tx, callback);
393
393
  }
394
394
  /**
395
- * Convert a raw hex-encoded transaction or an Extrinsic instance into a submittable extrinsic
395
+ * Convert a transaction input into a submittable extrinsic
396
396
  * with `sign`, `signAndSend`, `send`, and `paymentInfo` methods.
397
397
  *
398
- * @param tx - A hex-encoded transaction string or an Extrinsic instance
398
+ * @param tx - A hex-encoded extrinsic or runtime call, a Uint8Array of encoded bytes,
399
+ * an Extrinsic instance, or an IRuntimeTxCall object.
400
+ * For HexString/Uint8Array, it first tries to decode as a full extrinsic;
401
+ * if that fails, it falls back to decoding as a raw runtime call.
399
402
  * @returns A submittable extrinsic instance
400
403
  *
401
404
  * @example
402
405
  * ```typescript
403
- * // Convert a raw hex transaction to a submittable extrinsic
406
+ * // From a raw hex extrinsic
404
407
  * const submittable = client.toTx(rawTxHex);
405
408
  *
409
+ * // From a runtime call object
410
+ * const submittable = client.toTx({ pallet: 'Balances', palletCall: { name: 'TransferKeepAlive', params: { dest, value } } });
411
+ *
406
412
  * // Sign and send
407
413
  * const unsub = await submittable.signAndSend(alice, (result) => {
408
414
  * console.log('Status:', result.status);
409
415
  * });
410
- *
411
- * // Or query payment info
412
- * const paymentInfo = await submittable.paymentInfo(alice);
413
- * console.log('Estimated fee:', paymentInfo.partialFee);
414
416
  * ```
415
417
  */
416
418
  toTx(tx) {
@@ -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
  }
@@ -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
  }
@@ -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
- this.#signingHeader = await this.#getSigningHeader();
14
- this.data = { period: this.#calculateMortalLength(), current: BigInt(this.#signingHeader.number) };
15
- this.additionalSigned = this.#signingHeader.hash;
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.number),
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
- let extrinsic;
12
- if (isHex(tx)) {
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, isHex, noop, waitFor } from '@dedot/utils';
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
- let extrinsic;
18
- if (isHex(tx)) {
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.1.1",
3
+ "version": "1.2.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.1.1",
17
- "@dedot/providers": "^1.1.1",
18
- "@dedot/runtime-specs": "^1.1.1",
19
- "@dedot/shape": "^1.1.1",
20
- "@dedot/storage": "^1.1.1",
21
- "@dedot/types": "^1.1.1",
22
- "@dedot/utils": "^1.1.1"
16
+ "@dedot/codecs": "^1.2.0",
17
+ "@dedot/providers": "^1.2.0",
18
+ "@dedot/runtime-specs": "^1.2.0",
19
+ "@dedot/shape": "^1.2.0",
20
+ "@dedot/storage": "^1.2.0",
21
+ "@dedot/types": "^1.2.0",
22
+ "@dedot/utils": "^1.2.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": "d64c5da3433f21b17fcf1e431235b8694ed11fa2",
51
+ "gitHead": "d0da366e311d33389d0fd1b9e9435c1d61da5799",
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 raw hex-encoded transaction or an Extrinsic instance into a submittable extrinsic
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 transaction string or an Extrinsic instance
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
- * // Convert a raw hex transaction to a submittable extrinsic
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
  *