<commit_before>//! Use this module to interact with Poloniex exchange.
//! See examples for more informations.

use hmac::{Hmac, Mac};
use sha2::{Sha512};

use hyper_native_tls::NativeTlsClient;
use hyper::Client;
use hyper::header;
use hyper::net::HttpsConnector;

use data_encoding::HEXLOWER;

use serde_json::Value;
use serde_json::value::Map;

use std::collections::HashMap;
use std::io::Read;
use std::thread;
use std::time::Duration;

use error::*;
use helpers;

use exchange::Exchange;
use coinnect::Credentials;
use poloniex::utils;

header! {
    #[doc(hidden)]
    (KeyHeader, "Key") => [String]
}

header! {
    #[doc(hidden)]
    (SignHeader, "Sign") => [String]
}

header! {
    #[doc(hidden)]
    (ContentHeader, "Content-Type") => [String]
}

#[derive(Debug)]
pub struct PoloniexApi {
    last_request: i64, // unix timestamp in ms, to avoid ban
    api_key: String,
    api_secret: String,
    http_client: Client,
}


impl PoloniexApi {
    /// Create a new PoloniexApi by providing an API key & API secret
    pub fn new<C: Credentials>(creds: C) -> Result<PoloniexApi> {
        if creds.exchange() != Exchange::Poloniex {
            return Err(ErrorKind::InvalidConfigType(Exchange::Poloniex, creds.exchange()).into());
        }

        //TODO: Handle correctly the TLS errors with error_chain.
        let ssl = match NativeTlsClient::new() {
            Ok(res) => res,
            Err(_) => return Err(ErrorKind::TlsError.into()),
        };
        let connector = HttpsConnector::new(ssl);

        Ok(PoloniexApi {
               last_request: 0,
               api_key: creds.get("api_key").unwrap_or_default(),
               api_secret: creds.get("api_secret").unwrap_or_default(),
               http_client: Client::with_connector(connector),
           })
    }

    fn block_or_continue(&self) {
        let threshold = 167; // 6 requests/sec = 1/6*1000
        let delay = helpers::get_unix_timestamp_ms() - self.last_request;
        if delay < threshold {
            let duration_ms = Duration::from_millis(delay as u64);
            thread::sleep(duration_ms);
        }
    }

    fn public_query(&mut self,
                    method: &str,
                    params: &HashMap<&str, &str>)
                    -> Result<Map<String, Value>> {
        let mut params = params.clone();
        helpers::strip_empties(&mut params);
        let url = "https://poloniex.com/public?command=".to_string() + method + "&" +<commit_msg>Fix `block_or_continue` bug for Poloniex.<commit_after>//! Use this module to interact with Poloniex exchange.
//! See examples for more informations.

use hmac::{Hmac, Mac};
use sha2::{Sha512};

use hyper_native_tls::NativeTlsClient;
use hyper::Client;
use hyper::header;
use hyper::net::HttpsConnector;

use data_encoding::HEXLOWER;

use serde_json::Value;
use serde_json::value::Map;

use std::collections::HashMap;
use std::io::Read;
use std::thread;
use std::time::Duration;

use error::*;
use helpers;

use exchange::Exchange;
use coinnect::Credentials;
use poloniex::utils;

header! {
    #[doc(hidden)]
    (KeyHeader, "Key") => [String]
}

header! {
    #[doc(hidden)]
    (SignHeader, "Sign") => [String]
}

header! {
    #[doc(hidden)]
    (ContentHeader, "Content-Type") => [String]
}

#[derive(Debug)]
pub struct PoloniexApi {
    last_request: i64, // unix timestamp in ms, to avoid ban
    api_key: String,
    api_secret: String,
    http_client: Client,
}


impl PoloniexApi {
    /// Create a new PoloniexApi by providing an API key & API secret
    pub fn new<C: Credentials>(creds: C) -> Result<PoloniexApi> {
        if creds.exchange() != Exchange::Poloniex {
            return Err(ErrorKind::InvalidConfigType(Exchange::Poloniex, creds.exchange()).into());
        }

        //TODO: Handle correctly the TLS errors with error_chain.
        let ssl = match NativeTlsClient::new() {
            Ok(res) => res,
            Err(_) => return Err(ErrorKind::TlsError.into()),
        };
        let connector = HttpsConnector::new(ssl);

        Ok(PoloniexApi {
               last_request: 0,
               api_key: creds.get("api_key").unwrap_or_default(),
               api_secret: creds.get("api_secret").unwrap_or_default(),
               http_client: Client::with_connector(connector),
           })
    }

    fn block_or_continue(&self) {
        let threshold: u64 = 167; // 6 requests/sec = 1/6*1000
        let offset: u64 = helpers::get_unix_timestamp_ms() as u64 - self.last_request as u64;
        if offset < threshold {
            let wait_ms = Duration::from_millis(threshold - offset);
            thread::sleep(wait_ms);
        }
    }

    fn public_query(&mut self,
                    method: &str,
                    params: &HashMap<&str, &str>)
                    -> Result<Map<String, Value>> {
        let mut params = params.clone();
        helpers::strip_empties(&mut params);
        let url = "https://poloniex.com/public?command=".to_string() + method + "&" +
{'fraction_non_alphanumeric': 0.13947895791583168, 'fraction_numerical': 0.008817635270541082, 'mean_word_length': 2.807017543859649, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 27, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '615814', 'n_tokens_mistral': 1623, 'n_tokens_neox': 1602, 'n_words': 369}