Skip to main content

rust_okx/api/convert/
requests.rs

1use serde::Serialize;
2
3use crate::model::OrderSide;
4
5/// Convert mode used by currency-pair, quote, and trade requests.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
7#[non_exhaustive]
8pub enum ConvertMode {
9    /// Standard Convert flow.
10    #[serde(rename = "0")]
11    Standard,
12    /// Large-order Convert flow for eligible VIP users.
13    #[serde(rename = "1")]
14    LargeOrderVip,
15}
16
17/// Empty query for [`Convert::get_currencies`](super::Convert::get_currencies).
18#[derive(Debug, Clone, Copy, Default, Serialize)]
19pub struct ConvertCurrenciesRequest {}
20
21impl ConvertCurrenciesRequest {
22    /// Create the empty currencies request.
23    pub const fn new() -> Self {
24        Self {}
25    }
26}
27
28/// Query parameters for [`Convert::get_currency_pair`](super::Convert::get_currency_pair).
29#[derive(Debug, Clone, Serialize)]
30#[serde(rename_all = "camelCase")]
31pub struct ConvertCurrencyPairRequest {
32    from_ccy: String,
33    to_ccy: String,
34    #[serde(skip_serializing_if = "Option::is_none")]
35    convert_mode: Option<ConvertMode>,
36}
37
38impl ConvertCurrencyPairRequest {
39    /// Create a currency-pair request with the required source and destination currencies.
40    pub fn new(from_ccy: impl Into<String>, to_ccy: impl Into<String>) -> Self {
41        Self {
42            from_ccy: from_ccy.into(),
43            to_ccy: to_ccy.into(),
44            convert_mode: None,
45        }
46    }
47
48    /// Select the standard or VIP large-order Convert mode.
49    pub fn convert_mode(mut self, convert_mode: ConvertMode) -> Self {
50        self.convert_mode = Some(convert_mode);
51        self
52    }
53}
54
55/// Request body for [`Convert::estimate_quote`](super::Convert::estimate_quote).
56#[derive(Debug, Clone, Serialize)]
57#[serde(rename_all = "camelCase")]
58pub struct ConvertQuoteRequest {
59    base_ccy: String,
60    quote_ccy: String,
61    side: OrderSide,
62    rfq_sz: String,
63    rfq_sz_ccy: String,
64    #[serde(skip_serializing_if = "Option::is_none")]
65    cl_q_req_id: Option<String>,
66    #[serde(skip_serializing_if = "Option::is_none")]
67    tag: Option<String>,
68    #[serde(skip_serializing_if = "Option::is_none")]
69    convert_mode: Option<ConvertMode>,
70}
71
72impl ConvertQuoteRequest {
73    /// Create an estimate-quote request with all fields required by OKX.
74    pub fn new(
75        base_ccy: impl Into<String>,
76        quote_ccy: impl Into<String>,
77        side: OrderSide,
78        rfq_sz: impl Into<String>,
79        rfq_sz_ccy: impl Into<String>,
80    ) -> Self {
81        Self {
82            base_ccy: base_ccy.into(),
83            quote_ccy: quote_ccy.into(),
84            side,
85            rfq_sz: rfq_sz.into(),
86            rfq_sz_ccy: rfq_sz_ccy.into(),
87            cl_q_req_id: None,
88            tag: None,
89            convert_mode: None,
90        }
91    }
92
93    /// Set the client quote request ID (`clQReqId`).
94    pub fn client_quote_request_id(mut self, id: impl Into<String>) -> Self {
95        self.cl_q_req_id = Some(id.into());
96        self
97    }
98
99    /// Set the broker order tag.
100    pub fn tag(mut self, tag: impl Into<String>) -> Self {
101        self.tag = Some(tag.into());
102        self
103    }
104
105    /// Select the standard or VIP large-order Convert mode.
106    pub fn convert_mode(mut self, convert_mode: ConvertMode) -> Self {
107        self.convert_mode = Some(convert_mode);
108        self
109    }
110}
111
112/// Request body for [`Convert::convert_trade`](super::Convert::convert_trade).
113#[derive(Debug, Clone, Serialize)]
114#[serde(rename_all = "camelCase")]
115pub struct ConvertTradeRequest {
116    quote_id: String,
117    base_ccy: String,
118    quote_ccy: String,
119    side: OrderSide,
120    sz: String,
121    sz_ccy: String,
122    #[serde(skip_serializing_if = "Option::is_none")]
123    cl_t_req_id: Option<String>,
124    #[serde(skip_serializing_if = "Option::is_none")]
125    tag: Option<String>,
126    #[serde(skip_serializing_if = "Option::is_none")]
127    convert_mode: Option<ConvertMode>,
128}
129
130impl ConvertTradeRequest {
131    /// Create a Convert trade request with all fields required by OKX.
132    pub fn new(
133        quote_id: impl Into<String>,
134        base_ccy: impl Into<String>,
135        quote_ccy: impl Into<String>,
136        side: OrderSide,
137        sz: impl Into<String>,
138        sz_ccy: impl Into<String>,
139    ) -> Self {
140        Self {
141            quote_id: quote_id.into(),
142            base_ccy: base_ccy.into(),
143            quote_ccy: quote_ccy.into(),
144            side,
145            sz: sz.into(),
146            sz_ccy: sz_ccy.into(),
147            cl_t_req_id: None,
148            tag: None,
149            convert_mode: None,
150        }
151    }
152
153    /// Set the client trade request ID (`clTReqId`).
154    pub fn client_trade_request_id(mut self, id: impl Into<String>) -> Self {
155        self.cl_t_req_id = Some(id.into());
156        self
157    }
158
159    /// Set the broker order tag.
160    pub fn tag(mut self, tag: impl Into<String>) -> Self {
161        self.tag = Some(tag.into());
162        self
163    }
164
165    /// Select the standard or VIP large-order Convert mode.
166    pub fn convert_mode(mut self, convert_mode: ConvertMode) -> Self {
167        self.convert_mode = Some(convert_mode);
168        self
169    }
170}
171
172/// Query parameters for [`Convert::get_convert_history`](super::Convert::get_convert_history).
173#[derive(Debug, Clone, Default, Serialize)]
174#[serde(rename_all = "camelCase")]
175pub struct ConvertHistoryRequest {
176    #[serde(skip_serializing_if = "Option::is_none")]
177    cl_t_req_id: Option<String>,
178    #[serde(skip_serializing_if = "Option::is_none")]
179    after: Option<String>,
180    #[serde(skip_serializing_if = "Option::is_none")]
181    before: Option<String>,
182    #[serde(skip_serializing_if = "Option::is_none")]
183    limit: Option<String>,
184    #[serde(skip_serializing_if = "Option::is_none")]
185    tag: Option<String>,
186}
187
188impl ConvertHistoryRequest {
189    /// Create an empty history query.
190    pub fn new() -> Self {
191        Self::default()
192    }
193
194    /// Filter by the client trade request ID (`clTReqId`).
195    pub fn client_trade_request_id(mut self, id: impl Into<String>) -> Self {
196        self.cl_t_req_id = Some(id.into());
197        self
198    }
199
200    /// Return records earlier than this millisecond timestamp.
201    pub fn after(mut self, timestamp_ms: u64) -> Self {
202        self.after = Some(timestamp_ms.to_string());
203        self
204    }
205
206    /// Return records newer than this millisecond timestamp.
207    pub fn before(mut self, timestamp_ms: u64) -> Self {
208        self.before = Some(timestamp_ms.to_string());
209        self
210    }
211
212    /// Set the maximum number of returned rows. OKX accepts values from 1 to 100.
213    pub fn limit(mut self, limit: u8) -> Self {
214        self.limit = Some(limit.to_string());
215        self
216    }
217
218    /// Filter by the broker order tag used by the original Convert trade.
219    pub fn tag(mut self, tag: impl Into<String>) -> Self {
220        self.tag = Some(tag.into());
221        self
222    }
223}