switchboard_utils/exchanges/
mod.rs

1// use crate::*;
2
3// use rust_decimal::Decimal;
4pub 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
19// Idk if this is worth it, each exchange returns their own struct type
20// pub trait ExchangeApi {
21//     fn fetch_ticker(ticker: &str) -> Result<Decimal, SbError>;
22// }
23
24use 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}