From c2dc0ce2cde9f02e01f4b9ccbc5bf85e125db349 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 30 Nov 2022 13:05:42 +0000 Subject: [PATCH] blocks: Fetch chainHead call result Signed-off-by: Alexandru Vasile --- examples/examples/chainhead_subscription.rs | 13 ++++++-- subxt/src/blocks/block_types.rs | 35 +++++++++++++++++++++ subxt/src/rpc/rpc.rs | 21 +++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/examples/examples/chainhead_subscription.rs b/examples/examples/chainhead_subscription.rs index 9a3c2f0c6c..530bbe7460 100644 --- a/examples/examples/chainhead_subscription.rs +++ b/examples/examples/chainhead_subscription.rs @@ -10,13 +10,14 @@ //! polkadot --dev --tmp //! ``` +use codec::Encode; +use futures::StreamExt; +use sp_keyring::AccountKeyring; use subxt::{ OnlineClient, PolkadotConfig, }; -use futures::StreamExt; - #[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata.scale")] pub mod polkadot {} @@ -27,7 +28,7 @@ async fn main() -> Result<(), Box> { // Create a client to use: let api = OnlineClient::::new().await?; - let mut follow_sub = api.blocks().subscribe_chainhead_finalized(false).await?; + let mut follow_sub = api.blocks().subscribe_chainhead_finalized(true).await?; // Handle all subscriptions from the `chainHead_follow`. while let Some(block) = follow_sub.next().await { let block = block?; @@ -46,6 +47,12 @@ async fn main() -> Result<(), Box> { era.index, era.start ); + + let call_params = AccountKeyring::Alice.to_account_id().encode(); + let call = block + .call("AccountNonceApi_account_nonce".into(), &call_params) + .await?; + println!("[hash={:?}] call={:?}", block.hash(), call); } // Subscribe to the `chainHead_follow` method. diff --git a/subxt/src/blocks/block_types.rs b/subxt/src/blocks/block_types.rs index a63d58e3dd..0c407c8449 100644 --- a/subxt/src/blocks/block_types.rs +++ b/subxt/src/blocks/block_types.rs @@ -174,6 +174,41 @@ where Err(Error::Other("Failed to fetch the block body".into())) } + + /// Fetch the body (vector of extrinsics) of this block. + pub async fn call( + &self, + function: String, + call_parameters: &[u8], + ) -> Result, Error> { + let mut sub = self + .client + .rpc() + .subscribe_chainhead_call( + self.subscription_id.clone(), + self.hash, + function, + call_parameters, + ) + .await?; + + if let Some(event) = sub.next().await { + let event = event?; + + println!("Got event: {:?}", event); + + return match event { + ChainHeadEvent::Done(ChainHeadResult { result }) => { + let bytes = hex::decode(result.trim_start_matches("0x")) + .map_err(|err| Error::Other(err.to_string()))?; + Ok(bytes) + } + _ => Err(Error::Other("Failed to fetch the block body".into())), + } + } + + Err(Error::Other("Failed to fetch the block body".into())) + } } /// A representation of a block. diff --git a/subxt/src/rpc/rpc.rs b/subxt/src/rpc/rpc.rs index a4c6b10232..e787adbbf6 100644 --- a/subxt/src/rpc/rpc.rs +++ b/subxt/src/rpc/rpc.rs @@ -681,6 +681,27 @@ impl Rpc { Ok(subscription) } + + /// Subscribe to the chain head call. + pub async fn subscribe_chainhead_call( + &self, + subscription_id: String, + hash: T::Hash, + function: String, + call_parameters: &[u8], + ) -> Result>, Error> { + let subscription = self + .client + .subscribe( + "chainHead_unstable_call", + rpc_params![subscription_id, hash, function, to_hex(call_parameters)], + "chainHead_unstable_stopCall", + ) + .await?; + + Ok(subscription) + } + /// Subscribe to finalized block headers. /// /// Note: this may not produce _every_ block in the finalized chain;