nautilus_dydx/http/
error.rs1use serde::Deserialize;
22use thiserror::Error;
23
24#[derive(Debug, Error)]
26pub enum BuildError {
27 #[error("Missing required address parameter")]
29 MissingAddress,
30 #[error("Missing required market ticker parameter")]
32 MissingTicker,
33 #[error("Missing required subaccount number")]
35 MissingSubaccountNumber,
36 #[error("Cannot specify both 'createdBeforeOrAt' and 'createdBeforeOrAtHeight' parameters")]
38 BothCreatedBeforeParams,
39 #[error("Cannot specify both 'createdOnOrAfter' and 'createdOnOrAfterHeight' parameters")]
41 BothCreatedAfterParams,
42 #[error("Invalid time range: from_iso must be before to_iso")]
44 InvalidTimeRange,
45 #[error("Limit exceeds maximum allowed value")]
47 LimitTooHigh,
48 #[error("Invalid resolution parameter: {0}")]
50 InvalidResolution(String),
51}
52
53#[derive(Clone, Debug, Deserialize)]
55pub struct DydxErrorResponse {
56 #[serde(default)]
58 pub status: Option<u16>,
59 pub message: String,
61 #[serde(default)]
63 pub details: Option<String>,
64}
65
66#[derive(Debug, Error)]
68pub enum DydxHttpError {
69 #[error("dYdX API error {status}: {message}")]
71 HttpStatus { status: u16, message: String },
72 #[error("Serialization error: {error}")]
74 Serialization { error: String },
75 #[error("Deserialization error: {error}, body: {body}")]
77 Deserialization { error: String, body: String },
78 #[error("Parameter validation error: {0}")]
80 ValidationError(String),
81 #[error("Request canceled: {0}")]
83 Canceled(String),
84 #[error("Network error: {0}")]
86 HttpClientError(String),
87 #[error("Unexpected HTTP status code {status}: {body}")]
89 UnexpectedStatus { status: u16, body: String },
90}
91
92impl From<String> for DydxHttpError {
93 fn from(error: String) -> Self {
94 Self::ValidationError(error)
95 }
96}
97
98impl From<BuildError> for DydxHttpError {
99 fn from(error: BuildError) -> Self {
100 Self::ValidationError(error.to_string())
101 }
102}
103
104#[cfg(test)]
109mod tests {
110 use rstest::rstest;
111
112 use super::*;
113
114 #[rstest]
115 fn test_build_error_display() {
116 let error = BuildError::MissingAddress;
117 assert_eq!(error.to_string(), "Missing required address parameter");
118
119 let error = BuildError::MissingTicker;
120 assert_eq!(
121 error.to_string(),
122 "Missing required market ticker parameter"
123 );
124 }
125
126 #[rstest]
127 fn test_dydx_http_error_from_string() {
128 let error: DydxHttpError = "Invalid parameter".to_string().into();
129 match error {
130 DydxHttpError::ValidationError(msg) => assert_eq!(msg, "Invalid parameter"),
131 _ => panic!("Expected ValidationError"),
132 }
133 }
134
135 #[rstest]
136 fn test_dydx_http_error_from_build_error() {
137 let build_error = BuildError::MissingSubaccountNumber;
138 let http_error: DydxHttpError = build_error.into();
139 match http_error {
140 DydxHttpError::ValidationError(msg) => {
141 assert_eq!(msg, "Missing required subaccount number");
142 }
143 _ => panic!("Expected ValidationError"),
144 }
145 }
146}