mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-20 01:11:08 +00:00
Remove decoding bit from "extrinsics" and reference decoding in "blocks" (#951)
* Remove decoding bits from 'tx' and reference decoding in 'blocks' instead * newline * doc and fmt fixes
This commit is contained in:
@@ -1,99 +0,0 @@
|
|||||||
// Copyright 2019-2023 Parity Technologies (UK) Ltd.
|
|
||||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
|
||||||
// see LICENSE for license details.
|
|
||||||
|
|
||||||
//! To run this example, a local polkadot node should be running. Example verified against polkadot v0.9.28-9ffe6e9e3da.
|
|
||||||
//!
|
|
||||||
//! E.g.
|
|
||||||
//! ```bash
|
|
||||||
//! curl "https://github.com/paritytech/polkadot/releases/download/v0.9.28/polkadot" --output /usr/local/bin/polkadot --location
|
|
||||||
//! polkadot --dev --tmp
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use futures::StreamExt;
|
|
||||||
use sp_keyring::AccountKeyring;
|
|
||||||
use std::time::Duration;
|
|
||||||
use subxt::{tx::PairSigner, OnlineClient, PolkadotConfig};
|
|
||||||
|
|
||||||
#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata.scale")]
|
|
||||||
pub mod polkadot {}
|
|
||||||
|
|
||||||
/// Subscribe to all events, and then manually look through them and
|
|
||||||
/// pluck out the events that we care about.
|
|
||||||
#[tokio::main]
|
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
// Create a client to use:
|
|
||||||
let api = OnlineClient::<PolkadotConfig>::new().await?;
|
|
||||||
|
|
||||||
// Subscribe to (in this case, finalized) blocks.
|
|
||||||
let mut block_sub = api.blocks().subscribe_finalized().await?;
|
|
||||||
|
|
||||||
// While this subscription is active, balance transfers are made somewhere:
|
|
||||||
tokio::task::spawn({
|
|
||||||
let api = api.clone();
|
|
||||||
async move {
|
|
||||||
let signer = PairSigner::new(AccountKeyring::Alice.pair());
|
|
||||||
let mut transfer_amount = 1_000_000_000;
|
|
||||||
|
|
||||||
// Make small balance transfers from Alice to Bob in a loop:
|
|
||||||
loop {
|
|
||||||
let transfer_tx = polkadot::tx()
|
|
||||||
.balances()
|
|
||||||
.transfer(AccountKeyring::Bob.to_account_id().into(), transfer_amount);
|
|
||||||
api.tx()
|
|
||||||
.sign_and_submit_default(&transfer_tx, &signer)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
tokio::time::sleep(Duration::from_secs(10)).await;
|
|
||||||
transfer_amount += 100_000_000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get each finalized block as it arrives.
|
|
||||||
while let Some(block) = block_sub.next().await {
|
|
||||||
let block = block?;
|
|
||||||
|
|
||||||
let block_hash = block.hash();
|
|
||||||
println!(" Block {:?}", block_hash);
|
|
||||||
|
|
||||||
// Ask for the extrinsics for this block.
|
|
||||||
let extrinsics = block.body().await?.extrinsics();
|
|
||||||
|
|
||||||
let transfer_tx = extrinsics.find_first::<polkadot::balances::calls::types::Transfer>();
|
|
||||||
println!(" Transfer tx: {:?}", transfer_tx);
|
|
||||||
|
|
||||||
// Ask for the extrinsics for this block.
|
|
||||||
for extrinsic in extrinsics.iter() {
|
|
||||||
let extrinsic = extrinsic?;
|
|
||||||
|
|
||||||
println!(
|
|
||||||
" Extrinsic block index {:?}, pallet index {:?}, variant index {:?}",
|
|
||||||
extrinsic.index(),
|
|
||||||
extrinsic.pallet_index(),
|
|
||||||
extrinsic.variant_index()
|
|
||||||
);
|
|
||||||
|
|
||||||
let root_extrinsic = extrinsic.as_root_extrinsic::<polkadot::Call>();
|
|
||||||
println!(" As root extrinsic {:?}\n", root_extrinsic);
|
|
||||||
|
|
||||||
let pallet_extrinsic = extrinsic
|
|
||||||
.as_pallet_extrinsic::<polkadot::runtime_types::pallet_balances::pallet::Call>();
|
|
||||||
println!(
|
|
||||||
" Extrinsic as Balances Pallet call: {:?}\n",
|
|
||||||
pallet_extrinsic
|
|
||||||
);
|
|
||||||
|
|
||||||
let call = extrinsic.as_extrinsic::<polkadot::balances::calls::types::Transfer>()?;
|
|
||||||
println!(
|
|
||||||
" Extrinsic as polkadot::balances::calls::Transfer: {:?}\n\n",
|
|
||||||
call
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@@ -31,8 +31,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let events = ext.events().await?;
|
let events = ext.events().await?;
|
||||||
let bytes_hex = format!("0x{}", hex::encode(ext.bytes()));
|
let bytes_hex = format!("0x{}", hex::encode(ext.bytes()));
|
||||||
|
|
||||||
|
// See the API docs for more ways to decode extrinsics:
|
||||||
|
let decoded_ext = ext.as_root_extrinsic::<polkadot::Call>();
|
||||||
|
|
||||||
println!(" Extrinsic #{idx}:");
|
println!(" Extrinsic #{idx}:");
|
||||||
println!(" Bytes: {bytes_hex}");
|
println!(" Bytes: {bytes_hex}");
|
||||||
|
println!(" Decoded: {decoded_ext:?}");
|
||||||
println!(" Events:");
|
println!(" Events:");
|
||||||
|
|
||||||
for evt in events.iter() {
|
for evt in events.iter() {
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
//! accounts, Alice to Bob:
|
//! accounts, Alice to Bob:
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../examples/examples/balance_transfer_basic.rs")]
|
#![doc = include_str!("../../../examples/examples/tx_basic.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! This example assumes that a Polkadot node is running locally (Subxt endeavors to support all
|
//! This example assumes that a Polkadot node is running locally (Subxt endeavors to support all
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
//! Once Subxt is configured, the next step is interacting with a node. Follow the links
|
//! Once Subxt is configured, the next step is interacting with a node. Follow the links
|
||||||
//! below to learn more about how to use Subxt for each of the following things:
|
//! below to learn more about how to use Subxt for each of the following things:
|
||||||
//!
|
//!
|
||||||
//! - [Extrinsics](usage::extrinsics): Subxt can build and submit extrinsics, wait until they are in
|
//! - [Transactions](usage::transactions): Subxt can build and submit transactions, wait until they are in
|
||||||
//! blocks, and retrieve the associated events.
|
//! blocks, and retrieve the associated events.
|
||||||
//! - [Storage](usage::storage): Subxt can query the node storage.
|
//! - [Storage](usage::storage): Subxt can query the node storage.
|
||||||
//! - [Events](usage::events): Subxt can read the events emitted for recent blocks.
|
//! - [Events](usage::events): Subxt can read the events emitted for recent blocks.
|
||||||
|
|||||||
@@ -35,18 +35,17 @@
|
|||||||
//!
|
//!
|
||||||
//! Defining some custom config based off the default Substrate config:
|
//! Defining some custom config based off the default Substrate config:
|
||||||
//!
|
//!
|
||||||
//!
|
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/setup_client_custom_config.rs")]
|
#![doc = include_str!("../../../../examples/examples/setup_client_custom_config.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
//! Writing a custom [`crate::rpc::RpcClientT`] implementation:
|
|
||||||
//!
|
//!
|
||||||
|
//! Writing a custom [`crate::rpc::RpcClientT`] implementation:
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/setup_client_custom_rpc.rs")]
|
#![doc = include_str!("../../../../examples/examples/setup_client_custom_rpc.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
//! Creating an [`crate::OfflineClient`]:
|
|
||||||
//!
|
//!
|
||||||
|
//! Creating an [`crate::OfflineClient`]:
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/setup_client_offline.rs")]
|
#![doc = include_str!("../../../../examples/examples/setup_client_offline.rs")]
|
||||||
|
|||||||
@@ -24,14 +24,14 @@
|
|||||||
//! - [events](crate::blocks::Block::events())
|
//! - [events](crate::blocks::Block::events())
|
||||||
//! - [runtime APIs](crate::blocks::Block::runtime_api())
|
//! - [runtime APIs](crate::blocks::Block::runtime_api())
|
||||||
//!
|
//!
|
||||||
|
//! Aside from these links to other Subxt APIs, the main thing that we can do here is iterate over and
|
||||||
|
//! decode the extrinsics in a block body.
|
||||||
|
//!
|
||||||
//! ## Example
|
//! ## Example
|
||||||
//!
|
//!
|
||||||
//! Given a block, you can [download the block body](crate::blocks::Block::body()) and iterate over
|
//! Given a block, you can [download the block body](crate::blocks::Block::body()) and iterate over
|
||||||
//! the extrinsics stored within it using [`crate::blocks::BlockBody::extrinsics()`].
|
//! the extrinsics stored within it using [`crate::blocks::BlockBody::extrinsics()`]. From there, you
|
||||||
//!
|
//! can decode the extrinsics and access various details, including the associated events:
|
||||||
//! Here's an example in which we subscribe to blocks and print a bunch of information about each
|
|
||||||
//! one:
|
|
||||||
//!
|
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/blocks_subscribing.rs")]
|
#![doc = include_str!("../../../../examples/examples/blocks_subscribing.rs")]
|
||||||
|
|||||||
@@ -48,12 +48,11 @@
|
|||||||
//!
|
//!
|
||||||
//! Here's an example using a static query:
|
//! Here's an example using a static query:
|
||||||
//!
|
//!
|
||||||
//!
|
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/constants_static.rs")]
|
#![doc = include_str!("../../../../examples/examples/constants_static.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
//! And here's one using a dynamic query:
|
|
||||||
//!
|
//!
|
||||||
|
//! And here's one using a dynamic query:
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/constants_dynamic.rs")]
|
#![doc = include_str!("../../../../examples/examples/constants_dynamic.rs")]
|
||||||
|
|||||||
@@ -13,10 +13,10 @@
|
|||||||
//! keep a snapshot of the state at a small number of previous blocks, so you can sometimes access
|
//! keep a snapshot of the state at a small number of previous blocks, so you can sometimes access
|
||||||
//! older events by using [`crate::events::EventsClient::at()`] and providing an older block hash.
|
//! older events by using [`crate::events::EventsClient::at()`] and providing an older block hash.
|
||||||
//!
|
//!
|
||||||
//! When we submit extrinsics using Subxt, methods like [`crate::tx::TxProgress::wait_for_finalized_success()`]
|
//! When we submit transactions using Subxt, methods like [`crate::tx::TxProgress::wait_for_finalized_success()`]
|
||||||
//! return [`crate::blocks::ExtrinsicEvents`], which can be used to iterate and inspect the events produced
|
//! return [`crate::blocks::ExtrinsicEvents`], which can be used to iterate and inspect the events produced
|
||||||
//! for a specific extrinsic. We can also access _all_ of the events produced in a single block using one of these
|
//! by that transaction being executed. We can also access _all_ of the events produced in a single block using one
|
||||||
//! two interfaces:
|
//! of these two interfaces:
|
||||||
//!
|
//!
|
||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! # #[tokio::main]
|
//! # #[tokio::main]
|
||||||
@@ -43,7 +43,6 @@
|
|||||||
//!
|
//!
|
||||||
//! Here's an example which puts this all together:
|
//! Here's an example which puts this all together:
|
||||||
//!
|
//!
|
||||||
//!
|
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/events.rs")]
|
#![doc = include_str!("../../../../examples/examples/events.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
//! This modules contains examples of using Subxt; follow the links for more:
|
//! This modules contains examples of using Subxt; follow the links for more:
|
||||||
//!
|
//!
|
||||||
//! - [Extrinsics](extrinsics)
|
//! - [Transactions](transactions)
|
||||||
//! - [Storage](storage)
|
//! - [Storage](storage)
|
||||||
//! - [Events](events)
|
//! - [Events](events)
|
||||||
//! - [Constants](constants)
|
//! - [Constants](constants)
|
||||||
@@ -16,6 +16,6 @@
|
|||||||
pub mod blocks;
|
pub mod blocks;
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
pub mod extrinsics;
|
|
||||||
pub mod runtime_apis;
|
pub mod runtime_apis;
|
||||||
pub mod storage;
|
pub mod storage;
|
||||||
|
pub mod transactions;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
//! # Runtime API interface
|
//! # Runtime API interface
|
||||||
//!
|
//!
|
||||||
//! The Runtime API interface allows Subxt to call runtime APIs exposed by certain pallets in order
|
//! The Runtime API interface allows Subxt to call runtime APIs exposed by certain pallets in order
|
||||||
//! to obtain information. Much like [`super::storage`] and [`super::extrinsics`], Making a runtime
|
//! to obtain information. Much like [`super::storage`] and [`super::transactions`], Making a runtime
|
||||||
//! call to a node and getting the response back takes the following steps:
|
//! call to a node and getting the response back takes the following steps:
|
||||||
//!
|
//!
|
||||||
//! 1. [Constructing a runtime call](#constructing-a-runtime-call)
|
//! 1. [Constructing a runtime call](#constructing-a-runtime-call)
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
//! # Storage
|
//! # Storage
|
||||||
//!
|
//!
|
||||||
//! A Substrate based chain has storage, whose values are determined by the extrinsics added to past
|
//! A Substrate based chain can be seen as a key/value database which starts off at some initial
|
||||||
//! blocks. Subxt allows you to query the storage of a node, which consists of the following steps:
|
//! state, and is modified by the extrinsics in each block. This database is referred to as the
|
||||||
|
//! node storage. With Subxt, you can query this key/value storage with the following steps:
|
||||||
//!
|
//!
|
||||||
//! 1. [Constructing a storage query](#constructing-a-storage-query).
|
//! 1. [Constructing a storage query](#constructing-a-storage-query).
|
||||||
//! 2. [Submitting the query to get back the associated values](#submitting-it).
|
//! 2. [Submitting the query to get back the associated values](#submitting-it).
|
||||||
@@ -73,33 +74,33 @@
|
|||||||
//! [`crate::storage::Storage::fetch()`] or [`crate::storage::Storage::fetch_or_default()`] (the
|
//! [`crate::storage::Storage::fetch()`] or [`crate::storage::Storage::fetch_or_default()`] (the
|
||||||
//! latter will only work for storage queries that have a default value when empty):
|
//! latter will only work for storage queries that have a default value when empty):
|
||||||
//!
|
//!
|
||||||
//!
|
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/storage_fetch.rs")]
|
#![doc = include_str!("../../../../examples/examples/storage_fetch.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
|
//!
|
||||||
//! For completeness, below is an example using a dynamic query instead. The return type from a
|
//! For completeness, below is an example using a dynamic query instead. The return type from a
|
||||||
//! dynamic query is a [`crate::dynamic::DecodedValueThunk`], which can be decoded into a
|
//! dynamic query is a [`crate::dynamic::DecodedValueThunk`], which can be decoded into a
|
||||||
//! [`crate::dynamic::Value`], or else the raw bytes can be accessed instead.
|
//! [`crate::dynamic::Value`], or else the raw bytes can be accessed instead.
|
||||||
//!
|
//!
|
||||||
//!
|
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/storage_fetch_dynamic.rs")]
|
#![doc = include_str!("../../../../examples/examples/storage_fetch_dynamic.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
|
//!
|
||||||
//! ### Iterating storage entries
|
//! ### Iterating storage entries
|
||||||
//!
|
//!
|
||||||
//! Many storage entries are maps of values; as well as fetching individual values, it's possible to
|
//! Many storage entries are maps of values; as well as fetching individual values, it's possible to
|
||||||
//! iterate over all of the values stored at that location:
|
//! iterate over all of the values stored at that location:
|
||||||
//!
|
//!
|
||||||
//!
|
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/storage_iterating.rs")]
|
#![doc = include_str!("../../../../examples/examples/storage_iterating.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
//! Here's the same logic but using dynamically constructed values instead:
|
|
||||||
//!
|
//!
|
||||||
|
//! Here's the same logic but using dynamically constructed values instead:
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/storage_iterating_dynamic.rs")]
|
#![doc = include_str!("../../../../examples/examples/storage_iterating_dynamic.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
|
//!
|
||||||
//! ### Advanced
|
//! ### Advanced
|
||||||
//!
|
//!
|
||||||
//! For more advanced use cases, have a look at [`crate::storage::Storage::fetch_raw`] and
|
//! For more advanced use cases, have a look at [`crate::storage::Storage::fetch_raw`] and
|
||||||
|
|||||||
@@ -2,35 +2,35 @@
|
|||||||
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
// This file is dual-licensed as Apache-2.0 or GPL-3.0.
|
||||||
// see LICENSE for license details.
|
// see LICENSE for license details.
|
||||||
|
|
||||||
//! # Extrinsics
|
//! # Transactions
|
||||||
//!
|
//!
|
||||||
//! Extrinsics define function calls and their parameters, and are the only way that you can change
|
//! A transaction is an extrinsic that's signed (ie it originates from a given address). The purpose
|
||||||
//! the state of the blockchain. Submitting extrinsics to a node is one of the core features of
|
//! of extrinsics is to modify the node storage in a deterministic way, and so being able to submit
|
||||||
//! Subxt, and generally consists of the following steps:
|
//! transactions to a node is one of the core features of Subxt.
|
||||||
//!
|
//!
|
||||||
//! 1. [Constructing an extrinsic payload to submit](#constructing-an-extrinsic-payload).
|
//! > Note: the documentation tends to use the terms _extrinsic_ and _transaction_ interchangeably;
|
||||||
|
//! > An extrinsic is some data that can be added to a block, and is either signed (a _transaction_)
|
||||||
|
//! > or unsigned (an _inherent_). Subxt can construct either, but overwhelmingly you'll need to
|
||||||
|
//! > sign the payload you'd like to submit.
|
||||||
|
//!
|
||||||
|
//! Submitting a transaction to a node consists of the following steps:
|
||||||
|
//!
|
||||||
|
//! 1. [Constructing a transaction payload to submit](#constructing-a-transaction-payload).
|
||||||
//! 2. [Signing it](#signing-it).
|
//! 2. [Signing it](#signing-it).
|
||||||
//! 3. [Submitting it (optionally with some additional parameters)](#submitting-it).
|
//! 3. [Submitting it (optionally with some additional parameters)](#submitting-it).
|
||||||
//!
|
//!
|
||||||
//! We'll look at each of these steps in turn.
|
//! We'll look at each of these steps in turn.
|
||||||
//!
|
//!
|
||||||
//! > As a side note, an _extrinsic_ is anything that can be added to a block, and a _transaction_
|
//! ## Constructing a transaction payload
|
||||||
//! > is an extrinsic that is submitted from a particular user (and is therefore also signed). Subxt
|
|
||||||
//! > can construct unsigned extrinsics, but overwhelmingly you'll need to sign them, and so the
|
|
||||||
//! > documentation tends to use the terms _extrinsic_ and _transaction_ interchangeably.
|
|
||||||
//!
|
//!
|
||||||
//! Furthermore, Subxt is capable of decoding extrinsics included in blocks.
|
//! We can use the statically generated interface to build transaction payloads:
|
||||||
//!
|
|
||||||
//! ## Constructing an extrinsic payload
|
|
||||||
//!
|
|
||||||
//! We can use the statically generated interface to build extrinsic payloads:
|
|
||||||
//!
|
//!
|
||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! #[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata.scale")]
|
//! #[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata.scale")]
|
||||||
//! pub mod polkadot {}
|
//! pub mod polkadot {}
|
||||||
//!
|
//!
|
||||||
//! let remark = "Hello there".as_bytes().to_vec();
|
//! let remark = "Hello there".as_bytes().to_vec();
|
||||||
//! let extrinsic_payload = polkadot::tx().system().remark(remark);
|
//! let tx_payload = polkadot::tx().system().remark(remark);
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! > If you're not sure what types to import and use to build a given payload, you can use the
|
//! > If you're not sure what types to import and use to build a given payload, you can use the
|
||||||
@@ -38,13 +38,13 @@
|
|||||||
//! > interface.rs`, to see what types and things are available (or even just to use directly
|
//! > interface.rs`, to see what types and things are available (or even just to use directly
|
||||||
//! > instead of the [`#[subxt]`](crate::subxt) macro).
|
//! > instead of the [`#[subxt]`](crate::subxt) macro).
|
||||||
//!
|
//!
|
||||||
//! Alternately, we can dynamically construct an extrinsic payload. This will not be type checked or
|
//! Alternately, we can dynamically construct a transaction payload. This will not be type checked or
|
||||||
//! validated until it's submitted:
|
//! validated until it's submitted:
|
||||||
//!
|
//!
|
||||||
//! ```rust,no_run
|
//! ```rust,no_run
|
||||||
//! use subxt::dynamic::Value;
|
//! use subxt::dynamic::Value;
|
||||||
//!
|
//!
|
||||||
//! let extrinsic_payload = subxt::dynamic::tx("System", "remark", vec![
|
//! let tx_payload = subxt::dynamic::tx("System", "remark", vec![
|
||||||
//! Value::from_bytes("Hello there")
|
//! Value::from_bytes("Hello there")
|
||||||
//! ]);
|
//! ]);
|
||||||
//! ```
|
//! ```
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
//! represents any type of data that can be SCALE encoded or decoded. It can be serialized,
|
//! represents any type of data that can be SCALE encoded or decoded. It can be serialized,
|
||||||
//! deserialized and parsed from/to strings.
|
//! deserialized and parsed from/to strings.
|
||||||
//!
|
//!
|
||||||
//! A valid extrinsic payload is just something that implements the [`crate::tx::TxPayload`] trait;
|
//! A valid transaction payload is just something that implements the [`crate::tx::TxPayload`] trait;
|
||||||
//! you can implement this trait on your own custom types if the built-in ones are not suitable for
|
//! you can implement this trait on your own custom types if the built-in ones are not suitable for
|
||||||
//! your needs.
|
//! your needs.
|
||||||
//!
|
//!
|
||||||
@@ -96,21 +96,21 @@
|
|||||||
//! // Create client:
|
//! // Create client:
|
||||||
//! let client = OnlineClient::<PolkadotConfig>::new().await?;
|
//! let client = OnlineClient::<PolkadotConfig>::new().await?;
|
||||||
//!
|
//!
|
||||||
//! // Create a dummy extrinsic payload to sign:
|
//! // Create a dummy tx payload to sign:
|
||||||
//! let payload = subxt::dynamic::tx("System", "remark", vec![
|
//! let payload = subxt::dynamic::tx("System", "remark", vec![
|
||||||
//! Value::from_bytes("Hello there")
|
//! Value::from_bytes("Hello there")
|
||||||
//! ]);
|
//! ]);
|
||||||
//!
|
//!
|
||||||
//! // Construct the extrinsic but don't sign it. You need to provide the nonce
|
//! // Construct the tx but don't sign it. You need to provide the nonce
|
||||||
//! // here, or can use `create_partial_signed` to fetch the correct nonce.
|
//! // here, or can use `create_partial_signed` to fetch the correct nonce.
|
||||||
//! let partial_extrinsic = client.tx().create_partial_signed_with_nonce(
|
//! let partial_tx = client.tx().create_partial_signed_with_nonce(
|
||||||
//! &payload,
|
//! &payload,
|
||||||
//! 0,
|
//! 0,
|
||||||
//! Default::default()
|
//! Default::default()
|
||||||
//! )?;
|
//! )?;
|
||||||
//!
|
//!
|
||||||
//! // Fetch the payload that needs to be signed:
|
//! // Fetch the payload that needs to be signed:
|
||||||
//! let signer_payload = partial_extrinsic.signer_payload();
|
//! let signer_payload = partial_tx.signer_payload();
|
||||||
//!
|
//!
|
||||||
//! // ... At this point, we can hand off the `signer_payload` to be signed externally.
|
//! // ... At this point, we can hand off the `signer_payload` to be signed externally.
|
||||||
//! // Ultimately we need to be given back a `signature` (or really, anything
|
//! // Ultimately we need to be given back a `signature` (or really, anything
|
||||||
@@ -123,9 +123,9 @@
|
|||||||
//! # signature = signer.sign(&signer_payload);
|
//! # signature = signer.sign(&signer_payload);
|
||||||
//! # address = signer.address();
|
//! # address = signer.address();
|
||||||
//!
|
//!
|
||||||
//! // Now we can build an extrinsic, which one can call `submit` or `submit_and_watch`
|
//! // Now we can build an tx, which one can call `submit` or `submit_and_watch`
|
||||||
//! // on to submit to a node and optionally watch the status.
|
//! // on to submit to a node and optionally watch the status.
|
||||||
//! let extrinsic = partial_extrinsic.sign_with_address_and_signature(
|
//! let tx = partial_tx.sign_with_address_and_signature(
|
||||||
//! &address,
|
//! &address,
|
||||||
//! &signature
|
//! &signature
|
||||||
//! );
|
//! );
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ## Submitting it
|
//! ## Submitting it
|
||||||
//!
|
//!
|
||||||
//! Once we are able to sign the extrinsic, we need to submit it.
|
//! Once we have signed the transaction, we need to submit it.
|
||||||
//!
|
//!
|
||||||
//! ### The high level API
|
//! ### The high level API
|
||||||
//!
|
//!
|
||||||
@@ -146,21 +146,20 @@
|
|||||||
//! into a finalized block, check for an `ExtrinsicSuccess` event, and then hand back the events for
|
//! into a finalized block, check for an `ExtrinsicSuccess` event, and then hand back the events for
|
||||||
//! inspection. This looks like:
|
//! inspection. This looks like:
|
||||||
//!
|
//!
|
||||||
|
//! ```rust,ignore
|
||||||
|
#![doc = include_str!("../../../../examples/examples/tx_basic.rs")]
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! ### Providing transaction parameters
|
||||||
|
//!
|
||||||
|
//! If you'd like to provide parameters (such as mortality) to the transaction, you can use
|
||||||
|
//! [`crate::tx::TxClient::sign_and_submit_then_watch`] instead:
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/balance_transfer_basic.rs")]
|
#![doc = include_str!("../../../../examples/examples/tx_with_params.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
//! ### Providing extrinsic parameters
|
|
||||||
//!
|
//!
|
||||||
//! If you'd like to provide extrinsic parameters (such as mortality), you can use
|
//! This example doesn't wait for the transaction to be included in a block; it just submits it and
|
||||||
//! [`crate::tx::TxClient::sign_and_submit_then_watch`] instead, and provide parameters for your
|
|
||||||
//! chain:
|
|
||||||
//!
|
|
||||||
//!
|
|
||||||
//! ```rust,ignore
|
|
||||||
#![doc = include_str!("../../../../examples/examples/balance_transfer_with_params.rs")]
|
|
||||||
//! ```
|
|
||||||
//! This example doesn't wait for the extrinsic to be included in a block; it just submits it and
|
|
||||||
//! hopes for the best!
|
//! hopes for the best!
|
||||||
//!
|
//!
|
||||||
//! ### Custom handling of transaction status updates
|
//! ### Custom handling of transaction status updates
|
||||||
@@ -168,57 +167,10 @@
|
|||||||
//! If you'd like more control or visibility over exactly which status updates are being emitted for
|
//! If you'd like more control or visibility over exactly which status updates are being emitted for
|
||||||
//! the transaction, you can monitor them as they are emitted and react however you choose:
|
//! the transaction, you can monitor them as they are emitted and react however you choose:
|
||||||
//!
|
//!
|
||||||
//!
|
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../../../examples/examples/balance_transfer_status_stream.rs")]
|
#![doc = include_str!("../../../../examples/examples/tx_status_stream.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
|
//!
|
||||||
//! Take a look at the API docs for [`crate::tx::TxProgress`], [`crate::tx::TxStatus`] and
|
//! Take a look at the API docs for [`crate::tx::TxProgress`], [`crate::tx::TxStatus`] and
|
||||||
//! [`crate::tx::TxInBlock`] for more options.
|
//! [`crate::tx::TxInBlock`] for more options.
|
||||||
//!
|
//!
|
||||||
//! ## Decoding Extrinsics
|
|
||||||
//!
|
|
||||||
//! The block body is made up of extrinsics representing the generalization of the concept of transactions.
|
|
||||||
//! Extrinsics can contain any external data the underlying chain wishes to validate and track.
|
|
||||||
//!
|
|
||||||
//! The process of decoding extrinsics generally involves the following steps:
|
|
||||||
//!
|
|
||||||
//! 1. Retrieve a block from the chain: This can be done directly by providing a specific hash using [crate::blocks::BlocksClient::at()]
|
|
||||||
//! and [crate::blocks::BlocksClient::at_latest()], or indirectly by subscribing to the latest produced blocks of the chain using
|
|
||||||
//! [crate::blocks::BlocksClient::subscribe_finalized()].
|
|
||||||
//!
|
|
||||||
//! 2. Fetch the block's body using [crate::blocks::Block::body()].
|
|
||||||
//!
|
|
||||||
//! 3. Obtain the extrinsics from the block's body using [crate::blocks::BlockBody::extrinsics()].
|
|
||||||
//!
|
|
||||||
//! ```rust,no_run
|
|
||||||
//! # #[tokio::main]
|
|
||||||
//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
//! use subxt::client::OnlineClient;
|
|
||||||
//! use subxt::config::PolkadotConfig;
|
|
||||||
//!
|
|
||||||
//! // Create client:
|
|
||||||
//! let client = OnlineClient::<PolkadotConfig>::new().await?;
|
|
||||||
//!
|
|
||||||
//! // Get the lastest block (or use .at() to specify a block hash):
|
|
||||||
//! let block = client.blocks().at_latest().await?;
|
|
||||||
//!
|
|
||||||
//! // Get the block's body which contains the extrinsics.
|
|
||||||
//! let body = block.body().await?;
|
|
||||||
//!
|
|
||||||
//! // Fetch the extrinsics of the block's body.
|
|
||||||
//! let extrinsics = block.body().await?.extrinsics();
|
|
||||||
//! # Ok(())
|
|
||||||
//! # }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! Once the extrinsics are loaded, similar to events, you can iterate through the extrinsics or search for specific extrinsics using methods
|
|
||||||
//! such as [crate::blocks::Extrinsics::iter()] and [crate::blocks::Extrinsics::find()]. For more information, refer to [crate::blocks::ExtrinsicDetails].
|
|
||||||
//!
|
|
||||||
//! ### Example
|
|
||||||
//!
|
|
||||||
//! Here's an example that demonstrates the usage of these concepts:
|
|
||||||
//!
|
|
||||||
//! ```rust,ignore
|
|
||||||
#![doc = include_str!("../../../../examples/examples/block_extrinsics.rs")]
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
//! Subxt is a library for interacting with Substrate based nodes. Using it looks something like this:
|
//! Subxt is a library for interacting with Substrate based nodes. Using it looks something like this:
|
||||||
//!
|
//!
|
||||||
//! ```rust,ignore
|
//! ```rust,ignore
|
||||||
#![doc = include_str!("../../examples/examples/balance_transfer_basic.rs")]
|
#![doc = include_str!("../../examples/examples/tx_basic.rs")]
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Take a look at [the Subxt guide](book) to learn more about how to use Subxt.
|
//! Take a look at [the Subxt guide](book) to learn more about how to use Subxt.
|
||||||
|
|||||||
Reference in New Issue
Block a user