Skip to main content

bdk_bitcoind_client/
error.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! Error types for the Bitcoin RPC client.
4
5use core::fmt;
6use core::num::TryFromIntError;
7use std::io;
8
9use bitcoin::{consensus::encode::FromHexError, hex::HexToArrayError};
10#[cfg(feature = "28_0")]
11use corepc_types::v17::{GetBlockHeaderVerboseError, GetBlockVerboseOneError};
12#[cfg(not(feature = "28_0"))]
13use corepc_types::v30::{GetBlockHeaderVerboseError, GetBlockVerboseOneError};
14use corepc_types::{bitcoin, v30::GetBlockFilterError};
15use jsonrpc::serde_json;
16
17/// Result type alias for the RPC client.
18pub type Result<T> = std::result::Result<T, Error>;
19
20/// Errors that can occur when using the Bitcoin RPC client.
21#[derive(Debug)]
22pub enum Error {
23    /// Hex deserialization error
24    DecodeHex(FromHexError),
25
26    /// Error converting `GetBlockVersboseOne` type into the model type
27    GetBlockVerboseOne(GetBlockVerboseOneError),
28
29    /// Error modeling [`GetBlockHeaderVerbose`](corepc_types::model::GetBlockHeaderVerbose).
30    GetBlockHeaderVerbose(GetBlockHeaderVerboseError),
31
32    /// Error modeling [`GetBlockFilter`](corepc_types::model::GetBlockFilter)
33    GetBlockFilter(GetBlockFilterError),
34
35    /// Invalid or corrupted cookie file.
36    InvalidCookieFile,
37
38    /// The provided URL is syntactically incorrect
39    InvalidUrl(String),
40
41    /// JSON-RPC error from the server.
42    JsonRpc(jsonrpc::Error),
43
44    /// Hash parsing error.
45    HexToArray(HexToArrayError),
46
47    /// JSON serialization/deserialization error.
48    Json(serde_json::Error),
49
50    /// I/O error (e.g., reading cookie file, network issues).
51    Io(io::Error),
52
53    /// Error when converting an integer type to a smaller type due to overflow.
54    TryFromInt(TryFromIntError),
55}
56
57impl fmt::Display for Error {
58    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59        match self {
60            Error::DecodeHex(e) => write!(f, "hex deserialization error: {e}"),
61            Error::GetBlockVerboseOne(e) => write!(f, "block verbose error: {e}"),
62            Error::GetBlockHeaderVerbose(e) => write!(f, "block header verbose error: {e}"),
63            Error::GetBlockFilter(e) => write!(f, "block filter error: {e}"),
64            Error::InvalidCookieFile => write!(f, "invalid or missing cookie file"),
65            Error::InvalidUrl(e) => write!(f, "invalid RPC URL: {e}"),
66            Error::HexToArray(e) => write!(f, "hash parsing error: {e}"),
67            Error::JsonRpc(e) => write!(f, "JSON-RPC error: {e}"),
68            Error::Json(e) => write!(f, "JSON error: {e}"),
69            Error::Io(e) => write!(f, "I/O error: {e}"),
70            Error::TryFromInt(e) => write!(f, "integer conversion overflow: {e}"),
71        }
72    }
73}
74
75impl core::error::Error for Error {}
76
77// Conversions from other error types
78impl From<jsonrpc::Error> for Error {
79    fn from(e: jsonrpc::Error) -> Self {
80        Error::JsonRpc(e)
81    }
82}
83
84impl From<serde_json::Error> for Error {
85    fn from(e: serde_json::Error) -> Self {
86        Error::Json(e)
87    }
88}
89
90impl From<HexToArrayError> for Error {
91    fn from(e: HexToArrayError) -> Self {
92        Error::HexToArray(e)
93    }
94}
95
96impl From<io::Error> for Error {
97    fn from(e: io::Error) -> Self {
98        Error::Io(e)
99    }
100}
101
102impl From<TryFromIntError> for Error {
103    fn from(e: TryFromIntError) -> Self {
104        Error::TryFromInt(e)
105    }
106}
107
108impl From<GetBlockVerboseOneError> for Error {
109    fn from(e: GetBlockVerboseOneError) -> Self {
110        Error::GetBlockVerboseOne(e)
111    }
112}
113
114impl From<FromHexError> for Error {
115    fn from(e: FromHexError) -> Self {
116        Error::DecodeHex(e)
117    }
118}
119
120/// Extension methods for the client error type.
121impl Error {
122    /// Returns `true` if this is a "not found" error returned by `bitcoind`.
123    ///
124    /// `bitcoind` returns error code `-5` (`RPC_INVALID_ADDRESS_OR_KEY`)
125    /// whenever a requested block hash, transaction ID, address, or similar object
126    /// does not exist on the node.
127    pub fn is_not_found_error(&self) -> bool {
128        if let Error::JsonRpc(jsonrpc::Error::Rpc(rpc_err)) = self {
129            rpc_err.code == -5
130        } else {
131            false
132        }
133    }
134}