mina_producer_dashboard/rpc/
handlers.rs

1use reqwest::StatusCode;
2
3use crate::{
4    evaluator::epoch::EpochSlots,
5    node::{epoch_ledgers::Balances, NodeData},
6    storage::db_sled::Database,
7    NodeStatus,
8};
9
10use super::PaginationParams;
11
12pub async fn get_genesis_timestamp() -> Result<impl warp::Reply, warp::reject::Rejection> {
13    // TODO(adonagy): we need this only once, no need to query the node every time...
14    // match node::get_genesis_timestmap().await {
15    //     Ok(timestamp) => {
16    //         let datetime = OffsetDateTime::parse(&timestamp, &Rfc3339).unwrap();
17    //         let unix_timestamp = datetime.unix_timestamp();
18    //         Ok(warp::reply::with_status(
19    //             warp::reply::json(&unix_timestamp.to_string()),
20    //             StatusCode::OK,
21    //         ))
22    //     }
23    //     // TODO(adonagy)
24    //     Err(_) => Err(warp::reject()),
25    // }
26
27    Ok(warp::reply())
28}
29
30pub async fn get_node_status(
31    node_status: NodeStatus,
32) -> Result<impl warp::Reply, warp::reject::Rejection> {
33    let node_status: NodeData = node_status.read().await.clone();
34
35    Ok(warp::reply::with_status(
36        warp::reply::json(&node_status),
37        StatusCode::OK,
38    ))
39}
40
41pub async fn get_current_slot(
42    node_status: NodeStatus,
43) -> Result<impl warp::Reply, warp::reject::Rejection> {
44    let current_slot = node_status.read().await.current_slot();
45
46    Ok(warp::reply::with_status(
47        warp::reply::json(&current_slot),
48        StatusCode::OK,
49    ))
50}
51
52pub async fn get_latest_epoch_data(
53    storage: Database,
54    node_status: NodeStatus,
55) -> Result<impl warp::Reply, warp::reject::Rejection> {
56    let node_status = node_status.read().await;
57
58    let current_epoch = node_status.best_tip().unwrap().epoch();
59
60    match storage.get_slots_for_epoch(current_epoch) {
61        Ok(latest) => Ok(warp::reply::with_status(
62            warp::reply::json(&latest),
63            StatusCode::OK,
64        )),
65        // TODO(adonagy)
66        _ => Err(warp::reject()),
67    }
68}
69
70pub async fn get_epoch_data(
71    epoch: u32,
72    storage: Database,
73) -> Result<impl warp::Reply, warp::reject::Rejection> {
74    match storage.get_slots_for_epoch(epoch) {
75        Ok(slots) => Ok(warp::reply::with_status(
76            warp::reply::json(&slots),
77            StatusCode::OK,
78        )),
79        // TODO(adonagy)
80        _ => Err(warp::reject()),
81    }
82}
83
84pub async fn get_latest_epoch_data_summary(
85    storage: Database,
86    node_status: NodeStatus,
87    producer_pk: String,
88) -> Result<impl warp::Reply, warp::reject::Rejection> {
89    let node_status: tokio::sync::RwLockReadGuard<'_, NodeData> = node_status.read().await;
90
91    let current_epoch = node_status.best_tip().unwrap().epoch();
92
93    let balances = storage
94        .get_ledger(current_epoch)
95        .unwrap()
96        .unwrap()
97        .producer_balances(&producer_pk);
98
99    match storage.get_slots_for_epoch(current_epoch) {
100        Ok(latest) => {
101            let summary = EpochSlots::new(latest).merged_summary(current_epoch, balances);
102
103            Ok(warp::reply::with_status(
104                warp::reply::json(&summary),
105                StatusCode::OK,
106            ))
107        }
108        // TODO(adonagy)
109        _ => Err(warp::reject()),
110    }
111}
112
113pub async fn get_epoch_data_summary(
114    requested_epoch: u32,
115    pagination: PaginationParams,
116    storage: Database,
117    producer_pk: String,
118) -> Result<impl warp::Reply, warp::reject::Rejection> {
119    let range = (0..=requested_epoch).rev();
120    let limit = pagination.limit.unwrap_or(1);
121
122    let mut res = Vec::new();
123
124    for epoch in range.take(limit) {
125        println!("{epoch}");
126        match storage.get_slots_for_epoch(epoch) {
127            Ok(slots) => {
128                let balances = match storage.get_ledger(epoch) {
129                    Ok(Some(ledger)) => ledger.producer_balances(&producer_pk),
130                    _ => Balances::default(),
131                };
132                res.push(EpochSlots::new(slots).merged_summary(epoch, balances))
133            }
134            _ => continue,
135        }
136    }
137
138    Ok(warp::reply::with_status(
139        warp::reply::json(&res),
140        StatusCode::OK,
141    ))
142}
143
144pub async fn get_all_time_summary(
145    storage: Database,
146) -> Result<impl warp::Reply, warp::reject::Rejection> {
147    match storage.get_all_slots() {
148        Ok(slots) => {
149            let res = EpochSlots::new(slots).slot_summary().0;
150            Ok(warp::reply::with_status(
151                warp::reply::json(&res),
152                StatusCode::OK,
153            ))
154        }
155        _ => Err(warp::reject()),
156    }
157}