Last active
December 18, 2019 07:06
-
-
Save ggomagundan/5134d29e7ee37cc7aa568c347ade3c88 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "poloniex" | |
version = "0.1.0" | |
authors = ["Kai <ggogun@gmail.com>"] | |
edition = "2018" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
reqwest = "0.10.0-alpha.2" | |
tokio = { version = "0.2.0-alpha.6" } | |
serde = {version = "1.0", features = ["derive"] } | |
serde_json = "1.0" | |
dotenv = "0.14.1" | |
dotenv_codegen = "0.14.1" | |
chrono = { version = "0.4", features = ["serde"] } | |
rust-crypto = "^0.2" | |
url = "2.1.0" | |
hmac = "0.6.2" | |
sha2 = "0.7.1" | |
data-encoding = "2.1.2" | |
cargo-geiger = "0.7.3" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_use] | |
extern crate dotenv_codegen; | |
use std::collections::HashMap; | |
mod poloniex_requests; | |
mod models; | |
use models::*; | |
#[tokio::main] | |
async fn main() -> Result<(), Box<dyn std::error::Error>>{ | |
// let ticker_response: HashMap<String, Ticker> = poloniex_requests::get_ticker().await?; | |
// println!("Tciker: {:?}\n", ticker_response); | |
// let balance_response: HashMap<String, String> = poloniex_requests::get_balances().await?; | |
// println!("Balance: {:?}\n", balance_response); | |
let btc_loan_response: LoanOrders = poloniex_requests::get_load_orders("btc".to_owned()).await?; | |
let mut copied_loan = btc_loan_response; | |
let mut offers = copied_loan.offers().clone(); | |
offers.sort_by(|a, b| a.rate().cmp(&b.rate())); | |
println!("BTC Best Loand: {:?}\n", offers[0]); | |
println!("BTC Best Loand Rate: {:?}\n", offers[0].rate()); | |
let eth_loan_response: LoanOrders = poloniex_requests::get_load_orders("eth".to_owned()).await?; | |
copied_loan = eth_loan_response; | |
offers = copied_loan.offers().clone(); | |
offers.sort_by(|a, b| a.rate().cmp(&b.rate())); | |
println!("ETH Best Loand: {:?}\n", offers[0]); | |
let eth_best_rate = offers[0].rate().parse::<f32>().unwrap(); | |
println!("ETH Best Loand Rate: {:?}\n", eth_best_rate); | |
let all_balance_response: HashMap<String, CompleteBalances> = poloniex_requests::get_complete_balances().await?; | |
// println!("All Balance: {:?}\n", all_balance_response); | |
println!("BTC Balance : {:?}\n", all_balance_response.get("BTC")); | |
println!("ETH Balance : {:?}\n", all_balance_response.get("ETH")); | |
let eth_balance = all_balance_response.get("ETH").unwrap().available(); | |
let availe_eth = eth_balance.parse::<f64>().unwrap(); | |
println!("ETH Avail Balance : {:?} => {:?}\n",eth_balance, availe_eth); | |
// Will be change to percent (0.001 => 0.1%) | |
let loan_offer: LoanOffer = poloniex_requests::make_new_load_offer("ETH".to_string(), availe_eth, 2, false, eth_best_rate).await?; | |
println!("Offers {:?}", loan_offer); | |
Ok(()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use serde::{Deserialize, Serialize}; | |
#[derive(Deserialize, Serialize, Debug)] | |
pub struct Ticker { | |
id: u32, | |
last: String | |
} | |
#[derive(Deserialize, Serialize, Debug)] | |
pub struct Balances { | |
name: String, | |
balance: String | |
} | |
#[derive(Deserialize, Serialize, Debug)] | |
#[allow(non_snake_case)] | |
pub struct CompleteBalances { | |
available: String, | |
onOrders: String, | |
btcValue: String | |
} | |
#[derive(Deserialize, Serialize, Debug)] | |
#[allow(non_snake_case)] | |
pub struct LoanOffer { | |
success: u32, | |
message: String, | |
orderID: u32 | |
} | |
#[derive(Deserialize, Serialize, Debug )] | |
pub struct LoanOrders { | |
offers: Vec<LoanOrder>, | |
demands: Vec<LoanOrder> | |
} | |
#[derive(Deserialize, Serialize, Debug, Clone)] | |
#[allow(non_snake_case)] | |
pub struct LoanOrder { | |
rate: String, | |
amount: String, | |
rangeMin: u32, | |
rangeMax: u32 | |
} | |
impl LoanOrders { | |
// Immutable access. | |
pub fn offers(self) -> Vec<LoanOrder> { | |
self.offers | |
} | |
pub fn demands(self) -> Vec<LoanOrder> { | |
self.demands | |
} | |
} | |
impl LoanOrder { | |
pub fn rate(&self) -> &String { | |
&self.rate | |
} | |
} | |
impl CompleteBalances { | |
pub fn available(&self) -> &String { | |
&self.available | |
} | |
pub fn onOrders(&self) -> &String { | |
&self.onOrders | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use crate::models::LoanOffer; | |
use crate::models::LoanOrders; | |
use reqwest; | |
use std::collections::HashMap; | |
use crypto::hmac::Hmac; | |
use crypto::mac::Mac; | |
use crypto::sha2::Sha512; | |
use data_encoding::HEXLOWER; | |
use chrono::prelude::*; | |
use crate::models::Ticker; | |
use crate::models::CompleteBalances; | |
static PUBLIC_API_ENDPOINT: &str = "https://poloniex.com/public"; | |
static PRIVATE_API_ENDPOINT: &str = "https://poloniex.com/tradingApi"; | |
static POLONIEX_KET: &str = dotenv!("POLONIEX_KEY"); | |
use serde_json; | |
pub async fn get_ticker() | |
-> Result<HashMap<String, Ticker>, Box<dyn std::error::Error>> { | |
let ticker_url = get_get_path("returnTicker"); | |
let response: HashMap<String, Ticker> = reqwest::get(&ticker_url).await?.json::<HashMap<String, Ticker>>().await?; | |
Ok(response) | |
} | |
pub async fn get_load_orders(currency: String) | |
-> Result<LoanOrders, Box<dyn std::error::Error>> { | |
let mut ticker_url = get_get_path("returnLoanOrders"); | |
ticker_url = format!("{}¤cy={}", ticker_url, currency.to_uppercase()); | |
let response: LoanOrders = reqwest::get(&ticker_url).await?.json::<LoanOrders>().await?; | |
Ok(response) | |
} | |
pub async fn get_balances() | |
-> Result<HashMap<String, String>, Box<dyn std::error::Error>> { | |
let post_params = get_post_data("returnBalances".to_string()); | |
let body_data = create_body_data(post_params.clone()); | |
let sign_data = get_sign_data(&body_data); | |
let post_resp = reqwest::Client::new().post(PRIVATE_API_ENDPOINT) | |
.header("Sign", sign_data) | |
.header("Key", POLONIEX_KET) | |
.form(&post_params) | |
.send() | |
.await?.bytes().await?; | |
let response: HashMap<String, String> = serde_json::from_slice(&post_resp).unwrap(); | |
Ok(response) | |
} | |
pub async fn get_complete_balances() | |
-> Result<HashMap<String, CompleteBalances>, Box<dyn std::error::Error>> { | |
let mut post_params = get_post_data("returnCompleteBalances".to_string()); | |
post_params.insert("account".to_owned(), "all".to_owned()); | |
let body_data = create_body_data(post_params.clone()); | |
let sign_data = get_sign_data(&body_data); | |
let post_resp = reqwest::Client::new().post(PRIVATE_API_ENDPOINT) | |
.header("Sign", sign_data) | |
.header("Key", POLONIEX_KET) | |
.form(&post_params) | |
.send() | |
.await?.bytes().await?; | |
let response: HashMap<String, CompleteBalances> = serde_json::from_slice(&post_resp).unwrap(); | |
Ok(response) | |
} | |
pub async fn make_new_load_offer(currency: String, amount: f64, duration: u32, auto_renew: bool, rate: f32) | |
-> Result<LoanOffer, Box<dyn std::error::Error>> { | |
let mut post_params = get_post_data("createLoanOffer".to_string()); | |
post_params.insert("currency".to_owned(), currency.to_owned()); | |
post_params.insert("amount".to_owned(), amount.to_string().to_owned()); | |
post_params.insert("duration".to_owned(), duration.to_string().to_owned()); | |
post_params.insert("autoRenew".to_owned(), (auto_renew as i32).to_string().to_owned()); | |
post_params.insert("lendingRate".to_owned(), rate.to_string().to_owned()); | |
let body_data = create_body_data(post_params.clone()); | |
let sign_data = get_sign_data(&body_data); | |
let response = reqwest::Client::new().post(PRIVATE_API_ENDPOINT) | |
.header("Sign", sign_data) | |
.header("Key", POLONIEX_KET) | |
.form(&post_params) | |
.send() | |
.await?.bytes().await?; | |
//.json::<LoanOffer>().await?; | |
println!("return: {:?}", response); | |
let response1: LoanOffer = serde_json::from_slice(&response).unwrap(); | |
Ok(response1) | |
} | |
fn create_body_data(params_data: HashMap<String, String>) -> String { | |
let encoded: String = params_data.into_iter() | |
.map(|data| format!("{}={}",data.0,data.1) ) | |
.collect::<Vec<String>>().join("&"); | |
encoded | |
} | |
fn get_get_path(str: &str) -> String { | |
let ret = format!("{}?command={}", PUBLIC_API_ENDPOINT, str); | |
ret | |
} | |
fn get_post_data(command: String) | |
-> HashMap<String, String> { | |
let mut params = HashMap::new(); | |
let current_time = get_current_time(); | |
params.insert("command".to_owned(), command.to_owned()); | |
params.insert("nonce".to_owned(), current_time.to_owned()); | |
params | |
} | |
fn get_sign_data(data: &str) -> String { | |
let sec_key: &str = dotenv!("POLONIEX_SECRET"); | |
let mut hmac = Hmac::new(Sha512::new(), &sec_key.as_bytes()); | |
hmac.input(data.as_bytes()); | |
HEXLOWER.encode(hmac.result().code()) | |
} | |
fn get_current_time() -> String { | |
let local: DateTime<Local> = Local::now(); | |
local.format("%s0000000").to_string() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment