diff --git a/subxt/src/blocks/block_types.rs b/subxt/src/blocks/block_types.rs index 1f20b29fb5..feb97eba25 100644 --- a/subxt/src/blocks/block_types.rs +++ b/subxt/src/blocks/block_types.rs @@ -69,6 +69,8 @@ pub enum ChainHeadError { Error(String), /// The provided subscription ID is stale or invalid. Disjoint, + /// The RPC target node does not contain the given resource. + ResourceNonExistent, /// An error occurred internally. This is definitive. Other(String), } @@ -103,6 +105,18 @@ where T: Config, C: OnlineClientT, { + /// Fetch the body (vector of extrinsics) of this block. + pub async fn body(&self) -> Result>, ChainHeadError> { + self.fetch_body(self.subscription_id.clone(), self.hash) + .await + } + + /// Fetch the header of this block. + pub async fn header(&self) -> Result { + self.fetch_header(self.subscription_id.clone(), self.hash) + .await + } + /// Wrapper to fetch the block's body from the `chainHead_body` subscription. async fn fetch_body( &self, @@ -128,10 +142,29 @@ where Err(Error::Other("Failed to fetch the block body".into()).into()) } - /// Fetch the body (vector of extrinsics) of this block. - pub async fn body(&self) -> Result>, ChainHeadError> { - self.fetch_body(self.subscription_id.clone(), self.hash) - .await + /// Wrapper to fetch the block's header from the `chainHead_header` method. + async fn fetch_header( + &self, + subscription_id: String, + hash: T::Hash, + ) -> Result { + let header = self + .client + .rpc() + .chainhead_header(subscription_id, hash) + .await?; + + let header = match header { + Some(header) => header, + None => return Err(ChainHeadError::ResourceNonExistent), + }; + + 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[..]).map_err(Into::::into)?; + Ok(header) } }