Skip to main content

rust_okx/ws/
arg.rs

1//! WebSocket subscription arguments.
2
3use std::collections::BTreeMap;
4
5use serde::{Deserialize, Serialize};
6
7/// A WebSocket channel argument used in subscribe/unsubscribe requests and
8/// returned in channel acknowledgements/data pushes.
9///
10/// Use [`Arg::new`] for a channel-only subscription, then add standard
11/// instrument filters or custom channel parameters with consuming setters.
12///
13/// OKX docs: <https://www.okx.com/docs-v5/en/#overview-websocket-subscribe>
14#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
15#[serde(rename_all = "camelCase")]
16#[non_exhaustive]
17pub struct Arg {
18    /// OKX channel name, e.g. `tickers`, `books5`, `account`, or `orders`.
19    pub channel: String,
20    /// Instrument ID, e.g. `BTC-USDT`.
21    #[serde(rename = "instId", skip_serializing_if = "Option::is_none")]
22    pub inst_id: Option<String>,
23    /// Instrument type, e.g. `SPOT` or `SWAP`.
24    #[serde(rename = "instType", skip_serializing_if = "Option::is_none")]
25    pub inst_type: Option<String>,
26    /// Instrument family, e.g. `BTC-USD`.
27    #[serde(rename = "instFamily", skip_serializing_if = "Option::is_none")]
28    pub inst_family: Option<String>,
29    /// Additional channel parameters not modeled as first-class fields.
30    #[serde(flatten, default, skip_serializing_if = "BTreeMap::is_empty")]
31    pub extra: BTreeMap<String, String>,
32}
33
34impl Arg {
35    /// Create a channel argument.
36    pub fn new(channel: impl Into<String>) -> Self {
37        Self {
38            channel: channel.into(),
39            inst_id: None,
40            inst_type: None,
41            inst_family: None,
42            extra: BTreeMap::new(),
43        }
44    }
45
46    /// Set the instrument ID.
47    pub fn inst_id(mut self, inst_id: impl Into<String>) -> Self {
48        self.inst_id = Some(inst_id.into());
49        self
50    }
51
52    /// Set the instrument type.
53    pub fn inst_type(mut self, inst_type: impl Into<String>) -> Self {
54        self.inst_type = Some(inst_type.into());
55        self
56    }
57
58    /// Set the instrument family.
59    pub fn inst_family(mut self, inst_family: impl Into<String>) -> Self {
60        self.inst_family = Some(inst_family.into());
61        self
62    }
63
64    /// Set an arbitrary channel parameter.
65    pub fn param(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
66        self.extra.insert(key.into(), value.into());
67        self
68    }
69
70    /// Set the extraParams parameter.
71    pub fn extra_param(self, update_interval: impl Into<String>) -> Self {
72        let extra = format!("{{\"updateInterval\":\"{}\"}}", update_interval.into());
73        self.param("extraParams", extra)
74    }
75
76    /// Set the currency parameter.
77    pub fn ccy(self, ccy: impl Into<String>) -> Self {
78        self.param("ccy", ccy)
79    }
80
81    /// Set the spread ID parameter.
82    pub fn sprd_id(self, sprd_id: impl Into<String>) -> Self {
83        self.param("sprdId", sprd_id)
84    }
85
86    /// Set the algo order ID parameter.
87    pub fn algo_id(self, algo_id: impl Into<String>) -> Self {
88        self.param("algoId", algo_id)
89    }
90
91    /// Set the grid type parameter.
92    pub fn grid_type(self, grid_type: impl Into<String>) -> Self {
93        self.param("gridType", grid_type)
94    }
95}