mithril_aggregator_client/query/get/
get_cardano_transaction_proof.rs1use async_trait::async_trait;
2use reqwest::StatusCode;
3
4use mithril_common::messages::CardanoTransactionsProofsMessage;
5
6use crate::AggregatorHttpClientResult;
7use crate::query::{AggregatorQuery, QueryContext, QueryMethod, ResponseExt};
8
9pub struct GetCardanoTransactionProofQuery {
11 transactions_hashes: Vec<String>,
12}
13
14impl GetCardanoTransactionProofQuery {
15 pub fn for_hashes<H: ToString>(hashes: &[H]) -> Self {
17 Self {
18 transactions_hashes: hashes.iter().map(|h| h.to_string()).collect(),
19 }
20 }
21}
22
23#[cfg_attr(target_family = "wasm", async_trait(?Send))]
24#[cfg_attr(not(target_family = "wasm"), async_trait)]
25impl AggregatorQuery for GetCardanoTransactionProofQuery {
26 type Response = Option<CardanoTransactionsProofsMessage>;
27 type Body = ();
28
29 fn method() -> QueryMethod {
30 QueryMethod::Get
31 }
32
33 fn route(&self) -> String {
34 format!(
35 "proof/cardano-transaction?transaction_hashes={}",
36 self.transactions_hashes.join(",")
37 )
38 }
39
40 async fn handle_response(
41 &self,
42 context: QueryContext,
43 ) -> AggregatorHttpClientResult<Self::Response> {
44 match context.response.status() {
45 StatusCode::OK => context.response.parse_json_option().await,
46 StatusCode::NOT_FOUND => Ok(None),
47 _ => Err(context.unhandled_status_code().await),
48 }
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use serde_json::json;
55
56 use crate::AggregatorHttpClientError;
57 use crate::test::{assert_error_matches, setup_server_and_client};
58
59 use super::*;
60
61 #[tokio::test]
62 async fn test_cardano_transaction_proof_ok_200() {
63 let (server, client) = setup_server_and_client();
64 let expected_message = CardanoTransactionsProofsMessage {
65 certificate_hash: "whatever".to_string(),
66 certified_transactions: vec![],
67 non_certified_transactions: vec![],
68 latest_block_number: Default::default(),
69 };
70 let _server_mock = server.mock(|when, then| {
71 when.path("/proof/cardano-transaction")
72 .query_param("transaction_hashes", "hash1,hash3,hash2");
73 then.status(200).body(json!(expected_message).to_string());
74 });
75
76 let fetched_message = client
77 .send(GetCardanoTransactionProofQuery::for_hashes(&[
78 "hash1", "hash3", "hash2",
79 ]))
80 .await
81 .unwrap();
82
83 assert_eq!(Some(expected_message), fetched_message);
84 }
85
86 #[tokio::test]
87 async fn test_cardano_transaction_proof_ok_404() {
88 let (server, client) = setup_server_and_client();
89 let _server_mock = server.mock(|when, then| {
90 when.any_request();
91 then.status(404);
92 });
93
94 let fetched_message = client
95 .send(GetCardanoTransactionProofQuery::for_hashes(&["whatever"]))
96 .await
97 .unwrap();
98
99 assert_eq!(None, fetched_message);
100 }
101
102 #[tokio::test]
103 async fn test_cardano_transaction_proof_ko_500() {
104 let (server, client) = setup_server_and_client();
105 let _server_mock = server.mock(|when, then| {
106 when.any_request();
107 then.status(500).body("an error occurred");
108 });
109
110 let error = client
111 .send(GetCardanoTransactionProofQuery::for_hashes(&["whatever"]))
112 .await
113 .unwrap_err();
114
115 assert_error_matches!(error, AggregatorHttpClientError::RemoteServerTechnical(_));
116 }
117}