Support decoding signed extensions (#1209)

* skeleton commit

* signed extension decoding

* fix some minor things

* make api more similar to Extrinsics

* defer decoding of signed extensions

* fix byte slices

* add test for nonce signed extension

* adjust test and extend for tip

* clippy

* support both  ChargeTransactionPayment and ChargeAssetTxPayment

* address PR comments

* Extend lifetimes, expose pub structs, remove as_type

* add signed extensions to block subscribing example

* make example less ugly

---------

Co-authored-by: James Wilson <james@jsdw.me>
This commit is contained in:
Tadeo Hepperle
2023-10-31 10:40:23 +01:00
committed by GitHub
parent e53df87e72
commit 1b88ebf78e
4 changed files with 294 additions and 43 deletions
@@ -5,6 +5,8 @@
use crate::{test_context, utils::node_runtime};
use codec::{Compact, Encode};
use futures::StreamExt;
use subxt::config::DefaultExtrinsicParamsBuilder;
use subxt_metadata::Metadata;
use subxt_signer::sr25519::dev;
@@ -227,3 +229,81 @@ async fn fetch_block_and_decode_extrinsic_details() {
assert_eq!(ext.value, 10_000);
assert!(tx.is_signed());
}
#[tokio::test]
async fn decode_signed_extensions_from_blocks() {
let ctx = test_context().await;
let api = ctx.client();
let alice = dev::alice();
let bob = dev::bob();
macro_rules! submit_transfer_extrinsic_and_get_it_back {
($tip:expr) => {{
let tx = node_runtime::tx()
.balances()
.transfer_allow_death(bob.public_key().into(), 10_000);
let signed_extrinsic = api
.tx()
.create_signed(
&tx,
&alice,
DefaultExtrinsicParamsBuilder::new().tip($tip).build(),
)
.await
.unwrap();
let in_block = signed_extrinsic
.submit_and_watch()
.await
.unwrap()
.wait_for_finalized()
.await
.unwrap();
let block_hash = in_block.block_hash();
let block = api.blocks().at(block_hash).await.unwrap();
let extrinsics = block.extrinsics().await.unwrap();
let extrinsic_details = extrinsics
.iter()
.find_map(|e| e.ok().filter(|e| e.is_signed()))
.unwrap();
extrinsic_details
}};
}
let expected_signed_extensions = [
"CheckNonZeroSender",
"CheckSpecVersion",
"CheckTxVersion",
"CheckGenesis",
"CheckMortality",
"CheckNonce",
"CheckWeight",
"ChargeAssetTxPayment",
];
let transaction1 = submit_transfer_extrinsic_and_get_it_back!(1234);
let extensions1 = transaction1.signed_extensions().unwrap();
let nonce1 = extensions1.nonce().unwrap();
let tip1 = extensions1.tip().unwrap();
let transaction2 = submit_transfer_extrinsic_and_get_it_back!(5678);
let extensions2 = transaction2.signed_extensions().unwrap();
let nonce2 = extensions2.nonce().unwrap();
let tip2 = extensions2.tip().unwrap();
assert_eq!(nonce1, 0);
assert_eq!(tip1, 1234);
assert_eq!(nonce2, 1);
assert_eq!(tip2, 5678);
assert_eq!(extensions1.iter().count(), expected_signed_extensions.len());
for (e, expected_name) in extensions1.iter().zip(expected_signed_extensions.iter()) {
assert_eq!(e.unwrap().name(), *expected_name);
}
assert_eq!(extensions2.iter().count(), expected_signed_extensions.len());
for (e, expected_name) in extensions2.iter().zip(expected_signed_extensions.iter()) {
assert_eq!(e.unwrap().name(), *expected_name);
}
}