Skip to main content

brokapi_bybit_protocol/
error.rs

1//! Errors of the Bybit protocol layer.
2//!
3//! [`BybitApiError`] is what every client method returns. The connector crate maps it to the broker-independent error
4//! of `brokapi-core`.
5
6use thiserror::Error;
7
8/// An error of a call to Bybit.
9#[derive(Error, Debug)]
10pub enum BybitApiError {
11    /// The transport failed, or the server answered a status that is not a success.
12    #[error("HTTP error: {message}")]
13    Http {
14        /// The HTTP status, when the server answered.
15        status: Option<u16>,
16        /// What went wrong.
17        message: String,
18    },
19
20    /// The server answered HTTP 200 with a non-zero `retCode`: a refusal of the request itself.
21    #[error("API error {code}: {message}")]
22    Api {
23        /// The `retCode`.
24        code: i64,
25        /// The `retMsg`.
26        message: String,
27    },
28
29    /// The WebSocket failed.
30    #[error("WebSocket error: {message}")]
31    Ws {
32        /// What went wrong.
33        message: String,
34    },
35
36    /// The key pair was refused (HTTP 401, or a `retCode` of authentication: 10003, 10004, 10005, 10007, 10010).
37    #[error("authorization error: {message}")]
38    Auth {
39        /// The reason the exchange gave.
40        message: String,
41    },
42
43    /// The answer is a success but is not the JSON that was expected.
44    #[error("parse error: {0}")]
45    Parse(String),
46
47    /// The request rate limit: HTTP 429, or `retCode` 10006.
48    #[error("rate limit exceeded")]
49    RateLimitExceeded,
50
51    /// A subscription could not be made.
52    #[error("subscription error: {message}")]
53    Subscription {
54        /// What went wrong.
55        message: String,
56    },
57}
58
59impl BybitApiError {
60    /// The `retCode` of a refusal, if this is one.
61    pub fn code(&self) -> Option<i64> {
62        match self {
63            BybitApiError::Api { code, .. } => Some(*code),
64            _ => None,
65        }
66    }
67}
68
69impl From<reqwest::Error> for BybitApiError {
70    fn from(err: reqwest::Error) -> Self {
71        BybitApiError::Http {
72            status: err.status().map(|s| s.as_u16()),
73            message: err.to_string(),
74        }
75    }
76}
77
78impl From<serde_json::Error> for BybitApiError {
79    fn from(err: serde_json::Error) -> Self {
80        BybitApiError::Parse(err.to_string())
81    }
82}
83
84/// The `retCode`s that mean the key pair, its rights or its IP binding are wrong.
85pub fn is_auth_code(code: i64) -> bool {
86    matches!(code, 10003 | 10004 | 10005 | 10007 | 10010 | 33004)
87}