pub mod enums;
pub mod errors;
pub mod filters;
pub mod fix_api;
pub mod rest_api;
pub mod web_socket;
pub mod web_socket_api;
pub mod web_socket_stream;
pub mod margin;
pub mod spot;
pub mod usd_futures;
use base64::{engine::general_purpose::STANDARD as b64, Engine};
use ed25519_dalek::{ed25519::signature::SignerMut, pkcs8::DecodePrivateKey, SigningKey};
use hmac::{Hmac, Mac};
use rest_api::{RestApiClient, RestApiError};
use serde::{Deserialize, Serialize};
use sha2::Sha256;
pub fn rest_api(
base_url: &str,
api_key: &str,
secret_key: &str,
) -> Result<RestApiClient, RestApiError> {
RestApiClient::new(base_url, api_key, secret_key)
}
pub fn web_socket_api(
endpoint: &str,
api_key: &str,
secret_key: &str,
) -> web_socket_api::WebSocketApiClient {
web_socket_api::WebSocketApiClient::new(endpoint, api_key, secret_key)
}
pub trait Params: Sized + Send + Serialize {
fn as_query(&self) -> Result<String, RestApiError> {
Ok(serde_qs::to_string(self)?)
}
}
pub trait Response: Sized + for<'de> Deserialize<'de> {}
pub(crate) fn hmac_signature(key: &str, data: &str) -> Result<String, hmac::digest::InvalidLength> {
let mut mac = Hmac::<Sha256>::new_from_slice(key.as_bytes())?;
mac.update(data.as_bytes());
Ok(hex::encode(mac.finalize().into_bytes()))
}
pub(crate) fn ed25519_signature(
key: &str,
data: &str,
) -> Result<String, ed25519_dalek::pkcs8::Error> {
let mut key = SigningKey::from_pkcs8_pem(key)?;
let signature = key.sign(data.as_bytes());
let encoded = b64.encode(signature.to_bytes());
Ok(encoded)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hmac() {
let key = "NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j";
let data = "symbol=LTCBTC&side=BUY&type=LIMIT&timeInForce=GTC&quantity=1&price=0.1&recvWindow=5000×tamp=1499827319559";
let sig = hmac_signature(key, data).unwrap();
assert_eq!(
sig,
"c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71"
);
}
#[tokio::test]
async fn ed25519() {
let pem = r#"\
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIHWPzTvl8pIHsAbZtJv+/0kaXO611fs90IewpT1PEwFT
-----END PRIVATE KEY-----
"#;
let data = "hello world";
let signature = ed25519_signature(pem, data).unwrap();
assert_eq!(signature, "e2jzxQfzCeKvlScapTXk1Jt7e1i6rIXLZ4UVWcJ7kykMSARX/rUV7a3za+LlFizFUORuUs/38zlVbxFnrcCLBw==");
}
}