From 9ef0a7074291c38b06f578a3e408eb0d29a4a432 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile Date: Wed, 30 Nov 2022 11:04:43 +0000 Subject: [PATCH] blocks: Fetch chainHead header Signed-off-by: Alexandru Vasile --- examples/examples/chainhead_subscription.rs | 3 +++ subxt/src/blocks/block_types.rs | 27 ++++++++++++++++++++- subxt/src/rpc/rpc.rs | 19 ++++++++++++++- 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/examples/examples/chainhead_subscription.rs b/examples/examples/chainhead_subscription.rs index 37a0bc458d..dbd9641f06 100644 --- a/examples/examples/chainhead_subscription.rs +++ b/examples/examples/chainhead_subscription.rs @@ -34,6 +34,9 @@ async fn main() -> Result<(), Box> { let body = event.body().await?; println!("[hash={:?}] body={:?}", event.hash(), body); + + let header = event.header().await?; + println!("[hash={:?}] header={:?}", event.hash(), header); } // Subscribe to the `chainHead_follow` method. diff --git a/subxt/src/blocks/block_types.rs b/subxt/src/blocks/block_types.rs index ea3d315e66..0a84f9ab60 100644 --- a/subxt/src/blocks/block_types.rs +++ b/subxt/src/blocks/block_types.rs @@ -64,11 +64,12 @@ where T: Config, C: OnlineClientT, { + /// Fetch the body (vector of extrinsics) of this block. pub async fn body(&self) -> Result>, Error> { let mut sub = self .client .rpc() - .subscribe_chainhead_body(self.hash, self.subscription_id.clone()) + .subscribe_chainhead_body(self.subscription_id.clone(), self.hash) .await?; if let Some(event) = sub.next().await { @@ -90,6 +91,30 @@ where Err(Error::Other("Failed to fetch the block body".into())) } + + /// Fetch the header of this block. + pub async fn header(&self) -> Result { + let header = self + .client + .rpc() + .get_chainhead_header(self.subscription_id.clone(), self.hash) + .await?; + + let header = match header { + Some(header) => header, + None => { + return Err(Error::Other( + "Chain does not contain the header of this block".into(), + )) + } + }; + + let bytes = hex::decode(header.trim_start_matches("0x")) + .map_err(|err| Error::Other(err.to_string()))?; + + let header: T::Header = Decode::decode(&mut &bytes[..])?; + Ok(header) + } } /// A representation of a block. diff --git a/subxt/src/rpc/rpc.rs b/subxt/src/rpc/rpc.rs index 58ef1a9376..43e9c86277 100644 --- a/subxt/src/rpc/rpc.rs +++ b/subxt/src/rpc/rpc.rs @@ -630,8 +630,8 @@ impl Rpc { /// Subscribe to the chain head body. pub async fn subscribe_chainhead_body( &self, - hash: T::Hash, subscription_id: String, + hash: T::Hash, ) -> Result>, Error> { let subscription = self .client @@ -645,6 +645,23 @@ impl Rpc { Ok(subscription) } + /// Get the chain head header. + pub async fn get_chainhead_header( + &self, + subscription_id: String, + hash: T::Hash, + ) -> Result, Error> { + let header = self + .client + .request( + "chainHead_unstable_header", + rpc_params![subscription_id, hash], + ) + .await?; + + Ok(header) + } + /// Subscribe to finalized block headers. /// /// Note: this may not produce _every_ block in the finalized chain;