rust_okx/ws/request/
spread.rs1use serde::Serialize;
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
9#[serde(rename_all = "camelCase")]
10#[non_exhaustive]
11pub struct PlaceSpreadOrderRequest {
12 pub sprd_id: String,
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub cl_ord_id: Option<String>,
17 #[serde(skip_serializing_if = "Option::is_none")]
19 pub tag: Option<String>,
20 pub side: String,
22 pub ord_type: String,
24 pub sz: String,
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub px: Option<String>,
29}
30
31impl PlaceSpreadOrderRequest {
32 pub fn new(
34 sprd_id: impl Into<String>,
35 side: impl Into<String>,
36 ord_type: impl Into<String>,
37 size: impl Into<String>,
38 ) -> Self {
39 Self {
40 sprd_id: sprd_id.into(),
41 cl_ord_id: None,
42 tag: None,
43 side: side.into(),
44 ord_type: ord_type.into(),
45 sz: size.into(),
46 px: None,
47 }
48 }
49
50 pub fn client_order_id(mut self, cl_ord_id: impl Into<String>) -> Self {
52 self.cl_ord_id = Some(cl_ord_id.into());
53 self
54 }
55
56 pub fn tag(mut self, tag: impl Into<String>) -> Self {
58 self.tag = Some(tag.into());
59 self
60 }
61
62 pub fn price(mut self, price: impl Into<String>) -> Self {
64 self.px = Some(price.into());
65 self
66 }
67}
68
69#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
76#[serde(rename_all = "camelCase")]
77#[non_exhaustive]
78pub struct AmendSpreadOrderRequest {
79 #[serde(skip_serializing_if = "Option::is_none")]
81 pub ord_id: Option<String>,
82 #[serde(skip_serializing_if = "Option::is_none")]
84 pub cl_ord_id: Option<String>,
85 #[serde(skip_serializing_if = "Option::is_none")]
87 pub req_id: Option<String>,
88 #[serde(skip_serializing_if = "Option::is_none")]
90 pub new_sz: Option<String>,
91 #[serde(skip_serializing_if = "Option::is_none")]
93 pub new_px: Option<String>,
94}
95
96impl AmendSpreadOrderRequest {
97 pub fn by_order_id(ord_id: impl Into<String>) -> Self {
99 Self {
100 ord_id: Some(ord_id.into()),
101 ..Self::default()
102 }
103 }
104
105 pub fn by_client_order_id(cl_ord_id: impl Into<String>) -> Self {
107 Self {
108 cl_ord_id: Some(cl_ord_id.into()),
109 ..Self::default()
110 }
111 }
112
113 pub fn request_id(mut self, req_id: impl Into<String>) -> Self {
115 self.req_id = Some(req_id.into());
116 self
117 }
118
119 pub fn new_size(mut self, size: impl Into<String>) -> Self {
121 self.new_sz = Some(size.into());
122 self
123 }
124
125 pub fn new_price(mut self, price: impl Into<String>) -> Self {
127 self.new_px = Some(price.into());
128 self
129 }
130}
131
132#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
139#[serde(rename_all = "camelCase")]
140#[non_exhaustive]
141pub struct CancelSpreadOrderRequest {
142 #[serde(skip_serializing_if = "Option::is_none")]
144 pub ord_id: Option<String>,
145 #[serde(skip_serializing_if = "Option::is_none")]
147 pub cl_ord_id: Option<String>,
148}
149
150impl CancelSpreadOrderRequest {
151 pub fn by_order_id(ord_id: impl Into<String>) -> Self {
153 Self {
154 ord_id: Some(ord_id.into()),
155 cl_ord_id: None,
156 }
157 }
158
159 pub fn by_client_order_id(cl_ord_id: impl Into<String>) -> Self {
161 Self {
162 ord_id: None,
163 cl_ord_id: Some(cl_ord_id.into()),
164 }
165 }
166}
167
168#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
174#[serde(rename_all = "camelCase")]
175#[non_exhaustive]
176pub struct MassCancelSpreadOrdersRequest {
177 #[serde(skip_serializing_if = "Option::is_none")]
179 pub sprd_id: Option<String>,
180}
181
182impl MassCancelSpreadOrdersRequest {
183 pub fn all() -> Self {
185 Self::default()
186 }
187
188 pub fn for_spread(sprd_id: impl Into<String>) -> Self {
190 Self {
191 sprd_id: Some(sprd_id.into()),
192 }
193 }
194}
195
196#[cfg(test)]
197mod tests {
198 use super::*;
199
200 #[test]
201 fn serializes_documented_place_order_example() {
202 let request = PlaceSpreadOrderRequest::new("BTC-USDT_BTC-USDT-SWAP", "buy", "limit", "2")
203 .client_order_id("b15")
204 .price("2.15");
205 let value = serde_json::to_value(request).unwrap();
206 assert_eq!(value["sprdId"], "BTC-USDT_BTC-USDT-SWAP");
207 assert_eq!(value["ordType"], "limit");
208 assert_eq!(value["px"], "2.15");
209 }
210
211 #[test]
212 fn mass_cancel_all_serializes_as_empty_object() {
213 let value = serde_json::to_value(MassCancelSpreadOrdersRequest::all()).unwrap();
214 assert_eq!(value, serde_json::json!({}));
215 }
216}