midgard_rs/midgard/
mod.rs1use chrono::Duration;
2use chrono::{DateTime, Utc};
3pub use config::*;
4use serde::{Deserialize, Serialize};
5
6mod config;
7mod endpoints;
8
9#[derive(Debug, Serialize, Deserialize, Clone, Default)]
10pub struct Midgard {
11 config: Configuration,
12 last_call: DateTime<Utc>,
13}
14
15impl Midgard {
16 #[must_use]
17 pub fn new() -> Self {
18 Self { config: Configuration::default(), last_call: Utc::now() }
19 }
20
21 #[must_use]
22 pub fn with_config(config: Configuration) -> Self {
23 Self { config, last_call: Utc::now() }
24 }
25
26 #[must_use]
27 pub const fn get_config(&self) -> &Configuration {
28 &self.config
29 }
30
31 pub fn set_config(&mut self, config: Configuration) {
32 self.config = config;
33 }
34
35 #[must_use]
36 pub const fn get_last_call(&self) -> DateTime<Utc> {
37 self.last_call
38 }
39
40 fn set_last_call(&mut self, last_call: DateTime<Utc>) {
41 self.last_call = last_call;
42 }
43
44 fn ok_to_call_at(&self) -> DateTime<Utc> {
46 let rate_limit: i64 = i64::try_from(self.config.get_rate_limit_ms()).map_or(1000, |rate_limit| rate_limit);
47 let rate_limit = Duration::try_milliseconds(rate_limit).map_or_else(Duration::zero, |rate_limit| rate_limit);
48 self.last_call.checked_add_signed(rate_limit).map_or_else(Utc::now, |res| res)
49 }
50
51 async fn sleep_until_ok_to_call(&mut self) {
53 let now = Utc::now();
54 let ok_to_call_at = self.ok_to_call_at();
55 if now < ok_to_call_at {
56 let sleep_duration = ok_to_call_at - now;
57 tokio::time::sleep(sleep_duration.to_std().unwrap()).await;
58 }
59 self.set_last_call(Utc::now());
60 }
61}
62
63
64#[cfg(test)]
65mod tests {
66 use rand::prelude::*;
67 use serde_json::json;
68 use crate::GetActionList;
69
70 use super::*;
71
72 #[tokio::test]
73 async fn endpoints() {
74 let mut midgard = Midgard::new();
75
76
77 let params = GetActionList::new(vec!["BTC.BTC".to_string()], 10);
79 let actions = midgard.get_actions(params).await.unwrap();
80 assert!(!actions.get_actions().get_actions().is_empty());
81
82
83 let pool_list = midgard.get_pool_list(None, None).await.unwrap();
85 let random_usize = thread_rng().gen_range(0..pool_list.get_assets().len());
86 let pool = pool_list.get_assets()[random_usize].clone();
87
88 let mut params = GetActionList::new(vec![pool.clone()], 5);
89 let actions = midgard.get_actions(params.clone()).await.unwrap();
90 assert!(!actions.get_actions().get_actions().is_empty());
91
92 let next_page_token = actions.get_meta().get_next_page_token();
93 if let Some(next_page_token) = next_page_token {
94 params.set_next_page_token(next_page_token);
95 let next_actions = midgard.get_actions(params).await.unwrap();
96
97 assert!(!next_actions.get_actions().get_actions().is_empty());
98 }
99
100 let pool_list = midgard.get_pool_list(None, None).await.unwrap();
102 let savers_pools = pool_list.get_savers_pools();
103 assert!(!savers_pools.is_empty());
104
105 println!("savers pools: {}", json!(savers_pools));
106 }
107
108}