1mod dispatch_error;
8mod hex;
9
10use std::borrow::Cow;
11use thiserror::Error as DeriveError;
12
13#[cfg(feature = "light-client")]
14pub use subxt_lightclient::LightClientError;
15
16pub use dispatch_error::{
18 ArithmeticError, DispatchError, ModuleError, TokenError, TransactionalError,
19};
20
21pub use hex::Hex;
23pub use scale_decode::Error as DecodeError;
24pub use scale_encode::Error as EncodeError;
25pub use subxt_metadata::Metadata;
26pub use subxt_metadata::TryFromError as MetadataTryFromError;
27
28#[derive(Debug, thiserror::Error)]
31#[non_exhaustive]
32#[allow(missing_docs)]
33pub enum Error {
34 #[error(transparent)]
35 OnlineClientError(#[from] OnlineClientError),
36 #[error(transparent)]
37 OfflineClientAtBlockError(#[from] OfflineClientAtBlockError),
38 #[error(transparent)]
39 OnlineClientAtBlockError(#[from] OnlineClientAtBlockError),
40 #[error(transparent)]
41 ExtrinsicDecodeErrorAt(#[from] ExtrinsicDecodeErrorAt),
42 #[error(transparent)]
43 BlockError(#[from] BlockError),
44 #[error(transparent)]
45 ConstantError(#[from] ConstantError),
46 #[error(transparent)]
47 CustomValueError(#[from] CustomValueError),
48 #[error(transparent)]
49 StorageKeyError(#[from] StorageKeyError),
50 #[error(transparent)]
51 StorageValueError(#[from] StorageValueError),
52 #[error(transparent)]
53 BackendError(#[from] BackendError),
54 #[error(transparent)]
55 BlocksError(#[from] BlocksError),
56 #[error(transparent)]
57 AccountNonceError(#[from] AccountNonceError),
58 #[error(transparent)]
59 RuntimeApiError(#[from] RuntimeApiError),
60 #[error(transparent)]
61 EventsError(#[from] EventsError),
62 #[error(transparent)]
63 ExtrinsicError(#[from] ExtrinsicError),
64 #[error(transparent)]
65 ViewFunctionError(#[from] ViewFunctionError),
66 #[error(transparent)]
67 TransactionProgressError(#[from] TransactionProgressError),
68 #[error(transparent)]
69 TransactionStatusError(#[from] TransactionStatusError),
70 #[error(transparent)]
71 TransactionEventsError(#[from] TransactionEventsError),
72 #[error(transparent)]
73 TransactionFinalizedSuccessError(#[from] TransactionFinalizedSuccessError),
74 #[error(transparent)]
75 ModuleErrorDetailsError(#[from] ModuleErrorDetailsError),
76 #[error(transparent)]
77 ModuleErrorDecodeError(#[from] ModuleErrorDecodeError),
78 #[error(transparent)]
79 DispatchErrorDecodeError(#[from] DispatchErrorDecodeError),
80 #[error(transparent)]
81 StorageError(#[from] StorageError),
82 #[error(transparent)]
83 CombinedBackendError(#[from] CombinedBackendError),
84 #[error("Other RPC client error: {0}")]
88 OtherRpcClientError(#[from] subxt_rpcs::Error),
89 #[error("Other codec error: {0}")]
90 OtherCodecError(#[from] codec::Error),
91 #[cfg(feature = "light-client")]
92 #[error("Other light client error: {0}")]
93 OtherLightClientError(#[from] subxt_lightclient::LightClientError),
94 #[cfg(feature = "light-client")]
95 #[error("Other light client RPC error: {0}")]
96 OtherLightClientRpcError(#[from] subxt_lightclient::LightClientRpcError),
97 #[error("Other error: {0}")]
101 Other(Box<dyn std::error::Error + Send + Sync + 'static>),
102}
103
104impl From<std::convert::Infallible> for Error {
105 fn from(value: std::convert::Infallible) -> Self {
106 match value {}
107 }
108}
109
110impl Error {
111 pub fn other<E: std::error::Error + Send + Sync + 'static>(error: E) -> Error {
114 Error::Other(Box::new(error))
115 }
116
117 pub fn other_str(error: impl Into<String>) -> Error {
120 #[derive(thiserror::Error, Debug, Clone)]
121 #[error("{0}")]
122 struct StrError(String);
123 Error::Other(Box::new(StrError(error.into())))
124 }
125
126 pub fn is_disconnected_will_reconnect(&self) -> bool {
128 matches!(
129 self.backend_error(),
130 Some(BackendError::Rpc(RpcError::ClientError(
131 subxt_rpcs::Error::DisconnectedWillReconnect(_)
132 )))
133 )
134 }
135
136 pub fn is_rpc_limit_reached(&self) -> bool {
138 matches!(
139 self.backend_error(),
140 Some(BackendError::Rpc(RpcError::LimitReached))
141 )
142 }
143
144 fn backend_error(&self) -> Option<&BackendError> {
145 match self {
146 Error::BlocksError(e) => e.backend_error(),
150 Error::AccountNonceError(e) => e.backend_error(),
151 Error::OnlineClientError(e) => e.backend_error(),
152 Error::RuntimeApiError(e) => e.backend_error(),
153 Error::EventsError(e) => e.backend_error(),
154 Error::BlockError(e) => e.backend_error(),
155 Error::ExtrinsicError(e) => e.backend_error(),
156 Error::ViewFunctionError(e) => e.backend_error(),
157 Error::TransactionProgressError(e) => e.backend_error(),
158 Error::TransactionEventsError(e) => e.backend_error(),
159 Error::TransactionFinalizedSuccessError(e) => e.backend_error(),
160 Error::StorageError(e) => e.backend_error(),
161 Error::OfflineClientAtBlockError(e) => e.backend_error(),
162 Error::OnlineClientAtBlockError(e) => e.backend_error(),
163 Error::ExtrinsicDecodeErrorAt(e) => e.backend_error(),
164 Error::ConstantError(e) => e.backend_error(),
165 Error::CustomValueError(e) => e.backend_error(),
166 Error::StorageKeyError(e) => e.backend_error(),
167 Error::StorageValueError(e) => e.backend_error(),
168 Error::TransactionStatusError(e) => e.backend_error(),
169 Error::ModuleErrorDetailsError(e) => e.backend_error(),
170 Error::ModuleErrorDecodeError(e) => e.backend_error(),
171 Error::DispatchErrorDecodeError(e) => e.backend_error(),
172 Error::CombinedBackendError(e) => e.backend_error(),
173 #[cfg(feature = "light-client")]
174 Error::OtherLightClientError(_) => None,
175 #[cfg(feature = "light-client")]
176 Error::OtherLightClientRpcError(_) => None,
177 Error::BackendError(e) => Some(e),
179 Error::OtherRpcClientError(_) => None,
181 Error::OtherCodecError(_) => None,
182 Error::Other(_) => None,
183 }
184 }
185}
186
187#[allow(missing_docs)]
189#[derive(Debug, thiserror::Error)]
190#[non_exhaustive]
191pub enum OfflineClientAtBlockError {
192 #[error(
193 "Cannot construct OfflineClientAtBlock: spec version not found for block number {block_number}"
194 )]
195 SpecVersionNotFound {
196 block_number: u64,
198 },
199 #[error(
200 "Cannot construct OfflineClientAtBlock: metadata not found for spec version {spec_version}"
201 )]
202 MetadataNotFound {
203 spec_version: u32,
205 },
206}
207
208impl OfflineClientAtBlockError {
209 fn backend_error(&self) -> Option<&BackendError> {
210 None
211 }
212}
213
214#[derive(Debug, thiserror::Error)]
215#[non_exhaustive]
216#[allow(missing_docs)]
217pub enum OnlineClientError {
218 #[error("Cannot construct OnlineClient: {0}")]
219 RpcError(#[from] subxt_rpcs::Error),
220 #[error("Could not construct the CombinedBackend: {0}")]
221 CannotBuildCombinedBackend(CombinedBackendError),
222 #[error("Cannot construct OnlineClient: Cannot fetch genesis hash: {0}")]
223 CannotGetGenesisHash(BackendError),
224}
225
226impl OnlineClientError {
227 fn backend_error(&self) -> Option<&BackendError> {
228 match self {
229 OnlineClientError::CannotGetGenesisHash(e) => Some(e),
230 _ => None,
231 }
232 }
233}
234
235#[allow(missing_docs)]
237#[derive(Debug, thiserror::Error)]
238#[non_exhaustive]
239pub enum BlocksError {
240 #[error("Cannot construct block stream: cannot get the current block: {0}")]
241 CannotGetCurrentBlock(OnlineClientAtBlockError),
242 #[error("Cannot construct block stream: cannot get block header stream: {0}")]
243 CannotGetBlockHeaderStream(BackendError),
244 #[error("Error streaming blocks: cannot get the next block header: {0}")]
245 CannotGetBlockHeader(BackendError),
246}
247
248impl BlocksError {
249 fn backend_error(&self) -> Option<&BackendError> {
250 match self {
251 BlocksError::CannotGetCurrentBlock(e) => e.backend_error(),
252 BlocksError::CannotGetBlockHeaderStream(e) => Some(e),
253 BlocksError::CannotGetBlockHeader(e) => Some(e),
254 }
255 }
256}
257
258#[allow(missing_docs)]
260#[derive(Debug, thiserror::Error)]
261#[non_exhaustive]
262pub enum OnlineClientAtBlockError {
263 #[error("Cannot construct OnlineClientAtBlock: cannot get the current block: {reason}")]
264 CannotGetCurrentBlock {
265 reason: BackendError,
267 },
268 #[error(
269 "Cannot construct OnlineClientAtBlock: failed to get block hash from node for block {block_number}: {reason}"
270 )]
271 CannotGetBlockHash {
272 block_number: u64,
274 reason: BackendError,
276 },
277 #[error("Cannot construct OnlineClientAtBlock: block number {block_number} not found")]
278 BlockNotFound {
279 block_number: u64,
281 },
282 #[error(
283 "Cannot construct OnlineClientAtBlock: cannot get the block header for block {block_hash}: {reason}"
284 )]
285 CannotGetBlockHeader {
286 block_hash: Hex,
288 reason: BackendError,
290 },
291 #[error(
292 "Cannot construct OnlineClientAtBlock: cannot find the block header for block {block_hash}"
293 )]
294 BlockHeaderNotFound {
295 block_hash: Hex,
297 },
298 #[error(
299 "Cannot construct OnlineClientAtBlock: failed to obtain spec version for block {block_hash}: {reason}"
300 )]
301 CannotGetSpecVersion {
302 block_hash: Hex,
304 reason: BackendError,
306 },
307 #[error(
308 "Cannot construct OnlineClientAtBlock: failed to decode spec version for block {block_hash}: {reason}"
309 )]
310 CannotDecodeSpecVersion {
311 block_hash: Hex,
313 reason: codec::Error,
315 },
316 #[error(
317 "Cannot construct OnlineClientAtBlock: failed to get metadata for block {block_hash}: {reason}"
318 )]
319 CannotGetMetadata {
320 block_hash: Hex,
322 reason: String,
324 },
325 #[error(
326 "Cannot construct OnlineClientAtBlock: Metadata V{version} (required at block {block_hash} is not supported."
327 )]
328 UnsupportedMetadataVersion {
329 block_hash: Hex,
331 version: u32,
333 },
334 #[error(
335 "Cannot construct OnlineClientAtBlock: No legacy types were provided but we're trying to access a block that requires them."
336 )]
337 MissingLegacyTypes,
338 #[error(
339 "Cannot construct OnlineClientAtBlock: unable to convert legacy metadata (required at block {block_hash}): {reason}"
340 )]
341 CannotConvertLegacyMetadata {
342 block_hash: Hex,
344 metadata_version: u32,
346 reason: subxt_metadata::LegacyFromError,
348 },
349 #[error(
350 "Cannot construct OnlineClientAtBlock: unable to convert modern metadata (required at block {block_hash}): {reason}"
351 )]
352 CannotConvertModernMetadata {
353 block_hash: Hex,
355 metadata_version: u32,
357 reason: subxt_metadata::TryFromError,
359 },
360 #[error(
361 "Cannot construct OnlineClientAtBlock: cannot inject types from metadata: failure to parse a type found in the metadata: {parse_error}"
362 )]
363 CannotInjectMetadataTypes {
364 parse_error: scale_info_legacy::lookup_name::ParseError,
366 },
367}
368
369impl OnlineClientAtBlockError {
370 fn backend_error(&self) -> Option<&BackendError> {
371 match self {
372 OnlineClientAtBlockError::CannotGetCurrentBlock { reason }
373 | OnlineClientAtBlockError::CannotGetBlockHash { reason, .. }
374 | OnlineClientAtBlockError::CannotGetBlockHeader { reason, .. }
375 | OnlineClientAtBlockError::CannotGetSpecVersion { reason, .. } => Some(reason),
376 _ => None,
377 }
378 }
379}
380
381#[derive(Debug, thiserror::Error)]
382#[non_exhaustive]
383#[allow(missing_docs)]
384pub enum BlockError {
385 #[error("Could not find the block with hash {block_hash}")]
386 BlockNotFound { block_hash: Hex },
387 #[error("Could not download the block header with hash {block_hash}: {reason}")]
388 CouldNotDownloadBlockHeader {
389 block_hash: Hex,
390 reason: BackendError,
391 },
392}
393
394impl BlockError {
395 fn backend_error(&self) -> Option<&BackendError> {
396 match self {
397 BlockError::CouldNotDownloadBlockHeader { reason, .. } => Some(reason),
398 _ => None,
399 }
400 }
401}
402
403#[derive(Debug, thiserror::Error)]
404#[non_exhaustive]
405#[allow(missing_docs)]
406pub enum BackendError {
407 #[error("Backend error: RPC error: {0}")]
408 Rpc(#[from] RpcError),
409 #[error("Custom backend error: {0}")]
411 Other(Cow<'static, str>),
412}
413
414impl BackendError {
415 pub fn is_disconnected_will_reconnect(&self) -> bool {
417 matches!(
418 self,
419 BackendError::Rpc(RpcError::ClientError(
420 subxt_rpcs::Error::DisconnectedWillReconnect(_)
421 ))
422 )
423 }
424
425 pub fn is_rpc_limit_reached(&self) -> bool {
427 matches!(self, BackendError::Rpc(RpcError::LimitReached))
428 }
429
430 pub fn other(message: impl Into<Cow<'static, str>>) -> Self {
432 BackendError::Other(message.into())
433 }
434}
435
436impl From<subxt_rpcs::Error> for BackendError {
437 fn from(value: subxt_rpcs::Error) -> Self {
438 BackendError::Rpc(RpcError::ClientError(value))
439 }
440}
441
442#[derive(Debug, thiserror::Error)]
443#[non_exhaustive]
444#[allow(missing_docs)]
445pub enum CombinedBackendError {
446 #[error("Could not obtain the list of RPC methods to determine which backends can be used")]
447 CouldNotObtainRpcMethodList(subxt_rpcs::Error),
448}
449
450impl CombinedBackendError {
451 fn backend_error(&self) -> Option<&BackendError> {
452 None
453 }
454}
455
456#[derive(Debug, thiserror::Error)]
459#[non_exhaustive]
460pub enum RpcError {
461 #[error("RPC error: {0}")]
463 ClientError(#[from] subxt_rpcs::Error),
464 #[error("RPC error: limit reached")]
467 LimitReached,
468 #[error("RPC error: subscription dropped.")]
470 SubscriptionDropped,
471}
472
473#[derive(Debug, thiserror::Error)]
474#[non_exhaustive]
475#[allow(missing_docs)]
476pub enum AccountNonceError {
477 #[error("Could not retrieve account nonce: {0}")]
478 CouldNotRetrieve(BackendError),
479 #[error("Could not decode account nonce: {0}")]
480 CouldNotDecode(codec::Error),
481 #[error("Wrong number of account nonce bytes returned: {0} (expected 2, 4 or 8)")]
482 WrongNumberOfBytes(usize),
483}
484
485impl AccountNonceError {
486 fn backend_error(&self) -> Option<&BackendError> {
487 match self {
488 AccountNonceError::CouldNotRetrieve(e) => Some(e),
489 _ => None,
490 }
491 }
492}
493
494#[non_exhaustive]
496#[derive(Debug, thiserror::Error)]
497#[allow(missing_docs)]
498pub enum RuntimeApiError {
499 #[error("The static Runtime API address used is not compatible with the live chain")]
500 IncompatibleCodegen,
501 #[error("Runtime API trait not found: {0}")]
502 TraitNotFound(String),
503 #[error("Runtime API method {method_name} not found in trait {trait_name}")]
504 MethodNotFound {
505 trait_name: String,
506 method_name: String,
507 },
508 #[error("Failed to encode Runtime API inputs: {0}")]
509 CouldNotEncodeInputs(frame_decode::runtime_apis::RuntimeApiInputsEncodeError),
510 #[error("Failed to decode Runtime API: {0}")]
511 CouldNotDecodeResponse(frame_decode::runtime_apis::RuntimeApiDecodeError<u32>),
512 #[error("Cannot call the Runtime API: {0}")]
513 CannotCallApi(BackendError),
514}
515
516impl RuntimeApiError {
517 fn backend_error(&self) -> Option<&BackendError> {
518 match self {
519 RuntimeApiError::CannotCallApi(e) => Some(e),
520 _ => None,
521 }
522 }
523}
524
525#[non_exhaustive]
527#[derive(Debug, thiserror::Error)]
528#[allow(missing_docs)]
529pub enum EventsError {
530 #[error("Can't decode event: can't decode phase: {0}")]
531 CannotDecodePhase(codec::Error),
532 #[error("Can't decode event: can't decode pallet index: {0}")]
533 CannotDecodePalletIndex(codec::Error),
534 #[error("Can't decode event: can't decode variant index: {0}")]
535 CannotDecodeVariantIndex(codec::Error),
536 #[error("Can't decode event: can't find pallet with index {0}")]
537 CannotFindPalletWithIndex(u8),
538 #[error(
539 "Can't decode event: can't find variant with index {variant_index} in pallet {pallet_name}"
540 )]
541 CannotFindVariantWithIndex {
542 pallet_name: String,
543 variant_index: u8,
544 },
545 #[error("Can't decode field {field_name:?} in event {pallet_name}.{event_name}: {reason}")]
546 CannotDecodeFieldInEvent {
547 pallet_name: String,
548 event_name: String,
549 field_name: String,
550 reason: scale_decode::visitor::DecodeError,
551 },
552 #[error("Can't decode event topics: {0}")]
553 CannotDecodeEventTopics(codec::Error),
554 #[error("Can't decode the fields of event {pallet_name}.{event_name}: {reason}")]
555 CannotDecodeEventFields {
556 pallet_name: String,
557 event_name: String,
558 reason: scale_decode::Error,
559 },
560 #[error("Can't decode event {pallet_name}.{event_name} to Event enum: {reason}")]
561 CannotDecodeEventEnum {
562 pallet_name: String,
563 event_name: String,
564 reason: scale_decode::Error,
565 },
566 #[error("Cannot fetch event bytes: {0}")]
567 CannotFetchEventBytes(BackendError),
568}
569
570impl EventsError {
571 fn backend_error(&self) -> Option<&BackendError> {
572 match self {
573 EventsError::CannotFetchEventBytes(e) => Some(e),
574 _ => None,
575 }
576 }
577}
578
579#[non_exhaustive]
581#[derive(Debug, thiserror::Error)]
582#[allow(missing_docs)]
583pub enum ExtrinsicError {
584 #[error("Failed to construct extrinsic: {0}")]
585 EncodeError(#[from] frame_decode::extrinsics::ExtrinsicEncodeError),
586 #[error("The extrinsic payload is not compatible with the live chain")]
587 IncompatibleCodegen,
588 #[error("Can't find extrinsic: pallet with name {0} not found")]
589 PalletNameNotFound(String),
590 #[error("Can't find extrinsic: call name {call_name} doesn't exist in pallet {pallet_name}")]
591 CallNameNotFound {
592 pallet_name: String,
593 call_name: String,
594 },
595 #[error("Failed to encode an extrinsic: the genesis hash was not provided")]
596 GenesisHashNotProvided,
597 #[error("Subxt does not support the extrinsic versions expected by the chain")]
598 UnsupportedVersion,
599 #[error("Cannot construct the required transaction extensions: {0}")]
600 Params(#[from] TransactionExtensionError),
601 #[error("Cannot decode transaction extension '{name}': {error}")]
602 CouldNotDecodeTransactionExtension {
603 name: String,
605 error: scale_decode::Error,
607 },
608 #[error("Failed to decode the fields of an extrinsic at index {extrinsic_index}: {error}")]
609 CannotDecodeFields {
610 extrinsic_index: usize,
612 error: scale_decode::Error,
614 },
615 #[error("Failed to decode the extrinsic at index {extrinsic_index} to a root enum: {error}")]
616 CannotDecodeIntoRootExtrinsic {
617 extrinsic_index: usize,
619 error: scale_decode::Error,
621 },
622 #[error(
623 "Cannot decode call data: expected at least 2 bytes (the pallet and call index) but got {0}"
624 )]
625 CallDataTooShort(usize),
626 #[error("Cannot decode call data: {0}")]
627 CannotDecodeCallData(frame_decode::extrinsics::ExtrinsicInfoError<'static>),
628 #[error("Cannot decode the call data arguments: {0}")]
629 CannotDecodeCallDataFields(scale_decode::Error),
630 #[error("Cannot decode call data: {0} bytes are left over after decoding it")]
631 LeftoverBytesDecodingCallData(usize),
632 #[error("Could not download block body to extract extrinsics from: {0}")]
633 CannotGetBlockBody(BackendError),
634 #[error("Block not found: {0}")]
635 BlockNotFound(Hex),
636 #[error("Error getting account nonce at block {block_hash}")]
637 AccountNonceError {
638 block_hash: Hex,
639 account_id: Hex,
640 reason: AccountNonceError,
641 },
642 #[error("Cannot submit extrinsic: {0}")]
643 ErrorSubmittingTransaction(BackendError),
644 #[error("A transaction status error was returned while submitting the extrinsic: {0}")]
645 TransactionStatusError(TransactionStatusError),
646 #[error(
647 "The transaction status stream encountered an error while submitting the extrinsic: {0}"
648 )]
649 TransactionStatusStreamError(BackendError),
650 #[error(
651 "The transaction status stream unexpectedly ended, so we don't know the status of the submitted extrinsic"
652 )]
653 UnexpectedEndOfTransactionStatusStream,
654 #[error("Cannot get fee info from Runtime API: {0}")]
655 CannotGetFeeInfo(BackendError),
656 #[error("Cannot decode fee info from Runtime API: {0}")]
657 CannotDecodeFeeInfo(codec::Error),
658 #[error("Cannot get validation info from Runtime API: {0}")]
659 CannotGetValidationInfo(BackendError),
660 #[error("Cannot decode ValidationResult bytes: {0}")]
661 CannotDecodeValidationResult(codec::Error),
662 #[error("ValidationResult bytes could not be decoded")]
663 UnexpectedValidationResultBytes(Vec<u8>),
664}
665
666impl ExtrinsicError {
667 fn backend_error(&self) -> Option<&BackendError> {
668 match self {
669 ExtrinsicError::CannotGetBlockBody(e)
670 | ExtrinsicError::ErrorSubmittingTransaction(e)
671 | ExtrinsicError::TransactionStatusStreamError(e)
672 | ExtrinsicError::CannotGetFeeInfo(e)
673 | ExtrinsicError::CannotGetValidationInfo(e) => Some(e),
674 ExtrinsicError::AccountNonceError { reason, .. } => reason.backend_error(),
675 _ => None,
676 }
677 }
678}
679
680#[derive(Debug, DeriveError)]
681#[non_exhaustive]
682#[allow(missing_docs)]
683pub enum CustomValueError {
684 #[error("The static custom value address used is not compatible with the live chain")]
685 IncompatibleCodegen,
686 #[error("The custom value '{0}' was not found")]
687 NotFound(String),
688 #[error("Failed to decode custom value: {0}")]
689 CouldNotDecodeCustomValue(frame_decode::custom_values::CustomValueDecodeError<u32>),
690}
691
692impl CustomValueError {
693 fn backend_error(&self) -> Option<&BackendError> {
694 None
695 }
696}
697
698#[non_exhaustive]
700#[derive(Debug, thiserror::Error)]
701#[allow(missing_docs)]
702pub enum ViewFunctionError {
703 #[error("The static View Function address used is not compatible with the live chain")]
704 IncompatibleCodegen,
705 #[error("Can't find View Function: pallet {0} not found")]
706 PalletNotFound(String),
707 #[error("Can't find View Function {function_name} in pallet {pallet_name}")]
708 ViewFunctionNotFound {
709 pallet_name: String,
710 function_name: String,
711 },
712 #[error("Failed to encode View Function inputs: {0}")]
713 CouldNotEncodeInputs(frame_decode::view_functions::ViewFunctionInputsEncodeError),
714 #[error("Failed to decode View Function: {0}")]
715 CouldNotDecodeResponse(frame_decode::view_functions::ViewFunctionDecodeError<u32>),
716 #[error("Cannot call the View Function Runtime API: {0}")]
717 CannotCallApi(BackendError),
718}
719
720impl ViewFunctionError {
721 fn backend_error(&self) -> Option<&BackendError> {
722 match self {
723 ViewFunctionError::CannotCallApi(e) => Some(e),
724 _ => None,
725 }
726 }
727}
728
729#[non_exhaustive]
731#[derive(Debug, thiserror::Error)]
732#[allow(missing_docs)]
733pub enum TransactionProgressError {
734 #[error("Cannot get the next transaction progress update: {0}")]
735 CannotGetNextProgressUpdate(BackendError),
736 #[error("Error during transaction progress: {0}")]
737 TransactionStatusError(#[from] TransactionStatusError),
738 #[error(
739 "The transaction status stream unexpectedly ended, so we have no further transaction progress updates"
740 )]
741 UnexpectedEndOfTransactionStatusStream,
742}
743
744impl TransactionProgressError {
745 fn backend_error(&self) -> Option<&BackendError> {
746 match self {
747 TransactionProgressError::CannotGetNextProgressUpdate(e) => Some(e),
748 TransactionProgressError::TransactionStatusError(_) => None,
749 TransactionProgressError::UnexpectedEndOfTransactionStatusStream => None,
750 }
751 }
752}
753
754#[derive(Clone, Debug, Eq, thiserror::Error, PartialEq)]
756#[non_exhaustive]
757#[allow(missing_docs)]
758pub enum TransactionStatusError {
759 #[error("Error handling transaction: {0}")]
761 Error(String),
762 #[error("The transaction is not valid: {0}")]
764 Invalid(String),
765 #[error("The transaction was dropped: {0}")]
767 Dropped(String),
768}
769
770impl TransactionStatusError {
771 fn backend_error(&self) -> Option<&BackendError> {
772 None
773 }
774}
775
776#[derive(Debug, thiserror::Error)]
778#[non_exhaustive]
779#[allow(missing_docs)]
780pub enum TransactionEventsError {
781 #[error(
782 "The block containing the submitted transaction ({block_hash}) could not be downloaded: {error}"
783 )]
784 CannotFetchBlockBody {
785 block_hash: Hex,
786 error: BackendError,
787 },
788 #[error(
789 "Cannot find the the submitted transaction (hash: {transaction_hash}) in the block (hash: {block_hash}) it is supposed to be in."
790 )]
791 CannotFindTransactionInBlock {
792 block_hash: Hex,
793 transaction_hash: Hex,
794 },
795 #[error("The block containing the submitted transaction ({block_hash}) could not be found")]
796 BlockNotFound { block_hash: Hex },
797 #[error(
798 "Could not decode event at index {event_index} for the submitted transaction at block {block_hash}: {error}"
799 )]
800 CannotDecodeEventInBlock {
801 event_index: usize,
802 block_hash: Hex,
803 error: EventsError,
804 },
805 #[error("Could not instantiate a client at the required block to fetch events: {0}")]
806 CannotInstantiateClientAtBlock(OnlineClientAtBlockError),
807 #[error("Could not fetch events for the submitted transaction: {error}")]
808 CannotFetchEventsForTransaction {
809 block_hash: Hex,
810 transaction_hash: Hex,
811 error: EventsError,
812 },
813 #[error("The transaction led to a DispatchError, but we failed to decode it: {error}")]
814 CannotDecodeDispatchError {
815 error: DispatchErrorDecodeError,
816 bytes: Vec<u8>,
817 },
818 #[error("The transaction failed with the following dispatch error: {0}")]
819 ExtrinsicFailed(#[from] DispatchError),
820}
821
822impl TransactionEventsError {
823 fn backend_error(&self) -> Option<&BackendError> {
824 match self {
825 TransactionEventsError::CannotFetchBlockBody { error, .. } => Some(error),
826 TransactionEventsError::CannotDecodeEventInBlock { error, .. }
827 | TransactionEventsError::CannotFetchEventsForTransaction { error, .. } => {
828 error.backend_error()
829 }
830 _ => None,
831 }
832 }
833}
834
835#[derive(Debug, thiserror::Error)]
837#[non_exhaustive]
838#[allow(missing_docs, clippy::large_enum_variant)]
839pub enum TransactionFinalizedSuccessError {
840 #[error("Could not finalize the transaction: {0}")]
841 FinalizationError(#[from] TransactionProgressError),
842 #[error("The transaction did not succeed: {0}")]
843 SuccessError(#[from] TransactionEventsError),
844}
845
846impl TransactionFinalizedSuccessError {
847 fn backend_error(&self) -> Option<&BackendError> {
848 match self {
849 TransactionFinalizedSuccessError::FinalizationError(e) => e.backend_error(),
850 TransactionFinalizedSuccessError::SuccessError(e) => e.backend_error(),
851 }
852 }
853}
854
855#[derive(Debug, thiserror::Error)]
857#[non_exhaustive]
858#[allow(missing_docs)]
859pub enum ModuleErrorDetailsError {
860 #[error(
861 "Could not get details for the DispatchError: could not find pallet index {pallet_index}"
862 )]
863 PalletNotFound { pallet_index: u8 },
864 #[error(
865 "Could not get details for the DispatchError: could not find error index {error_index} in pallet {pallet_name}"
866 )]
867 ErrorVariantNotFound {
868 pallet_name: String,
869 error_index: u8,
870 },
871}
872
873impl ModuleErrorDetailsError {
874 fn backend_error(&self) -> Option<&BackendError> {
875 None
876 }
877}
878
879#[derive(Debug, thiserror::Error)]
881#[non_exhaustive]
882#[allow(missing_docs)]
883#[error("Could not decode the DispatchError::Module payload into the given type: {0}")]
884pub struct ModuleErrorDecodeError(scale_decode::Error);
885
886impl ModuleErrorDecodeError {
887 fn backend_error(&self) -> Option<&BackendError> {
888 None
889 }
890}
891
892#[derive(Debug, thiserror::Error)]
894#[non_exhaustive]
895#[allow(missing_docs)]
896pub enum DispatchErrorDecodeError {
897 #[error(
898 "Could not decode the DispatchError: could not find the corresponding type ID in the metadata"
899 )]
900 DispatchErrorTypeIdNotFound,
901 #[error("Could not decode the DispatchError: {0}")]
902 CouldNotDecodeDispatchError(scale_decode::Error),
903 #[error("Could not decode the DispatchError::Module variant")]
904 CouldNotDecodeModuleError {
905 bytes: Vec<u8>,
907 },
908}
909
910impl DispatchErrorDecodeError {
911 fn backend_error(&self) -> Option<&BackendError> {
912 None
913 }
914}
915
916#[derive(Debug, thiserror::Error)]
918#[non_exhaustive]
919#[allow(missing_docs)]
920pub enum StorageError {
921 #[error("The static storage address used is not compatible with the live chain")]
922 IncompatibleCodegen,
923 #[error("Can't find storage value: pallet with name {0} not found")]
924 PalletNameNotFound(String),
925 #[error(
926 "Storage entry '{entry_name}' not found in pallet {pallet_name} in the live chain metadata"
927 )]
928 StorageEntryNotFound {
929 pallet_name: String,
930 entry_name: String,
931 },
932 #[error("Cannot obtain storage information from metadata: {0}")]
933 StorageInfoError(frame_decode::storage::StorageInfoError<'static>),
934 #[error("Cannot encode storage key: {0}")]
935 StorageKeyEncodeError(frame_decode::storage::StorageKeyEncodeError),
936 #[error("Cannot create a key to iterate over a plain entry")]
937 CannotIterPlainEntry {
938 pallet_name: String,
939 entry_name: String,
940 },
941 #[error(
942 "Wrong number of key parts provided to iterate a storage address. We expected at most {max_expected} key parts but got {got} key parts"
943 )]
944 WrongNumberOfKeyPartsProvidedForIterating { max_expected: usize, got: usize },
945 #[error(
946 "Wrong number of key parts provided to fetch a storage address. We expected {expected} key parts but got {got} key parts"
947 )]
948 WrongNumberOfKeyPartsProvidedForFetching { expected: usize, got: usize },
949 #[error(
950 "No storage value found at the given address, and no default value to fall back to using."
951 )]
952 NoValueFound,
953 #[error("Cannot fetch the storage value: {0}")]
954 CannotFetchValue(BackendError),
955 #[error("Cannot iterate storage values: {0}")]
956 CannotIterateValues(BackendError),
957 #[error("Encountered an error iterating over storage values: {0}")]
958 StreamFailure(BackendError),
959 #[error("Cannot decode the storage version for a given entry: {0}")]
960 CannotDecodeStorageVersion(codec::Error),
961}
962
963impl StorageError {
964 fn backend_error(&self) -> Option<&BackendError> {
965 match self {
966 StorageError::CannotFetchValue(e)
967 | StorageError::CannotIterateValues(e)
968 | StorageError::StreamFailure(e) => Some(e),
969 _ => None,
970 }
971 }
972}
973
974#[derive(Debug, DeriveError)]
976#[non_exhaustive]
977#[allow(missing_docs)]
978pub enum ConstantError {
979 #[error("The static constant address used is not compatible with the live chain")]
980 IncompatibleCodegen,
981 #[error("Can't find constant: pallet with name {0} not found")]
982 PalletNameNotFound(String),
983 #[error(
984 "Constant '{constant_name}' not found in pallet {pallet_name} in the live chain metadata"
985 )]
986 ConstantNameNotFound {
987 pallet_name: String,
988 constant_name: String,
989 },
990 #[error("Failed to decode constant: {0}")]
991 CouldNotDecodeConstant(frame_decode::constants::ConstantDecodeError<u32>),
992 #[error("Cannot obtain constant information from metadata: {0}")]
993 ConstantInfoError(frame_decode::constants::ConstantInfoError<'static>),
994}
995
996impl ConstantError {
997 fn backend_error(&self) -> Option<&BackendError> {
998 None
999 }
1000}
1001
1002#[derive(Debug, DeriveError)]
1003#[non_exhaustive]
1004#[allow(missing_docs)]
1005pub enum StorageKeyError {
1006 #[error("Can't decode the storage key: {error}")]
1007 StorageKeyDecodeError {
1008 bytes: Vec<u8>,
1009 error: frame_decode::storage::StorageKeyDecodeError<u32>,
1010 },
1011 #[error("Can't decode the values from the storage key: {0}")]
1012 CannotDecodeValuesInKey(frame_decode::storage::StorageKeyValueDecodeError),
1013 #[error(
1014 "Cannot decode storage key: there were leftover bytes, indicating that the decoding failed"
1015 )]
1016 LeftoverBytes { bytes: Vec<u8> },
1017 #[error("Can't decode a single value from the storage key part at index {index}: {error}")]
1018 CannotDecodeValueInKey {
1019 index: usize,
1020 error: scale_decode::Error,
1021 },
1022}
1023
1024impl StorageKeyError {
1025 fn backend_error(&self) -> Option<&BackendError> {
1026 None
1027 }
1028}
1029
1030#[derive(Debug, DeriveError)]
1031#[non_exhaustive]
1032#[allow(missing_docs)]
1033pub enum StorageValueError {
1034 #[error("Cannot decode storage value: {0}")]
1035 CannotDecode(frame_decode::storage::StorageValueDecodeError<u32>),
1036 #[error(
1037 "Cannot decode storage value: there were leftover bytes, indicating that the decoding failed"
1038 )]
1039 LeftoverBytes { bytes: Vec<u8> },
1040}
1041
1042impl StorageValueError {
1043 fn backend_error(&self) -> Option<&BackendError> {
1044 None
1045 }
1046}
1047
1048#[derive(Debug, thiserror::Error)]
1049#[non_exhaustive]
1050#[allow(missing_docs)]
1051#[error("Cannot decode extrinsic at index {extrinsic_index}: {error}")]
1052pub struct ExtrinsicDecodeErrorAt {
1053 pub extrinsic_index: usize,
1054 pub error: ExtrinsicDecodeErrorAtReason,
1055}
1056
1057impl ExtrinsicDecodeErrorAt {
1058 fn backend_error(&self) -> Option<&BackendError> {
1059 None
1060 }
1061}
1062
1063#[derive(Debug, thiserror::Error)]
1064#[non_exhaustive]
1065#[allow(missing_docs)]
1066pub enum ExtrinsicDecodeErrorAtReason {
1067 #[error("{0}")]
1068 DecodeError(frame_decode::extrinsics::ExtrinsicDecodeError),
1069 #[error("Leftover bytes")]
1070 LeftoverBytes(Vec<u8>),
1071}
1072
1073#[derive(Debug, DeriveError)]
1076#[non_exhaustive]
1077#[allow(missing_docs)]
1078pub enum TransactionExtensionError {
1079 #[error("Error constructing extrinsic parameters: {0}")]
1080 Custom(Box<dyn core::error::Error + Send + Sync + 'static>),
1081}
1082
1083impl TransactionExtensionError {
1084 pub fn custom<S: Into<String>>(error: S) -> Self {
1086 let error: String = error.into();
1087 let error: Box<dyn core::error::Error + Send + Sync + 'static> = Box::from(error);
1088 TransactionExtensionError::Custom(error)
1089 }
1090}
1091
1092impl From<core::convert::Infallible> for TransactionExtensionError {
1093 fn from(value: core::convert::Infallible) -> Self {
1094 match value {}
1095 }
1096}