ccxt_exchanges/binance/
signing_strategy.rs1use crate::binance::Binance;
6use async_trait::async_trait;
7use ccxt_core::Result;
8use ccxt_core::signed_request::{SigningContext, SigningStrategy};
9use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
10use std::sync::Arc;
11
12pub struct BinanceSigningStrategy {
19 binance: Arc<Binance>,
21}
22
23impl BinanceSigningStrategy {
24 pub fn new(binance: Arc<Binance>) -> Self {
26 Self { binance }
27 }
28
29 pub fn from_ref(binance: &Arc<Binance>) -> Self {
31 Self {
32 binance: binance.clone(),
33 }
34 }
35}
36
37#[async_trait]
38impl SigningStrategy for BinanceSigningStrategy {
39 async fn prepare_request(&self, ctx: &mut SigningContext) -> Result<()> {
40 self.binance.check_required_credentials()?;
42
43 let timestamp = self.binance.get_signing_timestamp().await?;
45 ctx.timestamp = timestamp.to_string();
46
47 ctx.params
49 .insert("timestamp".to_string(), ctx.timestamp.clone());
50 ctx.params.insert(
51 "recvWindow".to_string(),
52 self.binance.options().recv_window.to_string(),
53 );
54
55 let auth = self.binance.get_auth()?;
57 let query_string = build_signing_string(&ctx.params);
58 let signature = auth.sign(&query_string)?;
59
60 ctx.signature = Some(signature.clone());
62 ctx.params.insert("signature".to_string(), signature);
63
64 Ok(())
65 }
66
67 fn add_auth_headers(&self, headers: &mut HeaderMap, _ctx: &SigningContext) {
68 if let Ok(auth) = self.binance.get_auth() {
70 if let Ok(header_name) = HeaderName::from_bytes(b"X-MBX-APIKEY") {
71 if let Ok(header_value) = HeaderValue::from_str(auth.api_key()) {
72 headers.insert(header_name, header_value);
73 }
74 }
75 }
76 }
77}
78
79fn build_signing_string(params: &std::collections::BTreeMap<String, String>) -> String {
81 params
82 .iter()
83 .map(|(k, v)| format!("{}={}", k, v))
84 .collect::<Vec<_>>()
85 .join("&")
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91 use ccxt_core::ExchangeConfig;
92
93 #[test]
94 fn test_signing_strategy_creation() {
95 let config = ExchangeConfig::default();
96 let binance = Arc::new(Binance::new(config).unwrap());
97 let strategy = BinanceSigningStrategy::new(binance);
98 assert!(true);
100 }
101
102 #[test]
103 fn test_build_signing_string() {
104 let mut params = std::collections::BTreeMap::new();
105 params.insert("symbol".to_string(), "BTCUSDT".to_string());
106 params.insert("side".to_string(), "BUY".to_string());
107 params.insert("timestamp".to_string(), "1234567890".to_string());
108
109 let query = build_signing_string(¶ms);
110 assert_eq!(query, "side=BUY&symbol=BTCUSDT×tamp=1234567890");
112 }
113}