use serde::{Deserialize, Serialize};
use crate::client::Client;
use crate::error::Error;
use crate::models::transaction::{
OrderCancelRejectTransaction, OrderCancelTransaction,
OrderClientExtensionsModifyRejectTransaction, OrderClientExtensionsModifyTransaction,
OrderFillTransaction, Transaction,
};
use crate::models::{
AccountId, ClientExtensions, InstrumentName, Order, OrderId, OrderRequest, OrderSpecifier,
OrderStateFilter, TransactionId,
};
impl Client {
pub async fn create_order(
&self,
account_id: impl Into<AccountId>,
order: impl Into<OrderRequest>,
) -> Result<CreateOrderResponse, Error> {
let account_id = account_id.into();
let request = self
.post(&["accounts", account_id.as_str(), "orders"])
.json(&OrderRequestBody {
order: order.into(),
});
let (mut response, headers): (CreateOrderResponse, _) =
self.execute_with_headers(request).await?;
response.location = crate::transport::header_str(&headers, "Location").map(str::to_owned);
Ok(response)
}
pub fn list_orders(&self, account_id: impl Into<AccountId>) -> ListOrdersRequest {
ListOrdersRequest {
client: self.clone(),
account_id: account_id.into(),
params: Vec::new(),
}
}
pub async fn list_pending_orders(
&self,
account_id: impl Into<AccountId>,
) -> Result<ListOrdersResponse, Error> {
let account_id = account_id.into();
self.execute(self.get(&["accounts", account_id.as_str(), "pendingOrders"]))
.await
}
pub async fn order(
&self,
account_id: impl Into<AccountId>,
order: impl Into<OrderSpecifier>,
) -> Result<OrderResponse, Error> {
let account_id = account_id.into();
let order = order.into();
self.execute(self.get(&["accounts", account_id.as_str(), "orders", order.as_str()]))
.await
}
pub async fn replace_order(
&self,
account_id: impl Into<AccountId>,
order: impl Into<OrderSpecifier>,
replacement: impl Into<OrderRequest>,
) -> Result<ReplaceOrderResponse, Error> {
let account_id = account_id.into();
let order = order.into();
let request = self
.put(&["accounts", account_id.as_str(), "orders", order.as_str()])
.json(&OrderRequestBody {
order: replacement.into(),
});
let (mut response, headers): (ReplaceOrderResponse, _) =
self.execute_with_headers(request).await?;
response.location = crate::transport::header_str(&headers, "Location").map(str::to_owned);
Ok(response)
}
pub async fn cancel_order(
&self,
account_id: impl Into<AccountId>,
order: impl Into<OrderSpecifier>,
) -> Result<CancelOrderResponse, Error> {
let account_id = account_id.into();
let order = order.into();
self.execute(self.put(&[
"accounts",
account_id.as_str(),
"orders",
order.as_str(),
"cancel",
]))
.await
}
pub fn set_order_client_extensions(
&self,
account_id: impl Into<AccountId>,
order: impl Into<OrderSpecifier>,
) -> SetOrderClientExtensionsRequest {
SetOrderClientExtensionsRequest {
client: self.clone(),
account_id: account_id.into(),
order: order.into(),
body: SetOrderClientExtensionsBody {
client_extensions: None,
trade_client_extensions: None,
},
}
}
}
#[derive(Debug, Serialize)]
struct OrderRequestBody {
order: OrderRequest,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct CreateOrderResponse {
#[serde(rename = "orderCreateTransaction")]
pub order_create_transaction: Transaction,
#[serde(
rename = "orderFillTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_fill_transaction: Option<OrderFillTransaction>,
#[serde(
rename = "orderCancelTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_cancel_transaction: Option<OrderCancelTransaction>,
#[serde(
rename = "orderReissueTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_reissue_transaction: Option<Transaction>,
#[serde(
rename = "orderReissueRejectTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_reissue_reject_transaction: Option<Transaction>,
#[serde(
rename = "relatedTransactionIDs",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub related_transaction_ids: Vec<TransactionId>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
#[serde(skip)]
pub location: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct CreateOrderRejectBody {
#[serde(
rename = "orderRejectTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_reject_transaction: Option<Transaction>,
#[serde(
rename = "relatedTransactionIDs",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub related_transaction_ids: Vec<TransactionId>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug)]
pub struct ListOrdersRequest {
client: Client,
account_id: AccountId,
params: Vec<(&'static str, String)>,
}
impl ListOrdersRequest {
pub fn ids<I>(mut self, ids: I) -> Self
where
I: IntoIterator,
I::Item: Into<OrderId>,
{
let joined = ids
.into_iter()
.map(|id| id.into().0)
.collect::<Vec<_>>()
.join(",");
self.params.push(("ids", joined));
self
}
pub fn state(mut self, state: OrderStateFilter) -> Self {
self.params.push(("state", state.to_string()));
self
}
pub fn instrument(mut self, instrument: impl Into<InstrumentName>) -> Self {
self.params
.push(("instrument", instrument.into().as_str().to_owned()));
self
}
pub fn count(mut self, count: u32) -> Self {
self.params.push(("count", count.to_string()));
self
}
pub fn before_id(mut self, before_id: impl Into<OrderId>) -> Self {
self.params.push(("beforeID", before_id.into().0));
self
}
pub async fn send(self) -> Result<ListOrdersResponse, Error> {
let request = self
.client
.get(&["accounts", self.account_id.as_str(), "orders"])
.query(&self.params);
self.client.execute(request).await
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ListOrdersResponse {
#[serde(rename = "orders", default, skip_serializing_if = "Vec::is_empty")]
pub orders: Vec<Order>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct OrderResponse {
#[serde(rename = "order")]
pub order: Order,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ReplaceOrderResponse {
#[serde(
rename = "orderCancelTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_cancel_transaction: Option<OrderCancelTransaction>,
#[serde(
rename = "orderCreateTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_create_transaction: Option<Transaction>,
#[serde(
rename = "orderFillTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_fill_transaction: Option<OrderFillTransaction>,
#[serde(
rename = "orderReissueTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_reissue_transaction: Option<Transaction>,
#[serde(
rename = "orderReissueRejectTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_reissue_reject_transaction: Option<Transaction>,
#[serde(
rename = "replacingOrderCancelTransaction",
skip_serializing_if = "Option::is_none"
)]
pub replacing_order_cancel_transaction: Option<OrderCancelTransaction>,
#[serde(
rename = "relatedTransactionIDs",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub related_transaction_ids: Vec<TransactionId>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
#[serde(skip)]
pub location: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct CancelOrderResponse {
#[serde(
rename = "orderCancelTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_cancel_transaction: Option<OrderCancelTransaction>,
#[serde(
rename = "relatedTransactionIDs",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub related_transaction_ids: Vec<TransactionId>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct CancelOrderRejectBody {
#[serde(
rename = "orderCancelRejectTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_cancel_reject_transaction: Option<OrderCancelRejectTransaction>,
#[serde(
rename = "relatedTransactionIDs",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub related_transaction_ids: Vec<TransactionId>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug)]
pub struct SetOrderClientExtensionsRequest {
client: Client,
account_id: AccountId,
order: OrderSpecifier,
body: SetOrderClientExtensionsBody,
}
#[derive(Debug, Serialize)]
struct SetOrderClientExtensionsBody {
#[serde(rename = "clientExtensions", skip_serializing_if = "Option::is_none")]
client_extensions: Option<ClientExtensions>,
#[serde(
rename = "tradeClientExtensions",
skip_serializing_if = "Option::is_none"
)]
trade_client_extensions: Option<ClientExtensions>,
}
impl SetOrderClientExtensionsRequest {
pub fn client_extensions(mut self, extensions: ClientExtensions) -> Self {
self.body.client_extensions = Some(extensions);
self
}
pub fn trade_client_extensions(mut self, extensions: ClientExtensions) -> Self {
self.body.trade_client_extensions = Some(extensions);
self
}
pub async fn send(self) -> Result<SetOrderClientExtensionsResponse, Error> {
let request = self
.client
.put(&[
"accounts",
self.account_id.as_str(),
"orders",
self.order.as_str(),
"clientExtensions",
])
.json(&self.body);
self.client.execute(request).await
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct SetOrderClientExtensionsResponse {
#[serde(
rename = "orderClientExtensionsModifyTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_client_extensions_modify_transaction: Option<OrderClientExtensionsModifyTransaction>,
#[serde(
rename = "relatedTransactionIDs",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub related_transaction_ids: Vec<TransactionId>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[non_exhaustive]
pub struct SetOrderClientExtensionsRejectBody {
#[serde(
rename = "orderClientExtensionsModifyRejectTransaction",
skip_serializing_if = "Option::is_none"
)]
pub order_client_extensions_modify_reject_transaction:
Option<OrderClientExtensionsModifyRejectTransaction>,
#[serde(
rename = "relatedTransactionIDs",
default,
skip_serializing_if = "Vec::is_empty"
)]
pub related_transaction_ids: Vec<TransactionId>,
#[serde(rename = "lastTransactionID", skip_serializing_if = "Option::is_none")]
pub last_transaction_id: Option<TransactionId>,
}