Skip to main content

rust_okx/api/convert/
requests.rs

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