1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::v0::context::SharedContext;
use warp::{http::Response, Rejection, Reply};

pub async fn get_genesis(context: SharedContext) -> Result<impl Reply, Rejection> {
    let mut response: Vec<u8> = context.read().await.block0.last().unwrap().block0.clone();

    // check if block0 is not loaded and try to load it again
    if response.is_empty() {
        let block0_path = context
            .read()
            .await
            .block0
            .last()
            .unwrap()
            .block0_path
            .clone();
        response = tokio::fs::read(&block0_path).await.unwrap_or_default();
        if !response.is_empty() {
            context.write().await.block0.last_mut().unwrap().block0 = response.clone();
        }
    }
    get_genesis_response(response)
}

pub async fn get_genesis_for_fund(
    fund_id: i32,
    context: SharedContext,
) -> Result<impl Reply, Rejection> {
    let response: Vec<u8> = context
        .read()
        .await
        .block0
        .iter()
        .find(|x| x.is_fund_id(fund_id))
        .unwrap()
        .clone()
        .block0;
    get_genesis_response(response)
}

fn get_genesis_response(response: Vec<u8>) -> Result<impl Reply, Rejection> {
    // if we have no block0
    if response.is_empty() {
        Ok(Response::builder()
            .status(warp::http::status::StatusCode::NO_CONTENT)
            .header("Content-Type", "application/octet-stream")
            .body(response)
            .unwrap())
        // if we have a block0
    } else {
        Ok(Response::builder()
            .header("Content-Type", "application/octet-stream")
            .body(response)
            .unwrap())
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::v0::context::test::new_test_shared_context_with_block0;
    use std::path::PathBuf;
    use std::str::FromStr;
    use vit_servicing_station_tests::common::startup::db::DbBuilder;
    use warp::Filter;

    #[tokio::test]
    async fn get_block0_succeed() {
        // build context
        let block0_path = "../resources/tests/block0.bin";
        let db_url = DbBuilder::new().build_async().await.unwrap();
        let shared_context = new_test_shared_context_with_block0(
            &db_url,
            vec![PathBuf::from_str(block0_path).unwrap()],
        );
        let block0 = std::fs::read(block0_path).unwrap();

        let with_context = warp::any().map(move || shared_context.clone());

        // build filter
        let filter = warp::any()
            .and(warp::get())
            .and(with_context)
            .and_then(get_genesis);

        // check status code and block0 data
        let result = warp::test::request().method("GET").reply(&filter).await;

        assert_eq!(result.status(), warp::http::StatusCode::OK);
        let body = result.body().to_vec();
        assert_eq!(block0, body);
    }
}