1#[derive(Debug, thiserror::Error)]
31pub enum BybitError {
32 RequestError(#[from] reqwest::Error),
33
34 ApiError {
35 ret_code: i32,
36 ret_msg: String,
37 },
38
39 InvalidTimestamp(String),
40
41 SerializationError(#[from] serde_json::Error),
42
43 InvalidParameter(String),
44
45 AuthenticationError(String),
46
47 RateLimitExceeded {
48 limit_type: String,
49 limit_reset_ms: Option<u64>,
50 },
51
52 InvalidEnumValue {
53 enum_name: String,
54 value: String,
55 },
56
57 MissingRequiredField {
58 field_name: String,
59 },
60}
61
62impl std::fmt::Display for BybitError {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 match self {
65 BybitError::RequestError(e) => write!(f, "HTTP request failed: {}", e),
66 BybitError::ApiError { ret_code, ret_msg } => {
67 write!(f, "API error (code {}): {}", ret_code, ret_msg)
68 }
69 BybitError::InvalidTimestamp(msg) => {
70 write!(f, "Invalid timestamp: {}", msg)
71 }
72 BybitError::SerializationError(e) => {
73 write!(f, "Serialization error: {}", e)
74 }
75 BybitError::InvalidParameter(msg) => {
76 write!(f, "Invalid parameter: {}", msg)
77 }
78 BybitError::AuthenticationError(msg) => {
79 write!(f, "Authentication failed: {}", msg)
80 }
81 BybitError::RateLimitExceeded { limit_type, .. } => {
82 write!(f, "Rate limit exceeded: {}", limit_type)
83 }
84 BybitError::InvalidEnumValue { enum_name, value } => {
85 write!(f, "Invalid enum value for {}: {}", enum_name, value)
86 }
87 BybitError::MissingRequiredField { field_name } => {
88 write!(f, "Missing required field: {}", field_name)
89 }
90 }
91 }
92}
93
94pub type Result<T> = std::result::Result<T, BybitError>;
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_bybit_error_display_api_error() {
102 let error = BybitError::ApiError {
103 ret_code: 10001,
104 ret_msg: "Invalid request".to_string(),
105 };
106
107 let display = format!("{}", error);
108 assert!(display.contains("API error"));
109 assert!(display.contains("10001"));
110 assert!(display.contains("Invalid request"));
111 }
112
113 #[test]
114 fn test_bybit_error_display_invalid_timestamp() {
115 let error = BybitError::InvalidTimestamp("Timestamp expired".to_string());
116
117 let display = format!("{}", error);
118 assert!(display.contains("Invalid timestamp"));
119 assert!(display.contains("Timestamp expired"));
120 }
121
122 #[test]
123 fn test_bybit_error_display_serialization_error() {
124 let json_error = serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
125 let error = BybitError::SerializationError(json_error);
126
127 let display = format!("{}", error);
128 assert!(display.contains("Serialization error"));
129 }
130
131 #[test]
132 fn test_bybit_error_display_invalid_parameter() {
133 let error = BybitError::InvalidParameter("Invalid symbol".to_string());
134
135 let display = format!("{}", error);
136 assert!(display.contains("Invalid parameter"));
137 assert!(display.contains("Invalid symbol"));
138 }
139
140 #[test]
141 fn test_bybit_error_display_authentication_error() {
142 let error = BybitError::AuthenticationError("Invalid signature".to_string());
143
144 let display = format!("{}", error);
145 assert!(display.contains("Authentication failed"));
146 assert!(display.contains("Invalid signature"));
147 }
148
149 #[test]
150 fn test_bybit_error_display_rate_limit_exceeded() {
151 let error = BybitError::RateLimitExceeded {
152 limit_type: "API".to_string(),
153 limit_reset_ms: Some(5000),
154 };
155
156 let display = format!("{}", error);
157 assert!(display.contains("Rate limit exceeded"));
158 assert!(display.contains("API"));
159 }
160
161 #[test]
162 fn test_bybit_error_display_invalid_enum_value() {
163 let error = BybitError::InvalidEnumValue {
164 enum_name: "Side".to_string(),
165 value: "InvalidSide".to_string(),
166 };
167
168 let display = format!("{}", error);
169 assert!(display.contains("Invalid enum value"));
170 assert!(display.contains("Side"));
171 assert!(display.contains("InvalidSide"));
172 }
173
174 #[test]
175 fn test_bybit_error_display_missing_required_field() {
176 let error = BybitError::MissingRequiredField {
177 field_name: "symbol".to_string(),
178 };
179
180 let display = format!("{}", error);
181 assert!(display.contains("Missing required field"));
182 assert!(display.contains("symbol"));
183 }
184
185 #[test]
186 fn test_bybit_error_debug() {
187 let error = BybitError::ApiError {
188 ret_code: 10006,
189 ret_msg: "Rate limit exceeded".to_string(),
190 };
191
192 let debug = format!("{:?}", error);
193 assert!(debug.contains("ApiError"));
194 }
195}