reth_rpc_eth_api/helpers/
spec.rs

1//! Loads chain metadata.
2
3use alloy_primitives::{Address, U256, U64};
4use alloy_rpc_types_eth::{Stage, SyncInfo, SyncStatus};
5use futures::Future;
6use reth_chainspec::{ChainInfo, EthereumHardforks};
7use reth_errors::{RethError, RethResult};
8use reth_network_api::NetworkInfo;
9use reth_provider::{BlockNumReader, ChainSpecProvider, StageCheckpointReader};
10
11use crate::{helpers::EthSigner, RpcNodeCore};
12
13/// `Eth` API trait.
14///
15/// Defines core functionality of the `eth` API implementation.
16#[auto_impl::auto_impl(&, Arc)]
17pub trait EthApiSpec:
18    RpcNodeCore<
19    Provider: ChainSpecProvider<ChainSpec: EthereumHardforks>
20                  + BlockNumReader
21                  + StageCheckpointReader,
22    Network: NetworkInfo,
23>
24{
25    /// The transaction type signers are using.
26    type Transaction;
27
28    /// Returns the block node is started on.
29    fn starting_block(&self) -> U256;
30
31    /// Returns a handle to the signers owned by provider.
32    fn signers(&self) -> &parking_lot::RwLock<Vec<Box<dyn EthSigner<Self::Transaction>>>>;
33
34    /// Returns the current ethereum protocol version.
35    fn protocol_version(&self) -> impl Future<Output = RethResult<U64>> + Send {
36        async move {
37            let status = self.network().network_status().await.map_err(RethError::other)?;
38            Ok(U64::from(status.protocol_version))
39        }
40    }
41
42    /// Returns the chain id
43    fn chain_id(&self) -> U64 {
44        U64::from(self.network().chain_id())
45    }
46
47    /// Returns provider chain info
48    fn chain_info(&self) -> RethResult<ChainInfo> {
49        Ok(self.provider().chain_info()?)
50    }
51
52    /// Returns a list of addresses owned by provider.
53    fn accounts(&self) -> Vec<Address> {
54        self.signers().read().iter().flat_map(|s| s.accounts()).collect()
55    }
56
57    /// Returns `true` if the network is undergoing sync.
58    fn is_syncing(&self) -> bool {
59        self.network().is_syncing()
60    }
61
62    /// Returns the [`SyncStatus`] of the network
63    fn sync_status(&self) -> RethResult<SyncStatus> {
64        let status = if self.is_syncing() {
65            let current_block = U256::from(
66                self.provider().chain_info().map(|info| info.best_number).unwrap_or_default(),
67            );
68
69            let stages = self
70                .provider()
71                .get_all_checkpoints()
72                .unwrap_or_default()
73                .into_iter()
74                .map(|(name, checkpoint)| Stage { name, block: checkpoint.block_number })
75                .collect();
76
77            SyncStatus::Info(Box::new(SyncInfo {
78                starting_block: self.starting_block(),
79                current_block,
80                highest_block: current_block,
81                warp_chunks_amount: None,
82                warp_chunks_processed: None,
83                stages: Some(stages),
84            }))
85        } else {
86            SyncStatus::None
87        };
88        Ok(status)
89    }
90}