1use crate::rest_model::{string_or_bool, string_or_float_opt};
2pub use crate::rest_model::{string_or_float, string_or_u64, Asks, Bids, BookTickers, KlineSummaries, KlineSummary,
3 OrderSide, OrderStatus, RateLimit, ServerTime, SymbolPrice, SymbolStatus, Tickers,
4 TimeInForce};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Serialize, Deserialize, Clone)]
8#[serde(rename_all = "camelCase")]
9pub struct ExchangeInformation {
10 pub timezone: String,
11 pub server_time: u64,
12 pub futures_type: String,
13 pub rate_limits: Vec<RateLimit>,
14 pub exchange_filters: Vec<Filters>,
15 pub assets: Vec<AssetDetail>,
16 pub symbols: Vec<Symbol>,
17}
18
19#[derive(Debug, Serialize, Deserialize, Clone)]
20#[serde(rename_all = "camelCase")]
21pub struct AssetDetail {
22 pub asset: String,
23 pub margin_available: bool,
24 #[serde(with = "string_or_float")]
25 pub auto_asset_exchange: f64,
26}
27
28#[derive(Debug, Serialize, Deserialize, Clone)]
29#[serde(rename_all = "camelCase")]
30pub struct Symbol {
31 pub symbol: String,
32 pub pair: String,
33 pub contract_type: ContractType,
34 pub delivery_date: u64,
35 pub onboard_date: u64,
36 pub status: SymbolStatus,
37 #[serde(with = "string_or_float")]
38 pub maint_margin_percent: f64,
39 #[serde(with = "string_or_float")]
40 pub required_margin_percent: f64,
41 pub base_asset: String,
42 pub quote_asset: String,
43 pub price_precision: u16,
44 pub quantity_precision: u16,
45 pub base_asset_precision: u64,
46 pub quote_precision: u64,
47 pub underlying_type: String,
48 pub underlying_sub_type: Vec<String>,
49 pub settle_plan: u64,
50 #[serde(with = "string_or_float")]
51 pub trigger_protect: f64,
52 pub filters: Vec<Filters>,
53 pub order_types: Vec<OrderType>,
54 pub time_in_force: Vec<TimeInForce>,
55}
56
57#[derive(Debug, Deserialize, Serialize, Clone)]
58#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
59pub enum ContractType {
60 Perpetual,
61 CurrentMonth,
62 NextMonth,
63 CurrentQuarter,
64 NextQuarter,
65 #[serde(rename = "CURRENT_QUARTER DELIVERING")]
66 CurrentQuarterDelivery,
67 PerpetualDelivering,
68 #[serde(rename = "")]
69 Empty,
70}
71
72#[derive(Debug, Deserialize, Serialize, Clone)]
73#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
74pub enum OrderType {
75 Limit,
76 Market,
77 Stop,
78 StopMarket,
79 TakeProfit,
80 TakeProfitMarket,
81 TrailingStopMarket,
82}
83
84impl Default for OrderType {
86 fn default() -> Self { Self::Market }
87}
88
89#[derive(Debug, Deserialize, Serialize, Clone)]
90#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
91pub enum PositionSide {
92 Both,
93 Long,
94 Short,
95}
96
97#[derive(Debug, Deserialize, Serialize, Clone)]
98#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
99pub enum WorkingType {
100 MarkPrice,
101 ContractPrice,
102}
103
104#[derive(Debug, Deserialize, Serialize, Clone)]
105#[serde(rename_all = "lowercase")]
106pub enum MarginType {
107 Isolated,
108 Cross,
109}
110
111#[derive(Debug, Serialize, Deserialize, Clone)]
112#[serde(tag = "filterType")]
113pub enum Filters {
114 #[serde(rename = "PRICE_FILTER")]
115 #[serde(rename_all = "camelCase")]
116 PriceFilter {
117 #[serde(with = "string_or_float")]
118 min_price: f64,
119 #[serde(with = "string_or_float")]
120 max_price: f64,
121 #[serde(with = "string_or_float")]
122 tick_size: f64,
123 },
124 #[serde(rename = "LOT_SIZE")]
125 #[serde(rename_all = "camelCase")]
126 LotSize {
127 #[serde(with = "string_or_float")]
128 min_qty: f64,
129 #[serde(with = "string_or_float")]
130 max_qty: f64,
131 #[serde(with = "string_or_float")]
132 step_size: f64,
133 },
134 #[serde(rename = "MARKET_LOT_SIZE")]
135 #[serde(rename_all = "camelCase")]
136 MarketLotSize {
137 min_qty: String,
138 max_qty: String,
139 step_size: String,
140 },
141 #[serde(rename = "MAX_NUM_ORDERS")]
142 #[serde(rename_all = "camelCase")]
143 MaxNumOrders { limit: u16 },
144 #[serde(rename = "MAX_NUM_ALGO_ORDERS")]
145 #[serde(rename_all = "camelCase")]
146 MaxNumAlgoOrders { limit: u16 },
147 #[serde(rename = "MIN_NOTIONAL")]
148 #[serde(rename_all = "camelCase")]
149 MinNotional {
150 #[serde(with = "string_or_float")]
151 notional: f64,
152 },
153 #[serde(rename = "PERCENT_PRICE")]
154 #[serde(rename_all = "camelCase")]
155 PercentPrice {
156 #[serde(with = "string_or_float")]
157 multiplier_up: f64,
158 #[serde(with = "string_or_float")]
159 multiplier_down: f64,
160 #[serde(with = "string_or_float")]
161 multiplier_decimal: f64,
162 },
163 #[serde(other)]
164 Others,
165}
166
167#[derive(Debug, Serialize, Deserialize, Clone)]
168#[serde(rename_all = "camelCase")]
169pub struct OrderBook {
170 pub last_update_id: u64,
171 #[serde(rename = "E")]
173 pub event_time: u64,
174 #[serde(rename = "T")]
176 pub trade_order_time: u64,
177 pub bids: Vec<Bids>,
178 pub asks: Vec<Asks>,
179}
180
181#[derive(Debug, Serialize, Deserialize, Clone)]
182#[serde(rename_all = "camelCase")]
183pub struct PriceStats {
184 pub symbol: String,
185 pub price_change: String,
186 pub price_change_percent: String,
187 pub weighted_avg_price: String,
188 #[serde(with = "string_or_float")]
189 pub last_price: f64,
190 #[serde(with = "string_or_float")]
191 pub open_price: f64,
192 #[serde(with = "string_or_float")]
193 pub high_price: f64,
194 #[serde(with = "string_or_float")]
195 pub low_price: f64,
196 #[serde(with = "string_or_float")]
197 pub volume: f64,
198 #[serde(with = "string_or_float")]
199 pub quote_volume: f64,
200 #[serde(with = "string_or_float")]
201 pub last_qty: f64,
202 pub open_time: u64,
203 pub close_time: u64,
204 pub first_id: u64,
205 pub last_id: u64,
206 pub count: u64,
207}
208
209#[derive(Debug, Serialize, Deserialize, Clone)]
210#[serde(untagged)]
211pub enum Trades {
212 AllTrades(Vec<Trade>),
213}
214
215#[derive(Debug, Serialize, Deserialize, Clone)]
216#[serde(rename_all = "camelCase")]
217pub struct Trade {
218 pub id: u64,
219 pub is_buyer_maker: bool,
220 #[serde(with = "string_or_float")]
221 pub price: f64,
222 #[serde(with = "string_or_float")]
223 pub qty: f64,
224 #[serde(with = "string_or_float")]
225 pub quote_qty: f64,
226 pub time: u64,
227}
228
229#[derive(Debug, Serialize, Deserialize, Clone)]
230#[serde(untagged)]
231pub enum AggTrades {
232 AllAggTrades(Vec<AggTrade>),
233}
234
235#[derive(Debug, Serialize, Deserialize, Clone)]
236#[serde(rename_all = "camelCase")]
237pub struct AggTrade {
238 #[serde(rename = "T")]
239 pub time: u64,
240 #[serde(rename = "a")]
241 pub agg_id: u64,
242 #[serde(rename = "f")]
243 pub first_id: u64,
244 #[serde(rename = "l")]
245 pub last_id: u64,
246 #[serde(rename = "m")]
247 pub maker: bool,
248 #[serde(rename = "p", with = "string_or_float")]
249 pub price: f64,
250 #[serde(rename = "q", with = "string_or_float")]
251 pub qty: f64,
252}
253
254#[derive(Debug, Serialize, Deserialize, Clone)]
261#[serde(rename_all = "camelCase")]
262pub struct MarkPrice {
263 pub symbol: String,
264 #[serde(with = "string_or_float")]
265 pub mark_price: f64,
266 #[serde(with = "string_or_float")]
267 pub index_price: f64,
268 #[serde(with = "string_or_float")]
269 pub estimated_settle_price: f64,
270 #[serde(with = "string_or_float")]
271 pub last_funding_rate: f64,
272 pub next_funding_time: u64,
273 #[serde(with = "string_or_float")]
274 pub interest_rate: f64,
275 pub time: u64,
276}
277
278#[derive(Debug, Serialize, Deserialize, Clone)]
279#[serde(untagged)]
280pub enum LiquidationOrders {
281 AllLiquidationOrders(Vec<LiquidationOrder>),
282}
283
284#[derive(Debug, Serialize, Deserialize, Clone)]
285#[serde(rename_all = "camelCase")]
286pub struct LiquidationOrder {
287 #[serde(with = "string_or_float")]
288 pub average_price: f64,
289 #[serde(with = "string_or_float")]
290 pub executed_qty: f64,
291 #[serde(with = "string_or_float")]
292 pub orig_qty: f64,
293 #[serde(with = "string_or_float")]
294 pub price: f64,
295 pub side: String,
296 pub status: String,
297 pub symbol: String,
298 pub time: u64,
299 pub time_in_force: String,
300 pub r#type: String,
301}
302
303#[derive(Debug, Serialize, Deserialize, Clone)]
304#[serde(rename_all = "camelCase")]
305pub struct OpenInterest {
306 #[serde(with = "string_or_float")]
307 pub open_interest: f64,
308 pub symbol: String,
309}
310
311#[derive(Debug, Deserialize, Clone)]
312#[serde(rename_all = "camelCase")]
313pub struct Order {
314 pub client_order_id: String,
315 #[serde(with = "string_or_float")]
316 pub cum_quote: f64,
317 #[serde(with = "string_or_float")]
318 pub executed_qty: f64,
319 pub order_id: u64,
320 #[serde(with = "string_or_float")]
321 pub avg_price: f64,
322 #[serde(with = "string_or_float")]
323 pub orig_qty: f64,
324 #[serde(with = "string_or_float")]
325 pub price: f64,
326 pub side: OrderSide,
327 pub reduce_only: bool,
328 pub position_side: PositionSide,
329 pub status: OrderStatus,
330 #[serde(with = "string_or_float", default = "default_stop_price")]
331 pub stop_price: f64,
332 pub close_position: bool,
333 pub symbol: String,
334 pub time_in_force: TimeInForce,
335 #[serde(rename = "type")]
336 pub order_type: OrderType,
337 pub orig_type: OrderType,
338 #[serde(with = "string_or_float", default = "default_activation_price")]
339 pub activate_price: f64,
340 #[serde(with = "string_or_float", default = "default_price_rate")]
341 pub price_rate: f64,
342 pub update_time: u64,
343 pub working_type: WorkingType,
344 pub price_protect: bool,
345}
346
347#[derive(Debug, Serialize, Deserialize, Clone)]
348#[serde(rename_all = "camelCase")]
349pub struct Transaction {
350 pub client_order_id: String,
351 #[serde(with = "string_or_float")]
352 pub cum_qty: f64,
353 #[serde(with = "string_or_float")]
354 pub cum_quote: f64,
355 #[serde(with = "string_or_float")]
356 pub executed_qty: f64,
357 pub order_id: u64,
358 #[serde(with = "string_or_float")]
359 pub avg_price: f64,
360 #[serde(with = "string_or_float")]
361 pub orig_qty: f64,
362 pub reduce_only: bool,
363 pub side: OrderSide,
364 pub position_side: PositionSide,
365 pub status: OrderStatus,
366 #[serde(with = "string_or_float")]
367 pub stop_price: f64,
368 pub close_position: bool,
369 pub symbol: String,
370 pub time_in_force: TimeInForce,
371 #[serde(rename = "type")]
372 pub type_name: OrderType,
373 pub orig_type: OrderType,
374 #[serde(default)]
375 #[serde(with = "string_or_float_opt")]
376 pub activate_price: Option<f64>,
377 #[serde(default)]
378 #[serde(with = "string_or_float_opt")]
379 pub price_rate: Option<f64>,
380 pub update_time: u64,
381 pub working_type: WorkingType,
382 price_protect: bool,
383}
384
385#[derive(Debug, Serialize, Deserialize, Clone)]
386#[serde(rename_all = "camelCase")]
387pub struct CanceledOrder {
388 pub client_order_id: String,
389 #[serde(with = "string_or_float")]
390 pub cum_qty: f64,
391 #[serde(with = "string_or_float")]
392 pub cum_quote: f64,
393 #[serde(with = "string_or_float")]
394 pub executed_qty: f64,
395 pub order_id: u64,
396 #[serde(with = "string_or_float")]
397 pub orig_qty: f64,
398 pub orig_type: String,
399 #[serde(with = "string_or_float")]
400 pub price: f64,
401 pub reduce_only: bool,
402 pub side: String,
403 pub position_side: String,
404 pub status: String,
405 #[serde(with = "string_or_float")]
406 pub stop_price: f64,
407 pub close_position: bool,
408 pub symbol: String,
409 pub time_in_force: String,
410 #[serde(rename = "type")]
411 pub type_name: String,
412 #[serde(default)]
413 #[serde(with = "string_or_float_opt")]
414 pub activate_price: Option<f64>,
415 #[serde(default)]
416 #[serde(with = "string_or_float_opt")]
417 pub price_rate: Option<f64>,
418 pub update_time: u64,
419 pub working_type: String,
420 price_protect: bool,
421}
422
423#[derive(Debug, Serialize, Deserialize, Clone)]
424#[serde(rename_all = "camelCase")]
425pub struct Position {
426 #[serde(with = "string_or_float")]
427 pub entry_price: f64,
428 pub margin_type: MarginType,
429 #[serde(with = "string_or_bool")]
430 pub is_auto_add_margin: bool,
431 #[serde(with = "string_or_float")]
432 pub isolated_margin: f64,
433 #[serde(with = "string_or_u64")]
434 pub leverage: u64,
435 #[serde(with = "string_or_float")]
436 pub liquidation_price: f64,
437 #[serde(with = "string_or_float")]
438 pub mark_price: f64,
439 #[serde(with = "string_or_float")]
440 pub max_notional_value: f64,
441 #[serde(with = "string_or_float", rename = "positionAmt")]
442 pub position_amount: f64,
443 pub symbol: String,
444 #[serde(with = "string_or_float", rename = "unRealizedProfit")]
445 pub unrealized_profit: f64,
446 pub position_side: PositionSide,
447 pub update_time: u64,
448 #[serde(with = "string_or_float")]
449 pub notional: f64,
450 #[serde(with = "string_or_float")]
451 pub isolated_wallet: f64,
452}
453
454#[derive(Debug, Serialize, Deserialize, Clone)]
457#[serde(rename_all = "camelCase")]
458pub struct AccountPosition {
459 pub symbol: String,
460 #[serde(with = "string_or_float")]
461 pub initial_margin: f64,
462 #[serde(with = "string_or_float", rename = "maintMargin")]
463 pub maintenance_margin: f64,
464 #[serde(with = "string_or_float")]
465 pub unrealized_profit: f64,
466 #[serde(with = "string_or_float")]
467 pub position_initial_margin: f64,
468 #[serde(with = "string_or_float")]
469 pub open_order_initial_margin: f64,
470 #[serde(with = "string_or_u64")]
471 pub leverage: u64,
472 pub isolated: bool,
473 #[serde(with = "string_or_float")]
474 pub entry_price: f64,
475 #[serde(with = "string_or_float")]
476 pub max_notional: f64,
477 #[serde(with = "string_or_float")]
478 pub bid_notional: f64,
479 #[serde(with = "string_or_float")]
480 pub ask_notional: f64,
481 pub position_side: PositionSide,
482 #[serde(with = "string_or_float", rename = "positionAmt")]
483 pub position_amount: f64,
484 pub update_time: u64,
485}
486
487#[derive(Debug, Serialize, Deserialize, Clone)]
488#[serde(rename_all = "camelCase")]
489pub struct AccountAsset {
490 pub asset: String,
491 #[serde(with = "string_or_float")]
492 pub wallet_balance: f64,
493 #[serde(with = "string_or_float")]
494 pub unrealized_profit: f64,
495 #[serde(with = "string_or_float")]
496 pub margin_balance: f64,
497 #[serde(with = "string_or_float")]
498 pub maint_margin: f64,
499 #[serde(with = "string_or_float")]
500 pub initial_margin: f64,
501 #[serde(with = "string_or_float")]
502 pub position_initial_margin: f64,
503 #[serde(with = "string_or_float")]
504 pub open_order_initial_margin: f64,
505 #[serde(with = "string_or_float")]
506 pub cross_wallet_balance: f64,
507 #[serde(with = "string_or_float", rename = "crossUnPnl")]
508 pub cross_unrealized_pnl: f64,
509 #[serde(with = "string_or_float")]
510 pub available_balance: f64,
511 #[serde(with = "string_or_float")]
512 pub max_withdraw_amount: f64,
513 pub margin_available: bool,
514 pub update_time: u64,
515}
516
517#[derive(Debug, Serialize, Deserialize, Clone)]
518#[serde(rename_all = "camelCase")]
519pub struct AccountInformation {
520 pub fee_tier: u64,
521 pub can_trade: bool,
522 pub can_deposit: bool,
523 pub can_withdraw: bool,
524 pub update_time: u64,
525 pub multi_assets_margin: bool,
526 #[serde(with = "string_or_float")]
527 pub total_initial_margin: f64,
528 #[serde(with = "string_or_float", rename = "totalMaintMargin")]
529 pub total_maintenance_margin: f64,
530 #[serde(with = "string_or_float")]
531 pub total_wallet_balance: f64,
532 #[serde(with = "string_or_float")]
533 pub total_unrealized_profit: f64,
534 #[serde(with = "string_or_float")]
535 pub total_margin_balance: f64,
536 #[serde(with = "string_or_float")]
537 pub total_position_initial_margin: f64,
538 #[serde(with = "string_or_float")]
539 pub total_open_order_initial_margin: f64,
540 #[serde(with = "string_or_float")]
541 pub total_cross_wallet_balance: f64,
542 #[serde(with = "string_or_float", rename = "totalCrossUnPnl")]
543 pub total_cross_unrealized_pnl: f64,
544 #[serde(with = "string_or_float")]
545 pub available_balance: f64,
546 #[serde(with = "string_or_float")]
547 pub max_withdraw_amount: f64,
548 pub assets: Vec<AccountAsset>,
549 pub positions: Vec<AccountPosition>,
550}
551
552#[derive(Debug, Serialize, Deserialize, Clone)]
553#[serde(rename_all = "camelCase")]
554pub struct AccountBalance {
555 pub account_alias: String,
556 pub asset: String,
557 #[serde(with = "string_or_float")]
558 pub balance: f64,
559 #[serde(with = "string_or_float")]
560 pub cross_wallet_balance: f64,
561 #[serde(with = "string_or_float", rename = "crossUnPnl")]
562 pub cross_unrealized_pnl: f64,
563 #[serde(with = "string_or_float")]
564 pub available_balance: f64,
565 #[serde(with = "string_or_float")]
566 pub max_withdraw_amount: f64,
567 pub margin_available: bool,
568 pub update_time: u64,
569}
570
571#[derive(Debug, Serialize, Deserialize, Clone)]
572#[serde(rename_all = "camelCase")]
573pub struct ChangeLeverageResponse {
574 pub leverage: u8,
575 #[serde(with = "string_or_float")]
576 pub max_notional_value: f64,
577 pub symbol: String,
578}
579
580fn default_stop_price() -> f64 { 0.0 }
581fn default_activation_price() -> f64 { 0.0 }
582fn default_price_rate() -> f64 { 0.0 }
583
584#[derive(Serialize)]
585#[serde(rename_all = "camelCase")]
586pub(crate) struct HistoryQuery {
587 pub start_time: Option<u64>,
588 pub end_time: Option<u64>,
589 pub from_id: Option<u64>,
590 pub limit: u16,
591 pub symbol: String,
592 pub interval: Option<String>,
593 pub period: Option<String>,
594}
595
596impl HistoryQuery {
597 pub fn validate(&self) -> crate::errors::Result<()> {
598 if let Some(period) = &self.period {
599 if !PERIODS.contains(&period.as_str()) {
600 return Err(crate::errors::Error::InvalidPeriod(period.clone()));
601 }
602 }
603 Ok(())
604 }
605}
606
607#[derive(Serialize)]
608#[serde(rename_all = "camelCase")]
609pub(crate) struct IndexQuery {
610 pub start_time: Option<u64>,
611 pub end_time: Option<u64>,
612 pub limit: u16,
613 pub pair: String,
614 pub interval: Option<String>,
615}
616
617#[derive(Deserialize, Debug, Clone)]
618#[serde(rename_all = "camelCase")]
619pub struct FundingRate {
620 pub symbol: String,
621 pub funding_time: u64,
622 #[serde(with = "string_or_float")]
623 pub funding_rate: f64,
624}
625
626pub static PERIODS: &[&str] = &["5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"];
627
628#[derive(Deserialize)]
629#[serde(rename_all = "camelCase")]
630pub struct OpenInterestHistory {
631 pub symbol: String,
632 #[serde(with = "string_or_float")]
633 pub sum_open_interest: f64,
634 #[serde(with = "string_or_float")]
635 pub sum_open_interest_value: f64,
636 pub timestamp: u64,
637}
638
639#[derive(Deserialize)]
640#[serde(rename_all = "camelCase")]
641pub struct LongShortRatio {
642 pub symbol: String,
643 #[serde(with = "string_or_float")]
644 pub long_account: f64,
645 #[serde(with = "string_or_float")]
646 pub long_short_ratio: f64,
647 #[serde(with = "string_or_float")]
648 pub short_account: f64,
649 pub timestamp: u64,
650}
651
652#[derive(Deserialize)]
653#[serde(rename_all = "camelCase")]
654pub struct LeverageBracket {
655 pub bracket: u8,
656 pub initial_leverage: u8,
657 pub notional_cap: u64,
658 pub notional_floor: u64,
659 pub maint_margin_ratio: f64,
660 pub cum: f64,
661}
662
663#[derive(Deserialize)]
664#[serde(rename_all = "camelCase")]
665pub struct SymbolBrackets {
666 pub symbol: String,
667 pub notional_coef: Option<f64>,
668 pub brackets: Vec<LeverageBracket>,
669}