Skip to content

Commit d7ac1ba

Browse files
committed
feat: Migrate price and size fields from String to Decimal with serde(with = "rust_decimal::serde::str") for accurate serialization.
1 parent 51ab35a commit d7ac1ba

File tree

6 files changed

+42
-16
lines changed

6 files changed

+42
-16
lines changed

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ hex = "0.4"
3939
tracing = "0.1"
4040
tokio-tungstenite = { version = "0.26", features = ["rustls-tls-webpki-roots"] }
4141
futures-util = "0.3"
42-
rust_decimal = "1.37"
42+
rust_decimal = { version = "1.37", features = ["serde-with-str"] }
4343

4444
[profile.release]
4545
opt-level = 3

polyoxide-clob/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,4 @@ tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
4949
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
5050
futures-util = { workspace = true }
5151
dotenvy = "0.15"
52+
rust_decimal_macros = "1.37"

polyoxide-clob/src/api/markets.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use polyoxide_core::QueryBuilder;
22
use reqwest::Client;
3+
use rust_decimal::Decimal;
34
use serde::{Deserialize, Serialize};
45
use url::Url;
56

@@ -167,8 +168,10 @@ pub struct MarketToken {
167168
/// Order book level (price and size)
168169
#[derive(Debug, Clone, Serialize, Deserialize)]
169170
pub struct OrderLevel {
170-
pub price: String,
171-
pub size: String,
171+
#[serde(with = "rust_decimal::serde::str")]
172+
pub price: Decimal,
173+
#[serde(with = "rust_decimal::serde::str")]
174+
pub size: Decimal,
172175
}
173176

174177
/// Order book data

polyoxide-clob/src/utils.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rand::Rng;
2+
use rust_decimal::prelude::ToPrimitive;
23

34
use crate::{
45
api::markets::OrderLevel,
@@ -96,8 +97,8 @@ pub fn calculate_market_price(levels: &[OrderLevel], amount: f64, side: OrderSid
9697
let mut sum = 0.0;
9798

9899
for level in levels {
99-
let p = level.price.parse::<f64>().ok()?;
100-
let s = level.size.parse::<f64>().ok()?;
100+
let p = level.price.to_f64()?;
101+
let s = level.size.to_f64()?;
101102

102103
match side {
103104
OrderSide::Buy => {
@@ -113,7 +114,7 @@ pub fn calculate_market_price(levels: &[OrderLevel], amount: f64, side: OrderSid
113114
}
114115
}
115116

116-
levels.last().and_then(|l| l.price.parse::<f64>().ok())
117+
levels.last().and_then(|l| l.price.to_f64())
117118
}
118119

119120
/// Convert f64 to raw integer string by multiplying by 10^decimals
@@ -207,10 +208,11 @@ mod tests {
207208

208209
#[test]
209210
fn test_calculate_market_price_buy_simple() {
211+
use rust_decimal_macros::dec;
210212
// Should find match at 0.50
211213
let levels = vec![OrderLevel {
212-
price: "0.50".to_string(),
213-
size: "1000".to_string(),
214+
price: dec!(0.50),
215+
size: dec!(1000),
214216
}];
215217
let price = calculate_market_price(&levels, 100.0, OrderSide::Buy);
216218
assert_eq!(price, Some(0.50));

polyoxide-clob/src/ws/market.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22
//!
33
//! The market channel provides real-time order book and price updates.
44
5+
use rust_decimal::Decimal;
56
use serde::{Deserialize, Serialize};
67

78
/// Order summary in the order book
89
#[derive(Debug, Clone, Serialize, Deserialize)]
910
pub struct OrderSummary {
1011
/// Price level
11-
pub price: String,
12+
#[serde(with = "rust_decimal::serde::str")]
13+
pub price: Decimal,
1214
/// Size at this price level
13-
pub size: String,
15+
#[serde(with = "rust_decimal::serde::str")]
16+
pub size: Decimal,
1417
}
1518

1619
/// Book message - full order book snapshot
@@ -40,17 +43,21 @@ pub struct PriceChange {
4043
/// Asset ID (token ID)
4144
pub asset_id: String,
4245
/// Price level
43-
pub price: String,
46+
#[serde(with = "rust_decimal::serde::str")]
47+
pub price: Decimal,
4448
/// Size at this price level
45-
pub size: String,
49+
#[serde(with = "rust_decimal::serde::str")]
50+
pub size: Decimal,
4651
/// Order side (BUY or SELL)
4752
pub side: String,
4853
/// Order book hash
4954
pub hash: String,
5055
/// Best bid price
51-
pub best_bid: Option<String>,
56+
#[serde(default, with = "rust_decimal::serde::str_option")]
57+
pub best_bid: Option<Decimal>,
5258
/// Best ask price
53-
pub best_ask: Option<String>,
59+
#[serde(default, with = "rust_decimal::serde::str_option")]
60+
pub best_ask: Option<Decimal>,
5461
}
5562

5663
/// Price change message - incremental order book update
@@ -95,11 +102,13 @@ pub struct LastTradePriceMessage {
95102
/// Market condition ID
96103
pub market: String,
97104
/// Trade price
98-
pub price: String,
105+
#[serde(with = "rust_decimal::serde::str")]
106+
pub price: Decimal,
99107
/// Trade side (BUY or SELL)
100108
pub side: String,
101109
/// Trade size
102-
pub size: String,
110+
#[serde(with = "rust_decimal::serde::str")]
111+
pub size: Decimal,
103112
/// Fee rate
104113
pub fee_rate_bps: Option<String>,
105114
/// Timestamp in milliseconds (as string)

0 commit comments

Comments
 (0)