105 lines
3.2 KiB
Rust
105 lines
3.2 KiB
Rust
use crate::{datastore, datastore::State, solana::SolClient};
|
|
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
|
|
use chrono::{DateTime, Utc};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::sync::Arc;
|
|
|
|
const HOMEPAGE: &str = include_str!("HOMEPAGE.md");
|
|
|
|
#[get("/")]
|
|
async fn homepage(sol_client: web::Data<Arc<SolClient>>) -> impl Responder {
|
|
let text = HOMEPAGE
|
|
.to_string()
|
|
.replace("TOKEN_ADDRESS", &sol_client.get_token_address())
|
|
.replace("MINT_AUTHORITY", &sol_client.get_wallet_pubkey());
|
|
HttpResponse::Ok().body(text)
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
pub struct NodesResp {
|
|
pub ip: String,
|
|
pub joined_at: String,
|
|
pub last_keepalive: String,
|
|
pub mint_requests: u64,
|
|
pub mints: u64,
|
|
pub ratls_attacks: u64,
|
|
pub total_ratls_conns: u64,
|
|
pub public: bool,
|
|
}
|
|
|
|
impl From<(String, datastore::NodeInfo)> for NodesResp {
|
|
fn from((ip, node_info): (String, datastore::NodeInfo)) -> Self {
|
|
let joined_at: DateTime<Utc> = node_info.started_at.into();
|
|
let last_keepalive: DateTime<Utc> = node_info.keepalive.into();
|
|
let joined_at = joined_at.format("%Y-%m-%d %H:%M:%S").to_string();
|
|
let last_keepalive = last_keepalive.format("%Y-%m-%d %H:%M:%S").to_string();
|
|
NodesResp {
|
|
ip,
|
|
joined_at,
|
|
last_keepalive,
|
|
mints: node_info.mints,
|
|
total_ratls_conns: node_info.mratls_conns,
|
|
ratls_attacks: node_info.net_attacks,
|
|
public: node_info.public,
|
|
mint_requests: node_info.mint_requests,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[get("/nodes")]
|
|
async fn get_nodes(ds: web::Data<Arc<State>>) -> HttpResponse {
|
|
HttpResponse::Ok()
|
|
.json(ds.get_nodes().into_iter().map(Into::<NodesResp>::into).collect::<Vec<NodesResp>>())
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct MintReq {
|
|
wallet: String,
|
|
}
|
|
|
|
#[post("/mint")]
|
|
async fn mint(
|
|
state: web::Data<Arc<State>>,
|
|
sol_client: web::Data<Arc<SolClient>>,
|
|
req: web::Json<MintReq>,
|
|
) -> impl Responder {
|
|
let recipient = req.into_inner().wallet;
|
|
state.increase_mint_requests();
|
|
let result =
|
|
web::block(move || sol_client.mint(&recipient).map_err(|e| e.to_string())).await.unwrap(); // TODO: check if this can get a BlockingError
|
|
|
|
match result {
|
|
Ok(s) => {
|
|
state.increase_mints();
|
|
HttpResponse::Ok().body(format!(r#"{{" signature": "{s} "}}"#))
|
|
}
|
|
Err(e) => HttpResponse::InternalServerError().body(format!(r#"{{ "error": "{e}" }}"#)),
|
|
}
|
|
}
|
|
|
|
#[get("/metrics")]
|
|
async fn metrics(ds: web::Data<Arc<State>>) -> HttpResponse {
|
|
let mut metrics = String::new();
|
|
for (ip, node) in ds.get_nodes() {
|
|
metrics.push_str(node.to_metrics(&ip).as_str());
|
|
}
|
|
HttpResponse::Ok().content_type("text/plain; version=0.0.4; charset=utf-8").body(metrics)
|
|
}
|
|
|
|
pub async fn http_new_server(state: Arc<State>, sol_client: Arc<SolClient>) {
|
|
HttpServer::new(move || {
|
|
App::new()
|
|
.app_data(web::Data::new(state.clone()))
|
|
.app_data(web::Data::new(sol_client.clone()))
|
|
.service(homepage)
|
|
.service(get_nodes)
|
|
.service(mint)
|
|
.service(metrics)
|
|
})
|
|
.bind("0.0.0.0:31372")
|
|
.unwrap()
|
|
.run()
|
|
.await
|
|
.unwrap();
|
|
}
|