use crate::client::RevolutXClient;
use crate::error::Result;
use crate::model::Data;
use crate::model::market_data::{Candle, LastTrades, OrderBook, Tickers};
use crate::transport::{RequestSpec, encode_component};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum CandleInterval {
OneMinute,
FiveMinutes,
FifteenMinutes,
ThirtyMinutes,
OneHour,
FourHours,
OneDay,
TwoDays,
FourDays,
OneWeek,
TwoWeeks,
FourWeeks,
}
impl CandleInterval {
pub const fn minutes(self) -> i32 {
match self {
CandleInterval::OneMinute => 1,
CandleInterval::FiveMinutes => 5,
CandleInterval::FifteenMinutes => 15,
CandleInterval::ThirtyMinutes => 30,
CandleInterval::OneHour => 60,
CandleInterval::FourHours => 240,
CandleInterval::OneDay => 1440,
CandleInterval::TwoDays => 2880,
CandleInterval::FourDays => 5760,
CandleInterval::OneWeek => 10080,
CandleInterval::TwoWeeks => 20160,
CandleInterval::FourWeeks => 40320,
}
}
}
#[derive(Debug, Clone, Default)]
pub struct CandlesQuery {
pub interval: Option<CandleInterval>,
pub since: Option<i64>,
pub until: Option<i64>,
}
impl CandlesQuery {
fn to_query(&self) -> Vec<(String, String)> {
let mut query = Vec::new();
if let Some(interval) = self.interval {
query.push(("interval".into(), interval.minutes().to_string()));
}
if let Some(since) = self.since {
query.push(("since".into(), since.to_string()));
}
if let Some(until) = self.until {
query.push(("until".into(), until.to_string()));
}
query
}
}
pub struct MarketDataApi<'a> {
client: &'a RevolutXClient,
}
impl<'a> MarketDataApi<'a> {
pub(crate) fn new(client: &'a RevolutXClient) -> Self {
Self { client }
}
pub async fn order_book(&self, symbol: &str) -> Result<OrderBook> {
let path = format!("/order-book/{}", encode_component(symbol));
self.client
.transport()
.send_json(RequestSpec::get(path))
.await
}
pub async fn order_book_with_limit(&self, symbol: &str, limit: u32) -> Result<OrderBook> {
let path = format!("/order-book/{}", encode_component(symbol));
self.client
.transport()
.send_json(RequestSpec::get(path).with_query(vec![("limit".into(), limit.to_string())]))
.await
}
pub async fn public_order_book(&self, symbol: &str) -> Result<OrderBook> {
let path = format!("/public/order-book/{}", encode_component(symbol));
self.client
.transport()
.send_json(RequestSpec::get(path).public())
.await
}
pub async fn candles(&self, symbol: &str, query: &CandlesQuery) -> Result<Vec<Candle>> {
let path = format!("/candles/{}", encode_component(symbol));
let data: Data<Vec<Candle>> = self
.client
.transport()
.send_json(RequestSpec::get(path).with_query(query.to_query()))
.await?;
Ok(data.data)
}
pub async fn tickers(&self) -> Result<Tickers> {
self.client
.transport()
.send_json(RequestSpec::get("/tickers"))
.await
}
pub async fn tickers_for<S: AsRef<str>>(&self, symbols: &[S]) -> Result<Tickers> {
let query = symbols
.iter()
.map(|s| ("symbols".to_string(), s.as_ref().to_string()))
.collect();
self.client
.transport()
.send_json(RequestSpec::get("/tickers").with_query(query))
.await
}
pub async fn last_trades(&self) -> Result<LastTrades> {
self.client
.transport()
.send_json(RequestSpec::get("/public/last-trades").public())
.await
}
}