Skip to main content

rust_okx/
error.rs

1//! Error types returned by the crate.
2
3use crate::transport::TransportError;
4#[cfg(feature = "websocket")]
5pub use crate::ws::WsError;
6
7type BoxError = Box<dyn std::error::Error + Send + Sync>;
8
9/// A type alias for [`std::result::Result`] using this crate's [`Error`].
10pub type Result<T> = std::result::Result<T, Error>;
11
12/// Top-level error type.
13///
14/// Wraps [`RestError`] (REST layer), optionally [`WsError`] (WebSocket layer),
15/// and [`RequestValidationError`] (shared pre-flight validation).
16///
17/// The enum is [`#[non_exhaustive]`](https://doc.rust-lang.org/reference/attributes/type_system.html)
18/// so new variants can be added without a breaking change.
19#[derive(Debug, thiserror::Error)]
20#[non_exhaustive]
21pub enum Error {
22    /// An error from the REST API layer.
23    #[error(transparent)]
24    Rest(#[from] RestError),
25
26    /// An error from the WebSocket layer.
27    #[cfg(feature = "websocket")]
28    #[error(transparent)]
29    Ws(#[from] WsError),
30}
31
32/// Errors from the REST API layer.
33#[derive(Debug, thiserror::Error)]
34#[non_exhaustive]
35pub enum RestError {
36    /// The underlying HTTP transport failed (connection, TLS, timeout, …).
37    #[error("transport error: {source}")]
38    Transport {
39        /// Finding the position of the error
40        #[from]
41        source: TransportError,
42    },
43
44    /// The HTTP response had a non-success status before the OKX envelope
45    /// could be decoded.
46    #[error("HTTP {status} from {endpoint}")]
47    HttpStatus {
48        /// The endpoint path, e.g. `/api/v5/account/balance`.
49        endpoint: &'static str,
50        /// HTTP response status code.
51        status: http::StatusCode,
52        /// Response body, decoded lossily as UTF-8 for diagnostics.
53        body: String,
54    },
55
56    /// OKX returned a non-zero response code.
57    #[error("OKX API error {code} from {endpoint}: {message}")]
58    Okx {
59        /// The endpoint path.
60        endpoint: &'static str,
61        /// OKX error code (e.g. `"50011"`). Kept as a string deliberately.
62        code: String,
63        /// Human-readable error message from OKX.
64        message: String,
65    },
66
67    /// The response body could not be decoded into the expected model.
68    #[error("failed to decode response from {endpoint}")]
69    Decode {
70        /// The endpoint path.
71        endpoint: &'static str,
72        /// The underlying deserialization error.
73        #[source]
74        source: serde_json::Error,
75    },
76
77    /// The request could not be encoded (query string, JSON body, or headers).
78    #[error("failed to encode request")]
79    Encode {
80        /// The underlying encoding error.
81        #[source]
82        source: BoxError,
83    },
84
85    /// The client was used in an invalid way (e.g. an authenticated endpoint
86    /// was called without credentials).
87    #[error("invalid configuration: {0}")]
88    Configuration(String),
89}