Skip to main content

espresso_api/
lib.rs

1//! Espresso API server with both Axum (HTTP/JSON) and gRPC endpoints
2
3// Module declarations
4mod axum;
5pub mod error;
6pub mod handlers;
7mod tonic;
8pub mod v1;
9pub mod v2;
10
11// Generated gRPC service code - committed to git for visibility in code review
12pub mod proto {
13    include!("espresso.api.v2.rs");
14}
15
16// Re-exports
17pub use self::{
18    axum::{create_combined_router, create_router_v1, create_router_v2, routes},
19    tonic::create_reward_service,
20};
21
22/// Start Axum HTTP server with combined v1 and v2 APIs
23///
24/// This serves both APIs at /v1/* and /v2/* from a single state implementation.
25pub async fn serve_axum<S>(port: u16, state: S) -> anyhow::Result<()>
26where
27    S: v1::RewardApi
28        + v1::AvailabilityApi
29        + v1::HotShotAvailabilityApi
30        + v1::BlockStateApi
31        + v1::FeeStateApi
32        + v1::StatusApi
33        + v1::ConfigApi
34        + v1::NodeApi
35        + v1::CatchupApi
36        + v1::SubmitApi
37        + v1::StateSignatureApi
38        + v1::HotShotEventsApi
39        + v1::LightClientApi
40        + v1::ExplorerApi
41        + v1::TokenApi
42        + v1::DatabaseApi
43        + v2::RewardApi
44        + v2::DataApi
45        + v2::ConsensusApi
46        + Clone
47        + Send
48        + Sync
49        + 'static,
50{
51    tracing::info!("Starting Axum server on port {} with v1 and v2 APIs", port);
52
53    let app = create_combined_router(state);
54    let addr = format!("0.0.0.0:{}", port);
55
56    tracing::info!("Binding to {}", addr);
57    let listener = tokio::net::TcpListener::bind(&addr).await?;
58
59    tracing::info!(
60        "Axum API server listening on {} (v1 and v2 routes available)",
61        addr
62    );
63    ::axum::serve(listener, app.into_make_service()).await?;
64
65    tracing::info!("Axum server stopped");
66    Ok(())
67}
68
69/// Start Tonic gRPC server
70pub async fn serve_tonic<S>(port: u16, state: S) -> anyhow::Result<()>
71where
72    S: v2::RewardApi + Clone + Send + Sync + 'static,
73{
74    use ::tonic::transport::Server;
75
76    let addr = std::net::SocketAddr::from(([0, 0, 0, 0], port));
77
78    let reward_service = create_reward_service(state);
79
80    // Enable gRPC reflection for tools like grpcurl
81    let reflection_service = tonic_reflection::server::Builder::configure()
82        .register_encoded_file_descriptor_set(include_bytes!(concat!(
83            env!("OUT_DIR"),
84            "/reflection_descriptor.bin"
85        )))
86        .build_v1()?;
87
88    tracing::info!("gRPC server listening on {}", addr);
89    Server::builder()
90        .add_service(reward_service)
91        .add_service(reflection_service)
92        .serve(addr)
93        .await?;
94
95    Ok(())
96}