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