1use derive_builder::Builder;
19use serde::{Deserialize, Serialize};
20
21use super::models::{DeribitCurrency, DeribitProductType};
22
23#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
25#[serde(rename_all = "snake_case")]
26pub enum DeribitExpirationKind {
27 Future,
29 Option,
31 Any,
33 FutureCombo,
35 OptionCombo,
37}
38
39#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
41#[builder(setter(into, strip_option))]
42pub struct GetExpirationsParams {
43 pub currency: String,
45 pub kind: DeribitExpirationKind,
47 #[serde(skip_serializing_if = "Option::is_none")]
49 #[builder(default)]
50 pub currency_pair: Option<String>,
51}
52
53impl GetExpirationsParams {
54 #[must_use]
56 pub fn builder() -> GetExpirationsParamsBuilder {
57 GetExpirationsParamsBuilder::default()
58 }
59
60 #[must_use]
62 pub fn new(currency: impl Into<String>, kind: DeribitExpirationKind) -> Self {
63 Self {
64 currency: currency.into(),
65 kind,
66 currency_pair: None,
67 }
68 }
69}
70
71#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
73#[builder(setter(into, strip_option))]
74pub struct GetInstrumentsParams {
75 pub currency: DeribitCurrency,
77 #[serde(skip_serializing_if = "Option::is_none")]
79 #[builder(default)]
80 pub kind: Option<DeribitProductType>,
81 #[serde(skip_serializing_if = "Option::is_none")]
83 #[builder(default)]
84 pub expired: Option<bool>,
85}
86
87impl GetInstrumentsParams {
88 #[must_use]
90 pub fn builder() -> GetInstrumentsParamsBuilder {
91 GetInstrumentsParamsBuilder::default()
92 }
93
94 #[must_use]
96 pub fn new(currency: DeribitCurrency) -> Self {
97 Self {
98 currency,
99 kind: None,
100 expired: None,
101 }
102 }
103
104 #[must_use]
106 pub fn with_kind(currency: DeribitCurrency, kind: DeribitProductType) -> Self {
107 Self {
108 currency,
109 kind: Some(kind),
110 expired: None,
111 }
112 }
113}
114
115#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
117pub struct GetInstrumentParams {
118 pub instrument_name: String,
120}
121
122#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
124#[builder(setter(into, strip_option))]
125pub struct GetCombosParams {
126 pub currency: DeribitCurrency,
128}
129
130impl GetCombosParams {
131 #[must_use]
133 pub fn builder() -> GetCombosParamsBuilder {
134 GetCombosParamsBuilder::default()
135 }
136
137 #[must_use]
139 pub fn new(currency: DeribitCurrency) -> Self {
140 Self { currency }
141 }
142}
143
144#[derive(Clone, Debug, Default, Deserialize, Serialize)]
146pub struct GetAccountSummariesParams {
147 #[serde(skip_serializing_if = "Option::is_none")]
149 pub subaccount_id: Option<String>,
150 #[serde(skip_serializing_if = "Option::is_none")]
152 pub extended: Option<bool>,
153}
154
155impl GetAccountSummariesParams {
156 #[must_use]
158 pub fn new(subaccount_id: String, extended: bool) -> Self {
159 Self {
160 subaccount_id: Some(subaccount_id),
161 extended: Some(extended),
162 }
163 }
164}
165
166#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
168#[builder(setter(into, strip_option))]
169pub struct GetLastTradesByInstrumentAndTimeParams {
170 pub instrument_name: String,
172 pub start_timestamp: i64,
174 pub end_timestamp: i64,
176 #[serde(skip_serializing_if = "Option::is_none")]
178 #[builder(default)]
179 pub count: Option<u32>,
180 #[serde(skip_serializing_if = "Option::is_none")]
182 #[builder(default)]
183 pub sorting: Option<String>,
184}
185
186impl GetLastTradesByInstrumentAndTimeParams {
187 #[must_use]
189 pub fn new(
190 instrument_name: impl Into<String>,
191 start_timestamp: i64,
192 end_timestamp: i64,
193 count: Option<u32>,
194 sorting: Option<String>,
195 ) -> Self {
196 Self {
197 instrument_name: instrument_name.into(),
198 start_timestamp,
199 end_timestamp,
200 count,
201 sorting,
202 }
203 }
204}
205
206#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
212#[builder(setter(into, strip_option))]
213pub struct GetLastTradesByCurrencyParams {
214 pub currency: DeribitCurrency,
216 #[serde(skip_serializing_if = "Option::is_none")]
218 #[builder(default)]
219 pub kind: Option<DeribitProductType>,
220 #[serde(skip_serializing_if = "Option::is_none")]
222 #[builder(default)]
223 pub start_id: Option<String>,
224 #[serde(skip_serializing_if = "Option::is_none")]
226 #[builder(default)]
227 pub end_id: Option<String>,
228 #[serde(skip_serializing_if = "Option::is_none")]
230 #[builder(default)]
231 pub count: Option<u32>,
232 #[serde(skip_serializing_if = "Option::is_none")]
234 #[builder(default)]
235 pub include_old: Option<bool>,
236 #[serde(skip_serializing_if = "Option::is_none")]
238 #[builder(default)]
239 pub sorting: Option<String>,
240}
241
242impl GetLastTradesByCurrencyParams {
243 #[must_use]
245 pub fn builder() -> GetLastTradesByCurrencyParamsBuilder {
246 GetLastTradesByCurrencyParamsBuilder::default()
247 }
248
249 #[must_use]
251 pub fn new(currency: DeribitCurrency) -> Self {
252 Self {
253 currency,
254 kind: None,
255 start_id: None,
256 end_id: None,
257 count: None,
258 include_old: None,
259 sorting: None,
260 }
261 }
262
263 #[must_use]
265 pub fn with_kind(currency: DeribitCurrency, kind: DeribitProductType) -> Self {
266 Self {
267 currency,
268 kind: Some(kind),
269 start_id: None,
270 end_id: None,
271 count: None,
272 include_old: None,
273 sorting: None,
274 }
275 }
276}
277
278#[derive(Clone, Debug, Deserialize, Serialize)]
280pub struct GetTradingViewChartDataParams {
281 pub instrument_name: String,
283 pub start_timestamp: i64,
285 pub end_timestamp: i64,
287 pub resolution: String,
290}
291
292impl GetTradingViewChartDataParams {
293 #[must_use]
295 pub fn new(
296 instrument_name: String,
297 start_timestamp: i64,
298 end_timestamp: i64,
299 resolution: String,
300 ) -> Self {
301 Self {
302 instrument_name,
303 start_timestamp,
304 end_timestamp,
305 resolution,
306 }
307 }
308}
309
310#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
312#[builder(setter(into, strip_option))]
313pub struct GetOrderBookParams {
314 pub instrument_name: String,
316 #[serde(skip_serializing_if = "Option::is_none")]
320 #[builder(default)]
321 pub depth: Option<u32>,
322}
323
324impl GetOrderBookParams {
325 #[must_use]
327 pub fn new(instrument_name: String, depth: Option<u32>) -> Self {
328 Self {
329 instrument_name,
330 depth,
331 }
332 }
333}
334
335#[derive(Clone, Debug, Deserialize, Serialize)]
338pub struct GetOrderStateParams {
339 pub order_id: String,
341}
342
343impl GetOrderStateParams {
344 #[must_use]
346 pub fn new(order_id: impl Into<String>) -> Self {
347 Self {
348 order_id: order_id.into(),
349 }
350 }
351}
352
353#[derive(Clone, Debug, Default, Deserialize, Serialize)]
356pub struct GetOpenOrdersParams {}
357
358impl GetOpenOrdersParams {
359 #[must_use]
361 pub fn new() -> Self {
362 Self {}
363 }
364}
365
366#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
369#[builder(setter(into, strip_option))]
370pub struct GetOpenOrdersByInstrumentParams {
371 pub instrument_name: String,
373 #[serde(skip_serializing_if = "Option::is_none")]
376 #[builder(default)]
377 pub r#type: Option<String>,
378}
379
380impl GetOpenOrdersByInstrumentParams {
381 #[must_use]
383 pub fn new(instrument_name: impl Into<String>) -> Self {
384 Self {
385 instrument_name: instrument_name.into(),
386 r#type: None,
387 }
388 }
389}
390
391#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
394#[builder(setter(into, strip_option))]
395pub struct GetOrderHistoryByInstrumentParams {
396 pub instrument_name: String,
398 #[serde(skip_serializing_if = "Option::is_none")]
400 #[builder(default)]
401 pub count: Option<u32>,
402 #[serde(skip_serializing_if = "Option::is_none")]
404 #[builder(default)]
405 pub offset: Option<u32>,
406 #[serde(skip_serializing_if = "Option::is_none")]
408 #[builder(default)]
409 pub include_old: Option<bool>,
410 #[serde(skip_serializing_if = "Option::is_none")]
412 #[builder(default)]
413 pub include_unfilled: Option<bool>,
414}
415
416impl GetOrderHistoryByInstrumentParams {
417 #[must_use]
419 pub fn new(instrument_name: impl Into<String>) -> Self {
420 Self {
421 instrument_name: instrument_name.into(),
422 count: None,
423 offset: None,
424 include_old: None,
425 include_unfilled: None,
426 }
427 }
428
429 #[must_use]
431 pub fn builder() -> GetOrderHistoryByInstrumentParamsBuilder {
432 GetOrderHistoryByInstrumentParamsBuilder::default()
433 }
434}
435
436#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
439#[builder(setter(into, strip_option))]
440pub struct GetOrderHistoryByCurrencyParams {
441 pub currency: DeribitCurrency,
443 #[serde(skip_serializing_if = "Option::is_none")]
445 #[builder(default)]
446 pub kind: Option<DeribitProductType>,
447 #[serde(skip_serializing_if = "Option::is_none")]
449 #[builder(default)]
450 pub count: Option<u32>,
451 #[serde(skip_serializing_if = "Option::is_none")]
453 #[builder(default)]
454 pub offset: Option<u32>,
455 #[serde(skip_serializing_if = "Option::is_none")]
457 #[builder(default)]
458 pub include_old: Option<bool>,
459 #[serde(skip_serializing_if = "Option::is_none")]
461 #[builder(default)]
462 pub include_unfilled: Option<bool>,
463}
464
465impl GetOrderHistoryByCurrencyParams {
466 #[must_use]
468 pub fn new(currency: DeribitCurrency) -> Self {
469 Self {
470 currency,
471 kind: None,
472 count: None,
473 offset: None,
474 include_old: None,
475 include_unfilled: None,
476 }
477 }
478
479 #[must_use]
481 pub fn builder() -> GetOrderHistoryByCurrencyParamsBuilder {
482 GetOrderHistoryByCurrencyParamsBuilder::default()
483 }
484}
485
486#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
489#[builder(setter(into, strip_option))]
490pub struct GetUserTradesByInstrumentAndTimeParams {
491 pub instrument_name: String,
493 pub start_timestamp: i64,
495 pub end_timestamp: i64,
497 #[serde(skip_serializing_if = "Option::is_none")]
499 #[builder(default)]
500 pub count: Option<u32>,
501 #[serde(skip_serializing_if = "Option::is_none")]
503 #[builder(default)]
504 pub sorting: Option<String>,
505}
506
507impl GetUserTradesByInstrumentAndTimeParams {
508 #[must_use]
510 pub fn new(
511 instrument_name: impl Into<String>,
512 start_timestamp: i64,
513 end_timestamp: i64,
514 ) -> Self {
515 Self {
516 instrument_name: instrument_name.into(),
517 start_timestamp,
518 end_timestamp,
519 count: None,
520 sorting: None,
521 }
522 }
523
524 #[must_use]
526 pub fn builder() -> GetUserTradesByInstrumentAndTimeParamsBuilder {
527 GetUserTradesByInstrumentAndTimeParamsBuilder::default()
528 }
529}
530
531#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
534#[builder(setter(into, strip_option))]
535pub struct GetUserTradesByCurrencyAndTimeParams {
536 pub currency: DeribitCurrency,
538 pub start_timestamp: i64,
540 pub end_timestamp: i64,
542 #[serde(skip_serializing_if = "Option::is_none")]
544 #[builder(default)]
545 pub kind: Option<DeribitProductType>,
546 #[serde(skip_serializing_if = "Option::is_none")]
548 #[builder(default)]
549 pub count: Option<u32>,
550 #[serde(skip_serializing_if = "Option::is_none")]
552 #[builder(default)]
553 pub sorting: Option<String>,
554}
555
556impl GetUserTradesByCurrencyAndTimeParams {
557 #[must_use]
559 pub fn new(currency: DeribitCurrency, start_timestamp: i64, end_timestamp: i64) -> Self {
560 Self {
561 currency,
562 start_timestamp,
563 end_timestamp,
564 kind: None,
565 count: None,
566 sorting: None,
567 }
568 }
569
570 #[must_use]
572 pub fn builder() -> GetUserTradesByCurrencyAndTimeParamsBuilder {
573 GetUserTradesByCurrencyAndTimeParamsBuilder::default()
574 }
575}
576
577#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
579#[builder(setter(into, strip_option))]
580pub struct GetBookSummaryByCurrencyParams {
581 pub currency: String,
583 #[serde(skip_serializing_if = "Option::is_none")]
585 #[builder(default)]
586 pub kind: Option<String>,
587}
588
589impl GetBookSummaryByCurrencyParams {
590 #[must_use]
592 pub fn options(currency: impl Into<String>) -> Self {
593 Self {
594 currency: currency.into(),
595 kind: Some("option".to_string()),
596 }
597 }
598}
599
600#[derive(Clone, Debug, Deserialize, Serialize)]
602pub struct GetTickerParams {
603 pub instrument_name: String,
605}
606
607#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
610#[builder(setter(into, strip_option))]
611pub struct GetPositionsParams {
612 pub currency: DeribitCurrency,
614 #[serde(skip_serializing_if = "Option::is_none")]
616 #[builder(default)]
617 pub kind: Option<DeribitProductType>,
618}
619
620impl GetPositionsParams {
621 #[must_use]
623 pub fn new(currency: DeribitCurrency) -> Self {
624 Self {
625 currency,
626 kind: None,
627 }
628 }
629
630 #[must_use]
632 pub fn builder() -> GetPositionsParamsBuilder {
633 GetPositionsParamsBuilder::default()
634 }
635}
636
637#[cfg(test)]
638mod tests {
639 use rstest::rstest;
640 use serde_json::{Value, json};
641
642 use super::*;
643
644 #[rstest]
645 fn test_get_expirations_params_default_payload() {
646 let params = GetExpirationsParams::new("BTC", DeribitExpirationKind::Option);
647 let value: Value = serde_json::to_value(¶ms).unwrap();
648 assert_eq!(value, json!({"currency": "BTC", "kind": "option"}));
649 }
650
651 #[rstest]
652 fn test_get_expirations_params_full_payload() {
653 let params = GetExpirationsParams::builder()
654 .currency("grouped")
655 .kind(DeribitExpirationKind::Any)
656 .currency_pair("btc_usd")
657 .build()
658 .unwrap();
659 let value: Value = serde_json::to_value(¶ms).unwrap();
660 assert_eq!(
661 value,
662 json!({
663 "currency": "grouped",
664 "kind": "any",
665 "currency_pair": "btc_usd",
666 }),
667 );
668 }
669
670 #[rstest]
671 fn test_get_expirations_params_combo_kind_serialization() {
672 let params = GetExpirationsParams::new("BTC", DeribitExpirationKind::OptionCombo);
673 let value: Value = serde_json::to_value(¶ms).unwrap();
674 assert_eq!(value, json!({"currency": "BTC", "kind": "option_combo"}));
675 }
676
677 #[rstest]
678 fn test_get_combos_params_serialization() {
679 let params = GetCombosParams::new(DeribitCurrency::BTC);
680 let value: Value = serde_json::to_value(params).unwrap();
681 assert_eq!(value, json!({"currency": "BTC"}));
682 }
683
684 #[rstest]
685 fn test_get_last_trades_by_currency_params_default_omits_optionals() {
686 let params = GetLastTradesByCurrencyParams::new(DeribitCurrency::BTC);
689 let value: Value = serde_json::to_value(¶ms).unwrap();
690 assert_eq!(value, json!({"currency": "BTC"}));
691 }
692
693 #[rstest]
694 fn test_get_last_trades_by_currency_params_full_payload() {
695 let params = GetLastTradesByCurrencyParams {
698 currency: DeribitCurrency::BTC,
699 kind: Some(DeribitProductType::FutureCombo),
700 start_id: Some("100".to_string()),
701 end_id: Some("200".to_string()),
702 count: Some(50),
703 include_old: Some(true),
704 sorting: Some("asc".to_string()),
705 };
706 let value: Value = serde_json::to_value(¶ms).unwrap();
707 assert_eq!(
708 value,
709 json!({
710 "currency": "BTC",
711 "kind": "future_combo",
712 "start_id": "100",
713 "end_id": "200",
714 "count": 50,
715 "include_old": true,
716 "sorting": "asc",
717 }),
718 );
719 }
720
721 #[rstest]
722 fn test_get_last_trades_by_currency_params_with_kind_constructor() {
723 let params = GetLastTradesByCurrencyParams::with_kind(
724 DeribitCurrency::ETH,
725 DeribitProductType::OptionCombo,
726 );
727 let value: Value = serde_json::to_value(¶ms).unwrap();
728 assert_eq!(value, json!({"currency": "ETH", "kind": "option_combo"}));
729 }
730
731 #[rstest]
732 fn test_get_last_trades_by_currency_params_builder_partial() {
733 let params = GetLastTradesByCurrencyParams::builder()
734 .currency(DeribitCurrency::BTC)
735 .kind(DeribitProductType::FutureCombo)
736 .count(25_u32)
737 .include_old(true)
738 .build()
739 .unwrap();
740 let value: Value = serde_json::to_value(¶ms).unwrap();
741 assert_eq!(
742 value,
743 json!({
744 "currency": "BTC",
745 "kind": "future_combo",
746 "count": 25,
747 "include_old": true,
748 }),
749 );
750 }
751}