use std::task::{Context, Poll};
use std::time::Duration;
use exc_core::exchange::{
MakeCancelOrderOptions, MakeCheckOrderOptions, MakeExchange, MakeFetchCandlesOptions,
MakeInstrumentsOptions, MakePlaceOrderOptions, MakeSubscribeOrdersOptions, MakeTickersOptions,
};
use exc_core::service::{BoxCloneExcService, BoxExcService};
use exc_core::types::{
CancelOrder, GetOrder, PlaceOrder, QueryCandles, SubscribeInstruments, SubscribeOrders,
SubscribeTickers,
};
use exc_core::util::fetch_candles::FetchCandlesBackwardLayer;
use exc_core::util::fetch_instruments_first::FetchThenSubscribeInstrumentsLayer;
use exc_core::util::trade_bid_ask::TradeBidAskLayer;
use exc_core::{ExcServiceExt, ExchangeError, IntoExc};
use futures::future::{ready, Ready};
use tower::{Layer, Service};
use crate::service::Okx;
#[derive(Clone)]
pub struct OkxExchange {
public: Okx,
private: Okx,
}
impl OkxExchange {
pub fn new(public: Okx, private: Okx) -> Self {
Self { public, private }
}
}
impl Service<MakeInstrumentsOptions> for OkxExchange {
type Response = BoxCloneExcService<SubscribeInstruments>;
type Error = ExchangeError;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, _req: MakeInstrumentsOptions) -> Self::Future {
ready(Ok(FetchThenSubscribeInstrumentsLayer
.layer(self.public.clone().into_exc())
.boxed_clone()))
}
}
impl Service<MakeTickersOptions> for OkxExchange {
type Response = BoxCloneExcService<SubscribeTickers>;
type Error = ExchangeError;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: MakeTickersOptions) -> Self::Future {
if req.is_prefer_trade_bid_ask() {
let svc = self.public.clone().into_exc();
let mut layer = TradeBidAskLayer::default();
layer.first_trade(req.get_first_trade());
if req.is_accept_bid_ask_ts() {
layer.accept_bid_ask_ts();
}
ready(Ok(
ExcServiceExt::<crate::OkxRequest>::apply(svc, &layer).boxed_clone()
))
} else {
ready(Ok(self.public.clone().adapt().boxed_clone()))
}
}
}
impl Service<MakePlaceOrderOptions> for OkxExchange {
type Response = BoxCloneExcService<PlaceOrder>;
type Error = ExchangeError;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, _req: MakePlaceOrderOptions) -> Self::Future {
ready(Ok(self.private.clone().adapt().boxed_clone()))
}
}
impl Service<MakeCancelOrderOptions> for OkxExchange {
type Response = BoxCloneExcService<CancelOrder>;
type Error = ExchangeError;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, _req: MakeCancelOrderOptions) -> Self::Future {
ready(Ok(self.private.clone().adapt().boxed_clone()))
}
}
impl Service<MakeCheckOrderOptions> for OkxExchange {
type Response = BoxCloneExcService<GetOrder>;
type Error = ExchangeError;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, _req: MakeCheckOrderOptions) -> Self::Future {
ready(Ok(self.private.clone().adapt().boxed_clone()))
}
}
impl Service<MakeSubscribeOrdersOptions> for OkxExchange {
type Response = BoxCloneExcService<SubscribeOrders>;
type Error = ExchangeError;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, _req: MakeSubscribeOrdersOptions) -> Self::Future {
ready(Ok(self.private.clone().adapt().boxed_clone()))
}
}
impl Service<MakeFetchCandlesOptions> for OkxExchange {
type Response = BoxExcService<QueryCandles>;
type Error = ExchangeError;
type Future = Ready<Result<Self::Response, Self::Error>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, req: MakeFetchCandlesOptions) -> Self::Future {
let MakeFetchCandlesOptions {
rate_limit,
batch_limit,
} = req;
let (num, per) = rate_limit.unwrap_or((19, Duration::from_secs(1)));
let limit = batch_limit.unwrap_or(100);
ready(Ok(self
.public
.clone()
.rate_limited(num, per)
.adapt()
.apply(&FetchCandlesBackwardLayer::with_default_bound(limit))
.boxed()))
}
}
impl MakeExchange for OkxExchange {
fn name(&self) -> &str {
"okx"
}
}