@dedot/api 0.10.0 → 0.11.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.
@@ -55,10 +55,35 @@ class BaseSubmittableExtrinsic extends codecs_1.Extrinsic {
55
55
  }
56
56
  return this;
57
57
  }
58
- async signAndSend(fromAccount, partialOptions, maybeCallback) {
58
+ signAndSend(fromAccount, partialOptions, maybeCallback) {
59
59
  const [options, callback] = this.#normalizeOptions(partialOptions, maybeCallback);
60
- await this.sign(fromAccount, options);
61
- return this.send(callback);
60
+ const { deferTx, deferFinalized, deferBestChainBlockIncluded, onTxProgress } = (0, utils_js_1.txDefer)();
61
+ this.sign(fromAccount, options)
62
+ .then(() => {
63
+ const deferSend = this.send(callback);
64
+ deferSend
65
+ .then(deferTx.resolve) // --
66
+ .catch(deferTx.reject);
67
+ deferSend
68
+ .untilBestChainBlockIncluded() //--
69
+ .then((r) => {
70
+ onTxProgress(r);
71
+ })
72
+ .catch((e) => {
73
+ deferBestChainBlockIncluded()?.reject(e);
74
+ });
75
+ deferSend
76
+ .untilFinalized() //--
77
+ .then((r) => {
78
+ onTxProgress(r);
79
+ })
80
+ .catch((e) => {
81
+ deferBestChainBlockIncluded()?.reject(e);
82
+ deferFinalized()?.reject(e);
83
+ });
84
+ })
85
+ .catch(deferTx.reject);
86
+ return deferTx.promise;
62
87
  }
63
88
  #normalizeOptions(partialOptions, callback) {
64
89
  if ((0, utils_1.isFunction)(partialOptions)) {
@@ -18,34 +18,42 @@ class SubmittableExtrinsic extends BaseSubmittableExtrinsic_js_1.BaseSubmittable
18
18
  await this.sign(account, optionsOrHash);
19
19
  return dryRunFn(this.toHex());
20
20
  }
21
- async send(callback) {
21
+ send(callback) {
22
22
  const isSubscription = !!callback;
23
23
  const txHex = this.toHex();
24
24
  const txHash = this.hash;
25
+ const { deferTx, onTxProgress } = (0, utils_js_1.txDefer)();
26
+ const unsub = this.client.rpc.author_submitAndWatchExtrinsic(txHex, async (txStatus) => {
27
+ if (txStatus.type === 'InBlock' || txStatus.type === 'Finalized') {
28
+ const blockHash = txStatus.value;
29
+ const [signedBlock, blockEvents] = await Promise.all([
30
+ this.client.rpc.chain_getBlock(blockHash),
31
+ this.getSystemEventsAt(blockHash),
32
+ ]);
33
+ const txIndex = signedBlock.block.extrinsics.indexOf(txHex);
34
+ (0, utils_1.assert)(txIndex >= 0, 'Extrinsic not found!');
35
+ const events = blockEvents.filter(({ phase }) => phase.type === 'ApplyExtrinsic' && phase.value === txIndex);
36
+ const blockNumber = signedBlock.block.header.number;
37
+ const status = (0, utils_js_1.toTxStatus)(txStatus, { txIndex, blockNumber });
38
+ const result = new SubmittableResult_js_1.SubmittableResult({ status, txHash, events, txIndex });
39
+ onTxProgress(result);
40
+ !isSubscription && deferTx.resolve(txHash);
41
+ return callback?.(result);
42
+ }
43
+ else {
44
+ const status = (0, utils_js_1.toTxStatus)(txStatus);
45
+ const result = new SubmittableResult_js_1.SubmittableResult({ status, txHash });
46
+ onTxProgress(result);
47
+ !isSubscription && deferTx.resolve(txHash);
48
+ return callback?.(new SubmittableResult_js_1.SubmittableResult({ status, txHash }));
49
+ }
50
+ });
25
51
  if (isSubscription) {
26
- return this.client.rpc.author_submitAndWatchExtrinsic(txHex, async (txStatus) => {
27
- if (txStatus.type === 'InBlock' || txStatus.type === 'Finalized') {
28
- const blockHash = txStatus.value;
29
- const [signedBlock, blockEvents] = await Promise.all([
30
- this.client.rpc.chain_getBlock(blockHash),
31
- this.getSystemEventsAt(blockHash),
32
- ]);
33
- const txIndex = signedBlock.block.extrinsics.indexOf(txHex);
34
- (0, utils_1.assert)(txIndex >= 0, 'Extrinsic not found!');
35
- const events = blockEvents.filter(({ phase }) => phase.type === 'ApplyExtrinsic' && phase.value === txIndex);
36
- const blockNumber = signedBlock.block.header.number;
37
- const status = (0, utils_js_1.toTxStatus)(txStatus, { txIndex, blockNumber });
38
- return callback(new SubmittableResult_js_1.SubmittableResult({ status, txHash, events, txIndex }));
39
- }
40
- else {
41
- const status = (0, utils_js_1.toTxStatus)(txStatus);
42
- return callback(new SubmittableResult_js_1.SubmittableResult({ status, txHash }));
43
- }
52
+ unsub.then((x) => {
53
+ deferTx.resolve(x);
44
54
  });
45
55
  }
46
- else {
47
- return this.client.rpc.author_submitExtrinsic(txHex);
48
- }
56
+ return deferTx.promise;
49
57
  }
50
58
  }
51
59
  exports.SubmittableExtrinsic = SubmittableExtrinsic;
@@ -5,6 +5,7 @@ const utils_1 = require("@dedot/utils");
5
5
  const BaseSubmittableExtrinsic_js_1 = require("./BaseSubmittableExtrinsic.js");
6
6
  const SubmittableResult_js_1 = require("./SubmittableResult.js");
7
7
  const errors_js_1 = require("./errors.js");
8
+ const utils_js_1 = require("./utils.js");
8
9
  /**
9
10
  * @name SubmittableExtrinsicV2
10
11
  * @description Submittable extrinsic based on JSON-RPC v2
@@ -176,31 +177,39 @@ class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic_js_1.BaseSubmittab
176
177
  };
177
178
  return txUnsub;
178
179
  }
179
- async send(callback) {
180
+ send(callback) {
180
181
  const isSubscription = !!callback;
181
- if (isSubscription) {
182
- return this.#send(callback);
183
- }
184
- else {
185
- const defer = (0, utils_1.deferred)();
186
- try {
187
- // TODO handle timeout for this with the Drop status, just in-case we somehow can't find the tx in any block
188
- const unsub = await this.#send(({ status, txHash }) => {
189
- if (status.type === 'BestChainBlockIncluded' || status.type === 'Finalized') {
190
- defer.resolve(txHash);
191
- unsub().catch(utils_1.noop);
192
- }
193
- else if (status.type === 'Invalid' || status.type === 'Drop') {
194
- defer.reject(new Error(status.value.error));
195
- unsub().catch(utils_1.noop);
196
- }
197
- });
182
+ const { deferTx, onTxProgress } = (0, utils_js_1.txDefer)();
183
+ // TODO handle timeout for this with the Drop status,
184
+ // just in-case we somehow can't find the tx in any block
185
+ let unsub;
186
+ this.#send((result) => {
187
+ onTxProgress(result);
188
+ if (isSubscription) {
189
+ try {
190
+ callback?.(result);
191
+ }
192
+ catch { }
193
+ return;
198
194
  }
199
- catch (e) {
200
- defer.reject(e);
195
+ const { status, txHash } = result;
196
+ if (status.type === 'BestChainBlockIncluded' ||
197
+ status.type === 'Finalized' ||
198
+ status.type === 'Invalid' ||
199
+ status.type === 'Drop') {
200
+ deferTx.resolve(txHash);
201
+ // Unsub the subscription if we're at the final states
202
+ if (status.type !== 'BestChainBlockIncluded') {
203
+ unsub?.().catch(utils_1.noop);
204
+ }
201
205
  }
202
- return defer.promise;
203
- }
206
+ })
207
+ .then((x) => {
208
+ unsub = x;
209
+ isSubscription && deferTx.resolve(unsub);
210
+ })
211
+ .catch(deferTx.reject);
212
+ return deferTx.promise;
204
213
  }
205
214
  }
206
215
  exports.SubmittableExtrinsicV2 = SubmittableExtrinsicV2;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InvalidTxError = void 0;
3
+ exports.RejectedTxError = exports.InvalidTxError = void 0;
4
4
  const utils_1 = require("@dedot/utils");
5
5
  /**
6
6
  * This throws out if the extrinsic is invalid
@@ -15,3 +15,12 @@ class InvalidTxError extends utils_1.DedotError {
15
15
  }
16
16
  }
17
17
  exports.InvalidTxError = InvalidTxError;
18
+ class RejectedTxError extends utils_1.DedotError {
19
+ result;
20
+ name = 'RejectedTxError';
21
+ constructor(result) {
22
+ super();
23
+ this.result = result;
24
+ }
25
+ }
26
+ exports.RejectedTxError = RejectedTxError;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toTxStatus = exports.signRaw = exports.isKeyringPair = void 0;
3
+ exports.txDefer = exports.toTxStatus = exports.signRaw = exports.isKeyringPair = void 0;
4
4
  const utils_1 = require("@dedot/utils");
5
+ const errors_js_1 = require("./errors.js");
5
6
  function isKeyringPair(account) {
6
7
  return (0, utils_1.isFunction)(account.sign);
7
8
  }
@@ -83,3 +84,40 @@ function toTxStatus(txStatus, txInfo) {
83
84
  }
84
85
  }
85
86
  exports.toTxStatus = toTxStatus;
87
+ function txDefer() {
88
+ const deferTx = (0, utils_1.deferred)();
89
+ let deferFinalized;
90
+ let deferBestChainBlockIncluded;
91
+ Object.assign(deferTx.promise, {
92
+ untilFinalized: () => {
93
+ deferFinalized = (0, utils_1.deferred)();
94
+ return deferFinalized.promise;
95
+ },
96
+ untilBestChainBlockIncluded: () => {
97
+ deferBestChainBlockIncluded = (0, utils_1.deferred)();
98
+ return deferBestChainBlockIncluded.promise;
99
+ },
100
+ });
101
+ const onTxProgress = (result) => {
102
+ const { status } = result;
103
+ if (status.type === 'BestChainBlockIncluded') {
104
+ deferBestChainBlockIncluded?.resolve(result);
105
+ }
106
+ else if (status.type === 'Finalized') {
107
+ deferBestChainBlockIncluded?.resolve(result);
108
+ deferFinalized?.resolve(result);
109
+ }
110
+ else if (status.type === 'Invalid' || status.type === 'Drop') {
111
+ const e = new errors_js_1.RejectedTxError(result);
112
+ deferBestChainBlockIncluded?.reject(e);
113
+ deferFinalized?.reject(e);
114
+ }
115
+ };
116
+ return {
117
+ deferTx,
118
+ deferFinalized: () => deferFinalized,
119
+ deferBestChainBlockIncluded: () => deferBestChainBlockIncluded,
120
+ onTxProgress,
121
+ };
122
+ }
123
+ exports.txDefer = txDefer;
@@ -1,5 +1,5 @@
1
- import { BlockHash, Extrinsic, Hash } from '@dedot/codecs';
2
- import { AddressOrPair, Callback, IRuntimeTxCall, ISubmittableExtrinsic, ISubmittableResult, PayloadOptions, SignerOptions, TxPaymentInfo, Unsub } from '@dedot/types';
1
+ import { BlockHash, Extrinsic } from '@dedot/codecs';
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';
5
5
  import type { ISubstrateClient } from '../../types.js';
@@ -9,11 +9,11 @@ export declare abstract class BaseSubmittableExtrinsic extends Extrinsic impleme
9
9
  constructor(client: ISubstrateClient, call: IRuntimeTxCall);
10
10
  paymentInfo(account: AddressOrPair, options?: Partial<PayloadOptions>): Promise<TxPaymentInfo>;
11
11
  sign(fromAccount: AddressOrPair, options?: Partial<SignerOptions>): Promise<this>;
12
- signAndSend(account: AddressOrPair, options?: Partial<SignerOptions>): Promise<Hash>;
13
- signAndSend(account: AddressOrPair, callback: Callback<ISubmittableResult>): Promise<Unsub>;
14
- signAndSend(account: AddressOrPair, options: Partial<SignerOptions>, callback?: Callback<ISubmittableResult>): Promise<Unsub>;
15
- send(): Promise<Hash>;
16
- send(callback: Callback): Promise<Unsub>;
12
+ signAndSend(account: AddressOrPair, options?: Partial<SignerOptions>): TxHash;
13
+ signAndSend(account: AddressOrPair, callback: Callback<ISubmittableResult>): TxUnsub;
14
+ signAndSend(account: AddressOrPair, options: Partial<SignerOptions>, callback?: Callback<ISubmittableResult>): TxUnsub;
15
+ send(): TxHash;
16
+ send(callback: Callback): TxUnsub;
17
17
  protected getSystemEventsAt(hash: BlockHash): Promise<FrameSystemEventRecord[]>;
18
18
  toHex(): HexString;
19
19
  }
@@ -2,7 +2,7 @@ import { Extrinsic } from '@dedot/codecs';
2
2
  import { DedotError, isFunction, toHex, u8aToHex } from '@dedot/utils';
3
3
  import { ExtraSignedExtension } from '../extensions/index.js';
4
4
  import { fakeSigner } from './fakeSigner.js';
5
- import { isKeyringPair, signRaw } from './utils.js';
5
+ import { isKeyringPair, signRaw, txDefer } from './utils.js';
6
6
  export class BaseSubmittableExtrinsic extends Extrinsic {
7
7
  client;
8
8
  #alterTx;
@@ -52,10 +52,35 @@ export class BaseSubmittableExtrinsic extends Extrinsic {
52
52
  }
53
53
  return this;
54
54
  }
55
- async signAndSend(fromAccount, partialOptions, maybeCallback) {
55
+ signAndSend(fromAccount, partialOptions, maybeCallback) {
56
56
  const [options, callback] = this.#normalizeOptions(partialOptions, maybeCallback);
57
- await this.sign(fromAccount, options);
58
- return this.send(callback);
57
+ const { deferTx, deferFinalized, deferBestChainBlockIncluded, onTxProgress } = txDefer();
58
+ this.sign(fromAccount, options)
59
+ .then(() => {
60
+ const deferSend = this.send(callback);
61
+ deferSend
62
+ .then(deferTx.resolve) // --
63
+ .catch(deferTx.reject);
64
+ deferSend
65
+ .untilBestChainBlockIncluded() //--
66
+ .then((r) => {
67
+ onTxProgress(r);
68
+ })
69
+ .catch((e) => {
70
+ deferBestChainBlockIncluded()?.reject(e);
71
+ });
72
+ deferSend
73
+ .untilFinalized() //--
74
+ .then((r) => {
75
+ onTxProgress(r);
76
+ })
77
+ .catch((e) => {
78
+ deferBestChainBlockIncluded()?.reject(e);
79
+ deferFinalized()?.reject(e);
80
+ });
81
+ })
82
+ .catch(deferTx.reject);
83
+ return deferTx.promise;
59
84
  }
60
85
  #normalizeOptions(partialOptions, callback) {
61
86
  if (isFunction(partialOptions)) {
@@ -1,5 +1,5 @@
1
- import { BlockHash, Hash } from '@dedot/codecs';
2
- import { AddressOrPair, Callback, DryRunResult, ISubmittableExtrinsicLegacy, ISubmittableResult, SignerOptions, Unsub } from '@dedot/types';
1
+ import { BlockHash } from '@dedot/codecs';
2
+ import { AddressOrPair, Callback, DryRunResult, ISubmittableExtrinsicLegacy, ISubmittableResult, SignerOptions, TxHash, TxUnsub } from '@dedot/types';
3
3
  import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
4
4
  /**
5
5
  * @name SubmittableExtrinsic
@@ -7,6 +7,6 @@ import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
7
7
  */
8
8
  export declare class SubmittableExtrinsic extends BaseSubmittableExtrinsic implements ISubmittableExtrinsicLegacy {
9
9
  dryRun(account: AddressOrPair, optionsOrHash?: Partial<SignerOptions> | BlockHash): Promise<DryRunResult>;
10
- send(): Promise<Hash>;
11
- send(callback: Callback<ISubmittableResult>): Promise<Unsub>;
10
+ send(): TxHash;
11
+ send(callback: Callback<ISubmittableResult>): TxUnsub;
12
12
  }
@@ -1,7 +1,7 @@
1
1
  import { assert, isHex } from '@dedot/utils';
2
2
  import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
3
3
  import { SubmittableResult } from './SubmittableResult.js';
4
- import { toTxStatus } from './utils.js';
4
+ import { 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.
@@ -15,33 +15,41 @@ export class SubmittableExtrinsic extends BaseSubmittableExtrinsic {
15
15
  await this.sign(account, optionsOrHash);
16
16
  return dryRunFn(this.toHex());
17
17
  }
18
- async send(callback) {
18
+ send(callback) {
19
19
  const isSubscription = !!callback;
20
20
  const txHex = this.toHex();
21
21
  const txHash = this.hash;
22
+ const { deferTx, onTxProgress } = txDefer();
23
+ const unsub = this.client.rpc.author_submitAndWatchExtrinsic(txHex, async (txStatus) => {
24
+ if (txStatus.type === 'InBlock' || txStatus.type === 'Finalized') {
25
+ const blockHash = txStatus.value;
26
+ const [signedBlock, blockEvents] = await Promise.all([
27
+ this.client.rpc.chain_getBlock(blockHash),
28
+ this.getSystemEventsAt(blockHash),
29
+ ]);
30
+ const txIndex = signedBlock.block.extrinsics.indexOf(txHex);
31
+ assert(txIndex >= 0, 'Extrinsic not found!');
32
+ const events = blockEvents.filter(({ phase }) => phase.type === 'ApplyExtrinsic' && phase.value === txIndex);
33
+ const blockNumber = signedBlock.block.header.number;
34
+ const status = toTxStatus(txStatus, { txIndex, blockNumber });
35
+ const result = new SubmittableResult({ status, txHash, events, txIndex });
36
+ onTxProgress(result);
37
+ !isSubscription && deferTx.resolve(txHash);
38
+ return callback?.(result);
39
+ }
40
+ else {
41
+ const status = toTxStatus(txStatus);
42
+ const result = new SubmittableResult({ status, txHash });
43
+ onTxProgress(result);
44
+ !isSubscription && deferTx.resolve(txHash);
45
+ return callback?.(new SubmittableResult({ status, txHash }));
46
+ }
47
+ });
22
48
  if (isSubscription) {
23
- return this.client.rpc.author_submitAndWatchExtrinsic(txHex, async (txStatus) => {
24
- if (txStatus.type === 'InBlock' || txStatus.type === 'Finalized') {
25
- const blockHash = txStatus.value;
26
- const [signedBlock, blockEvents] = await Promise.all([
27
- this.client.rpc.chain_getBlock(blockHash),
28
- this.getSystemEventsAt(blockHash),
29
- ]);
30
- const txIndex = signedBlock.block.extrinsics.indexOf(txHex);
31
- assert(txIndex >= 0, 'Extrinsic not found!');
32
- const events = blockEvents.filter(({ phase }) => phase.type === 'ApplyExtrinsic' && phase.value === txIndex);
33
- const blockNumber = signedBlock.block.header.number;
34
- const status = toTxStatus(txStatus, { txIndex, blockNumber });
35
- return callback(new SubmittableResult({ status, txHash, events, txIndex }));
36
- }
37
- else {
38
- const status = toTxStatus(txStatus);
39
- return callback(new SubmittableResult({ status, txHash }));
40
- }
49
+ unsub.then((x) => {
50
+ deferTx.resolve(x);
41
51
  });
42
52
  }
43
- else {
44
- return this.client.rpc.author_submitExtrinsic(txHex);
45
- }
53
+ return deferTx.promise;
46
54
  }
47
55
  }
@@ -1,5 +1,4 @@
1
- import type { Hash } from '@dedot/codecs';
2
- import type { Callback, IRuntimeTxCall, Unsub } from '@dedot/types';
1
+ import { Callback, IRuntimeTxCall, TxHash, TxUnsub } from '@dedot/types';
3
2
  import { DedotClient } from '../../client/index.js';
4
3
  import { BaseSubmittableExtrinsic } from './BaseSubmittableExtrinsic.js';
5
4
  /**
@@ -10,6 +9,6 @@ export declare class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic {
10
9
  #private;
11
10
  client: DedotClient;
12
11
  constructor(client: DedotClient, call: IRuntimeTxCall);
13
- send(): Promise<Hash>;
14
- send(callback: Callback): Promise<Unsub>;
12
+ send(): TxHash;
13
+ send(callback: Callback): TxUnsub;
15
14
  }
@@ -1,7 +1,8 @@
1
- import { AsyncQueue, deferred, noop } from '@dedot/utils';
1
+ import { AsyncQueue, noop } 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
6
  /**
6
7
  * @name SubmittableExtrinsicV2
7
8
  * @description Submittable extrinsic based on JSON-RPC v2
@@ -173,30 +174,38 @@ export class SubmittableExtrinsicV2 extends BaseSubmittableExtrinsic {
173
174
  };
174
175
  return txUnsub;
175
176
  }
176
- async send(callback) {
177
+ send(callback) {
177
178
  const isSubscription = !!callback;
178
- if (isSubscription) {
179
- return this.#send(callback);
180
- }
181
- else {
182
- const defer = deferred();
183
- try {
184
- // TODO handle timeout for this with the Drop status, just in-case we somehow can't find the tx in any block
185
- const unsub = await this.#send(({ status, txHash }) => {
186
- if (status.type === 'BestChainBlockIncluded' || status.type === 'Finalized') {
187
- defer.resolve(txHash);
188
- unsub().catch(noop);
189
- }
190
- else if (status.type === 'Invalid' || status.type === 'Drop') {
191
- defer.reject(new Error(status.value.error));
192
- unsub().catch(noop);
193
- }
194
- });
179
+ const { deferTx, onTxProgress } = txDefer();
180
+ // TODO handle timeout for this with the Drop status,
181
+ // just in-case we somehow can't find the tx in any block
182
+ let unsub;
183
+ this.#send((result) => {
184
+ onTxProgress(result);
185
+ if (isSubscription) {
186
+ try {
187
+ callback?.(result);
188
+ }
189
+ catch { }
190
+ return;
195
191
  }
196
- catch (e) {
197
- defer.reject(e);
192
+ const { status, txHash } = result;
193
+ if (status.type === 'BestChainBlockIncluded' ||
194
+ status.type === 'Finalized' ||
195
+ status.type === 'Invalid' ||
196
+ status.type === 'Drop') {
197
+ deferTx.resolve(txHash);
198
+ // Unsub the subscription if we're at the final states
199
+ if (status.type !== 'BestChainBlockIncluded') {
200
+ unsub?.().catch(noop);
201
+ }
198
202
  }
199
- return defer.promise;
200
- }
203
+ })
204
+ .then((x) => {
205
+ unsub = x;
206
+ isSubscription && deferTx.resolve(unsub);
207
+ })
208
+ .catch(deferTx.reject);
209
+ return deferTx.promise;
201
210
  }
202
211
  }
@@ -1,4 +1,5 @@
1
1
  import type { Result } from '@dedot/codecs';
2
+ import { ISubmittableResult } from '@dedot/types';
2
3
  import { DedotError } from '@dedot/utils';
3
4
  import type { SpRuntimeTransactionValidityTransactionValidityError, SpRuntimeTransactionValidityValidTransaction } from '../../chaintypes/index.js';
4
5
  /**
@@ -10,3 +11,8 @@ export declare class InvalidTxError extends DedotError {
10
11
  name: string;
11
12
  constructor(message: string, data: Result<SpRuntimeTransactionValidityValidTransaction, SpRuntimeTransactionValidityTransactionValidityError>);
12
13
  }
14
+ export declare class RejectedTxError extends DedotError {
15
+ result: ISubmittableResult;
16
+ name: string;
17
+ constructor(result: ISubmittableResult);
18
+ }
@@ -11,3 +11,11 @@ export class InvalidTxError extends DedotError {
11
11
  this.data = data;
12
12
  }
13
13
  }
14
+ export class RejectedTxError extends DedotError {
15
+ result;
16
+ name = 'RejectedTxError';
17
+ constructor(result) {
18
+ super();
19
+ this.result = result;
20
+ }
21
+ }
@@ -1,6 +1,6 @@
1
1
  import { TransactionStatus } from '@dedot/codecs';
2
- import type { AddressOrPair, IKeyringPair, TxStatus } from '@dedot/types';
3
- import { HexString } from '@dedot/utils';
2
+ import { AddressOrPair, IKeyringPair, ISubmittableResult, TxStatus, Unsub } from '@dedot/types';
3
+ import { Deferred, HexString } from '@dedot/utils';
4
4
  export declare function isKeyringPair(account: AddressOrPair): account is IKeyringPair;
5
5
  /**
6
6
  * Sign a raw message
@@ -20,4 +20,10 @@ type TxInfo = {
20
20
  * @param txInfo
21
21
  */
22
22
  export declare function toTxStatus(txStatus: TransactionStatus, txInfo?: TxInfo): TxStatus;
23
+ export declare function txDefer(): {
24
+ deferTx: Deferred<`0x${string}` | Unsub>;
25
+ deferFinalized: () => Deferred<ISubmittableResult<import("@dedot/types").IEventRecord<import("@dedot/types").IRuntimeEvent, `0x${string}`>>> | undefined;
26
+ deferBestChainBlockIncluded: () => Deferred<ISubmittableResult<import("@dedot/types").IEventRecord<import("@dedot/types").IRuntimeEvent, `0x${string}`>>> | undefined;
27
+ onTxProgress: (result: ISubmittableResult) => void;
28
+ };
23
29
  export {};
@@ -1,4 +1,5 @@
1
- import { assert, blake2AsU8a, hexToU8a, isFunction } from '@dedot/utils';
1
+ import { assert, blake2AsU8a, deferred, hexToU8a, isFunction } from '@dedot/utils';
2
+ import { RejectedTxError } from './errors.js';
2
3
  export function isKeyringPair(account) {
3
4
  return isFunction(account.sign);
4
5
  }
@@ -77,3 +78,39 @@ export function toTxStatus(txStatus, txInfo) {
77
78
  };
78
79
  }
79
80
  }
81
+ export function txDefer() {
82
+ const deferTx = deferred();
83
+ let deferFinalized;
84
+ let deferBestChainBlockIncluded;
85
+ Object.assign(deferTx.promise, {
86
+ untilFinalized: () => {
87
+ deferFinalized = deferred();
88
+ return deferFinalized.promise;
89
+ },
90
+ untilBestChainBlockIncluded: () => {
91
+ deferBestChainBlockIncluded = deferred();
92
+ return deferBestChainBlockIncluded.promise;
93
+ },
94
+ });
95
+ const onTxProgress = (result) => {
96
+ const { status } = result;
97
+ if (status.type === 'BestChainBlockIncluded') {
98
+ deferBestChainBlockIncluded?.resolve(result);
99
+ }
100
+ else if (status.type === 'Finalized') {
101
+ deferBestChainBlockIncluded?.resolve(result);
102
+ deferFinalized?.resolve(result);
103
+ }
104
+ else if (status.type === 'Invalid' || status.type === 'Drop') {
105
+ const e = new RejectedTxError(result);
106
+ deferBestChainBlockIncluded?.reject(e);
107
+ deferFinalized?.reject(e);
108
+ }
109
+ };
110
+ return {
111
+ deferTx,
112
+ deferFinalized: () => deferFinalized,
113
+ deferBestChainBlockIncluded: () => deferBestChainBlockIncluded,
114
+ onTxProgress,
115
+ };
116
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dedot/api",
3
- "version": "0.10.0",
3
+ "version": "0.11.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": "0.10.0",
17
- "@dedot/providers": "0.10.0",
18
- "@dedot/runtime-specs": "0.10.0",
19
- "@dedot/shape": "0.10.0",
20
- "@dedot/storage": "0.10.0",
21
- "@dedot/types": "0.10.0",
22
- "@dedot/utils": "0.10.0"
16
+ "@dedot/codecs": "0.11.0",
17
+ "@dedot/providers": "0.11.0",
18
+ "@dedot/runtime-specs": "0.11.0",
19
+ "@dedot/shape": "0.11.0",
20
+ "@dedot/storage": "0.11.0",
21
+ "@dedot/types": "0.11.0",
22
+ "@dedot/utils": "0.11.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": "b6139d257df621080e3e7a0ce260da19e572c1c5",
51
+ "gitHead": "5aa20d8c24305df30528f008b55dc0f6f89b9e95",
52
52
  "module": "./index.js",
53
53
  "types": "./index.d.ts"
54
54
  }