use serde::Deserialize;
#[derive(Debug, Clone, Deserialize)]
pub struct PublicTrade {
#[serde(rename = "i")]
#[serde(default)]
pub trade_id: Option<String>,
#[serde(rename = "T")]
#[serde(default)]
pub timestamp: Option<i64>,
#[serde(rename = "s")]
#[serde(default)]
pub symbol: Option<String>,
#[serde(rename = "S")]
#[serde(default)]
pub side: Option<String>,
#[serde(rename = "p")]
#[serde(default)]
pub price: Option<String>,
#[serde(rename = "v")]
#[serde(default)]
pub size: Option<String>,
#[serde(rename = "L")]
#[serde(default)]
pub direction: Option<String>,
#[serde(rename = "BT")]
#[serde(default)]
pub block_trade: Option<bool>,
}
pub struct TradeStream;
impl TradeStream {
pub fn parse(data: &serde_json::Value) -> serde_json::Result<Vec<PublicTrade>> {
serde_json::from_value(data.clone())
}
pub fn matches_topic(topic: &str) -> bool {
topic.starts_with("publicTrade.")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_trades() {
let json = serde_json::json!([
{
"i": "123456",
"T": 1672828800000_i64,
"s": "BTCUSDT",
"S": "Buy",
"p": "50000.00",
"v": "0.01",
"L": "PlusTick",
"BT": false
}
]);
let trades = TradeStream::parse(&json).unwrap();
assert_eq!(trades.len(), 1);
assert_eq!(trades[0].side.as_deref(), Some("Buy"));
assert_eq!(trades[0].price.as_deref(), Some("50000.00"));
}
#[test]
fn test_matches_topic() {
assert!(TradeStream::matches_topic("publicTrade.BTCUSDT"));
assert!(!TradeStream::matches_topic("orderbook.1.BTCUSDT"));
}
}