1mod dispatch_error;
8
9use subxt_core::error::{BlockError as CoreBlockError, Error as CoreError};
10
11crate::macros::cfg_unstable_light_client! {
12 pub use subxt_lightclient::LightClientError;
13}
14
15pub use dispatch_error::{
17 ArithmeticError, DispatchError, ModuleError, TokenError, TransactionalError,
18};
19
20pub use crate::metadata::Metadata;
22pub use scale_decode::Error as DecodeError;
23pub use scale_encode::Error as EncodeError;
24pub use subxt_core::error::{ExtrinsicError, MetadataError, StorageAddressError};
25pub use subxt_metadata::TryFromError as MetadataTryFromError;
26
27#[derive(Debug, thiserror::Error)]
31#[non_exhaustive]
32pub enum Error {
33 #[error("Io error: {0}")]
35 Io(#[from] std::io::Error),
36 #[error("Scale codec error: {0}")]
38 Codec(#[from] codec::Error),
39 #[error(transparent)]
41 Rpc(#[from] RpcError),
42 #[error("Serde json error: {0}")]
44 Serialization(#[from] serde_json::error::Error),
45 #[error("Metadata error: {0}")]
47 Metadata(#[from] MetadataError),
48 #[error("Metadata Decoding error: {0}")]
50 MetadataDecoding(#[from] MetadataTryFromError),
51 #[error("Runtime error: {0}")]
53 Runtime(#[from] DispatchError),
54 #[error("Error decoding into dynamic value: {0}")]
56 Decode(#[from] DecodeError),
57 #[error("Error encoding from dynamic value: {0}")]
59 Encode(#[from] EncodeError),
60 #[error("Transaction error: {0}")]
62 Transaction(#[from] TransactionError),
63 #[error("Extrinsic params error: {0}")]
65 Extrinsic(#[from] ExtrinsicError),
66 #[error("Block error: {0}")]
68 Block(#[from] BlockError),
69 #[error("Error encoding storage address: {0}")]
71 StorageAddress(#[from] StorageAddressError),
72 #[error("An error occurred but it could not be decoded: {0:?}")]
74 Unknown(Vec<u8>),
75 #[cfg(feature = "unstable-light-client")]
77 #[cfg_attr(docsrs, doc(cfg(feature = "unstable-light-client")))]
78 #[error("An error occurred but it could not be decoded: {0}")]
79 LightClient(#[from] LightClientError),
80 #[error("Other error: {0}")]
82 Other(String),
83}
84
85impl From<CoreError> for Error {
86 fn from(value: CoreError) -> Self {
87 match value {
88 CoreError::Codec(e) => Error::Codec(e),
89 CoreError::Metadata(e) => Error::Metadata(e),
90 CoreError::StorageAddress(e) => Error::StorageAddress(e),
91 CoreError::Decode(e) => Error::Decode(e),
92 CoreError::Encode(e) => Error::Encode(e),
93 CoreError::Extrinsic(e) => Error::Extrinsic(e),
94 CoreError::Block(e) => Error::Block(e.into()),
95 }
96 }
97}
98
99impl<'a> From<&'a str> for Error {
100 fn from(error: &'a str) -> Self {
101 Error::Other(error.into())
102 }
103}
104
105impl From<String> for Error {
106 fn from(error: String) -> Self {
107 Error::Other(error)
108 }
109}
110
111impl From<std::convert::Infallible> for Error {
112 fn from(value: std::convert::Infallible) -> Self {
113 match value {}
114 }
115}
116
117impl From<scale_decode::visitor::DecodeError> for Error {
118 fn from(value: scale_decode::visitor::DecodeError) -> Self {
119 Error::Decode(value.into())
120 }
121}
122
123impl From<subxt_rpcs::Error> for Error {
124 fn from(value: subxt_rpcs::Error) -> Self {
125 Error::Rpc(value.into())
126 }
127}
128
129impl Error {
130 pub fn is_disconnected_will_reconnect(&self) -> bool {
132 matches!(
133 self,
134 Error::Rpc(RpcError::ClientError(
135 subxt_rpcs::Error::DisconnectedWillReconnect(_)
136 ))
137 )
138 }
139
140 pub fn is_rpc_limit_reached(&self) -> bool {
142 matches!(self, Error::Rpc(RpcError::LimitReached))
143 }
144}
145
146#[derive(Debug, thiserror::Error)]
149#[non_exhaustive]
150pub enum RpcError {
151 #[error("RPC error: {0}")]
155 ClientError(#[from] subxt_rpcs::Error),
156 #[error("RPC error: limit reached")]
159 LimitReached,
160 #[error("RPC error: subscription dropped.")]
162 SubscriptionDropped,
163}
164
165#[derive(Clone, Debug, thiserror::Error)]
167#[non_exhaustive]
168pub enum BlockError {
169 #[error("Could not find a block with hash {0} (perhaps it was on a non-finalized fork?)")]
171 NotFound(String),
172 #[error(
174 "After decoding the exntrinsic at index {extrinsic_index}, {num_leftover_bytes} bytes were left, suggesting that decoding may have failed"
175 )]
176 LeftoverBytes {
177 extrinsic_index: usize,
179 num_leftover_bytes: usize,
181 },
182 #[error("Cannot decode extrinsic at index {extrinsic_index}: {error}")]
184 ExtrinsicDecodeError {
185 extrinsic_index: usize,
187 error: subxt_core::error::ExtrinsicDecodeError,
189 },
190}
191
192impl From<CoreBlockError> for BlockError {
193 fn from(value: CoreBlockError) -> Self {
194 match value {
195 CoreBlockError::LeftoverBytes {
196 extrinsic_index,
197 num_leftover_bytes,
198 } => BlockError::LeftoverBytes {
199 extrinsic_index,
200 num_leftover_bytes,
201 },
202 CoreBlockError::ExtrinsicDecodeError {
203 extrinsic_index,
204 error,
205 } => BlockError::ExtrinsicDecodeError {
206 extrinsic_index,
207 error,
208 },
209 }
210 }
211}
212
213impl BlockError {
214 pub fn not_found(hash: impl AsRef<[u8]>) -> BlockError {
216 let hash = format!("0x{}", hex::encode(hash));
217 BlockError::NotFound(hash)
218 }
219}
220
221#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
223#[non_exhaustive]
224pub enum TransactionError {
225 #[error(
228 "The block containing the transaction can no longer be found (perhaps it was on a non-finalized fork?)"
229 )]
230 BlockNotFound,
231 #[error("Error handling transaction: {0}")]
233 Error(String),
234 #[error("The transaction is not valid: {0}")]
236 Invalid(String),
237 #[error("The transaction was dropped: {0}")]
239 Dropped(String),
240}