Skip to main content

metaflux_client/
error.rs

1//! Crate-wide error type.
2//!
3//! Every fallible SDK operation returns [`Result<T, ClientError>`]. The
4//! variants are deliberately coarse — enough to discriminate the failure
5//! mode for retry policy, but not so granular that callers have to match on
6//! every wire field.
7
8use thiserror::Error;
9
10/// The single error type returned by every fallible operation in this SDK.
11#[derive(Debug, Error)]
12#[non_exhaustive]
13pub enum ClientError {
14    /// Client setup failure (bad URL, TLS init, etc.).
15    #[error("client builder error: {0}")]
16    Builder(String),
17
18    /// HTTP transport failure (connection refused, timeout, etc.).
19    #[error("HTTP error: {0}")]
20    Http(#[from] reqwest::Error),
21
22    /// JSON encode / decode failure.
23    #[error("decode error: {0}")]
24    Decode(#[from] serde_json::Error),
25
26    /// The server returned an error envelope with a code + message.
27    ///
28    /// `code` is the HTTP status code; `msg` is the `error` field from the
29    /// MTF-native error envelope (`{"error": "..."}`).
30    #[error("protocol error ({code}): {msg}")]
31    ProtocolError {
32        /// HTTP status code returned by the server.
33        code: u16,
34        /// Error message from the server's error envelope.
35        msg: String,
36    },
37
38    /// EIP-712 signature production failed.
39    #[error("signature error: {0}")]
40    Signature(String),
41
42    /// The signature recovered does not match the wallet's address.
43    ///
44    /// This indicates an internal bug — the SDK signed a message but
45    /// recovering the signer from the digest + signature did not yield the
46    /// expected address. Should never happen in practice.
47    #[error("signature mismatch: expected signer {expected}, recovered {recovered}")]
48    SignatureMismatch {
49        /// Expected signer address (hex, no 0x prefix).
50        expected: String,
51        /// Recovered signer address (hex, no 0x prefix).
52        recovered: String,
53    },
54
55    /// Private key parsing failed (wrong length / not hex / out of curve).
56    #[error("invalid key: {0}")]
57    InvalidKey(String),
58
59    /// WebSocket transport failure.
60    #[error("websocket error: {0}")]
61    WebSocket(String),
62
63    /// User input failed local validation before any network call.
64    #[error("validation error: {0}")]
65    Validation(String),
66}
67
68impl From<k256::ecdsa::Error> for ClientError {
69    fn from(e: k256::ecdsa::Error) -> Self {
70        Self::Signature(e.to_string())
71    }
72}
73
74impl From<tokio_tungstenite::tungstenite::Error> for ClientError {
75    fn from(e: tokio_tungstenite::tungstenite::Error) -> Self {
76        Self::WebSocket(e.to_string())
77    }
78}