use super::wire::{TradeResponse, WsTrade};
use super::Trade;
use chrono::TimeZone;
use rust_decimal::Decimal;
use std::str::FromStr;
impl From<TradeResponse> for Trade {
fn from(t: TradeResponse) -> Self {
Self {
orderbook_id: t.orderbook_id,
trade_id: t.trade_id,
cursor_id: Some(t.id),
timestamp: chrono::Utc
.timestamp_millis_opt(t.executed_at)
.single()
.unwrap_or_else(chrono::Utc::now),
price: Decimal::from_str(&t.price).unwrap_or_default(),
size: Decimal::from_str(&t.size).unwrap_or_default(),
side: t.side,
sequence: 0,
}
}
}
impl From<WsTrade> for Trade {
fn from(t: WsTrade) -> Self {
Self {
orderbook_id: t.orderbook_id,
trade_id: t.trade_id,
cursor_id: None,
timestamp: t.timestamp,
price: t.price,
size: t.size,
side: t.side,
sequence: t.sequence,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::shared::{OrderBookId, Side};
use chrono::Utc;
fn sample_trade_response() -> TradeResponse {
TradeResponse {
id: 456,
trade_id: "taker_hash_maker_hash".to_string(),
orderbook_id: OrderBookId::from("ob_123"),
taker_pubkey: "taker123".to_string(),
maker_pubkey: "maker456".to_string(),
side: Side::Bid,
size: "10.000000".to_string(),
price: "5.000000".to_string(),
taker_fee: Some("0.003250".to_string()),
maker_fee: None,
executed_at: 1740076800000,
}
}
fn sample_ws_trade() -> WsTrade {
WsTrade {
orderbook_id: OrderBookId::from("ob_789"),
trade_id: "ws_trade_999".to_string(),
timestamp: Utc::now(),
price: Decimal::new(75, 1),
size: Decimal::new(5, 0),
side: Side::Ask,
sequence: 1,
}
}
#[test]
fn test_trade_response_conversion() {
let resp = sample_trade_response();
let trade: Trade = resp.into();
assert_eq!(trade.orderbook_id.as_str(), "ob_123");
assert_eq!(trade.trade_id, "taker_hash_maker_hash");
assert_eq!(trade.cursor_id, Some(456));
assert_eq!(trade.price, Decimal::from_str("5.000000").unwrap());
assert_eq!(trade.size, Decimal::from_str("10.000000").unwrap());
assert_eq!(trade.side, Side::Bid);
assert_eq!(trade.sequence, 0);
}
#[test]
fn test_ws_trade_conversion() {
let ws = sample_ws_trade();
let trade: Trade = ws.into();
assert_eq!(trade.orderbook_id.as_str(), "ob_789");
assert_eq!(trade.trade_id, "ws_trade_999");
assert_eq!(trade.cursor_id, None);
assert_eq!(trade.price, Decimal::new(75, 1));
assert_eq!(trade.size, Decimal::new(5, 0));
assert_eq!(trade.side, Side::Ask);
assert_eq!(trade.sequence, 1);
}
}