mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-29 05:37:58 +00:00
1fd1eee72a
* metadata: Implement MetadataHashable for deterministic hashing Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Hash `scale_info::Field` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Hash `scale_info::Variant` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Hash `scale_info::TypeDef` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Hash pallet metadata Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Avoid data representation collision via unique identifiers Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Finalize hashing on recursive types Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Cache recursive calls Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Move `MetadataHashable` to codegen to avoid cyclic dependency Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Add pallet unique hash Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Wrap metadata as owned Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Use MetadataHashable wrapper for clients Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Generate runtime pallet uid from metadata Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Validate metadata compatibility at the pallet level Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update polkadot.rs Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Modify examples and tests for the new API Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Implement metadata uid Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update polkadot with TryFrom implementation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * client: Change `to_runtime_api` to reflect TryFrom changes Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * client: Skip full metadata validation option Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Add option to skip pallet validation for TransactionApi Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Add option to skip pallet validation for StorageApi Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update polkadot.rs with ability to skip pallet validation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Change `MetadataHashable` to per function implementation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Use metadata hashes functions Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Use metadata hashes functions Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Make `get_type_uid` private Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen, subxt: Rename metadata functions `*_uid` to `*_hash` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Update `get_field_hash` to use `codec::Encode` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Update polkadot.rs Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen, subxt: Move metadata check from client to subxt::Metadata Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen, subxt: Rename metadata check functions to follow `*_hash` naming Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Update polkadot.rs to reflect naming changes Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Use `encode_to` for metadata generation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Update polkadot.rs to reflect `encode_to` changes Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Specific name for visited set Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Provide cache to hashing functions Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Compute metadata hash by sorted pallets Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Get extrinsic hash Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Extend metadata hash with extrinsic and metadata type Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Add cache as metadata parameter Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen, subxt: Update metadata hash to use cache Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Implement Default trait for MetadataHasherCache Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Add cache for pallets Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Move functionality to metadata crate Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen, subxt: Use subxt-metadata crate Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Remove metdata hashing functionality Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Add documentation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Fix vector capacity to include extrinisc and type hash Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Add empty CLI Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-cli: Fetch metadata from substrate nodes Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-cli: Log metadata hashes of provided nodes Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-cli: Group compatible nodes by metadata Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-cli: Simplify hash map insertion Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-cli: Move full metadata check to function Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-cli: Group metadata validation at the pallet level Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Persist metadata cache Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Move compatibility cli from subxt-metadata to subxt-cli Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Remove cli from subxt-metadata Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * cli: Fix clippy Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Fix compatible metadata when pallets are registered in different order Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * tests: Handle result of pallet hashing Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Remove type cache for deterministic hashing Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Add test assets from `substrate-node-template` tag `polkadot-v0.9.17` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-tests: Check cache hashing for Balances pallet Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Fix `get_type_hash` clippy issue Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-tests: Compare one time cache with persistent cache Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-test: Check metadata hash populates cache for pallets Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-tests: Simplify `cache_deterministic_hash` test Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata-tests: Check deterministic metadata for different order pallets Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Fix clippy Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Implement TransactionApiUnchecked for skipping pallet validation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Implement StorageApiUnchecked for skipping pallet validation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Remove skip_pallet_validation boolean Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Implement ClientUnchecked for skipping metadata validation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update polkadot.rs Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update examples of rpc_call to skip metadata Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Remove heck dependency Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Add pallet name as an identifier for pallet hashing Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Implement MetadataHashDetails Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Adjust testing to `MetadataHashDetails` interface Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Remove extra `pallet_name` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Update polkadot.rs Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Fix clippy issue Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Change StorageApi to support `_unchecked` methods Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Change TransactionApi to support `_unchecked` methods Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Switch back from `TryFrom` to `From` for `subxt::Client` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen, subxt: Remove `ClientUnchecked` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Expose `validate_metadata` as validation of compatibility method Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * examples: Update to the new interface Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Update test integration to latest interface Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Update polkadot.rs Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Check different pallet index order Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Check recursive type hashing Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Check recursive types registered in different order Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Fix recursive types warning Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Remove test assets Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Extend tests to verify cached pallet values Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * examples: Add metadata compatiblity example Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * examples: Revert balance_transfer to initial form Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Add ConstantsApi metadata check Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * tests: Modify tests to accomodate ConstantsApi changes Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * examples: Modify verified version Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Generate polkadot.rs from `0.9.18-4542a603cc-aarch64-macos` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * examples: Update polkadot_metadata.scale from `0.9.18-4542a603cc-aarch64-macos` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Update documentation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * tests: Modify default pallet usage Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Remove hex dependency Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Add MetadataTestType to capture complex types Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Update tests to use complex types Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Check metadata correctness via extending pallets Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Extend pallet hash with Events Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Extend pallet hash with constants Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Extend pallet hash with error Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * examples: Extend metadata compatibiliy with StorageApi and ConstantsApi Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Modify comments and documentation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Benchmarks for full validation and pallet validation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/benches: Fix clippy Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Hash metadata just by inspecting the provided pallets Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Make pallets generic over T for `AsRef<str>` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Expose the name of the pallets composing the metadata Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt/tests: Update polkadot.rs with pallets name Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen: Obtain metadata hash only by inspecting pallets Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * codegen,subxt: Extend the metadata hash to utilize just pallets Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt/tests: Update polkadot.rs with client metadata has per pallet Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Test `get_metadata_per_pallet_hash` correctness Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Fix clippy Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/benches: Fix decode of metadata Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Fix clippy Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * [static metadata] validate storage, calls and constants per call (#507) * validate storage, calls and constants per call * fix typo * cache per-thing hashing, move an Arc, remove some unused bits * create hash_cache to simplify metadata call/constant/storage caching * simplify/robustify the caching logic to help prevent mismatch between get and set * cargo fmt * Fix clippy Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * bench the per-call metadata functions * metadata: Add test for `node_template_runtime_variant` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * ensure criteron cli opts work * group benchmarks and avoid unwrap issues * metadata: Check template runtime for handling the pallet swap order case Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Remove debug logs Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Optimise by removing field's name and type_name and type's path Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Refactor `get_type_hash` to break recursion earlier Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Add tests for `hash_cache` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Add tests for checking Metadata Inner cache Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Check semantic changes inside enum and struct fields Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Add enums named differently with compatible semantic meaning Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Guard testing of release versions for `node_template_runtime` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Improve documentation Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * Update polkadot.rs Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata/tests: Manually construct type of `node_template_runtimeL::Call` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * no more special Call handling, avoid a little cloning, and actually sort by name * remove unused deps and fmt * RuntimeMetadataLastVersion => RuntimeMetadataV14 * remove a bunch of allocations in the metadata hashing, speed up from ~17ms to ~5ms * update release docs to release metadata crate too * subxt: Remove codegen dependency Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Replace std RwLock with parking_lot Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt/tests: Add ws address to `TestNodeProcess` Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt/tests: Add metadata validation integration test Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Allow setting metadata on the ClientBuilder Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt/tests: Check incompatible metadatas Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * metadata: Fix constant hashing for deterministic output Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt/tests: Check metadata validation for constants Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt/tests: Test validation for calls Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt/tests: Test validation for storage Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Expose `set_metadata` for testing only Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> * subxt: Guard metadata tests under integration-tests Signed-off-by: Alexandru Vasile <alexandru.vasile@parity.io> Co-authored-by: James Wilson <james@jsdw.me>
377 lines
12 KiB
Rust
377 lines
12 KiB
Rust
// Copyright 2019-2022 Parity Technologies (UK) Ltd.
|
|
// This file is part of subxt.
|
|
//
|
|
// subxt is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// subxt is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with subxt. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
use futures::future;
|
|
use sp_runtime::traits::Hash;
|
|
pub use sp_runtime::traits::SignedExtension;
|
|
|
|
use crate::{
|
|
error::{
|
|
BasicError,
|
|
HasModuleError,
|
|
},
|
|
extrinsic::{
|
|
ExtrinsicParams,
|
|
Signer,
|
|
},
|
|
rpc::{
|
|
Rpc,
|
|
RpcClient,
|
|
RuntimeVersion,
|
|
SystemProperties,
|
|
},
|
|
storage::StorageClient,
|
|
transaction::TransactionProgress,
|
|
Call,
|
|
Config,
|
|
Encoded,
|
|
Metadata,
|
|
};
|
|
use codec::{
|
|
Compact,
|
|
Decode,
|
|
Encode,
|
|
};
|
|
use derivative::Derivative;
|
|
|
|
/// ClientBuilder for constructing a Client.
|
|
#[derive(Default)]
|
|
pub struct ClientBuilder {
|
|
url: Option<String>,
|
|
client: Option<RpcClient>,
|
|
metadata: Option<Metadata>,
|
|
page_size: Option<u32>,
|
|
}
|
|
|
|
impl ClientBuilder {
|
|
/// Creates a new ClientBuilder.
|
|
pub fn new() -> Self {
|
|
Self {
|
|
url: None,
|
|
client: None,
|
|
metadata: None,
|
|
page_size: None,
|
|
}
|
|
}
|
|
|
|
/// Sets the jsonrpsee client.
|
|
pub fn set_client<C: Into<RpcClient>>(mut self, client: C) -> Self {
|
|
self.client = Some(client.into());
|
|
self
|
|
}
|
|
|
|
/// Set the substrate rpc address.
|
|
pub fn set_url<P: Into<String>>(mut self, url: P) -> Self {
|
|
self.url = Some(url.into());
|
|
self
|
|
}
|
|
|
|
/// Set the page size.
|
|
pub fn set_page_size(mut self, size: u32) -> Self {
|
|
self.page_size = Some(size);
|
|
self
|
|
}
|
|
|
|
/// Set the metadata.
|
|
///
|
|
/// *Note:* Metadata will no longer be downloaded from the runtime node.
|
|
#[cfg(integration_tests)]
|
|
pub fn set_metadata(mut self, metadata: Metadata) -> Self {
|
|
self.metadata = Some(metadata);
|
|
self
|
|
}
|
|
|
|
/// Creates a new Client.
|
|
pub async fn build<T: Config>(self) -> Result<Client<T>, BasicError> {
|
|
let client = if let Some(client) = self.client {
|
|
client
|
|
} else {
|
|
let url = self.url.as_deref().unwrap_or("ws://127.0.0.1:9944");
|
|
crate::rpc::ws_client(url).await?
|
|
};
|
|
let rpc = Rpc::new(client);
|
|
let (genesis_hash, runtime_version, properties) = future::join3(
|
|
rpc.genesis_hash(),
|
|
rpc.runtime_version(None),
|
|
rpc.system_properties(),
|
|
)
|
|
.await;
|
|
|
|
let metadata = if let Some(metadata) = self.metadata {
|
|
metadata
|
|
} else {
|
|
rpc.metadata().await?
|
|
};
|
|
|
|
Ok(Client {
|
|
rpc,
|
|
genesis_hash: genesis_hash?,
|
|
metadata,
|
|
properties: properties.unwrap_or_else(|_| Default::default()),
|
|
runtime_version: runtime_version?,
|
|
iter_page_size: self.page_size.unwrap_or(10),
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Client to interface with a substrate node.
|
|
#[derive(Derivative)]
|
|
#[derivative(Clone(bound = ""))]
|
|
pub struct Client<T: Config> {
|
|
rpc: Rpc<T>,
|
|
genesis_hash: T::Hash,
|
|
metadata: Metadata,
|
|
properties: SystemProperties,
|
|
runtime_version: RuntimeVersion,
|
|
iter_page_size: u32,
|
|
}
|
|
|
|
impl<T: Config> std::fmt::Debug for Client<T> {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.debug_struct("Client")
|
|
.field("rpc", &"<Rpc>")
|
|
.field("genesis_hash", &self.genesis_hash)
|
|
.field("metadata", &"<Metadata>")
|
|
.field("events_decoder", &"<EventsDecoder>")
|
|
.field("properties", &self.properties)
|
|
.field("runtime_version", &self.runtime_version)
|
|
.field("iter_page_size", &self.iter_page_size)
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
impl<T: Config> Client<T> {
|
|
/// Returns the genesis hash.
|
|
pub fn genesis(&self) -> &T::Hash {
|
|
&self.genesis_hash
|
|
}
|
|
|
|
/// Returns the chain metadata.
|
|
pub fn metadata(&self) -> &Metadata {
|
|
&self.metadata
|
|
}
|
|
|
|
/// Returns the properties defined in the chain spec as a JSON object.
|
|
///
|
|
/// # Note
|
|
///
|
|
/// Many chains use this to define common properties such as `token_decimals` and `token_symbol`
|
|
/// required for UIs, but this is merely a convention. It is up to the library user to
|
|
/// deserialize the JSON into the appropriate type or otherwise extract the properties defined
|
|
/// in the target chain's spec.
|
|
pub fn properties(&self) -> &SystemProperties {
|
|
&self.properties
|
|
}
|
|
|
|
/// Returns the rpc client.
|
|
pub fn rpc(&self) -> &Rpc<T> {
|
|
&self.rpc
|
|
}
|
|
|
|
/// Create a client for accessing runtime storage
|
|
pub fn storage(&self) -> StorageClient<T> {
|
|
StorageClient::new(&self.rpc, &self.metadata, self.iter_page_size)
|
|
}
|
|
|
|
/// Convert the client to a runtime api wrapper for custom runtime access.
|
|
///
|
|
/// The `subxt` proc macro will provide methods to submit extrinsics and read storage specific
|
|
/// to the target runtime.
|
|
pub fn to_runtime_api<R: From<Self>>(self) -> R {
|
|
self.into()
|
|
}
|
|
}
|
|
|
|
/// A constructed call ready to be signed and submitted.
|
|
pub struct SubmittableExtrinsic<'client, T: Config, X, C, E: Decode, Evs: Decode> {
|
|
client: &'client Client<T>,
|
|
call: C,
|
|
marker: std::marker::PhantomData<(X, E, Evs)>,
|
|
}
|
|
|
|
impl<'client, T, X, C, E, Evs> SubmittableExtrinsic<'client, T, X, C, E, Evs>
|
|
where
|
|
T: Config,
|
|
X: ExtrinsicParams<T>,
|
|
C: Call + Send + Sync,
|
|
E: Decode + HasModuleError,
|
|
Evs: Decode,
|
|
{
|
|
/// Create a new [`SubmittableExtrinsic`].
|
|
pub fn new(client: &'client Client<T>, call: C) -> Self {
|
|
Self {
|
|
client,
|
|
call,
|
|
marker: Default::default(),
|
|
}
|
|
}
|
|
|
|
/// Creates and signs an extrinsic and submits it to the chain. Passes default parameters
|
|
/// to construct the "signed extra" and "additional" payloads needed by the extrinsic.
|
|
///
|
|
/// Returns a [`TransactionProgress`], which can be used to track the status of the transaction
|
|
/// and obtain details about it, once it has made it into a block.
|
|
pub async fn sign_and_submit_then_watch_default(
|
|
self,
|
|
signer: &(dyn Signer<T> + Send + Sync),
|
|
) -> Result<TransactionProgress<'client, T, E, Evs>, BasicError>
|
|
where
|
|
X::OtherParams: Default,
|
|
{
|
|
self.sign_and_submit_then_watch(signer, Default::default())
|
|
.await
|
|
}
|
|
|
|
/// Creates and signs an extrinsic and submits it to the chain.
|
|
///
|
|
/// Returns a [`TransactionProgress`], which can be used to track the status of the transaction
|
|
/// and obtain details about it, once it has made it into a block.
|
|
pub async fn sign_and_submit_then_watch(
|
|
self,
|
|
signer: &(dyn Signer<T> + Send + Sync),
|
|
other_params: X::OtherParams,
|
|
) -> Result<TransactionProgress<'client, T, E, Evs>, BasicError> {
|
|
// Sign the call data to create our extrinsic.
|
|
let extrinsic = self.create_signed(signer, other_params).await?;
|
|
|
|
// Get a hash of the extrinsic (we'll need this later).
|
|
let ext_hash = T::Hashing::hash_of(&extrinsic);
|
|
|
|
// Submit and watch for transaction progress.
|
|
let sub = self.client.rpc().watch_extrinsic(extrinsic).await?;
|
|
|
|
Ok(TransactionProgress::new(sub, self.client, ext_hash))
|
|
}
|
|
|
|
/// Creates and signs an extrinsic and submits to the chain for block inclusion. Passes
|
|
/// default parameters to construct the "signed extra" and "additional" payloads needed
|
|
/// by the extrinsic.
|
|
///
|
|
/// Returns `Ok` with the extrinsic hash if it is valid extrinsic.
|
|
///
|
|
/// # Note
|
|
///
|
|
/// Success does not mean the extrinsic has been included in the block, just that it is valid
|
|
/// and has been included in the transaction pool.
|
|
pub async fn sign_and_submit_default(
|
|
self,
|
|
signer: &(dyn Signer<T> + Send + Sync),
|
|
) -> Result<T::Hash, BasicError>
|
|
where
|
|
X::OtherParams: Default,
|
|
{
|
|
self.sign_and_submit(signer, Default::default()).await
|
|
}
|
|
|
|
/// Creates and signs an extrinsic and submits to the chain for block inclusion.
|
|
///
|
|
/// Returns `Ok` with the extrinsic hash if it is valid extrinsic.
|
|
///
|
|
/// # Note
|
|
///
|
|
/// Success does not mean the extrinsic has been included in the block, just that it is valid
|
|
/// and has been included in the transaction pool.
|
|
pub async fn sign_and_submit(
|
|
self,
|
|
signer: &(dyn Signer<T> + Send + Sync),
|
|
other_params: X::OtherParams,
|
|
) -> Result<T::Hash, BasicError> {
|
|
let extrinsic = self.create_signed(signer, other_params).await?;
|
|
self.client.rpc().submit_extrinsic(extrinsic).await
|
|
}
|
|
|
|
/// Creates a returns a raw signed extrinsic, without submitting it.
|
|
pub async fn create_signed(
|
|
&self,
|
|
signer: &(dyn Signer<T> + Send + Sync),
|
|
other_params: X::OtherParams,
|
|
) -> Result<Encoded, BasicError> {
|
|
// 1. Get nonce
|
|
let account_nonce = if let Some(nonce) = signer.nonce() {
|
|
nonce
|
|
} else {
|
|
self.client
|
|
.rpc()
|
|
.system_account_next_index(signer.account_id())
|
|
.await?
|
|
};
|
|
|
|
// 2. SCALE encode call data to bytes (pallet u8, call u8, call params).
|
|
let call_data = {
|
|
let mut bytes = Vec::new();
|
|
let pallet = self.client.metadata().pallet(C::PALLET)?;
|
|
bytes.push(pallet.index());
|
|
bytes.push(pallet.call_index::<C>()?);
|
|
self.call.encode_to(&mut bytes);
|
|
Encoded(bytes)
|
|
};
|
|
|
|
// 3. Construct our custom additional/extra params.
|
|
let additional_and_extra_params = X::new(
|
|
self.client.runtime_version.spec_version,
|
|
self.client.runtime_version.transaction_version,
|
|
account_nonce,
|
|
self.client.genesis_hash,
|
|
other_params,
|
|
);
|
|
|
|
// 4. Construct signature. This is compatible with the Encode impl
|
|
// for SignedPayload (which is this payload of bytes that we'd like)
|
|
// to sign. See:
|
|
// https://github.com/paritytech/substrate/blob/9a6d706d8db00abb6ba183839ec98ecd9924b1f8/primitives/runtime/src/generic/unchecked_extrinsic.rs#L215)
|
|
let signature = {
|
|
let mut bytes = Vec::new();
|
|
call_data.encode_to(&mut bytes);
|
|
additional_and_extra_params.encode_extra_to(&mut bytes);
|
|
additional_and_extra_params.encode_additional_to(&mut bytes);
|
|
if bytes.len() > 256 {
|
|
signer.sign(&sp_core::blake2_256(&bytes))
|
|
} else {
|
|
signer.sign(&bytes)
|
|
}
|
|
};
|
|
|
|
// 5. Encode extrinsic, now that we have the parts we need. This is compatible
|
|
// with the Encode impl for UncheckedExtrinsic (protocol version 4).
|
|
let extrinsic = {
|
|
let mut encoded_inner = Vec::new();
|
|
// "is signed" + transaction protocol version (4)
|
|
(0b10000000 + 4u8).encode_to(&mut encoded_inner);
|
|
// from address for signature
|
|
signer.address().encode_to(&mut encoded_inner);
|
|
// the signature bytes
|
|
signature.encode_to(&mut encoded_inner);
|
|
// attach custom extra params
|
|
additional_and_extra_params.encode_extra_to(&mut encoded_inner);
|
|
// and now, call data
|
|
call_data.encode_to(&mut encoded_inner);
|
|
// now, prefix byte length:
|
|
let len = Compact(
|
|
u32::try_from(encoded_inner.len())
|
|
.expect("extrinsic size expected to be <4GB"),
|
|
);
|
|
let mut encoded = Vec::new();
|
|
len.encode_to(&mut encoded);
|
|
encoded.extend(encoded_inner);
|
|
encoded
|
|
};
|
|
|
|
// Wrap in Encoded to ensure that any more "encode" calls leave it in the right state.
|
|
// maybe we can just return the raw bytes..
|
|
Ok(Encoded(extrinsic))
|
|
}
|
|
}
|