clob_client_rust/
headers.rs1use crate::errors::ClobError;
2use crate::types::ApiKeyCreds;
3use std::collections::HashMap;
4use std::time::{SystemTime, UNIX_EPOCH};
5
6pub type Headers = HashMap<String, String>;
8
9pub async fn create_l1_headers<S: crate::signing::Eip712Signer + Send + Sync>(
11 signer: &S,
12 chain_id: i32,
13 nonce: Option<u64>,
14 timestamp: Option<u64>,
15) -> Result<Headers, ClobError> {
16 let ts = timestamp.unwrap_or_else(|| {
19 SystemTime::now()
20 .duration_since(UNIX_EPOCH)
21 .map(|d| d.as_secs())
22 .unwrap_or(0)
23 });
24 let n = nonce.unwrap_or(0);
25
26 let address = signer.get_address().await?;
27
28 let sig = crate::signing::build_clob_eip712_signature(signer, chain_id as i64, ts, n)
29 .await
30 .map_err(|e| ClobError::Other(format!("failed to build eip712 signature: {}", e)))?;
31
32 let mut headers = Headers::new();
33 headers.insert("POLY_ADDRESS".to_string(), address);
34 headers.insert("POLY_SIGNATURE".to_string(), sig);
35 headers.insert("POLY_TIMESTAMP".to_string(), ts.to_string());
36 headers.insert("POLY_NONCE".to_string(), n.to_string());
37 Ok(headers)
38}
39
40pub async fn create_l2_headers<S: crate::signing::Eip712Signer + Send + Sync>(
42 signer: &S,
43 creds: &ApiKeyCreds,
44 method: &str,
45 request_path: &str,
46 body: Option<&str>,
47 timestamp: Option<u64>,
48) -> Result<Headers, ClobError> {
49 let ts = timestamp.unwrap_or_else(|| {
50 SystemTime::now()
51 .duration_since(UNIX_EPOCH)
52 .map(|d| d.as_secs())
53 .unwrap_or(0)
54 });
55 let address = signer.get_address().await?;
56
57 let sig = match crate::signing::build_poly_hmac_signature(
59 &creds.secret,
60 ts,
61 method,
62 request_path,
63 body,
64 ) {
65 Ok(s) => s,
66 Err(e) => {
67 return Err(ClobError::Other(format!(
69 "failed to build hmac signature: {}",
70 e
71 )));
72 }
73 };
74
75 if std::env::var("CLOB_DEBUG_FULL").is_ok() || std::env::var("CLOB_DEBUG_RAW").is_ok() {
78 let preview_secret = if creds.secret.len() > 6 {
79 format!("{}***", &creds.secret[..6])
80 } else {
81 "***".to_string()
82 };
83 let payload_preview = {
84 let mut base = format!("{}{}{}", ts, method, request_path);
85 if let Some(b) = body {
86 base.push_str(b);
87 }
88 if base.len() > 420 {
90 format!("{} ... {}", &base[..200], &base[base.len() - 200..])
91 } else {
92 base
93 }
94 };
95 eprintln!(
96 "[L2 DEBUG] ts(sec)={} method={} path={} secret(b64-prefix)={} sig={} payload_part={} body_len={}",
97 ts,
98 method,
99 request_path,
100 preview_secret,
101 sig,
102 payload_preview,
103 body.map(|b| b.len()).unwrap_or(0)
104 );
105 }
106
107 let mut headers = Headers::new();
108 headers.insert("POLY_ADDRESS".to_string(), address);
109 headers.insert("POLY_SIGNATURE".to_string(), sig);
110 headers.insert("POLY_TIMESTAMP".to_string(), ts.to_string());
111 headers.insert("POLY_API_KEY".to_string(), creds.key.clone());
112 headers.insert("POLY_PASSPHRASE".to_string(), creds.passphrase.clone());
113 Ok(headers)
114}
115
116pub fn inject_builder_headers(
117 mut l2: Headers,
118 builder: &std::collections::HashMap<String, String>,
119) -> Headers {
120 for (k, v) in builder.iter() {
121 l2.insert(k.clone(), v.clone());
122 }
123 l2
124}