Skip to main content

avail_rust_client/chain/
finalized.rs

1use crate::{Client, Error, block, chain::Chain};
2use avail_rust_core::{
3	AccountIdLike, AvailHeader, BlockInfo, H256, RpcError,
4	avail::{balances::types::AccountData, system::types::AccountInfo},
5	rpc::LegacyBlock,
6};
7
8/// Helper bound to the chain's latest finalized block view.
9pub struct Finalized {
10	chain: Chain,
11}
12
13impl Finalized {
14	/// Builds a helper focused on finalised blocks.
15	///
16	/// # Arguments
17	/// * `client` - Client used to perform RPC calls.
18	///
19	/// # Returns
20	/// Returns a [`Finalized`] helper that honours the client's retry settings.
21	pub fn new(client: Client) -> Self {
22		let chain = Chain::new(client).retry_on(None, Some(true));
23		Self { chain }
24	}
25
26	/// Overrides whether upcoming calls retry after RPC errors.
27	///
28	/// # Arguments
29	/// * `error` - `Some(true)` to force retries, `Some(false)` to disable retries, `None` to inherit defaults.
30	///
31	/// # Returns
32	/// Returns the helper with the updated retry preference.
33	pub fn retry_on(mut self, error: Option<bool>) -> Self {
34		self.chain = self.chain.retry_on(error, Some(true));
35		self
36	}
37
38	/// Returns the hash of the latest finalised block.
39	///
40	/// # Returns
41	/// Returns the block hash recorded for the most recently finalised block.
42	///
43	/// # Errors
44	/// Propagates any RPC error encountered while fetching block information.
45	pub async fn block_hash(&self) -> Result<H256, RpcError> {
46		self.block_info().await.map(|x| x.hash)
47	}
48
49	/// Returns the height of the latest finalised block.
50	///
51	/// # Returns
52	/// Returns the block number recorded for the most recently finalised block.
53	///
54	/// # Errors
55	/// Propagates any RPC error encountered while fetching block information.
56	pub async fn block_height(&self) -> Result<u32, RpcError> {
57		self.block_info().await.map(|x| x.height)
58	}
59
60	/// Returns the latest finalised block header.
61	///
62	/// # Returns
63	/// Returns the header associated with the finalised block.
64	///
65	/// # Errors
66	/// Returns `Err(Error)` when the node does not provide a header or the RPC call fails.
67	pub async fn block_header(&self) -> Result<AvailHeader, Error> {
68		let block_hash = self.block_hash().await?;
69		let block_header = self.chain.block_header(Some(block_hash)).await?;
70		let Some(block_header) = block_header else {
71			return Err(RpcError::ExpectedData("Failed to fetch finalized block header".into()).into());
72		};
73
74		Ok(block_header)
75	}
76
77	/// Returns a block helper bound to the latest finalised block.
78	///
79	/// # Returns
80	/// Returns a [`block::Block`] helper scoped to the finalised block.
81	///
82	/// # Errors
83	/// Returns `Err(Error)` when the block hash cannot be fetched.
84	pub async fn block(&self) -> Result<block::Block, Error> {
85		let block_hash = self.block_hash().await?;
86		Ok(block::Block::new(self.chain.client.clone(), block_hash))
87	}
88
89	/// Returns height and hash for the latest finalised block.
90	///
91	/// # Returns
92	/// Returns [`BlockInfo`] describing the most recently finalised block.
93	///
94	/// # Errors
95	/// Propagates any RPC error encountered while fetching block information.
96	pub async fn block_info(&self) -> Result<BlockInfo, RpcError> {
97		self.chain.block_info(false).await
98	}
99
100	/// Loads the legacy block view for the latest finalised block.
101	///
102	/// # Returns
103	/// Returns the legacy block representation for the finalised block.
104	///
105	/// # Errors
106	/// Returns `Err(RpcError::ExpectedData)` when the node reports no legacy block for the finalised height.
107	pub async fn legacy_block(&self) -> Result<LegacyBlock, RpcError> {
108		let block_hash = self.block_hash().await?;
109		let block = self.chain.legacy_block(Some(block_hash)).await?;
110		let Some(block) = block else {
111			return Err(RpcError::ExpectedData("Failed to fetch finalized legacy block".into()));
112		};
113
114		Ok(block)
115	}
116
117	/// Returns the latest finalised nonce for the account.
118	///
119	/// # Arguments
120	/// * `account_id` - Account identifier convertible into `AccountIdLike`.
121	///
122	/// # Returns
123	/// Returns the account nonce observed at the finalised block.
124	///
125	/// # Errors
126	/// Returns `Err(Error)` when the account cannot be parsed or the RPC call fails.
127	pub async fn account_nonce(&self, account_id: impl Into<AccountIdLike>) -> Result<u32, Error> {
128		self.account_info(account_id).await.map(|v| v.nonce)
129	}
130
131	/// Returns account balances from the latest finalised block.
132	///
133	/// # Arguments
134	/// * `account_id` - Account identifier convertible into `AccountIdLike`.
135	///
136	/// # Returns
137	/// Returns [`AccountData`] describing balances observed at the finalised block.
138	///
139	/// # Errors
140	/// Returns `Err(Error)` when the account cannot be parsed or the RPC call fails.
141	pub async fn account_balance(&self, account_id: impl Into<AccountIdLike>) -> Result<AccountData, Error> {
142		self.account_info(account_id).await.map(|x| x.data)
143	}
144
145	/// Returns the full account record from the latest finalised block.
146	///
147	/// # Arguments
148	/// * `account_id` - Account identifier convertible into `AccountIdLike`.
149	///
150	/// # Returns
151	/// Returns [`AccountInfo`] mirroring the state at the finalised block.
152	///
153	/// # Errors
154	/// Returns `Err(Error)` when the account cannot be parsed or the RPC call fails.
155	pub async fn account_info(&self, account_id: impl Into<AccountIdLike>) -> Result<AccountInfo, Error> {
156		let at = self.block_hash().await?;
157		self.chain.account_info(account_id, at).await
158	}
159
160	/// Reports whether finalised-block queries retry after RPC errors.
161	///
162	/// # Returns
163	/// Returns `true` when retries are enabled, otherwise `false`.
164	pub fn should_retry_on_error(&self) -> bool {
165		self.chain.should_retry_on_error()
166	}
167}