Skip to main content

csv_adapter_bitcoin/
error.rs

1//! Bitcoin adapter error types
2
3use thiserror::Error;
4
5/// Bitcoin adapter specific errors
6#[derive(Error, Debug)]
7pub enum BitcoinError {
8    /// Bitcoin RPC error
9    #[error("RPC error: {0}")]
10    RpcError(String),
11
12    /// Transaction not found
13    #[error("Transaction not found: {0}")]
14    TransactionNotFound(String),
15
16    /// UTXO already spent
17    #[error("UTXO already spent: {0}")]
18    UTXOSpent(String),
19
20    /// Invalid Merkle proof
21    #[error("Invalid Merkle proof: {0}")]
22    InvalidMerkleProof(String),
23
24    /// Registry full (max size reached)
25    #[error("Registry full: {0}")]
26    RegistryFull(String),
27
28    /// Reorg detected
29    #[error("Reorg detected at height {height}, depth {depth}")]
30    ReorgDetected { height: u64, depth: u64 },
31
32    /// Insufficient confirmations
33    #[error("Insufficient confirmations: got {got}, need {need}")]
34    InsufficientConfirmations { got: u64, need: u64 },
35
36    /// Wrapper for core adapter errors
37    #[error(transparent)]
38    CoreError(#[from] csv_adapter_core::AdapterError),
39}
40
41impl From<BitcoinError> for csv_adapter_core::AdapterError {
42    fn from(err: BitcoinError) -> Self {
43        match err {
44            BitcoinError::CoreError(e) => e,
45            BitcoinError::RpcError(msg) => csv_adapter_core::AdapterError::NetworkError(msg),
46            BitcoinError::TransactionNotFound(msg) => csv_adapter_core::AdapterError::Generic(msg),
47            BitcoinError::UTXOSpent(msg) => csv_adapter_core::AdapterError::InvalidSeal(msg),
48            BitcoinError::InvalidMerkleProof(msg) => {
49                csv_adapter_core::AdapterError::InclusionProofFailed(msg)
50            }
51            BitcoinError::RegistryFull(msg) => csv_adapter_core::AdapterError::Generic(msg),
52            BitcoinError::ReorgDetected { height, depth } => {
53                csv_adapter_core::AdapterError::ReorgInvalid(format!(
54                    "Reorg at height {}, depth {}",
55                    height, depth
56                ))
57            }
58            BitcoinError::InsufficientConfirmations { got, need } => {
59                csv_adapter_core::AdapterError::FinalityNotReached(format!(
60                    "Got {} confirmations, need {}",
61                    got, need
62                ))
63            }
64        }
65    }
66}
67
68impl BitcoinError {
69    /// Whether this error is transient and may be retried
70    pub fn is_transient(&self) -> bool {
71        match self {
72            BitcoinError::RpcError(_) => true,
73            BitcoinError::TransactionNotFound(_) => true,
74            BitcoinError::InsufficientConfirmations { .. } => true,
75            BitcoinError::ReorgDetected { .. } => true,
76            BitcoinError::UTXOSpent(_) => false,
77            BitcoinError::InvalidMerkleProof(_) => false,
78            BitcoinError::RegistryFull(_) => false,
79            BitcoinError::CoreError(_) => false,
80        }
81    }
82}
83
84/// Result type for Bitcoin adapter operations
85pub type BitcoinResult<T> = Result<T, BitcoinError>;