use reth_evm::ConfigureEvm;
use reth_provider::{BlockReader, CanonStateSubscriptions, EvmEnvProvider, StateProviderFactory};
use reth_rpc::{EthFilter, EthPubSub};
use reth_rpc_eth_types::{
cache::cache_new_blocks_task, EthApiBuilderCtx, EthConfig, EthStateCache,
};
use reth_tasks::TaskSpawner;
pub type DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi> =
Box<dyn Fn(&EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>) -> EthApi>;
#[derive(Debug, Clone)]
pub struct EthHandlers<Provider, Pool, Network, Events, EthApi> {
pub api: EthApi,
pub cache: EthStateCache,
pub filter: EthFilter<Provider, Pool>,
pub pubsub: EthPubSub<Provider, Pool, Events, Network>,
}
impl<Provider, Pool, Network, Events, EthApi> EthHandlers<Provider, Pool, Network, Events, EthApi> {
#[allow(clippy::too_many_arguments)]
pub fn builder<EvmConfig, Tasks>(
provider: Provider,
pool: Pool,
network: Network,
evm_config: EvmConfig,
config: EthConfig,
executor: Tasks,
events: Events,
eth_api_builder: DynEthApiBuilder<
Provider,
Pool,
EvmConfig,
Network,
Tasks,
Events,
EthApi,
>,
) -> EthHandlersBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi> {
EthHandlersBuilder {
provider,
pool,
network,
evm_config,
config,
executor,
events,
eth_api_builder,
}
}
}
#[allow(missing_debug_implementations)]
pub struct EthHandlersBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi> {
provider: Provider,
pool: Pool,
network: Network,
evm_config: EvmConfig,
config: EthConfig,
executor: Tasks,
events: Events,
eth_api_builder: DynEthApiBuilder<Provider, Pool, EvmConfig, Network, Tasks, Events, EthApi>,
}
impl<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi>
EthHandlersBuilder<Provider, Pool, Network, Tasks, Events, EvmConfig, EthApi>
where
Provider: StateProviderFactory + BlockReader + EvmEnvProvider + Clone + Unpin + 'static,
Pool: Send + Sync + Clone + 'static,
EvmConfig: ConfigureEvm,
Network: Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,
Events: CanonStateSubscriptions + Clone + 'static,
EthApi: 'static,
{
pub fn build(self) -> EthHandlers<Provider, Pool, Network, Events, EthApi> {
let Self { provider, pool, network, evm_config, config, executor, events, eth_api_builder } =
self;
let cache = EthStateCache::spawn_with(
provider.clone(),
config.cache,
executor.clone(),
evm_config.clone(),
);
let new_canonical_blocks = events.canonical_state_stream();
let c = cache.clone();
executor.spawn_critical(
"cache canonical blocks task",
Box::pin(async move {
cache_new_blocks_task(c, new_canonical_blocks).await;
}),
);
let ctx = EthApiBuilderCtx {
provider,
pool,
network,
evm_config,
config,
executor,
events,
cache,
};
let api = eth_api_builder(&ctx);
let filter = EthFilterApiBuilder::build(&ctx);
let pubsub = EthPubSubApiBuilder::build(&ctx);
EthHandlers { api, cache: ctx.cache, filter, pubsub }
}
}
#[derive(Debug)]
pub struct EthFilterApiBuilder;
impl EthFilterApiBuilder {
pub fn build<Provider, Pool, EvmConfig, Network, Tasks, Events>(
ctx: &EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>,
) -> EthFilter<Provider, Pool>
where
Provider: Send + Sync + Clone + 'static,
Pool: Send + Sync + Clone + 'static,
Tasks: TaskSpawner + Clone + 'static,
{
EthFilter::new(
ctx.provider.clone(),
ctx.pool.clone(),
ctx.cache.clone(),
ctx.config.filter_config(),
Box::new(ctx.executor.clone()),
)
}
}
#[derive(Debug)]
pub struct EthPubSubApiBuilder;
impl EthPubSubApiBuilder {
pub fn build<Provider, Pool, EvmConfig, Network, Tasks, Events>(
ctx: &EthApiBuilderCtx<Provider, Pool, EvmConfig, Network, Tasks, Events>,
) -> EthPubSub<Provider, Pool, Events, Network>
where
Provider: Clone,
Pool: Clone,
Events: Clone,
Network: Clone,
Tasks: TaskSpawner + Clone + 'static,
{
EthPubSub::with_spawner(
ctx.provider.clone(),
ctx.pool.clone(),
ctx.events.clone(),
ctx.network.clone(),
Box::new(ctx.executor.clone()),
)
}
}