Skip to main content

polyoxide_clob/account/
signer.rs

1//! Re-export of shared HMAC signer from polyoxide-core
2//!
3//! This module provides a thin wrapper around the unified Signer implementation
4//! to maintain backward compatibility with the CLOB API client.
5
6pub use polyoxide_core::{Base64Format, Signer as CoreSigner};
7
8use crate::error::ClobError;
9
10/// HMAC signer for API authentication
11///
12/// This is a thin wrapper around the shared `polyoxide_core::Signer` that provides
13/// CLOB-specific error handling.
14#[derive(Clone, Debug)]
15pub struct Signer {
16    inner: CoreSigner,
17}
18
19impl Signer {
20    /// Create a new signer from base64-encoded secret (supports multiple formats)
21    pub fn new(secret: &str) -> Self {
22        Self {
23            inner: CoreSigner::new(secret),
24        }
25    }
26
27    /// Sign a message with HMAC-SHA256, using URL-safe base64 encoding
28    pub fn sign(&self, message: &str) -> Result<String, ClobError> {
29        self.inner
30            .sign(message, Base64Format::UrlSafe)
31            .map_err(ClobError::Crypto)
32    }
33
34    /// Create signature message for API request
35    pub fn create_message(timestamp: u64, method: &str, path: &str, body: Option<&str>) -> String {
36        CoreSigner::create_message(timestamp, method, path, body)
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn test_sign() {
46        // Test secret (base64)
47        let secret = "c2VjcmV0"; // "secret" in base64
48        let signer = Signer::new(secret);
49
50        let message = Signer::create_message(1234567890, "GET", "/api/test", None);
51        let signature = signer.sign(&message).unwrap();
52
53        // Signature should be URL-safe base64
54        assert!(!signature.contains('+'));
55        assert!(!signature.contains('/'));
56    }
57}