use crate::{EthApi, IpcTask};
use anvil_server::{ipc::IpcEndpoint, ServerConfig};
use axum::Router;
use futures::StreamExt;
use handler::{HttpEthRpcHandler, PubSubEthRpcHandler};
use std::{future::Future, io, net::SocketAddr, pin::pin};
use tokio::net::TcpListener;
pub mod error;
mod handler;
pub async fn serve(
addr: SocketAddr,
api: EthApi,
config: ServerConfig,
) -> io::Result<impl Future<Output = io::Result<()>>> {
let tcp_listener = TcpListener::bind(addr).await?;
Ok(serve_on(tcp_listener, api, config))
}
pub async fn serve_on(
tcp_listener: TcpListener,
api: EthApi,
config: ServerConfig,
) -> io::Result<()> {
axum::serve(tcp_listener, router(api, config).into_make_service()).await
}
pub fn router(api: EthApi, config: ServerConfig) -> Router {
let http = HttpEthRpcHandler::new(api.clone());
let ws = PubSubEthRpcHandler::new(api);
anvil_server::http_ws_router(config, http, ws)
}
#[track_caller]
pub fn spawn_ipc(api: EthApi, path: String) -> IpcTask {
try_spawn_ipc(api, path).expect("failed to establish ipc connection")
}
pub fn try_spawn_ipc(api: EthApi, path: String) -> io::Result<IpcTask> {
let handler = PubSubEthRpcHandler::new(api);
let ipc = IpcEndpoint::new(handler, path);
let incoming = ipc.incoming()?;
let task = tokio::task::spawn(async move {
let mut incoming = pin!(incoming);
while let Some(stream) = incoming.next().await {
trace!(target: "ipc", "new ipc connection");
tokio::task::spawn(stream);
}
});
Ok(task)
}