1use crate::client::BybitClient;
19use crate::error::Result;
20use crate::types::{InstrumentList, OrderBook, ServerTime, TickerList};
21
22impl BybitClient {
23 pub async fn get_server_time(&self) -> Result<ServerTime> {
24 self.get("/v5/market/time", None).await
25 }
26
27 pub async fn get_kline(
28 &self,
29 category: &str,
30 symbol: &str,
31 interval: &str,
32 start: Option<i64>,
33 end: Option<i64>,
34 ) -> Result<serde_json::Value> {
35 let mut params: Vec<(String, String)> = vec![
36 ("category".to_string(), category.to_string()),
37 ("symbol".to_string(), symbol.to_string()),
38 ("interval".to_string(), interval.to_string()),
39 ];
40
41 if let Some(s) = start {
42 params.push(("start".to_string(), s.to_string()));
43 }
44
45 if let Some(e) = end {
46 params.push(("end".to_string(), e.to_string()));
47 }
48
49 let query: Vec<(&str, &str)> = params
50 .iter()
51 .map(|(k, v)| (k.as_str(), v.as_str()))
52 .collect();
53
54 self.get("/v5/market/kline", Some(query)).await
55 }
56
57 pub async fn get_tickers(&self, category: &str) -> Result<TickerList> {
58 let query = vec![("category", category)];
59 self.get("/v5/market/tickers", Some(query)).await
60 }
61
62 pub async fn get_orderbook(
63 &self,
64 category: &str,
65 symbol: &str,
66 limit: u32,
67 ) -> Result<OrderBook> {
68 let limit_str = limit.to_string();
69 let query = vec![
70 ("category", category),
71 ("symbol", symbol),
72 ("limit", limit_str.as_str()),
73 ];
74 self.get("/v5/market/orderbook", Some(query)).await
75 }
76
77 pub async fn get_instruments(&self, category: &str) -> Result<InstrumentList> {
78 let query = vec![("category", category)];
79 self.get("/v5/market/instruments-info", Some(query)).await
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 #[test]
86 fn test_get_kline_basic_params() {
87 let params: Vec<(String, String)> = vec![
88 ("category".to_string(), "linear".to_string()),
89 ("symbol".to_string(), "BTCUSDT".to_string()),
90 ("interval".to_string(), "15".to_string()),
91 ];
92
93 let query: Vec<(&str, &str)> = params
94 .iter()
95 .map(|(k, v)| (k.as_str(), v.as_str()))
96 .collect();
97
98 assert_eq!(query.len(), 3);
99 assert!(query.contains(&("category", "linear")));
100 assert!(query.contains(&("symbol", "BTCUSDT")));
101 assert!(query.contains(&("interval", "15")));
102 }
103
104 #[test]
105 fn test_get_kline_with_start_only() {
106 let mut params: Vec<(String, String)> = vec![
107 ("category".to_string(), "linear".to_string()),
108 ("symbol".to_string(), "BTCUSDT".to_string()),
109 ("interval".to_string(), "15".to_string()),
110 ];
111
112 let start = 1670601600000_i64;
113 params.push(("start".to_string(), start.to_string()));
114
115 let query: Vec<(&str, &str)> = params
116 .iter()
117 .map(|(k, v)| (k.as_str(), v.as_str()))
118 .collect();
119
120 assert_eq!(query.len(), 4);
121 assert!(query.contains(&("category", "linear")));
122 assert!(query.contains(&("symbol", "BTCUSDT")));
123 assert!(query.contains(&("interval", "15")));
124 assert!(query.contains(&("start", "1670601600000")));
125 }
126
127 #[test]
128 fn test_get_kline_with_end_only() {
129 let mut params: Vec<(String, String)> = vec![
130 ("category".to_string(), "linear".to_string()),
131 ("symbol".to_string(), "BTCUSDT".to_string()),
132 ("interval".to_string(), "15".to_string()),
133 ];
134
135 let end = 1670608800000_i64;
136 params.push(("end".to_string(), end.to_string()));
137
138 let query: Vec<(&str, &str)> = params
139 .iter()
140 .map(|(k, v)| (k.as_str(), v.as_str()))
141 .collect();
142
143 assert_eq!(query.len(), 4);
144 assert!(query.contains(&("category", "linear")));
145 assert!(query.contains(&("symbol", "BTCUSDT")));
146 assert!(query.contains(&("interval", "15")));
147 assert!(query.contains(&("end", "1670608800000")));
148 }
149
150 #[test]
151 fn test_get_kline_with_both_start_and_end() {
152 let mut params: Vec<(String, String)> = vec![
153 ("category".to_string(), "linear".to_string()),
154 ("symbol".to_string(), "BTCUSDT".to_string()),
155 ("interval".to_string(), "15".to_string()),
156 ];
157
158 let start = 1670601600000_i64;
159 let end = 1670608800000_i64;
160
161 params.push(("start".to_string(), start.to_string()));
162 params.push(("end".to_string(), end.to_string()));
163
164 let query: Vec<(&str, &str)> = params
165 .iter()
166 .map(|(k, v)| (k.as_str(), v.as_str()))
167 .collect();
168
169 assert_eq!(query.len(), 5);
170 assert!(query.contains(&("category", "linear")));
171 assert!(query.contains(&("symbol", "BTCUSDT")));
172 assert!(query.contains(&("interval", "15")));
173 assert!(query.contains(&("start", "1670601600000")));
174 assert!(query.contains(&("end", "1670608800000")));
175 }
176}