nautilus_bybit/http/
error.rs1use nautilus_network::http::HttpClientError;
24use serde::{Deserialize, Serialize};
25use thiserror::Error;
26
27#[derive(Debug, Clone, Error)]
29pub enum BybitBuildError {
30 #[error("Missing required category")]
32 MissingCategory,
33 #[error("Missing required symbol")]
35 MissingSymbol,
36 #[error("Missing required interval")]
38 MissingInterval,
39 #[error("Invalid limit: must be between 1 and 1000")]
41 InvalidLimit,
42 #[error("Invalid time range: start ({start}) must be less than end ({end})")]
44 InvalidTimeRange { start: i64, end: i64 },
45 #[error("Cannot specify both 'orderId' and 'orderLinkId'")]
47 BothOrderIds,
48 #[error("Missing required order identifier (orderId or orderLinkId)")]
50 MissingOrderId,
51}
52
53#[derive(Clone, Debug, Deserialize, Serialize)]
58#[serde(rename_all = "camelCase")]
59pub struct BybitErrorResponse {
60 pub ret_code: i32,
62 pub ret_msg: String,
64 #[serde(default)]
66 pub ret_ext_info: Option<serde_json::Value>,
67}
68
69#[derive(Debug, Clone, Error)]
71pub enum BybitHttpError {
72 #[error("Missing credentials for authenticated request")]
74 MissingCredentials,
75 #[error("Bybit error {error_code}: {message}")]
77 BybitError { error_code: i32, message: String },
78 #[error("JSON error: {0}")]
80 JsonError(String),
81 #[error("Parameter validation error: {0}")]
83 ValidationError(String),
84 #[error("Build error: {0}")]
86 BuildError(#[from] BybitBuildError),
87 #[error("Request canceled: {0}")]
89 Canceled(String),
90 #[error("Network error: {0}")]
92 NetworkError(String),
93 #[error("Unexpected HTTP status code {status}: {body}")]
95 UnexpectedStatus { status: u16, body: String },
96}
97
98impl From<HttpClientError> for BybitHttpError {
99 fn from(error: HttpClientError) -> Self {
100 Self::NetworkError(error.to_string())
101 }
102}
103
104impl From<String> for BybitHttpError {
105 fn from(error: String) -> Self {
106 Self::ValidationError(error)
107 }
108}
109
110impl From<serde_json::Error> for BybitHttpError {
113 fn from(error: serde_json::Error) -> Self {
114 Self::JsonError(error.to_string())
115 }
116}
117
118impl From<BybitErrorResponse> for BybitHttpError {
119 fn from(error: BybitErrorResponse) -> Self {
120 Self::BybitError {
121 error_code: error.ret_code,
122 message: error.ret_msg,
123 }
124 }
125}
126
127#[cfg(test)]
132mod tests {
133 use rstest::rstest;
134
135 use super::*;
136
137 #[rstest]
138 fn test_bybit_build_error_display() {
139 let error = BybitBuildError::MissingSymbol;
140 assert_eq!(error.to_string(), "Missing required symbol");
141
142 let error = BybitBuildError::InvalidLimit;
143 assert_eq!(
144 error.to_string(),
145 "Invalid limit: must be between 1 and 1000"
146 );
147
148 let error = BybitBuildError::InvalidTimeRange {
149 start: 100,
150 end: 50,
151 };
152 assert_eq!(
153 error.to_string(),
154 "Invalid time range: start (100) must be less than end (50)"
155 );
156 }
157
158 #[rstest]
159 fn test_bybit_http_error_from_error_response() {
160 let error_response = BybitErrorResponse {
161 ret_code: 10001,
162 ret_msg: "Parameter error".to_string(),
163 ret_ext_info: None,
164 };
165
166 let http_error: BybitHttpError = error_response.into();
167 assert_eq!(http_error.to_string(), "Bybit error 10001: Parameter error");
168 }
169
170 #[rstest]
171 fn test_bybit_http_error_from_json_error() {
172 let json_err = serde_json::from_str::<BybitErrorResponse>("invalid json").unwrap_err();
173 let http_error: BybitHttpError = json_err.into();
174 assert!(http_error.to_string().contains("JSON error"));
175 }
176
177 #[rstest]
178 fn test_bybit_http_error_from_string() {
179 let error_msg = "Invalid parameter value".to_string();
180 let http_error: BybitHttpError = error_msg.into();
181 assert_eq!(
182 http_error.to_string(),
183 "Parameter validation error: Invalid parameter value"
184 );
185 }
186
187 #[rstest]
188 fn test_unexpected_status_error() {
189 let error = BybitHttpError::UnexpectedStatus {
190 status: 502,
191 body: "Server error".to_string(),
192 };
193 assert_eq!(
194 error.to_string(),
195 "Unexpected HTTP status code 502: Server error"
196 );
197 }
198}