use anyhow::{Context, Ok};
use hmac::{Hmac, Mac};
use reqwest::{Client, Response};
use sha2::Sha256;
use std::time::{SystemTime, UNIX_EPOCH};
use crate::model::binance_model::{BinanceRequest, Endpoint};
pub fn create_signature(secret_key: &str, query: &str) -> anyhow::Result<String> {
let mut mac = Hmac::<Sha256>::new_from_slice(secret_key.as_bytes()).with_context(|| { format!("create_signature error")})?;
mac.update(query.as_bytes());
Ok(hex::encode(mac.finalize().into_bytes()))
}
pub fn create_timestamp() -> anyhow::Result<String> {
Ok(
SystemTime::now()
.duration_since(UNIX_EPOCH)?
.as_millis()
.to_string()
)
}
pub async fn request_with_signature<T>(method: &str, secret_key: &str, api_key: &str, model: BinanceRequest<T>) -> anyhow::Result<String>
where
T: Endpoint + Into<String>,
{
let client = Client::new();
let query = model.query_with_timestamp();
let signature = create_signature(&secret_key, &query)?;
println!("query: {}", query);
println!("query: {}", signature);
let mut url = url::Url::parse(&model.base_url())
.context("fail to parse base url")?
.join(&(model.endpoint_url.into()))
.context("fail to parse endpoint url")?;
url.set_query(Some(&format!("{}&signature={}", query, signature)));
println!("url: {}", url);
let request = match method.to_lowercase().as_str() {
"get" => client.get(url.as_str()),
"post" => client.post(url.as_str()),
"delete" => client.delete(url.as_str()),
_ => return Err(anyhow::anyhow!("Unsupported method: {}", method)),
};
let text = request
.header("X-MBX-APIKEY", api_key.clone())
.send()
.await
.context("fail to send")?
.text()
.await?;
Ok(text)
}
pub async fn request<T>(method: &str, model: BinanceRequest<T>) -> anyhow::Result<String>
where
T: Endpoint + Into<String>
{
let client = Client::new();
let query = model.query();
println!("query: {}", query);
let mut url = url::Url::parse(&model.base_url())
.context("fail to parse base url")?
.join(&(model.endpoint_url.into()))
.context("fail to parse endpoint url")?;
url.set_query(Some(&format!("{}", query)));
let request = match method.to_lowercase().as_str() {
"get" => client.get(url.as_str()),
"post" => client.post(url.as_str()),
"delete" => client.delete(url.as_str()),
_ => return Err(anyhow::anyhow!("Unsupported method: {}", method)),
};
let text = request
.send()
.await
.context("fail to send")?
.text()
.await?;
Ok(text)
}