Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand chain api #538

Merged
merged 8 commits into from
Apr 19, 2023
Merged
2 changes: 1 addition & 1 deletion examples/examples/compose_extrinsic_offline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion examples/examples/custom_nonce.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
22 changes: 16 additions & 6 deletions examples/examples/get_blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -33,16 +33,26 @@ async fn main() {
let api =
Api::<sr25519::Pair, _, PlainTipExtrinsicParams<Runtime>, 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());

Expand Down
2 changes: 1 addition & 1 deletion src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
1 change: 1 addition & 0 deletions src/api/rpc_api/author.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ where
Runtime: FrameSystemConfig + GetRuntimeBlockType,
Runtime::RuntimeBlock: BlockTrait + DeserializeOwned,
Runtime::Hashing: HashTrait<Output = Runtime::Hash>,
Runtime::Header: DeserializeOwned,
haerdib marked this conversation as resolved.
Show resolved Hide resolved
{
type Client = Client;
type Hash = Runtime::Hash;
Expand Down
85 changes: 55 additions & 30 deletions src/api/rpc_api/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Option<Self::Hash>>;

fn get_header(&self, hash: Option<Self::Hash>) -> Result<Option<Self::Header>>;
}

impl<Signer, Client, Params, Runtime> GetHeader for Api<Signer, Client, Params, Runtime>
where
Client: Request,
Runtime: FrameSystemConfig,
Params: ExtrinsicParams<Runtime::Index, Runtime::Hash>,
Runtime::Header: DeserializeOwned,
{
type Hash = Runtime::Hash;
type Header = Runtime::Header;

fn get_finalized_head(&self) -> Result<Option<Self::Hash>> {
let finalized_block_hash =
self.client().request("chain_getFinalizedHead", rpc_params![])?;
Ok(finalized_block_hash)
}

fn get_header(&self, hash: Option<Self::Hash>) -> Result<Option<Self::Header>> {
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<Self::BlockNumber>) -> Result<Option<Self::Hash>>;

/// Returns the genesis block
fn get_genesis_block(&self) -> Result<Self::Block>;

fn get_block(&self, hash: Option<Self::Hash>) -> Result<Option<Self::Block>>;

fn get_block_by_num(&self, number: Option<Self::BlockNumber>) -> Result<Option<Self::Block>>;
Expand All @@ -76,24 +55,51 @@ pub trait GetBlock {
&self,
number: Option<Self::BlockNumber>,
) -> Result<Option<SignedBlock<Self::Block>>>;

/// Get the last finalized signed block.
fn get_finalized_block(&self) -> Result<Option<SignedBlock<Self::Block>>>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add some comments? E.g. /// Get the last finalized signed block.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


/// 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<Vec<SignedBlock<Self::Block>>>;
}

impl<Signer, Client, Params, Runtime> GetBlock for Api<Signer, Client, Params, Runtime>
impl<Signer, Client, Params, Runtime> GetChainInfo for Api<Signer, Client, Params, Runtime>
where
Client: Request,
Runtime: FrameSystemConfig + GetRuntimeBlockType,
Params: ExtrinsicParams<Runtime::Index, Runtime::Hash>,
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<Option<Self::Hash>> {
let finalized_block_hash =
self.client().request("chain_getFinalizedHead", rpc_params![])?;
Ok(finalized_block_hash)
}

fn get_header(&self, hash: Option<Self::Hash>) -> Result<Option<Self::Header>> {
let block_hash = self.client().request("chain_getHeader", rpc_params![hash])?;
Ok(block_hash)
}

fn get_block_hash(&self, number: Option<Self::BlockNumber>) -> Result<Option<Self::Hash>> {
let block_hash = self.client().request("chain_getBlockHash", rpc_params![number])?;
Ok(block_hash)
}

fn get_genesis_block(&self) -> Result<Self::Block> {
self.get_block(Some(self.genesis_hash()))?.ok_or(Error::BlockHashNotFound)
}

fn get_block(&self, hash: Option<Self::Hash>) -> Result<Option<Self::Block>> {
Self::get_signed_block(self, hash).map(|sb_opt| sb_opt.map(|sb| sb.block))
}
Expand All @@ -116,6 +122,25 @@ where
) -> Result<Option<SignedBlock<Self::Block>>> {
self.get_block_hash(number).map(|h| self.get_signed_block(h))?
}

fn get_finalized_block(&self) -> Result<Option<SignedBlock<Self::Block>>> {
self.get_finalized_head()?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this, two prior independent traits are now not independent anymore. Since GetHeader is so small anyway, it might be sensible to merge these two traits to a GetChain Trait.

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think merging the traits makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merged the two traits now into the new GetChainInfo trait

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thanks !

.map_or_else(|| Ok(None), |hash| self.get_signed_block(Some(hash)))
}

fn get_signed_blocks(
&self,
block_numbers: &[Self::BlockNumber],
) -> Result<Vec<SignedBlock<Self::Block>>> {
let mut blocks = Vec::<SignedBlock<Self::Block>>::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;
Expand Down
4 changes: 3 additions & 1 deletion src/api/rpc_api/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -50,6 +50,7 @@ where
Runtime: FrameSystemConfig + GetRuntimeBlockType,
Runtime::RuntimeBlock: BlockTrait + DeserializeOwned,
Runtime::Hashing: HashTrait<Output = Runtime::Hash>,
Runtime::Header: DeserializeOwned,
haerdib marked this conversation as resolved.
Show resolved Hide resolved
{
type Hash = Runtime::Hash;

Expand Down Expand Up @@ -159,6 +160,7 @@ where
Runtime: FrameSystemConfig + GetRuntimeBlockType,
Runtime::RuntimeBlock: BlockTrait + DeserializeOwned,
Runtime::Hashing: HashTrait<Output = Runtime::Hash>,
Runtime::Header: DeserializeOwned,
haerdib marked this conversation as resolved.
Show resolved Hide resolved
{
/// Retrieve block details from node and search for the position of the given extrinsic.
fn retrieve_extrinsic_index_from_block(
Expand Down
6 changes: 2 additions & 4 deletions testing/examples/chain_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -31,12 +31,10 @@ async fn main() {
let mut api = Api::<_, _, AssetTipExtrinsicParams<Runtime>, 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();
Expand Down
2 changes: 1 addition & 1 deletion testing/examples/events_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion testing/examples/pallet_transaction_payment_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use substrate_api_client::{
ac_primitives::{AssetTipExtrinsicParams, ExtrinsicSigner},
extrinsic::BalancesExtrinsics,
rpc::JsonrpseeClient,
Api, GetBlock, GetTransactionPayment,
Api, GetChainInfo, GetTransactionPayment,
};

#[tokio::main]
Expand Down
2 changes: 1 addition & 1 deletion testing/examples/state_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <Runtime as pallet_balances::Config>::Balance;
Expand Down