1use crate::{EthApi, IpcTask};
5use anvil_server::{ServerConfig, ipc::IpcEndpoint};
6use axum::Router;
7use foundry_primitives::FoundryNetwork;
8use futures::StreamExt;
9use rpc_handlers::{HttpEthRpcHandler, PubSubEthRpcHandler};
10use std::{io, net::SocketAddr, pin::pin};
11use tokio::net::TcpListener;
12
13mod beacon;
14mod rpc_handlers;
15
16pub async fn serve(
21 addr: SocketAddr,
22 api: EthApi<FoundryNetwork>,
23 config: ServerConfig,
24) -> io::Result<impl Future<Output = io::Result<()>>> {
25 let tcp_listener = TcpListener::bind(addr).await?;
26 Ok(serve_on(tcp_listener, api, config))
27}
28
29pub async fn serve_on(
31 tcp_listener: TcpListener,
32 api: EthApi<FoundryNetwork>,
33 config: ServerConfig,
34) -> io::Result<()> {
35 axum::serve(tcp_listener, router(api, config).into_make_service()).await
36}
37
38pub fn router(api: EthApi<FoundryNetwork>, config: ServerConfig) -> Router {
41 let http = HttpEthRpcHandler::new(api.clone());
42 let ws = PubSubEthRpcHandler::new(api.clone());
43
44 let rpc_router = anvil_server::http_ws_router(config, http, ws);
46
47 let beacon_router = beacon::router(api);
49
50 rpc_router.merge(beacon_router)
52}
53
54#[track_caller]
60pub fn spawn_ipc(api: EthApi<FoundryNetwork>, path: String) -> IpcTask {
61 try_spawn_ipc(api, path).expect("failed to establish ipc connection")
62}
63
64pub fn try_spawn_ipc(api: EthApi<FoundryNetwork>, path: String) -> io::Result<IpcTask> {
66 let handler = PubSubEthRpcHandler::new(api);
67 let ipc = IpcEndpoint::new(handler, path);
68 let incoming = ipc.incoming()?;
69
70 let task = tokio::task::spawn(async move {
71 let mut incoming = pin!(incoming);
72 while let Some(stream) = incoming.next().await {
73 trace!(target: "ipc", "new ipc connection");
74 tokio::task::spawn(stream);
75 }
76 });
77
78 Ok(task)
79}