use serde::Serialize;
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct PlaceSpreadOrderRequest {
pub sprd_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub cl_ord_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tag: Option<String>,
pub side: String,
pub ord_type: String,
pub sz: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub px: Option<String>,
}
impl PlaceSpreadOrderRequest {
pub fn new(
sprd_id: impl Into<String>,
side: impl Into<String>,
ord_type: impl Into<String>,
size: impl Into<String>,
) -> Self {
Self {
sprd_id: sprd_id.into(),
cl_ord_id: None,
tag: None,
side: side.into(),
ord_type: ord_type.into(),
sz: size.into(),
px: None,
}
}
pub fn client_order_id(mut self, cl_ord_id: impl Into<String>) -> Self {
self.cl_ord_id = Some(cl_ord_id.into());
self
}
pub fn tag(mut self, tag: impl Into<String>) -> Self {
self.tag = Some(tag.into());
self
}
pub fn price(mut self, price: impl Into<String>) -> Self {
self.px = Some(price.into());
self
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct AmendSpreadOrderRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub ord_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cl_ord_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub req_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub new_sz: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub new_px: Option<String>,
}
impl AmendSpreadOrderRequest {
pub fn by_order_id(ord_id: impl Into<String>) -> Self {
Self {
ord_id: Some(ord_id.into()),
..Self::default()
}
}
pub fn by_client_order_id(cl_ord_id: impl Into<String>) -> Self {
Self {
cl_ord_id: Some(cl_ord_id.into()),
..Self::default()
}
}
pub fn request_id(mut self, req_id: impl Into<String>) -> Self {
self.req_id = Some(req_id.into());
self
}
pub fn new_size(mut self, size: impl Into<String>) -> Self {
self.new_sz = Some(size.into());
self
}
pub fn new_price(mut self, price: impl Into<String>) -> Self {
self.new_px = Some(price.into());
self
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct CancelSpreadOrderRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub ord_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cl_ord_id: Option<String>,
}
impl CancelSpreadOrderRequest {
pub fn by_order_id(ord_id: impl Into<String>) -> Self {
Self {
ord_id: Some(ord_id.into()),
cl_ord_id: None,
}
}
pub fn by_client_order_id(cl_ord_id: impl Into<String>) -> Self {
Self {
ord_id: None,
cl_ord_id: Some(cl_ord_id.into()),
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct MassCancelSpreadOrdersRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub sprd_id: Option<String>,
}
impl MassCancelSpreadOrdersRequest {
pub fn all() -> Self {
Self::default()
}
pub fn for_spread(sprd_id: impl Into<String>) -> Self {
Self {
sprd_id: Some(sprd_id.into()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serializes_documented_place_order_example() {
let request = PlaceSpreadOrderRequest::new("BTC-USDT_BTC-USDT-SWAP", "buy", "limit", "2")
.client_order_id("b15")
.price("2.15");
let value = serde_json::to_value(request).unwrap();
assert_eq!(value["sprdId"], "BTC-USDT_BTC-USDT-SWAP");
assert_eq!(value["ordType"], "limit");
assert_eq!(value["px"], "2.15");
}
#[test]
fn mass_cancel_all_serializes_as_empty_object() {
let value = serde_json::to_value(MassCancelSpreadOrdersRequest::all()).unwrap();
assert_eq!(value, serde_json::json!({}));
}
}