openlimits_binance/client/
market.rs

1use serde_json::json;
2use serde_json::Value;
3use super::BaseClient;
4use crate::model::{BookTickers, KlineParams, KlineSummaries, KlineSummary, OrderBook, PriceStats, Prices, SymbolPrice, Ticker, MarketPair};
5pub use openlimits_exchange::OpenLimitsError;
6use rust_decimal::prelude::Decimal;
7use super::shared::Result;
8
9// Market Data endpoints
10impl BaseClient {
11    // Order book (Default 100; max 100)
12    pub async fn get_depth<I, S>(&self, symbol: S, limit: I) -> Result<OrderBook>
13    where
14        I: Into<Option<u64>>,
15        S: Into<MarketPair>
16    {
17        let symbol = format!("{}", symbol.into().0);
18        let limit = limit.into().unwrap_or(100);
19        let params = json! {{"symbol": symbol, "limit": limit}};
20
21        Ok(self.transport.get("/api/v3/depth", Some(&params)).await?)
22    }
23
24    // Latest price for ALL symbols.
25    pub async fn get_all_prices(&self) -> Result<Prices> {
26        Ok(self
27            .transport
28            .get::<_, ()>("/api/v3/ticker/price", None)
29            .await?)
30    }
31
32    // Latest price for ONE symbol.
33    pub async fn get_price<S: Into<MarketPair>>(&self, symbol: S) -> Result<SymbolPrice> {
34        let symbol = format!("{}", symbol.into().0);
35        let params = json! {{"symbol": symbol}};
36
37        let price = self
38            .transport
39            .get("/api/v3/ticker/price", Some(&params))
40            .await?;
41
42        Ok(price)
43    }
44
45    // Symbols order book ticker
46    // -> Best price/qty on the order book for ALL symbols.
47    pub async fn get_all_book_tickers(&self) -> Result<BookTickers> {
48        Ok(self
49            .transport
50            .get::<_, ()>("/api/v3/ticker/bookTicker", None)
51            .await?)
52    }
53
54    // -> Best price/qty on the order book for ONE symbol
55    pub async fn get_book_ticker(&self, symbol: &str) -> Result<Ticker> {
56        let symbol = symbol.to_string();
57        self.get_all_book_tickers().await.and_then(
58            move |BookTickers::AllBookTickers(book_tickers)| {
59                Ok(book_tickers
60                    .into_iter()
61                    .find(|obj| obj.symbol == symbol)
62                    .ok_or(OpenLimitsError::SymbolNotFound())?)
63            },
64        )
65    }
66
67    // 24hr ticker price change statistics
68    pub async fn get_24h_price_stats(&self, symbol: &str) -> Result<PriceStats> {
69        let params = json! {{"symbol": symbol}};
70        Ok(self
71            .transport
72            .get("/api/v3/ticker/24hr", Some(&params))
73            .await?)
74    }
75
76    // Returns up to 'limit' klines for given symbol and interval ("1m", "5m", ...)
77    // https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#klinecandlestick-data
78    pub async fn get_klines(&self, params: &KlineParams) -> Result<KlineSummaries> {
79        self.transport
80            .get("/api/v3/klines", Some(params))
81            .await
82            .map(|data: Vec<Vec<Value>>| {
83                KlineSummaries::AllKlineSummaries(
84                    data.iter()
85                        .map(|row| KlineSummary {
86                            open_time: to_i64(&row[0]),
87                            open: to_decimal(&row[1]),
88                            high: to_decimal(&row[2]),
89                            low: to_decimal(&row[3]),
90                            close: to_decimal(&row[4]),
91                            volume: to_decimal(&row[5]),
92                            close_time: to_i64(&row[6]),
93                            quote_asset_volume: to_decimal(&row[7]),
94                            number_of_trades: to_i64(&row[8]),
95                            taker_buy_base_asset_volume: to_decimal(&row[9]),
96                            taker_buy_quote_asset_volume: to_decimal(&row[10]),
97                        })
98                        .collect(),
99                )
100            })
101    }
102
103    // 24hr ticker price change statistics
104    pub async fn get_24h_price_stats_all(&self) -> Result<Vec<PriceStats>> {
105        Ok(self
106            .transport
107            .get::<_, ()>("/api/v3/ticker/24hr", None)
108            .await?)
109    }
110}
111
112fn to_i64(v: &Value) -> i64 {
113    v.as_i64().expect("Couldn't get JSON Value as i64.")
114}
115
116fn to_decimal(v: &Value) -> Decimal {
117    v.as_str()
118        .expect("Couldn't get JSON Value as str.")
119        .parse()
120        .expect("Couldn't parse str as Decimal.")
121}