use std::collections::HashMap;
use std::hash::Hash;
use std::cmp::{Eq, PartialEq};
use std::fmt;
extern crate reqwest;
const URL: &str = "https://rest.coinapi.io/v1/exchangerate";
#[derive(Clone, Hash, Debug, PartialEq, Eq)]
pub enum Coins {
BTC,
BCH,
ETH,
XMR,
NANO,
DOGE,
CUSTOM(String),
}
impl<'a> fmt::Display for Coins {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", match self {
Self::CUSTOM(x) => x.clone(),
x => {
format!("{:?}", x)
}
})
}
}
#[derive(Clone, Hash, Debug, PartialEq, Eq)]
pub enum Currencies {
USD,
EUR,
CUSTOM(String),
}
impl fmt::Display for Currencies {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", match self {
Self::CUSTOM(x) => x.clone(),
x => {
format!("{:?}", x)
}
})
}
}
type CoinReturn = Result<f32, String>;
pub struct CoinApi {
key: String,
client: reqwest::blocking::Client,
}
impl CoinApi {
pub fn new(key: String) -> Self {
Self {
key,
client: reqwest::blocking::Client::new(),
}
}
pub fn get(&mut self, coin: Coins, currency: Currencies) -> CoinReturn {
self.internal_get(coin, currency)
}
fn internal_get(&self, coin: Coins, currency: Currencies) -> CoinReturn {
self.request_exchange(format!("{}", coin), format!("{}", currency))
}
fn request_exchange(&self, coin: String, currency: String) -> CoinReturn {
let response = self.client.get(format!("{}/{}/{}", URL, coin, currency))
.header("X-CoinAPI-Key", self.key.clone())
.send().unwrap()
.json::<HashMap<String, String>>().unwrap();
match response.get(&"rate".to_string()) {
Some(x) => Ok(x.parse::<f32>().unwrap_or(0.0)),
None => {
match response.get("error") {
Some(x) => Err(x.clone()),
None => Err("Neither Error nor Rate found.".to_string())
}
}
}
}
}