use serde::Serialize;
use crate::model::{
OrderSide, RequestValidationError, ValidateRequest, non_empty, range_u64,
validate_client_request_id, validate_side,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize)]
#[non_exhaustive]
pub enum ConvertMode {
#[serde(rename = "0")]
Standard,
#[serde(rename = "1")]
LargeOrderVip,
}
#[derive(Debug, Clone, Copy, Default, Serialize)]
pub struct ConvertCurrenciesRequest {}
impl ConvertCurrenciesRequest {
pub const fn new() -> Self {
Self {}
}
}
impl ValidateRequest for ConvertCurrenciesRequest {
fn validate(&self) -> Result<(), RequestValidationError> {
Ok(())
}
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ConvertCurrencyPairRequest {
from_ccy: String,
to_ccy: String,
#[serde(skip_serializing_if = "Option::is_none")]
convert_mode: Option<ConvertMode>,
}
impl ConvertCurrencyPairRequest {
pub fn new(from_ccy: impl Into<String>, to_ccy: impl Into<String>) -> Self {
Self {
from_ccy: from_ccy.into(),
to_ccy: to_ccy.into(),
convert_mode: None,
}
}
pub fn convert_mode(mut self, convert_mode: ConvertMode) -> Self {
self.convert_mode = Some(convert_mode);
self
}
}
impl ValidateRequest for ConvertCurrencyPairRequest {
fn validate(&self) -> Result<(), RequestValidationError> {
non_empty("fromCcy", &self.from_ccy)?;
non_empty("toCcy", &self.to_ccy)
}
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ConvertQuoteRequest {
base_ccy: String,
quote_ccy: String,
side: OrderSide,
rfq_sz: String,
rfq_sz_ccy: String,
#[serde(skip_serializing_if = "Option::is_none")]
cl_q_req_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
tag: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
convert_mode: Option<ConvertMode>,
}
impl ConvertQuoteRequest {
pub fn new(
base_ccy: impl Into<String>,
quote_ccy: impl Into<String>,
side: OrderSide,
rfq_sz: impl Into<String>,
rfq_sz_ccy: impl Into<String>,
) -> Self {
Self {
base_ccy: base_ccy.into(),
quote_ccy: quote_ccy.into(),
side,
rfq_sz: rfq_sz.into(),
rfq_sz_ccy: rfq_sz_ccy.into(),
cl_q_req_id: None,
tag: None,
convert_mode: None,
}
}
pub fn client_quote_request_id(mut self, id: impl Into<String>) -> Self {
self.cl_q_req_id = Some(id.into());
self
}
pub fn tag(mut self, tag: impl Into<String>) -> Self {
self.tag = Some(tag.into());
self
}
pub fn convert_mode(mut self, convert_mode: ConvertMode) -> Self {
self.convert_mode = Some(convert_mode);
self
}
}
impl ValidateRequest for ConvertQuoteRequest {
fn validate(&self) -> Result<(), RequestValidationError> {
non_empty("baseCcy", &self.base_ccy)?;
non_empty("quoteCcy", &self.quote_ccy)?;
validate_side(&self.side)?;
non_empty("rfqSz", &self.rfq_sz)?;
non_empty("rfqSzCcy", &self.rfq_sz_ccy)?;
validate_client_request_id("clQReqId", self.cl_q_req_id.as_deref())
}
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ConvertTradeRequest {
quote_id: String,
base_ccy: String,
quote_ccy: String,
side: OrderSide,
sz: String,
sz_ccy: String,
#[serde(skip_serializing_if = "Option::is_none")]
cl_t_req_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
tag: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
convert_mode: Option<ConvertMode>,
}
impl ConvertTradeRequest {
pub fn new(
quote_id: impl Into<String>,
base_ccy: impl Into<String>,
quote_ccy: impl Into<String>,
side: OrderSide,
sz: impl Into<String>,
sz_ccy: impl Into<String>,
) -> Self {
Self {
quote_id: quote_id.into(),
base_ccy: base_ccy.into(),
quote_ccy: quote_ccy.into(),
side,
sz: sz.into(),
sz_ccy: sz_ccy.into(),
cl_t_req_id: None,
tag: None,
convert_mode: None,
}
}
pub fn client_trade_request_id(mut self, id: impl Into<String>) -> Self {
self.cl_t_req_id = Some(id.into());
self
}
pub fn tag(mut self, tag: impl Into<String>) -> Self {
self.tag = Some(tag.into());
self
}
pub fn convert_mode(mut self, convert_mode: ConvertMode) -> Self {
self.convert_mode = Some(convert_mode);
self
}
}
impl ValidateRequest for ConvertTradeRequest {
fn validate(&self) -> Result<(), RequestValidationError> {
non_empty("quoteId", &self.quote_id)?;
non_empty("baseCcy", &self.base_ccy)?;
non_empty("quoteCcy", &self.quote_ccy)?;
validate_side(&self.side)?;
non_empty("sz", &self.sz)?;
non_empty("szCcy", &self.sz_ccy)?;
validate_client_request_id("clTReqId", self.cl_t_req_id.as_deref())
}
}
#[derive(Debug, Clone, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ConvertHistoryRequest {
#[serde(skip_serializing_if = "Option::is_none")]
cl_t_req_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
after: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
before: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
limit: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
tag: Option<String>,
}
impl ConvertHistoryRequest {
pub fn new() -> Self {
Self::default()
}
pub fn client_trade_request_id(mut self, id: impl Into<String>) -> Self {
self.cl_t_req_id = Some(id.into());
self
}
pub fn after(mut self, timestamp_ms: u64) -> Self {
self.after = Some(timestamp_ms.to_string());
self
}
pub fn before(mut self, timestamp_ms: u64) -> Self {
self.before = Some(timestamp_ms.to_string());
self
}
pub fn limit(mut self, limit: u8) -> Self {
self.limit = Some(limit.to_string());
self
}
pub fn tag(mut self, tag: impl Into<String>) -> Self {
self.tag = Some(tag.into());
self
}
}
impl ValidateRequest for ConvertHistoryRequest {
fn validate(&self) -> Result<(), RequestValidationError> {
validate_client_request_id("clTReqId", self.cl_t_req_id.as_deref())?;
match &self.limit {
Some(limit) => {
let parsed = limit
.parse::<u64>()
.expect("ConvertHistoryRequest::limit stores a u8 as decimal text");
range_u64("limit", parsed, 1, 100)
}
None => Ok(()),
}
}
}