reth_rpc_eth_api/helpers/
spec.rs1use 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#[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 type Transaction;
28
29 type Rpc: RpcTypes;
31
32 fn starting_block(&self) -> U256;
34
35 fn signers(&self) -> &SignersForApi<Self>;
37
38 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 fn chain_id(&self) -> U64 {
48 U64::from(self.network().chain_id())
49 }
50
51 fn chain_info(&self) -> RethResult<ChainInfo> {
53 Ok(self.provider().chain_info()?)
54 }
55
56 fn accounts(&self) -> Vec<Address> {
58 self.signers().read().iter().flat_map(|s| s.accounts()).collect()
59 }
60
61 fn is_syncing(&self) -> bool {
63 self.network().is_syncing()
64 }
65
66 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
96pub type SignersForApi<Api> = parking_lot::RwLock<
98 Vec<Box<dyn EthSigner<<Api as EthApiSpec>::Transaction, RpcTxReq<<Api as EthApiSpec>::Rpc>>>>,
99>;
100
101pub type SignersForRpc<Provider, Rpc> = parking_lot::RwLock<
104 Vec<Box<dyn EthSigner<<Provider as TransactionsProvider>::Transaction, RpcTxReq<Rpc>>>>,
105>;