nash_protocol/protocol/subscriptions/new_account_trades/
response.rs

1use super::super::super::ResponseOrError;
2use super::request::SubscribeAccountTrades;
3use crate::errors::{ProtocolError, Result};
4use crate::graphql;
5use crate::types::{BuyOrSell, Trade, AccountTradeSide};
6use graphql::new_account_trades;
7use chrono::{DateTime, Utc};
8use bigdecimal::BigDecimal;
9use std::str::FromStr;
10use crate::protocol::traits::TryFromState;
11use crate::protocol::state::State;
12use std::sync::Arc;
13use tokio::sync::RwLock;
14use async_trait::async_trait;
15
16/// List of new incoming trades for a market via subscription.
17#[derive(Clone, Debug)]
18pub struct AccountTradesResponse {
19    pub trades: Vec<Trade>,
20}
21#[async_trait]
22impl TryFromState<new_account_trades::ResponseData> for Vec<Trade> {
23    async fn from(response: new_account_trades::ResponseData, _state: Arc<RwLock<State>>) -> Result<Vec<Trade>> {
24        let mut trades = Vec::new();
25        for trade_data in response.new_account_trades {
26            let market = trade_data.market.name.clone();
27            let taker_fee = BigDecimal::from_str(&trade_data.taker_fee.amount)?;
28            let maker_fee = BigDecimal::from_str(&trade_data.maker_fee.amount)?;
29            let amount = BigDecimal::from_str(&trade_data.amount.amount)?;
30            let maker_recieved = BigDecimal::from_str(&trade_data.maker_received.amount)?;
31            let taker_recieved = BigDecimal::from_str(&trade_data.taker_received.amount)?;
32            let limit_price = BigDecimal::from_str(&trade_data.limit_price.amount)?;
33            trades.push(Trade {
34                market,
35                amount,
36                taker_fee,
37                maker_fee,
38                maker_recieved,
39                taker_recieved,
40                taker_order_id: trade_data.taker_order_id.clone(),
41                maker_order_id: trade_data.maker_order_id.clone(),
42                account_side: trade_data.account_side.into(),
43                id: trade_data.id,
44                executed_at: DateTime::<Utc>::from_str(&trade_data.executed_at)
45                    .map_err(|_| ProtocolError("Could not convert value to DateTime"))?,
46                limit_price,
47                direction: trade_data.direction.into(),
48            })
49        }
50        Ok(trades)
51    }
52}
53
54impl SubscribeAccountTrades {
55    pub async fn response_from_graphql(
56        &self,
57        response: ResponseOrError<new_account_trades::ResponseData>,
58        state: Arc<RwLock<State>>
59    ) -> Result<ResponseOrError<AccountTradesResponse>> {
60        Ok(match response {
61            ResponseOrError::Response(data) => {
62                let response = data.data;
63                ResponseOrError::from_data(AccountTradesResponse {
64                    trades: TryFromState::from(response, state).await?,
65                })
66            }
67            ResponseOrError::Error(error) => ResponseOrError::Error(error),
68        })
69    }
70}
71
72impl From<new_account_trades::Direction> for BuyOrSell {
73    fn from(direction: new_account_trades::Direction) -> Self {
74        match direction {
75            new_account_trades::Direction::BUY => BuyOrSell::Buy,
76            new_account_trades::Direction::SELL => BuyOrSell::Sell,
77            // What is up with this?
78            new_account_trades::Direction::Other(_) => panic!("A trade without a direction?"),
79        }
80    }
81}
82
83impl From<new_account_trades::AccountTradeSide> for AccountTradeSide {
84    fn from(trade_side: new_account_trades::AccountTradeSide) -> Self {
85        match trade_side {
86            new_account_trades::AccountTradeSide::MAKER => AccountTradeSide::Maker,
87            new_account_trades::AccountTradeSide::TAKER => AccountTradeSide::Taker,
88            new_account_trades::AccountTradeSide::NONE => AccountTradeSide::None,
89            _ => panic!("Unsupported value in AccountTradeSide"),
90        }
91    }
92}