1use alloy_primitives::{hex, ChainId};
2use k256::ecdsa;
3use std::{fmt, fmt::Display};
4use thiserror::Error;
5
6pub type Result<T, E = Error> = std::result::Result<T, E>;
8
9#[derive(Debug, Error)]
11pub enum Error {
12    #[error("operation `{0}` is not supported by the signer")]
14    UnsupportedOperation(UnsupportedSignerOperation),
15    #[error(
17        "transaction-provided chain ID ({tx}) does not match the signer's chain ID ({signer})"
18    )]
19    TransactionChainIdMismatch {
20        signer: ChainId,
22        tx: ChainId,
24    },
25    #[error(transparent)]
27    #[cfg(feature = "eip712")]
28    DynAbiError(#[from] alloy_dyn_abi::Error),
29    #[error(transparent)]
31    Ecdsa(#[from] ecdsa::Error),
32    #[error(transparent)]
34    HexError(#[from] hex::FromHexError),
35    #[error(transparent)]
37    SignatureError(#[from] alloy_primitives::SignatureError),
38    #[error(transparent)]
40    Other(#[from] Box<dyn std::error::Error + Send + Sync + 'static>),
41}
42
43impl Error {
44    #[cold]
46    pub fn other(error: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>) -> Self {
47        Self::Other(error.into())
48    }
49
50    #[cold]
52    pub fn message(err: impl Display) -> Self {
53        Self::Other(err.to_string().into())
54    }
55
56    #[inline]
58    pub const fn is_unsupported(&self) -> bool {
59        matches!(self, Self::UnsupportedOperation(_))
60    }
61
62    #[inline]
65    pub const fn unsupported(&self) -> Option<UnsupportedSignerOperation> {
66        match self {
67            Self::UnsupportedOperation(op) => Some(*op),
68            _ => None,
69        }
70    }
71}
72
73#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
75pub enum UnsupportedSignerOperation {
76    SignHash,
78    SignMessage,
80    SignTransaction,
82    SignTypedData,
84}
85
86impl fmt::Display for UnsupportedSignerOperation {
87    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88        self.as_str().fmt(f)
89    }
90}
91
92impl UnsupportedSignerOperation {
93    #[inline]
95    pub const fn as_str(&self) -> &'static str {
96        match self {
97            Self::SignHash => "sign_hash",
98            Self::SignMessage => "sign_message",
99            Self::SignTransaction => "sign_transaction",
100            Self::SignTypedData => "sign_typed_data",
101        }
102    }
103}