Get workspace compiling via 'cargo check'

This commit is contained in:
James Wilson
2025-12-12 12:30:42 +00:00
parent 6215b15fdf
commit 37d4cf7524
35 changed files with 179 additions and 131 deletions
+9 -2
View File
@@ -144,7 +144,7 @@ pub async fn run(opts: Opts, output: &mut impl std::io::Write) -> color_eyre::Re
// get the metadata
let file_or_url = opts.file_or_url;
let bytes = file_or_url.fetch().await?;
let metadata = Metadata::decode(&mut &bytes[..])?;
let metadata = Metadata::decode(&mut &bytes[..])?.arc();
let pallet_placeholder = "<PALLET>".blue();
let runtime_api_placeholder = "<RUNTIME_API>".blue();
@@ -185,7 +185,14 @@ pub async fn run(opts: Opts, output: &mut impl std::io::Write) -> color_eyre::Re
.pallets()
.find(|e| e.name().eq_ignore_ascii_case(&name))
{
pallets::run(opts.subcommand, pallet, &metadata, file_or_url, output).await
pallets::run(
opts.subcommand,
pallet,
metadata.clone(),
file_or_url,
output,
)
.await
} else {
Err(eyre!(
"pallet \"{name}\" not found in metadata!\n{}",
+17 -18
View File
@@ -5,14 +5,11 @@ use indoc::{formatdoc, writedoc};
use scale_info::form::PortableForm;
use scale_info::{PortableRegistry, Type, TypeDef, TypeDefVariant};
use scale_value::{Composite, ValueDef};
use std::str::FromStr;
use subxt::tx;
use subxt::utils::H256;
use subxt::{
OfflineClient,
OfflineClient, OfflineClientAtBlock,
config::SubstrateConfig,
metadata::{Metadata, PalletMetadata},
metadata::{ArcMetadata, PalletMetadata},
tx,
};
use crate::utils::{
@@ -30,7 +27,7 @@ pub struct CallsSubcommand {
pub fn explore_calls(
command: CallsSubcommand,
pallet_metadata: PalletMetadata,
metadata: &Metadata,
metadata: ArcMetadata,
output: &mut impl std::io::Write,
) -> color_eyre::Result<()> {
let pallet_name = pallet_metadata.name();
@@ -148,18 +145,20 @@ fn get_calls_enum_type<'a>(
Ok((calls_enum_type_def, calls_enum_type))
}
/// The specific values used for construction do not matter too much, we just need any OfflineClient to create unsigned extrinsics
fn mocked_offline_client(metadata: Metadata) -> OfflineClient<SubstrateConfig> {
let genesis_hash =
H256::from_str("91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3")
.expect("Valid hash; qed");
/// We don't care about any specific genesis hash etc; we just need any OfflineClient to create unsigned extrinsics
fn mocked_offline_client(metadata: ArcMetadata) -> OfflineClientAtBlock<SubstrateConfig> {
let config = SubstrateConfig::builder()
.set_spec_version_for_block_ranges([subxt::config::substrate::SpecVersionForRange {
block_range: 0..1,
spec_version: 1,
transaction_version: 1,
}])
.set_metadata_for_spec_versions([(1, metadata)])
.build();
let runtime_version = subxt::client::RuntimeVersion {
spec_version: 9370,
transaction_version: 20,
};
OfflineClient::<SubstrateConfig>::new(genesis_hash, runtime_version, metadata)
OfflineClient::<SubstrateConfig>::new(config)
.at_block(0u64)
.expect("Should not fail since we plugged consistent data into the config")
}
/// composites stay composites, all other types are converted into a 1-fielded unnamed composite
@@ -2,7 +2,7 @@ use clap::Args;
use color_eyre::eyre::eyre;
use indoc::{formatdoc, writedoc};
use scale_typegen_description::type_description;
use subxt::metadata::{Metadata, PalletMetadata};
use subxt::metadata::{ArcMetadata, PalletMetadata};
use crate::utils::{Indent, SyntaxHighlight, first_paragraph_of_docs, format_scale_value};
@@ -14,7 +14,7 @@ pub struct ConstantsSubcommand {
pub fn explore_constants(
command: ConstantsSubcommand,
pallet_metadata: PalletMetadata,
metadata: &Metadata,
metadata: ArcMetadata,
output: &mut impl std::io::Write,
) -> color_eyre::Result<()> {
let pallet_name = pallet_metadata.name();
+2 -2
View File
@@ -2,7 +2,7 @@ use clap::Args;
use color_eyre::eyre::eyre;
use indoc::{formatdoc, writedoc};
use scale_info::{Variant, form::PortableForm};
use subxt::metadata::{Metadata, PalletMetadata};
use subxt::metadata::{ArcMetadata, PalletMetadata};
use crate::utils::{Indent, fields_description, first_paragraph_of_docs};
@@ -14,7 +14,7 @@ pub struct EventsSubcommand {
pub fn explore_events(
command: EventsSubcommand,
pallet_metadata: PalletMetadata,
metadata: &Metadata,
metadata: ArcMetadata,
output: &mut impl std::io::Write,
) -> color_eyre::Result<()> {
let pallet_name = pallet_metadata.name();
+2 -2
View File
@@ -1,7 +1,7 @@
use clap::Subcommand;
use indoc::writedoc;
use subxt::Metadata;
use subxt::ArcMetadata;
use subxt_metadata::PalletMetadata;
use crate::utils::{FileOrUrl, Indent, first_paragraph_of_docs};
@@ -33,7 +33,7 @@ pub enum PalletSubcommand {
pub async fn run<'a>(
subcommand: Option<PalletSubcommand>,
pallet_metadata: PalletMetadata<'a>,
metadata: &'a Metadata,
metadata: ArcMetadata,
file_or_url: FileOrUrl,
output: &mut impl std::io::Write,
) -> color_eyre::Result<()> {
+4 -4
View File
@@ -5,7 +5,7 @@ use scale_typegen_description::type_description;
use scale_value::Value;
use std::fmt::Write;
use std::write;
use subxt::metadata::{Metadata, PalletMetadata, StorageMetadata};
use subxt::metadata::{ArcMetadata, PalletMetadata, StorageMetadata};
use crate::utils::{
FileOrUrl, Indent, SyntaxHighlight, create_client, first_paragraph_of_docs,
@@ -24,7 +24,7 @@ pub struct StorageSubcommand {
pub async fn explore_storage(
command: StorageSubcommand,
pallet_metadata: PalletMetadata<'_>,
metadata: &Metadata,
metadata: ArcMetadata,
file_or_url: FileOrUrl,
output: &mut impl std::io::Write,
) -> color_eyre::Result<()> {
@@ -197,9 +197,9 @@ pub async fn explore_storage(
// Fetch the value:
let storage_value = client
.storage()
.at_latest()
.at_current_block()
.await?
.storage()
.fetch((pallet_name, storage.name()), storage_entry_keys)
.await?
.decode()?;
+2 -2
View File
@@ -172,9 +172,9 @@ pub async fn run<'a>(
subxt::dynamic::runtime_api_call::<_, Value>(api_name, method.name(), args_data);
let client = create_client(&file_or_url).await?;
let output_value = client
.runtime_api()
.at_latest()
.at_current_block()
.await?
.runtime_apis()
.call(method_call)
.await?;
+4 -3
View File
@@ -232,9 +232,10 @@ impl<T: Display> Indent for T {}
pub async fn create_client(
file_or_url: &FileOrUrl,
) -> color_eyre::Result<OnlineClient<PolkadotConfig>> {
let config = PolkadotConfig::new();
let client = match &file_or_url.url {
Some(url) => OnlineClient::<PolkadotConfig>::from_url(url).await?,
None => OnlineClient::<PolkadotConfig>::new().await?,
Some(url) => OnlineClient::<PolkadotConfig>::from_url(config, url).await?,
None => OnlineClient::<PolkadotConfig>::new(config).await?,
};
Ok(client)
}
@@ -326,7 +327,7 @@ pub fn validate_url_security(url: Option<&Url>, allow_insecure: bool) -> color_e
let Some(url) = url else {
return Ok(());
};
match subxt::utils::url_is_secure(url.as_str()) {
match subxt::ext::subxt_rpcs::utils::url_is_secure(url.as_str()) {
Ok(is_secure) => {
if !allow_insecure && !is_secure {
bail!(
+2 -2
View File
@@ -92,8 +92,8 @@ pub fn generate_calls(
pub fn #fn_name(
&self,
#( #call_fn_args, )*
) -> #crate_path::transactions::payload::StaticPayload<types::#struct_name> {
#crate_path::transactions::payload::StaticPayload::new_static(
) -> #crate_path::transactions::StaticPayload<types::#struct_name> {
#crate_path::transactions::StaticPayload::new_static(
#pallet_name,
#call_name,
types::#struct_name { #( #call_args, )* },
+2 -2
View File
@@ -68,8 +68,8 @@ pub fn generate_constants(
Ok(quote! {
#docs
pub fn #fn_name(&self) -> #crate_path::constants::address::StaticAddress<#return_ty> {
#crate_path::constants::address::StaticAddress::new_static(
pub fn #fn_name(&self) -> #crate_path::constants::StaticAddress<#return_ty> {
#crate_path::constants::StaticAddress::new_static(
#pallet_name,
#constant_name,
[#(#constant_hash,)*]
+2 -2
View File
@@ -71,8 +71,8 @@ fn generate_custom_value_fn(
};
Some(quote!(
pub fn #fn_name_ident(&self) -> #crate_path::custom_values::address::StaticAddress<#return_ty, #decodable> {
#crate_path::custom_values::address::StaticAddress::new_static(#name, [#(#custom_value_hash,)*])
pub fn #fn_name_ident(&self) -> #crate_path::custom_values::StaticAddress<#return_ty, #decodable> {
#crate_path::custom_values::StaticAddress::new_static(#name, [#(#custom_value_hash,)*])
}
))
}
+2 -2
View File
@@ -167,11 +167,11 @@ fn generate_pallet_view_function(
pub fn #view_function_name_ident(
&self,
#(#input_args),*
) -> #crate_path::view_functions::payload::StaticPayload<
) -> #crate_path::view_functions::StaticPayload<
(#(#input_tuple_types,)*),
#view_function_name_ident::output::Output
> {
#crate_path::view_functions::payload::StaticPayload::new_static(
#crate_path::view_functions::StaticPayload::new_static(
#pallet_name,
#view_function_name_str,
(#(#input_param_names,)*),
+2 -2
View File
@@ -183,11 +183,11 @@ fn generate_runtime_api(
pub fn #method_name(
&self,
#(#input_args),*
) -> #crate_path::runtime_apis::payload::StaticPayload<
) -> #crate_path::runtime_apis::StaticPayload<
(#(#input_tuple_types,)*),
#method_name::output::Output
> {
#crate_path::runtime_apis::payload::StaticPayload::new_static(
#crate_path::runtime_apis::StaticPayload::new_static(
#trait_name_str,
#method_name_str,
(#(#input_param_names,)*),
+2 -2
View File
@@ -153,12 +153,12 @@ fn generate_storage_entry_fns(
let storage_entry_method = quote!(
#docs
pub fn #storage_entry_snake_case_ident(&self) -> #crate_path::storage::address::StaticAddress<
pub fn #storage_entry_snake_case_ident(&self) -> #crate_path::storage::StaticAddress<
(#(#storage_key_tuple_types,)*),
#storage_entry_snake_case_ident::output::Output,
#is_plain
> {
#crate_path::storage::address::StaticAddress::new_static(
#crate_path::storage::StaticAddress::new_static(
#pallet_name,
#storage_entry_name_str,
[#(#validation_hash,)*],
+10
View File
@@ -25,6 +25,7 @@ mod utils;
use alloc::borrow::Cow;
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
use alloc::sync::Arc;
use alloc::vec::Vec;
use frame_decode::constants::{ConstantEntry, ConstantInfo, ConstantInfoError};
use frame_decode::custom_values::{CustomValue, CustomValueInfo, CustomValueInfoError};
@@ -58,6 +59,9 @@ pub use from::legacy::Error as LegacyFromError;
type CustomMetadataInner = frame_metadata::v15::CustomMetadata<PortableForm>;
/// Metadata is often passed around wrapped in an [`Arc`] so that it can be cheaply cloned.
pub type ArcMetadata = Arc<Metadata>;
/// Node metadata. This can be constructed by providing some compatible [`frame_metadata`]
/// which is then decoded into this. We aim to preserve all of the existing information in
/// the incoming metadata while optimizing the format a little for Subxt's use cases.
@@ -370,6 +374,12 @@ impl frame_decode::custom_values::CustomValueEntryInfo for Metadata {
}
impl Metadata {
/// Metadata tends to be passed around wrapped in an [`Arc`] so that it can be
/// cheaply cloned. This is a shorthand to return that.
pub fn arc(self) -> ArcMetadata {
Arc::new(self)
}
/// This is essentially an alias for `<Metadata as codec::Decode>::decode(&mut bytes)`
pub fn decode_from(mut bytes: &[u8]) -> Result<Self, codec::Error> {
<Self as codec::Decode>::decode(&mut bytes)
+2 -2
View File
@@ -365,9 +365,9 @@ mod test {
use bip39::Mnemonic;
use proptest::prelude::*;
use secp256k1::Secp256k1;
use subxt::utils::AccountId20;
use subxt::transactions::Signer as SignerT;
use subxt::config::{Config, HashFor, substrate};
use subxt::transactions::Signer as SignerT;
use subxt::utils::AccountId20;
use super::*;
+12 -3
View File
@@ -14,12 +14,15 @@ use crate::view_functions::ViewFunctionsClient;
use core::marker::PhantomData;
use subxt_metadata::Metadata;
pub use offline_client::{OfflineClient, OfflineClientAtBlock, OfflineClientAtBlockT};
pub use offline_client::{OfflineClient, OfflineClientAtBlockImpl, OfflineClientAtBlockT};
pub use online_client::{
BlockNumberOrRef, OnlineClient, OnlineClientAtBlock, OnlineClientAtBlockT,
BlockNumberOrRef, OnlineClient, OnlineClientAtBlockImpl, OnlineClientAtBlockT,
};
/// This represents a client at a specific block number.
/// This represents a client at a specific block number. This wraps a client impl
/// which will either be [`OfflineClientAtBlockImpl`] or [`OnlineClientAtBlockImpl`].
/// Prefer to use the type aliases [`OfflineClientAtBlock`] and [`OnlineClientAtBlock`]
/// if you need to refer to the concrete instances of this.
#[derive(Clone, Debug)]
pub struct ClientAtBlock<T, Client> {
pub(crate) client: Client,
@@ -125,3 +128,9 @@ where
Ok(header)
}
}
/// An offline client at a specific block.
pub type OfflineClientAtBlock<T> = ClientAtBlock<T, OfflineClientAtBlockImpl<T>>;
/// An online client at a specific block.
pub type OnlineClientAtBlock<T> = ClientAtBlock<T, OnlineClientAtBlockImpl<T>>;
+7 -4
View File
@@ -20,7 +20,7 @@ impl<T: Config> OfflineClient<T> {
pub fn at_block(
&self,
block_number: impl Into<u64>,
) -> Result<ClientAtBlock<T, OfflineClientAtBlock<T>>, OfflineClientAtBlockError> {
) -> Result<ClientAtBlock<T, OfflineClientAtBlockImpl<T>>, OfflineClientAtBlockError> {
let block_number = block_number.into();
let (spec_version, transaction_version) = self
.config
@@ -36,7 +36,7 @@ impl<T: Config> OfflineClient<T> {
let hasher = <T::Hasher as Hasher>::new(&metadata);
let offline_client_at_block = OfflineClientAtBlock {
let offline_client_at_block = OfflineClientAtBlockImpl {
metadata,
block_number,
genesis_hash,
@@ -49,8 +49,11 @@ impl<T: Config> OfflineClient<T> {
}
}
/// An implementation of the [`OfflineClientAtBlockT`] trait, which is used in conjunction
/// with [`crate::client::ClientAtBlock`] to provide a working client. You won't tend to need this
/// type and instead should prefer to refer to [`crate::client::OfflineClientAtBlock`].
#[derive(Clone)]
pub struct OfflineClientAtBlock<T: Config> {
pub struct OfflineClientAtBlockImpl<T: Config> {
metadata: ArcMetadata,
block_number: u64,
genesis_hash: Option<HashFor<T>>,
@@ -81,7 +84,7 @@ pub trait OfflineClientAtBlockT<T: Config>: Clone {
fn transaction_version(&self) -> u32;
}
impl<T: Config> OfflineClientAtBlockT<T> for OfflineClientAtBlock<T> {
impl<T: Config> OfflineClientAtBlockT<T> for OfflineClientAtBlockImpl<T> {
fn metadata_ref(&self) -> &Metadata {
&self.metadata
}
+11 -22
View File
@@ -65,10 +65,7 @@ impl<T: Config> OnlineClient<T> {
url: impl AsRef<str>,
) -> Result<OnlineClient<T>, OnlineClientError> {
let url_str = url.as_ref();
let url = url::Url::parse(url_str).map_err(|_| OnlineClientError::InvalidUrl {
url: url_str.to_string(),
})?;
if !Self::is_url_secure(&url) {
if !subxt_rpcs::utils::url_is_secure(url_str).map_err(OnlineClientError::RpcError)? {
return Err(OnlineClientError::RpcError(subxt_rpcs::Error::InsecureUrl(
url_str.to_string(),
)));
@@ -88,16 +85,6 @@ impl<T: Config> OnlineClient<T> {
OnlineClient::from_rpc_client(config, rpc_client).await
}
fn is_url_secure(url: &url::Url) -> bool {
let secure_scheme = url.scheme() == "https" || url.scheme() == "wss";
let is_localhost = url.host().is_some_and(|e| match e {
url::Host::Domain(e) => e == "localhost",
url::Host::Ipv4(e) => e.is_loopback(),
url::Host::Ipv6(e) => e.is_loopback(),
});
secure_scheme || is_localhost
}
/// Construct a new [`OnlineClient`] by providing an [`RpcClient`] to drive the connection.
/// This will use the current default [`Backend`], which may change in future releases.
#[cfg(all(feature = "jsonrpsee", feature = "runtime"))]
@@ -210,7 +197,7 @@ impl<T: Config> OnlineClient<T> {
/// This does not track new blocks.
pub async fn at_current_block(
&self,
) -> Result<ClientAtBlock<T, OnlineClientAtBlock<T>>, OnlineClientAtBlockError> {
) -> Result<ClientAtBlock<T, OnlineClientAtBlockImpl<T>>, OnlineClientAtBlockError> {
let latest_block = self
.inner
.backend
@@ -225,7 +212,7 @@ impl<T: Config> OnlineClient<T> {
pub async fn at_block(
&self,
number_or_hash: impl Into<BlockNumberOrRef<T>>,
) -> Result<ClientAtBlock<T, OnlineClientAtBlock<T>>, OnlineClientAtBlockError> {
) -> Result<ClientAtBlock<T, OnlineClientAtBlockImpl<T>>, OnlineClientAtBlockError> {
let number_or_hash = number_or_hash.into();
// We are given either a block hash or number. We need both.
@@ -274,7 +261,7 @@ impl<T: Config> OnlineClient<T> {
&self,
block_ref: impl Into<BlockRef<HashFor<T>>>,
block_number: u64,
) -> Result<ClientAtBlock<T, OnlineClientAtBlock<T>>, OnlineClientAtBlockError> {
) -> Result<ClientAtBlock<T, OnlineClientAtBlockImpl<T>>, OnlineClientAtBlockError> {
let block_ref = block_ref.into();
let block_hash = block_ref.hash();
@@ -427,7 +414,7 @@ impl<T: Config> OnlineClient<T> {
}
};
let online_client_at_block = OnlineClientAtBlock {
let online_client_at_block = OnlineClientAtBlockImpl {
client: self.clone(),
hasher: <T::Hasher as Hasher>::new(&metadata),
metadata,
@@ -458,9 +445,11 @@ pub trait OnlineClientAtBlockT<T: Config>: OfflineClientAtBlockT<T> {
) -> impl Future<Output = Result<ClientAtBlock<T, Self>, OnlineClientAtBlockError>>;
}
/// The inner type providing the necessary data to work online at a specific block.
/// An implementation of the [`OnlineClientAtBlockImpl`] trait, which is used in conjunction
/// with [`crate::client::ClientAtBlock`] to provide a working client. You won't tend to need this
/// type and instead should prefer to refer to [`crate::client::OnlineClientAtBlock`].
#[derive(Clone)]
pub struct OnlineClientAtBlock<T: Config> {
pub struct OnlineClientAtBlockImpl<T: Config> {
client: OnlineClient<T>,
metadata: ArcMetadata,
hasher: T::Hasher,
@@ -470,7 +459,7 @@ pub struct OnlineClientAtBlock<T: Config> {
transaction_version: u32,
}
impl<T: Config> OnlineClientAtBlockT<T> for OnlineClientAtBlock<T> {
impl<T: Config> OnlineClientAtBlockT<T> for OnlineClientAtBlockImpl<T> {
fn backend(&self) -> &dyn Backend<T> {
&*self.client.inner.backend
}
@@ -485,7 +474,7 @@ impl<T: Config> OnlineClientAtBlockT<T> for OnlineClientAtBlock<T> {
}
}
impl<T: Config> OfflineClientAtBlockT<T> for OnlineClientAtBlock<T> {
impl<T: Config> OfflineClientAtBlockT<T> for OnlineClientAtBlockImpl<T> {
fn metadata_ref(&self) -> &Metadata {
&self.metadata
}
+2 -2
View File
@@ -1,5 +1,5 @@
use crate::backend::{BlockRef, StreamOfResults};
use crate::client::{ClientAtBlock, OnlineClient, OnlineClientAtBlock};
use crate::client::{ClientAtBlock, OnlineClient, OnlineClientAtBlockImpl};
use crate::config::{Config, HashFor, Header};
use crate::error::{BlocksError, OnlineClientAtBlockError};
use futures::{Stream, StreamExt};
@@ -70,7 +70,7 @@ impl<T: Config> Block<T> {
/// Instantiate a client at this block.
pub async fn client(
&self,
) -> Result<ClientAtBlock<T, OnlineClientAtBlock<T>>, OnlineClientAtBlockError> {
) -> Result<ClientAtBlock<T, OnlineClientAtBlockImpl<T>>, OnlineClientAtBlockError> {
self.client.at_block(self.block_ref.clone()).await
}
}
+2 -2
View File
@@ -35,7 +35,7 @@ impl PolkadotConfigBuilder {
/// Set the metadata to be used for decoding blocks at the given spec versions.
pub fn set_metadata_for_spec_versions(
mut self,
ranges: impl Iterator<Item = (u32, ArcMetadata)>,
ranges: impl IntoIterator<Item = (u32, ArcMetadata)>,
) -> Self {
self = Self(self.0.set_metadata_for_spec_versions(ranges));
self
@@ -45,7 +45,7 @@ impl PolkadotConfigBuilder {
/// to this configuration.
pub fn set_spec_version_for_block_ranges(
mut self,
ranges: impl Iterator<Item = SpecVersionForRange>,
ranges: impl IntoIterator<Item = SpecVersionForRange>,
) -> Self {
self = Self(self.0.set_spec_version_for_block_ranges(ranges));
self
+4 -4
View File
@@ -60,10 +60,10 @@ impl SubstrateConfigBuilder {
/// Set the metadata to be used for decoding blocks at the given spec versions.
pub fn set_metadata_for_spec_versions(
self,
ranges: impl Iterator<Item = (u32, ArcMetadata)>,
ranges: impl IntoIterator<Item = (u32, ArcMetadata)>,
) -> Self {
let mut map = self.metadata_for_spec_version.lock().unwrap();
for (spec_version, metadata) in ranges {
for (spec_version, metadata) in ranges.into_iter() {
map.insert(spec_version, metadata);
}
drop(map);
@@ -74,10 +74,10 @@ impl SubstrateConfigBuilder {
/// to this configuration.
pub fn set_spec_version_for_block_ranges(
mut self,
ranges: impl Iterator<Item = SpecVersionForRange>,
ranges: impl IntoIterator<Item = SpecVersionForRange>,
) -> Self {
let mut m = RangeMap::builder();
for version_for_range in ranges {
for version_for_range in ranges.into_iter() {
let start = version_for_range.block_range.start;
let end = version_for_range.block_range.end;
let spec_version = version_for_range.spec_version;
+3 -2
View File
@@ -1,12 +1,13 @@
mod address;
use crate::client::OfflineClientAtBlockT;
use crate::config::Config;
use crate::error::ConstantError;
use address::Address;
use frame_decode::constants::ConstantTypeInfo;
use scale_decode::IntoVisitor;
use std::marker::PhantomData;
pub mod address;
pub use address::{Address, DynamicAddress, StaticAddress, dynamic};
/// A client for working with storage entries.
#[derive(Clone)]
+3 -2
View File
@@ -1,13 +1,14 @@
mod address;
use crate::client::OfflineClientAtBlockT;
use crate::config::Config;
use crate::error::CustomValueError;
use crate::utils::Maybe;
use address::Address;
use derive_where::derive_where;
use frame_decode::custom_values::CustomValueTypeInfo;
use scale_decode::IntoVisitor;
pub mod address;
pub use address::{Address, DynamicAddress, StaticAddress, dynamic};
/// A client for accessing custom values stored in the metadata.
#[derive_where(Clone; Client)]
+1 -3
View File
@@ -4,13 +4,11 @@
//! Construct addresses to access custom values with.
use crate::utils::{Maybe, NoMaybe};
use derive_where::derive_where;
use scale_decode::DecodeAsType;
use std::borrow::Cow;
/// Use this with [`Address::IsDecodable`].
pub use crate::utils::{Maybe, No, NoMaybe};
/// This represents the address of a custom value in the metadata.
/// Anything that implements it can be used to fetch custom values from the metadata.
/// The trait is implemented by [`str`] for dynamic lookup and [`StaticAddress`] for static queries.
+7 -6
View File
@@ -7,19 +7,20 @@
pub use scale_value::{At, Value, value};
// Submit dynamic transactions.
pub use crate::transactions::payload::dynamic as transaction;
pub use crate::transactions::dynamic as transaction;
pub use crate::transactions::dynamic as tx;
// Lookup constants dynamically.
pub use crate::constants::address::dynamic as constant;
pub use crate::constants::dynamic as constant;
// Lookup storage values dynamically.
pub use crate::storage::address::dynamic as storage;
pub use crate::storage::dynamic as storage;
// Execute runtime API function call dynamically.
pub use crate::runtime_apis::payload::dynamic as runtime_api_call;
pub use crate::runtime_apis::dynamic as runtime_api_call;
// Execute View Function API function call dynamically.
pub use crate::view_functions::payload::dynamic as view_function_call;
pub use crate::view_functions::dynamic as view_function_call;
/// Obtain a custom value from the metadata.
pub use crate::custom_values::address::dynamic as custom_value;
pub use crate::custom_values::dynamic as custom_value;
+8 -2
View File
@@ -47,17 +47,23 @@ pub mod dynamic;
pub mod error;
pub mod events;
pub mod extrinsics;
pub mod metadata;
pub mod runtime_apis;
pub mod storage;
pub mod transactions;
pub mod utils;
pub mod view_functions;
// Re-export the [`subxt_metadata`] crate.
pub use subxt_metadata as metadata;
// A shorthand to match previous versions and the
// tx shorthand in other places.
pub use transactions as tx;
// Expose a few of the most common types at root,
// but leave most types behind their respective modules.
pub use crate::{
client::{OfflineClient, OnlineClient},
client::{OfflineClient, OfflineClientAtBlock, OnlineClient, OnlineClientAtBlock},
config::{Config, PolkadotConfig, SubstrateConfig},
error::Error,
metadata::{ArcMetadata, Metadata},
-7
View File
@@ -1,7 +0,0 @@
use std::sync::Arc;
// Re-export everything from subxt-metadata here.
pub use subxt_metadata::*;
/// A cheaply clonable version of our [`Metadata`].
pub type ArcMetadata = Arc<Metadata>;
+3 -2
View File
@@ -2,15 +2,16 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
mod payload;
use crate::client::{OfflineClientAtBlockT, OnlineClientAtBlockT};
use crate::config::Config;
use crate::error::RuntimeApiError;
use derive_where::derive_where;
use payload::Payload;
use scale_decode::IntoVisitor;
use std::marker::PhantomData;
pub mod payload;
pub use payload::{DynamicPayload, Payload, StaticPayload, dynamic};
/// Execute runtime API calls.
#[derive_where(Clone; Client)]
+2 -2
View File
@@ -1,3 +1,4 @@
mod address;
mod prefix_of;
mod storage_entry;
mod storage_key;
@@ -8,18 +9,17 @@ use crate::backend::BackendExt;
use crate::client::{OfflineClientAtBlockT, OnlineClientAtBlockT};
use crate::config::Config;
use crate::error::StorageError;
use address::Address;
use core::marker::PhantomData;
use frame_decode::helpers::Entry;
use frame_decode::storage::StorageEntryInfo;
use std::borrow::Cow;
pub use address::{Address, DynamicAddress, StaticAddress, dynamic};
pub use prefix_of::PrefixOf;
pub use storage_entry::StorageEntry;
pub use storage_key::{StorageKey, StorageKeyPart};
pub use storage_key_value::StorageKeyValue;
pub use storage_value::StorageValue;
pub mod address;
/// A client for working with storage entries.
#[derive(Clone)]
+2 -3
View File
@@ -1,11 +1,10 @@
mod account_nonce;
mod default_params;
mod payload;
mod signer;
mod transaction_progress;
mod validation_result;
pub mod payload;
use crate::backend::{BackendExt, TransactionStatus as BackendTransactionStatus};
use crate::client::{OfflineClientAtBlockT, OnlineClientAtBlockT};
use crate::config::extrinsic_params::Params;
@@ -20,7 +19,7 @@ use sp_crypto_hashing::blake2_256;
use std::borrow::Cow;
pub use default_params::DefaultParams;
pub use payload::Payload;
pub use payload::{DynamicPayload, Payload, StaticPayload, dynamic};
pub use signer::Signer;
pub use transaction_progress::{TransactionProgress, TransactionStatus};
pub use validation_result::{
+3 -2
View File
@@ -2,15 +2,16 @@
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
// see LICENSE for license details.
mod payload;
use crate::client::{OfflineClientAtBlockT, OnlineClientAtBlockT};
use crate::config::Config;
use crate::error::ViewFunctionError;
use derive_where::derive_where;
use payload::Payload;
use scale_decode::IntoVisitor;
use std::marker::PhantomData;
pub mod payload;
pub use payload::{DynamicPayload, Payload, StaticPayload, dynamic};
/// The name of the Runtime API call which can execute
const CALL_NAME: &str = "RuntimeViewFunction_execute_view_function";
+1 -1
View File
@@ -193,4 +193,4 @@ mod test {
);
}
}
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ mod error;
#[cfg(feature = "url")]
mod url;
#[cfg(feature = "url")]
pub use url::{from_url, from_url_blocking, MetadataVersion, Url};
pub use url::{MetadataVersion, Url, from_url, from_url_blocking};
pub use error::Error;
+41 -12
View File
@@ -5,7 +5,7 @@
//! Fetch metadata from a URL.
use crate::Error;
use codec::{Decode, Encode};
use codec::{Decode, Encode};
use jsonrpsee::{
core::client::ClientT, http_client::HttpClientBuilder, rpc_params, ws_client::WsClientBuilder,
};
@@ -44,7 +44,11 @@ impl std::str::FromStr for MetadataVersion {
}
/// Returns the metadata bytes from the provided URL.
pub async fn from_url(url: Url, version: MetadataVersion, at_block_hash: Option<&str>) -> Result<Vec<u8>, Error> {
pub async fn from_url(
url: Url,
version: MetadataVersion,
at_block_hash: Option<&str>,
) -> Result<Vec<u8>, Error> {
let bytes = match url.scheme() {
"http" | "https" => fetch_metadata_http(url, version, at_block_hash).await,
"ws" | "wss" => fetch_metadata_ws(url, version, at_block_hash).await,
@@ -55,7 +59,11 @@ pub async fn from_url(url: Url, version: MetadataVersion, at_block_hash: Option<
}
/// Returns the metadata bytes from the provided URL, blocking the current thread.
pub fn from_url_blocking(url: Url, version: MetadataVersion, at_block_hash: Option<&str>) -> Result<Vec<u8>, Error> {
pub fn from_url_blocking(
url: Url,
version: MetadataVersion,
at_block_hash: Option<&str>,
) -> Result<Vec<u8>, Error> {
tokio_block_on(from_url(url, version, at_block_hash))
}
@@ -68,7 +76,11 @@ fn tokio_block_on<T, Fut: std::future::Future<Output = T>>(fut: Fut) -> T {
.block_on(fut)
}
async fn fetch_metadata_ws(url: Url, version: MetadataVersion, at_block_hash: Option<&str>) -> Result<Vec<u8>, Error> {
async fn fetch_metadata_ws(
url: Url,
version: MetadataVersion,
at_block_hash: Option<&str>,
) -> Result<Vec<u8>, Error> {
let client = WsClientBuilder::default()
.request_timeout(std::time::Duration::from_secs(180))
.max_buffer_capacity_per_subscription(4096)
@@ -78,7 +90,11 @@ async fn fetch_metadata_ws(url: Url, version: MetadataVersion, at_block_hash: Op
fetch_metadata(client, version, at_block_hash).await
}
async fn fetch_metadata_http(url: Url, version: MetadataVersion, at_block_hash: Option<&str>) -> Result<Vec<u8>, Error> {
async fn fetch_metadata_http(
url: Url,
version: MetadataVersion,
at_block_hash: Option<&str>,
) -> Result<Vec<u8>, Error> {
let client = HttpClientBuilder::default()
.request_timeout(std::time::Duration::from_secs(180))
.build(url)?;
@@ -87,12 +103,16 @@ async fn fetch_metadata_http(url: Url, version: MetadataVersion, at_block_hash:
}
/// The innermost call to fetch metadata:
async fn fetch_metadata(client: impl ClientT, version: MetadataVersion, at_block_hash: Option<&str>) -> Result<Vec<u8>, Error> {
async fn fetch_metadata(
client: impl ClientT,
version: MetadataVersion,
at_block_hash: Option<&str>,
) -> Result<Vec<u8>, Error> {
const UNSTABLE_METADATA_VERSION: u32 = u32::MAX;
// Ensure always 0x prefix.
let at_block_hash = at_block_hash
.map(|hash| format!("0x{}", hash.strip_prefix("0x").unwrap_or(hash)));
let at_block_hash =
at_block_hash.map(|hash| format!("0x{}", hash.strip_prefix("0x").unwrap_or(hash)));
let at_block_hash = at_block_hash.as_deref();
// Fetch available metadata versions. If error, revert to legacy metadata code.
@@ -101,7 +121,10 @@ async fn fetch_metadata(client: impl ClientT, version: MetadataVersion, at_block
at_block_hash: Option<&str>,
) -> Result<Vec<u32>, Error> {
let res: String = client
.request("state_call", rpc_params!["Metadata_metadata_versions", "0x", at_block_hash])
.request(
"state_call",
rpc_params!["Metadata_metadata_versions", "0x", at_block_hash],
)
.await?;
let raw_bytes = hex::decode(res.trim_start_matches("0x"))?;
Decode::decode(&mut &raw_bytes[..]).map_err(Into::into)
@@ -170,7 +193,10 @@ async fn fetch_metadata(client: impl ClientT, version: MetadataVersion, at_block
) -> Result<Vec<u8>, Error> {
// Fetch the metadata.
let metadata_string: String = client
.request("state_call", rpc_params!["Metadata_metadata", "0x", at_block_hash])
.request(
"state_call",
rpc_params!["Metadata_metadata", "0x", at_block_hash],
)
.await?;
// Decode the metadata.
@@ -182,12 +208,15 @@ async fn fetch_metadata(client: impl ClientT, version: MetadataVersion, at_block
match fetch_available_versions(&client, at_block_hash).await {
Ok(supported_versions) => {
fetch_inner(&client, version, supported_versions, at_block_hash).await
},
}
Err(e) => {
// The "new" interface failed. if the user is asking for V14 or the "latest"
// metadata then try the legacy interface instead. Else, just return the
// reason for failure.
if matches!(version, MetadataVersion::Version(14) | MetadataVersion::Latest) {
if matches!(
version,
MetadataVersion::Version(14) | MetadataVersion::Latest
) {
fetch_inner_legacy(&client, at_block_hash).await
} else {
Err(e)