xapi 0.2.4

The xStation5 API Rust library
Documentation
use crate::connection::Connection;
use crate::data::*;
use crate::error::Error;

use serde::de::DeserializeOwned;
use serde::Deserialize;

#[derive(Debug, Clone)]
pub struct Stream {
    conn: Connection,
    stream_session_id: String,
}

impl Stream {
    pub async fn connect(url: &str, stream_session_id: String) -> Result<Stream, Error> {
        Ok(Stream { conn: Connection::connect(url).await?, stream_session_id })
    }

    pub async fn skip_delay(&self) {
        self.conn.skip_delay().await;
    }

    pub async fn get_balance(&self) -> Result<(), Error> {
        self.conn
            .request(&format!(
                "{{\"command\":\"getBalance\",\"streamSessionId\":\"{}\"}}",
                self.stream_session_id
            ))
            .await
    }

    pub async fn stop_balance(&self) -> Result<(), Error> {
        self.conn.request("{\"command\":\"stopBalance\"}").await
    }

    pub async fn get_candles(&self, symbol: &str) -> Result<(), Error> {
        self.conn
            .request(&format!(
                "{{\"command\":\"getCandles\",\"streamSessionId\":\"{}\",\"symbol\":\"{symbol}\"}}",
                self.stream_session_id
            ))
            .await
    }

    pub async fn stop_candles(&self, symbol: &str) -> Result<(), Error> {
        self.conn
            .request(&format!("{{\"command\":\"stopCandles\",\"symbol\":\"{symbol}\"}}"))
            .await
    }

    pub async fn get_keep_alive(&self) -> Result<(), Error> {
        self.conn
            .request(&format!(
                "{{\"command\":\"getKeepAlive\",\"streamSessionId\":\"{}\"}}",
                self.stream_session_id
            ))
            .await
    }

    pub async fn stop_keep_alive(&self) -> Result<(), Error> {
        self.conn.request("{\"command\":\"stopKeepAlive\"}").await
    }

    pub async fn get_news(&self) -> Result<(), Error> {
        self.conn
            .request(&format!(
                "{{\"command\":\"getNews\",\"streamSessionId\":\"{}\"}}",
                self.stream_session_id
            ))
            .await
    }

    pub async fn stop_news(&self) -> Result<(), Error> {
        self.conn.request("{\"command\":\"stopNews\"}").await
    }

    pub async fn get_profits(&self) -> Result<(), Error> {
        self.conn
            .request(&format!(
                "{{\"command\":\"getProfits\",\"streamSessionId\":\"{}\"}}",
                self.stream_session_id
            ))
            .await
    }

    pub async fn stop_profits(&self) -> Result<(), Error> {
        self.conn.request("{\"command\":\"stopProfits\"}").await
    }

    pub async fn get_tick_prices(&self, symbol: &str, min_arrival_time: i64, max_level: i64) -> Result<(), Error> {
        self.conn
            .request(&format!(
                "{{\"command\":\"getTickPrices\",\"streamSessionId\":\"{}\",\"symbol\":\"{}\",\"minArrivalTime\":{},\"maxLevel\":{}}}",
                self.stream_session_id, symbol, min_arrival_time, max_level
            ))
            .await
    }

    pub async fn stop_tick_prices(&self, symbol: &str) -> Result<(), Error> {
        self.conn
            .request(&format!("{{\"command\":\"stopTickPrices\",\"symbol\":\"{}\"}}", symbol))
            .await
    }

    pub async fn get_trades(&self) -> Result<(), Error> {
        self.conn
            .request(&format!(
                "{{\"command\":\"getTrades\",\"streamSessionId\":\"{}\"}}",
                self.stream_session_id
            ))
            .await
    }

    pub async fn stop_trades(&self) -> Result<(), Error> {
        self.conn.request("{\"command\":\"stopTrades\"}").await
    }

    pub async fn get_trade_status(&self) -> Result<(), Error> {
        self.conn
            .request(&format!(
                "{{\"command\":\"getTradeStatus\",\"streamSessionId\":\"{}\"}}",
                self.stream_session_id
            ))
            .await
    }

    pub async fn stop_trade_status(&self) -> Result<(), Error> {
        self.conn.request("{\"command\":\"stopTradeStatus\"}").await
    }

    pub async fn ping(&self) -> Result<(), Error> {
        self.conn
            .request(&format!(
                "{{\"command\":\"ping\",\"streamSessionId\":\"{}\"}}",
                self.stream_session_id
            ))
            .await
    }

    pub async fn listen(&self) -> Result<Record, Error> {
        let record = self.conn.receive().await?;

        #[derive(Deserialize)]
        struct Command {
            command: String,
        }
        #[derive(Deserialize)]
        struct Data<T> {
            data: T,
        }

        fn from<T: DeserializeOwned>(record: &str) -> Result<T, Error> {
            let d = serde_json::from_str::<Data<T>>(record)?;
            Ok(d.data)
        }

        let c = serde_json::from_str::<Command>(&record)?;
        match c.command.as_str() {
            "balance" => Ok(Record::Balance(from::<Balance>(&record)?)),
            "candle" => Ok(Record::Candle(from::<Candle>(&record)?)),
            "keepAlive" => Ok(Record::KeepAlive(from::<KeepAlive>(&record)?)),
            "news" => Ok(Record::News(from::<News>(&record)?)),
            "profit" => Ok(Record::Profit(from::<Profit>(&record)?)),
            "tickPrices" => Ok(Record::Tick(from::<Tick>(&record)?)),
            "trade" => Ok(Record::Trade(from::<Trade>(&record)?)),
            "tradeStatus" => Ok(Record::TradeStatus(from::<TradeStatus>(&record)?)),
            _ => Err(Error::UnknownRecord { record }),
        }
    }
}