switchboard_utils/exchanges/
mod.rs1pub mod binance;
5pub use binance::BinanceApi;
6
7pub mod bitfinex;
8pub use bitfinex::BitfinexApi;
9
10pub mod coinbase;
11pub use coinbase::CoinbaseApi;
12
13pub mod huobi;
14pub use huobi::HuobiApi;
15
16pub mod kraken;
17pub use kraken::KrakenApi;
18
19use serde::Deserialize;
25use serde::Deserializer;
26
27pub use reqwest;
28use std::hash::Hash;
29
30#[allow(non_snake_case)]
31#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)]
32pub struct Pair {
33 pub base: String,
34 pub quote: String,
35}
36impl Pair {
37 pub fn from_string(mut s: String) -> Self {
38 s = s.to_uppercase();
39 let parts: Vec<String> = s
40 .split(|c| c == '-' || c == '/' || c == '_' || c == ':')
41 .map(|x| x.to_string())
42 .collect();
43 if parts.len() == 2 {
44 return Pair {
45 base: parts[0].to_string(),
46 quote: parts[1].to_string(),
47 };
48 }
49 let suffixes = ["USDC", "USDT"];
50 if parts.len() == 1 {
51 let ends_with_any = suffixes.iter().any(|&suffix| s.ends_with(suffix));
52 if ends_with_any {
53 let quote = s.split_off(s.len() - 4);
54 return Pair {
55 base: s.clone(),
56 quote: quote.clone(),
57 };
58 } else {
59 let quote = s.split_off(s.len() - 3);
60 return Pair {
61 base: s.clone(),
62 quote: quote.clone(),
63 };
64 }
65 }
66
67 if parts.len() != 2 {
68 return Pair {
69 base: s.clone(),
70 quote: "".to_string(),
71 };
72 }
73
74 Pair {
75 base: parts[0].to_string(),
76 quote: parts[1].to_string(),
77 }
78 }
79}
80impl<'de> Deserialize<'de> for Pair {
81 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
82 where
83 D: Deserializer<'de>,
84 {
85 let s = String::deserialize(deserializer)?;
86 Ok(Pair::from_string(s))
87 }
88}
89impl From<String> for Pair {
90 fn from(s: String) -> Self {
91 Pair::from_string(s)
92 }
93}
94impl From<&str> for Pair {
95 fn from(s: &str) -> Self {
96 Pair::from_string(s.to_string())
97 }
98}