anvil/server/
mod.rs

1//! Contains the code to launch an Ethereum RPC server.
2
3use crate::{EthApi, IpcTask};
4use anvil_server::{ServerConfig, ipc::IpcEndpoint};
5use axum::{Router, routing::get};
6use futures::StreamExt;
7use handler::{HttpEthRpcHandler, PubSubEthRpcHandler};
8use std::{io, net::SocketAddr, pin::pin};
9use tokio::net::TcpListener;
10
11mod beacon_handler;
12pub mod error;
13mod handler;
14
15/// Configures a server that handles [`EthApi`] related JSON-RPC calls via HTTP and WS.
16///
17/// The returned future creates a new server, binding it to the given address, which returns another
18/// future that runs it.
19pub async fn serve(
20    addr: SocketAddr,
21    api: EthApi,
22    config: ServerConfig,
23) -> io::Result<impl Future<Output = io::Result<()>>> {
24    let tcp_listener = TcpListener::bind(addr).await?;
25    Ok(serve_on(tcp_listener, api, config))
26}
27
28/// Configures a server that handles [`EthApi`] related JSON-RPC calls via HTTP and WS.
29pub async fn serve_on(
30    tcp_listener: TcpListener,
31    api: EthApi,
32    config: ServerConfig,
33) -> io::Result<()> {
34    axum::serve(tcp_listener, router(api, config).into_make_service()).await
35}
36
37/// Configures an [`axum::Router`] that handles [`EthApi`] related JSON-RPC calls via HTTP and WS,
38/// and Beacon REST API calls.
39pub fn router(api: EthApi, config: ServerConfig) -> Router {
40    let http = HttpEthRpcHandler::new(api.clone());
41    let ws = PubSubEthRpcHandler::new(api.clone());
42
43    // JSON-RPC router
44    let rpc_router = anvil_server::http_ws_router(config, http, ws);
45
46    // Beacon REST API router
47    let beacon_router = beacon_router(api);
48
49    // Merge the routers
50    rpc_router.merge(beacon_router)
51}
52
53/// Configures an [`axum::Router`] that handles Beacon REST API calls.
54fn beacon_router(api: EthApi) -> Router {
55    Router::new()
56        .route(
57            "/eth/v1/beacon/blob_sidecars/{block_id}",
58            get(beacon_handler::handle_get_blob_sidecars),
59        )
60        .route("/eth/v1/beacon/blobs/{block_id}", get(beacon_handler::handle_get_blobs))
61        .with_state(api)
62}
63
64/// Launches an ipc server at the given path in a new task
65///
66/// # Panics
67///
68/// Panics if setting up the IPC connection was unsuccessful.
69#[track_caller]
70pub fn spawn_ipc(api: EthApi, path: String) -> IpcTask {
71    try_spawn_ipc(api, path).expect("failed to establish ipc connection")
72}
73
74/// Launches an ipc server at the given path in a new task.
75pub fn try_spawn_ipc(api: EthApi, path: String) -> io::Result<IpcTask> {
76    let handler = PubSubEthRpcHandler::new(api);
77    let ipc = IpcEndpoint::new(handler, path);
78    let incoming = ipc.incoming()?;
79
80    let task = tokio::task::spawn(async move {
81        let mut incoming = pin!(incoming);
82        while let Some(stream) = incoming.next().await {
83            trace!(target: "ipc", "new ipc connection");
84            tokio::task::spawn(stream);
85        }
86    });
87
88    Ok(task)
89}