Obtain DispatchError::Module info dynamically#453
Conversation
There was a problem hiding this comment.
Using this API is a bit clunky, e.g.
.wait_for_finalized_success()
.await
.map_err(|e| match e {
subxt::Error::Runtime(err) => {
let inner = err.inner();
match inner.details(self.api.client.metadata()) {
Ok(Some(details)) =>
eyre::eyre!(
"Runtime: {} -> {}: {:?}",
details.pallet(),
details.error(),
details.description(),
),
Ok(None) => eyre::eyre!("Runtime: {:?}", inner),
Err(e) => e.into(),
}
}
err => err.into(),
})?;Perhaps we could integrate it directly into wait_for_success, by defining a trait with fn module_error_indices(&self) -> (u8, u8) which is implemented by the macro where at the moment you define fn details(&metadata: Metadata). In this context we already have the self.client so can easily grab a reference to the metadata. Then we can construct a tuple (E, Option<ErrorMetadata>).
The slight wrinkle is what to do if the error cannot be resolved from the metadata, perhaps it would be better to roll that in to a None on the right hand side rather than having a nested Option<Result<ErrorMetadata>> or Option<Result<ErrorMetadata>>. Because the original error is still present on the left hand side, so can still match that case with (RuntimeError::ModuleError(_), None)
|
Oooh interesting! I definitely agree that the API is clunky! Your suggestion has got me thinking; if we define the trait you suggest, we could extend the |
It wouldn't be a problem, except that you have to use the same pattern for every extrinsic call, so would have to use a similar helper method everywhere.
Yes that would be very nice, we are usually very interested in what the module error actually is. |
…m easier to work with
|
Ok, I've added a Module variant, and any Finally, if the original Module variant contains extra information beyond the pallet and error index, at present that'll be lost. When we drop backward compat we could more easily embed the new module error struct into this variant that's been added to preserve all of the info. All that said, this API is much nicer to work with! |
| impl<'client, T: Config, E, Evs> Unpin for TransactionProgress<'client, T, E, Evs> {} | ||
|
|
||
| impl<'client, T: Config, E: Decode, Evs: Decode> TransactionProgress<'client, T, E, Evs> { | ||
| impl<'client, T: Config, E: Decode + HasModuleError, Evs: Decode> |
There was a problem hiding this comment.
Maybe worth moving to a where-clause at this point?
Static error info is troublesome if the node you interact with uses a different pallet index for the pallet you're working with. This PR moves error info back to being obtained via runtime metadata, but keeps the
details()fn in codegen for now to provide a nicer API for obtaining it.closes #443.