use hyper_native_tls::NativeTlsClient;
use hyper::Client;
use hyper::header::ContentType;
use hyper::net::HttpsConnector;
use serde_json;
use serde_json::Value;
use serde_json::value::Map;
use std::collections::HashMap;
use std::io::Read;
use std::path::PathBuf;
use std::fs::File;
use helpers;
use bitstamp::utils;
use error::Error;
use exchange::ExchangeApi;
use pair::Pair;
use types::Ticker;
header! {
#[doc(hidden)]
(KeyHeader, "Key") => [String]
}
header! {
#[doc(hidden)]
(SignHeader, "Sign") => [String]
}
header! {
#[doc(hidden)]
(ContentHeader, "Content-Type") => [String]
}
#[derive(Debug)]
pub struct BitstampApi {
last_request: i64, api_key: String,
api_secret: String,
customer_id: String,
http_client: Client,
}
impl BitstampApi {
pub fn new(params: &HashMap<&str, &str>) -> BitstampApi {
let mut params = params.clone();
helpers::strip_empties(&mut params);
let empty_str: &str = "";
let api_key = params.get("api_key").unwrap_or(&empty_str);
let api_secret = params.get("api_secret").unwrap_or(&empty_str);
let customer_id = params.get("customer_id").unwrap_or(&empty_str);
let ssl = NativeTlsClient::new().unwrap();
let connector = HttpsConnector::new(ssl);
BitstampApi {
last_request: 0,
api_key: api_key.to_string(),
api_secret: api_secret.to_string(),
customer_id: customer_id.to_string(),
http_client: Client::with_connector(connector),
}
}
pub fn new_from_file(config_name: &str, path: PathBuf) -> BitstampApi {
let mut f = File::open(&path).unwrap();
let mut buffer = String::new();
f.read_to_string(&mut buffer).unwrap();
let data: Value = serde_json::from_str(&buffer).unwrap();
let json_obj = data.as_object().unwrap().get(config_name).unwrap();
let api_key = json_obj.get("api_key").unwrap().as_str().unwrap();
let api_secret = json_obj.get("api_secret").unwrap().as_str().unwrap();
let customer_id = json_obj.get("customer_id").unwrap().as_str().unwrap();
let mut params = HashMap::new();
params.insert("api_key", api_key);
params.insert("api_secret", api_secret);
params.insert("customer_id", customer_id);
BitstampApi::new(¶ms)
}
fn public_query(&mut self,
params: &HashMap<&str, &str>)
-> Option<Map<String, Value>> {
let method: &str = params.get("method").unwrap();
let pair: &str = params.get("pair").unwrap();
let url: String = utils::build_url(method, pair);
utils::block_or_continue(self.last_request);
let mut response = self.http_client.get(&url).send().unwrap();
self.last_request = helpers::get_unix_timestamp_ms();
let mut buffer = String::new();
response.read_to_string(&mut buffer).unwrap();
return utils::deserialize_json(buffer);
}
fn private_query(&mut self,
params: &HashMap<&str, &str>)
-> Option<Map<String, Value>> {
let method: &str = params.get("method").unwrap();
let pair: &str = params.get("pair").unwrap();
let url: String = utils::build_url(method, pair);
let nonce = utils::generate_nonce(None);
let signature = utils::build_signature(nonce.clone(),
self.customer_id.clone(),
self.api_key.clone(),
self.api_secret.clone());
let copy_api_key = self.api_key.clone();
let mut post_params: &mut HashMap<&str, &str> = &mut HashMap::new();
post_params.insert("key", ©_api_key);
post_params.insert("signature", &signature);
post_params.insert("nonce", &nonce);
helpers::strip_empties(&mut post_params);
let post_data = helpers::url_encode_hashmap(&post_params);
let mut response = self.http_client.post(&url)
.header(ContentType::form_url_encoded())
.body(&post_data)
.send()
.unwrap();
let mut buffer = String::new();
response.read_to_string(&mut buffer).unwrap();
utils::deserialize_json(buffer)
}
}
impl ExchangeApi for BitstampApi {
fn ticker(&mut self, pair: Pair) -> Result<Ticker, Error> {
let currency_pair = match pair {
Pair::BTC_USD => "btcusd",
_ => panic!("Unknown pair"),
};
let mut params = HashMap::new();
params.insert("pair", currency_pair);
params.insert("method", "ticker");
self.public_query(¶ms);
panic!("Request was sent but no func to translate to a TickerInfo was written yet :)");
}
fn return_order_book(&mut self, pair: Pair) -> Option<Map<String, Value>> {
let currency_pair = match pair {
Pair::BTC_USD => "btcusd",
_ => panic!("Unknown pair"),
};
let mut params = HashMap::new();
params.insert("method", "order_book");
params.insert("pair", currency_pair);
self.public_query(¶ms)
}
fn return_trade_history(&mut self, pair: Pair) -> Option<Map<String, Value>> {
let currency_pair = match pair {
Pair::BTC_USD => "btcusd",
_ => panic!("Unknown pair"),
};
let mut params = HashMap::new();
params.insert("pair", currency_pair);
params.insert("method", "transactions");
self.public_query(¶ms)
}
fn return_balances(&mut self, pair: Pair) -> Option<Map<String, Value>> {
let currency_pair = match pair {
Pair::BTC_USD => "btcusd",
_ => panic!("Unknown pair"),
};
let mut params = HashMap::new();
params.insert("method", "balance");
params.insert("pair", currency_pair);
self.private_query(¶ms)
}
}