1use pretty_simple_display::{DebugPretty, DisplaySimple};
7use serde::{Deserialize, Serialize};
8
9#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
11pub struct DeribitConfig {
12 pub client_id: String,
14 pub client_secret: String,
16 pub test_net: bool,
18 pub timeout_seconds: u64,
20 pub max_retries: u32,
22 pub rate_limit: Option<u32>,
24 pub user_agent: Option<String>,
26}
27
28impl DeribitConfig {
29 pub fn new(client_id: String, client_secret: String) -> Self {
31 Self {
32 client_id,
33 client_secret,
34 test_net: false,
35 timeout_seconds: 30,
36 max_retries: 3,
37 rate_limit: None,
38 user_agent: None,
39 }
40 }
41
42 pub fn testnet(client_id: String, client_secret: String) -> Self {
44 Self {
45 client_id,
46 client_secret,
47 test_net: true,
48 timeout_seconds: 30,
49 max_retries: 3,
50 rate_limit: None,
51 user_agent: None,
52 }
53 }
54
55 pub fn with_timeout(mut self, timeout_seconds: u64) -> Self {
57 self.timeout_seconds = timeout_seconds;
58 self
59 }
60
61 pub fn with_max_retries(mut self, max_retries: u32) -> Self {
63 self.max_retries = max_retries;
64 self
65 }
66
67 pub fn with_rate_limit(mut self, rate_limit: u32) -> Self {
69 self.rate_limit = Some(rate_limit);
70 self
71 }
72
73 pub fn with_user_agent(mut self, user_agent: String) -> Self {
75 self.user_agent = Some(user_agent);
76 self
77 }
78
79 pub fn base_url(&self) -> &'static str {
81 if self.test_net {
82 DeribitUrls::TEST_BASE_URL
83 } else {
84 DeribitUrls::PROD_BASE_URL
85 }
86 }
87
88 pub fn ws_url(&self) -> &'static str {
90 if self.test_net {
91 DeribitUrls::TEST_WS_URL
92 } else {
93 DeribitUrls::PROD_WS_URL
94 }
95 }
96
97 pub fn api_url(&self) -> String {
99 format!("{}/api/v2", self.base_url())
100 }
101}
102
103impl Default for DeribitConfig {
104 fn default() -> Self {
105 Self {
106 client_id: String::new(),
107 client_secret: String::new(),
108 test_net: true, timeout_seconds: 30,
110 max_retries: 3,
111 rate_limit: None,
112 user_agent: Some("deribit-rust-client/1.0".to_string()),
113 }
114 }
115}
116
117pub struct DeribitUrls;
119
120impl DeribitUrls {
121 pub const PROD_BASE_URL: &'static str = "https://www.deribit.com";
123 pub const TEST_BASE_URL: &'static str = "https://test.deribit.com";
125 pub const PROD_WS_URL: &'static str = "wss://www.deribit.com/ws/api/v2";
127 pub const TEST_WS_URL: &'static str = "wss://test.deribit.com/ws/api/v2";
129}
130
131#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
133pub struct WebSocketConfig {
134 pub base: DeribitConfig,
136 pub ping_interval: u64,
138 pub pong_timeout: u64,
140 pub reconnect_attempts: u32,
142 pub reconnect_delay: u64,
144 pub max_message_size: usize,
146 pub compression: bool,
148}
149
150impl WebSocketConfig {
151 pub fn new(base: DeribitConfig) -> Self {
153 Self {
154 base,
155 ping_interval: 30,
156 pong_timeout: 10,
157 reconnect_attempts: 5,
158 reconnect_delay: 5,
159 max_message_size: 1024 * 1024, compression: true,
161 }
162 }
163
164 pub fn with_ping_interval(mut self, ping_interval: u64) -> Self {
166 self.ping_interval = ping_interval;
167 self
168 }
169
170 pub fn with_pong_timeout(mut self, pong_timeout: u64) -> Self {
172 self.pong_timeout = pong_timeout;
173 self
174 }
175
176 pub fn with_reconnect_attempts(mut self, reconnect_attempts: u32) -> Self {
178 self.reconnect_attempts = reconnect_attempts;
179 self
180 }
181
182 pub fn with_reconnect_delay(mut self, reconnect_delay: u64) -> Self {
184 self.reconnect_delay = reconnect_delay;
185 self
186 }
187
188 pub fn with_compression(mut self, compression: bool) -> Self {
190 self.compression = compression;
191 self
192 }
193}
194
195#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
197pub struct HttpConfig {
198 pub base: DeribitConfig,
200 pub pool_size: Option<usize>,
202 pub keep_alive: Option<u64>,
204 pub http2: bool,
206 pub gzip: bool,
208}
209
210impl HttpConfig {
211 pub fn new(base: DeribitConfig) -> Self {
213 Self {
214 base,
215 pool_size: None,
216 keep_alive: Some(30),
217 http2: true,
218 gzip: true,
219 }
220 }
221
222 pub fn with_pool_size(mut self, pool_size: usize) -> Self {
224 self.pool_size = Some(pool_size);
225 self
226 }
227
228 pub fn with_keep_alive(mut self, keep_alive: u64) -> Self {
230 self.keep_alive = Some(keep_alive);
231 self
232 }
233
234 pub fn with_http2(mut self, http2: bool) -> Self {
236 self.http2 = http2;
237 self
238 }
239
240 pub fn with_gzip(mut self, gzip: bool) -> Self {
242 self.gzip = gzip;
243 self
244 }
245}
246
247#[cfg(test)]
248mod tests {
249 use super::*;
250
251 #[test]
252 fn test_deribit_config_new() {
253 let config = DeribitConfig::new("client123".to_string(), "secret456".to_string());
254 assert_eq!(config.client_id, "client123");
255 assert_eq!(config.client_secret, "secret456");
256 assert!(!config.test_net);
257 assert_eq!(config.timeout_seconds, 30);
258 assert_eq!(config.max_retries, 3);
259 assert_eq!(config.rate_limit, None);
260 assert_eq!(config.user_agent, None);
261 }
262
263 #[test]
264 fn test_deribit_config_testnet() {
265 let config = DeribitConfig::testnet("client123".to_string(), "secret456".to_string());
266 assert_eq!(config.client_id, "client123");
267 assert_eq!(config.client_secret, "secret456");
268 assert!(config.test_net);
269 assert_eq!(config.timeout_seconds, 30);
270 assert_eq!(config.max_retries, 3);
271 assert_eq!(config.rate_limit, None);
272 assert_eq!(config.user_agent, None);
273 }
274
275 #[test]
276 fn test_deribit_config_with_timeout() {
277 let config =
278 DeribitConfig::new("client".to_string(), "secret".to_string()).with_timeout(60);
279 assert_eq!(config.timeout_seconds, 60);
280 }
281
282 #[test]
283 fn test_deribit_config_with_max_retries() {
284 let config =
285 DeribitConfig::new("client".to_string(), "secret".to_string()).with_max_retries(5);
286 assert_eq!(config.max_retries, 5);
287 }
288
289 #[test]
290 fn test_deribit_config_with_rate_limit() {
291 let config =
292 DeribitConfig::new("client".to_string(), "secret".to_string()).with_rate_limit(10);
293 assert_eq!(config.rate_limit, Some(10));
294 }
295
296 #[test]
297 fn test_deribit_config_with_user_agent() {
298 let config = DeribitConfig::new("client".to_string(), "secret".to_string())
299 .with_user_agent("custom-agent".to_string());
300 assert_eq!(config.user_agent, Some("custom-agent".to_string()));
301 }
302
303 #[test]
304 fn test_deribit_config_base_url() {
305 let prod_config = DeribitConfig::new("client".to_string(), "secret".to_string());
306 assert_eq!(prod_config.base_url(), DeribitUrls::PROD_BASE_URL);
307
308 let test_config = DeribitConfig::testnet("client".to_string(), "secret".to_string());
309 assert_eq!(test_config.base_url(), DeribitUrls::TEST_BASE_URL);
310 }
311
312 #[test]
313 fn test_deribit_config_ws_url() {
314 let prod_config = DeribitConfig::new("client".to_string(), "secret".to_string());
315 assert_eq!(prod_config.ws_url(), DeribitUrls::PROD_WS_URL);
316
317 let test_config = DeribitConfig::testnet("client".to_string(), "secret".to_string());
318 assert_eq!(test_config.ws_url(), DeribitUrls::TEST_WS_URL);
319 }
320
321 #[test]
322 fn test_deribit_config_api_url() {
323 let prod_config = DeribitConfig::new("client".to_string(), "secret".to_string());
324 assert_eq!(prod_config.api_url(), "https://www.deribit.com/api/v2");
325
326 let test_config = DeribitConfig::testnet("client".to_string(), "secret".to_string());
327 assert_eq!(test_config.api_url(), "https://test.deribit.com/api/v2");
328 }
329
330 #[test]
331 fn test_deribit_config_default() {
332 let config = DeribitConfig::default();
333 assert_eq!(config.client_id, "");
334 assert_eq!(config.client_secret, "");
335 assert!(config.test_net);
336 assert_eq!(config.timeout_seconds, 30);
337 assert_eq!(config.max_retries, 3);
338 assert_eq!(config.rate_limit, None);
339 assert_eq!(
340 config.user_agent,
341 Some("deribit-rust-client/1.0".to_string())
342 );
343 }
344
345 #[test]
346 fn test_deribit_urls_constants() {
347 assert_eq!(DeribitUrls::PROD_BASE_URL, "https://www.deribit.com");
348 assert_eq!(DeribitUrls::TEST_BASE_URL, "https://test.deribit.com");
349 assert_eq!(DeribitUrls::PROD_WS_URL, "wss://www.deribit.com/ws/api/v2");
350 assert_eq!(DeribitUrls::TEST_WS_URL, "wss://test.deribit.com/ws/api/v2");
351 }
352
353 #[test]
354 fn test_websocket_config_new() {
355 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
356 let ws_config = WebSocketConfig::new(base.clone());
357
358 assert_eq!(ws_config.base.client_id, base.client_id);
359 assert_eq!(ws_config.ping_interval, 30);
360 assert_eq!(ws_config.pong_timeout, 10);
361 assert_eq!(ws_config.reconnect_attempts, 5);
362 assert_eq!(ws_config.reconnect_delay, 5);
363 assert_eq!(ws_config.max_message_size, 1024 * 1024);
364 assert!(ws_config.compression);
365 }
366
367 #[test]
368 fn test_websocket_config_with_ping_interval() {
369 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
370 let ws_config = WebSocketConfig::new(base).with_ping_interval(60);
371 assert_eq!(ws_config.ping_interval, 60);
372 }
373
374 #[test]
375 fn test_websocket_config_with_pong_timeout() {
376 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
377 let ws_config = WebSocketConfig::new(base).with_pong_timeout(20);
378 assert_eq!(ws_config.pong_timeout, 20);
379 }
380
381 #[test]
382 fn test_websocket_config_with_reconnect_attempts() {
383 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
384 let ws_config = WebSocketConfig::new(base).with_reconnect_attempts(10);
385 assert_eq!(ws_config.reconnect_attempts, 10);
386 }
387
388 #[test]
389 fn test_websocket_config_with_reconnect_delay() {
390 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
391 let ws_config = WebSocketConfig::new(base).with_reconnect_delay(15);
392 assert_eq!(ws_config.reconnect_delay, 15);
393 }
394
395 #[test]
396 fn test_websocket_config_with_compression() {
397 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
398 let ws_config = WebSocketConfig::new(base).with_compression(false);
399 assert!(!ws_config.compression);
400 }
401
402 #[test]
403 fn test_http_config_new() {
404 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
405 let http_config = HttpConfig::new(base.clone());
406
407 assert_eq!(http_config.base.client_id, base.client_id);
408 assert_eq!(http_config.pool_size, None);
409 assert_eq!(http_config.keep_alive, Some(30));
410 assert!(http_config.http2);
411 assert!(http_config.gzip);
412 }
413
414 #[test]
415 fn test_http_config_with_pool_size() {
416 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
417 let http_config = HttpConfig::new(base).with_pool_size(20);
418 assert_eq!(http_config.pool_size, Some(20));
419 }
420
421 #[test]
422 fn test_http_config_with_keep_alive() {
423 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
424 let http_config = HttpConfig::new(base).with_keep_alive(60);
425 assert_eq!(http_config.keep_alive, Some(60));
426 }
427
428 #[test]
429 fn test_http_config_with_http2() {
430 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
431 let http_config = HttpConfig::new(base).with_http2(false);
432 assert!(!http_config.http2);
433 }
434
435 #[test]
436 fn test_http_config_with_gzip() {
437 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
438 let http_config = HttpConfig::new(base).with_gzip(false);
439 assert!(!http_config.gzip);
440 }
441
442 #[test]
443 fn test_config_serialization() {
444 let config = DeribitConfig::new("client".to_string(), "secret".to_string());
445 let json = serde_json::to_string(&config).unwrap();
446 let deserialized: DeribitConfig = serde_json::from_str(&json).unwrap();
447 assert_eq!(config.client_id, deserialized.client_id);
448 assert_eq!(config.client_secret, deserialized.client_secret);
449 }
450
451 #[test]
452 fn test_websocket_config_serialization() {
453 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
454 let ws_config = WebSocketConfig::new(base);
455 let json = serde_json::to_string(&ws_config).unwrap();
456 let deserialized: WebSocketConfig = serde_json::from_str(&json).unwrap();
457 assert_eq!(ws_config.ping_interval, deserialized.ping_interval);
458 }
459
460 #[test]
461 fn test_http_config_serialization() {
462 let base = DeribitConfig::new("client".to_string(), "secret".to_string());
463 let http_config = HttpConfig::new(base);
464 let json = serde_json::to_string(&http_config).unwrap();
465 let deserialized: HttpConfig = serde_json::from_str(&json).unwrap();
466 assert_eq!(http_config.http2, deserialized.http2);
467 }
468
469 #[test]
470 fn test_debug_and_display_implementations() {
471 let config = DeribitConfig::new("client".to_string(), "secret".to_string());
472 let debug_str = format!("{:?}", config);
473 let display_str = format!("{}", config);
474
475 assert!(debug_str.contains("client"));
476 assert!(display_str.contains("client"));
477 }
478}