mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 07:01:05 +00:00
Claude pass
This commit is contained in:
@@ -7,7 +7,7 @@ use crate::{
|
|||||||
blocks::Extrinsics,
|
blocks::Extrinsics,
|
||||||
client::{OfflineClientT, OnlineClientT},
|
client::{OfflineClientT, OnlineClientT},
|
||||||
config::{Config, HashFor, Header},
|
config::{Config, HashFor, Header},
|
||||||
error::{BlockError, DecodeError, Error},
|
error::{BlockError, Error},
|
||||||
events,
|
events,
|
||||||
runtime_api::RuntimeApi,
|
runtime_api::RuntimeApi,
|
||||||
storage::StorageClientAt,
|
storage::StorageClientAt,
|
||||||
@@ -173,10 +173,10 @@ where
|
|||||||
4 => u32::decode(cursor)?.into(),
|
4 => u32::decode(cursor)?.into(),
|
||||||
8 => u64::decode(cursor)?,
|
8 => u64::decode(cursor)?,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::Decode(DecodeError::custom_string(format!(
|
return Err(Error::Other(format!(
|
||||||
"state call AccountNonceApi_account_nonce returned an unexpected number of bytes: {} (expected 2, 4 or 8)",
|
"state call AccountNonceApi_account_nonce returned an unexpected number of bytes: {} (expected 2, 4 or 8)",
|
||||||
account_nonce_bytes.len()
|
account_nonce_bytes.len()
|
||||||
))));
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(account_nonce)
|
Ok(account_nonce)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use scale_decode::{DecodeAsType, TypeResolver, visitor::DecodeAsTypeResult};
|
|||||||
|
|
||||||
use std::{borrow::Cow, marker::PhantomData};
|
use std::{borrow::Cow, marker::PhantomData};
|
||||||
|
|
||||||
use super::{Error, MetadataError};
|
use super::Error;
|
||||||
|
|
||||||
/// An error dispatching a transaction.
|
/// An error dispatching a transaction.
|
||||||
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
|
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
|
||||||
@@ -169,24 +169,22 @@ impl std::fmt::Display for ModuleError {
|
|||||||
|
|
||||||
impl ModuleError {
|
impl ModuleError {
|
||||||
/// Return more details about this error.
|
/// Return more details about this error.
|
||||||
pub fn details(&self) -> Result<ModuleErrorDetails<'_>, MetadataError> {
|
pub fn details(&self) -> Option<ModuleErrorDetails<'_>> {
|
||||||
let pallet = self.metadata.pallet_by_index_err(self.pallet_index())?;
|
let pallet = self.metadata.pallet_by_index(self.pallet_index())?;
|
||||||
let variant = pallet
|
let variant = pallet.error_variant_by_index(self.error_index())?;
|
||||||
.error_variant_by_index(self.error_index())
|
|
||||||
.ok_or_else(|| MetadataError::VariantIndexNotFound(self.error_index()))?;
|
|
||||||
|
|
||||||
Ok(ModuleErrorDetails { pallet, variant })
|
Some(ModuleErrorDetails { pallet, variant })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a formatted string of the resolved error details for debugging/display purposes.
|
/// Return a formatted string of the resolved error details for debugging/display purposes.
|
||||||
pub fn details_string(&self) -> String {
|
pub fn details_string(&self) -> String {
|
||||||
match self.details() {
|
match self.details() {
|
||||||
Ok(details) => format!(
|
Some(details) => format!(
|
||||||
"{pallet_name}::{variant_name}",
|
"{pallet_name}::{variant_name}",
|
||||||
pallet_name = details.pallet.name(),
|
pallet_name = details.pallet.name(),
|
||||||
variant_name = details.variant.name,
|
variant_name = details.variant.name,
|
||||||
),
|
),
|
||||||
Err(_) => format!(
|
None => format!(
|
||||||
"Unknown pallet error '{bytes:?}' (pallet and error details cannot be retrieved)",
|
"Unknown pallet error '{bytes:?}' (pallet and error details cannot be retrieved)",
|
||||||
bytes = self.bytes
|
bytes = self.bytes
|
||||||
),
|
),
|
||||||
@@ -223,7 +221,7 @@ impl ModuleError {
|
|||||||
/// Details about the module error.
|
/// Details about the module error.
|
||||||
pub struct ModuleErrorDetails<'a> {
|
pub struct ModuleErrorDetails<'a> {
|
||||||
/// The pallet that the error is in
|
/// The pallet that the error is in
|
||||||
pub pallet: crate::metadata::types::PalletMetadata<'a>,
|
pub pallet: crate::metadata::PalletMetadata<'a>,
|
||||||
/// The variant representing the error
|
/// The variant representing the error
|
||||||
pub variant: &'a scale_info::Variant<scale_info::form::PortableForm>,
|
pub variant: &'a scale_info::Variant<scale_info::form::PortableForm>,
|
||||||
}
|
}
|
||||||
@@ -238,7 +236,7 @@ impl DispatchError {
|
|||||||
let bytes = bytes.into();
|
let bytes = bytes.into();
|
||||||
let dispatch_error_ty_id = metadata
|
let dispatch_error_ty_id = metadata
|
||||||
.dispatch_error_ty()
|
.dispatch_error_ty()
|
||||||
.ok_or(MetadataError::DispatchErrorNotFound)?;
|
.ok_or_else(|| super::Error::Other("DispatchError type not found in metadata".to_string()))?;
|
||||||
|
|
||||||
// The aim is to decode our bytes into roughly this shape. This is copied from
|
// 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
|
// `sp_runtime::DispatchError`; we need the variant names and any inner variant
|
||||||
@@ -290,10 +288,10 @@ impl DispatchError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decode into our temporary error:
|
// Decode into our temporary error:
|
||||||
let decoded_dispatch_err = DecodedDispatchError::decode_with_metadata(
|
let decoded_dispatch_err = DecodedDispatchError::decode_as_type(
|
||||||
&mut &*bytes,
|
&mut &*bytes,
|
||||||
dispatch_error_ty_id,
|
dispatch_error_ty_id,
|
||||||
&metadata,
|
metadata.types(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Convert into the outward-facing error, mainly by handling the Module variant.
|
// Convert into the outward-facing error, mainly by handling the Module variant.
|
||||||
|
|||||||
+512
-68
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
mod dispatch_error;
|
mod dispatch_error;
|
||||||
|
|
||||||
use subxt_core::error::{BlockError as CoreBlockError, Error as CoreError};
|
use subxt_core::error::Error as CoreError;
|
||||||
|
|
||||||
crate::macros::cfg_unstable_light_client! {
|
crate::macros::cfg_unstable_light_client! {
|
||||||
pub use subxt_lightclient::LightClientError;
|
pub use subxt_lightclient::LightClientError;
|
||||||
@@ -19,11 +19,20 @@ pub use dispatch_error::{
|
|||||||
|
|
||||||
// Re-expose the errors we use from other crates here:
|
// Re-expose the errors we use from other crates here:
|
||||||
pub use crate::Metadata;
|
pub use crate::Metadata;
|
||||||
pub use scale_decode::Error as DecodeError;
|
|
||||||
pub use scale_encode::Error as EncodeError;
|
|
||||||
pub use subxt_core::error::{ExtrinsicError, MetadataError, StorageError};
|
|
||||||
pub use subxt_metadata::TryFromError as MetadataTryFromError;
|
pub use subxt_metadata::TryFromError as MetadataTryFromError;
|
||||||
|
|
||||||
|
// Re-export subxt-core error types that we'll use directly:
|
||||||
|
pub use subxt_core::error::{
|
||||||
|
ConstantError as CoreConstantError,
|
||||||
|
CustomValueError as CoreCustomValueError,
|
||||||
|
EventsError as CoreEventsError,
|
||||||
|
ExtrinsicError as CoreExtrinsicError,
|
||||||
|
ExtrinsicParamsError,
|
||||||
|
RuntimeApiError as CoreRuntimeApiError,
|
||||||
|
StorageError as CoreStorageError,
|
||||||
|
ViewFunctionError as CoreViewFunctionError,
|
||||||
|
};
|
||||||
|
|
||||||
/// The underlying error enum, generic over the type held by the `Runtime`
|
/// The underlying error enum, generic over the type held by the `Runtime`
|
||||||
/// variant. Prefer to use the [`Error<E>`] and [`Error`] aliases over
|
/// variant. Prefer to use the [`Error<E>`] and [`Error`] aliases over
|
||||||
/// using this type directly.
|
/// using this type directly.
|
||||||
@@ -31,71 +40,66 @@ pub use subxt_metadata::TryFromError as MetadataTryFromError;
|
|||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Io error.
|
/// Io error.
|
||||||
#[error("Io error: {0}")]
|
#[error(transparent)]
|
||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
/// Codec error.
|
|
||||||
#[error("Scale codec error: {0}")]
|
|
||||||
Codec(#[from] codec::Error),
|
|
||||||
/// Rpc error.
|
/// Rpc error.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Rpc(#[from] RpcError),
|
Rpc(#[from] RpcError),
|
||||||
/// Serde serialization error
|
/// Serde serialization error
|
||||||
#[error("Serde json error: {0}")]
|
#[error(transparent)]
|
||||||
Serialization(#[from] serde_json::error::Error),
|
Serialization(#[from] serde_json::error::Error),
|
||||||
/// Error working with metadata.
|
|
||||||
#[error("Metadata error: {0}")]
|
|
||||||
Metadata(#[from] MetadataError),
|
|
||||||
/// Error decoding metadata.
|
/// Error decoding metadata.
|
||||||
#[error("Metadata Decoding error: {0}")]
|
#[error(transparent)]
|
||||||
MetadataDecoding(#[from] MetadataTryFromError),
|
MetadataDecoding(#[from] MetadataTryFromError),
|
||||||
/// Runtime error.
|
/// Runtime error.
|
||||||
#[error("Runtime error: {0}")]
|
#[error(transparent)]
|
||||||
Runtime(#[from] DispatchError),
|
Runtime(#[from] DispatchError),
|
||||||
/// Error decoding to a [`crate::dynamic::Value`].
|
|
||||||
#[error("Error decoding into dynamic value: {0}")]
|
|
||||||
Decode(#[from] DecodeError),
|
|
||||||
/// Error encoding from a [`crate::dynamic::Value`].
|
|
||||||
#[error("Error encoding from dynamic value: {0}")]
|
|
||||||
Encode(#[from] EncodeError),
|
|
||||||
/// Transaction progress error.
|
/// Transaction progress error.
|
||||||
#[error("Transaction error: {0}")]
|
#[error(transparent)]
|
||||||
Transaction(#[from] TransactionError),
|
Transaction(#[from] TransactionError),
|
||||||
/// Error constructing the appropriate extrinsic params.
|
|
||||||
#[error("Extrinsic params error: {0}")]
|
|
||||||
Extrinsic(#[from] ExtrinsicError),
|
|
||||||
/// Block related error.
|
/// Block related error.
|
||||||
#[error("Block error: {0}")]
|
#[error(transparent)]
|
||||||
Block(#[from] BlockError),
|
Block(#[from] BlockError),
|
||||||
/// An error encoding a storage address.
|
/// Storage error.
|
||||||
#[error("Error encoding storage address: {0}")]
|
#[error(transparent)]
|
||||||
StorageAddress(#[from] StorageError),
|
Storage(#[from] StorageError),
|
||||||
|
/// Storage key error.
|
||||||
|
#[error(transparent)]
|
||||||
|
StorageKey(#[from] StorageKeyError),
|
||||||
|
/// Storage value error.
|
||||||
|
#[error(transparent)]
|
||||||
|
StorageValue(#[from] StorageValueError),
|
||||||
|
/// Constant error.
|
||||||
|
#[error(transparent)]
|
||||||
|
Constant(#[from] ConstantError),
|
||||||
|
/// Custom value error.
|
||||||
|
#[error(transparent)]
|
||||||
|
CustomValue(#[from] CustomValueError),
|
||||||
|
/// Runtime API error.
|
||||||
|
#[error(transparent)]
|
||||||
|
RuntimeApi(#[from] RuntimeApiError),
|
||||||
|
/// View function error.
|
||||||
|
#[error(transparent)]
|
||||||
|
ViewFunction(#[from] ViewFunctionError),
|
||||||
|
/// Events error.
|
||||||
|
#[error(transparent)]
|
||||||
|
Events(#[from] EventsError),
|
||||||
|
/// Extrinsic error.
|
||||||
|
#[error(transparent)]
|
||||||
|
Extrinsic(#[from] ExtrinsicError),
|
||||||
/// The bytes representing an error that we were unable to decode.
|
/// The bytes representing an error that we were unable to decode.
|
||||||
#[error("An error occurred but it could not be decoded: {0:?}")]
|
#[error("An error occurred but it could not be decoded: {0:?}")]
|
||||||
Unknown(Vec<u8>),
|
Unknown(Vec<u8>),
|
||||||
/// Light client error.
|
/// Light client error.
|
||||||
#[cfg(feature = "unstable-light-client")]
|
#[cfg(feature = "unstable-light-client")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-light-client")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-light-client")))]
|
||||||
#[error("An error occurred but it could not be decoded: {0}")]
|
#[error(transparent)]
|
||||||
LightClient(#[from] LightClientError),
|
LightClient(#[from] LightClientError),
|
||||||
/// Other error.
|
/// Other error.
|
||||||
#[error("Other error: {0}")]
|
#[error("Other error: {0}")]
|
||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CoreError> for Error {
|
|
||||||
fn from(value: CoreError) -> Self {
|
|
||||||
match value {
|
|
||||||
CoreError::Codec(e) => Error::Codec(e),
|
|
||||||
CoreError::Metadata(e) => Error::Metadata(e),
|
|
||||||
CoreError::StorageError(e) => Error::StorageAddress(e),
|
|
||||||
CoreError::Decode(e) => Error::Decode(e),
|
|
||||||
CoreError::Encode(e) => Error::Encode(e),
|
|
||||||
CoreError::Extrinsic(e) => Error::Extrinsic(e),
|
|
||||||
CoreError::Block(e) => Error::Block(e.into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<&'a str> for Error {
|
impl<'a> From<&'a str> for Error {
|
||||||
fn from(error: &'a str) -> Self {
|
fn from(error: &'a str) -> Self {
|
||||||
Error::Other(error.into())
|
Error::Other(error.into())
|
||||||
@@ -114,9 +118,17 @@ impl From<std::convert::Infallible> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<scale_decode::visitor::DecodeError> for Error {
|
impl From<codec::Error> for Error {
|
||||||
fn from(value: scale_decode::visitor::DecodeError) -> Self {
|
fn from(value: codec::Error) -> Self {
|
||||||
Error::Decode(value.into())
|
// Codec errors typically happen during event/extrinsic decoding, so we map to Other
|
||||||
|
Error::Other(format!("Codec error: {}", value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<scale_decode::Error> for Error {
|
||||||
|
fn from(value: scale_decode::Error) -> Self {
|
||||||
|
// Scale decode errors typically happen during decoding, so we map to Other
|
||||||
|
Error::Other(format!("Decode error: {}", value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +138,62 @@ impl From<subxt_rpcs::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add From implementations for core error types through their module-specific wrappers
|
||||||
|
impl From<CoreStorageError> for Error {
|
||||||
|
fn from(e: CoreStorageError) -> Self {
|
||||||
|
Error::Storage(StorageError::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreExtrinsicError> for Error {
|
||||||
|
fn from(e: CoreExtrinsicError) -> Self {
|
||||||
|
Error::Extrinsic(ExtrinsicError::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreConstantError> for Error {
|
||||||
|
fn from(e: CoreConstantError) -> Self {
|
||||||
|
Error::Constant(ConstantError::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreCustomValueError> for Error {
|
||||||
|
fn from(e: CoreCustomValueError) -> Self {
|
||||||
|
Error::CustomValue(CustomValueError::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreRuntimeApiError> for Error {
|
||||||
|
fn from(e: CoreRuntimeApiError) -> Self {
|
||||||
|
Error::RuntimeApi(RuntimeApiError::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreViewFunctionError> for Error {
|
||||||
|
fn from(e: CoreViewFunctionError) -> Self {
|
||||||
|
Error::ViewFunction(ViewFunctionError::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreEventsError> for Error {
|
||||||
|
fn from(e: CoreEventsError) -> Self {
|
||||||
|
Error::Events(EventsError::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add From implementations for frame_decode error types that go through StorageError
|
||||||
|
impl From<frame_decode::storage::StorageInfoError<'_>> for Error {
|
||||||
|
fn from(e: frame_decode::storage::StorageInfoError<'_>) -> Self {
|
||||||
|
Error::Storage(StorageError::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<frame_decode::storage::StorageKeyEncodeError> for Error {
|
||||||
|
fn from(e: frame_decode::storage::StorageKeyEncodeError) -> Self {
|
||||||
|
Error::Storage(StorageError::from(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
/// Checks whether the error was caused by a RPC re-connection.
|
/// Checks whether the error was caused by a RPC re-connection.
|
||||||
pub fn is_disconnected_will_reconnect(&self) -> bool {
|
pub fn is_disconnected_will_reconnect(&self) -> bool {
|
||||||
@@ -185,31 +253,10 @@ pub enum BlockError {
|
|||||||
/// Index of the extrinsic that failed to decode.
|
/// Index of the extrinsic that failed to decode.
|
||||||
extrinsic_index: usize,
|
extrinsic_index: usize,
|
||||||
/// The decode error.
|
/// The decode error.
|
||||||
error: subxt_core::error::ExtrinsicDecodeError,
|
error: frame_decode::extrinsics::ExtrinsicDecodeError,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CoreBlockError> for BlockError {
|
|
||||||
fn from(value: CoreBlockError) -> Self {
|
|
||||||
match value {
|
|
||||||
CoreBlockError::LeftoverBytes {
|
|
||||||
extrinsic_index,
|
|
||||||
num_leftover_bytes,
|
|
||||||
} => BlockError::LeftoverBytes {
|
|
||||||
extrinsic_index,
|
|
||||||
num_leftover_bytes,
|
|
||||||
},
|
|
||||||
CoreBlockError::ExtrinsicDecodeError {
|
|
||||||
extrinsic_index,
|
|
||||||
error,
|
|
||||||
} => BlockError::ExtrinsicDecodeError {
|
|
||||||
extrinsic_index,
|
|
||||||
error,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BlockError {
|
impl BlockError {
|
||||||
/// Produce an error that a block with the given hash cannot be found.
|
/// Produce an error that a block with the given hash cannot be found.
|
||||||
pub fn not_found(hash: impl AsRef<[u8]>) -> BlockError {
|
pub fn not_found(hash: impl AsRef<[u8]>) -> BlockError {
|
||||||
@@ -238,3 +285,400 @@ pub enum TransactionError {
|
|||||||
#[error("The transaction was dropped: {0}")]
|
#[error("The transaction was dropped: {0}")]
|
||||||
Dropped(String),
|
Dropped(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Module-specific error types following the subxt-core pattern:
|
||||||
|
|
||||||
|
/// Errors that can occur when working with storage.
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum StorageError {
|
||||||
|
#[error("Storage: The static storage address used is not compatible with the live chain")]
|
||||||
|
IncompatibleCodegen,
|
||||||
|
#[error("Storage: Can't find storage value - pallet with name '{0}' not found")]
|
||||||
|
PalletNameNotFound(String),
|
||||||
|
#[error("Storage: Entry '{entry_name}' not found in pallet '{pallet_name}'")]
|
||||||
|
StorageEntryNotFound {
|
||||||
|
pallet_name: String,
|
||||||
|
entry_name: String,
|
||||||
|
},
|
||||||
|
#[error("Storage: Cannot obtain storage information from metadata: {0}")]
|
||||||
|
StorageInfoError(String),
|
||||||
|
#[error("Storage: Cannot decode storage value: {0}")]
|
||||||
|
StorageValueDecodeError(String),
|
||||||
|
#[error("Storage: Cannot encode storage key: {0}")]
|
||||||
|
StorageKeyEncodeError(#[from] frame_decode::storage::StorageKeyEncodeError),
|
||||||
|
#[error("Storage: RPC error - {0}")]
|
||||||
|
Rpc(#[from] RpcError),
|
||||||
|
#[error("Storage: Could not fetch next entry from storage subscription - {reason}")]
|
||||||
|
StorageEventError {
|
||||||
|
reason: String,
|
||||||
|
},
|
||||||
|
#[error(
|
||||||
|
"Storage: Wrong number of keys provided (expected {num_keys_expected}, got {num_keys_provided})"
|
||||||
|
)]
|
||||||
|
WrongNumberOfKeysProvidedForFetch {
|
||||||
|
num_keys_provided: usize,
|
||||||
|
num_keys_expected: usize,
|
||||||
|
},
|
||||||
|
#[error(
|
||||||
|
"Storage: Too many keys provided for iteration (expected at most {max_keys_expected}, got {num_keys_provided})"
|
||||||
|
)]
|
||||||
|
TooManyKeysProvidedForIter {
|
||||||
|
num_keys_provided: usize,
|
||||||
|
max_keys_expected: usize,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreStorageError> for StorageError {
|
||||||
|
fn from(e: CoreStorageError) -> Self {
|
||||||
|
match e {
|
||||||
|
CoreStorageError::IncompatibleCodegen => StorageError::IncompatibleCodegen,
|
||||||
|
CoreStorageError::PalletNameNotFound(name) => StorageError::PalletNameNotFound(name),
|
||||||
|
CoreStorageError::StorageEntryNotFound { pallet_name, entry_name } => {
|
||||||
|
StorageError::StorageEntryNotFound { pallet_name, entry_name }
|
||||||
|
}
|
||||||
|
CoreStorageError::StorageInfoError(e) => StorageError::StorageInfoError(e.to_string()),
|
||||||
|
CoreStorageError::StorageValueDecodeError(e) => {
|
||||||
|
StorageError::StorageValueDecodeError(e.to_string())
|
||||||
|
}
|
||||||
|
CoreStorageError::StorageKeyEncodeError(e) => StorageError::StorageKeyEncodeError(e),
|
||||||
|
_ => StorageError::StorageInfoError(e.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<frame_decode::storage::StorageInfoError<'_>> for StorageError {
|
||||||
|
fn from(e: frame_decode::storage::StorageInfoError<'_>) -> Self {
|
||||||
|
StorageError::StorageInfoError(e.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur when working with storage keys.
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum StorageKeyError {
|
||||||
|
#[error("Storage: Could not decode storage key - {reason}")]
|
||||||
|
DecodeError {
|
||||||
|
reason: frame_decode::storage::StorageKeyDecodeError<String>,
|
||||||
|
},
|
||||||
|
#[error("Storage: Could not decode storage key - leftover bytes after decoding")]
|
||||||
|
LeftoverBytes {
|
||||||
|
leftover_bytes: Vec<u8>,
|
||||||
|
},
|
||||||
|
#[error("Storage: Could not decode part of storage key at index {index} - {reason}")]
|
||||||
|
DecodePartError {
|
||||||
|
index: usize,
|
||||||
|
reason: scale_decode::Error,
|
||||||
|
},
|
||||||
|
#[error("Storage: Could not decode values from storage key - {reason}")]
|
||||||
|
DecodeKeyValueError {
|
||||||
|
reason: frame_decode::storage::StorageKeyValueDecodeError,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur when working with storage values.
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum StorageValueError {
|
||||||
|
#[error("Storage: Could not decode storage value - {reason}")]
|
||||||
|
DecodeError {
|
||||||
|
reason: scale_decode::Error,
|
||||||
|
},
|
||||||
|
#[error("Storage: Could not decode storage value - leftover bytes after decoding")]
|
||||||
|
LeftoverBytes {
|
||||||
|
leftover_bytes: Vec<u8>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur when working with constants.
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum ConstantError {
|
||||||
|
#[error("Constant: The static constant address used is not compatible with the live chain")]
|
||||||
|
IncompatibleCodegen,
|
||||||
|
#[error("Constant: Can't find constant - pallet with name '{0}' not found")]
|
||||||
|
PalletNameNotFound(String),
|
||||||
|
#[error("Constant: '{constant_name}' not found in pallet '{pallet_name}'")]
|
||||||
|
ConstantNameNotFound {
|
||||||
|
pallet_name: String,
|
||||||
|
constant_name: String,
|
||||||
|
},
|
||||||
|
#[error("Constant: Failed to decode constant - {0}")]
|
||||||
|
CouldNotDecodeConstant(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreConstantError> for ConstantError {
|
||||||
|
fn from(e: CoreConstantError) -> Self {
|
||||||
|
match e {
|
||||||
|
CoreConstantError::IncompatibleCodegen => ConstantError::IncompatibleCodegen,
|
||||||
|
CoreConstantError::PalletNameNotFound(name) => ConstantError::PalletNameNotFound(name),
|
||||||
|
CoreConstantError::ConstantNameNotFound { pallet_name, constant_name } => {
|
||||||
|
ConstantError::ConstantNameNotFound { pallet_name, constant_name }
|
||||||
|
}
|
||||||
|
CoreConstantError::CouldNotDecodeConstant(e) => {
|
||||||
|
ConstantError::CouldNotDecodeConstant(e.to_string())
|
||||||
|
}
|
||||||
|
_ => ConstantError::CouldNotDecodeConstant(e.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur when working with custom values.
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum CustomValueError {
|
||||||
|
#[error("Custom Value: The static custom value address used is not compatible with the live chain")]
|
||||||
|
IncompatibleCodegen,
|
||||||
|
#[error("Custom Value: '{0}' was not found")]
|
||||||
|
NotFound(String),
|
||||||
|
#[error("Custom Value: Failed to decode custom value - {0}")]
|
||||||
|
CouldNotDecodeCustomValue(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreCustomValueError> for CustomValueError {
|
||||||
|
fn from(e: CoreCustomValueError) -> Self {
|
||||||
|
match e {
|
||||||
|
CoreCustomValueError::IncompatibleCodegen => CustomValueError::IncompatibleCodegen,
|
||||||
|
CoreCustomValueError::NotFound(name) => CustomValueError::NotFound(name),
|
||||||
|
CoreCustomValueError::CouldNotDecodeCustomValue(e) => {
|
||||||
|
CustomValueError::CouldNotDecodeCustomValue(e.to_string())
|
||||||
|
}
|
||||||
|
_ => CustomValueError::CouldNotDecodeCustomValue(e.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur when working with runtime APIs.
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum RuntimeApiError {
|
||||||
|
#[error("Runtime API: The static Runtime API address used is not compatible with the live chain")]
|
||||||
|
IncompatibleCodegen,
|
||||||
|
#[error("Runtime API: Trait '{0}' not found")]
|
||||||
|
TraitNotFound(String),
|
||||||
|
#[error("Runtime API: Method '{method_name}' not found in trait '{trait_name}'")]
|
||||||
|
MethodNotFound {
|
||||||
|
trait_name: String,
|
||||||
|
method_name: String,
|
||||||
|
},
|
||||||
|
#[error("Runtime API: Failed to encode inputs - {0}")]
|
||||||
|
CouldNotEncodeInputs(String),
|
||||||
|
#[error("Runtime API: Failed to decode response - {0}")]
|
||||||
|
CouldNotDecodeResponse(String),
|
||||||
|
#[error("Runtime API: RPC error - {0}")]
|
||||||
|
Rpc(#[from] RpcError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreRuntimeApiError> for RuntimeApiError {
|
||||||
|
fn from(e: CoreRuntimeApiError) -> Self {
|
||||||
|
match e {
|
||||||
|
CoreRuntimeApiError::IncompatibleCodegen => RuntimeApiError::IncompatibleCodegen,
|
||||||
|
CoreRuntimeApiError::TraitNotFound(name) => RuntimeApiError::TraitNotFound(name),
|
||||||
|
CoreRuntimeApiError::MethodNotFound { trait_name, method_name } => {
|
||||||
|
RuntimeApiError::MethodNotFound { trait_name, method_name }
|
||||||
|
}
|
||||||
|
CoreRuntimeApiError::CouldNotEncodeInputs(e) => {
|
||||||
|
RuntimeApiError::CouldNotEncodeInputs(e.to_string())
|
||||||
|
}
|
||||||
|
CoreRuntimeApiError::CouldNotDecodeResponse(e) => {
|
||||||
|
RuntimeApiError::CouldNotDecodeResponse(e.to_string())
|
||||||
|
}
|
||||||
|
_ => RuntimeApiError::CouldNotDecodeResponse(e.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur when working with view functions.
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum ViewFunctionError {
|
||||||
|
#[error("View Function: The static View Function address used is not compatible with the live chain")]
|
||||||
|
IncompatibleCodegen,
|
||||||
|
#[error("View Function: Pallet '{0}' not found")]
|
||||||
|
PalletNotFound(String),
|
||||||
|
#[error("View Function: '{function_name}' not found in pallet '{pallet_name}'")]
|
||||||
|
ViewFunctionNotFound {
|
||||||
|
pallet_name: String,
|
||||||
|
function_name: String,
|
||||||
|
},
|
||||||
|
#[error("View Function: Failed to encode inputs - {0}")]
|
||||||
|
CouldNotEncodeInputs(String),
|
||||||
|
#[error("View Function: Failed to decode response - {0}")]
|
||||||
|
CouldNotDecodeResponse(String),
|
||||||
|
#[error("View Function: RPC error - {0}")]
|
||||||
|
Rpc(#[from] RpcError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreViewFunctionError> for ViewFunctionError {
|
||||||
|
fn from(e: CoreViewFunctionError) -> Self {
|
||||||
|
match e {
|
||||||
|
CoreViewFunctionError::IncompatibleCodegen => ViewFunctionError::IncompatibleCodegen,
|
||||||
|
CoreViewFunctionError::PalletNotFound(name) => ViewFunctionError::PalletNotFound(name),
|
||||||
|
CoreViewFunctionError::ViewFunctionNotFound { pallet_name, function_name } => {
|
||||||
|
ViewFunctionError::ViewFunctionNotFound { pallet_name, function_name }
|
||||||
|
}
|
||||||
|
CoreViewFunctionError::CouldNotEncodeInputs(e) => {
|
||||||
|
ViewFunctionError::CouldNotEncodeInputs(e.to_string())
|
||||||
|
}
|
||||||
|
CoreViewFunctionError::CouldNotDecodeResponse(e) => {
|
||||||
|
ViewFunctionError::CouldNotDecodeResponse(e.to_string())
|
||||||
|
}
|
||||||
|
_ => ViewFunctionError::CouldNotDecodeResponse(e.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur when working with events.
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum EventsError {
|
||||||
|
#[error("Events: Can't decode event - can't decode phase: {0}")]
|
||||||
|
CannotDecodePhase(codec::Error),
|
||||||
|
#[error("Events: Can't decode event - can't decode pallet index: {0}")]
|
||||||
|
CannotDecodePalletIndex(codec::Error),
|
||||||
|
#[error("Events: Can't decode event - can't decode variant index: {0}")]
|
||||||
|
CannotDecodeVariantIndex(codec::Error),
|
||||||
|
#[error("Events: Can't decode event - can't find pallet with index {0}")]
|
||||||
|
CannotFindPalletWithIndex(u8),
|
||||||
|
#[error("Events: Can't decode event - can't find variant with index {variant_index} in pallet {pallet_name}")]
|
||||||
|
CannotFindVariantWithIndex {
|
||||||
|
pallet_name: String,
|
||||||
|
variant_index: u8,
|
||||||
|
},
|
||||||
|
#[error("Events: Can't decode field {field_name:?} in event {pallet_name}.{event_name} - {reason}")]
|
||||||
|
CannotDecodeFieldInEvent {
|
||||||
|
pallet_name: String,
|
||||||
|
event_name: String,
|
||||||
|
field_name: String,
|
||||||
|
reason: scale_decode::visitor::DecodeError,
|
||||||
|
},
|
||||||
|
#[error("Events: Can't decode event topics: {0}")]
|
||||||
|
CannotDecodeEventTopics(codec::Error),
|
||||||
|
#[error("Events: Can't decode fields of event {pallet_name}.{event_name} - {reason}")]
|
||||||
|
CannotDecodeEventFields {
|
||||||
|
pallet_name: String,
|
||||||
|
event_name: String,
|
||||||
|
reason: scale_decode::Error,
|
||||||
|
},
|
||||||
|
#[error("Events: Can't decode event {pallet_name}.{event_name} to Event enum - {reason}")]
|
||||||
|
CannotDecodeEventEnum {
|
||||||
|
pallet_name: String,
|
||||||
|
event_name: String,
|
||||||
|
reason: scale_decode::Error,
|
||||||
|
},
|
||||||
|
#[error("Events: RPC error - {0}")]
|
||||||
|
Rpc(#[from] RpcError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreEventsError> for EventsError {
|
||||||
|
fn from(e: CoreEventsError) -> Self {
|
||||||
|
match e {
|
||||||
|
CoreEventsError::CannotDecodePhase(err) => EventsError::CannotDecodePhase(err),
|
||||||
|
CoreEventsError::CannotDecodePalletIndex(err) => EventsError::CannotDecodePalletIndex(err),
|
||||||
|
CoreEventsError::CannotDecodeVariantIndex(err) => EventsError::CannotDecodeVariantIndex(err),
|
||||||
|
CoreEventsError::CannotFindPalletWithIndex(idx) => EventsError::CannotFindPalletWithIndex(idx),
|
||||||
|
CoreEventsError::CannotFindVariantWithIndex { pallet_name, variant_index } => {
|
||||||
|
EventsError::CannotFindVariantWithIndex { pallet_name, variant_index }
|
||||||
|
}
|
||||||
|
CoreEventsError::CannotDecodeFieldInEvent { pallet_name, event_name, field_name, reason } => {
|
||||||
|
EventsError::CannotDecodeFieldInEvent { pallet_name, event_name, field_name, reason }
|
||||||
|
}
|
||||||
|
CoreEventsError::CannotDecodeEventTopics(err) => EventsError::CannotDecodeEventTopics(err),
|
||||||
|
CoreEventsError::CannotDecodeEventFields { pallet_name, event_name, reason } => {
|
||||||
|
EventsError::CannotDecodeEventFields { pallet_name, event_name, reason }
|
||||||
|
}
|
||||||
|
CoreEventsError::CannotDecodeEventEnum { pallet_name, event_name, reason } => {
|
||||||
|
EventsError::CannotDecodeEventEnum { pallet_name, event_name, reason }
|
||||||
|
}
|
||||||
|
_ => EventsError::CannotDecodeEventTopics(codec::Error::from("Unknown events error")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors that can occur when working with extrinsics/transactions.
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum ExtrinsicError {
|
||||||
|
#[error("Extrinsic: The extrinsic payload is not compatible with the live chain")]
|
||||||
|
IncompatibleCodegen,
|
||||||
|
#[error("Extrinsic: Can't find extrinsic - pallet with name '{0}' not found")]
|
||||||
|
PalletNameNotFound(String),
|
||||||
|
#[error("Extrinsic: Call '{call_name}' doesn't exist in pallet '{pallet_name}'")]
|
||||||
|
CallNameNotFound {
|
||||||
|
pallet_name: String,
|
||||||
|
call_name: String,
|
||||||
|
},
|
||||||
|
#[error("Extrinsic: Can't encode call data - {0}")]
|
||||||
|
CannotEncodeCallData(scale_encode::Error),
|
||||||
|
#[error("Extrinsic: Unsupported extrinsic version")]
|
||||||
|
UnsupportedVersion,
|
||||||
|
#[error("Extrinsic: Cannot construct transaction extensions - {0}")]
|
||||||
|
Params(#[from] ExtrinsicParamsError),
|
||||||
|
#[error("Extrinsic: Cannot decode transaction extension '{name}' - {error}")]
|
||||||
|
CouldNotDecodeTransactionExtension {
|
||||||
|
name: String,
|
||||||
|
error: scale_decode::Error,
|
||||||
|
},
|
||||||
|
#[error("Extrinsic: Leftover bytes after decoding extrinsic at index {extrinsic_index} ({num_leftover_bytes} bytes remaining)")]
|
||||||
|
LeftoverBytes {
|
||||||
|
extrinsic_index: usize,
|
||||||
|
num_leftover_bytes: usize,
|
||||||
|
},
|
||||||
|
#[error("Extrinsic: Failed to decode extrinsic at index {extrinsic_index} - {error}")]
|
||||||
|
ExtrinsicDecodeError {
|
||||||
|
extrinsic_index: usize,
|
||||||
|
error: frame_decode::extrinsics::ExtrinsicDecodeError,
|
||||||
|
},
|
||||||
|
#[error("Extrinsic: Failed to decode fields of extrinsic at index {extrinsic_index} - {error}")]
|
||||||
|
CannotDecodeFields {
|
||||||
|
extrinsic_index: usize,
|
||||||
|
error: scale_decode::Error,
|
||||||
|
},
|
||||||
|
#[error("Extrinsic: Failed to decode extrinsic at index {extrinsic_index} to root enum - {error}")]
|
||||||
|
CannotDecodeIntoRootExtrinsic {
|
||||||
|
extrinsic_index: usize,
|
||||||
|
error: scale_decode::Error,
|
||||||
|
},
|
||||||
|
#[error("Extrinsic: RPC error - {0}")]
|
||||||
|
Rpc(#[from] RpcError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CoreExtrinsicError> for ExtrinsicError {
|
||||||
|
fn from(e: CoreExtrinsicError) -> Self {
|
||||||
|
match e {
|
||||||
|
CoreExtrinsicError::IncompatibleCodegen => ExtrinsicError::IncompatibleCodegen,
|
||||||
|
CoreExtrinsicError::PalletNameNotFound(name) => ExtrinsicError::PalletNameNotFound(name),
|
||||||
|
CoreExtrinsicError::CallNameNotFound { pallet_name, call_name } => {
|
||||||
|
ExtrinsicError::CallNameNotFound { pallet_name, call_name }
|
||||||
|
}
|
||||||
|
CoreExtrinsicError::CannotEncodeCallData(err) => ExtrinsicError::CannotEncodeCallData(err),
|
||||||
|
CoreExtrinsicError::UnsupportedVersion => ExtrinsicError::UnsupportedVersion,
|
||||||
|
CoreExtrinsicError::Params(err) => ExtrinsicError::Params(err),
|
||||||
|
CoreExtrinsicError::CouldNotDecodeTransactionExtension { name, error } => {
|
||||||
|
ExtrinsicError::CouldNotDecodeTransactionExtension { name, error }
|
||||||
|
}
|
||||||
|
CoreExtrinsicError::LeftoverBytes { extrinsic_index, num_leftover_bytes } => {
|
||||||
|
ExtrinsicError::LeftoverBytes { extrinsic_index, num_leftover_bytes }
|
||||||
|
}
|
||||||
|
CoreExtrinsicError::ExtrinsicDecodeError { extrinsic_index, error } => {
|
||||||
|
ExtrinsicError::ExtrinsicDecodeError { extrinsic_index, error }
|
||||||
|
}
|
||||||
|
CoreExtrinsicError::CannotDecodeFields { extrinsic_index, error } => {
|
||||||
|
ExtrinsicError::CannotDecodeFields { extrinsic_index, error }
|
||||||
|
}
|
||||||
|
CoreExtrinsicError::CannotDecodeIntoRootExtrinsic { extrinsic_index, error } => {
|
||||||
|
ExtrinsicError::CannotDecodeIntoRootExtrinsic { extrinsic_index, error }
|
||||||
|
}
|
||||||
|
_ => ExtrinsicError::CannotEncodeCallData(scale_encode::Error::custom_string(e.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::{
|
|||||||
backend::{BackendExt, BlockRef},
|
backend::{BackendExt, BlockRef},
|
||||||
client::{OfflineClientT, OnlineClientT},
|
client::{OfflineClientT, OnlineClientT},
|
||||||
config::{Config, HashFor},
|
config::{Config, HashFor},
|
||||||
error::{Error, MetadataError, StorageError},
|
error::Error,
|
||||||
storage::storage_value::StorageValue,
|
storage::storage_value::StorageValue,
|
||||||
};
|
};
|
||||||
use codec::Decode;
|
use codec::Decode;
|
||||||
@@ -60,14 +60,15 @@ where
|
|||||||
T: Config,
|
T: Config,
|
||||||
Client: OfflineClientT<T>,
|
Client: OfflineClientT<T>,
|
||||||
{
|
{
|
||||||
|
/// Access a specific storage entry. This returns a [`StorageEntryClient`] which can be used to
|
||||||
|
/// interact with the storage entry at this specific block.
|
||||||
pub fn entry<Addr: Address>(&'_ self, address: Addr) -> Result<StorageEntryClient<'_, T, Client, Addr, Addr::IsPlain>, Error> {
|
pub fn entry<Addr: Address>(&'_ self, address: Addr) -> Result<StorageEntryClient<'_, T, Client, Addr, Addr::IsPlain>, Error> {
|
||||||
subxt_core::storage::validate(&address, &self.client.metadata())?;
|
subxt_core::storage::validate(&address, &self.metadata)?;
|
||||||
|
|
||||||
use frame_decode::storage::StorageTypeInfo;
|
use frame_decode::storage::StorageTypeInfo;
|
||||||
let types = self.metadata.types();
|
let types = self.metadata.types();
|
||||||
let info = self
|
let info = self
|
||||||
.client
|
.metadata
|
||||||
.metadata()
|
|
||||||
.storage_info(address.pallet_name(), address.entry_name())?;
|
.storage_info(address.pallet_name(), address.entry_name())?;
|
||||||
|
|
||||||
Ok(StorageEntryClient {
|
Ok(StorageEntryClient {
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
use super::storage_value::StorageValue;
|
use super::storage_value::StorageValue;
|
||||||
use super::storage_key::StorageKey;
|
use super::storage_key::StorageKey;
|
||||||
|
use crate::error::StorageKeyError;
|
||||||
use subxt_core::storage::address::Address;
|
use subxt_core::storage::address::Address;
|
||||||
use frame_decode::storage::StorageInfo;
|
use frame_decode::storage::{StorageInfo, IntoDecodableValues};
|
||||||
use scale_info::PortableRegistry;
|
use scale_info::PortableRegistry;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
@@ -42,7 +43,10 @@ impl<'entry, 'atblock, Addr: Address> StorageEntry<'entry, 'atblock, Addr> {
|
|||||||
|
|
||||||
/// Decode the key for this storage entry. This gives back a type from which we can
|
/// Decode the key for this storage entry. This gives back a type from which we can
|
||||||
/// decode specific parts of the key hash (where applicable).
|
/// decode specific parts of the key hash (where applicable).
|
||||||
pub fn key(&'_ self) -> Result<StorageKey<'_, 'atblock, Addr::KeyParts>, StorageKeyError> {
|
pub fn key(&'_ self) -> Result<StorageKey<'_, 'atblock, Addr::KeyParts>, StorageKeyError>
|
||||||
|
where
|
||||||
|
Addr::KeyParts: IntoDecodableValues,
|
||||||
|
{
|
||||||
StorageKey::new(self.value.info, self.value.types, &self.key)
|
StorageKey::new(self.value.info, self.value.types, &self.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
||||||
// see LICENSE for license details.
|
// see LICENSE for license details.
|
||||||
|
|
||||||
|
use crate::error::StorageKeyError;
|
||||||
use frame_decode::storage::{StorageInfo, StorageKey as StorageKeyPartInfo, IntoDecodableValues};
|
use frame_decode::storage::{StorageInfo, StorageKey as StorageKeyPartInfo, IntoDecodableValues};
|
||||||
use scale_info::PortableRegistry;
|
use scale_info::PortableRegistry;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use scale_info::PortableRegistry;
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::Error;
|
use crate::error::StorageValueError;
|
||||||
|
|
||||||
/// This represents a storage value.
|
/// This represents a storage value.
|
||||||
pub struct StorageValue<'entry, 'atblock, Value> {
|
pub struct StorageValue<'entry, 'atblock, Value> {
|
||||||
@@ -39,22 +39,24 @@ impl<'entry, 'atblock, Value: DecodeAsType> StorageValue<'entry, 'atblock, Value
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Decode this storage value into the provided response type.
|
/// Decode this storage value into the provided response type.
|
||||||
pub fn decode(&self) -> Result<Value, Error> {
|
pub fn decode(&self) -> Result<Value, StorageValueError> {
|
||||||
self.decode_as::<Value>()
|
self.decode_as::<Value>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode this storage value into an arbitrary type.
|
/// Decode this storage value into an arbitrary type.
|
||||||
pub fn decode_as<T: DecodeAsType>(&self) -> Result<T, Error> {
|
pub fn decode_as<T: DecodeAsType>(&self) -> Result<T, StorageValueError> {
|
||||||
let cursor = &mut &*self.bytes;
|
let cursor = &mut &*self.bytes;
|
||||||
|
|
||||||
let value = T::decode_as_type(
|
let value = T::decode_as_type(
|
||||||
cursor,
|
cursor,
|
||||||
self.info.value_id,
|
self.info.value_id,
|
||||||
self.types,
|
self.types,
|
||||||
).map_err(|e| todo!("Define proper errors"))?;
|
).map_err(|reason| StorageValueError::DecodeError { reason })?;
|
||||||
|
|
||||||
if !cursor.is_empty() {
|
if !cursor.is_empty() {
|
||||||
return Err(todo!("Define proper errors"));
|
return Err(StorageValueError::LeftoverBytes {
|
||||||
|
leftover_bytes: cursor.to_vec(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
|
|||||||
Reference in New Issue
Block a user