pezkuwi_subxt_core/
error.rs

1// Copyright 2019-2024 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//! The errors that can be emitted in this crate.
6
7use alloc::{boxed::Box, string::String, vec::Vec};
8use thiserror::Error as DeriveError;
9
10/// The error emitted when something goes wrong.
11#[derive(Debug, DeriveError)]
12#[allow(missing_docs)]
13pub enum Error {
14	#[error(transparent)]
15	StorageError(#[from] StorageError),
16	#[error(transparent)]
17	Extrinsic(#[from] ExtrinsicError),
18	#[error(transparent)]
19	Constant(#[from] ConstantError),
20	#[error(transparent)]
21	CustomValue(#[from] CustomValueError),
22	#[error(transparent)]
23	RuntimeApi(#[from] RuntimeApiError),
24	#[error(transparent)]
25	ViewFunction(#[from] ViewFunctionError),
26	#[error(transparent)]
27	Events(#[from] EventsError),
28}
29
30#[derive(Debug, DeriveError)]
31#[non_exhaustive]
32#[allow(missing_docs)]
33pub enum EventsError {
34	#[error("Can't decode event: can't decode phase: {0}")]
35	CannotDecodePhase(codec::Error),
36	#[error("Can't decode event: can't decode pallet index: {0}")]
37	CannotDecodePalletIndex(codec::Error),
38	#[error("Can't decode event: can't decode variant index: {0}")]
39	CannotDecodeVariantIndex(codec::Error),
40	#[error("Can't decode event: can't find pallet with index {0}")]
41	CannotFindPalletWithIndex(u8),
42	#[error(
43		"Can't decode event: can't find variant with index {variant_index} in pallet {pallet_name}"
44	)]
45	CannotFindVariantWithIndex { pallet_name: String, variant_index: u8 },
46	#[error("Can't decode field {field_name:?} in event {pallet_name}.{event_name}: {reason}")]
47	CannotDecodeFieldInEvent {
48		pallet_name: String,
49		event_name: String,
50		field_name: String,
51		reason: scale_decode::visitor::DecodeError,
52	},
53	#[error("Can't decode event topics: {0}")]
54	CannotDecodeEventTopics(codec::Error),
55	#[error("Can't decode the fields of event {pallet_name}.{event_name}: {reason}")]
56	CannotDecodeEventFields { pallet_name: String, event_name: String, reason: scale_decode::Error },
57	#[error("Can't decode event {pallet_name}.{event_name} to Event enum: {reason}")]
58	CannotDecodeEventEnum { pallet_name: String, event_name: String, reason: scale_decode::Error },
59}
60
61#[derive(Debug, DeriveError)]
62#[non_exhaustive]
63#[allow(missing_docs)]
64pub enum ViewFunctionError {
65	#[error("The static View Function address used is not compatible with the live chain")]
66	IncompatibleCodegen,
67	#[error("Can't find View Function: pallet {0} not found")]
68	PalletNotFound(String),
69	#[error("Can't find View Function {function_name} in pallet {pallet_name}")]
70	ViewFunctionNotFound { pallet_name: String, function_name: String },
71	#[error("Failed to encode View Function inputs: {0}")]
72	CouldNotEncodeInputs(frame_decode::view_functions::ViewFunctionInputsEncodeError),
73	#[error("Failed to decode View Function: {0}")]
74	CouldNotDecodeResponse(frame_decode::view_functions::ViewFunctionDecodeError<u32>),
75}
76
77#[derive(Debug, DeriveError)]
78#[non_exhaustive]
79#[allow(missing_docs)]
80pub enum RuntimeApiError {
81	#[error("The static Runtime API address used is not compatible with the live chain")]
82	IncompatibleCodegen,
83	#[error("Runtime API trait not found: {0}")]
84	TraitNotFound(String),
85	#[error("Runtime API method {method_name} not found in trait {trait_name}")]
86	MethodNotFound { trait_name: String, method_name: String },
87	#[error("Failed to encode Runtime API inputs: {0}")]
88	CouldNotEncodeInputs(frame_decode::runtime_apis::RuntimeApiInputsEncodeError),
89	#[error("Failed to decode Runtime API: {0}")]
90	CouldNotDecodeResponse(frame_decode::runtime_apis::RuntimeApiDecodeError<u32>),
91}
92
93#[derive(Debug, DeriveError)]
94#[non_exhaustive]
95#[allow(missing_docs)]
96pub enum CustomValueError {
97	#[error("The static custom value address used is not compatible with the live chain")]
98	IncompatibleCodegen,
99	#[error("The custom value '{0}' was not found")]
100	NotFound(String),
101	#[error("Failed to decode custom value: {0}")]
102	CouldNotDecodeCustomValue(frame_decode::custom_values::CustomValueDecodeError<u32>),
103}
104
105/// Something went wrong working with a constant.
106#[derive(Debug, DeriveError)]
107#[non_exhaustive]
108#[allow(missing_docs)]
109pub enum ConstantError {
110	#[error("The static constant address used is not compatible with the live chain")]
111	IncompatibleCodegen,
112	#[error("Can't find constant: pallet with name {0} not found")]
113	PalletNameNotFound(String),
114	#[error(
115		"Constant '{constant_name}' not found in pallet {pallet_name} in the live chain metadata"
116	)]
117	ConstantNameNotFound { pallet_name: String, constant_name: String },
118	#[error("Failed to decode constant: {0}")]
119	CouldNotDecodeConstant(frame_decode::constants::ConstantDecodeError<u32>),
120	#[error("Cannot obtain constant information from metadata: {0}")]
121	ConstantInfoError(frame_decode::constants::ConstantInfoError<'static>),
122}
123
124/// Something went wrong trying to encode or decode a storage address.
125#[derive(Debug, DeriveError)]
126#[non_exhaustive]
127#[allow(missing_docs)]
128pub enum StorageError {
129	#[error("The static storage address used is not compatible with the live chain")]
130	IncompatibleCodegen,
131	#[error("Can't find storage value: pallet with name {0} not found")]
132	PalletNameNotFound(String),
133	#[error(
134		"Storage entry '{entry_name}' not found in pallet {pallet_name} in the live chain metadata"
135	)]
136	StorageEntryNotFound { pallet_name: String, entry_name: String },
137	#[error("Cannot obtain storage information from metadata: {0}")]
138	StorageInfoError(frame_decode::storage::StorageInfoError<'static>),
139	#[error("Cannot encode storage key: {0}")]
140	StorageKeyEncodeError(frame_decode::storage::StorageKeyEncodeError),
141	#[error("Cannot create a key to iterate over a plain entry")]
142	CannotIterPlainEntry { pallet_name: String, entry_name: String },
143	#[error(
144		"Wrong number of key parts provided to iterate a storage address. We expected at most {max_expected} key parts but got {got} key parts"
145	)]
146	WrongNumberOfKeyPartsProvidedForIterating { max_expected: usize, got: usize },
147	#[error(
148		"Wrong number of key parts provided to fetch a storage address. We expected {expected} key parts but got {got} key parts"
149	)]
150	WrongNumberOfKeyPartsProvidedForFetching { expected: usize, got: usize },
151}
152
153#[derive(Debug, DeriveError)]
154#[non_exhaustive]
155#[allow(missing_docs)]
156pub enum StorageKeyError {
157	#[error("Can't decode the storage key: {error}")]
158	StorageKeyDecodeError {
159		bytes: Vec<u8>,
160		error: frame_decode::storage::StorageKeyDecodeError<u32>,
161	},
162	#[error("Can't decode the values from the storage key: {0}")]
163	CannotDecodeValuesInKey(frame_decode::storage::StorageKeyValueDecodeError),
164	#[error(
165		"Cannot decode storage key: there were leftover bytes, indicating that the decoding failed"
166	)]
167	LeftoverBytes { bytes: Vec<u8> },
168	#[error("Can't decode a single value from the storage key part at index {index}: {error}")]
169	CannotDecodeValueInKey { index: usize, error: scale_decode::Error },
170}
171
172#[derive(Debug, DeriveError)]
173#[non_exhaustive]
174#[allow(missing_docs)]
175pub enum StorageValueError {
176	#[error("Cannot decode storage value: {0}")]
177	CannotDecode(frame_decode::storage::StorageValueDecodeError<u32>),
178	#[error(
179		"Cannot decode storage value: there were leftover bytes, indicating that the decoding failed"
180	)]
181	LeftoverBytes { bytes: Vec<u8> },
182}
183
184/// An error that can be encountered when constructing a transaction.
185#[derive(Debug, DeriveError)]
186#[allow(missing_docs)]
187pub enum ExtrinsicError {
188	#[error("The extrinsic payload is not compatible with the live chain")]
189	IncompatibleCodegen,
190	#[error("Can't find extrinsic: pallet with name {0} not found")]
191	PalletNameNotFound(String),
192	#[error("Can't find extrinsic: call name {call_name} doesn't exist in pallet {pallet_name}")]
193	CallNameNotFound { pallet_name: String, call_name: String },
194	#[error("Can't encode the extrinsic call data: {0}")]
195	CannotEncodeCallData(scale_encode::Error),
196	#[error("Subxt does not support the extrinsic versions expected by the chain")]
197	UnsupportedVersion,
198	#[error("Cannot construct the required transaction extensions: {0}")]
199	Params(#[from] ExtrinsicParamsError),
200	#[error("Cannot decode transaction extension '{name}': {error}")]
201	CouldNotDecodeTransactionExtension {
202		/// The extension name.
203		name: String,
204		/// The decode error.
205		error: scale_decode::Error,
206	},
207	#[error(
208		"After decoding the extrinsic at index {extrinsic_index}, {num_leftover_bytes} bytes were left, suggesting that decoding may have failed"
209	)]
210	LeftoverBytes {
211		/// Index of the extrinsic that failed to decode.
212		extrinsic_index: usize,
213		/// Number of bytes leftover after decoding the extrinsic.
214		num_leftover_bytes: usize,
215	},
216	#[error("{0}")]
217	ExtrinsicDecodeErrorAt(#[from] ExtrinsicDecodeErrorAt),
218	#[error("Failed to decode the fields of an extrinsic at index {extrinsic_index}: {error}")]
219	CannotDecodeFields {
220		/// Index of the extrinsic whose fields we could not decode
221		extrinsic_index: usize,
222		/// The decode error.
223		error: scale_decode::Error,
224	},
225	#[error("Failed to decode the extrinsic at index {extrinsic_index} to a root enum: {error}")]
226	CannotDecodeIntoRootExtrinsic {
227		/// Index of the extrinsic that we failed to decode
228		extrinsic_index: usize,
229		/// The decode error.
230		error: scale_decode::Error,
231	},
232}
233
234#[derive(Debug, thiserror::Error)]
235#[non_exhaustive]
236#[allow(missing_docs)]
237#[error("Cannot decode extrinsic at index {extrinsic_index}: {error}")]
238pub struct ExtrinsicDecodeErrorAt {
239	pub extrinsic_index: usize,
240	pub error: ExtrinsicDecodeErrorAtReason,
241}
242
243#[derive(Debug, thiserror::Error)]
244#[non_exhaustive]
245#[allow(missing_docs)]
246pub enum ExtrinsicDecodeErrorAtReason {
247	#[error("{0}")]
248	DecodeError(frame_decode::extrinsics::ExtrinsicDecodeError),
249	#[error("Leftover bytes")]
250	LeftoverBytes(Vec<u8>),
251}
252
253/// An error that can be emitted when trying to construct an instance of
254/// [`crate::config::ExtrinsicParams`], encode data from the instance, or match on signed
255/// extensions.
256#[derive(Debug, DeriveError)]
257#[non_exhaustive]
258#[allow(missing_docs)]
259pub enum ExtrinsicParamsError {
260	#[error("Cannot find type id '{type_id} in the metadata (context: {context})")]
261	MissingTypeId {
262		/// Type ID.
263		type_id: u32,
264		/// Some arbitrary context to help narrow the source of the error.
265		context: &'static str,
266	},
267	#[error("The chain expects a signed extension with the name {0}, but we did not provide one")]
268	UnknownTransactionExtension(String),
269	#[error("Error constructing extrinsic parameters: {0}")]
270	Custom(Box<dyn core::error::Error + Send + Sync + 'static>),
271}
272
273impl ExtrinsicParamsError {
274	/// Create a custom [`ExtrinsicParamsError`] from a string.
275	pub fn custom<S: Into<String>>(error: S) -> Self {
276		let error: String = error.into();
277		let error: Box<dyn core::error::Error + Send + Sync + 'static> = Box::from(error);
278		ExtrinsicParamsError::Custom(error)
279	}
280}
281
282impl From<core::convert::Infallible> for ExtrinsicParamsError {
283	fn from(value: core::convert::Infallible) -> Self {
284		match value {}
285	}
286}