1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#![allow(dead_code)]
use std::convert::TryFrom;
use serde_json::Value;
use cxmr_api_clients_errors::Error;
use cxmr_currency::CurrencyPair;
use cxmr_exchanges::{Exchange, ExchangeInfo, MarketInfo, MarketStatus, OrderType, RateLimit};
use super::{filters::parse_filter, limits::BncRateLimit};
#[derive(Deserialize)]
pub struct BncExchangeInfo {
#[serde(rename = "serverTime")]
server_time: u64,
#[serde(rename = "rateLimits")]
rate_limits: Vec<BncRateLimit>,
symbols: Vec<BncMarketInfo>,
}
impl TryFrom<BncExchangeInfo> for ExchangeInfo {
type Error = Error;
#[inline]
fn try_from(info: BncExchangeInfo) -> Result<ExchangeInfo, Error> {
let symbols = info
.symbols
.into_iter()
.map(|i| MarketInfo::try_from(i))
.collect::<Result<_, _>>()?;
let limits = info
.rate_limits
.into_iter()
.map(|i| RateLimit::try_from(i))
.collect::<Result<_, _>>()?;
Ok(ExchangeInfo {
markets: symbols,
limits: limits,
exchange: Exchange::Binance,
})
}
}
#[derive(Deserialize)]
pub struct BncMarketInfo {
symbol: String,
status: String,
#[serde(rename = "baseAsset")]
base_asset: String,
#[serde(rename = "quoteAsset")]
quote_asset: String,
#[serde(rename = "baseAssetPrecision")]
base_asset_precision: u64,
#[serde(rename = "quotePrecision")]
quote_precision: u64,
#[serde(rename = "orderTypes")]
order_types: Vec<String>,
#[serde(rename = "icebergAllowed")]
iceberg_allowed: bool,
filters: Vec<Value>,
}
impl TryFrom<BncMarketInfo> for MarketInfo {
type Error = Error;
#[inline]
fn try_from(info: BncMarketInfo) -> Result<MarketInfo, Error> {
let status = match_status(&info.status)?;
let filters = info
.filters
.into_iter()
.map(|i| parse_filter(i))
.collect::<Result<_, _>>()?;
let order_types = info
.order_types
.into_iter()
.map(|t| order_type(&t))
.collect::<Result<_, _>>()?;
let pair = CurrencyPair::new(
info.base_asset.as_str().into(),
info.quote_asset.as_str().into(),
);
Ok(MarketInfo {
pair: pair,
status: status,
filters: filters,
order_types: order_types,
})
}
}
#[inline]
fn match_status(s: &str) -> Result<MarketStatus, Error> {
match s {
"PRE_TRADING" => Ok(MarketStatus::PreTrading),
"TRADING" => Ok(MarketStatus::Trading),
"POST_TRADING" => Ok(MarketStatus::PostTrading),
"END_OF_DAY" => Ok(MarketStatus::EndOfDay),
"HALT" => Ok(MarketStatus::Halt),
"AUCTION_MATCH" => Ok(MarketStatus::AuctionMatch),
"BREAK" => Ok(MarketStatus::Break),
_ => Err(Error::UnexpectedMarketStatus(s.to_string())),
}
}
#[inline]
pub fn order_type_to_str(s: &OrderType) -> &str {
match s {
&OrderType::Limit => "LIMIT",
&OrderType::Market => "MARKET",
&OrderType::StopLoss => "STOP_LOSS",
&OrderType::StopLossLimit => "STOP_LOSS_LIMIT",
&OrderType::TakeProfit => "TAKE_PROFIT",
&OrderType::TakeProfitLimit => "TAKE_PROFIT_LIMIT",
&OrderType::LimitMaker => "LIMIT_MAKER",
}
}
#[inline]
pub fn order_type(s: &str) -> Result<OrderType, Error> {
match s {
"LIMIT" => Ok(OrderType::Limit),
"MARKET" => Ok(OrderType::Market),
"STOP_LOSS" => Ok(OrderType::StopLoss),
"STOP_LOSS_LIMIT" => Ok(OrderType::StopLossLimit),
"TAKE_PROFIT" => Ok(OrderType::TakeProfit),
"TAKE_PROFIT_LIMIT" => Ok(OrderType::TakeProfitLimit),
"LIMIT_MAKER" => Ok(OrderType::LimitMaker),
_ => Err(Error::UnexpectedOrderType(s.to_string())),
}
}