You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/pages/typed/tx.md
+25-14
Original file line number
Diff line number
Diff line change
@@ -168,7 +168,7 @@ type TxEstimateFees = (
168
168
169
169
### `sign`
170
170
171
-
As simple as it seems, this method packs the transaction, sends it to the signer, and receives the signature. It requires a [`PolkadotSigner`]("/signers"), we saw them in another section of the docs. Let's see its interface:
171
+
As simple as it seems, this method packs the transaction, sends it to the signer, and receives the signature. It requires a [`PolkadotSigner`](/signers), we saw them in another section of the docs. Let's see its interface:
172
172
173
173
```ts
174
174
typeTxSignFn= (
@@ -181,7 +181,12 @@ It'll get back the whole `SignedExtrinsic` that needs to be broadcasted. If the
181
181
182
182
### `signAndSubmit`
183
183
184
-
`signAndSubmit` will sign (exactly the same way as `sign`) and then broadcast the transaction. If any error happens (both in the signing or if the transaction fails, i.e. wrong nonce, mortality period ended, etc) the promise will be rejected with an error. The promise will resolve as soon as the transaction is found in a finalized block, and will reject if the transaction fails. Note that this promise is not abortable. Let's see the interface:
184
+
`signAndSubmit` will sign (exactly the same way as `sign`). After signing it will validate the transaction against the block specified in `txOptions` and broadcast the transaction if it is valid. If it is not it will throw an [`InvalidTxError`](#invalidtxerror).
185
+
186
+
- The promise will resolve as soon as the transaction is found in a finalized block.
187
+
- The promise will reject if the transaction is invalid at any finalized block after broadcasting. It will throw as well an [`InvalidTxError`](#invalidtxerror).
188
+
189
+
Note that this promise is not abortable. Let's see the interface:
185
190
186
191
```ts
187
192
typeTxPromise= (
@@ -198,11 +203,11 @@ type TxFinalized = {
198
203
}
199
204
```
200
205
201
-
You get the `txHash`; the bunch of `events` that this extrinsic emitted (see [this section]("/typed/events") to see what to do with them); `ok` which simply tells if the extrinsic was successful (i.e. event `System.ExtrinsicSuccess` is found) and the `block` information where the tx is found.
206
+
You get the `txHash`; the bunch of `events` that this extrinsic emitted (see [this section](/typed/events) to see what to do with them); `ok` which simply tells if the extrinsic was successful (i.e. event `System.ExtrinsicSuccess` is found), with its [`dispatchError`](#dispatcherror) and the `block` information where the tx is found.
202
207
203
208
### `signSubmitAndWatch`
204
209
205
-
`signSubmitAndWatch` is the Observable-based version of `signAndSubmit`. The function returns an Observable and will emit a bunch of events giving information about the status of transaction in the chain, until it'll be eventually finalized. Let's see its interface:
210
+
`signSubmitAndWatch` is the Observable-based version of `signAndSubmit`. The function returns an Observable and will emit a bunch of events giving information about the status of transaction in the chain, until it'll be eventually finalized or definitely invalid. Let's see its interface:
206
211
207
212
:::warning
208
213
The Observable is single cast, and it's not stateful. The transaction will be sent to signature, broadcasted, etc on every single subscription individually. If you want to share the subscription, you could craft an observable using `shareLatest`.
@@ -221,14 +226,18 @@ export type TxObservable = (
The first two are fairly straight-forward. As soon as the transaction gets signed, `TxSigned` will be emitted and the transaction will be broadcasted by the client. `TxBroadcasted` will be emitted then. This two events can only be emitted once each:
229
+
The first two are fairly straight-forward. Let's see them.
230
+
231
+
First of all, the transaction will be signed (exactly the same way as [`sign`](#sign)) and the event `TxSigned` will be emitted. As soon as the transaction gets signed, the transaction will be validated aganst the block specified in `txOptions` and, if it is valid, the transaction will be broadcasted and `TxBroadcasted` will be emitted then. If the transaction is invalid the observable will error with an [`InvalidTxError`](#invalidtxerror).
Then, as soon as the block is found in a `bestBlock`(or if the transaction is not valid anymore in the latest known bestBlock) the following event will be emitted:
240
+
Then, as soon as the block is found in a `bestBlock` or if the transaction is not valid in one of the best blocks the following event will be emitted:
232
241
233
242
```ts
234
243
typeTxBestBlocksState= {
@@ -249,9 +258,9 @@ type TxBestBlocksState = {
249
258
)
250
259
```
251
260
252
-
We can see that this is a 2-in-1 event. After the broadcast, the library will start verifying the state of the transaction against the latest known `bestBlock`. Then, two main situations could happen:
261
+
We can see that this is a 2-in-1 event. After the broadcast, the library will start verifying the state of the transaction against some best blocks in a smart way. Then, two main situations could happen:
253
262
254
-
- The transaction is not found in the latest known `bestBlock`. If this is the case, polkadot-api will check if the transaction is still valid in the block. The event received in this case will be
263
+
- The transaction is not found in any block in the latest known `bestBlock` branch. If this is the case, `polkadot-api` will check if the transaction is still valid in the block. The event received in this case will be
- The transaction is found in the latest known`bestBlock`. We already infer that the transaction is valid in this block (otherwise it wouldn't get inside it). Therefore, we align the payload to the finalized event, and the event received is as follows. See the finalized event for more info on the fields.
274
+
- The transaction is found in a`bestBlock`. We already infer that the transaction is valid in this block (otherwise it wouldn't get inside it). Therefore, we align the payload to the finalized event, and the event received is as follows. See the finalized event for more info on the fields.
266
275
267
276
```ts
268
277
interfaceTxBestBlockFound {
@@ -276,9 +285,9 @@ interface TxBestBlockFound {
276
285
}
277
286
```
278
287
279
-
This event will be emitted any number of times. It might happen that the tx is found in a best block, then it disappears, comes back, etc. We'll pass all that information to the consumer.
288
+
This event will be emitted any number of times. It might happen that the tx is found in a best block, then this block gets pruned and is not anymore in the new best block branch, comes back, etc. We'll pass all that information to the consumer.
280
289
281
-
Then, when the tx will be finalized, we'll emit the following event once and will complete the subscription.
290
+
Here two things can happen. The first one is that the tx gets in a block that becomes finalized. In this case we will emit the following event once and will complete the subscription.
282
291
283
292
```ts
284
293
typeTxFinalized= {
@@ -295,10 +304,12 @@ At this stage, the transaction is valid and already in the canonical chain, in a
295
304
296
305
- `ok`: it tells if the extrinsic was successful in its purpose. Under the hood it basically checks that the event `System.ExtrinsicFailed` was not emitted.
297
306
- `events`: array of all events emitted by the extrinsic. They are ordered as emitted on-chain.
298
-
- `dispatchError`: in case the transaction failed, this will have the `dispatchError` value of `System.ExtrinsicFailed`.
307
+
- `dispatchError`: in case the transaction failed, this will have the `dispatchError` value of `System.ExtrinsicFailed`. Read more about it in [`DispatchError`](#dispatcherror)
299
308
- `block`: information of the block where the `tx` is present. `hash` of the block, `number` of the block, `index` of the tx in the block.
300
309
301
-
### `InvalidError`
310
+
On the other hand, if the transaction is invalid in any finalized block after the broadcasting the observable will error with an [`InvalidTxError`](#invalidtxerror).
311
+
312
+
### `InvalidTxError`
302
313
303
314
When a transaction is deemed as invalid (due to, for example, wrong nonce, expired mortality, not enough balance to pay the fees, etc) we provide a strongly typed error. It can be used as follows:
304
315
@@ -334,7 +345,7 @@ This error will only be available for chains with Runtime Metadata `v15` or grea
334
345
In case you are using the whitelist feature of the codegen, remember to add `"api.TaggedTransactionQueue.validate_transaction"` to the list of whitelisted interactions.
335
346
:::
336
347
337
-
### Failed extrinsic
348
+
### `DispatchError`
338
349
339
350
In Polkadot, a transaction can be valid (and therefore not to throw the `InvalidError`) but the inner extrinsic fail. In this case, the event `ExtrinsicFailed` gives all the information required to understand why it failed. We also expose a `dispatchError` field that helps to guess why it failed. Better a picture than a thousand words:
0 commit comments