mod dispatch_error;
mod hex;
use std::borrow::Cow;
use thiserror::Error as DeriveError;
#[cfg(feature = "light-client")]
pub use subxt_lightclient::LightClientError;
pub use dispatch_error::{
ArithmeticError, DispatchError, ModuleError, TokenError, TransactionalError,
};
pub use hex::Hex;
pub use scale_decode::Error as DecodeError;
pub use scale_encode::Error as EncodeError;
pub use subxt_metadata::Metadata;
pub use subxt_metadata::TryFromError as MetadataTryFromError;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
OnlineClientError(#[from] OnlineClientError),
#[error(transparent)]
OfflineClientAtBlockError(#[from] OfflineClientAtBlockError),
#[error(transparent)]
OnlineClientAtBlockError(#[from] OnlineClientAtBlockError),
#[error(transparent)]
ExtrinsicDecodeErrorAt(#[from] ExtrinsicDecodeErrorAt),
#[error(transparent)]
BlockError(#[from] BlockError),
#[error(transparent)]
ConstantError(#[from] ConstantError),
#[error(transparent)]
CustomValueError(#[from] CustomValueError),
#[error(transparent)]
StorageKeyError(#[from] StorageKeyError),
#[error(transparent)]
StorageValueError(#[from] StorageValueError),
#[error(transparent)]
BackendError(#[from] BackendError),
#[error(transparent)]
BlocksError(#[from] BlocksError),
#[error(transparent)]
AccountNonceError(#[from] AccountNonceError),
#[error(transparent)]
RuntimeApiError(#[from] RuntimeApiError),
#[error(transparent)]
EventsError(#[from] EventsError),
#[error(transparent)]
ExtrinsicError(#[from] ExtrinsicError),
#[error(transparent)]
ViewFunctionError(#[from] ViewFunctionError),
#[error(transparent)]
TransactionProgressError(#[from] TransactionProgressError),
#[error(transparent)]
TransactionStatusError(#[from] TransactionStatusError),
#[error(transparent)]
TransactionEventsError(#[from] TransactionEventsError),
#[error(transparent)]
TransactionFinalizedSuccessError(#[from] TransactionFinalizedSuccessError),
#[error(transparent)]
ModuleErrorDetailsError(#[from] ModuleErrorDetailsError),
#[error(transparent)]
ModuleErrorDecodeError(#[from] ModuleErrorDecodeError),
#[error(transparent)]
DispatchErrorDecodeError(#[from] DispatchErrorDecodeError),
#[error(transparent)]
StorageError(#[from] StorageError),
#[error(transparent)]
CombinedBackendError(#[from] CombinedBackendError),
#[error("Other RPC client error: {0}")]
OtherRpcClientError(#[from] subxt_rpcs::Error),
#[error("Other codec error: {0}")]
OtherCodecError(#[from] codec::Error),
#[cfg(feature = "light-client")]
#[error("Other light client error: {0}")]
OtherLightClientError(#[from] subxt_lightclient::LightClientError),
#[cfg(feature = "light-client")]
#[error("Other light client RPC error: {0}")]
OtherLightClientRpcError(#[from] subxt_lightclient::LightClientRpcError),
#[error("Other error: {0}")]
Other(Box<dyn std::error::Error + Send + Sync + 'static>),
}
impl From<std::convert::Infallible> for Error {
fn from(value: std::convert::Infallible) -> Self {
match value {}
}
}
impl Error {
pub fn other<E: std::error::Error + Send + Sync + 'static>(error: E) -> Error {
Error::Other(Box::new(error))
}
pub fn other_str(error: impl Into<String>) -> Error {
#[derive(thiserror::Error, Debug, Clone)]
#[error("{0}")]
struct StrError(String);
Error::Other(Box::new(StrError(error.into())))
}
pub fn is_disconnected_will_reconnect(&self) -> bool {
matches!(
self.backend_error(),
Some(BackendError::Rpc(RpcError::ClientError(
subxt_rpcs::Error::DisconnectedWillReconnect(_)
)))
)
}
pub fn is_rpc_limit_reached(&self) -> bool {
matches!(
self.backend_error(),
Some(BackendError::Rpc(RpcError::LimitReached))
)
}
fn backend_error(&self) -> Option<&BackendError> {
match self {
Error::BlocksError(e) => e.backend_error(),
Error::AccountNonceError(e) => e.backend_error(),
Error::OnlineClientError(e) => e.backend_error(),
Error::RuntimeApiError(e) => e.backend_error(),
Error::EventsError(e) => e.backend_error(),
Error::BlockError(e) => e.backend_error(),
Error::ExtrinsicError(e) => e.backend_error(),
Error::ViewFunctionError(e) => e.backend_error(),
Error::TransactionProgressError(e) => e.backend_error(),
Error::TransactionEventsError(e) => e.backend_error(),
Error::TransactionFinalizedSuccessError(e) => e.backend_error(),
Error::StorageError(e) => e.backend_error(),
Error::OfflineClientAtBlockError(e) => e.backend_error(),
Error::OnlineClientAtBlockError(e) => e.backend_error(),
Error::ExtrinsicDecodeErrorAt(e) => e.backend_error(),
Error::ConstantError(e) => e.backend_error(),
Error::CustomValueError(e) => e.backend_error(),
Error::StorageKeyError(e) => e.backend_error(),
Error::StorageValueError(e) => e.backend_error(),
Error::TransactionStatusError(e) => e.backend_error(),
Error::ModuleErrorDetailsError(e) => e.backend_error(),
Error::ModuleErrorDecodeError(e) => e.backend_error(),
Error::DispatchErrorDecodeError(e) => e.backend_error(),
Error::CombinedBackendError(e) => e.backend_error(),
#[cfg(feature = "light-client")]
Error::OtherLightClientError(_) => None,
#[cfg(feature = "light-client")]
Error::OtherLightClientRpcError(_) => None,
Error::BackendError(e) => Some(e),
Error::OtherRpcClientError(_) => None,
Error::OtherCodecError(_) => None,
Error::Other(_) => None,
}
}
}
#[allow(missing_docs)]
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum OfflineClientAtBlockError {
#[error(
"Cannot construct OfflineClientAtBlock: spec version not found for block number {block_number}"
)]
SpecVersionNotFound {
block_number: u64,
},
#[error(
"Cannot construct OfflineClientAtBlock: metadata not found for spec version {spec_version}"
)]
MetadataNotFound {
spec_version: u32,
},
}
impl OfflineClientAtBlockError {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum OnlineClientError {
#[error("Cannot construct OnlineClient: {0}")]
RpcError(#[from] subxt_rpcs::Error),
#[error("Could not construct the CombinedBackend: {0}")]
CannotBuildCombinedBackend(CombinedBackendError),
#[error("Cannot construct OnlineClient: Cannot fetch genesis hash: {0}")]
CannotGetGenesisHash(BackendError),
}
impl OnlineClientError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
OnlineClientError::CannotGetGenesisHash(e) => Some(e),
_ => None,
}
}
}
#[allow(missing_docs)]
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum BlocksError {
#[error("Cannot construct block stream: cannot get the current block: {0}")]
CannotGetCurrentBlock(OnlineClientAtBlockError),
#[error("Cannot construct block stream: cannot get block header stream: {0}")]
CannotGetBlockHeaderStream(BackendError),
#[error("Error streaming blocks: cannot get the next block header: {0}")]
CannotGetBlockHeader(BackendError),
}
impl BlocksError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
BlocksError::CannotGetCurrentBlock(e) => e.backend_error(),
BlocksError::CannotGetBlockHeaderStream(e) => Some(e),
BlocksError::CannotGetBlockHeader(e) => Some(e),
}
}
}
#[allow(missing_docs)]
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum OnlineClientAtBlockError {
#[error("Cannot construct OnlineClientAtBlock: cannot get the current block: {reason}")]
CannotGetCurrentBlock {
reason: BackendError,
},
#[error(
"Cannot construct OnlineClientAtBlock: failed to get block hash from node for block {block_number}: {reason}"
)]
CannotGetBlockHash {
block_number: u64,
reason: BackendError,
},
#[error("Cannot construct OnlineClientAtBlock: block number {block_number} not found")]
BlockNotFound {
block_number: u64,
},
#[error(
"Cannot construct OnlineClientAtBlock: cannot get the block header for block {block_hash}: {reason}"
)]
CannotGetBlockHeader {
block_hash: Hex,
reason: BackendError,
},
#[error(
"Cannot construct OnlineClientAtBlock: cannot find the block header for block {block_hash}"
)]
BlockHeaderNotFound {
block_hash: Hex,
},
#[error(
"Cannot construct OnlineClientAtBlock: failed to obtain spec version for block {block_hash}: {reason}"
)]
CannotGetSpecVersion {
block_hash: Hex,
reason: BackendError,
},
#[error(
"Cannot construct OnlineClientAtBlock: failed to decode spec version for block {block_hash}: {reason}"
)]
CannotDecodeSpecVersion {
block_hash: Hex,
reason: codec::Error,
},
#[error(
"Cannot construct OnlineClientAtBlock: failed to get metadata for block {block_hash}: {reason}"
)]
CannotGetMetadata {
block_hash: Hex,
reason: String,
},
#[error(
"Cannot construct OnlineClientAtBlock: Metadata V{version} (required at block {block_hash} is not supported."
)]
UnsupportedMetadataVersion {
block_hash: Hex,
version: u32,
},
#[error(
"Cannot construct OnlineClientAtBlock: No legacy types were provided but we're trying to access a block that requires them."
)]
MissingLegacyTypes,
#[error(
"Cannot construct OnlineClientAtBlock: unable to convert legacy metadata (required at block {block_hash}): {reason}"
)]
CannotConvertLegacyMetadata {
block_hash: Hex,
metadata_version: u32,
reason: subxt_metadata::LegacyFromError,
},
#[error(
"Cannot construct OnlineClientAtBlock: unable to convert modern metadata (required at block {block_hash}): {reason}"
)]
CannotConvertModernMetadata {
block_hash: Hex,
metadata_version: u32,
reason: subxt_metadata::TryFromError,
},
#[error(
"Cannot construct OnlineClientAtBlock: cannot inject types from metadata: failure to parse a type found in the metadata: {parse_error}"
)]
CannotInjectMetadataTypes {
parse_error: scale_info_legacy::lookup_name::ParseError,
},
}
impl OnlineClientAtBlockError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
OnlineClientAtBlockError::CannotGetCurrentBlock { reason }
| OnlineClientAtBlockError::CannotGetBlockHash { reason, .. }
| OnlineClientAtBlockError::CannotGetBlockHeader { reason, .. }
| OnlineClientAtBlockError::CannotGetSpecVersion { reason, .. } => Some(reason),
_ => None,
}
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum BlockError {
#[error("Could not find the block with hash {block_hash}")]
BlockNotFound { block_hash: Hex },
#[error("Could not download the block header with hash {block_hash}: {reason}")]
CouldNotDownloadBlockHeader {
block_hash: Hex,
reason: BackendError,
},
}
impl BlockError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
BlockError::CouldNotDownloadBlockHeader { reason, .. } => Some(reason),
_ => None,
}
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum BackendError {
#[error("Backend error: RPC error: {0}")]
Rpc(#[from] RpcError),
#[error("Custom backend error: {0}")]
Other(Cow<'static, str>),
}
impl BackendError {
pub fn is_disconnected_will_reconnect(&self) -> bool {
matches!(
self,
BackendError::Rpc(RpcError::ClientError(
subxt_rpcs::Error::DisconnectedWillReconnect(_)
))
)
}
pub fn is_rpc_limit_reached(&self) -> bool {
matches!(self, BackendError::Rpc(RpcError::LimitReached))
}
pub fn other(message: impl Into<Cow<'static, str>>) -> Self {
BackendError::Other(message.into())
}
}
impl From<subxt_rpcs::Error> for BackendError {
fn from(value: subxt_rpcs::Error) -> Self {
BackendError::Rpc(RpcError::ClientError(value))
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum CombinedBackendError {
#[error("Could not obtain the list of RPC methods to determine which backends can be used")]
CouldNotObtainRpcMethodList(subxt_rpcs::Error),
}
impl CombinedBackendError {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum RpcError {
#[error("RPC error: {0}")]
ClientError(#[from] subxt_rpcs::Error),
#[error("RPC error: limit reached")]
LimitReached,
#[error("RPC error: subscription dropped.")]
SubscriptionDropped,
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum AccountNonceError {
#[error("Could not retrieve account nonce: {0}")]
CouldNotRetrieve(BackendError),
#[error("Could not decode account nonce: {0}")]
CouldNotDecode(codec::Error),
#[error("Wrong number of account nonce bytes returned: {0} (expected 2, 4 or 8)")]
WrongNumberOfBytes(usize),
}
impl AccountNonceError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
AccountNonceError::CouldNotRetrieve(e) => Some(e),
_ => None,
}
}
}
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum RuntimeApiError {
#[error("The static Runtime API address used is not compatible with the live chain")]
IncompatibleCodegen,
#[error("Runtime API trait not found: {0}")]
TraitNotFound(String),
#[error("Runtime API method {method_name} not found in trait {trait_name}")]
MethodNotFound {
trait_name: String,
method_name: String,
},
#[error("Failed to encode Runtime API inputs: {0}")]
CouldNotEncodeInputs(frame_decode::runtime_apis::RuntimeApiInputsEncodeError),
#[error("Failed to decode Runtime API: {0}")]
CouldNotDecodeResponse(frame_decode::runtime_apis::RuntimeApiDecodeError<u32>),
#[error("Cannot call the Runtime API: {0}")]
CannotCallApi(BackendError),
}
impl RuntimeApiError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
RuntimeApiError::CannotCallApi(e) => Some(e),
_ => None,
}
}
}
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum EventsError {
#[error("Can't decode event: can't decode phase: {0}")]
CannotDecodePhase(codec::Error),
#[error("Can't decode event: can't decode pallet index: {0}")]
CannotDecodePalletIndex(codec::Error),
#[error("Can't decode event: can't decode variant index: {0}")]
CannotDecodeVariantIndex(codec::Error),
#[error("Can't decode event: can't find pallet with index {0}")]
CannotFindPalletWithIndex(u8),
#[error(
"Can't decode event: can't find variant with index {variant_index} in pallet {pallet_name}"
)]
CannotFindVariantWithIndex {
pallet_name: String,
variant_index: u8,
},
#[error("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("Can't decode event topics: {0}")]
CannotDecodeEventTopics(codec::Error),
#[error("Can't decode the fields of event {pallet_name}.{event_name}: {reason}")]
CannotDecodeEventFields {
pallet_name: String,
event_name: String,
reason: scale_decode::Error,
},
#[error("Can't decode event {pallet_name}.{event_name} to Event enum: {reason}")]
CannotDecodeEventEnum {
pallet_name: String,
event_name: String,
reason: scale_decode::Error,
},
#[error("Cannot fetch event bytes: {0}")]
CannotFetchEventBytes(BackendError),
}
impl EventsError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
EventsError::CannotFetchEventBytes(e) => Some(e),
_ => None,
}
}
}
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum ExtrinsicError {
#[error("Failed to construct extrinsic: {0}")]
EncodeError(#[from] frame_decode::extrinsics::ExtrinsicEncodeError),
#[error("The extrinsic payload is not compatible with the live chain")]
IncompatibleCodegen,
#[error("Can't find extrinsic: pallet with name {0} not found")]
PalletNameNotFound(String),
#[error("Can't find extrinsic: call name {call_name} doesn't exist in pallet {pallet_name}")]
CallNameNotFound {
pallet_name: String,
call_name: String,
},
#[error("Failed to encode an extrinsic: the genesis hash was not provided")]
GenesisHashNotProvided,
#[error("Subxt does not support the extrinsic versions expected by the chain")]
UnsupportedVersion,
#[error("Cannot construct the required transaction extensions: {0}")]
Params(#[from] TransactionExtensionError),
#[error("Cannot decode transaction extension '{name}': {error}")]
CouldNotDecodeTransactionExtension {
name: String,
error: scale_decode::Error,
},
#[error("Failed to decode the fields of an extrinsic at index {extrinsic_index}: {error}")]
CannotDecodeFields {
extrinsic_index: usize,
error: scale_decode::Error,
},
#[error("Failed to decode the extrinsic at index {extrinsic_index} to a root enum: {error}")]
CannotDecodeIntoRootExtrinsic {
extrinsic_index: usize,
error: scale_decode::Error,
},
#[error("Could not download block body to extract extrinsics from: {0}")]
CannotGetBlockBody(BackendError),
#[error("Block not found: {0}")]
BlockNotFound(Hex),
#[error("Error getting account nonce at block {block_hash}")]
AccountNonceError {
block_hash: Hex,
account_id: Hex,
reason: AccountNonceError,
},
#[error("Cannot submit extrinsic: {0}")]
ErrorSubmittingTransaction(BackendError),
#[error("A transaction status error was returned while submitting the extrinsic: {0}")]
TransactionStatusError(TransactionStatusError),
#[error(
"The transaction status stream encountered an error while submitting the extrinsic: {0}"
)]
TransactionStatusStreamError(BackendError),
#[error(
"The transaction status stream unexpectedly ended, so we don't know the status of the submitted extrinsic"
)]
UnexpectedEndOfTransactionStatusStream,
#[error("Cannot get fee info from Runtime API: {0}")]
CannotGetFeeInfo(BackendError),
#[error("Cannot decode fee info from Runtime API: {0}")]
CannotDecodeFeeInfo(codec::Error),
#[error("Cannot get validation info from Runtime API: {0}")]
CannotGetValidationInfo(BackendError),
#[error("Cannot decode ValidationResult bytes: {0}")]
CannotDecodeValidationResult(codec::Error),
#[error("ValidationResult bytes could not be decoded")]
UnexpectedValidationResultBytes(Vec<u8>),
}
impl ExtrinsicError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
ExtrinsicError::CannotGetBlockBody(e)
| ExtrinsicError::ErrorSubmittingTransaction(e)
| ExtrinsicError::TransactionStatusStreamError(e)
| ExtrinsicError::CannotGetFeeInfo(e)
| ExtrinsicError::CannotGetValidationInfo(e) => Some(e),
ExtrinsicError::AccountNonceError { reason, .. } => reason.backend_error(),
_ => None,
}
}
}
#[derive(Debug, DeriveError)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum CustomValueError {
#[error("The static custom value address used is not compatible with the live chain")]
IncompatibleCodegen,
#[error("The custom value '{0}' was not found")]
NotFound(String),
#[error("Failed to decode custom value: {0}")]
CouldNotDecodeCustomValue(frame_decode::custom_values::CustomValueDecodeError<u32>),
}
impl CustomValueError {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum ViewFunctionError {
#[error("The static View Function address used is not compatible with the live chain")]
IncompatibleCodegen,
#[error("Can't find View Function: pallet {0} not found")]
PalletNotFound(String),
#[error("Can't find View Function {function_name} in pallet {pallet_name}")]
ViewFunctionNotFound {
pallet_name: String,
function_name: String,
},
#[error("Failed to encode View Function inputs: {0}")]
CouldNotEncodeInputs(frame_decode::view_functions::ViewFunctionInputsEncodeError),
#[error("Failed to decode View Function: {0}")]
CouldNotDecodeResponse(frame_decode::view_functions::ViewFunctionDecodeError<u32>),
#[error("Cannot call the View Function Runtime API: {0}")]
CannotCallApi(BackendError),
}
impl ViewFunctionError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
ViewFunctionError::CannotCallApi(e) => Some(e),
_ => None,
}
}
}
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum TransactionProgressError {
#[error("Cannot get the next transaction progress update: {0}")]
CannotGetNextProgressUpdate(BackendError),
#[error("Error during transaction progress: {0}")]
TransactionStatusError(#[from] TransactionStatusError),
#[error(
"The transaction status stream unexpectedly ended, so we have no further transaction progress updates"
)]
UnexpectedEndOfTransactionStatusStream,
}
impl TransactionProgressError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
TransactionProgressError::CannotGetNextProgressUpdate(e) => Some(e),
TransactionProgressError::TransactionStatusError(_) => None,
TransactionProgressError::UnexpectedEndOfTransactionStatusStream => None,
}
}
}
#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum TransactionStatusError {
#[error("Error handling transaction: {0}")]
Error(String),
#[error("The transaction is not valid: {0}")]
Invalid(String),
#[error("The transaction was dropped: {0}")]
Dropped(String),
}
impl TransactionStatusError {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum TransactionEventsError {
#[error(
"The block containing the submitted transaction ({block_hash}) could not be downloaded: {error}"
)]
CannotFetchBlockBody {
block_hash: Hex,
error: BackendError,
},
#[error(
"Cannot find the the submitted transaction (hash: {transaction_hash}) in the block (hash: {block_hash}) it is supposed to be in."
)]
CannotFindTransactionInBlock {
block_hash: Hex,
transaction_hash: Hex,
},
#[error("The block containing the submitted transaction ({block_hash}) could not be found")]
BlockNotFound { block_hash: Hex },
#[error(
"Could not decode event at index {event_index} for the submitted transaction at block {block_hash}: {error}"
)]
CannotDecodeEventInBlock {
event_index: usize,
block_hash: Hex,
error: EventsError,
},
#[error("Could not instantiate a client at the required block to fetch events: {0}")]
CannotInstantiateClientAtBlock(OnlineClientAtBlockError),
#[error("Could not fetch events for the submitted transaction: {error}")]
CannotFetchEventsForTransaction {
block_hash: Hex,
transaction_hash: Hex,
error: EventsError,
},
#[error("The transaction led to a DispatchError, but we failed to decode it: {error}")]
CannotDecodeDispatchError {
error: DispatchErrorDecodeError,
bytes: Vec<u8>,
},
#[error("The transaction failed with the following dispatch error: {0}")]
ExtrinsicFailed(#[from] DispatchError),
}
impl TransactionEventsError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
TransactionEventsError::CannotFetchBlockBody { error, .. } => Some(error),
TransactionEventsError::CannotDecodeEventInBlock { error, .. }
| TransactionEventsError::CannotFetchEventsForTransaction { error, .. } => {
error.backend_error()
}
_ => None,
}
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs, clippy::large_enum_variant)]
pub enum TransactionFinalizedSuccessError {
#[error("Could not finalize the transaction: {0}")]
FinalizationError(#[from] TransactionProgressError),
#[error("The transaction did not succeed: {0}")]
SuccessError(#[from] TransactionEventsError),
}
impl TransactionFinalizedSuccessError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
TransactionFinalizedSuccessError::FinalizationError(e) => e.backend_error(),
TransactionFinalizedSuccessError::SuccessError(e) => e.backend_error(),
}
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum ModuleErrorDetailsError {
#[error(
"Could not get details for the DispatchError: could not find pallet index {pallet_index}"
)]
PalletNotFound { pallet_index: u8 },
#[error(
"Could not get details for the DispatchError: could not find error index {error_index} in pallet {pallet_name}"
)]
ErrorVariantNotFound {
pallet_name: String,
error_index: u8,
},
}
impl ModuleErrorDetailsError {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
#[error("Could not decode the DispatchError::Module payload into the given type: {0}")]
pub struct ModuleErrorDecodeError(scale_decode::Error);
impl ModuleErrorDecodeError {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum DispatchErrorDecodeError {
#[error(
"Could not decode the DispatchError: could not find the corresponding type ID in the metadata"
)]
DispatchErrorTypeIdNotFound,
#[error("Could not decode the DispatchError: {0}")]
CouldNotDecodeDispatchError(scale_decode::Error),
#[error("Could not decode the DispatchError::Module variant")]
CouldNotDecodeModuleError {
bytes: Vec<u8>,
},
}
impl DispatchErrorDecodeError {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum StorageError {
#[error("The static storage address used is not compatible with the live chain")]
IncompatibleCodegen,
#[error("Can't find storage value: pallet with name {0} not found")]
PalletNameNotFound(String),
#[error(
"Storage entry '{entry_name}' not found in pallet {pallet_name} in the live chain metadata"
)]
StorageEntryNotFound {
pallet_name: String,
entry_name: String,
},
#[error("Cannot obtain storage information from metadata: {0}")]
StorageInfoError(frame_decode::storage::StorageInfoError<'static>),
#[error("Cannot encode storage key: {0}")]
StorageKeyEncodeError(frame_decode::storage::StorageKeyEncodeError),
#[error("Cannot create a key to iterate over a plain entry")]
CannotIterPlainEntry {
pallet_name: String,
entry_name: String,
},
#[error(
"Wrong number of key parts provided to iterate a storage address. We expected at most {max_expected} key parts but got {got} key parts"
)]
WrongNumberOfKeyPartsProvidedForIterating { max_expected: usize, got: usize },
#[error(
"Wrong number of key parts provided to fetch a storage address. We expected {expected} key parts but got {got} key parts"
)]
WrongNumberOfKeyPartsProvidedForFetching { expected: usize, got: usize },
#[error(
"No storage value found at the given address, and no default value to fall back to using."
)]
NoValueFound,
#[error("Cannot fetch the storage value: {0}")]
CannotFetchValue(BackendError),
#[error("Cannot iterate storage values: {0}")]
CannotIterateValues(BackendError),
#[error("Encountered an error iterating over storage values: {0}")]
StreamFailure(BackendError),
#[error("Cannot decode the storage version for a given entry: {0}")]
CannotDecodeStorageVersion(codec::Error),
}
impl StorageError {
fn backend_error(&self) -> Option<&BackendError> {
match self {
StorageError::CannotFetchValue(e)
| StorageError::CannotIterateValues(e)
| StorageError::StreamFailure(e) => Some(e),
_ => None,
}
}
}
#[derive(Debug, DeriveError)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum ConstantError {
#[error("The static constant address used is not compatible with the live chain")]
IncompatibleCodegen,
#[error("Can't find constant: pallet with name {0} not found")]
PalletNameNotFound(String),
#[error(
"Constant '{constant_name}' not found in pallet {pallet_name} in the live chain metadata"
)]
ConstantNameNotFound {
pallet_name: String,
constant_name: String,
},
#[error("Failed to decode constant: {0}")]
CouldNotDecodeConstant(frame_decode::constants::ConstantDecodeError<u32>),
#[error("Cannot obtain constant information from metadata: {0}")]
ConstantInfoError(frame_decode::constants::ConstantInfoError<'static>),
}
impl ConstantError {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[derive(Debug, DeriveError)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum StorageKeyError {
#[error("Can't decode the storage key: {error}")]
StorageKeyDecodeError {
bytes: Vec<u8>,
error: frame_decode::storage::StorageKeyDecodeError<u32>,
},
#[error("Can't decode the values from the storage key: {0}")]
CannotDecodeValuesInKey(frame_decode::storage::StorageKeyValueDecodeError),
#[error(
"Cannot decode storage key: there were leftover bytes, indicating that the decoding failed"
)]
LeftoverBytes { bytes: Vec<u8> },
#[error("Can't decode a single value from the storage key part at index {index}: {error}")]
CannotDecodeValueInKey {
index: usize,
error: scale_decode::Error,
},
}
impl StorageKeyError {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[derive(Debug, DeriveError)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum StorageValueError {
#[error("Cannot decode storage value: {0}")]
CannotDecode(frame_decode::storage::StorageValueDecodeError<u32>),
#[error(
"Cannot decode storage value: there were leftover bytes, indicating that the decoding failed"
)]
LeftoverBytes { bytes: Vec<u8> },
}
impl StorageValueError {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
#[error("Cannot decode extrinsic at index {extrinsic_index}: {error}")]
pub struct ExtrinsicDecodeErrorAt {
pub extrinsic_index: usize,
pub error: ExtrinsicDecodeErrorAtReason,
}
impl ExtrinsicDecodeErrorAt {
fn backend_error(&self) -> Option<&BackendError> {
None
}
}
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum ExtrinsicDecodeErrorAtReason {
#[error("{0}")]
DecodeError(frame_decode::extrinsics::ExtrinsicDecodeError),
#[error("Leftover bytes")]
LeftoverBytes(Vec<u8>),
}
#[derive(Debug, DeriveError)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum TransactionExtensionError {
#[error("Error constructing extrinsic parameters: {0}")]
Custom(Box<dyn core::error::Error + Send + Sync + 'static>),
}
impl TransactionExtensionError {
pub fn custom<S: Into<String>>(error: S) -> Self {
let error: String = error.into();
let error: Box<dyn core::error::Error + Send + Sync + 'static> = Box::from(error);
TransactionExtensionError::Custom(error)
}
}
impl From<core::convert::Infallible> for TransactionExtensionError {
fn from(value: core::convert::Infallible) -> Self {
match value {}
}
}