reth_rpc_eth_api/helpers/
spec.rsuse alloy_primitives::{Address, U256, U64};
use alloy_rpc_types_eth::{Stage, SyncInfo, SyncStatus};
use futures::Future;
use reth_chainspec::{ChainInfo, EthereumHardforks};
use reth_errors::{RethError, RethResult};
use reth_network_api::NetworkInfo;
use reth_provider::{BlockNumReader, ChainSpecProvider, StageCheckpointReader};
use crate::{helpers::EthSigner, RpcNodeCore};
#[auto_impl::auto_impl(&, Arc)]
pub trait EthApiSpec:
RpcNodeCore<
Provider: ChainSpecProvider<ChainSpec: EthereumHardforks>
+ BlockNumReader
+ StageCheckpointReader,
Network: NetworkInfo,
>
{
type Transaction;
fn starting_block(&self) -> U256;
fn signers(&self) -> &parking_lot::RwLock<Vec<Box<dyn EthSigner<Self::Transaction>>>>;
fn protocol_version(&self) -> impl Future<Output = RethResult<U64>> + Send {
async move {
let status = self.network().network_status().await.map_err(RethError::other)?;
Ok(U64::from(status.protocol_version))
}
}
fn chain_id(&self) -> U64 {
U64::from(self.network().chain_id())
}
fn chain_info(&self) -> RethResult<ChainInfo> {
Ok(self.provider().chain_info()?)
}
fn accounts(&self) -> Vec<Address> {
self.signers().read().iter().flat_map(|s| s.accounts()).collect()
}
fn is_syncing(&self) -> bool {
self.network().is_syncing()
}
fn sync_status(&self) -> RethResult<SyncStatus> {
let status = if self.is_syncing() {
let current_block = U256::from(
self.provider().chain_info().map(|info| info.best_number).unwrap_or_default(),
);
let stages = self
.provider()
.get_all_checkpoints()
.unwrap_or_default()
.into_iter()
.map(|(name, checkpoint)| Stage { name, block: checkpoint.block_number })
.collect();
SyncStatus::Info(Box::new(SyncInfo {
starting_block: self.starting_block(),
current_block,
highest_block: current_block,
warp_chunks_amount: None,
warp_chunks_processed: None,
stages: Some(stages),
}))
} else {
SyncStatus::None
};
Ok(status)
}
}