-
Notifications
You must be signed in to change notification settings - Fork 262
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Co-authored-by: Pan chao <[email protected]>
- Loading branch information
1 parent
833beb2
commit f29fbed
Showing
7 changed files
with
243 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters