gear_subxt/error/
mod.rs

1// Copyright 2019-2023 Parity Technologies (UK) Ltd.
2// This file is dual-licensed as Apache-2.0 or GPL-3.0.
3// see LICENSE for license details.
4
5//! Types representing the errors that can be returned.
6
7mod dispatch_error;
8
9use core::fmt::Debug;
10
11// Re-export dispatch error types:
12pub use dispatch_error::{
13    ArithmeticError, DispatchError, ModuleError, RawModuleError, TokenError, TransactionalError,
14};
15
16// Re-expose the errors we use from other crates here:
17pub use crate::metadata::Metadata;
18pub use scale_decode::Error as DecodeError;
19pub use scale_encode::Error as EncodeError;
20pub use subxt_metadata::TryFromError as MetadataTryFromError;
21
22/// The underlying error enum, generic over the type held by the `Runtime`
23/// variant. Prefer to use the [`Error<E>`] and [`Error`] aliases over
24/// using this type directly.
25#[derive(Debug, thiserror::Error)]
26#[non_exhaustive]
27pub enum Error {
28    /// Io error.
29    #[error("Io error: {0}")]
30    Io(#[from] std::io::Error),
31    /// Codec error.
32    #[error("Scale codec error: {0}")]
33    Codec(#[from] codec::Error),
34    /// Rpc error.
35    #[error("Rpc error: {0}")]
36    Rpc(#[from] RpcError),
37    /// Serde serialization error
38    #[error("Serde json error: {0}")]
39    Serialization(#[from] serde_json::error::Error),
40    /// Error working with metadata.
41    #[error("Metadata: {0}")]
42    Metadata(#[from] MetadataError),
43    /// Error decoding metadata.
44    #[error("Metadata: {0}")]
45    MetadataDecoding(#[from] MetadataTryFromError),
46    /// Runtime error.
47    #[error("Runtime error: {0:?}")]
48    Runtime(#[from] DispatchError),
49    /// Error decoding to a [`crate::dynamic::Value`].
50    #[error("Error decoding into dynamic value: {0}")]
51    Decode(#[from] DecodeError),
52    /// Error encoding from a [`crate::dynamic::Value`].
53    #[error("Error encoding from dynamic value: {0}")]
54    Encode(#[from] EncodeError),
55    /// Transaction progress error.
56    #[error("Transaction error: {0}")]
57    Transaction(#[from] TransactionError),
58    /// Block related error.
59    #[error("Block error: {0}")]
60    Block(#[from] BlockError),
61    /// An error encoding a storage address.
62    #[error("Error encoding storage address: {0}")]
63    StorageAddress(#[from] StorageAddressError),
64    /// The bytes representing an error that we were unable to decode.
65    #[error("An error occurred but it could not be decoded: {0:?}")]
66    Unknown(Vec<u8>),
67    /// Other error.
68    #[error("Other error: {0}")]
69    Other(String),
70}
71
72impl<'a> From<&'a str> for Error {
73    fn from(error: &'a str) -> Self {
74        Error::Other(error.into())
75    }
76}
77
78impl From<String> for Error {
79    fn from(error: String) -> Self {
80        Error::Other(error)
81    }
82}
83
84/// An RPC error. Since we are generic over the RPC client that is used,
85/// the error is boxed and could be casted.
86#[derive(Debug, thiserror::Error)]
87#[non_exhaustive]
88pub enum RpcError {
89    // Dev note: We need the error to be safely sent between threads
90    // for `subscribe_to_block_headers_filling_in_gaps` and friends.
91    /// Error related to the RPC client.
92    #[error("RPC error: {0}")]
93    ClientError(Box<dyn std::error::Error + Send + Sync + 'static>),
94    /// The RPC subscription dropped.
95    #[error("RPC error: subscription dropped.")]
96    SubscriptionDropped,
97}
98
99/// Block error
100#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
101#[non_exhaustive]
102pub enum BlockError {
103    /// An error containing the hash of the block that was not found.
104    #[error("Could not find a block with hash {0} (perhaps it was on a non-finalized fork?)")]
105    NotFound(String),
106    /// Extrinsic type ID cannot be resolved with the provided metadata.
107    #[error("Extrinsic type ID cannot be resolved with the provided metadata. Make sure this is a valid metadata")]
108    MissingType,
109    /// Unsupported signature.
110    #[error("Unsupported extrinsic version, only version 4 is supported currently")]
111    /// The extrinsic has an unsupported version.
112    UnsupportedVersion(u8),
113    /// Decoding error.
114    #[error("Cannot decode extrinsic: {0}")]
115    DecodingError(codec::Error),
116}
117
118impl BlockError {
119    /// Produce an error that a block with the given hash cannot be found.
120    pub fn not_found(hash: impl AsRef<[u8]>) -> BlockError {
121        let hash = format!("0x{}", hex::encode(hash));
122        BlockError::NotFound(hash)
123    }
124}
125
126/// Transaction error.
127#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
128#[non_exhaustive]
129pub enum TransactionError {
130    /// The finality subscription expired (after ~512 blocks we give up if the
131    /// block hasn't yet been finalized).
132    #[error("The finality subscription expired")]
133    FinalityTimeout,
134    /// The block hash that the transaction was added to could not be found.
135    /// This is probably because the block was retracted before being finalized.
136    #[error("The block containing the transaction can no longer be found (perhaps it was on a non-finalized fork?)")]
137    BlockNotFound,
138    /// The transaction was deemed invalid in the current chain state.
139    #[error("The transaction is no longer valid")]
140    Invalid,
141    /// The transaction was replaced by a transaction with the same (sender, nonce) pair but with higher priority
142    #[error("The transaction was replaced by a transaction with the same (sender, nonce) pair but with higher priority.")]
143    Usurped,
144    /// The transaction was dropped because of some limit
145    #[error("The transaction was dropped from the pool because of a limit.")]
146    Dropped,
147}
148
149/// Something went wrong trying to encode a storage address.
150#[derive(Clone, Debug, thiserror::Error)]
151#[non_exhaustive]
152pub enum StorageAddressError {
153    /// Storage map type must be a composite type.
154    #[error("Storage map type must be a composite type")]
155    MapTypeMustBeTuple,
156    /// Storage lookup does not have the expected number of keys.
157    #[error("Storage lookup requires {expected} keys but got {actual} keys")]
158    WrongNumberOfKeys {
159        /// The actual number of keys needed, based on the metadata.
160        actual: usize,
161        /// The number of keys provided in the storage address.
162        expected: usize,
163    },
164    /// This storage entry in the metadata does not have the correct number of hashers to fields.
165    #[error("Storage entry in metadata does not have the correct number of hashers to fields")]
166    WrongNumberOfHashers {
167        /// The number of hashers in the metadata for this storage entry.
168        hashers: usize,
169        /// The number of fields in the metadata for this storage entry.
170        fields: usize,
171    },
172}
173
174/// Something went wrong trying to access details in the metadata.
175#[derive(Clone, Debug, PartialEq, thiserror::Error)]
176#[non_exhaustive]
177pub enum MetadataError {
178    /// The DispatchError type isn't available in the metadata
179    #[error("The DispatchError type isn't available")]
180    DispatchErrorNotFound,
181    /// Type not found in metadata.
182    #[error("Type with ID {0} not found")]
183    TypeNotFound(u32),
184    /// Pallet not found (index).
185    #[error("Pallet with index {0} not found")]
186    PalletIndexNotFound(u8),
187    /// Pallet not found (name).
188    #[error("Pallet with name {0} not found")]
189    PalletNameNotFound(String),
190    /// Variant not found.
191    #[error("Variant with index {0} not found")]
192    VariantIndexNotFound(u8),
193    /// Constant not found.
194    #[error("Constant with name {0} not found")]
195    ConstantNameNotFound(String),
196    /// Call not found.
197    #[error("Call with name {0} not found")]
198    CallNameNotFound(String),
199    /// Runtime trait not found.
200    #[error("Runtime trait with name {0} not found")]
201    RuntimeTraitNotFound(String),
202    /// Runtime method not found.
203    #[error("Runtime method with name {0} not found")]
204    RuntimeMethodNotFound(String),
205    /// Call type not found in metadata.
206    #[error("Call type not found in pallet with index {0}")]
207    CallTypeNotFoundInPallet(u8),
208    /// Event type not found in metadata.
209    #[error("Event type not found in pallet with index {0}")]
210    EventTypeNotFoundInPallet(u8),
211    /// Storage details not found in metadata.
212    #[error("Storage details not found in pallet with name {0}")]
213    StorageNotFoundInPallet(String),
214    /// Storage entry not found.
215    #[error("Storage entry {0} not found")]
216    StorageEntryNotFound(String),
217    /// The generated interface used is not compatible with the node.
218    #[error("The generated code is not compatible with the node")]
219    IncompatibleCodegen,
220}
221
222/// This trait is implemented on the statically generated root ModuleError type
223#[doc(hidden)]
224pub trait RootError: Sized {
225    /// Given details of the pallet error we want to decode
226    fn root_error(
227        // typically a [u8; 4] encodes the error of a pallet
228        pallet_bytes: &[u8],
229        pallet_name: &str,
230        metadata: &Metadata,
231    ) -> Result<Self, Error>;
232}