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)]
105mod tests {
106 use rstest::rstest;
107
108 use super::*;
109
110 #[rstest]
111 fn test_build_error_display() {
112 let error = BuildError::MissingAddress;
113 assert_eq!(error.to_string(), "Missing required address parameter");
114
115 let error = BuildError::MissingTicker;
116 assert_eq!(
117 error.to_string(),
118 "Missing required market ticker parameter"
119 );
120 }
121
122 #[rstest]
123 fn test_dydx_http_error_from_string() {
124 let error: DydxHttpError = "Invalid parameter".to_string().into();
125 match error {
126 DydxHttpError::ValidationError(msg) => assert_eq!(msg, "Invalid parameter"),
127 _ => panic!("Expected ValidationError"),
128 }
129 }
130
131 #[rstest]
132 fn test_dydx_http_error_from_build_error() {
133 let build_error = BuildError::MissingSubaccountNumber;
134 let http_error: DydxHttpError = build_error.into();
135 match http_error {
136 DydxHttpError::ValidationError(msg) => {
137 assert_eq!(msg, "Missing required subaccount number");
138 }
139 _ => panic!("Expected ValidationError"),
140 }
141 }
142}