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 .unwrap()
22 .as_secs()
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)
30 .await
31 .map_err(|e| ClobError::Other(format!("failed to build eip712 signature: {}", e)))?;
32
33 let mut headers = Headers::new();
34 headers.insert("POLY_ADDRESS".to_string(), address);
35 headers.insert("POLY_SIGNATURE".to_string(), sig);
36 headers.insert("POLY_TIMESTAMP".to_string(), ts.to_string());
37 headers.insert("POLY_NONCE".to_string(), n.to_string());
38 Ok(headers)
39}
40
41pub async fn create_l2_headers<S: crate::signing::Eip712Signer + Send + Sync>(
43 signer: &S,
44 creds: &ApiKeyCreds,
45 method: &str,
46 request_path: &str,
47 body: Option<&str>,
48 timestamp: Option<u64>,
49) -> Result<Headers, ClobError> {
50 let ts = timestamp.unwrap_or_else(|| {
52 SystemTime::now()
53 .duration_since(UNIX_EPOCH)
54 .unwrap()
55 .as_secs()
56 });
57 let address = signer.get_address().await?;
58
59 let sig = match crate::signing::build_poly_hmac_signature(
61 &creds.secret,
62 ts,
63 method,
64 request_path,
65 body,
66 ) {
67 Ok(s) => s,
68 Err(e) => {
69 return Err(ClobError::Other(format!(
71 "failed to build hmac signature: {}",
72 e
73 )));
74 }
75 };
76
77 if std::env::var("CLOB_DEBUG_FULL").is_ok() || std::env::var("CLOB_DEBUG_RAW").is_ok() {
80 let preview_secret = if creds.secret.len() > 6 {
81 format!("{}***", &creds.secret[..6])
82 } else {
83 "***".to_string()
84 };
85 let payload_preview = {
86 let mut base = format!("{}{}{}", ts, method, request_path);
87 if let Some(b) = body {
88 base.push_str(b);
89 }
90 if base.len() > 420 {
92 format!("{} ... {}", &base[..200], &base[base.len() - 200..])
93 } else {
94 base
95 }
96 };
97 eprintln!(
98 "[L2 DEBUG] ts(sec)={} method={} path={} secret(b64-prefix)={} sig={} payload_part={} body_len={}",
99 ts,
100 method,
101 request_path,
102 preview_secret,
103 sig,
104 payload_preview,
105 body.map(|b| b.len()).unwrap_or(0)
106 );
107 }
108
109 let mut headers = Headers::new();
110 headers.insert("POLY_ADDRESS".to_string(), address);
111 headers.insert("POLY_SIGNATURE".to_string(), sig);
112 headers.insert("POLY_TIMESTAMP".to_string(), ts.to_string());
113 headers.insert("POLY_API_KEY".to_string(), creds.key.clone());
114 headers.insert("POLY_PASSPHRASE".to_string(), creds.passphrase.clone());
115 Ok(headers)
116}
117
118pub fn inject_builder_headers(
119 mut l2: Headers,
120 builder: &std::collections::HashMap<String, String>,
121) -> Headers {
122 for (k, v) in builder.iter() {
123 l2.insert(k.clone(), v.clone());
124 }
125 l2
126}