mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 07:41:08 +00:00
Introduce Metadata type (#974)
* WIP new Metadata type * Finish basic Metadata impl inc hashing and validation * remove caching from metadata; can add that higher up * remove caches * update retain to use Metadata * clippy fixes * update codegen to use Metadata * clippy * WIP fixing subxt lib * WIP fixing tests, rebuild artifacts, fix OrderedMap::retain * get --all-targets compiling * move DispatchError type lookup back to being optional * cargo clippy * fix docs * re-use VariantIndex to get variants * add docs and enforce docs on metadata crate * fix docs * add test and fix docs * cargo fmt * address review comments * update lockfiles * ExactSizeIter so we can ask for len() of things (and hopefully soon is_empty()
This commit is contained in:
@@ -10,7 +10,7 @@ use core::fmt::Debug;
|
||||
use scale_decode::visitor::DecodeAsTypeResult;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::Error;
|
||||
use super::{Error, MetadataError};
|
||||
use crate::error::RootError;
|
||||
|
||||
/// An error dispatching a transaction.
|
||||
@@ -145,20 +145,27 @@ impl std::fmt::Display for ModuleError {
|
||||
return f.write_str("Unknown pallet error (pallet and error details cannot be retrieved)");
|
||||
};
|
||||
|
||||
let pallet = details.pallet();
|
||||
let error = details.error();
|
||||
let pallet = details.pallet.name();
|
||||
let error = &details.variant.name;
|
||||
write!(f, "Pallet error {pallet}::{error}")
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleError {
|
||||
/// Return more details about this error.
|
||||
pub fn details(&self) -> Result<&crate::metadata::ErrorMetadata, super::Error> {
|
||||
let error_details = self
|
||||
pub fn details(&self) -> Result<ModuleErrorDetails, MetadataError> {
|
||||
let pallet = self
|
||||
.metadata
|
||||
.error(self.raw.pallet_index, self.raw.error[0])?;
|
||||
Ok(error_details)
|
||||
.pallet_by_index(self.raw.pallet_index)
|
||||
.ok_or(MetadataError::PalletIndexNotFound(self.raw.pallet_index))?;
|
||||
|
||||
let variant = pallet
|
||||
.error_variant_by_index(self.raw.error[0])
|
||||
.ok_or_else(|| MetadataError::VariantIndexNotFound(self.raw.error[0]))?;
|
||||
|
||||
Ok(ModuleErrorDetails { pallet, variant })
|
||||
}
|
||||
|
||||
/// Return the underlying module error data that was decoded.
|
||||
pub fn raw(&self) -> RawModuleError {
|
||||
self.raw
|
||||
@@ -167,10 +174,22 @@ impl ModuleError {
|
||||
/// Attempts to decode the ModuleError into a value implementing the trait `RootError`
|
||||
/// where the actual type of value is the generated top level enum `Error`.
|
||||
pub fn as_root_error<E: RootError>(&self) -> Result<E, Error> {
|
||||
E::root_error(&self.raw.error, self.details()?.pallet(), &self.metadata)
|
||||
E::root_error(
|
||||
&self.raw.error,
|
||||
self.details()?.pallet.name(),
|
||||
&self.metadata,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Details about the module error.
|
||||
pub struct ModuleErrorDetails<'a> {
|
||||
/// The pallet that the error came from
|
||||
pub pallet: crate::metadata::types::PalletMetadata<'a>,
|
||||
/// The variant representing the error
|
||||
pub variant: &'a scale_info::Variant<scale_info::form::PortableForm>,
|
||||
}
|
||||
|
||||
/// The error details about a module error that has occurred.
|
||||
///
|
||||
/// **Note**: Structure used to obtain the underlying bytes of a ModuleError.
|
||||
@@ -198,16 +217,9 @@ impl DispatchError {
|
||||
metadata: Metadata,
|
||||
) -> Result<Self, super::Error> {
|
||||
let bytes = bytes.into();
|
||||
|
||||
let dispatch_error_ty_id = match metadata.dispatch_error_ty() {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
tracing::warn!(
|
||||
"Can't decode error: sp_runtime::DispatchError was not found in Metadata"
|
||||
);
|
||||
return Err(super::Error::Unknown(bytes.into_owned()));
|
||||
}
|
||||
};
|
||||
let dispatch_error_ty_id = metadata
|
||||
.dispatch_error_ty()
|
||||
.ok_or(MetadataError::DispatchErrorNotFound)?;
|
||||
|
||||
// The aim is to decode our bytes into roughly this shape. This is copied from
|
||||
// `sp_runtime::DispatchError`; we need the variant names and any inner variant
|
||||
|
||||
+54
-8
@@ -14,9 +14,10 @@ pub use dispatch_error::{
|
||||
};
|
||||
|
||||
// Re-expose the errors we use from other crates here:
|
||||
pub use crate::metadata::{InvalidMetadataError, Metadata, MetadataError};
|
||||
pub use crate::metadata::Metadata;
|
||||
pub use scale_decode::Error as DecodeError;
|
||||
pub use scale_encode::Error as EncodeError;
|
||||
pub use subxt_metadata::TryFromError as MetadataTryFromError;
|
||||
|
||||
/// The underlying error enum, generic over the type held by the `Runtime`
|
||||
/// variant. Prefer to use the [`Error<E>`] and [`Error`] aliases over
|
||||
@@ -36,12 +37,12 @@ pub enum Error {
|
||||
/// Serde serialization error
|
||||
#[error("Serde json error: {0}")]
|
||||
Serialization(#[from] serde_json::error::Error),
|
||||
/// Invalid metadata error
|
||||
#[error("Invalid Metadata: {0}")]
|
||||
InvalidMetadata(#[from] InvalidMetadataError),
|
||||
/// Invalid metadata error
|
||||
/// Error working with metadata.
|
||||
#[error("Metadata: {0}")]
|
||||
Metadata(#[from] MetadataError),
|
||||
/// Error decoding metadata.
|
||||
#[error("Metadata: {0}")]
|
||||
MetadataDecoding(#[from] MetadataTryFromError),
|
||||
/// Runtime error.
|
||||
#[error("Runtime error: {0:?}")]
|
||||
Runtime(#[from] DispatchError),
|
||||
@@ -160,9 +161,6 @@ pub enum StorageAddressError {
|
||||
/// The number of keys provided in the storage address.
|
||||
expected: usize,
|
||||
},
|
||||
/// Storage lookup requires a type that wasn't found in the metadata.
|
||||
#[error("Storage lookup requires type {0} to exist in the metadata, but it was not found")]
|
||||
TypeNotFound(u32),
|
||||
/// This storage entry in the metadata does not have the correct number of hashers to fields.
|
||||
#[error("Storage entry in metadata does not have the correct number of hashers to fields")]
|
||||
WrongNumberOfHashers {
|
||||
@@ -173,6 +171,54 @@ pub enum StorageAddressError {
|
||||
},
|
||||
}
|
||||
|
||||
/// Something went wrong trying to access details in the metadata.
|
||||
#[derive(Clone, Debug, PartialEq, thiserror::Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum MetadataError {
|
||||
/// The DispatchError type isn't available in the metadata
|
||||
#[error("The DispatchError type isn't available")]
|
||||
DispatchErrorNotFound,
|
||||
/// Type not found in metadata.
|
||||
#[error("Type with ID {0} not found")]
|
||||
TypeNotFound(u32),
|
||||
/// Pallet not found (index).
|
||||
#[error("Pallet with index {0} not found")]
|
||||
PalletIndexNotFound(u8),
|
||||
/// Pallet not found (name).
|
||||
#[error("Pallet with name {0} not found")]
|
||||
PalletNameNotFound(String),
|
||||
/// Variant not found.
|
||||
#[error("Variant with index {0} not found")]
|
||||
VariantIndexNotFound(u8),
|
||||
/// Constant not found.
|
||||
#[error("Constant with name {0} not found")]
|
||||
ConstantNameNotFound(String),
|
||||
/// Call not found.
|
||||
#[error("Call with name {0} not found")]
|
||||
CallNameNotFound(String),
|
||||
/// Runtime trait not found.
|
||||
#[error("Runtime trait with name {0} not found")]
|
||||
RuntimeTraitNotFound(String),
|
||||
/// Runtime method not found.
|
||||
#[error("Runtime method with name {0} not found")]
|
||||
RuntimeMethodNotFound(String),
|
||||
/// Call type not found in metadata.
|
||||
#[error("Call type not found in pallet with index {0}")]
|
||||
CallTypeNotFoundInPallet(u8),
|
||||
/// Event type not found in metadata.
|
||||
#[error("Event type not found in pallet with index {0}")]
|
||||
EventTypeNotFoundInPallet(u8),
|
||||
/// Storage details not found in metadata.
|
||||
#[error("Storage details not found in pallet with name {0}")]
|
||||
StorageNotFoundInPallet(String),
|
||||
/// Storage entry not found.
|
||||
#[error("Storage entry {0} not found")]
|
||||
StorageEntryNotFound(String),
|
||||
/// The generated interface used is not compatible with the node.
|
||||
#[error("The generated code is not compatible with the node")]
|
||||
IncompatibleCodegen,
|
||||
}
|
||||
|
||||
/// This trait is implemented on the statically generated root ModuleError type
|
||||
#[doc(hidden)]
|
||||
pub trait RootError: Sized {
|
||||
|
||||
Reference in New Issue
Block a user