mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 01:41:09 +00:00
Improve Signed Extension and Block Decoding Examples/Book (#1357)
* asset hub example and book adjustment * formatting * recursive derives * polkadot monitor example and book adjustments * formatting * adjust docs and examples, add dynamic example * james suggestions * fmt * chore(subxt/src): typo fix (#1370) * rpcmethods * followstr * mod and else * Weekly Cronjob fetching artifacts and generating polkadot.rs file. (#1352) * github CI action cronjob * add commit message * fix the CI yml files * binary crate for CI script with substrate-runner * update the CI script * correct the artifacts script * remove bash script --------- Co-authored-by: James Wilson <james@jsdw.me> Co-authored-by: Pan chao <152830401+Pan-chao@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
#![allow(missing_docs)]
|
||||
use subxt::{OnlineClient, PolkadotConfig};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Create a client that subscribes to blocks of the Polkadot network.
|
||||
let api = OnlineClient::<PolkadotConfig>::from_url("wss://rpc.polkadot.io:443").await?;
|
||||
|
||||
// Subscribe to all finalized blocks:
|
||||
let mut blocks_sub = api.blocks().subscribe_finalized().await?;
|
||||
while let Some(block) = blocks_sub.next().await {
|
||||
let block = block?;
|
||||
let block_number = block.header().number;
|
||||
let block_hash = block.hash();
|
||||
println!("Block #{block_number} ({block_hash})");
|
||||
|
||||
// Decode each signed extrinsic in the block dynamically
|
||||
let extrinsics = block.extrinsics().await?;
|
||||
for ext in extrinsics.iter() {
|
||||
let ext = ext?;
|
||||
|
||||
let Some(signed_extensions) = ext.signed_extensions() else {
|
||||
continue; // we do not look at inherents in this example
|
||||
};
|
||||
|
||||
let meta = ext.extrinsic_metadata()?;
|
||||
let fields = ext.field_values()?;
|
||||
|
||||
println!(" {}/{}", meta.pallet.name(), meta.variant.name);
|
||||
println!(" Signed Extensions:");
|
||||
for signed_ext in signed_extensions.iter() {
|
||||
let signed_ext = signed_ext?;
|
||||
// We only want to take a look at these 3 signed extensions, because the others all just have unit fields.
|
||||
if ["CheckMortality", "CheckNonce", "ChargeTransactionPayment"]
|
||||
.contains(&signed_ext.name())
|
||||
{
|
||||
println!(" {}: {}", signed_ext.name(), signed_ext.value()?);
|
||||
}
|
||||
}
|
||||
println!(" Fields:");
|
||||
println!(" {}\n", fields);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#![allow(missing_docs)]
|
||||
use subxt::{
|
||||
utils::{AccountId32, MultiAddress},
|
||||
OnlineClient, PolkadotConfig,
|
||||
};
|
||||
|
||||
use codec::Decode;
|
||||
|
||||
#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_small.scale")]
|
||||
pub mod polkadot {}
|
||||
|
||||
use polkadot::balances::calls::types::TransferKeepAlive;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Create a client that subscribes to blocks of the Polkadot network.
|
||||
let api = OnlineClient::<PolkadotConfig>::from_url("wss://rpc.polkadot.io:443").await?;
|
||||
|
||||
// Subscribe to all finalized blocks:
|
||||
let mut blocks_sub = api.blocks().subscribe_finalized().await?;
|
||||
|
||||
// For each block, print details about the `TransferKeepAlive` transactions we are interested in.
|
||||
while let Some(block) = blocks_sub.next().await {
|
||||
let block = block?;
|
||||
let block_number = block.header().number;
|
||||
let block_hash = block.hash();
|
||||
println!("Block #{block_number} ({block_hash}):");
|
||||
|
||||
let extrinsics = block.extrinsics().await?;
|
||||
for ext in extrinsics.iter() {
|
||||
let ext = ext?;
|
||||
if let Ok(Some(transfer)) = ext.as_extrinsic::<TransferKeepAlive>() {
|
||||
let Some(extensions) = ext.signed_extensions() else {
|
||||
panic!("TransferKeepAlive should be signed")
|
||||
};
|
||||
|
||||
ext.address_bytes().unwrap();
|
||||
let addr_bytes = ext
|
||||
.address_bytes()
|
||||
.expect("TransferKeepAlive should be signed");
|
||||
let sender = MultiAddress::<AccountId32, ()>::decode(&mut &addr_bytes[..])
|
||||
.expect("Decoding should work");
|
||||
let sender = display_address(&sender);
|
||||
let receiver = display_address(&transfer.dest);
|
||||
let value = transfer.value;
|
||||
let tip = extensions.tip().expect("Should have tip");
|
||||
let nonce = extensions.nonce().expect("Should have nonce");
|
||||
|
||||
println!(
|
||||
" Transfer of {value} DOT:\n {sender} (Tip: {tip}, Nonce: {nonce}) ---> {receiver}",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn display_address(addr: &MultiAddress<AccountId32, ()>) -> String {
|
||||
if let MultiAddress::Id(id32) = addr {
|
||||
format!("{id32}")
|
||||
} else {
|
||||
"MultiAddress::...".into()
|
||||
}
|
||||
}
|
||||
@@ -37,8 +37,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!(" Extrinsic #{idx}:");
|
||||
println!(" Bytes: {bytes_hex}");
|
||||
println!(" Decoded: {decoded_ext:?}");
|
||||
println!(" Events:");
|
||||
|
||||
println!(" Events:");
|
||||
for evt in events.iter() {
|
||||
let evt = evt?;
|
||||
let pallet_name = evt.pallet_name();
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#![allow(missing_docs)]
|
||||
use subxt::config::{
|
||||
Config, DefaultExtrinsicParams, DefaultExtrinsicParamsBuilder, PolkadotConfig, SubstrateConfig,
|
||||
};
|
||||
use subxt_signer::sr25519::dev;
|
||||
|
||||
#[subxt::subxt(
|
||||
runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
|
||||
derive_for_type(
|
||||
path = "xcm::v2::multilocation::MultiLocation",
|
||||
derive = "Clone",
|
||||
recursive
|
||||
)
|
||||
)]
|
||||
pub mod runtime {}
|
||||
use runtime::runtime_types::xcm::v2::multilocation::{Junctions, MultiLocation};
|
||||
|
||||
// We don't need to construct this at runtime, so an empty enum is appropriate.
|
||||
pub enum AssetHubConfig {}
|
||||
|
||||
impl Config for AssetHubConfig {
|
||||
type Hash = <SubstrateConfig as Config>::Hash;
|
||||
type AccountId = <SubstrateConfig as Config>::AccountId;
|
||||
type Address = <PolkadotConfig as Config>::Address;
|
||||
type Signature = <SubstrateConfig as Config>::Signature;
|
||||
type Hasher = <SubstrateConfig as Config>::Hasher;
|
||||
type Header = <SubstrateConfig as Config>::Header;
|
||||
type ExtrinsicParams = DefaultExtrinsicParams<AssetHubConfig>;
|
||||
// Here we use the MultiLocation from the metadata as a part of the config:
|
||||
// The `ChargeAssetTxPayment` signed extension that is part of the ExtrinsicParams above, now uses the type:
|
||||
type AssetId = MultiLocation;
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
// With the config defined, we can create an extrinsic with subxt:
|
||||
let client = subxt::OnlineClient::<AssetHubConfig>::new().await.unwrap();
|
||||
let tx_payload = runtime::tx().system().remark(b"Hello".to_vec());
|
||||
|
||||
// Build extrinsic params using an asset at this location as a tip:
|
||||
let location: MultiLocation = MultiLocation {
|
||||
parents: 3,
|
||||
interior: Junctions::Here,
|
||||
};
|
||||
let tx_config = DefaultExtrinsicParamsBuilder::<AssetHubConfig>::new()
|
||||
.tip_of(1234, location)
|
||||
.build();
|
||||
|
||||
// And provide the extrinsic params including the tip when submitting a transaction:
|
||||
let _ = client
|
||||
.tx()
|
||||
.sign_and_submit_then_watch(&tx_payload, &dev::alice(), tx_config)
|
||||
.await;
|
||||
}
|
||||
@@ -4,16 +4,8 @@ use subxt::client::OfflineClientT;
|
||||
use subxt::config::{Config, ExtrinsicParams, ExtrinsicParamsEncoder, ExtrinsicParamsError};
|
||||
use subxt_signer::sr25519::dev;
|
||||
|
||||
#[subxt::subxt(
|
||||
runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
|
||||
derive_for_type(
|
||||
path = "xcm::v2::multilocation::MultiLocation",
|
||||
derive = "Clone",
|
||||
recursive
|
||||
)
|
||||
)]
|
||||
#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale")]
|
||||
pub mod runtime {}
|
||||
use runtime::runtime_types::xcm::v2::multilocation::MultiLocation;
|
||||
|
||||
// We don't need to construct this at runtime,
|
||||
// so an empty enum is appropriate:
|
||||
@@ -27,7 +19,7 @@ impl Config for CustomConfig {
|
||||
type Hasher = subxt::config::substrate::BlakeTwo256;
|
||||
type Header = subxt::config::substrate::SubstrateHeader<u32, Self::Hasher>;
|
||||
type ExtrinsicParams = CustomExtrinsicParams<Self>;
|
||||
type AssetId = MultiLocation;
|
||||
type AssetId = u32;
|
||||
}
|
||||
|
||||
// This represents some arbitrary (and nonsensical) custom parameters that
|
||||
|
||||
Reference in New Issue
Block a user