use thiserror::Error;
#[derive(Error, Debug, Clone)]
pub enum SignerError {
#[error("No signer context available - must be called within SignerContext::with_signer")]
NoSignerContext,
#[error("Blockchain transaction error: {0}")]
BlockchainTransaction(String),
#[error("EVM transaction error: {0}")]
EvmTransaction(String),
#[error("Invalid configuration: {0}")]
Configuration(String),
#[error("Signing error: {0}")]
Signing(String),
#[error("Client creation error: {0}")]
ClientCreation(String),
#[error("Invalid private key: {0}")]
InvalidPrivateKey(String),
#[error("Provider error: {0}")]
ProviderError(String),
#[error("Transaction failed: {0}")]
TransactionFailed(String),
#[error("Unsupported operation: {0}")]
UnsupportedOperation(String),
#[error("Blockhash error: {0}")]
BlockhashError(String),
#[error("Unsupported network: {0}")]
UnsupportedNetwork(String),
#[error("Invalid RPC URL: {0}")]
InvalidRpcUrl(String),
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_no_signer_context_error_display() {
let error = SignerError::NoSignerContext;
assert_eq!(
error.to_string(),
"No signer context available - must be called within SignerContext::with_signer"
);
}
#[test]
fn test_blockchain_transaction_error_display() {
let error = SignerError::BlockchainTransaction("Connection refused".to_string());
assert!(error.to_string().contains("Blockchain transaction error:"));
assert!(error.to_string().contains("Connection refused"));
}
#[test]
fn test_evm_transaction_error_display() {
let error = SignerError::EvmTransaction("Transaction reverted".to_string());
assert_eq!(
error.to_string(),
"EVM transaction error: Transaction reverted"
);
}
#[test]
fn test_configuration_error_display() {
let error = SignerError::Configuration("Invalid network config".to_string());
assert_eq!(
error.to_string(),
"Invalid configuration: Invalid network config"
);
}
#[test]
fn test_signing_error_display() {
let error = SignerError::Signing("Key derivation failed".to_string());
assert_eq!(error.to_string(), "Signing error: Key derivation failed");
}
#[test]
fn test_client_creation_error_display() {
let error = SignerError::ClientCreation("Failed to initialize RPC client".to_string());
assert_eq!(
error.to_string(),
"Client creation error: Failed to initialize RPC client"
);
}
#[test]
fn test_invalid_private_key_error_display() {
let error = SignerError::InvalidPrivateKey("Invalid hex format".to_string());
assert_eq!(error.to_string(), "Invalid private key: Invalid hex format");
}
#[test]
fn test_provider_error_display() {
let error = SignerError::ProviderError("Provider timeout".to_string());
assert_eq!(error.to_string(), "Provider error: Provider timeout");
}
#[test]
fn test_transaction_failed_error_display() {
let error = SignerError::TransactionFailed("Insufficient funds".to_string());
assert_eq!(error.to_string(), "Transaction failed: Insufficient funds");
}
#[test]
fn test_unsupported_operation_error_display() {
let error = SignerError::UnsupportedOperation("Multi-sig not supported".to_string());
assert_eq!(
error.to_string(),
"Unsupported operation: Multi-sig not supported"
);
}
#[test]
fn test_blockhash_error_display() {
let error = SignerError::BlockhashError("Failed to fetch recent blockhash".to_string());
assert_eq!(
error.to_string(),
"Blockhash error: Failed to fetch recent blockhash"
);
}
#[test]
fn test_unsupported_network_error_display() {
let error = SignerError::UnsupportedNetwork("Polygon".to_string());
assert_eq!(error.to_string(), "Unsupported network: Polygon");
}
#[test]
fn test_invalid_rpc_url_error_display() {
let error = SignerError::InvalidRpcUrl("malformed://url".to_string());
assert_eq!(error.to_string(), "Invalid RPC URL: malformed://url");
}
#[test]
fn test_error_variants_are_debug() {
let error = SignerError::NoSignerContext;
let debug_string = format!("{:?}", error);
assert!(debug_string.contains("NoSignerContext"));
}
#[test]
fn test_all_error_variants_with_empty_strings() {
let errors = vec![
SignerError::EvmTransaction(String::new()),
SignerError::Configuration(String::new()),
SignerError::Signing(String::new()),
SignerError::ClientCreation(String::new()),
SignerError::InvalidPrivateKey(String::new()),
SignerError::ProviderError(String::new()),
SignerError::TransactionFailed(String::new()),
SignerError::UnsupportedOperation(String::new()),
SignerError::BlockhashError(String::new()),
SignerError::UnsupportedNetwork(String::new()),
SignerError::InvalidRpcUrl(String::new()),
];
for error in errors {
let _error_string = error.to_string();
let _debug_string = format!("{:?}", error);
}
}
#[test]
fn test_blockchain_transaction_error_creation() {
let error = SignerError::BlockchainTransaction("Request timed out".to_string());
match error {
SignerError::BlockchainTransaction(msg) => {
assert_eq!(msg, "Request timed out");
}
_ => panic!("Expected SignerError::BlockchainTransaction variant"),
}
}
#[test]
fn test_error_variants_with_special_characters() {
let special_chars = "çšćŽćĺ đ \n\t\"'\\";
let errors = vec![
SignerError::EvmTransaction(special_chars.to_string()),
SignerError::Configuration(special_chars.to_string()),
SignerError::Signing(special_chars.to_string()),
SignerError::ClientCreation(special_chars.to_string()),
SignerError::InvalidPrivateKey(special_chars.to_string()),
SignerError::ProviderError(special_chars.to_string()),
SignerError::TransactionFailed(special_chars.to_string()),
SignerError::UnsupportedOperation(special_chars.to_string()),
SignerError::BlockhashError(special_chars.to_string()),
SignerError::UnsupportedNetwork(special_chars.to_string()),
SignerError::InvalidRpcUrl(special_chars.to_string()),
];
for error in errors {
let error_string = error.to_string();
assert!(error_string.contains(special_chars));
}
}
}