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}