substrate_api_client/api/rpc_api/
chain.rs

1/*
2   Copyright 2019 Supercomputing Systems AG
3   Licensed under the Apache License, Version 2.0 (the "License");
4   you may not use this file except in compliance with the License.
5   You may obtain a copy of the License at
6	   http://www.apache.org/licenses/LICENSE-2.0
7   Unless required by applicable law or agreed to in writing, software
8   distributed under the License is distributed on an "AS IS" BASIS,
9   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10   See the License for the specific language governing permissions and
11   limitations under the License.
12*/
13
14use crate::{
15	api::{Api, Result},
16	rpc::{Request, Subscribe},
17	Error,
18};
19use ac_compose_macros::rpc_params;
20use ac_primitives::config::Config;
21#[cfg(all(not(feature = "sync-api"), not(feature = "std")))]
22use alloc::boxed::Box;
23use alloc::vec::Vec;
24use log::*;
25use serde::de::DeserializeOwned;
26use sp_runtime::generic::SignedBlock;
27
28#[maybe_async::maybe_async(?Send)]
29pub trait GetChainInfo {
30	type BlockNumber;
31	type Hash;
32	type Header;
33	type Block;
34
35	async fn get_finalized_head(&self) -> Result<Option<Self::Hash>>;
36
37	async fn get_header(&self, hash: Option<Self::Hash>) -> Result<Option<Self::Header>>;
38
39	async fn get_block_hash(&self, number: Option<Self::BlockNumber>)
40		-> Result<Option<Self::Hash>>;
41
42	/// Returns the genesis block
43	async fn get_genesis_block(&self) -> Result<Self::Block>;
44
45	async fn get_block(&self, hash: Option<Self::Hash>) -> Result<Option<Self::Block>>;
46
47	async fn get_block_by_num(
48		&self,
49		number: Option<Self::BlockNumber>,
50	) -> Result<Option<Self::Block>>;
51
52	/// A signed block is a block with Justification ,i.e., a Grandpa finality proof.
53	/// The interval at which finality proofs are provided is set via the
54	/// the `GrandpaConfig.justification_period` in a node's service.rs.
55	/// The Justification may be None.
56	async fn get_signed_block(
57		&self,
58		hash: Option<Self::Hash>,
59	) -> Result<Option<SignedBlock<Self::Block>>>;
60
61	async fn get_signed_block_by_num(
62		&self,
63		number: Option<Self::BlockNumber>,
64	) -> Result<Option<SignedBlock<Self::Block>>>;
65
66	/// Get the last finalized signed block.
67	async fn get_finalized_block(&self) -> Result<Option<SignedBlock<Self::Block>>>;
68
69	/// Returns a vector containing the blocks with the block numbers given in the input parameter.
70	/// If fetching any of the block fails then a `Result::Err` will be returned.
71	async fn get_signed_blocks(
72		&self,
73		block_numbers: &[Self::BlockNumber],
74	) -> Result<Vec<SignedBlock<Self::Block>>>;
75}
76
77#[maybe_async::maybe_async(?Send)]
78impl<T, Client> GetChainInfo for Api<T, Client>
79where
80	T: Config,
81	Client: Request,
82{
83	type BlockNumber = T::BlockNumber;
84	type Hash = T::Hash;
85	type Header = T::Header;
86	type Block = T::Block;
87
88	async fn get_finalized_head(&self) -> Result<Option<Self::Hash>> {
89		let finalized_block_hash =
90			self.client().request("chain_getFinalizedHead", rpc_params![]).await?;
91		Ok(finalized_block_hash)
92	}
93
94	async fn get_header(&self, hash: Option<Self::Hash>) -> Result<Option<Self::Header>> {
95		let block_hash = self.client().request("chain_getHeader", rpc_params![hash]).await?;
96		Ok(block_hash)
97	}
98
99	async fn get_block_hash(
100		&self,
101		number: Option<Self::BlockNumber>,
102	) -> Result<Option<Self::Hash>> {
103		let block_hash = self.client().request("chain_getBlockHash", rpc_params![number]).await?;
104		Ok(block_hash)
105	}
106
107	async fn get_genesis_block(&self) -> Result<Self::Block> {
108		self.get_block(Some(self.genesis_hash())).await?.ok_or(Error::BlockHashNotFound)
109	}
110
111	async fn get_block(&self, hash: Option<Self::Hash>) -> Result<Option<Self::Block>> {
112		Self::get_signed_block(self, hash).await.map(|sb_opt| sb_opt.map(|sb| sb.block))
113	}
114
115	async fn get_block_by_num(
116		&self,
117		number: Option<Self::BlockNumber>,
118	) -> Result<Option<Self::Block>> {
119		Self::get_signed_block_by_num(self, number)
120			.await
121			.map(|sb_opt| sb_opt.map(|sb| sb.block))
122	}
123
124	async fn get_signed_block(
125		&self,
126		hash: Option<Self::Hash>,
127	) -> Result<Option<SignedBlock<Self::Block>>> {
128		let block = self.client().request("chain_getBlock", rpc_params![hash]).await?;
129		Ok(block)
130	}
131
132	async fn get_signed_block_by_num(
133		&self,
134		number: Option<Self::BlockNumber>,
135	) -> Result<Option<SignedBlock<Self::Block>>> {
136		self.get_block_hash(number).await.map(|h| self.get_signed_block(h))?.await
137	}
138
139	async fn get_finalized_block(&self) -> Result<Option<SignedBlock<Self::Block>>> {
140		let hash = self.get_finalized_head().await?;
141		match hash {
142			Some(hash) => self.get_signed_block(Some(hash)).await,
143			None => Ok(None),
144		}
145	}
146
147	async fn get_signed_blocks(
148		&self,
149		block_numbers: &[Self::BlockNumber],
150	) -> Result<Vec<SignedBlock<Self::Block>>> {
151		let mut blocks = Vec::<SignedBlock<Self::Block>>::new();
152
153		for n in block_numbers {
154			if let Some(block) = self.get_signed_block_by_num(Some(*n)).await? {
155				blocks.push(block);
156			}
157		}
158		Ok(blocks)
159	}
160}
161#[maybe_async::maybe_async(?Send)]
162pub trait SubscribeChain {
163	type Client: Subscribe;
164	type Header: DeserializeOwned;
165
166	async fn subscribe_finalized_heads(
167		&self,
168	) -> Result<<Self::Client as Subscribe>::Subscription<Self::Header>>;
169}
170
171#[maybe_async::maybe_async(?Send)]
172impl<T, Client> SubscribeChain for Api<T, Client>
173where
174	T: Config,
175	Client: Subscribe,
176{
177	type Client = Client;
178	type Header = T::Header;
179
180	async fn subscribe_finalized_heads(
181		&self,
182	) -> Result<<Self::Client as Subscribe>::Subscription<Self::Header>> {
183		debug!("subscribing to finalized heads");
184		self.client()
185			.subscribe(
186				"chain_subscribeFinalizedHeads",
187				rpc_params![],
188				"chain_unsubscribeFinalizedHeads",
189			)
190			.await
191			.map_err(|e| e.into())
192	}
193}