@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
@@ -0,0 +1,174 @@
1
+ import { ApiCompatibilityError, isNumber } from '@dedot/utils';
2
+ /**
3
+ * Check if a codec is an Option type
4
+ */
5
+ export function isOptionCodec(codec) {
6
+ try {
7
+ const metadata = codec?.metadata?.[0];
8
+ return metadata?.name === '$.option';
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ /**
15
+ * Check if a parameter is optional (wrapped in Option)
16
+ */
17
+ export function isOptionalParam(param, registry) {
18
+ // Check direct codec first
19
+ if (param.codec) {
20
+ return isOptionCodec(param.codec);
21
+ }
22
+ // Check via typeId using registry
23
+ if (isNumber(param.typeId)) {
24
+ try {
25
+ const type = registry.findType(param.typeId);
26
+ return type.typeDef.type === 'Enum' && type.path.join('::') === 'Option';
27
+ }
28
+ catch {
29
+ // ignore
30
+ }
31
+ }
32
+ return false;
33
+ }
34
+ /**
35
+ * Pad args array with undefined for missing trailing optional parameters.
36
+ * This allows users to omit optional parameters at the end of the parameter list.
37
+ */
38
+ export function padArgsForOptionalParams(args, params, registry) {
39
+ // If args already match params length, no padding needed
40
+ if (args.length === params.length) {
41
+ return args;
42
+ }
43
+ // If more args than params, validation will fail later
44
+ if (args.length > params.length) {
45
+ return args;
46
+ }
47
+ // Check that all missing parameters are optional
48
+ for (let i = args.length; i < params.length; i++) {
49
+ const param = params[i];
50
+ if (!isOptionalParam(param, registry)) {
51
+ // Required parameter is missing, let the validation fail naturally
52
+ return args;
53
+ }
54
+ }
55
+ // All missing parameters are optional, pad with undefined
56
+ return [...args, ...Array(params.length - args.length).fill(undefined)];
57
+ }
58
+ /**
59
+ * Format a value for display in error messages
60
+ * Stringifies and truncates to 20 characters max
61
+ */
62
+ function formatValue(value) {
63
+ try {
64
+ let str;
65
+ if (typeof value === 'string') {
66
+ str = JSON.stringify(value);
67
+ }
68
+ else if (typeof value === 'undefined') {
69
+ str = 'undefined';
70
+ }
71
+ else if (value === null) {
72
+ str = 'null';
73
+ }
74
+ else if (typeof value === 'bigint') {
75
+ str = `${value}n`;
76
+ }
77
+ else if (typeof value === 'object') {
78
+ // For objects/arrays, use JSON.stringify
79
+ str = JSON.stringify(value);
80
+ }
81
+ else {
82
+ str = String(value);
83
+ }
84
+ // Truncate to 20 characters
85
+ if (str.length > 20) {
86
+ return str.slice(0, 20) + '...';
87
+ }
88
+ return str;
89
+ }
90
+ catch {
91
+ return '[complex value]';
92
+ }
93
+ }
94
+ /**
95
+ * Build a comprehensive API compatibility error with detailed information
96
+ */
97
+ export function buildCompatibilityError(originalError, params, args, context) {
98
+ const lines = [];
99
+ // Header
100
+ if (context.itemIndex !== undefined) {
101
+ lines.push(`API Compatibility Error: ${context.apiName} (item ${context.itemIndex})`);
102
+ }
103
+ else {
104
+ lines.push(`API Compatibility Error: ${context.apiName}`);
105
+ }
106
+ lines.push('');
107
+ // Check parameter count mismatch
108
+ if (args.length !== params.length) {
109
+ lines.push(`Expected ${params.length} parameter${params.length !== 1 ? 's' : ''} but received ${args.length}`);
110
+ lines.push('');
111
+ }
112
+ // Validate each parameter and report errors
113
+ const paramErrors = [];
114
+ const maxParams = Math.max(args.length, params.length);
115
+ for (let i = 0; i < maxParams; i++) {
116
+ const param = params[i];
117
+ const value = args[i];
118
+ if (!param) {
119
+ // Extra argument provided
120
+ paramErrors.push(` [${i}] (unexpected) - value: ${formatValue(value)}`);
121
+ continue;
122
+ }
123
+ if (value === undefined && i >= args.length) {
124
+ // Missing argument - check if it's actually optional
125
+ const isOptional = isOptionalParam(param, context.registry);
126
+ if (isOptional) {
127
+ paramErrors.push(` [${i}] ${param.name}: omitted (optional)`);
128
+ }
129
+ else {
130
+ paramErrors.push(` [${i}] ${param.name}: ✗ required parameter missing - value: undefined`);
131
+ }
132
+ continue;
133
+ }
134
+ // Try to validate the parameter
135
+ try {
136
+ const $codec = findCodec(param, context.registry);
137
+ if ($codec) {
138
+ $codec.assert?.(value);
139
+ // Valid parameter
140
+ paramErrors.push(` [${i}] ${param.name}: ✓ valid`);
141
+ }
142
+ }
143
+ catch (error) {
144
+ // Invalid parameter
145
+ paramErrors.push(` [${i}] ${param.name}: ✗ invalid input type - value: ${formatValue(value)}`);
146
+ }
147
+ }
148
+ if (paramErrors.length > 0) {
149
+ lines.push('Parameters:');
150
+ lines.push(...paramErrors);
151
+ lines.push('');
152
+ }
153
+ // Add suggestion
154
+ lines.push('This may indicate your chaintypes definitions are outdated.');
155
+ lines.push('Consider regenerating chaintypes with:');
156
+ lines.push(' npx dedot chaintypes -w <your-chain-endpoint>');
157
+ return new ApiCompatibilityError(lines.join('\n'));
158
+ }
159
+ /**
160
+ * Find codec for a parameter (internal helper)
161
+ */
162
+ function findCodec(param, registry) {
163
+ if (param.codec)
164
+ return param.codec;
165
+ if (isNumber(param.typeId)) {
166
+ try {
167
+ return registry.findCodec(param.typeId);
168
+ }
169
+ catch {
170
+ // ignore
171
+ }
172
+ }
173
+ return undefined;
174
+ }
@@ -35,7 +35,7 @@ export declare abstract class SignedExtension<Data extends any = {}, AdditionalS
35
35
  typeId: number;
36
36
  additionalSigned: number;
37
37
  };
38
- get payloadOptions(): Partial<PayloadOptions>;
38
+ get payloadOptions(): Partial<PayloadOptions<any>>;
39
39
  toPayload(...args: any[]): Partial<SignerPayloadJSON>;
40
40
  }
41
41
  export {};
@@ -1,4 +1,4 @@
1
- import { BlockHash, Extrinsic } from '@dedot/codecs';
1
+ import { BlockHash, Extrinsic, Preamble } from '@dedot/codecs';
2
2
  import { AddressOrPair, Callback, IRuntimeTxCall, ISubmittableExtrinsic, ISubmittableResult, PayloadOptions, SignerOptions, TxHash, TxPaymentInfo, TxUnsub } from '@dedot/types';
3
3
  import { HexString } from '@dedot/utils';
4
4
  import type { FrameSystemEventRecord } from '../../chaintypes/index.js';
@@ -9,8 +9,8 @@ interface TxHooks {
9
9
  }
10
10
  export declare abstract class BaseSubmittableExtrinsic extends Extrinsic implements ISubmittableExtrinsic {
11
11
  #private;
12
- readonly client: ISubstrateClient<any>;
13
- constructor(client: ISubstrateClient<any>, call: IRuntimeTxCall);
12
+ readonly client: ISubstrateClient<any, any>;
13
+ constructor(client: ISubstrateClient<any, any>, call: IRuntimeTxCall, preamble?: Preamble);
14
14
  withHooks(hooks: TxHooks): void;
15
15
  protected transformTxResult<R extends ISubmittableResult = ISubmittableResult>(result: ISubmittableResult): R;
16
16
  paymentInfo(account: AddressOrPair, options?: Partial<PayloadOptions>): Promise<TxPaymentInfo>;
@@ -21,6 +21,10 @@ export declare abstract class BaseSubmittableExtrinsic extends Extrinsic impleme
21
21
  send(): TxHash;
22
22
  send(callback: Callback): TxUnsub;
23
23
  protected getSystemEventsAt(hash: BlockHash): Promise<FrameSystemEventRecord[]>;
24
+ /**
25
+ * Override callU8a to add transaction parameter validation before encoding
26
+ */
27
+ get callU8a(): Uint8Array;
24
28
  toU8a(): Uint8Array;
25
29
  toHex(): HexString;
26
30
  }
@@ -1,5 +1,7 @@
1
1
  import { Extrinsic } from '@dedot/codecs';
2
- import { DedotError, hexToU8a, isFunction, toHex, u8aToHex } from '@dedot/utils';
2
+ import * as $ from '@dedot/shape';
3
+ import { DedotError, hexToU8a, isFunction, stringCamelCase, toHex, u8aToHex } from '@dedot/utils';
4
+ import { buildCompatibilityError } from '../../executor/validation-helpers.js';
3
5
  import { ExtraSignedExtension } from '../extensions/index.js';
4
6
  import { fakeSigner } from './fakeSigner.js';
5
7
  import { isKeyringPair, signRawMessage, txDefer } from './utils.js';
@@ -7,8 +9,8 @@ export class BaseSubmittableExtrinsic extends Extrinsic {
7
9
  client;
8
10
  #alterTx;
9
11
  #hooks;
10
- constructor(client, call) {
11
- super(client.registry, call);
12
+ constructor(client, call, preamble) {
13
+ super(client.registry, call, preamble);
12
14
  this.client = client;
13
15
  }
14
16
  withHooks(hooks) {
@@ -115,10 +117,69 @@ export class BaseSubmittableExtrinsic extends Extrinsic {
115
117
  const atApi = (await this.client.at(hash));
116
118
  return await atApi.query.system.events();
117
119
  }
120
+ /**
121
+ * Override callU8a to add transaction parameter validation before encoding
122
+ */
123
+ get callU8a() {
124
+ // Validate transaction parameters first
125
+ this.#validateTxParams();
126
+ // Then call parent implementation which does $RuntimeCall.assert and encoding
127
+ return super.callU8a;
128
+ }
129
+ /**
130
+ * Validate transaction parameters against their type definitions
131
+ * @private
132
+ */
133
+ #validateTxParams() {
134
+ // Skip if palletCall is a string (flat enum, no params)
135
+ if (typeof this.call.palletCall === 'string')
136
+ return;
137
+ if (!this.call.palletCall?.name)
138
+ return;
139
+ // 1. Find pallet metadata
140
+ const palletName = this.call.pallet;
141
+ const pallet = this.registry.metadata.pallets.find((p) => stringCamelCase(p.name) === stringCamelCase(palletName));
142
+ if (!pallet?.calls)
143
+ return;
144
+ // 2. Get calls enum type definition
145
+ const callsType = this.registry.metadata.types[pallet.calls.typeId];
146
+ if (callsType.typeDef.type !== 'Enum')
147
+ return;
148
+ // 3. Find specific call definition
149
+ const callName = this.call.palletCall.name;
150
+ const callDef = callsType.typeDef.value.members.find((m) => stringCamelCase(m.name) === stringCamelCase(callName));
151
+ if (!callDef)
152
+ return;
153
+ // 4. Build param specs from field definitions
154
+ const paramSpecs = callDef.fields.map((f) => ({
155
+ name: stringCamelCase(f.name || ''),
156
+ typeId: f.typeId,
157
+ }));
158
+ // 5. Extract args in field order from params object
159
+ const params = this.call.palletCall.params || {};
160
+ const args = paramSpecs.map((spec) => params[spec.name]);
161
+ // 6. Validate with tuple codec
162
+ const $ParamsTuple = $.Tuple(...paramSpecs.map((spec) => this.registry.findCodec(spec.typeId)));
163
+ try {
164
+ $ParamsTuple.assert?.(args);
165
+ }
166
+ catch (error) {
167
+ if (error instanceof $.ShapeAssertError) {
168
+ throw buildCompatibilityError(error, // --
169
+ paramSpecs, args, {
170
+ apiName: `${stringCamelCase(pallet.name)}.${stringCamelCase(callDef.name)}`,
171
+ registry: this.registry,
172
+ });
173
+ }
174
+ throw error;
175
+ }
176
+ }
118
177
  toU8a() {
119
178
  if (this.#alterTx) {
120
179
  return hexToU8a(this.#alterTx);
121
180
  }
181
+ // Validate transaction parameters before encoding
182
+ this.#validateTxParams();
122
183
  return super.toU8a();
123
184
  }
124
185
  toHex() {
@@ -1,11 +1,14 @@
1
- import { BlockHash } from '@dedot/codecs';
1
+ import { BlockHash, Extrinsic } from '@dedot/codecs';
2
2
  import { AddressOrPair, Callback, DryRunResult, ISubmittableExtrinsicLegacy, ISubmittableResult, SignerOptions, TxHash, TxUnsub } from '@dedot/types';
3
+ import { HexString } from '@dedot/utils';
4
+ import { LegacyClient } from '../../client/LegacyClient.js';
3
5
  import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
4
6
  /**
5
7
  * @name SubmittableExtrinsic
6
8
  * @description A wrapper around an Extrinsic that exposes methods to sign, send, and other utility around Extrinsic.
7
9
  */
8
10
  export declare class SubmittableExtrinsic extends BaseSubmittableExtrinsic implements ISubmittableExtrinsicLegacy {
11
+ static fromTx(client: LegacyClient<any>, tx: HexString | Extrinsic): SubmittableExtrinsic;
9
12
  dryRun(account: AddressOrPair, optionsOrHash?: Partial<SignerOptions> | BlockHash): Promise<DryRunResult>;
10
13
  send(): TxHash;
11
14
  send(callback: Callback<ISubmittableResult>): TxUnsub;
@@ -1,4 +1,4 @@
1
- import { assert, isHex } from '@dedot/utils';
1
+ import { assert, isHex, noop } from '@dedot/utils';
2
2
  import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
3
3
  import { SubmittableResult } from './SubmittableResult.js';
4
4
  import { toTxStatus, txDefer } from './utils.js';
@@ -7,6 +7,16 @@ import { toTxStatus, txDefer } from './utils.js';
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
+ 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);
19
+ }
10
20
  async dryRun(account, optionsOrHash) {
11
21
  const dryRunFn = this.client.rpc.system_dryRun;
12
22
  if (isHex(optionsOrHash)) {
@@ -20,7 +30,11 @@ export class SubmittableExtrinsic extends BaseSubmittableExtrinsic {
20
30
  const txHex = this.toHex();
21
31
  const txHash = this.hash;
22
32
  const { deferTx, onTxProgress } = txDefer();
23
- const unsub = this.client.rpc.author_submitAndWatchExtrinsic(txHex, async (txStatus) => {
33
+ let unsub;
34
+ this.client.rpc
35
+ .author_submitAndWatchExtrinsic(txHex, async (txStatus) => {
36
+ let status;
37
+ let result;
24
38
  if (txStatus.type === 'InBlock' || txStatus.type === 'Finalized') {
25
39
  const blockHash = txStatus.value;
26
40
  const [signedBlock, blockEvents] = await Promise.all([
@@ -31,25 +45,33 @@ export class SubmittableExtrinsic extends BaseSubmittableExtrinsic {
31
45
  assert(txIndex >= 0, 'Extrinsic not found!');
32
46
  const events = blockEvents.filter(({ phase }) => phase.type === 'ApplyExtrinsic' && phase.value === txIndex);
33
47
  const blockNumber = signedBlock.block.header.number;
34
- const status = toTxStatus(txStatus, { txIndex, blockNumber });
35
- const result = this.transformTxResult(new SubmittableResult({ status, txHash, events, txIndex }));
36
- onTxProgress(result);
37
- !isSubscription && deferTx.resolve(txHash);
38
- return callback?.(result);
48
+ status = toTxStatus(txStatus, { txIndex, blockNumber });
49
+ result = this.transformTxResult(new SubmittableResult({ status, txHash, events, txIndex }));
39
50
  }
40
51
  else {
41
- const status = toTxStatus(txStatus);
42
- const result = this.transformTxResult(new SubmittableResult({ status, txHash }));
43
- onTxProgress(result);
44
- !isSubscription && deferTx.resolve(txHash);
45
- return callback?.(result);
52
+ status = toTxStatus(txStatus);
53
+ result = this.transformTxResult(new SubmittableResult({ status, txHash }));
46
54
  }
47
- });
48
- if (isSubscription) {
49
- unsub.then((x) => {
55
+ onTxProgress(result);
56
+ if (isSubscription) {
57
+ callback?.(result);
58
+ }
59
+ else {
60
+ deferTx.resolve(txHash);
61
+ }
62
+ if (status.type === 'Finalized' || // --
63
+ status.type === 'Invalid' ||
64
+ status.type === 'Drop') {
65
+ unsub?.().catch(noop);
66
+ }
67
+ })
68
+ .then((x) => {
69
+ unsub = x;
70
+ if (isSubscription) {
50
71
  deferTx.resolve(x);
51
- });
52
- }
72
+ }
73
+ })
74
+ .catch(deferTx.reject);
53
75
  return deferTx.promise;
54
76
  }
55
77
  }
@@ -1,5 +1,7 @@
1
+ import { Extrinsic, Preamble } from '@dedot/codecs';
1
2
  import { Callback, IRuntimeTxCall, TxHash, TxUnsub } from '@dedot/types';
2
- import { DedotClient } from '../../client/index.js';
3
+ import { HexString } from '@dedot/utils';
4
+ import { V2Client } from '../../client/V2Client.js';
3
5
  import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
4
6
  /**
5
7
  * @name SubmittableExtrinsicV2
@@ -7,8 +9,9 @@ import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
7
9
  */
8
10
  export declare class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic {
9
11
  #private;
10
- client: DedotClient<any>;
11
- constructor(client: DedotClient<any>, call: IRuntimeTxCall);
12
+ client: V2Client<any>;
13
+ constructor(client: V2Client<any>, call: IRuntimeTxCall, preamble?: Preamble);
14
+ static fromTx(client: V2Client<any>, tx: HexString | Extrinsic): SubmittableExtrinsicV2;
12
15
  send(): TxHash;
13
16
  send(callback: Callback): TxUnsub;
14
17
  }
@@ -1,4 +1,4 @@
1
- import { AsyncQueue, noop, waitFor } from '@dedot/utils';
1
+ import { AsyncQueue, isHex, 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';
@@ -9,10 +9,20 @@ import { txDefer } from './utils.js';
9
9
  */
10
10
  export class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic {
11
11
  client;
12
- constructor(client, call) {
13
- super(client, call);
12
+ constructor(client, call, preamble) {
13
+ super(client, call, preamble);
14
14
  this.client = client;
15
15
  }
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);
25
+ }
16
26
  async #send(callback) {
17
27
  const api = this.client;
18
28
  const txHex = this.toHex();
@@ -1,11 +1,11 @@
1
1
  import type { ConnectionStatus, JsonRpcProvider, ProviderEvent } from '@dedot/providers';
2
- import type { RpcVersion, VersionedGenericSubstrateApi } from '@dedot/types';
2
+ import type { GenericSubstrateApi } from '@dedot/types';
3
3
  import { EventEmitter } from '@dedot/utils';
4
4
  import type { SubstrateApi } from '../chaintypes/index.js';
5
5
  import type { IJsonRpcClient, JsonRpcClientOptions } from '../types.js';
6
6
  export declare const isJsonRpcProvider: (provider: any) => provider is JsonRpcProvider;
7
- export declare class JsonRpcClient<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi, // prettier-end-here
8
- Events extends string = ProviderEvent> extends EventEmitter<Events> implements IJsonRpcClient<ChainApi[RpcVersion], Events> {
7
+ export declare class JsonRpcClient<ChainApi extends GenericSubstrateApi = SubstrateApi, // prettier-end-here
8
+ Events extends string = ProviderEvent> extends EventEmitter<Events> implements IJsonRpcClient<ChainApi, Events> {
9
9
  #private;
10
10
  constructor(options: JsonRpcClientOptions | JsonRpcProvider);
11
11
  /**
@@ -13,13 +13,13 @@ Events extends string = ProviderEvent> extends EventEmitter<Events> implements I
13
13
  *
14
14
  * @param options
15
15
  */
16
- static create<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi>(options: JsonRpcClientOptions | JsonRpcProvider): Promise<JsonRpcClient<ChainApi>>;
16
+ static create<ChainApi extends GenericSubstrateApi = SubstrateApi>(options: JsonRpcClientOptions | JsonRpcProvider): Promise<JsonRpcClient<ChainApi>>;
17
17
  /**
18
18
  * Alias for __JsonRpcClient.create__
19
19
  *
20
20
  * @param options
21
21
  */
22
- static new<ChainApi extends VersionedGenericSubstrateApi = SubstrateApi>(options: JsonRpcClientOptions | JsonRpcProvider): Promise<JsonRpcClient<ChainApi>>;
22
+ static new<ChainApi extends GenericSubstrateApi = SubstrateApi>(options: JsonRpcClientOptions | JsonRpcProvider): Promise<JsonRpcClient<ChainApi>>;
23
23
  get options(): JsonRpcClientOptions;
24
24
  /**
25
25
  * @description Check connection status of the api instance
@@ -47,5 +47,5 @@ Events extends string = ProviderEvent> extends EventEmitter<Events> implements I
47
47
  * const result = await client.rpc.module_rpc_name();
48
48
  * ```
49
49
  */
50
- get rpc(): ChainApi[RpcVersion]['rpc'];
50
+ get rpc(): ChainApi['rpc'];
51
51
  }
@@ -13,7 +13,7 @@ import { JsonRpcGroup, JsonRpcGroupOptions } from './JsonRpcGroup.js';
13
13
  */
14
14
  export declare class Archive extends JsonRpcGroup {
15
15
  #private;
16
- constructor(client: IJsonRpcClient, options?: Partial<JsonRpcGroupOptions>);
16
+ constructor(client: IJsonRpcClient<any>, options?: Partial<JsonRpcGroupOptions>);
17
17
  /**
18
18
  * Retrieves the body (list of transactions) of a given block.
19
19
  * Returns an array of strings containing the hexadecimal-encoded SCALE-codec-encoded
@@ -1,5 +1,6 @@
1
1
  import { BlockHash, Option } from '@dedot/codecs';
2
2
  import type { ChainHeadRuntimeVersion, OperationId, StorageQuery, StorageResult } from '@dedot/types/json-rpc';
3
+ import { HashFn } from '@dedot/utils';
3
4
  import { Deferred, HexString } from '@dedot/utils';
4
5
  import type { IJsonRpcClient } from '../../../types.js';
5
6
  import { Archive } from '../Archive.js';
@@ -10,16 +11,22 @@ export type OperationHandler<T = any> = {
10
11
  storageResults?: Array<StorageResult>;
11
12
  hash: BlockHash;
12
13
  };
14
+ export type PendingRequest<T = any> = {
15
+ method: string;
16
+ params: any[];
17
+ defer: Deferred<T>;
18
+ };
13
19
  export type PinnedBlock = {
14
20
  hash: BlockHash;
15
21
  number: number;
16
22
  parent: BlockHash;
17
23
  runtime?: ChainHeadRuntimeVersion;
24
+ runtimeUpgraded?: boolean;
18
25
  };
19
26
  export type ChainHeadEvent = 'newBlock' | 'bestBlock' | 'finalizedBlock' | 'bestChainChanged';
20
27
  export declare class ChainHead extends JsonRpcGroup<ChainHeadEvent> {
21
28
  #private;
22
- constructor(client: IJsonRpcClient, options?: Partial<JsonRpcGroupOptions>);
29
+ constructor(client: IJsonRpcClient<any>, options?: Partial<JsonRpcGroupOptions>);
23
30
  /**
24
31
  * Attach an Archive instance as fallback for operations that fail due to unpinned blocks.
25
32
  * When a ChainHeadBlockNotPinnedError occurs, the operation will automatically fallback
@@ -29,12 +36,21 @@ export declare class ChainHead extends JsonRpcGroup<ChainHeadEvent> {
29
36
  * @returns this ChainHead instance for method chaining
30
37
  */
31
38
  withArchive(archive: Archive): this;
39
+ /**
40
+ * Override send() to track pending requests for retry on network disconnection
41
+ */
42
+ send<T = any>(method: string, ...params: any[]): Promise<T>;
32
43
  runtimeVersion(): Promise<ChainHeadRuntimeVersion>;
33
44
  bestRuntimeVersion(): Promise<ChainHeadRuntimeVersion>;
34
45
  finalizedHash(): Promise<BlockHash>;
35
46
  bestHash(): Promise<BlockHash>;
36
47
  bestBlock(): Promise<PinnedBlock>;
37
48
  finalizedBlock(): Promise<PinnedBlock>;
49
+ /**
50
+ * Returns the detected hasher for the chain
51
+ * Returns undefined if detection failed (client should use default)
52
+ */
53
+ hasher(): Promise<HashFn | undefined>;
38
54
  findBlock(hash: BlockHash): PinnedBlock | undefined;
39
55
  isPinned(hash: BlockHash): boolean;
40
56
  /**
@@ -44,7 +60,7 @@ export declare class ChainHead extends JsonRpcGroup<ChainHeadEvent> {
44
60
  /**
45
61
  * chainHead_follow
46
62
  */
47
- follow(): Promise<void>;
63
+ follow(force?: boolean): Promise<void>;
48
64
  /**
49
65
  * chainHead_body
50
66
  */