diff --git a/node-api/src/error.rs b/node-api/src/error/dispatch_error.rs similarity index 74% rename from node-api/src/error.rs rename to node-api/src/error/dispatch_error.rs index bc7d39a07..22fc07bc5 100644 --- a/node-api/src/error.rs +++ b/node-api/src/error/dispatch_error.rs @@ -1,23 +1,22 @@ -// This file was taken from subxt (Parity Technologies (UK)) -// https://github.com/paritytech/subxt/ -// And was adapted by Supercomputing Systems AG and Integritee AG. -// -// Copyright 2019-2022 Parity Technologies (UK) Ltd, Supercomputing Systems AG and Integritee AG. -// This file is licensed as Apache-2.0 -// see LICENSE for license details. +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ -//! General node-api Error and Substrate DispatchError implementation. - -use crate::{ - alloc::{ - borrow::Cow, - format, - string::{String, ToString}, - vec::Vec, - }, - metadata::Metadata, +use crate::metadata::Metadata; +use alloc::{ + borrow::Cow, + string::{String, ToString}, + vec::Vec, }; - use codec::{Decode, Encode}; use core::fmt::Debug; use derive_more::From; @@ -32,45 +31,6 @@ pub use crate::{ pub use sp_core::crypto::SecretStringError; pub use sp_runtime::transaction_validity::TransactionValidityError; -/// The underlying error enum, generic over the type held by the `Runtime` -/// variant. Prefer to use the [`Error`] and [`Error`] aliases over -/// using this type directly. -#[derive(Debug, From)] -pub enum Error { - /// Codec error. - Codec(codec::Error), - /// Serde serialization error - Serialization(serde_json::error::Error), - /// Secret string error. - SecretString(SecretStringError), - /// Extrinsic validity error - Invalid(TransactionValidityError), - /// Invalid metadata error - InvalidMetadata(InvalidMetadataError), - /// Invalid metadata error - Metadata(MetadataError), - /// Runtime error. - Runtime(DispatchError), - /// Error decoding to a [`crate::dynamic::Value`]. - DecodeValue(DecodeError), - /// Error encoding from a [`crate::dynamic::Value`]. - EncodeValue(EncodeError), - /// Transaction progress error. - Transaction(TransactionError), - /// Block related error. - Block(BlockError), - /// An error encoding a storage address. - StorageAddress(StorageAddressError), - /// Other error. - Other(String), -} - -impl From<&str> for Error { - fn from(error: &str) -> Self { - Error::Other(error.into()) - } -} - /// An error dispatching a transaction. See Substrate DispatchError //https://github.com/paritytech/substrate/blob/890451221db37176e13cb1a306246f02de80590a/primitives/runtime/src/lib.rs#L524 #[derive(Debug, From)] @@ -295,32 +255,6 @@ pub enum TransactionalError { NoLayer, } -/// Block error -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum BlockError { - /// The block - BlockHashNotFound(String), -} - -impl BlockError { - /// Produce an error that a block with the given hash cannot be found. - pub fn block_hash_not_found(hash: impl AsRef<[u8]>) -> BlockError { - let hash = format!("0x{}", hex::encode(hash)); - BlockError::BlockHashNotFound(hash) - } -} - -/// Transaction error. -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum TransactionError { - /// The finality subscription expired (after ~512 blocks we give up if the - /// block hasn't yet been finalized). - FinalitySubscriptionTimeout, - /// The block hash that the transaction was added to could not be found. - /// This is probably because the block was retracted before being finalized. - BlockHashNotFound, -} - /// Details about a module error that has occurred. #[derive(Clone, Debug)] pub struct ModuleError { @@ -352,26 +286,3 @@ impl ModuleErrorData { self.error[0] } } - -/// Something went wrong trying to encode a storage address. -#[derive(Clone, Debug)] -pub enum StorageAddressError { - /// Storage map type must be a composite type. - MapTypeMustBeTuple, - /// Storage lookup does not have the expected number of keys. - WrongNumberOfKeys { - /// The actual number of keys needed, based on the metadata. - actual: usize, - /// The number of keys provided in the storage address. - expected: usize, - }, - /// Storage lookup requires a type that wasn't found in the metadata. - TypeNotFound(u32), - /// This storage entry in the metadata does not have the correct number of hashers to fields. - WrongNumberOfHashers { - /// The number of hashers in the metadata for this storage entry. - hashers: usize, - /// The number of fields in the metadata for this storage entry. - fields: usize, - }, -} diff --git a/node-api/src/error/mod.rs b/node-api/src/error/mod.rs new file mode 100644 index 000000000..1e6dd8605 --- /dev/null +++ b/node-api/src/error/mod.rs @@ -0,0 +1,112 @@ +// This file was taken from subxt (Parity Technologies (UK)) +// https://github.com/paritytech/subxt/ +// And was adapted by Supercomputing Systems AG and Integritee AG. +// +// Copyright 2019-2022 Parity Technologies (UK) Ltd, Supercomputing Systems AG and Integritee AG. +// This file is licensed as Apache-2.0 +// see LICENSE for license details. + +//! General node-api Error implementation. + +use alloc::{format, string::String}; +use core::fmt::Debug; +use derive_more::From; + +// Re-expose the errors we use from other crates here: +pub use crate::{ + metadata::{InvalidMetadataError, MetadataError}, + scale_value::{DecodeError, EncodeError}, +}; +pub use sp_core::crypto::SecretStringError; +pub use sp_runtime::transaction_validity::TransactionValidityError; + +mod dispatch_error; +pub use dispatch_error::*; + +/// The underlying error enum, generic over the type held by the `Runtime` +/// variant. Prefer to use the [`Error`] and [`Error`] aliases over +/// using this type directly. +#[derive(Debug, From)] +pub enum Error { + /// Codec error. + Codec(codec::Error), + /// Serde serialization error + Serialization(serde_json::error::Error), + /// Secret string error. + SecretString(SecretStringError), + /// Extrinsic validity error + Invalid(TransactionValidityError), + /// Invalid metadata error + InvalidMetadata(InvalidMetadataError), + /// Invalid metadata error + Metadata(MetadataError), + /// Runtime error. + Runtime(DispatchError), + /// Error decoding to a [`crate::dynamic::Value`]. + DecodeValue(DecodeError), + /// Error encoding from a [`crate::dynamic::Value`]. + EncodeValue(EncodeError), + /// Transaction progress error. + Transaction(TransactionError), + /// Block related error. + Block(BlockError), + /// An error encoding a storage address. + StorageAddress(StorageAddressError), + /// Other error. + Other(String), +} + +impl From<&str> for Error { + fn from(error: &str) -> Self { + Error::Other(error.into()) + } +} + +/// Block error +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum BlockError { + /// The block + BlockHashNotFound(String), +} + +impl BlockError { + /// Produce an error that a block with the given hash cannot be found. + pub fn block_hash_not_found(hash: impl AsRef<[u8]>) -> BlockError { + let hash = format!("0x{}", hex::encode(hash)); + BlockError::BlockHashNotFound(hash) + } +} + +/// Transaction error. +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum TransactionError { + /// The finality subscription expired (after ~512 blocks we give up if the + /// block hasn't yet been finalized). + FinalitySubscriptionTimeout, + /// The block hash that the transaction was added to could not be found. + /// This is probably because the block was retracted before being finalized. + BlockHashNotFound, +} + +/// Something went wrong trying to encode a storage address. +#[derive(Clone, Debug)] +pub enum StorageAddressError { + /// Storage map type must be a composite type. + MapTypeMustBeTuple, + /// Storage lookup does not have the expected number of keys. + WrongNumberOfKeys { + /// The actual number of keys needed, based on the metadata. + actual: usize, + /// The number of keys provided in the storage address. + expected: usize, + }, + /// Storage lookup requires a type that wasn't found in the metadata. + TypeNotFound(u32), + /// This storage entry in the metadata does not have the correct number of hashers to fields. + WrongNumberOfHashers { + /// The number of hashers in the metadata for this storage entry. + hashers: usize, + /// The number of fields in the metadata for this storage entry. + fields: usize, + }, +} diff --git a/node-api/src/events/event_details.rs b/node-api/src/events/event_details.rs new file mode 100644 index 000000000..dbb4c0d48 --- /dev/null +++ b/node-api/src/events/event_details.rs @@ -0,0 +1,214 @@ +/* + Copyright 2021 Integritee AG and Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +use crate::{ + error::{DispatchError, Error}, + metadata::EventMetadata, + scale_value::{decode_as_type, Composite, TypeId}, + Metadata, Phase, StaticEvent, +}; +use alloc::{string::ToString, sync::Arc, vec, vec::Vec}; +use codec::{Decode, Error as CodecError}; +use log::*; +use sp_core::H256; + +/// The event details. +#[derive(Debug, Clone)] +pub struct EventDetails { + phase: Phase, + index: u32, + all_bytes: Arc<[u8]>, + // start of the bytes (phase, pallet/variant index and then fields and then topic to follow). + start_idx: usize, + // start of the fields (ie after phase nad pallet/variant index). + fields_start_idx: usize, + // end of the fields. + fields_end_idx: usize, + // end of everything (fields + topics) + end_idx: usize, + metadata: Metadata, +} + +impl EventDetails { + // Attempt to dynamically decode a single event from our events input. + pub(crate) fn decode_from( + metadata: Metadata, + all_bytes: Arc<[u8]>, + start_idx: usize, + index: u32, + ) -> Result { + let input = &mut &all_bytes[start_idx..]; + + let phase = Phase::decode(input)?; + let pallet_index = u8::decode(input)?; + let variant_index = u8::decode(input)?; + + let fields_start_idx = all_bytes.len() - input.len(); + + // Get metadata for the event: + let event_metadata = metadata.event(pallet_index, variant_index)?; + debug!("Decoding Event '{}::{}'", event_metadata.pallet(), event_metadata.event()); + + // Skip over the bytes belonging to this event. + for field_metadata in event_metadata.fields() { + // Skip over the bytes for this field: + decode_as_type(input, field_metadata.type_id(), &metadata.runtime_metadata().types)?; + } + + // the end of the field bytes. + let fields_end_idx = all_bytes.len() - input.len(); + + // topics come after the event data in EventRecord. They aren't used for + // anything at the moment, so just decode and throw them away. + let _topics = Vec::::decode(input)?; + + // what bytes did we skip over in total, including topics. + let end_idx = all_bytes.len() - input.len(); + + Ok(EventDetails { + phase, + index, + start_idx, + fields_start_idx, + fields_end_idx, + end_idx, + all_bytes, + metadata, + }) + } + + /// When was the event produced? + pub fn phase(&self) -> Phase { + self.phase.clone() + } + + /// What index is this event in the stored events for this block. + pub fn index(&self) -> u32 { + self.index + } + + /// The index of the pallet that the event originated from. + pub fn pallet_index(&self) -> u8 { + // Note: never panics; we expect these bytes to exist + // in order that the EventDetails could be created. + self.all_bytes[self.fields_start_idx - 2] + } + + /// The index of the event variant that the event originated from. + pub fn variant_index(&self) -> u8 { + // Note: never panics; we expect these bytes to exist + // in order that the EventDetails could be created. + self.all_bytes[self.fields_start_idx - 1] + } + + /// The name of the pallet from whence the Event originated. + pub fn pallet_name(&self) -> &str { + self.event_metadata().pallet() + } + + /// The name of the event (ie the name of the variant that it corresponds to). + pub fn variant_name(&self) -> &str { + self.event_metadata().event() + } + + /// Fetch the metadata for this event. + pub fn event_metadata(&self) -> &EventMetadata { + self.metadata + .event(self.pallet_index(), self.variant_index()) + .expect("this must exist in order to have produced the EventDetails") + } + + /// Return _all_ of the bytes representing this event, which include, in order: + /// - The phase. + /// - Pallet and event index. + /// - Event fields. + /// - Event Topics. + pub fn bytes(&self) -> &[u8] { + &self.all_bytes[self.start_idx..self.end_idx] + } + + /// Return the bytes representing the fields stored in this event. + pub fn field_bytes(&self) -> &[u8] { + &self.all_bytes[self.fields_start_idx..self.fields_end_idx] + } + + /// Decode and provide the event fields back in the form of a [`scale_value::Composite`] + /// type which represents the named or unnamed fields that were + /// present in the event. + pub fn field_values(&self) -> Result, Error> { + let bytes = &mut self.field_bytes(); + let event_metadata = self.event_metadata(); + + // If the first field has a name, we assume that the rest do too (it'll either + // be a named struct or a tuple type). If no fields, assume unnamed. + let is_named = + event_metadata.fields().get(0).map(|fm| fm.name().is_some()).unwrap_or(false); + + if !is_named { + let mut event_values = vec![]; + for field_metadata in event_metadata.fields() { + let value = decode_as_type( + bytes, + field_metadata.type_id(), + &self.metadata.runtime_metadata().types, + )?; + event_values.push(value); + } + + Ok(Composite::Unnamed(event_values)) + } else { + let mut event_values = vec![]; + for field_metadata in event_metadata.fields() { + let value = decode_as_type( + bytes, + field_metadata.type_id(), + &self.metadata.runtime_metadata().types, + )?; + event_values.push((field_metadata.name().unwrap_or_default().to_string(), value)); + } + + Ok(Composite::Named(event_values)) + } + } + + /// Attempt to decode these [`EventDetails`] into a specific static event. + /// This targets the fields within the event directly. You can also attempt to + /// decode the entirety of the event type (including the pallet and event + /// variants) using [`EventDetails::as_root_event()`]. + pub fn as_event(&self) -> Result, CodecError> { + let ev_metadata = self.event_metadata(); + if ev_metadata.pallet() == E::PALLET && ev_metadata.event() == E::EVENT { + Ok(Some(E::decode(&mut self.field_bytes())?)) + } else { + Ok(None) + } + } + + /// Attempt to decode these [`EventDetails`] into a root event type (which includes + /// the pallet and event enum variants as well as the event fields). A compatible + /// type for this is exposed via static codegen as a root level `Event` type. + pub fn as_root_event(&self) -> Result { + E::decode(&mut self.bytes()) + } +} + +impl EventDetails { + /// Checks if the extrinsic has failed. If so, the corresponding DispatchError is returned. + pub fn check_if_failed(&self) -> Result<(), DispatchError> { + if self.pallet_name() == "System" && self.variant_name() == "ExtrinsicFailed" { + let dispatch_error = DispatchError::decode_from(self.field_bytes(), &self.metadata); + return Err(dispatch_error) + } + Ok(()) + } +} diff --git a/node-api/src/events.rs b/node-api/src/events/mod.rs similarity index 70% rename from node-api/src/events.rs rename to node-api/src/events/mod.rs index 858a88e26..b5ec21c2d 100644 --- a/node-api/src/events.rs +++ b/node-api/src/events/mod.rs @@ -11,16 +11,12 @@ //! This file is very similar to subxt, except where noted. //! Based on https://github.com/paritytech/subxt/commit/1e8d0956cc6aeb882637bde1d09ac44186181781# -use crate::{ - alloc::{string::ToString, sync::Arc, vec, vec::Vec}, - error::{DispatchError, Error}, - metadata::EventMetadata, - scale_value::{decode_as_type, Composite, TypeId}, - Metadata, Phase, StaticEvent, -}; -use codec::{Compact, Decode, Error as CodecError}; -use log::*; -use sp_core::H256; +use crate::{error::Error, Metadata, StaticEvent}; +use alloc::{sync::Arc, vec::Vec}; +use codec::{Compact, Decode}; + +mod event_details; +pub use event_details::EventDetails; /// A collection of events obtained from a block, bundled with the necessary /// information needed to decode and iterate over them. @@ -134,197 +130,6 @@ impl Events { } } -/// The event details. -#[derive(Debug, Clone)] -pub struct EventDetails { - phase: Phase, - index: u32, - all_bytes: Arc<[u8]>, - // start of the bytes (phase, pallet/variant index and then fields and then topic to follow). - start_idx: usize, - // start of the fields (ie after phase nad pallet/variant index). - fields_start_idx: usize, - // end of the fields. - fields_end_idx: usize, - // end of everything (fields + topics) - end_idx: usize, - metadata: Metadata, -} - -impl EventDetails { - // Attempt to dynamically decode a single event from our events input. - fn decode_from( - metadata: Metadata, - all_bytes: Arc<[u8]>, - start_idx: usize, - index: u32, - ) -> Result { - let input = &mut &all_bytes[start_idx..]; - - let phase = Phase::decode(input)?; - let pallet_index = u8::decode(input)?; - let variant_index = u8::decode(input)?; - - let fields_start_idx = all_bytes.len() - input.len(); - - // Get metadata for the event: - let event_metadata = metadata.event(pallet_index, variant_index)?; - debug!("Decoding Event '{}::{}'", event_metadata.pallet(), event_metadata.event()); - - // Skip over the bytes belonging to this event. - for field_metadata in event_metadata.fields() { - // Skip over the bytes for this field: - decode_as_type(input, field_metadata.type_id(), &metadata.runtime_metadata().types)?; - } - - // the end of the field bytes. - let fields_end_idx = all_bytes.len() - input.len(); - - // topics come after the event data in EventRecord. They aren't used for - // anything at the moment, so just decode and throw them away. - let _topics = Vec::::decode(input)?; - - // what bytes did we skip over in total, including topics. - let end_idx = all_bytes.len() - input.len(); - - Ok(EventDetails { - phase, - index, - start_idx, - fields_start_idx, - fields_end_idx, - end_idx, - all_bytes, - metadata, - }) - } - - /// When was the event produced? - pub fn phase(&self) -> Phase { - self.phase.clone() - } - - /// What index is this event in the stored events for this block. - pub fn index(&self) -> u32 { - self.index - } - - /// The index of the pallet that the event originated from. - pub fn pallet_index(&self) -> u8 { - // Note: never panics; we expect these bytes to exist - // in order that the EventDetails could be created. - self.all_bytes[self.fields_start_idx - 2] - } - - /// The index of the event variant that the event originated from. - pub fn variant_index(&self) -> u8 { - // Note: never panics; we expect these bytes to exist - // in order that the EventDetails could be created. - self.all_bytes[self.fields_start_idx - 1] - } - - /// The name of the pallet from whence the Event originated. - pub fn pallet_name(&self) -> &str { - self.event_metadata().pallet() - } - - /// The name of the event (ie the name of the variant that it corresponds to). - pub fn variant_name(&self) -> &str { - self.event_metadata().event() - } - - /// Fetch the metadata for this event. - pub fn event_metadata(&self) -> &EventMetadata { - self.metadata - .event(self.pallet_index(), self.variant_index()) - .expect("this must exist in order to have produced the EventDetails") - } - - /// Return _all_ of the bytes representing this event, which include, in order: - /// - The phase. - /// - Pallet and event index. - /// - Event fields. - /// - Event Topics. - pub fn bytes(&self) -> &[u8] { - &self.all_bytes[self.start_idx..self.end_idx] - } - - /// Return the bytes representing the fields stored in this event. - pub fn field_bytes(&self) -> &[u8] { - &self.all_bytes[self.fields_start_idx..self.fields_end_idx] - } - - /// Decode and provide the event fields back in the form of a [`scale_value::Composite`] - /// type which represents the named or unnamed fields that were - /// present in the event. - pub fn field_values(&self) -> Result, Error> { - let bytes = &mut self.field_bytes(); - let event_metadata = self.event_metadata(); - - // If the first field has a name, we assume that the rest do too (it'll either - // be a named struct or a tuple type). If no fields, assume unnamed. - let is_named = - event_metadata.fields().get(0).map(|fm| fm.name().is_some()).unwrap_or(false); - - if !is_named { - let mut event_values = vec![]; - for field_metadata in event_metadata.fields() { - let value = decode_as_type( - bytes, - field_metadata.type_id(), - &self.metadata.runtime_metadata().types, - )?; - event_values.push(value); - } - - Ok(Composite::Unnamed(event_values)) - } else { - let mut event_values = vec![]; - for field_metadata in event_metadata.fields() { - let value = decode_as_type( - bytes, - field_metadata.type_id(), - &self.metadata.runtime_metadata().types, - )?; - event_values.push((field_metadata.name().unwrap_or_default().to_string(), value)); - } - - Ok(Composite::Named(event_values)) - } - } - - /// Attempt to decode these [`EventDetails`] into a specific static event. - /// This targets the fields within the event directly. You can also attempt to - /// decode the entirety of the event type (including the pallet and event - /// variants) using [`EventDetails::as_root_event()`]. - pub fn as_event(&self) -> Result, CodecError> { - let ev_metadata = self.event_metadata(); - if ev_metadata.pallet() == E::PALLET && ev_metadata.event() == E::EVENT { - Ok(Some(E::decode(&mut self.field_bytes())?)) - } else { - Ok(None) - } - } - - /// Attempt to decode these [`EventDetails`] into a root event type (which includes - /// the pallet and event enum variants as well as the event fields). A compatible - /// type for this is exposed via static codegen as a root level `Event` type. - pub fn as_root_event(&self) -> Result { - E::decode(&mut self.bytes()) - } -} - -impl EventDetails { - /// Checks if the extrinsic has failed. If so, the corresponding DispatchError is returned. - pub fn check_if_failed(&self) -> Result<(), DispatchError> { - if self.pallet_name() == "System" && self.variant_name() == "ExtrinsicFailed" { - let dispatch_error = DispatchError::decode_from(self.field_bytes(), &self.metadata); - return Err(dispatch_error) - } - Ok(()) - } -} - #[cfg(test)] mod tests { use super::*; @@ -333,7 +138,9 @@ mod tests { test_utils::{ event_record, events, events_raw, metadata_with_version, SupportedMetadataVersions, }, + Phase, }; + use codec::Encode; use scale_info::TypeInfo; use test_case::test_case; diff --git a/node-api/src/lib.rs b/node-api/src/lib.rs index 210e05a8f..88ff0c1d6 100644 --- a/node-api/src/lib.rs +++ b/node-api/src/lib.rs @@ -26,7 +26,6 @@ pub use metadata::{Metadata, MetadataError}; pub mod error; pub mod events; -pub mod from_v14_to_v15; pub mod metadata; pub mod scale_value; pub mod storage; @@ -34,9 +33,6 @@ pub mod storage; #[cfg(any(feature = "mocks", test))] pub mod test_utils; -#[cfg(feature = "std")] -mod print_metadata; - /// Wraps an already encoded byte vector, prevents being encoded as a raw byte vector as part of /// the transaction payload #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] diff --git a/node-api/src/metadata/error.rs b/node-api/src/metadata/error.rs new file mode 100644 index 000000000..6d37c1cab --- /dev/null +++ b/node-api/src/metadata/error.rs @@ -0,0 +1,60 @@ +/* + Copyright 2021 Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +use alloc::string::String; +use codec::{Decode, Encode, Error as CodecError}; + +/// Metadata error originated from inspecting the internal representation of the runtime metadata. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum MetadataError { + /// Module is not in metadata. + PalletNotFound(String), + /// Pallet is not in metadata. + PalletIndexNotFound(u8), + /// Call is not in metadata. + CallNotFound(&'static str), + /// Event is not in metadata. + EventNotFound(u8, u8), + /// Error is not in metadata. + ErrorNotFound(u8, u8), + /// Storage is not in metadata. + StorageNotFound(&'static str), + /// Storage type does not match requested type. + StorageTypeError, + /// Default error. + DefaultError(CodecError), + /// Failure to decode constant value. + ConstantValueError(CodecError), + /// Constant is not in metadata. + ConstantNotFound(&'static str), + /// Type is not in metadata. + TypeNotFound(u32), + /// Runtime constant metadata is incompatible with the static one. + IncompatibleConstantMetadata(String, String), + /// Runtime call metadata is incompatible with the static one. + IncompatibleCallMetadata(String, String), + /// Runtime storage metadata is incompatible with the static one. + IncompatibleStorageMetadata(String, String), + /// Runtime metadata is not fully compatible with the static one. + IncompatibleMetadata, +} + +#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Encode, Decode)] +pub enum InvalidMetadataError { + InvalidPrefix, + InvalidVersion, + /// Type is missing from type registry. + MissingType(u32), + /// Type was not variant/enum type. + TypeDefNotVariant(u32), +} diff --git a/node-api/src/from_v14_to_v15.rs b/node-api/src/metadata/from_v14_to_v15.rs similarity index 100% rename from node-api/src/from_v14_to_v15.rs rename to node-api/src/metadata/from_v14_to_v15.rs diff --git a/node-api/src/metadata.rs b/node-api/src/metadata/metadata_types.rs similarity index 88% rename from node-api/src/metadata.rs rename to node-api/src/metadata/metadata_types.rs index 43c168423..c7dd114f8 100644 --- a/node-api/src/metadata.rs +++ b/node-api/src/metadata/metadata_types.rs @@ -11,9 +11,19 @@ //! This file is mostly subxt. use crate::{ - alloc::borrow::ToOwned, from_v14_to_v15::v14_to_v15, storage::GetStorageTypes, Encoded, + metadata::{v14_to_v15, InvalidMetadataError, MetadataError}, + storage::GetStorageTypes, + Encoded, }; -use codec::{Decode, Encode, Error as CodecError}; +use alloc::{ + borrow::ToOwned, + // We use `BTreeMap` because we can't use `HashMap` in `no_std`. + collections::btree_map::BTreeMap, + string::{String, ToString}, + vec, + vec::Vec, +}; +use codec::{Decode, Encode}; use frame_metadata::{ v15::{PalletConstantMetadata, RuntimeMetadataLastVersion, StorageEntryMetadata}, RuntimeMetadata, RuntimeMetadataPrefixed, META_RESERVED, @@ -24,49 +34,6 @@ use sp_storage::StorageKey; #[cfg(feature = "std")] use serde::Serialize; -use alloc::{ - // We use `BTreeMap` because we can't use `HashMap` in `no_std`. - collections::btree_map::BTreeMap, - string::{String, ToString}, - vec, - vec::Vec, -}; - -/// Metadata error originated from inspecting the internal representation of the runtime metadata. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum MetadataError { - /// Module is not in metadata. - PalletNotFound(String), - /// Pallet is not in metadata. - PalletIndexNotFound(u8), - /// Call is not in metadata. - CallNotFound(&'static str), - /// Event is not in metadata. - EventNotFound(u8, u8), - /// Error is not in metadata. - ErrorNotFound(u8, u8), - /// Storage is not in metadata. - StorageNotFound(&'static str), - /// Storage type does not match requested type. - StorageTypeError, - /// Default error. - DefaultError(CodecError), - /// Failure to decode constant value. - ConstantValueError(CodecError), - /// Constant is not in metadata. - ConstantNotFound(&'static str), - /// Type is not in metadata. - TypeNotFound(u32), - /// Runtime constant metadata is incompatible with the static one. - IncompatibleConstantMetadata(String, String), - /// Runtime call metadata is incompatible with the static one. - IncompatibleCallMetadata(String, String), - /// Runtime storage metadata is incompatible with the static one. - IncompatibleStorageMetadata(String, String), - /// Runtime metadata is not fully compatible with the static one. - IncompatibleMetadata, -} - /// Metadata wrapper around the runtime metadata. Offers some extra features, /// such as direct pallets, events and error access. #[derive(Clone, Debug, Encode, Decode)] @@ -318,16 +285,6 @@ impl ErrorMetadata { } } -#[derive(Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Encode, Decode)] -pub enum InvalidMetadataError { - InvalidPrefix, - InvalidVersion, - /// Type is missing from type registry. - MissingType(u32), - /// Type was not variant/enum type. - TypeDefNotVariant(u32), -} - impl TryFrom for Metadata { type Error = InvalidMetadataError; diff --git a/node-api/src/metadata/mod.rs b/node-api/src/metadata/mod.rs new file mode 100644 index 000000000..6641d66fa --- /dev/null +++ b/node-api/src/metadata/mod.rs @@ -0,0 +1,23 @@ +/* + Copyright 2021 Supercomputing Systems AG + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +mod error; +mod from_v14_to_v15; +mod metadata_types; + +pub use error::*; +pub use from_v14_to_v15::v14_to_v15; +pub use metadata_types::*; + +#[cfg(feature = "std")] +mod print_metadata; diff --git a/node-api/src/print_metadata.rs b/node-api/src/metadata/print_metadata.rs similarity index 100% rename from node-api/src/print_metadata.rs rename to node-api/src/metadata/print_metadata.rs