exc_make/
tickers.rs

1use exc_service::{ExchangeError, Request, SendExcService};
2use exc_types::SubscribeTickers;
3use futures::{future::MapErr, TryFutureExt};
4use std::{
5    future::Future,
6    task::{Context, Poll},
7};
8use tower_make::MakeService;
9
10/// How to get the first trade.
11#[derive(Debug, Clone, Copy, Default)]
12pub enum FirstTrade {
13    /// Wait for the first trade.
14    #[default]
15    Wait,
16    /// Use bid for the first trade.
17    Bid,
18    /// Use ask for the first trade.
19    Ask,
20    /// Use first bid/ask for the first trade.
21    BidAsk,
22}
23
24/// Options for making a service to subscribe tickers.
25#[derive(Debug, Default)]
26pub struct MakeTickersOptions {
27    prefer_trade_bid_ask: bool,
28    first_trade: FirstTrade,
29    accept_bid_ask_ts: bool,
30}
31
32impl MakeTickersOptions {
33    /// Set whether to prefer use ticker from trade bid/ask. Default is `false`.
34    pub fn prefer_trade_bid_ask(mut self, flag: bool) -> Self {
35        self.prefer_trade_bid_ask = flag;
36        self
37    }
38
39    /// Set how to get the first trade. Default is [`FirstTrade::Wait`].
40    /// Only works when [`MakeTickersOptions::prefer_trade_bid_ask`] is `true`.
41    pub fn first_trade(mut self, mode: FirstTrade) -> Self {
42        self.first_trade = mode;
43        self
44    }
45
46    /// Get whether to prefer use ticker from trade bid/ask.
47    pub fn is_prefer_trade_bid_ask(&self) -> bool {
48        self.prefer_trade_bid_ask
49    }
50
51    /// Get how to get the first trade.
52    pub fn get_first_trade(&self) -> FirstTrade {
53        self.first_trade
54    }
55
56    /// Accept bid/ask ts. Default is `false`. Only works when
57    /// [`MakeTickersOptions::prefer_trade_bid_ask`] is `true`.
58    pub fn accept_bid_ask_ts(mut self, flag: bool) -> Self {
59        self.accept_bid_ask_ts = flag;
60        self
61    }
62
63    /// Get whether to accept bid/ask ts.
64    pub fn is_accept_bid_ask_ts(&self) -> bool {
65        self.accept_bid_ask_ts
66    }
67}
68
69/// Make a service to subscribe tickers.
70pub trait MakeTickers {
71    /// Service to subscribe tickers.
72    type Service: SendExcService<SubscribeTickers>;
73
74    /// The future of the service.
75    type Future: Future<Output = Result<Self::Service, ExchangeError>>;
76
77    /// Returns `Ready` when the factory is able to create more service.
78    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), ExchangeError>>;
79
80    /// Create a new service to subscribe tickers.
81    fn make_tickers(&mut self, options: MakeTickersOptions) -> Self::Future;
82
83    /// Convert to a [`Service`](tower_service::Service).
84    fn as_make_tickers_service(&mut self) -> AsService<'_, Self>
85    where
86        Self: Sized,
87    {
88        AsService { make: self }
89    }
90}
91
92impl<M> MakeTickers for M
93where
94    M: MakeService<
95        MakeTickersOptions,
96        SubscribeTickers,
97        Response = <SubscribeTickers as Request>::Response,
98        Error = ExchangeError,
99    >,
100    M::Service: SendExcService<SubscribeTickers>,
101    M::MakeError: Into<ExchangeError>,
102{
103    type Service = M::Service;
104
105    type Future = MapErr<M::Future, fn(M::MakeError) -> ExchangeError>;
106
107    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), ExchangeError>> {
108        self.poll_ready(cx).map_err(Into::into)
109    }
110
111    fn make_tickers(&mut self, options: MakeTickersOptions) -> Self::Future {
112        self.make_service(options).map_err(Into::into)
113    }
114}
115
116crate::create_as_service!(
117    MakeTickers,
118    MakeTickersOptions,
119    make_tickers,
120    "Service returns by [`MakeTickers::as_make_tickers_service`]."
121);