mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 06:08:00 +00:00
Get workspace compiling via 'cargo check'
This commit is contained in:
@@ -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{}",
|
||||
|
||||
@@ -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,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();
|
||||
|
||||
@@ -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<()> {
|
||||
|
||||
@@ -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()?;
|
||||
|
||||
@@ -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
@@ -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!(
|
||||
|
||||
@@ -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, )* },
|
||||
|
||||
@@ -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,)*]
|
||||
|
||||
@@ -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,)*])
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
@@ -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,)*),
|
||||
|
||||
@@ -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,)*),
|
||||
|
||||
@@ -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,)*],
|
||||
|
||||
@@ -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
@@ -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
@@ -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>>;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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,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
@@ -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},
|
||||
|
||||
@@ -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>;
|
||||
@@ -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)]
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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::{
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -193,4 +193,4 @@ mod test {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user