mithril_aggregator_client/query/post/
post_register_signer.rs

1use async_trait::async_trait;
2use reqwest::StatusCode;
3
4use mithril_common::messages::RegisterSignerMessage;
5
6use crate::AggregatorHttpClientResult;
7use crate::query::{AggregatorQuery, QueryContext, QueryLogFields, QueryMethod};
8
9/// Query to register a signer to a Mithril Aggregator.
10pub struct PostRegisterSignerQuery {
11    message: RegisterSignerMessage,
12}
13
14impl PostRegisterSignerQuery {
15    /// Instantiate a new query to register a signer
16    pub fn new(message: RegisterSignerMessage) -> Self {
17        Self { message }
18    }
19}
20
21#[cfg_attr(target_family = "wasm", async_trait(?Send))]
22#[cfg_attr(not(target_family = "wasm"), async_trait)]
23impl AggregatorQuery for PostRegisterSignerQuery {
24    type Response = ();
25    type Body = RegisterSignerMessage;
26
27    fn method() -> QueryMethod {
28        QueryMethod::Post
29    }
30
31    fn route(&self) -> String {
32        "register-signer".to_string()
33    }
34
35    fn body(&self) -> Option<Self::Body> {
36        Some(self.message.clone())
37    }
38
39    fn entry_log_additional_fields(&self) -> QueryLogFields {
40        QueryLogFields::from([
41            ("epoch", format!("{}", *self.message.epoch)),
42            ("party_id", self.message.party_id.clone()),
43        ])
44    }
45
46    async fn handle_response(
47        &self,
48        context: QueryContext,
49    ) -> AggregatorHttpClientResult<Self::Response> {
50        match context.response.status() {
51            StatusCode::CREATED => Ok(()),
52            _ => Err(context.unhandled_status_code().await),
53        }
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use httpmock::Method::POST;
60
61    use mithril_common::entities::ClientError;
62    use mithril_common::test::double::Dummy;
63
64    use crate::AggregatorHttpClientError;
65    use crate::test::{assert_error_matches, setup_server_and_client};
66
67    use super::*;
68
69    #[tokio::test]
70    async fn test_register_signer_ok_201() {
71        let expected_message = RegisterSignerMessage::dummy();
72        let (server, client) = setup_server_and_client();
73        let _server_mock = server.mock(|when, then| {
74            when.method(POST)
75                .path("/register-signer")
76                .body(serde_json::to_string(&expected_message).unwrap());
77            then.status(201);
78        });
79
80        let register_signer = client.send(PostRegisterSignerQuery::new(expected_message)).await;
81        register_signer.expect("unexpected error");
82    }
83
84    #[tokio::test]
85    async fn test_register_signer_ko_400() {
86        let (server, client) = setup_server_and_client();
87        let _server_mock = server.mock(|when, then| {
88            when.any_request();
89            then.status(400)
90                .body(serde_json::to_vec(&ClientError::dummy()).unwrap());
91        });
92
93        let error = client
94            .send(PostRegisterSignerQuery::new(RegisterSignerMessage::dummy()))
95            .await
96            .unwrap_err();
97
98        assert_error_matches!(error, AggregatorHttpClientError::RemoteServerLogical(_));
99    }
100
101    #[tokio::test]
102    async fn test_register_signer_ko_500() {
103        let (server, client) = setup_server_and_client();
104        let _server_mock = server.mock(|when, then| {
105            when.any_request();
106            then.status(500).body("an error occurred");
107        });
108
109        let error = client
110            .send(PostRegisterSignerQuery::new(RegisterSignerMessage::dummy()))
111            .await
112            .unwrap_err();
113
114        assert_error_matches!(error, AggregatorHttpClientError::RemoteServerTechnical(_));
115    }
116}