Skip to main content

barter_data/exchange/binance/
mod.rs

1use self::{
2    book::l1::BinanceOrderBookL1, channel::BinanceChannel, market::BinanceMarket,
3    subscription::BinanceSubResponse, trade::BinanceTrade,
4};
5use crate::{
6    ExchangeWsStream, NoInitialSnapshots,
7    exchange::{Connector, ExchangeServer, ExchangeSub, StreamSelector},
8    instrument::InstrumentData,
9    subscriber::{WebSocketSubscriber, validator::WebSocketSubValidator},
10    subscription::{Map, book::OrderBooksL1, trade::PublicTrades},
11    transformer::stateless::StatelessTransformer,
12};
13use barter_instrument::exchange::ExchangeId;
14use barter_integration::protocol::websocket::{WebSocketSerdeParser, WsMessage};
15use std::{fmt::Debug, marker::PhantomData};
16use url::Url;
17
18/// OrderBook types common to both [`BinanceSpot`](spot::BinanceSpot) and
19/// [`BinanceFuturesUsd`](futures::BinanceFuturesUsd).
20pub mod book;
21
22/// Defines the type that translates a Barter [`Subscription`](crate::subscription::Subscription)
23/// into an exchange [`Connector`] specific channel used for generating [`Connector::requests`].
24pub mod channel;
25
26/// [`ExchangeServer`] and [`StreamSelector`] implementations for
27/// [`BinanceFuturesUsd`](futures::BinanceFuturesUsd).
28pub mod futures;
29
30/// Defines the type that translates a Barter [`Subscription`](crate::subscription::Subscription)
31/// into an exchange [`Connector`] specific market used for generating [`Connector::requests`].
32pub mod market;
33
34/// [`ExchangeServer`] and [`StreamSelector`] implementations for
35/// [`BinanceSpot`](spot::BinanceSpot).
36pub mod spot;
37
38/// [`Subscription`](crate::subscription::Subscription) response type and response
39/// [`Validator`](barter_integration::Validator) common to both [`BinanceSpot`](spot::BinanceSpot)
40/// and [`BinanceFuturesUsd`](futures::BinanceFuturesUsd).
41pub mod subscription;
42
43/// Public trade types common to both [`BinanceSpot`](spot::BinanceSpot) and
44/// [`BinanceFuturesUsd`](futures::BinanceFuturesUsd).
45pub mod trade;
46
47/// Convenient type alias for a Binance [`ExchangeWsStream`] using [`WebSocketSerdeParser`].
48pub type BinanceWsStream<Transformer> = ExchangeWsStream<WebSocketSerdeParser, Transformer>;
49
50/// Generic [`Binance<Server>`](Binance) exchange.
51///
52/// ### Notes
53/// A `Server` [`ExchangeServer`] implementations exists for
54/// [`BinanceSpot`](spot::BinanceSpot) and [`BinanceFuturesUsd`](futures::BinanceFuturesUsd).
55#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
56pub struct Binance<Server> {
57    server: PhantomData<Server>,
58}
59
60impl<Server> Connector for Binance<Server>
61where
62    Server: ExchangeServer,
63{
64    const ID: ExchangeId = Server::ID;
65    type Channel = BinanceChannel;
66    type Market = BinanceMarket;
67    type Subscriber = WebSocketSubscriber;
68    type SubValidator = WebSocketSubValidator;
69    type SubResponse = BinanceSubResponse;
70
71    fn url() -> Result<Url, url::ParseError> {
72        Url::parse(Server::websocket_url())
73    }
74
75    fn requests(exchange_subs: Vec<ExchangeSub<Self::Channel, Self::Market>>) -> Vec<WsMessage> {
76        let stream_names = exchange_subs
77            .into_iter()
78            .map(|sub| {
79                // Note:
80                // Market must be lowercase when subscribing, but lowercase in general since
81                // Binance sends message with uppercase MARKET (eg/ BTCUSDT).
82                format!(
83                    "{}{}",
84                    sub.market.as_ref().to_lowercase(),
85                    sub.channel.as_ref()
86                )
87            })
88            .collect::<Vec<String>>();
89
90        vec![WsMessage::text(
91            serde_json::json!({
92                "method": "SUBSCRIBE",
93                "params": stream_names,
94                "id": 1
95            })
96            .to_string(),
97        )]
98    }
99
100    fn expected_responses<InstrumentKey>(_: &Map<InstrumentKey>) -> usize {
101        1
102    }
103}
104
105impl<Instrument, Server> StreamSelector<Instrument, PublicTrades> for Binance<Server>
106where
107    Instrument: InstrumentData,
108    Server: ExchangeServer + Debug + Send + Sync,
109{
110    type SnapFetcher = NoInitialSnapshots;
111    type Stream =
112        BinanceWsStream<StatelessTransformer<Self, Instrument::Key, PublicTrades, BinanceTrade>>;
113}
114
115impl<Instrument, Server> StreamSelector<Instrument, OrderBooksL1> for Binance<Server>
116where
117    Instrument: InstrumentData,
118    Server: ExchangeServer + Debug + Send + Sync,
119{
120    type SnapFetcher = NoInitialSnapshots;
121    type Stream = BinanceWsStream<
122        StatelessTransformer<Self, Instrument::Key, OrderBooksL1, BinanceOrderBookL1>,
123    >;
124}
125
126impl<'de, Server> serde::Deserialize<'de> for Binance<Server>
127where
128    Server: ExchangeServer,
129{
130    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
131    where
132        D: serde::de::Deserializer<'de>,
133    {
134        let input = <String as serde::Deserialize>::deserialize(deserializer)?;
135
136        if input.as_str() == Self::ID.as_str() {
137            Ok(Self::default())
138        } else {
139            Err(serde::de::Error::invalid_value(
140                serde::de::Unexpected::Str(input.as_str()),
141                &Self::ID.as_str(),
142            ))
143        }
144    }
145}
146
147impl<Server> serde::Serialize for Binance<Server>
148where
149    Server: ExchangeServer,
150{
151    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
152    where
153        S: serde::ser::Serializer,
154    {
155        serializer.serialize_str(Self::ID.as_str())
156    }
157}