three_commas_types/
account.rs

1use chrono::{DateTime, Utc};
2use rust_decimal::Decimal;
3use serde::{de, Deserialize, Serialize};
4use std::{cmp::Ordering, fmt};
5
6#[derive(Debug, Deserialize, Clone)]
7pub struct Account {
8  pub id: AccountId,
9  pub auto_balance_period: u32,
10  pub auto_balance_portfolio_id: Option<u32>,
11  pub auto_balance_currency_change_limit: Option<u32>,
12  pub autobalance_enabled: bool,
13  pub hedge_mode_available: bool,
14  pub hedge_mode_enabled: bool,
15  pub is_locked: bool,
16  pub smart_trading_supported: bool,
17  // pub available_for_trading: bool,
18  pub stats_supported: bool,
19  pub trading_supported: bool,
20  pub market_buy_supported: bool,
21  pub market_sell_supported: bool,
22  pub conditional_buy_supported: bool,
23  pub bots_allowed: bool,
24  pub bots_ttp_allowed: bool,
25  pub bots_tsl_allowed: bool,
26  pub gordon_bots_available: bool,
27  pub multi_bots_allowed: bool,
28  pub created_at: Option<DateTime<Utc>>,
29  pub updated_at: Option<DateTime<Utc>>,
30  pub last_auto_balance: Option<DateTime<Utc>>,
31  /// Sell all to USD/BTC possibility
32  pub fast_convert_available: bool,
33  pub grid_bots_allowed: bool,
34  pub api_key_invalid: bool,
35  pub deposit_enabled: bool,
36  pub supported_market_types: Vec<String>,
37  pub api_key: Option<String>,
38  pub name: String,
39  pub auto_balance_method: Option<AutoBalanceMethod>,
40  pub auto_balance_error: Option<String>,
41  pub customer_id: Option<String>,
42  pub subaccount_name: Option<String>,
43  pub lock_reason: Option<String>,
44  pub btc_amount: Decimal,
45  pub usd_amount: Decimal,
46  pub day_profit_btc: Decimal,
47  pub day_profit_usd: Decimal,
48  pub day_profit_btc_percentage: Decimal,
49  pub day_profit_usd_percentage: Decimal,
50  /// Month period
51  pub btc_profit: Decimal,
52  /// Month period
53  pub usd_profit: Decimal,
54  /// Month period
55  pub usd_profit_percentage: Decimal,
56  /// Month period
57  pub btc_profit_percentage: Decimal,
58  pub total_btc_profit: Decimal,
59  pub total_usd_profit: Decimal,
60  pub pretty_display_type: String,
61  pub exchange_name: String,
62  pub market_code: String,
63  pub address: Option<String>,
64}
65
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
67pub enum AccountId {
68  Summary,
69
70  AccountId(u32),
71}
72
73#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
74pub enum AutoBalanceMethod {
75  #[serde(rename = "time")]
76  Time,
77
78  #[serde(rename = "currency_change")]
79  CurrencyChange,
80}
81
82#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
83pub enum MarketType {
84  #[serde(rename = "spot")]
85  Spot,
86
87  #[serde(rename = "futures")]
88  Futures,
89}
90
91impl PartialOrd for AccountId {
92  #[inline]
93  fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
94    Some(self.cmp(other))
95  }
96}
97
98impl Ord for AccountId {
99  fn cmp(&self, other: &Self) -> Ordering {
100    match (self, other) {
101      (AccountId::Summary, AccountId::Summary) => Ordering::Equal,
102      (AccountId::Summary, _) => Ordering::Less,
103      (_, AccountId::Summary) => Ordering::Greater,
104      (AccountId::AccountId(l), AccountId::AccountId(r)) => Ord::cmp(l, r),
105    }
106  }
107}
108
109impl fmt::Display for AccountId {
110  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111    match self {
112      Self::Summary => f.write_str("summary"),
113      Self::AccountId(id) => fmt::Display::fmt(id, f),
114    }
115  }
116}
117
118impl Serialize for AccountId {
119  #[inline]
120  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
121  where
122    S: serde::Serializer,
123  {
124    match self {
125      Self::Summary => serializer.serialize_str("summary"),
126      Self::AccountId(id) => id.serialize(serializer),
127    }
128  }
129}
130
131struct AccountIdVisitor;
132impl<'de> de::Visitor<'de> for AccountIdVisitor {
133  type Value = AccountId;
134
135  fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
136    formatter.write_str("account id string or number")
137  }
138
139  fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
140  where
141    E: de::Error,
142  {
143    match v {
144      "summary" => Ok(AccountId::Summary),
145      _ => Err(E::invalid_value(de::Unexpected::Str(v), &self)),
146    }
147  }
148
149  fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
150  where
151    E: de::Error,
152  {
153    match u32::try_from(v) {
154      Ok(v) => self.visit_u32(v),
155      Err(_) => Err(E::invalid_value(de::Unexpected::Unsigned(v), &self)),
156    }
157  }
158
159  fn visit_u32<E>(self, v: u32) -> Result<Self::Value, E>
160  where
161    E: de::Error,
162  {
163    Ok(AccountId::AccountId(v))
164  }
165
166  fn visit_i32<E>(self, v: i32) -> Result<Self::Value, E>
167  where
168    E: de::Error,
169  {
170    match u32::try_from(v) {
171      Ok(v) => self.visit_u32(v),
172      Err(_) => Err(E::invalid_value(de::Unexpected::Signed(v as i64), &self)),
173    }
174  }
175
176  fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
177  where
178    E: de::Error,
179  {
180    match u32::try_from(v) {
181      Ok(v) => self.visit_u32(v),
182      Err(_) => Err(E::invalid_value(de::Unexpected::Signed(v), &self)),
183    }
184  }
185}
186
187impl<'de> Deserialize<'de> for AccountId {
188  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
189  where
190    D: serde::Deserializer<'de>,
191  {
192    deserializer.deserialize_any(AccountIdVisitor)
193  }
194}
195
196#[cfg(test)]
197mod tests {
198  use super::*;
199
200  #[test]
201  fn account_id_ord() {
202    assert!(AccountId::Summary < AccountId::AccountId(0));
203    assert!(AccountId::AccountId(0) > AccountId::Summary);
204    assert!(AccountId::AccountId(1) > AccountId::AccountId(0));
205  }
206}