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