diff --git a/examples/examples/compose_extrinsic_offline.rs b/examples/examples/compose_extrinsic_offline.rs index 165222a18..18e1cd18d 100644 --- a/examples/examples/compose_extrinsic_offline.rs +++ b/examples/examples/compose_extrinsic_offline.rs @@ -22,7 +22,7 @@ use sp_runtime::{generic::Era, MultiAddress}; use substrate_api_client::{ ac_primitives::{AssetTipExtrinsicParams, ExtrinsicSigner, GenericAdditionalParams}, rpc::JsonrpseeClient, - Api, GetHeader, SubmitAndWatch, XtStatus, + Api, GetChainInfo, SubmitAndWatch, XtStatus, }; #[tokio::main] diff --git a/examples/examples/custom_nonce.rs b/examples/examples/custom_nonce.rs index 362c8df4a..4096e684c 100644 --- a/examples/examples/custom_nonce.rs +++ b/examples/examples/custom_nonce.rs @@ -22,7 +22,7 @@ use sp_runtime::{generic::Era, MultiAddress}; use substrate_api_client::{ ac_primitives::{AssetTipExtrinsicParams, ExtrinsicSigner, GenericAdditionalParams}, rpc::JsonrpseeClient, - Api, Error, GetHeader, SubmitAndWatch, UnexpectedTxStatus, XtStatus, + Api, Error, GetChainInfo, SubmitAndWatch, UnexpectedTxStatus, XtStatus, }; #[tokio::main] diff --git a/examples/examples/get_blocks.rs b/examples/examples/get_blocks.rs index 55c40ecdc..8dedfe09c 100644 --- a/examples/examples/get_blocks.rs +++ b/examples/examples/get_blocks.rs @@ -21,7 +21,7 @@ use sp_core::sr25519; use substrate_api_client::{ ac_primitives::PlainTipExtrinsicParams, rpc::{HandleSubscription, JsonrpseeClient}, - Api, GetBlock, GetHeader, SubscribeChain, + Api, GetChainInfo, SubscribeChain, }; #[tokio::main] @@ -33,16 +33,26 @@ async fn main() { let api = Api::, Runtime>::new(client).unwrap(); - println!("Genesis block: \n {:?} \n", api.get_block_by_num(Some(0)).unwrap()); + println!("Genesis block: \n {:?} \n", api.get_genesis_block().unwrap()); let header_hash = api.get_finalized_head().unwrap().unwrap(); println!("Latest Finalized Header Hash:\n {} \n", header_hash); - let h = api.get_header(Some(header_hash)).unwrap().unwrap(); - println!("Finalized header:\n {:?} \n", h); + let header = api.get_header(Some(header_hash)).unwrap().unwrap(); + println!("Finalized header:\n {:?} \n", header); - let b = api.get_signed_block(Some(header_hash)).unwrap().unwrap(); - println!("Finalized signed block:\n {:?} \n", b); + let signed_block = api.get_finalized_block().unwrap().unwrap(); + println!("Finalized block:\n {:?} \n", signed_block); + + let last_block_number = signed_block.block.header.number; + // Get the previous three blocks of the last_block_number + let number_of_last_three_blocks: Vec<_> = + (last_block_number.saturating_sub(3)..last_block_number).collect(); + let blocks = api.get_signed_blocks(&number_of_last_three_blocks).unwrap(); + println!("Block numbers of the previous three blocks: "); + for (i, b) in blocks.iter().enumerate() { + println!(" Block {} has block number {}", i, b.block.header.number); + } println!("Latest Header: \n {:?} \n", api.get_header(None).unwrap()); diff --git a/src/api/mod.rs b/src/api/mod.rs index a2f1ac624..1df1e822b 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -23,7 +23,7 @@ use serde::{Deserialize, Serialize}; pub use api_client::Api; pub use error::{Error, Result}; pub use rpc_api::{ - FetchEvents, GetAccountInformation, GetBalance, GetBlock, GetHeader, GetStorage, + FetchEvents, GetAccountInformation, GetBalance, GetChainInfo, GetStorage, GetTransactionPayment, SubmitAndWatch, SubmitAndWatchUntilSuccess, SubmitExtrinsic, SubscribeChain, SubscribeEvents, SystemApi, }; diff --git a/src/api/rpc_api/author.rs b/src/api/rpc_api/author.rs index 4bce32a2a..6bb69f5a6 100644 --- a/src/api/rpc_api/author.rs +++ b/src/api/rpc_api/author.rs @@ -267,6 +267,7 @@ where Runtime: FrameSystemConfig + GetRuntimeBlockType, Runtime::RuntimeBlock: BlockTrait + DeserializeOwned, Runtime::Hashing: HashTrait, + Runtime::Header: DeserializeOwned, { type Client = Client; type Hash = Runtime::Hash; diff --git a/src/api/rpc_api/chain.rs b/src/api/rpc_api/chain.rs index c53840db6..2268acc2b 100644 --- a/src/api/rpc_api/chain.rs +++ b/src/api/rpc_api/chain.rs @@ -14,51 +14,30 @@ use crate::{ api::{Api, Result}, rpc::{Request, Subscribe}, + Error, }; use ac_compose_macros::rpc_params; use ac_primitives::{ExtrinsicParams, FrameSystemConfig, SignedBlock}; +use alloc::vec::Vec; use log::*; use serde::de::DeserializeOwned; use sp_runtime::traits::GetRuntimeBlockType; -pub trait GetHeader { +pub trait GetChainInfo { + type BlockNumber; type Hash; type Header; + type Block; fn get_finalized_head(&self) -> Result>; fn get_header(&self, hash: Option) -> Result>; -} - -impl GetHeader for Api -where - Client: Request, - Runtime: FrameSystemConfig, - Params: ExtrinsicParams, - Runtime::Header: DeserializeOwned, -{ - type Hash = Runtime::Hash; - type Header = Runtime::Header; - - fn get_finalized_head(&self) -> Result> { - let finalized_block_hash = - self.client().request("chain_getFinalizedHead", rpc_params![])?; - Ok(finalized_block_hash) - } - - fn get_header(&self, hash: Option) -> Result> { - let block_hash = self.client().request("chain_getHeader", rpc_params![hash])?; - Ok(block_hash) - } -} - -pub trait GetBlock { - type BlockNumber; - type Hash; - type Block; fn get_block_hash(&self, number: Option) -> Result>; + /// Returns the genesis block + fn get_genesis_block(&self) -> Result; + fn get_block(&self, hash: Option) -> Result>; fn get_block_by_num(&self, number: Option) -> Result>; @@ -76,24 +55,51 @@ pub trait GetBlock { &self, number: Option, ) -> Result>>; + + /// Get the last finalized signed block. + fn get_finalized_block(&self) -> Result>>; + + /// Returns a vector containing the blocks with the block numbers given in the input parameter. + /// If fetching any of the block fails then a `Result::Err` will be returned. + fn get_signed_blocks( + &self, + block_numbers: &[Self::BlockNumber], + ) -> Result>>; } -impl GetBlock for Api +impl GetChainInfo for Api where Client: Request, Runtime: FrameSystemConfig + GetRuntimeBlockType, Params: ExtrinsicParams, Runtime::RuntimeBlock: DeserializeOwned, + Runtime::Header: DeserializeOwned, { type BlockNumber = Runtime::BlockNumber; type Hash = Runtime::Hash; + type Header = Runtime::Header; type Block = Runtime::RuntimeBlock; + fn get_finalized_head(&self) -> Result> { + let finalized_block_hash = + self.client().request("chain_getFinalizedHead", rpc_params![])?; + Ok(finalized_block_hash) + } + + fn get_header(&self, hash: Option) -> Result> { + let block_hash = self.client().request("chain_getHeader", rpc_params![hash])?; + Ok(block_hash) + } + fn get_block_hash(&self, number: Option) -> Result> { let block_hash = self.client().request("chain_getBlockHash", rpc_params![number])?; Ok(block_hash) } + fn get_genesis_block(&self) -> Result { + self.get_block(Some(self.genesis_hash()))?.ok_or(Error::BlockHashNotFound) + } + fn get_block(&self, hash: Option) -> Result> { Self::get_signed_block(self, hash).map(|sb_opt| sb_opt.map(|sb| sb.block)) } @@ -116,6 +122,25 @@ where ) -> Result>> { self.get_block_hash(number).map(|h| self.get_signed_block(h))? } + + fn get_finalized_block(&self) -> Result>> { + self.get_finalized_head()? + .map_or_else(|| Ok(None), |hash| self.get_signed_block(Some(hash))) + } + + fn get_signed_blocks( + &self, + block_numbers: &[Self::BlockNumber], + ) -> Result>> { + let mut blocks = Vec::>::new(); + + for n in block_numbers { + if let Some(block) = self.get_signed_block_by_num(Some(*n))? { + blocks.push(block); + } + } + Ok(blocks) + } } pub trait SubscribeChain { type Client: Subscribe; diff --git a/src/api/rpc_api/events.rs b/src/api/rpc_api/events.rs index d61d7fefd..0a0a6854b 100644 --- a/src/api/rpc_api/events.rs +++ b/src/api/rpc_api/events.rs @@ -14,7 +14,7 @@ use crate::{ api::{Api, Error, Result}, rpc::{HandleSubscription, Request, Subscribe}, - GetBlock, GetStorage, + GetChainInfo, GetStorage, }; use ac_compose_macros::rpc_params; use ac_node_api::{EventDetails, EventRecord, Events, Phase}; @@ -50,6 +50,7 @@ where Runtime: FrameSystemConfig + GetRuntimeBlockType, Runtime::RuntimeBlock: BlockTrait + DeserializeOwned, Runtime::Hashing: HashTrait, + Runtime::Header: DeserializeOwned, { type Hash = Runtime::Hash; @@ -159,6 +160,7 @@ where Runtime: FrameSystemConfig + GetRuntimeBlockType, Runtime::RuntimeBlock: BlockTrait + DeserializeOwned, Runtime::Hashing: HashTrait, + Runtime::Header: DeserializeOwned, { /// Retrieve block details from node and search for the position of the given extrinsic. fn retrieve_extrinsic_index_from_block( diff --git a/testing/examples/chain_tests.rs b/testing/examples/chain_tests.rs index 38e2f28c7..02bebaa6d 100644 --- a/testing/examples/chain_tests.rs +++ b/testing/examples/chain_tests.rs @@ -20,7 +20,7 @@ use sp_keyring::AccountKeyring; use substrate_api_client::{ ac_primitives::AssetTipExtrinsicParams, rpc::{HandleSubscription, JsonrpseeClient}, - Api, GetBlock, GetHeader, SubscribeChain, + Api, GetChainInfo, SubscribeChain, }; #[tokio::main] @@ -31,12 +31,10 @@ async fn main() { let mut api = Api::<_, _, AssetTipExtrinsicParams, Runtime>::new(client).unwrap(); api.set_signer(alice_pair); - // GetHeader + // GetChainInfo let finalized_header_hash = api.get_finalized_head().unwrap().unwrap(); let _latest_header = api.get_header(None).unwrap().unwrap(); let _some_header = api.get_header(Some(finalized_header_hash)).unwrap().unwrap(); - - // GetBlock let _block_hash = api.get_block_hash(None).unwrap().unwrap(); let block_hash = api.get_block_hash(Some(1)).unwrap().unwrap(); let _block = api.get_block(None).unwrap().unwrap(); diff --git a/testing/examples/events_tests.rs b/testing/examples/events_tests.rs index 7b975a5d5..99b4071e6 100644 --- a/testing/examples/events_tests.rs +++ b/testing/examples/events_tests.rs @@ -24,7 +24,7 @@ use substrate_api_client::{ ac_primitives::{AssetTipExtrinsicParams, ExtrinsicSigner, FrameSystemConfig}, extrinsic::BalancesExtrinsics, rpc::JsonrpseeClient, - Api, FetchEvents, GetBlock, SubmitAndWatch, SubscribeEvents, XtStatus, + Api, FetchEvents, GetChainInfo, SubmitAndWatch, SubscribeEvents, XtStatus, }; /// Check out frame_system::Event::ExtrinsicSuccess: diff --git a/testing/examples/pallet_transaction_payment_tests.rs b/testing/examples/pallet_transaction_payment_tests.rs index 23c44237d..faea9c8e6 100644 --- a/testing/examples/pallet_transaction_payment_tests.rs +++ b/testing/examples/pallet_transaction_payment_tests.rs @@ -22,7 +22,7 @@ use substrate_api_client::{ ac_primitives::{AssetTipExtrinsicParams, ExtrinsicSigner}, extrinsic::BalancesExtrinsics, rpc::JsonrpseeClient, - Api, GetBlock, GetTransactionPayment, + Api, GetChainInfo, GetTransactionPayment, }; #[tokio::main] diff --git a/testing/examples/state_tests.rs b/testing/examples/state_tests.rs index 0276df776..cf46fe6a0 100644 --- a/testing/examples/state_tests.rs +++ b/testing/examples/state_tests.rs @@ -23,7 +23,7 @@ use sp_core::{crypto::Ss58Codec, sr25519}; use sp_keyring::AccountKeyring; use sp_staking::EraIndex; use substrate_api_client::{ - ac_primitives::AssetTipExtrinsicParams, rpc::JsonrpseeClient, Api, GetBlock, GetStorage, + ac_primitives::AssetTipExtrinsicParams, rpc::JsonrpseeClient, Api, GetChainInfo, GetStorage, }; type Balance = ::Balance;