switchboard_utils/exchanges/
huobi.rs1use crate::*;
2
3use futures_util::TryFutureExt;
4
5use serde::Deserialize;
6
7#[allow(dead_code)]
8#[derive(Debug, Deserialize, Clone)]
9struct HuobiMarketData {
10 pub ch: String,
11 pub status: String,
12 pub ts: i64,
13 pub tick: HuobiTickerInfo,
14}
15
16#[derive(Debug, Clone, Deserialize)]
17pub struct HuobiTickerInfo {
18 pub id: i64,
19 pub version: i64,
20 pub open: f64,
21 pub close: f64,
22 pub low: f64,
23 pub high: f64,
24 pub amount: f64,
25 pub vol: f64,
26 pub count: i64,
27 pub bid: (f64, f64),
28 pub ask: (f64, f64),
29}
30
31pub struct HuobiApi {}
32
33impl HuobiApi {
34 fn get_ticker_url(ticker: &str, url: Option<&str>) -> String {
36 format!(
37 "{}/market/detail/merged?symbol={}",
38 url.unwrap_or("https://api.huobi.pro"),
39 ticker
40 )
41 }
42
43 pub async fn fetch_ticker(ticker: &str, url: Option<&str>) -> Result<HuobiTickerInfo, SbError> {
44 let ticker_url = HuobiApi::get_ticker_url(ticker, url);
45
46 let response: HuobiMarketData = reqwest::get(&ticker_url)
47 .and_then(|r| r.json())
48 .await
49 .map_err(handle_reqwest_err)?;
50
51 Ok(response.tick)
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 const MOCK_HUOBI_RESPONSE: &str = r#"{"ch":"market.btcusdt.detail.merged","status":"ok","ts":1696450585149,"tick":{"id":330331957961,"version":330331957961,"open":27346.88,"close":27703.8,"low":27204.95,"high":27835.9,"amount":4105.804118401724,"vol":1.1280903302844201E8,"count":557808,"bid":[27699.26,1.218876],"ask":[27699.27,0.32722]}}"#;
60
61 #[tokio::test]
62 async fn test_huobi_api() {
63 let mut server = mockito::Server::new();
65 let server_url = server.url();
66
67 let _mock = server
69 .mock("GET", "/market/detail/merged?symbol=btcusdt")
70 .with_status(201)
71 .with_header("content-type", "application/json")
72 .with_body(MOCK_HUOBI_RESPONSE)
73 .create();
74
75 let _ticker = HuobiApi::fetch_ticker("btcusdt", Some(server_url.as_str()))
76 .await
77 .unwrap();
78 }
86}