bybit_rust_api/ws/public/
kline.rs1use serde::Deserialize;
12
13#[derive(Debug, Clone, Deserialize)]
15pub struct KlineData {
16 #[serde(rename = "start")]
18 #[serde(default)]
19 pub start: Option<i64>,
20 #[serde(rename = "end")]
22 #[serde(default)]
23 pub end: Option<i64>,
24 #[serde(rename = "interval")]
26 #[serde(default)]
27 pub interval: Option<String>,
28 #[serde(rename = "open")]
30 #[serde(default)]
31 pub open: Option<String>,
32 #[serde(rename = "close")]
34 #[serde(default)]
35 pub close: Option<String>,
36 #[serde(rename = "high")]
38 #[serde(default)]
39 pub high: Option<String>,
40 #[serde(rename = "low")]
42 #[serde(default)]
43 pub low: Option<String>,
44 #[serde(rename = "volume")]
46 #[serde(default)]
47 pub volume: Option<String>,
48 #[serde(rename = "turnover")]
50 #[serde(default)]
51 pub turnover: Option<String>,
52 #[serde(rename = "confirm")]
54 #[serde(default)]
55 pub confirm: Option<bool>,
56 #[serde(rename = "timestamp")]
58 #[serde(default)]
59 pub timestamp: Option<i64>,
60}
61
62pub struct KlineStream;
66
67impl KlineStream {
68 pub fn parse(data: &serde_json::Value) -> serde_json::Result<Vec<KlineData>> {
70 serde_json::from_value(data.clone())
71 }
72
73 pub fn parse_single(data: &serde_json::Value) -> serde_json::Result<KlineData> {
75 let mut klines: Vec<KlineData> = serde_json::from_value(data.clone())?;
76 klines
77 .pop()
78 .ok_or_else(|| serde::de::Error::custom("empty kline array"))
79 }
80
81 pub fn matches_topic(topic: &str) -> bool {
83 topic.starts_with("kline.")
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
92 fn test_parse_kline() {
93 let json = serde_json::json!([{
94 "start": 1672828800000_i64,
95 "end": 1672832400000_i64,
96 "interval": "60",
97 "open": "50000.00",
98 "close": "50100.00",
99 "high": "50200.00",
100 "low": "49900.00",
101 "volume": "150.5",
102 "turnover": "7525000.00",
103 "confirm": false,
104 "timestamp": 1672832100000_i64
105 }]);
106
107 let kline = KlineStream::parse_single(&json).unwrap();
108 assert_eq!(kline.open.as_deref(), Some("50000.00"));
109 assert_eq!(kline.close.as_deref(), Some("50100.00"));
110 assert_eq!(kline.confirm, Some(false));
111 }
112
113 #[test]
114 fn test_matches_topic() {
115 assert!(KlineStream::matches_topic("kline.1.BTCUSDT"));
116 assert!(KlineStream::matches_topic("kline.D.ETHUSDT"));
117 assert!(!KlineStream::matches_topic("tickers.BTCUSDT"));
118 }
119}