hypercall_db_diesel/
mmp.rs1use anyhow::Result;
7use diesel::prelude::*;
8use diesel::RunQueryDsl;
9
10use hypercall_types::WalletAddress;
11
12use crate::database_handler::DatabaseHandler;
13
14impl hypercall_db::MmpConfigReader for DatabaseHandler {
15 fn get_mmp_config_sync(
16 &self,
17 wallet: &WalletAddress,
18 currency: &str,
19 ) -> Result<Option<hypercall_db::MmpConfigRecord>> {
20 use crate::schema::mmp_configs::dsl;
21
22 let mut conn = self.pool().get()?;
23 let result = dsl::mmp_configs
24 .filter(dsl::wallet_address.eq(wallet))
25 .filter(dsl::currency.eq(currency))
26 .first::<crate::models::MmpConfig>(&mut conn)
27 .optional()?;
28 Ok(result.map(Into::into))
29 }
30
31 fn get_all_mmp_configs_for_wallet_sync(
32 &self,
33 wallet: &WalletAddress,
34 ) -> Result<Vec<hypercall_db::MmpConfigRecord>> {
35 use crate::schema::mmp_configs::dsl;
36
37 let mut conn = self.pool().get()?;
38 let results = dsl::mmp_configs
39 .filter(dsl::wallet_address.eq(wallet))
40 .load::<crate::models::MmpConfig>(&mut conn)?;
41 Ok(results.into_iter().map(Into::into).collect())
42 }
43
44 fn get_all_mmp_configs_sync(&self) -> Result<Vec<hypercall_db::MmpConfigRecord>> {
45 use crate::schema::mmp_configs::dsl;
46
47 let mut conn = self.pool().get()?;
48 let results = dsl::mmp_configs
49 .filter(dsl::enabled.eq(true))
50 .load::<crate::models::MmpConfig>(&mut conn)?;
51 Ok(results.into_iter().map(Into::into).collect())
52 }
53}
54
55impl hypercall_db::MmpConfigWriter for DatabaseHandler {
56 fn save_mmp_config_sync(&self, config: &hypercall_db::MmpConfigRecord) -> Result<()> {
57 let new_config = crate::models::NewMmpConfig {
58 wallet_address: config.wallet_address,
59 currency: config.currency.clone(),
60 interval_ms: config.interval_ms,
61 frozen_time_ms: config.frozen_time_ms,
62 qty_limit: config.qty_limit,
63 delta_limit: config.delta_limit,
64 vega_limit: config.vega_limit,
65 enabled: config.enabled,
66 };
67
68 let mut conn = self.pool().get()?;
69 diesel::insert_into(crate::schema::mmp_configs::table)
70 .values(&new_config)
71 .on_conflict((
72 crate::schema::mmp_configs::wallet_address,
73 crate::schema::mmp_configs::currency,
74 ))
75 .do_update()
76 .set(&new_config)
77 .execute(&mut conn)?;
78 Ok(())
79 }
80
81 fn delete_mmp_config_sync(&self, wallet: &WalletAddress, currency: &str) -> Result<()> {
82 use crate::schema::mmp_configs::dsl;
83
84 let mut conn = self.pool().get()?;
85 diesel::update(
86 dsl::mmp_configs
87 .filter(dsl::wallet_address.eq(wallet))
88 .filter(dsl::currency.eq(currency)),
89 )
90 .set(dsl::enabled.eq(false))
91 .execute(&mut conn)?;
92 Ok(())
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use crate::test_helpers::TestDb;
99 use hypercall_db::*;
100 use hypercall_types::wallet_address::test_wallet;
101 use rust_decimal_macros::dec;
102
103 #[tokio::test]
104 async fn mmp_config_write_read_roundtrip() {
105 let test_db = TestDb::new().await.unwrap();
106 let db = test_db.handler.as_ref();
107 let wallet = test_wallet(5);
108
109 let config = MmpConfigRecord {
110 wallet_address: wallet,
111 currency: "BTC".to_string(),
112 interval_ms: 1000,
113 frozen_time_ms: 5000,
114 qty_limit: Some(dec!(10)),
115 delta_limit: None,
116 vega_limit: Some(dec!(100)),
117 enabled: true,
118 created_at: None,
119 updated_at: None,
120 };
121
122 db.save_mmp_config_sync(&config).unwrap();
123 let loaded = db.get_mmp_config_sync(&wallet, "BTC").unwrap().unwrap();
124 assert_eq!(loaded.wallet_address, wallet);
125 assert_eq!(loaded.currency, "BTC");
126 assert_eq!(loaded.interval_ms, 1000);
127 assert_eq!(loaded.qty_limit, Some(dec!(10)));
128 assert!(loaded.enabled);
129 }
130
131 #[tokio::test]
132 async fn mmp_config_get_all_for_wallet() {
133 let test_db = TestDb::new().await.unwrap();
134 let db = test_db.handler.as_ref();
135 let wallet = test_wallet(6);
136
137 for currency in ["BTC", "ETH", "SOL"] {
138 let config = MmpConfigRecord {
139 wallet_address: wallet,
140 currency: currency.to_string(),
141 interval_ms: 1000,
142 frozen_time_ms: 5000,
143 qty_limit: None,
144 delta_limit: None,
145 vega_limit: None,
146 enabled: true,
147 created_at: None,
148 updated_at: None,
149 };
150 db.save_mmp_config_sync(&config).unwrap();
151 }
152
153 let all = db.get_all_mmp_configs_for_wallet_sync(&wallet).unwrap();
154 assert_eq!(all.len(), 3);
155 }
156
157 #[tokio::test]
158 async fn mmp_config_delete_disables() {
159 let test_db = TestDb::new().await.unwrap();
160 let db = test_db.handler.as_ref();
161 let wallet = test_wallet(7);
162
163 let config = MmpConfigRecord {
164 wallet_address: wallet,
165 currency: "BTC".to_string(),
166 interval_ms: 1000,
167 frozen_time_ms: 5000,
168 qty_limit: None,
169 delta_limit: None,
170 vega_limit: None,
171 enabled: true,
172 created_at: None,
173 updated_at: None,
174 };
175 db.save_mmp_config_sync(&config).unwrap();
176 db.delete_mmp_config_sync(&wallet, "BTC").unwrap();
177
178 let loaded = db.get_mmp_config_sync(&wallet, "BTC").unwrap().unwrap();
180 assert!(!loaded.enabled);
181 }
182}