mirror of
https://github.com/floor-licker/polyfill-rs.git
synced 2026-08-22 17:08:07 +00:00
feat(clob): support all order types for order posting
This commit is contained in:
+90
-36
@@ -1079,14 +1079,28 @@ impl ClobClient {
|
|||||||
Ok(response.json::<Value>().await?)
|
Ok(response.json::<Value>().await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create and post an order in one call
|
/// Create and post an order in one call with an explicit order type
|
||||||
pub async fn create_and_post_order(&self, order_args: &OrderArgs) -> Result<Value> {
|
pub async fn create_and_post_order_with_type(
|
||||||
|
&self,
|
||||||
|
order_args: &OrderArgs,
|
||||||
|
order_type: OrderType,
|
||||||
|
) -> Result<Value> {
|
||||||
let order = self.create_order(order_args, None, None, None).await?;
|
let order = self.create_order(order_args, None, None, None).await?;
|
||||||
self.post_order(order, OrderType::GTC).await
|
self.post_order(order, order_type).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create and post multiple orders in one call
|
/// Create and post an order in one call (defaults to GTC)
|
||||||
pub async fn create_and_post_orders(&self, order_args: &[OrderArgs]) -> Result<Value> {
|
pub async fn create_and_post_order(&self, order_args: &OrderArgs) -> Result<Value> {
|
||||||
|
self.create_and_post_order_with_type(order_args, OrderType::GTC)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create and post multiple orders in one call with an explicit order type
|
||||||
|
pub async fn create_and_post_orders_with_type(
|
||||||
|
&self,
|
||||||
|
order_args: &[OrderArgs],
|
||||||
|
order_type: OrderType,
|
||||||
|
) -> Result<Value> {
|
||||||
if order_args.is_empty() {
|
if order_args.is_empty() {
|
||||||
return Err(PolyfillError::validation("order_args cannot be empty"));
|
return Err(PolyfillError::validation("order_args cannot be empty"));
|
||||||
}
|
}
|
||||||
@@ -1096,7 +1110,13 @@ impl ClobClient {
|
|||||||
orders.push(self.create_order(args, None, None, None).await?);
|
orders.push(self.create_order(args, None, None, None).await?);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.post_orders(orders, OrderType::GTC).await
|
self.post_orders(orders, order_type).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create and post multiple orders in one call (defaults to GTC)
|
||||||
|
pub async fn create_and_post_orders(&self, order_args: &[OrderArgs]) -> Result<Value> {
|
||||||
|
self.create_and_post_orders_with_type(order_args, OrderType::GTC)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cancel an order
|
/// Cancel an order
|
||||||
@@ -2394,6 +2414,24 @@ mod tests {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sample_signed_order() -> crate::types::SignedOrderRequest {
|
||||||
|
crate::types::SignedOrderRequest {
|
||||||
|
salt: 1,
|
||||||
|
maker: "0x0000000000000000000000000000000000000000".to_string(),
|
||||||
|
signer: "0x0000000000000000000000000000000000000000".to_string(),
|
||||||
|
taker: "0x0000000000000000000000000000000000000000".to_string(),
|
||||||
|
token_id: "123".to_string(),
|
||||||
|
maker_amount: "100".to_string(),
|
||||||
|
taker_amount: "50".to_string(),
|
||||||
|
expiration: "0".to_string(),
|
||||||
|
nonce: "0".to_string(),
|
||||||
|
fee_rate_bps: "0".to_string(),
|
||||||
|
side: "BUY".to_string(),
|
||||||
|
signature_type: 0,
|
||||||
|
signature: "0xdeadbeef".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_client_creation() {
|
async fn test_client_creation() {
|
||||||
let client = create_test_client("https://test.example.com");
|
let client = create_test_client("https://test.example.com");
|
||||||
@@ -2947,21 +2985,7 @@ mod tests {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
let client = create_test_client_with_l2_auth(&server.url());
|
let client = create_test_client_with_l2_auth(&server.url());
|
||||||
let signed_order = crate::types::SignedOrderRequest {
|
let signed_order = sample_signed_order();
|
||||||
salt: 1,
|
|
||||||
maker: "0x0000000000000000000000000000000000000000".to_string(),
|
|
||||||
signer: "0x0000000000000000000000000000000000000000".to_string(),
|
|
||||||
taker: "0x0000000000000000000000000000000000000000".to_string(),
|
|
||||||
token_id: "123".to_string(),
|
|
||||||
maker_amount: "100".to_string(),
|
|
||||||
taker_amount: "50".to_string(),
|
|
||||||
expiration: "0".to_string(),
|
|
||||||
nonce: "0".to_string(),
|
|
||||||
fee_rate_bps: "0".to_string(),
|
|
||||||
side: "BUY".to_string(),
|
|
||||||
signature_type: 0,
|
|
||||||
signature: "0xdeadbeef".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = client
|
let result = client
|
||||||
.post_orders(
|
.post_orders(
|
||||||
@@ -2986,27 +3010,57 @@ mod tests {
|
|||||||
async fn test_post_orders_batch_too_many_validation() {
|
async fn test_post_orders_batch_too_many_validation() {
|
||||||
let client = create_test_client_with_l2_auth("https://test.example.com");
|
let client = create_test_client_with_l2_auth("https://test.example.com");
|
||||||
let orders = (0..16)
|
let orders = (0..16)
|
||||||
.map(|_| crate::types::SignedOrderRequest {
|
.map(|_| sample_signed_order())
|
||||||
salt: 1,
|
|
||||||
maker: "0x0000000000000000000000000000000000000000".to_string(),
|
|
||||||
signer: "0x0000000000000000000000000000000000000000".to_string(),
|
|
||||||
taker: "0x0000000000000000000000000000000000000000".to_string(),
|
|
||||||
token_id: "123".to_string(),
|
|
||||||
maker_amount: "100".to_string(),
|
|
||||||
taker_amount: "50".to_string(),
|
|
||||||
expiration: "0".to_string(),
|
|
||||||
nonce: "0".to_string(),
|
|
||||||
fee_rate_bps: "0".to_string(),
|
|
||||||
side: "BUY".to_string(),
|
|
||||||
signature_type: 0,
|
|
||||||
signature: "0xdeadbeef".to_string(),
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let result = client.post_orders(orders, crate::types::OrderType::GTC).await;
|
let result = client.post_orders(orders, crate::types::OrderType::GTC).await;
|
||||||
assert!(matches!(result, Err(PolyfillError::Validation { .. })));
|
assert!(matches!(result, Err(PolyfillError::Validation { .. })));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_post_order_supports_fak() {
|
||||||
|
let mut server = Server::new_async().await;
|
||||||
|
let mock = server
|
||||||
|
.mock("POST", "/order")
|
||||||
|
.match_body(Matcher::Regex(r#""orderType":"FAK""#.to_string()))
|
||||||
|
.with_status(200)
|
||||||
|
.with_header("content-type", "application/json")
|
||||||
|
.with_body(r#"{"success":true,"orderID":"a"}"#)
|
||||||
|
.create_async()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let client = create_test_client_with_l2_auth(&server.url());
|
||||||
|
let result = client
|
||||||
|
.post_order(sample_signed_order(), crate::types::OrderType::FAK)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
mock.assert_async().await;
|
||||||
|
assert!(result.is_ok());
|
||||||
|
assert_eq!(result.unwrap()["success"], true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn test_post_orders_supports_fak() {
|
||||||
|
let mut server = Server::new_async().await;
|
||||||
|
let mock = server
|
||||||
|
.mock("POST", "/orders")
|
||||||
|
.match_body(Matcher::Regex(r#""orderType":"FAK""#.to_string()))
|
||||||
|
.with_status(200)
|
||||||
|
.with_header("content-type", "application/json")
|
||||||
|
.with_body(r#"[{"success":true,"orderID":"a"}]"#)
|
||||||
|
.create_async()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let client = create_test_client_with_l2_auth(&server.url());
|
||||||
|
let result = client
|
||||||
|
.post_orders(vec![sample_signed_order()], crate::types::OrderType::FAK)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
mock.assert_async().await;
|
||||||
|
assert!(result.is_ok());
|
||||||
|
assert_eq!(result.unwrap()[0]["success"], true);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn test_create_or_derive_api_key() {
|
async fn test_create_or_derive_api_key() {
|
||||||
let mut server = Server::new_async().await;
|
let mut server = Server::new_async().await;
|
||||||
|
|||||||
@@ -214,6 +214,7 @@ pub enum OrderType {
|
|||||||
#[default]
|
#[default]
|
||||||
GTC,
|
GTC,
|
||||||
FOK,
|
FOK,
|
||||||
|
FAK,
|
||||||
GTD,
|
GTD,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +223,7 @@ impl OrderType {
|
|||||||
match self {
|
match self {
|
||||||
OrderType::GTC => "GTC",
|
OrderType::GTC => "GTC",
|
||||||
OrderType::FOK => "FOK",
|
OrderType::FOK => "FOK",
|
||||||
|
OrderType::FAK => "FAK",
|
||||||
OrderType::GTD => "GTD",
|
OrderType::GTD => "GTD",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1657,3 +1659,19 @@ pub type Result<T> = std::result::Result<T, crate::errors::PolyfillError>;
|
|||||||
pub type ApiCreds = ApiCredentials;
|
pub type ApiCreds = ApiCredentials;
|
||||||
pub type CreateOrderOptions = OrderOptions;
|
pub type CreateOrderOptions = OrderOptions;
|
||||||
pub type OrderArgs = OrderRequest;
|
pub type OrderArgs = OrderRequest;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::OrderType;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_order_type_fak_serde_and_string() {
|
||||||
|
assert_eq!(OrderType::FAK.as_str(), "FAK");
|
||||||
|
|
||||||
|
let json = serde_json::to_string(&OrderType::FAK).unwrap();
|
||||||
|
assert_eq!(json, "\"FAK\"");
|
||||||
|
|
||||||
|
let parsed: OrderType = serde_json::from_str("\"FAK\"").unwrap();
|
||||||
|
assert_eq!(parsed, OrderType::FAK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user