mithril_client/
mithril_stake_distribution_client.rs1use std::sync::Arc;
42
43use crate::aggregator_client::{AggregatorClient, AggregatorClientError, AggregatorRequest};
44use anyhow::Context;
45
46use crate::{MithrilResult, MithrilStakeDistribution, MithrilStakeDistributionListItem};
47
48pub struct MithrilStakeDistributionClient {
50 aggregator_client: Arc<dyn AggregatorClient>,
51}
52
53impl MithrilStakeDistributionClient {
54 pub fn new(aggregator_client: Arc<dyn AggregatorClient>) -> Self {
56 Self { aggregator_client }
57 }
58
59 pub async fn list(&self) -> MithrilResult<Vec<MithrilStakeDistributionListItem>> {
61 let response = self
62 .aggregator_client
63 .get_content(AggregatorRequest::ListMithrilStakeDistributions)
64 .await
65 .with_context(|| "MithrilStakeDistribution Client can not get the artifact list")?;
66 let items = serde_json::from_str::<Vec<MithrilStakeDistributionListItem>>(&response)
67 .with_context(|| "MithrilStakeDistribution Client can not deserialize artifact list")?;
68
69 Ok(items)
70 }
71
72 pub async fn get(&self, hash: &str) -> MithrilResult<Option<MithrilStakeDistribution>> {
74 match self
75 .aggregator_client
76 .get_content(AggregatorRequest::GetMithrilStakeDistribution {
77 hash: hash.to_string(),
78 })
79 .await
80 {
81 Ok(content) => {
82 let stake_distribution_entity: MithrilStakeDistribution =
83 serde_json::from_str(&content).with_context(|| {
84 "MithrilStakeDistribution Client can not deserialize artifact"
85 })?;
86
87 Ok(Some(stake_distribution_entity))
88 }
89 Err(AggregatorClientError::RemoteServerLogical(_)) => Ok(None),
90 Err(e) => Err(e.into()),
91 }
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use chrono::{DateTime, Utc};
98 use mithril_common::test_utils::fake_data;
99
100 use crate::aggregator_client::MockAggregatorClient;
101 use crate::common::Epoch;
102 use crate::MithrilSigner;
103
104 use super::*;
105
106 fn fake_messages() -> Vec<MithrilStakeDistributionListItem> {
107 vec![
108 MithrilStakeDistributionListItem {
109 epoch: Epoch(1),
110 hash: "hash-123".to_string(),
111 certificate_hash: "cert-hash-123".to_string(),
112 created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
113 .unwrap()
114 .with_timezone(&Utc),
115 },
116 MithrilStakeDistributionListItem {
117 epoch: Epoch(2),
118 hash: "hash-456".to_string(),
119 certificate_hash: "cert-hash-456".to_string(),
120 created_at: DateTime::parse_from_rfc3339("2023-01-19T13:43:05.618857482Z")
121 .unwrap()
122 .with_timezone(&Utc),
123 },
124 ]
125 }
126
127 #[tokio::test]
128 async fn get_mithril_stake_distribution_list() {
129 let message = fake_messages();
130 let mut http_client = MockAggregatorClient::new();
131 http_client
132 .expect_get_content()
133 .return_once(move |_| Ok(serde_json::to_string(&message).unwrap()));
134 let client = MithrilStakeDistributionClient::new(Arc::new(http_client));
135 let items = client.list().await.unwrap();
136
137 assert_eq!(2, items.len());
138 assert_eq!("hash-123".to_string(), items[0].hash);
139 assert_eq!("hash-456".to_string(), items[1].hash);
140 }
141
142 #[tokio::test]
143 async fn get_mithril_stake_distribution() {
144 let mut http_client = MockAggregatorClient::new();
145 let message = MithrilStakeDistribution {
146 certificate_hash: "certificate-hash-123".to_string(),
147 epoch: Epoch(1),
148 signers_with_stake: MithrilSigner::from_signers(fake_data::signers_with_stakes(2)),
149 hash: "hash".to_string(),
150 created_at: DateTime::<Utc>::default(),
151 protocol_parameters: fake_data::protocol_parameters(),
152 };
153 http_client
154 .expect_get_content()
155 .return_once(move |_| Ok(serde_json::to_string(&message).unwrap()));
156 let client = MithrilStakeDistributionClient::new(Arc::new(http_client));
157 let stake_distribution_entity = client
158 .get("hash")
159 .await
160 .unwrap()
161 .expect("This test returns a stake distribution");
162
163 assert_eq!("hash".to_string(), stake_distribution_entity.hash);
164 assert_eq!(2, stake_distribution_entity.signers_with_stake.len(),);
165 }
166}