1use crate::clients::errors::ClientError;
3use crate::crypto::secrets::Token;
4use crate::request_types::TriggerType;
5use rust_decimal::Decimal;
6use serde::{Deserialize, Serialize};
7use serde_this_or_that::as_i64;
8use serde_tuple::Deserialize_tuple;
9use serde_with::StringWithSeparator;
10use serde_with::formats::CommaSeparator;
11use serde_with::serde_as;
12use std::collections::HashMap;
13use std::fmt::{Debug, Display, Formatter};
14use std::str::FromStr;
15
16#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
20#[serde(rename_all = "snake_case")]
21pub enum VerificationTier {
22 Intermediate,
23 Pro,
24}
25
26#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
28#[serde(rename_all = "snake_case")]
29pub enum SystemStatus {
30 Online,
31 Maintenance,
32 CancelOnly,
33 PostOnly,
34}
35
36#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
38#[serde(rename_all = "snake_case")]
39pub enum TradableAssetStatus {
40 Online,
41 CancelOnly,
42 PostOnly,
43 LimitOnly,
44 ReduceOnly,
45}
46
47#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
49#[serde(rename_all = "snake_case")]
50pub enum AssetStatus {
51 Enabled,
52 DepositOnly,
53 WithdrawalOnly,
54 FundingTemporarilyDisabled,
55}
56
57#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Copy)]
59#[serde(rename_all = "lowercase")]
60pub enum BuySell {
61 Buy,
62 Sell,
63}
64
65impl Display for BuySell {
66 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
67 match self {
68 BuySell::Buy => write!(f, "buy"),
69 BuySell::Sell => write!(f, "sell"),
70 }
71 }
72}
73
74#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Copy)]
76pub enum OrderFlag {
77 #[serde(rename = "post")]
79 Post,
80 #[serde(rename = "fcib")]
82 FeesInBase,
83 #[serde(rename = "fciq")]
85 FeesInQuote,
86 #[serde(rename = "nompp")]
88 NoMarketPriceProtection,
89 #[serde(rename = "viqc")]
91 OrderVolumeInQuote,
92}
93
94impl Display for OrderFlag {
95 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
96 match self {
97 OrderFlag::Post => write!(f, "post"),
98 OrderFlag::FeesInBase => write!(f, "fcib"),
99 OrderFlag::FeesInQuote => write!(f, "fciq"),
100 OrderFlag::NoMarketPriceProtection => write!(f, "nompp"),
101 OrderFlag::OrderVolumeInQuote => write!(f, "viqc"),
102 }
103 }
104}
105
106impl FromStr for OrderFlag {
107 type Err = ClientError;
108
109 fn from_str(s: &str) -> Result<Self, Self::Err> {
110 match s {
111 "post" => Ok(OrderFlag::Post),
112 "fcib" => Ok(OrderFlag::FeesInBase),
113 "fciq" => Ok(OrderFlag::FeesInQuote),
114 "nompp" => Ok(OrderFlag::NoMarketPriceProtection),
115 "viqc" => Ok(OrderFlag::OrderVolumeInQuote),
116 _ => Err(ClientError::Parse("Failed to parse order flag")),
117 }
118 }
119}
120
121#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
123#[serde(rename_all = "lowercase")]
124pub enum BidOrAsk {
125 Bid,
126 Ask,
127}
128
129#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
131pub enum BuySellChar {
132 #[serde(rename(deserialize = "b"))]
133 Buy,
134 #[serde(rename(deserialize = "s"))]
135 Sell,
136}
137
138#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
140pub enum MarketLimitChar {
141 #[serde(rename(deserialize = "m"))]
142 Market,
143 #[serde(rename(deserialize = "l"))]
144 Limit,
145}
146
147#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Copy)]
149#[serde(rename_all = "kebab-case")]
150pub enum OrderType {
151 Limit,
152 Market,
153 Iceberg, StopLoss,
155 StopLossLimit,
156 TakeProfit,
157 TakeProfitLimit,
158 TrailingStop,
159 TrailingStopLimit,
160 SettlePosition,
161}
162
163#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Copy)]
165pub enum TradeType {
166 #[serde(rename = "market")]
167 Market,
168 #[serde(rename = "limit")]
169 Limit,
170 #[serde(rename = "stop loss")]
171 StopLoss,
172 #[serde(rename = "stop limit")]
173 StopLimit,
174 #[serde(rename = "take profit")]
175 TakeProfit,
176 #[serde(rename = "stop loss limit")]
177 StopLossLimit,
178 #[serde(rename = "take profit limit")]
179 TakeProfitLimit,
180 #[serde(rename = "settle position")]
181 SettlePosition,
182 #[serde(rename = "stop market")]
183 StopMarket,
184 #[serde(rename = "touched market")]
185 TouchedMarket,
186 #[serde(rename = "liquidation market")]
187 LiquidationMarket,
188}
189
190impl Display for OrderType {
191 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
192 match self {
193 OrderType::Market => write!(f, "market"),
194 OrderType::Limit => write!(f, "limit"),
195 OrderType::StopLoss => write!(f, "stop-loss"),
196 OrderType::TakeProfit => write!(f, "take-profit"),
197 OrderType::StopLossLimit => write!(f, "stop-loss-limit"),
198 OrderType::TakeProfitLimit => write!(f, "take-profit-limit"),
199 OrderType::SettlePosition => write!(f, "settle-position"),
200 OrderType::Iceberg => write!(f, "iceberg"),
201 OrderType::TrailingStop => write!(f, "trailing-stop"),
202 OrderType::TrailingStopLimit => write!(f, "trailing-stop-limit"),
203 }
204 }
205}
206
207#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
209#[serde(rename_all = "lowercase")]
210pub enum OrderStatus {
211 Pending,
212 Open,
213 Closed,
214 Canceled,
215 Expired,
216}
217
218#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
220#[serde(rename_all = "snake_case")]
221pub enum OrderStatusV2 {
222 PendingNew,
223 New,
224 PartiallyFilled,
225 Filled,
226 Canceled,
227 Expired,
228}
229
230#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
232#[serde(rename_all = "lowercase")]
233pub enum PositionStatus {
234 Open,
235 Closed,
236}
237
238#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
240#[serde(rename_all = "lowercase")]
241pub enum PositionStatusV2 {
242 Opened,
243 Closing,
244 Closed,
245}
246
247#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
249#[serde(rename_all = "lowercase")]
250pub enum LedgerEntryType {
251 None,
252 Trade,
253 Credit,
254 Deposit,
255 Withdrawal,
256 Transfer,
257 Margin,
258 Rollover,
259 Spend,
260 Receive,
261 Settled,
262 Adjustment,
263 Staking,
264 Sale,
265 Dividend,
266 NftRebate,
267 NftTrade,
268 NftCreatorFee,
269 CustodyTransfer,
270}
271
272impl Display for LedgerEntryType {
273 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
274 match self {
275 LedgerEntryType::None => write!(f, "none"),
276 LedgerEntryType::Trade => write!(f, "trade"),
277 LedgerEntryType::Credit => write!(f, "credit"),
278 LedgerEntryType::Deposit => write!(f, "deposit"),
279 LedgerEntryType::Withdrawal => write!(f, "withdrawal"),
280 LedgerEntryType::Transfer => write!(f, "transfer"),
281 LedgerEntryType::Margin => write!(f, "margin"),
282 LedgerEntryType::Rollover => write!(f, "rollover"),
283 LedgerEntryType::Spend => write!(f, "spend"),
284 LedgerEntryType::Receive => write!(f, "receive"),
285 LedgerEntryType::Settled => write!(f, "settled"),
286 LedgerEntryType::Adjustment => write!(f, "adjustment"),
287 LedgerEntryType::Staking => write!(f, "staking"),
288 LedgerEntryType::Sale => write!(f, "sale"),
289 LedgerEntryType::Dividend => write!(f, "dividend"),
290 LedgerEntryType::NftRebate => write!(f, "nftrebate"),
291 LedgerEntryType::NftTrade => write!(f, "nfttrade"),
292 LedgerEntryType::NftCreatorFee => write!(f, "nftcreatorfee"),
293 LedgerEntryType::CustodyTransfer => write!(f, "custodytransfer"),
294 }
295 }
296}
297
298#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
300pub enum ExportReportStatusType {
301 Queued,
302 Processing,
303 Processed,
304}
305
306impl Display for ExportReportStatusType {
307 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
308 match self {
309 ExportReportStatusType::Queued => write!(f, "Queued"),
310 ExportReportStatusType::Processing => write!(f, "Processing"),
311 ExportReportStatusType::Processed => write!(f, "Processed"),
312 }
313 }
314}
315
316#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
318#[serde(rename_all = "lowercase")]
319pub enum OrderEditStatus {
320 Ok,
321 Err,
322}
323
324#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
329#[serde(untagged)]
330pub enum BoolOrString {
331 Bool(bool),
332 String(String),
333}
334
335#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)]
337#[serde(rename_all = "kebab-case")]
338pub enum StatusProp {
339 CancelPending,
340 Canceled,
341 CancelDenied,
342 Return,
343 #[serde(rename = "onhold")]
344 OnHold,
345}
346
347#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)]
349pub enum TransferStatus {
350 Initial,
351 Pending,
352 Settled,
353 Success,
354 Failure,
355}
356
357#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)]
359#[serde(rename_all = "lowercase")]
360pub enum AccountTransferStatus {
361 Pending,
362 Complete,
363}
364
365#[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
367#[serde(untagged)]
368pub enum EarnFee {
369 Decimal(Decimal),
370 Integer(i64),
371 Float(f64),
372}
373
374#[derive(Debug, Deserialize, PartialEq, Eq, Clone, Copy)]
376#[serde(rename_all = "snake_case")]
377pub enum YieldSourceType {
378 Staking,
379 OffChain,
380 OptInRewards,
381}
382
383#[derive(Debug, Deserialize, PartialEq, Eq, Clone, Copy)]
385#[serde(rename_all = "lowercase")]
386pub enum AutoCompoundType {
387 Enabled,
388 Disabled,
389 Optional,
390}
391
392#[derive(Debug, Deserialize, PartialEq, Eq, Clone, Copy)]
394#[serde(rename_all = "lowercase")]
395pub enum LockType {
396 Flex,
397 Bonded,
398 Instant,
399}
400
401#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Copy)]
403#[serde(rename_all = "lowercase")]
404pub enum AmendType {
405 Original,
406 User,
407 Restated,
408}
409
410#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
412pub struct SystemTime {
413 #[serde(rename = "unixtime")]
414 pub unix_time: i64,
415 pub rfc1123: String,
416}
417
418#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
420pub struct SystemStatusInfo {
421 pub status: SystemStatus,
422 pub timestamp: String,
423}
424
425#[derive(Debug, Deserialize, PartialEq, Clone)]
427pub struct AssetInfo {
428 #[serde(rename = "aclass")]
429 pub asset_class: String,
430 #[serde(rename = "altname")]
431 pub alt_name: String,
432 pub decimals: i64,
433 pub display_decimals: i64,
434 pub collateral_value: Option<f64>,
435 pub status: AssetStatus,
436}
437
438#[derive(Debug, Deserialize_tuple, PartialEq, Clone)]
440pub struct FeeByVolume {
441 pub volume: f64,
442 pub fee: f64,
443}
444
445#[derive(Debug, Deserialize, PartialEq, Clone)]
447pub struct TradableAssetPair {
448 #[serde(rename = "altname")]
449 pub alt_name: String,
450 #[serde(rename = "wsname")]
451 pub ws_name: String,
452 #[serde(rename = "aclass_base")]
453 pub asset_class_base: String,
454 pub base: String,
455 #[serde(rename = "aclass_quote")]
456 pub asset_class_quote: String,
457 pub quote: String,
458 pub lot: String,
459 pub cost_decimals: i64,
460 pub pair_decimals: i64,
461 pub lot_decimals: i64,
462 pub lot_multiplier: i64,
463 pub leverage_buy: Vec<i64>,
464 pub leverage_sell: Vec<i64>,
465 pub fees: Vec<FeeByVolume>,
466 pub fees_maker: Vec<FeeByVolume>,
467 pub fee_volume_currency: String,
468 pub margin_call: i64,
469 pub margin_stop: i64,
470 #[serde(rename = "ordermin")]
471 pub order_min: Decimal,
472 #[serde(rename = "costmin")]
473 pub cost_min: Decimal,
474 pub tick_size: Decimal,
475 pub status: TradableAssetStatus,
476 pub long_position_limit: Option<i64>,
477 pub short_position_limit: Option<i64>,
478}
479
480#[derive(Debug, Deserialize_tuple, PartialEq, Clone)]
482pub struct TickerTrades {
483 pub today: i64,
484 pub last_24_h: i64,
485}
486
487#[derive(Debug, Deserialize_tuple, PartialEq, Clone)]
489pub struct TickerDecimal {
490 pub today: Decimal,
491 pub last_24_h: Decimal,
492}
493
494#[derive(Debug, Deserialize_tuple, PartialEq, Clone)]
498pub struct RestTickerBidAsk {
499 pub price: Decimal,
500 pub whole_lot_volume: Decimal,
501 pub lot_volume: Decimal,
502}
503
504#[derive(Debug, Deserialize_tuple, PartialEq, Clone)]
508pub struct TickerBidAsk {
509 pub price: Decimal,
510 #[serde(deserialize_with = "as_i64")]
511 pub whole_lot_volume: i64,
512 pub lot_volume: Decimal,
513}
514
515#[derive(Debug, Deserialize_tuple, PartialEq, Clone)]
517pub struct LastTrade {
518 pub price: Decimal,
519 pub volume: Decimal,
520}
521
522#[derive(Debug, Deserialize, PartialEq, Clone)]
524pub struct RestTickerInfo {
525 #[serde(rename(deserialize = "a"))]
526 pub asks: TickerBidAsk,
527 #[serde(rename(deserialize = "b"))]
528 pub bids: TickerBidAsk,
529 #[serde(rename(deserialize = "c"))]
530 pub closed: LastTrade,
531 #[serde(rename(deserialize = "v"))]
532 pub volume: TickerDecimal,
533 #[serde(rename(deserialize = "p"))]
534 pub vwap: TickerDecimal,
535 #[serde(rename(deserialize = "t"))]
536 pub trades: TickerTrades,
537 #[serde(rename(deserialize = "l"))]
538 pub low: TickerDecimal,
539 #[serde(rename(deserialize = "h"))]
540 pub high: TickerDecimal,
541 #[serde(rename(deserialize = "o"))]
542 pub open: Decimal,
543}
544
545#[derive(Debug, Deserialize_tuple, PartialEq, Clone)]
547pub struct OHLC {
548 pub time: i64,
549 pub open: Decimal,
550 pub high: Decimal,
551 pub low: Decimal,
552 pub close: Decimal,
553 pub vwap: Decimal,
554 pub volume: Decimal,
555 pub count: i64,
556}
557
558#[derive(Debug, Deserialize, PartialEq, Clone)]
562pub struct OhlcResponse {
563 pub last: i64,
564 #[serde(flatten)]
565 pub ohlc: HashMap<String, Vec<OHLC>>,
566}
567
568#[derive(Debug, Deserialize_tuple, PartialEq, Clone)]
572pub struct BidAsk {
573 pub price: Decimal,
574 pub volume: Decimal,
575 pub time: i64,
576}
577
578#[derive(Debug, Deserialize, PartialEq, Clone)]
580pub struct Orderbook {
581 pub asks: Vec<BidAsk>,
582 pub bids: Vec<BidAsk>,
583}
584
585#[derive(Debug, Deserialize_tuple, PartialEq, Clone)]
589pub struct RecentTrade {
590 pub price: Decimal,
591 pub volume: Decimal,
592 pub time: Decimal,
594 pub buy_sell: BuySellChar,
595 pub market_limit: MarketLimitChar,
596 pub misc: String,
597 pub trade_id: i64,
598}
599
600#[serde_as]
604#[derive(Debug, Deserialize, PartialEq, Clone)]
605pub struct RecentTrades {
606 pub last: String,
607 #[serde(flatten)]
608 pub trades: HashMap<String, Vec<RecentTrade>>,
609}
610
611#[derive(Debug, Deserialize_tuple, PartialEq, Clone)]
613pub struct Spread {
614 pub time: i64,
615 pub bid: Decimal,
616 pub ask: Decimal,
617}
618
619#[derive(Debug, Deserialize, PartialEq, Clone)]
623pub struct RecentSpreads {
624 pub last: i64,
625 #[serde(flatten)]
626 pub spreads: HashMap<String, Vec<Spread>>,
627}
628
629pub type AccountBalances = HashMap<String, Decimal>;
631
632pub type ExtendedBalances = HashMap<String, ExtendedBalance>;
634
635#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
637pub struct ExtendedBalance {
638 pub balance: Decimal,
639 pub hold_trade: Decimal,
640 pub credit: Option<Decimal>,
641 pub credit_used: Option<Decimal>,
642}
643
644#[derive(Debug, Deserialize, PartialEq, Clone)]
646pub struct TradeBalances {
647 #[serde(rename(deserialize = "eb"))]
648 pub equivalent_balance: Decimal,
649 #[serde(rename(deserialize = "tb"))]
650 pub trade_balance: Decimal,
651 #[serde(rename(deserialize = "m"))]
652 pub margin: Decimal,
653 #[serde(rename(deserialize = "n"))]
654 pub net_pnl_open: Decimal,
655 #[serde(rename(deserialize = "c"))]
656 pub cost_basis_open: Decimal,
657 #[serde(rename(deserialize = "v"))]
658 pub floating_valuation: Decimal,
659 #[serde(rename(deserialize = "e"))]
660 pub equity: Decimal,
661 #[serde(rename(deserialize = "mf"))]
662 pub free_margin: Decimal,
663 #[serde(rename(deserialize = "ml"))]
664 pub margin_level: Option<Decimal>,
665 #[serde(rename(deserialize = "uv"))]
666 pub unexecuted_value: Option<Decimal>,
667}
668
669#[derive(Debug, Deserialize, PartialEq, Clone)]
671pub struct OrderDescription {
672 pub pair: String,
673 #[serde(rename(deserialize = "type"))]
674 pub side: BuySell,
675 #[serde(rename(deserialize = "ordertype"))]
676 pub order_type: OrderType,
677 pub price: Decimal,
678 pub price2: Decimal,
679 pub leverage: String,
680 pub order: String,
681 pub close: String,
682}
683
684#[derive(Debug, Deserialize, PartialEq, Clone)]
686pub struct OpenOrders {
687 pub open: HashMap<String, Order>,
688}
689
690#[serde_as]
692#[derive(Debug, Deserialize, PartialEq, Clone)]
693pub struct Order {
694 #[serde(rename = "refid")]
695 pub ref_id: Option<String>,
696 pub userref: Option<i64>,
697 #[serde(rename = "cl_ord_id")]
698 pub client_order_id: Option<String>,
699 pub status: OrderStatus,
700 #[serde(rename = "opentm")]
701 pub open_time: f64,
702 #[serde(rename = "starttm")]
703 pub start_time: f64,
704 #[serde(rename = "expiretm")]
705 pub expire_time: f64,
706 #[serde(rename = "closetm")]
707 pub close_time: Option<f64>,
708 pub descr: OrderDescription,
709 #[serde(rename(deserialize = "vol"))]
710 pub volume: Decimal,
711 #[serde(rename(deserialize = "vol_exec"))]
712 pub volume_executed: Decimal,
713 pub cost: Decimal,
714 pub fee: Decimal,
715 pub price: Decimal,
716 #[serde(rename = "stopprice")]
717 pub stop_price: Decimal,
718 #[serde(rename = "limitprice")]
719 pub limit_price: Decimal,
720 pub trigger: Option<TriggerType>,
721 pub margin: Option<bool>,
722 pub misc: String,
723 pub sender_sub_id: Option<String>,
724 #[serde(rename = "oflags")]
725 #[serde_as(as = "StringWithSeparator::<CommaSeparator, OrderFlag>")]
726 pub order_flags: Vec<OrderFlag>,
727 pub trades: Option<Vec<String>>,
728 pub reason: Option<String>,
729}
730
731#[derive(Debug, Deserialize, PartialEq, Clone)]
733pub struct ClosedOrders {
734 pub closed: HashMap<String, Order>,
735 pub count: i64,
736}
737
738#[derive(Debug, Deserialize, PartialEq, Clone)]
742pub struct Trade {
743 #[serde(rename = "ordertxid")]
744 pub order_tx_id: String,
745 #[serde(rename = "postxid")]
746 pub post_xid: String,
747 pub pair: String,
748 pub time: f64,
749 #[serde(rename(deserialize = "type"))]
750 pub side: BuySell,
751 #[serde(rename = "ordertype")]
752 pub order_type: TradeType,
753 pub price: Decimal,
754 pub cost: Decimal,
755 pub fee: Decimal,
756 #[serde(rename(deserialize = "vol"))]
757 pub volume: Decimal,
758 pub margin: Decimal,
759 pub misc: String,
760 pub ledgers: Option<Vec<String>>,
761 pub trade_id: u64,
762 pub maker: bool,
763}
764
765pub type TradesInfo = HashMap<String, Trade>;
767
768#[derive(Debug, Deserialize, PartialEq, Clone)]
770pub struct TradesHistory {
771 pub trades: TradesInfo,
772 pub count: i64,
773}
774
775#[derive(Debug, Deserialize, PartialEq, Clone)]
776pub struct OrderAmends {
777 pub amends: Vec<OrderAmend>,
778 pub count: u32,
779}
780
781#[derive(Debug, Deserialize, PartialEq, Clone)]
782pub struct OrderAmend {
783 pub amend_id: String,
784 pub amend_type: AmendType,
785 #[serde(rename = "order_qty")]
786 pub order_quantity: Decimal,
787 #[serde(rename = "display_qty")]
788 pub display_quantity: Option<Decimal>,
789 #[serde(rename = "remaining_qty")]
790 pub remaining_quantity: Decimal,
791 pub limit_price: Decimal,
792 pub trigger_price: Option<Decimal>,
793 pub reason: Option<String>,
794 pub post_only: bool,
795 pub timestamp: u64,
796}
797
798pub type OpenPositions = HashMap<String, OpenPosition>;
800
801#[serde_as]
803#[derive(Debug, Deserialize, PartialEq, Clone)]
804pub struct OpenPosition {
805 #[serde(rename = "ordertxid")]
806 pub order_tx_id: String,
807 #[serde(rename = "posstatus")]
808 pub pos_status: PositionStatus,
809 pub pair: String,
810 pub time: f64,
811 #[serde(rename(deserialize = "type"))]
812 pub side: BuySell,
813 #[serde(rename = "ordertype")]
814 pub order_type: OrderType,
815 pub cost: Decimal,
816 pub fee: Decimal,
817 #[serde(rename(deserialize = "vol"))]
818 pub volume: Decimal,
819 #[serde(rename(deserialize = "vol_closed"))]
820 pub volume_closed: Decimal,
821 pub margin: Decimal,
822 pub value: Option<Decimal>,
823 pub net: Option<Decimal>,
824 pub terms: String,
825 #[serde(rename = "rollovertm")]
826 pub rollover_time: String,
827 pub misc: String,
828 #[serde(rename = "oflags")]
829 #[serde_as(as = "StringWithSeparator::<CommaSeparator, OrderFlag>")]
830 pub order_flags: Vec<OrderFlag>,
831}
832
833#[derive(Debug, Deserialize, PartialEq, Clone)]
835pub struct LedgerEntry {
836 #[serde(rename = "refid")]
837 pub ref_id: String,
838 pub time: f64,
839 #[serde(rename(deserialize = "type"))]
840 pub entry_type: LedgerEntryType,
841 pub subtype: String,
842 #[serde(rename = "aclass")]
843 pub asset_class: String,
844 pub asset: String,
845 pub amount: Decimal,
846 pub fee: Decimal,
847 pub balance: Decimal,
848}
849
850pub type QueryLedgerInfo = HashMap<String, LedgerEntry>;
852
853#[derive(Debug, Deserialize, PartialEq, Clone)]
855pub struct LedgerInfo {
856 pub ledger: QueryLedgerInfo,
857 pub count: i64,
858}
859
860#[derive(Debug, Deserialize, PartialEq, Clone)]
862pub struct Fees {
863 pub fee: Decimal,
864 #[serde(rename = "minfee")]
865 pub min_fee: Decimal,
866 #[serde(rename = "maxfee")]
867 pub max_fee: Decimal,
868 #[serde(rename = "nextfee")]
869 pub next_fee: Option<Decimal>,
870 #[serde(rename = "nextvolume")]
871 pub next_volume: Option<Decimal>,
872 #[serde(rename = "tiervolume")]
873 pub tier_volume: Option<Decimal>,
874}
875
876#[derive(Debug, Deserialize, PartialEq, Clone)]
881pub struct TradeVolume {
882 pub currency: String,
883 pub volume: Decimal,
884 pub fees: Option<HashMap<String, Fees>>,
885 pub fees_maker: Option<HashMap<String, Fees>>,
886}
887
888#[derive(Debug, Deserialize, PartialEq, Clone)]
890pub struct ExportReport {
891 pub id: String,
892}
893
894#[derive(Debug, Deserialize, PartialEq, Clone)]
896pub struct ExportReportStatus {
897 pub id: String,
898 pub descr: String,
899 pub format: String,
900 pub report: String,
901 pub subtype: String,
902 pub status: ExportReportStatusType,
903 pub fields: String,
904 #[serde(rename = "createdtm")]
905 pub created_time: String,
906 #[serde(rename = "starttm")]
907 pub start_time: String,
908 #[serde(rename = "completedtm")]
909 pub completed_time: String,
910 #[serde(rename = "datastarttm")]
911 pub data_start_time: String,
912 #[serde(rename = "dataendtm")]
913 pub data_end_time: String,
914 pub asset: String,
915}
916
917#[derive(Debug, Deserialize, PartialEq, Clone)]
919pub struct DeleteExportReport {
920 pub delete: Option<bool>,
921 pub cancel: Option<bool>,
922}
923
924#[derive(Debug, Deserialize, PartialEq, Clone)]
928pub struct AddOrderDescription {
929 pub order: String,
930 pub close: Option<String>,
931}
932
933#[derive(Debug, Deserialize, PartialEq, Clone)]
935pub struct AddOrder {
936 #[serde(rename = "txid")]
937 pub tx_id: Vec<String>,
938 pub descr: AddOrderDescription,
939 pub error: Option<String>,
940}
941
942#[derive(Debug, Deserialize, PartialEq, Clone)]
944pub struct BatchedOrder {
945 #[serde(rename = "txid")]
946 pub tx_id: String,
947 pub descr: AddOrderDescription,
948 pub error: Option<String>,
949}
950
951#[derive(Debug, Deserialize, PartialEq, Clone)]
953pub struct AddOrderBatch {
954 pub orders: Vec<BatchedOrder>,
955}
956
957#[derive(Debug, Deserialize, PartialEq, Clone)]
958pub struct AmendOrder {
959 pub amend_id: String,
960}
961
962#[derive(Debug, Deserialize, PartialEq, Clone)]
964pub struct OrderEdit {
965 pub status: OrderEditStatus,
966 #[serde(rename = "txid")]
967 pub tx_id: String,
968 #[serde(rename = "originaltxid")]
969 pub original_tx_id: String,
970 pub volume: Decimal,
971 pub price: Decimal,
972 pub price2: Option<Decimal>,
973 pub orders_cancelled: i64,
974 pub descr: AddOrderDescription,
975}
976
977#[derive(Debug, Deserialize, PartialEq, Clone)]
979pub struct CancelOrder {
980 pub count: i64,
981 pub pending: Option<bool>,
982}
983
984#[derive(Debug, Deserialize, PartialEq, Clone)]
986#[serde(rename_all = "camelCase")]
987pub struct CancelAllOrdersAfter {
988 pub current_time: String,
989 pub trigger_time: String,
990}
991
992#[derive(Debug, Deserialize, PartialEq, Clone)]
994#[serde(rename_all = "kebab-case")]
995pub struct DepositMethod {
996 pub method: String,
997 pub limit: BoolOrString,
998 pub fee: Option<Decimal>,
999 pub address_setup_fee: Option<Decimal>,
1000 pub gen_address: Option<bool>,
1001 pub minimum: Decimal,
1002}
1003
1004#[derive(Debug, Deserialize, PartialEq, Clone)]
1006pub struct WithdrawMethod {
1007 pub asset: String,
1008 pub method: String,
1009 pub network: Option<String>,
1010 pub minimum: Decimal,
1011}
1012
1013#[derive(Debug, Deserialize, PartialEq, Clone)]
1015pub struct DepositAddress {
1016 pub address: String,
1017 #[serde(rename = "expiretm")]
1018 pub expire_time: String,
1019 pub new: Option<bool>,
1020 pub memo: Option<String>,
1021 pub tag: Option<String>,
1022}
1023
1024#[derive(Debug, Deserialize, PartialEq, Clone)]
1026pub struct WithdrawalAddress {
1027 pub address: String,
1028 pub asset: String,
1029 pub method: String,
1030 pub key: String,
1031 pub memo: Option<String>,
1032 pub verified: bool,
1033}
1034
1035#[derive(Debug, Deserialize, PartialEq, Clone)]
1039#[serde(untagged)]
1040pub enum DepositWithdrawResponse {
1041 Cursor(DepositWithdrawalCursor),
1042 Response(Vec<DepositWithdrawal>),
1043}
1044
1045#[derive(Debug, Deserialize, PartialEq, Clone)]
1047pub struct DepositWithdrawalCursor {
1048 deposit: Vec<DepositWithdrawal>,
1049 cursor: BoolOrString,
1050}
1051
1052#[derive(Debug, Deserialize, PartialEq, Clone)]
1054pub struct DepositWithdrawal {
1055 pub method: String,
1056 #[serde(rename = "aclass")]
1057 pub asset_class: String,
1058 pub asset: String,
1059 #[serde(rename = "refid")]
1060 pub ref_id: String,
1061 #[serde(rename = "txid")]
1062 pub tx_id: String,
1063 pub info: String,
1064 pub amount: Decimal,
1065 pub fee: Decimal,
1066 pub time: i64,
1067 pub status: TransferStatus,
1068 #[serde(rename = "status-prop")]
1069 pub status_prop: Option<StatusProp>,
1070 pub orginators: Option<Vec<String>>,
1071}
1072
1073#[derive(Debug, Deserialize, PartialEq, Clone)]
1075pub struct Withdrawal {
1076 pub method: String,
1077 pub limit: BoolOrString,
1078 pub fee: Decimal,
1079 pub amount: Decimal,
1080}
1081
1082#[derive(Debug, Deserialize, PartialEq, Clone)]
1084pub struct ConfirmationRefId {
1085 #[serde(rename = "refid")]
1086 pub ref_id: String,
1087}
1088
1089#[derive(Debug, Deserialize, PartialEq, Clone)]
1091pub struct AccountTransfer {
1092 pub transfer_id: String,
1093 pub status: AccountTransferStatus,
1094}
1095
1096#[derive(Debug, Deserialize, PartialEq, Clone)]
1098pub struct AllocationStatus {
1099 pub pending: bool,
1100}
1101
1102#[derive(Debug, Deserialize, PartialEq, Clone)]
1104pub struct EarnStrategies {
1105 pub items: Vec<EarnStrategy>,
1106 pub next_cursor: Option<String>,
1107}
1108
1109#[derive(Debug, Deserialize, PartialEq, Clone)]
1111pub struct EarnStrategy {
1112 pub allocation_fee: EarnFee,
1113 pub allocation_restriction_info: Vec<String>,
1114 pub apr_estimate: Option<AprEstimate>,
1115 pub asset: String,
1116 pub auto_compound: AutoCompound,
1117 pub can_allocate: bool,
1118 pub can_deallocate: bool,
1119 pub deallocation_fee: EarnFee,
1120 pub id: String,
1121 pub lock_type: LockTypeDetail,
1122 pub user_cap: Option<Decimal>,
1123 pub user_min_allocation: Option<Decimal>,
1124 pub yield_source: YieldSource,
1125}
1126
1127#[derive(Debug, Deserialize, PartialEq, Clone)]
1129pub struct LockTypeDetail {
1130 #[serde(rename = "type")]
1131 pub lock_type: LockType,
1132 #[serde(flatten)]
1133 pub bonding: Option<BondingDetail>,
1134}
1135
1136#[derive(Debug, Deserialize, PartialEq, Clone)]
1138pub struct BondingDetail {
1139 pub payout_frequency: Option<i64>,
1140 pub bonding_period: Option<i64>,
1141 pub bonding_period_variable: Option<bool>,
1142 pub bonding_rewards: Option<bool>,
1143 pub exit_queue_period: Option<i64>,
1144 pub unbonding_period: Option<i64>,
1145 pub unbonding_period_variable: Option<bool>,
1146 pub unbonding_rewards: Option<bool>,
1147}
1148
1149#[derive(Debug, Deserialize, PartialEq, Clone)]
1151pub struct AprEstimate {
1152 pub low: Decimal,
1153 pub high: Decimal,
1154}
1155
1156#[derive(Debug, Deserialize, PartialEq, Clone)]
1158pub struct AutoCompound {
1159 #[serde(rename = "type")]
1160 pub auto_compound_type: AutoCompoundType,
1161 pub default: Option<bool>,
1162}
1163
1164#[derive(Debug, Deserialize, PartialEq, Clone)]
1166pub struct YieldSource {
1167 #[serde(rename = "type")]
1168 pub yield_type: YieldSourceType,
1169}
1170
1171#[derive(Debug, Deserialize, PartialEq, Clone)]
1173pub struct EarnAllocations {
1174 pub converted_asset: String,
1175 pub items: Vec<EarnAllocation>,
1176 pub total_allocated: Decimal,
1177 pub total_rewarded: Decimal,
1178}
1179
1180#[derive(Debug, Deserialize, PartialEq, Clone)]
1182pub struct EarnAllocation {
1183 pub amount_allocated: AmountAllocated,
1184 pub native_asset: String,
1185 pub payout: Option<Payout>,
1186 pub strategy_id: String,
1187 pub total_rewarded: EarnAmount,
1188}
1189
1190#[derive(Debug, Deserialize, PartialEq, Clone)]
1192pub struct AmountAllocated {
1193 pub bonding: Option<AllocationState>,
1194 pub exit_queue: Option<AllocationState>,
1195 pub pending: Option<EarnAmount>,
1196 pub total: EarnAmount,
1197 pub unbonding: Option<AllocationState>,
1198}
1199
1200#[derive(Debug, Deserialize, PartialEq, Clone)]
1202pub struct AllocationState {
1203 pub allocation_count: i64,
1204 pub allocations: Vec<Allocation>,
1205 pub converted: Decimal,
1206 pub native: Decimal,
1207}
1208
1209#[derive(Debug, Deserialize, PartialEq, Clone)]
1211pub struct Allocation {
1212 pub created_at: String,
1213 pub expires: String,
1214 pub converted: Decimal,
1215 pub native: Decimal,
1216}
1217
1218#[derive(Debug, Deserialize, PartialEq, Clone)]
1220pub struct Payout {
1221 pub period_end: String,
1222 pub period_start: String,
1223 pub accumulated_reward: EarnAmount,
1224 pub estimated_reward: EarnAmount,
1225}
1226
1227#[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
1229pub struct EarnAmount {
1230 pub converted: Decimal,
1231 pub native: Decimal,
1232}
1233
1234#[derive(Debug, Deserialize, Clone)]
1236pub struct WebsocketToken {
1237 pub token: Token,
1238 pub expires: i64,
1239}
1240
1241#[cfg(test)]
1242mod tests {
1243 use crate::response_types::ExtendedBalance;
1244 use rust_decimal_macros::dec;
1245
1246 #[test]
1247 fn test_deserializing_extended_balance_full() {
1248 let balance =
1249 r#"{"balance": "0.01", "hold_trade": "0.02", "credit": "0.03", "credit_used": "0.04"}"#;
1250
1251 let expected_balance = ExtendedBalance {
1252 balance: dec!(0.01),
1253 hold_trade: dec!(0.02),
1254 credit: Some(dec!(0.03)),
1255 credit_used: Some(dec!(0.04)),
1256 };
1257
1258 assert_eq!(expected_balance, serde_json::from_str(balance).unwrap());
1259 }
1260
1261 #[test]
1262 fn test_deserializing_extended_balance_some_none() {
1263 let balance_missing = r#"{"balance": "0.01", "hold_trade": "0.02"}"#;
1264
1265 let expected_balance = ExtendedBalance {
1266 balance: dec!(0.01),
1267 hold_trade: dec!(0.02),
1268 credit: None,
1269 credit_used: None,
1270 };
1271
1272 assert_eq!(
1273 expected_balance,
1274 serde_json::from_str(balance_missing).unwrap()
1275 );
1276 }
1277
1278 #[test]
1279 fn test_deserializing_extended_balance_some_gibberish() {
1280 let gibberish = r#"{"balance": "0.01", "hold_trade": "0.02", "credit": "soNotANumber"}"#;
1281
1282 assert!(serde_json::from_str::<ExtendedBalance>(gibberish).is_err())
1283 }
1284}