1use crate::{
4 eth::{core::EthApiInner, EthTxBuilder},
5 EthApi,
6};
7use reth_chain_state::CanonStateSubscriptions;
8use reth_chainspec::ChainSpecProvider;
9use reth_node_api::NodePrimitives;
10use reth_rpc_eth_types::{
11 fee_history::fee_history_cache_new_blocks_task, EthStateCache, EthStateCacheConfig,
12 FeeHistoryCache, FeeHistoryCacheConfig, GasCap, GasPriceOracle, GasPriceOracleConfig,
13};
14use reth_rpc_server_types::constants::{
15 DEFAULT_ETH_PROOF_WINDOW, DEFAULT_MAX_SIMULATE_BLOCKS, DEFAULT_PROOF_PERMITS,
16};
17use reth_storage_api::{BlockReaderIdExt, StateProviderFactory};
18use reth_tasks::{pool::BlockingTaskPool, TaskSpawner, TokioTaskExecutor};
19use std::sync::Arc;
20
21#[derive(Debug)]
26pub struct EthApiBuilder<Provider, Pool, Network, EvmConfig>
27where
28 Provider: BlockReaderIdExt,
29{
30 provider: Provider,
31 pool: Pool,
32 network: Network,
33 evm_config: EvmConfig,
34 gas_cap: GasCap,
35 max_simulate_blocks: u64,
36 eth_proof_window: u64,
37 fee_history_cache_config: FeeHistoryCacheConfig,
38 proof_permits: usize,
39 eth_state_cache_config: EthStateCacheConfig,
40 eth_cache: Option<EthStateCache<Provider::Block, Provider::Receipt>>,
41 gas_oracle_config: GasPriceOracleConfig,
42 gas_oracle: Option<GasPriceOracle<Provider>>,
43 blocking_task_pool: Option<BlockingTaskPool>,
44 task_spawner: Box<dyn TaskSpawner + 'static>,
45}
46
47impl<Provider, Pool, Network, EvmConfig> EthApiBuilder<Provider, Pool, Network, EvmConfig>
48where
49 Provider: BlockReaderIdExt,
50{
51 pub fn new(provider: Provider, pool: Pool, network: Network, evm_config: EvmConfig) -> Self
53 where
54 Provider: BlockReaderIdExt,
55 {
56 Self {
57 provider,
58 pool,
59 network,
60 evm_config,
61 eth_cache: None,
62 gas_oracle: None,
63 gas_cap: GasCap::default(),
64 max_simulate_blocks: DEFAULT_MAX_SIMULATE_BLOCKS,
65 eth_proof_window: DEFAULT_ETH_PROOF_WINDOW,
66 blocking_task_pool: None,
67 fee_history_cache_config: FeeHistoryCacheConfig::default(),
68 proof_permits: DEFAULT_PROOF_PERMITS,
69 task_spawner: TokioTaskExecutor::default().boxed(),
70 gas_oracle_config: Default::default(),
71 eth_state_cache_config: Default::default(),
72 }
73 }
74
75 pub fn task_spawner(mut self, spawner: impl TaskSpawner + 'static) -> Self {
77 self.task_spawner = Box::new(spawner);
78 self
79 }
80
81 pub const fn eth_state_cache_config(
84 mut self,
85 eth_state_cache_config: EthStateCacheConfig,
86 ) -> Self {
87 self.eth_state_cache_config = eth_state_cache_config;
88 self
89 }
90
91 pub fn eth_cache(
93 mut self,
94 eth_cache: EthStateCache<Provider::Block, Provider::Receipt>,
95 ) -> Self {
96 self.eth_cache = Some(eth_cache);
97 self
98 }
99
100 pub const fn gas_oracle_config(mut self, gas_oracle_config: GasPriceOracleConfig) -> Self {
103 self.gas_oracle_config = gas_oracle_config;
104 self
105 }
106
107 pub fn gas_oracle(mut self, gas_oracle: GasPriceOracle<Provider>) -> Self {
109 self.gas_oracle = Some(gas_oracle);
110 self
111 }
112
113 pub const fn gas_cap(mut self, gas_cap: GasCap) -> Self {
115 self.gas_cap = gas_cap;
116 self
117 }
118
119 pub const fn max_simulate_blocks(mut self, max_simulate_blocks: u64) -> Self {
121 self.max_simulate_blocks = max_simulate_blocks;
122 self
123 }
124
125 pub const fn eth_proof_window(mut self, eth_proof_window: u64) -> Self {
127 self.eth_proof_window = eth_proof_window;
128 self
129 }
130
131 pub fn blocking_task_pool(mut self, blocking_task_pool: BlockingTaskPool) -> Self {
133 self.blocking_task_pool = Some(blocking_task_pool);
134 self
135 }
136
137 pub const fn fee_history_cache_config(
139 mut self,
140 fee_history_cache_config: FeeHistoryCacheConfig,
141 ) -> Self {
142 self.fee_history_cache_config = fee_history_cache_config;
143 self
144 }
145
146 pub const fn proof_permits(mut self, proof_permits: usize) -> Self {
148 self.proof_permits = proof_permits;
149 self
150 }
151
152 pub fn build_inner(self) -> EthApiInner<Provider, Pool, Network, EvmConfig>
161 where
162 Provider: BlockReaderIdExt
163 + StateProviderFactory
164 + ChainSpecProvider
165 + CanonStateSubscriptions<
166 Primitives: NodePrimitives<Block = Provider::Block, Receipt = Provider::Receipt>,
167 > + Clone
168 + Unpin
169 + 'static,
170 {
171 let Self {
172 provider,
173 pool,
174 network,
175 evm_config,
176 eth_state_cache_config,
177 gas_oracle_config,
178 eth_cache,
179 gas_oracle,
180 gas_cap,
181 max_simulate_blocks,
182 eth_proof_window,
183 blocking_task_pool,
184 fee_history_cache_config,
185 proof_permits,
186 task_spawner,
187 } = self;
188
189 let eth_cache = eth_cache
190 .unwrap_or_else(|| EthStateCache::spawn(provider.clone(), eth_state_cache_config));
191 let gas_oracle = gas_oracle.unwrap_or_else(|| {
192 GasPriceOracle::new(provider.clone(), gas_oracle_config, eth_cache.clone())
193 });
194 let fee_history_cache = FeeHistoryCache::new(fee_history_cache_config);
195 let new_canonical_blocks = provider.canonical_state_stream();
196 let fhc = fee_history_cache.clone();
197 let cache = eth_cache.clone();
198 let prov = provider.clone();
199 task_spawner.spawn_critical(
200 "cache canonical blocks for fee history task",
201 Box::pin(async move {
202 fee_history_cache_new_blocks_task(fhc, new_canonical_blocks, prov, cache).await;
203 }),
204 );
205
206 EthApiInner::new(
207 provider,
208 pool,
209 network,
210 eth_cache,
211 gas_oracle,
212 gas_cap,
213 max_simulate_blocks,
214 eth_proof_window,
215 blocking_task_pool.unwrap_or_else(|| {
216 BlockingTaskPool::build().expect("failed to build blocking task pool")
217 }),
218 fee_history_cache,
219 evm_config,
220 task_spawner,
221 proof_permits,
222 )
223 }
224
225 pub fn build(self) -> EthApi<Provider, Pool, Network, EvmConfig>
234 where
235 Provider: BlockReaderIdExt
236 + StateProviderFactory
237 + CanonStateSubscriptions<
238 Primitives: NodePrimitives<Block = Provider::Block, Receipt = Provider::Receipt>,
239 > + ChainSpecProvider
240 + Clone
241 + Unpin
242 + 'static,
243 {
244 EthApi { inner: Arc::new(self.build_inner()), tx_resp_builder: EthTxBuilder }
245 }
246}