use alloy::signers::local::PrivateKeySigner;
use std::str::FromStr;
use crate::clob::{ClobError, Result};
#[derive(Clone)]
pub struct Signer {
signer: PrivateKeySigner,
chain_id: u64,
}
impl Signer {
pub fn new(private_key: &str, chain_id: u64) -> Result<Self> {
let signer = PrivateKeySigner::from_str(private_key)
.map_err(|e| ClobError::InvalidPrivateKey(e.to_string()))?;
Ok(Self { signer, chain_id })
}
pub fn address(&self) -> String {
self.signer.address().to_string()
}
pub fn chain_id(&self) -> u64 {
self.chain_id
}
pub fn inner(&self) -> &PrivateKeySigner {
&self.signer
}
pub async fn sign_hash(&self, message_hash: &[u8; 32]) -> Result<String> {
use alloy::signers::Signer as AlloySigner;
use alloy::primitives::FixedBytes;
let hash: &FixedBytes<32> = message_hash.into();
let signature = self
.signer
.sign_hash(hash)
.await
.map_err(|e| ClobError::SigningError(e.to_string()))?;
Ok(format!("0x{}", hex::encode(signature.as_bytes())))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_signer_creation() {
let private_key = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
let signer = Signer::new(private_key, 137);
assert!(signer.is_ok());
let s = signer.unwrap();
assert_eq!(s.chain_id(), 137);
assert!(s.address().starts_with("0x"));
}
#[test]
fn test_invalid_private_key() {
let invalid_key = "invalid";
let result = Signer::new(invalid_key, 137);
assert!(result.is_err());
}
#[tokio::test]
async fn test_sign_hash() {
let private_key = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
let signer = Signer::new(private_key, 137).unwrap();
let message_hash = [0u8; 32];
let signature = signer.sign_hash(&message_hash).await;
assert!(signature.is_ok());
let sig = signature.unwrap();
assert!(sig.starts_with("0x"));
}
}