1use serde::{Deserialize, Serialize};
4
5use crate::client::Client;
6use crate::error::Error;
7use crate::models::transaction::{
8 OrderCancelRejectTransaction, OrderCancelTransaction,
9 OrderClientExtensionsModifyRejectTransaction, OrderClientExtensionsModifyTransaction,
10 OrderFillTransaction, Transaction,
11};
12use crate::models::{
13 AccountId, ClientExtensions, InstrumentName, Order, OrderId, OrderRequest, OrderSpecifier,
14 OrderStateFilter, TransactionId,
15};
16
17impl Client {
18 pub async fn create_order(
48 &self,
49 account_id: impl Into<AccountId>,
50 order: impl Into<OrderRequest>,
51 ) -> Result<CreateOrderResponse, Error> {
52 let account_id = account_id.into();
53 let request = self
54 .post(&["accounts", account_id.as_str(), "orders"])
55 .json(&OrderRequestBody {
56 order: order.into(),
57 });
58 let (mut response, headers): (CreateOrderResponse, _) =
59 self.execute_with_headers(request).await?;
60 response.location = crate::transport::header_str(&headers, "Location").map(str::to_owned);
61 Ok(response)
62 }
63
64 pub fn list_orders(&self, account_id: impl Into<AccountId>) -> ListOrdersRequest {
68 ListOrdersRequest {
69 client: self.clone(),
70 account_id: account_id.into(),
71 params: Vec::new(),
72 }
73 }
74
75 pub async fn list_pending_orders(
79 &self,
80 account_id: impl Into<AccountId>,
81 ) -> Result<ListOrdersResponse, Error> {
82 let account_id = account_id.into();
83 self.execute(self.get(&["accounts", account_id.as_str(), "pendingOrders"]))
84 .await
85 }
86
87 pub async fn order(
91 &self,
92 account_id: impl Into<AccountId>,
93 order: impl Into<OrderSpecifier>,
94 ) -> Result<OrderResponse, Error> {
95 let account_id = account_id.into();
96 let order = order.into();
97 self.execute(self.get(&["accounts", account_id.as_str(), "orders", order.as_str()]))
98 .await
99 }
100
101 pub async fn replace_order(
106 &self,
107 account_id: impl Into<AccountId>,
108 order: impl Into<OrderSpecifier>,
109 replacement: impl Into<OrderRequest>,
110 ) -> Result<ReplaceOrderResponse, Error> {
111 let account_id = account_id.into();
112 let order = order.into();
113 let request = self
114 .put(&["accounts", account_id.as_str(), "orders", order.as_str()])
115 .json(&OrderRequestBody {
116 order: replacement.into(),
117 });
118 let (mut response, headers): (ReplaceOrderResponse, _) =
119 self.execute_with_headers(request).await?;
120 response.location = crate::transport::header_str(&headers, "Location").map(str::to_owned);
121 Ok(response)
122 }
123
124 pub async fn cancel_order(
134 &self,
135 account_id: impl Into<AccountId>,
136 order: impl Into<OrderSpecifier>,
137 ) -> Result<CancelOrderResponse, Error> {
138 let account_id = account_id.into();
139 let order = order.into();
140 self.execute(self.put(&[
141 "accounts",
142 account_id.as_str(),
143 "orders",
144 order.as_str(),
145 "cancel",
146 ]))
147 .await
148 }
149
150 pub fn set_order_client_extensions(
157 &self,
158 account_id: impl Into<AccountId>,
159 order: impl Into<OrderSpecifier>,
160 ) -> SetOrderClientExtensionsRequest {
161 SetOrderClientExtensionsRequest {
162 client: self.clone(),
163 account_id: account_id.into(),
164 order: order.into(),
165 body: SetOrderClientExtensionsBody {
166 client_extensions: None,
167 trade_client_extensions: None,
168 },
169 }
170 }
171}
172
173#[derive(Debug, Serialize)]
174struct OrderRequestBody {
175 order: OrderRequest,
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize)]
180#[non_exhaustive]
181pub struct CreateOrderResponse {
182 #[serde(rename = "orderCreateTransaction")]
184 pub order_create_transaction: Transaction,
185 #[serde(
188 rename = "orderFillTransaction",
189 skip_serializing_if = "Option::is_none"
190 )]
191 pub order_fill_transaction: Option<OrderFillTransaction>,
192 #[serde(
195 rename = "orderCancelTransaction",
196 skip_serializing_if = "Option::is_none"
197 )]
198 pub order_cancel_transaction: Option<OrderCancelTransaction>,
199 #[serde(
202 rename = "orderReissueTransaction",
203 skip_serializing_if = "Option::is_none"
204 )]
205 pub order_reissue_transaction: Option<Transaction>,
206 #[serde(
208 rename = "orderReissueRejectTransaction",
209 skip_serializing_if = "Option::is_none"
210 )]
211 pub order_reissue_reject_transaction: Option<Transaction>,
212 #[serde(
214 rename = "relatedTransactionIDs",
215 default,
216 skip_serializing_if = "Vec::is_empty"
217 )]
218 pub related_transaction_ids: Vec<TransactionId>,
219 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
221 pub last_transaction_id: Option<TransactionId>,
222 #[serde(skip)]
224 pub location: Option<String>,
225}
226
227#[derive(Debug, Clone, Serialize, Deserialize)]
231#[non_exhaustive]
232pub struct CreateOrderRejectBody {
233 #[serde(
235 rename = "orderRejectTransaction",
236 skip_serializing_if = "Option::is_none"
237 )]
238 pub order_reject_transaction: Option<Transaction>,
239 #[serde(
241 rename = "relatedTransactionIDs",
242 default,
243 skip_serializing_if = "Vec::is_empty"
244 )]
245 pub related_transaction_ids: Vec<TransactionId>,
246 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
248 pub last_transaction_id: Option<TransactionId>,
249}
250
251#[derive(Debug)]
253pub struct ListOrdersRequest {
254 client: Client,
255 account_id: AccountId,
256 params: Vec<(&'static str, String)>,
257}
258
259impl ListOrdersRequest {
260 pub fn ids<I>(mut self, ids: I) -> Self
262 where
263 I: IntoIterator,
264 I::Item: Into<OrderId>,
265 {
266 let joined = ids
267 .into_iter()
268 .map(|id| id.into().0)
269 .collect::<Vec<_>>()
270 .join(",");
271 self.params.push(("ids", joined));
272 self
273 }
274
275 pub fn state(mut self, state: OrderStateFilter) -> Self {
277 self.params.push(("state", state.to_string()));
278 self
279 }
280
281 pub fn instrument(mut self, instrument: impl Into<InstrumentName>) -> Self {
283 self.params
284 .push(("instrument", instrument.into().as_str().to_owned()));
285 self
286 }
287
288 pub fn count(mut self, count: u32) -> Self {
290 self.params.push(("count", count.to_string()));
291 self
292 }
293
294 pub fn before_id(mut self, before_id: impl Into<OrderId>) -> Self {
297 self.params.push(("beforeID", before_id.into().0));
298 self
299 }
300
301 pub async fn send(self) -> Result<ListOrdersResponse, Error> {
303 let request = self
304 .client
305 .get(&["accounts", self.account_id.as_str(), "orders"])
306 .query(&self.params);
307 self.client.execute(request).await
308 }
309}
310
311#[derive(Debug, Clone, Serialize, Deserialize)]
313#[non_exhaustive]
314pub struct ListOrdersResponse {
315 #[serde(rename = "orders", default, skip_serializing_if = "Vec::is_empty")]
317 pub orders: Vec<Order>,
318 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
320 pub last_transaction_id: Option<TransactionId>,
321}
322
323#[derive(Debug, Clone, Serialize, Deserialize)]
325#[non_exhaustive]
326pub struct OrderResponse {
327 #[serde(rename = "order")]
329 pub order: Order,
330 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
332 pub last_transaction_id: Option<TransactionId>,
333}
334
335#[derive(Debug, Clone, Serialize, Deserialize)]
337#[non_exhaustive]
338pub struct ReplaceOrderResponse {
339 #[serde(
341 rename = "orderCancelTransaction",
342 skip_serializing_if = "Option::is_none"
343 )]
344 pub order_cancel_transaction: Option<OrderCancelTransaction>,
345 #[serde(
347 rename = "orderCreateTransaction",
348 skip_serializing_if = "Option::is_none"
349 )]
350 pub order_create_transaction: Option<Transaction>,
351 #[serde(
354 rename = "orderFillTransaction",
355 skip_serializing_if = "Option::is_none"
356 )]
357 pub order_fill_transaction: Option<OrderFillTransaction>,
358 #[serde(
360 rename = "orderReissueTransaction",
361 skip_serializing_if = "Option::is_none"
362 )]
363 pub order_reissue_transaction: Option<Transaction>,
364 #[serde(
366 rename = "orderReissueRejectTransaction",
367 skip_serializing_if = "Option::is_none"
368 )]
369 pub order_reissue_reject_transaction: Option<Transaction>,
370 #[serde(
373 rename = "replacingOrderCancelTransaction",
374 skip_serializing_if = "Option::is_none"
375 )]
376 pub replacing_order_cancel_transaction: Option<OrderCancelTransaction>,
377 #[serde(
379 rename = "relatedTransactionIDs",
380 default,
381 skip_serializing_if = "Vec::is_empty"
382 )]
383 pub related_transaction_ids: Vec<TransactionId>,
384 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
386 pub last_transaction_id: Option<TransactionId>,
387 #[serde(skip)]
389 pub location: Option<String>,
390}
391
392#[derive(Debug, Clone, Serialize, Deserialize)]
394#[non_exhaustive]
395pub struct CancelOrderResponse {
396 #[serde(
398 rename = "orderCancelTransaction",
399 skip_serializing_if = "Option::is_none"
400 )]
401 pub order_cancel_transaction: Option<OrderCancelTransaction>,
402 #[serde(
404 rename = "relatedTransactionIDs",
405 default,
406 skip_serializing_if = "Vec::is_empty"
407 )]
408 pub related_transaction_ids: Vec<TransactionId>,
409 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
411 pub last_transaction_id: Option<TransactionId>,
412}
413
414#[derive(Debug, Clone, Serialize, Deserialize)]
418#[non_exhaustive]
419pub struct CancelOrderRejectBody {
420 #[serde(
422 rename = "orderCancelRejectTransaction",
423 skip_serializing_if = "Option::is_none"
424 )]
425 pub order_cancel_reject_transaction: Option<OrderCancelRejectTransaction>,
426 #[serde(
428 rename = "relatedTransactionIDs",
429 default,
430 skip_serializing_if = "Vec::is_empty"
431 )]
432 pub related_transaction_ids: Vec<TransactionId>,
433 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
435 pub last_transaction_id: Option<TransactionId>,
436}
437
438#[derive(Debug)]
440pub struct SetOrderClientExtensionsRequest {
441 client: Client,
442 account_id: AccountId,
443 order: OrderSpecifier,
444 body: SetOrderClientExtensionsBody,
445}
446
447#[derive(Debug, Serialize)]
448struct SetOrderClientExtensionsBody {
449 #[serde(rename = "clientExtensions", skip_serializing_if = "Option::is_none")]
450 client_extensions: Option<ClientExtensions>,
451 #[serde(
452 rename = "tradeClientExtensions",
453 skip_serializing_if = "Option::is_none"
454 )]
455 trade_client_extensions: Option<ClientExtensions>,
456}
457
458impl SetOrderClientExtensionsRequest {
459 pub fn client_extensions(mut self, extensions: ClientExtensions) -> Self {
461 self.body.client_extensions = Some(extensions);
462 self
463 }
464
465 pub fn trade_client_extensions(mut self, extensions: ClientExtensions) -> Self {
468 self.body.trade_client_extensions = Some(extensions);
469 self
470 }
471
472 pub async fn send(self) -> Result<SetOrderClientExtensionsResponse, Error> {
474 let request = self
475 .client
476 .put(&[
477 "accounts",
478 self.account_id.as_str(),
479 "orders",
480 self.order.as_str(),
481 "clientExtensions",
482 ])
483 .json(&self.body);
484 self.client.execute(request).await
485 }
486}
487
488#[derive(Debug, Clone, Serialize, Deserialize)]
490#[non_exhaustive]
491pub struct SetOrderClientExtensionsResponse {
492 #[serde(
494 rename = "orderClientExtensionsModifyTransaction",
495 skip_serializing_if = "Option::is_none"
496 )]
497 pub order_client_extensions_modify_transaction: Option<OrderClientExtensionsModifyTransaction>,
498 #[serde(
500 rename = "relatedTransactionIDs",
501 default,
502 skip_serializing_if = "Vec::is_empty"
503 )]
504 pub related_transaction_ids: Vec<TransactionId>,
505 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
507 pub last_transaction_id: Option<TransactionId>,
508}
509
510#[derive(Debug, Clone, Serialize, Deserialize)]
514#[non_exhaustive]
515pub struct SetOrderClientExtensionsRejectBody {
516 #[serde(
518 rename = "orderClientExtensionsModifyRejectTransaction",
519 skip_serializing_if = "Option::is_none"
520 )]
521 pub order_client_extensions_modify_reject_transaction:
522 Option<OrderClientExtensionsModifyRejectTransaction>,
523 #[serde(
525 rename = "relatedTransactionIDs",
526 default,
527 skip_serializing_if = "Vec::is_empty"
528 )]
529 pub related_transaction_ids: Vec<TransactionId>,
530 #[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
532 pub last_transaction_id: Option<TransactionId>,
533}