mithril_aggregator_client/query/get/
get_mithril_stake_distribution.rs

1use async_trait::async_trait;
2use reqwest::StatusCode;
3
4use mithril_common::messages::MithrilStakeDistributionMessage;
5
6use crate::AggregatorHttpClientResult;
7use crate::query::{AggregatorQuery, QueryContext, QueryMethod, ResponseExt};
8
9/// Query to get the details of a Mithril stake distribution
10pub struct GetMithrilStakeDistributionQuery {
11    hash: String,
12}
13
14impl GetMithrilStakeDistributionQuery {
15    /// Instantiate a query to get a Mithril stake distribution by hash
16    pub fn by_hash<H: Into<String>>(hash: H) -> Self {
17        Self { hash: hash.into() }
18    }
19}
20
21#[cfg_attr(target_family = "wasm", async_trait(?Send))]
22#[cfg_attr(not(target_family = "wasm"), async_trait)]
23impl AggregatorQuery for GetMithrilStakeDistributionQuery {
24    type Response = Option<MithrilStakeDistributionMessage>;
25    type Body = ();
26
27    fn method() -> QueryMethod {
28        QueryMethod::Get
29    }
30
31    fn route(&self) -> String {
32        format!("artifact/mithril-stake-distribution/{}", self.hash)
33    }
34
35    async fn handle_response(
36        &self,
37        context: QueryContext,
38    ) -> AggregatorHttpClientResult<Self::Response> {
39        match context.response.status() {
40            StatusCode::OK => context.response.parse_json_option().await,
41            StatusCode::NOT_FOUND => Ok(None),
42            _ => Err(context.unhandled_status_code().await),
43        }
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use serde_json::json;
50
51    use mithril_common::test::double::Dummy;
52
53    use crate::AggregatorHttpClientError;
54    use crate::test::{assert_error_matches, setup_server_and_client};
55
56    use super::*;
57
58    #[tokio::test]
59    async fn test_mithril_stake_distributions_details_ok_200() {
60        let (server, client) = setup_server_and_client();
61        let expected_message = MithrilStakeDistributionMessage::dummy();
62        let _server_mock = server.mock(|when, then| {
63            when.path(format!(
64                "/artifact/mithril-stake-distribution/{}",
65                expected_message.hash
66            ));
67            then.status(200).body(json!(expected_message).to_string());
68        });
69
70        let fetched_message = client
71            .send(GetMithrilStakeDistributionQuery::by_hash(
72                &expected_message.hash,
73            ))
74            .await
75            .unwrap();
76
77        assert_eq!(Some(expected_message), fetched_message);
78    }
79
80    #[tokio::test]
81    async fn test_mithril_stake_distributions_details_ok_404() {
82        let (server, client) = setup_server_and_client();
83        let _server_mock = server.mock(|when, then| {
84            when.any_request();
85            then.status(404);
86        });
87
88        let fetched_message = client
89            .send(GetMithrilStakeDistributionQuery::by_hash("whatever"))
90            .await
91            .unwrap();
92
93        assert_eq!(None, fetched_message);
94    }
95
96    #[tokio::test]
97    async fn test_mithril_stake_distributions_details_ko_500() {
98        let (server, client) = setup_server_and_client();
99        let _server_mock = server.mock(|when, then| {
100            when.any_request();
101            then.status(500).body("an error occurred");
102        });
103
104        let error = client
105            .send(GetMithrilStakeDistributionQuery::by_hash("whatever"))
106            .await
107            .unwrap_err();
108
109        assert_error_matches!(error, AggregatorHttpClientError::RemoteServerTechnical(_));
110    }
111}