1use hyper::http::uri::InvalidUri;
3use hyper::http::Error as HyperHttpError;
4use hyper::Error as HyperError;
5use hyper_util::client::legacy::Error as HyperClientError;
6use serde::Deserialize;
7use serde_json::Error as SerdeError;
8use std::error::Error;
9use std::fmt::{Display, Formatter};
10use url::ParseError as UrlParseError;
11
12#[derive(Debug)]
18pub enum ClientError {
19 Serde(SerdeError),
20 Hyper(HyperError),
21 HyperClient(HyperClientError),
22 HyperHttp(HyperHttpError),
23 HyperUri(InvalidUri),
24 HttpStatus(String),
25 UrlParse(UrlParseError),
26 Parse(&'static str),
27 Kraken(KrakenError),
28}
29
30impl From<HyperError> for ClientError {
31 fn from(value: HyperError) -> Self {
32 Self::Hyper(value)
33 }
34}
35
36impl From<HyperHttpError> for ClientError {
37 fn from(value: HyperHttpError) -> Self {
38 Self::HyperHttp(value)
39 }
40}
41
42impl From<HyperClientError> for ClientError {
43 fn from(value: HyperClientError) -> Self {
44 Self::HyperClient(value)
45 }
46}
47
48impl From<UrlParseError> for ClientError {
49 fn from(value: UrlParseError) -> Self {
50 Self::UrlParse(value)
51 }
52}
53
54impl From<InvalidUri> for ClientError {
55 fn from(value: InvalidUri) -> Self {
56 Self::HyperUri(value)
57 }
58}
59
60impl From<SerdeError> for ClientError {
61 fn from(value: SerdeError) -> Self {
62 Self::Serde(value)
63 }
64}
65
66impl Display for ClientError {
67 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
68 match self {
69 ClientError::Serde(err) => write!(f, "{}", err),
70 ClientError::Hyper(err) => write!(f, "{}", err),
71 ClientError::HyperClient(err) => write!(f, "{}", err),
72 ClientError::HyperHttp(err) => write!(f, "{}", err),
73 ClientError::HyperUri(err) => write!(f, "{}", err),
74 ClientError::HttpStatus(body) => write!(f, "Non-successful status with body: {}", body),
75 ClientError::UrlParse(err) => write!(f, "{}", err),
76 ClientError::Parse(err) => write!(f, "{}", err),
77 ClientError::Kraken(err) => write!(f, "{}", err),
78 }
79 }
80}
81
82impl Error for ClientError {
83 fn source(&self) -> Option<&(dyn Error + 'static)> {
84 match self {
85 ClientError::Serde(e) => Some(e),
86 ClientError::Hyper(e) => Some(e),
87 ClientError::HyperClient(e) => Some(e),
88 ClientError::HyperHttp(e) => Some(e),
89 ClientError::HyperUri(e) => Some(e),
90 ClientError::HttpStatus(_) => None,
91 ClientError::UrlParse(e) => Some(e),
92 ClientError::Parse(_) => None,
93 ClientError::Kraken(e) => Some(e),
94 }
95 }
96}
97
98#[derive(Debug, Deserialize, Eq, PartialEq, Clone)]
111pub enum KrakenError {
112 PermissionDenied,
113 InvalidKey,
114 UnknownAssetPair,
115 InvalidArguments(String),
116 InvalidSignature,
117 InvalidNonce,
118 InvalidSession,
119 BadRequest,
120 UnknownMethod,
121 RateLimitExceeded,
122 TradingRateLimitExceeded,
123 TemporaryLockout,
124 ServiceUnavailable,
125 ServiceBusy,
126 InternalError,
127 TradeLocked,
128 FeatureDisabled,
129}
130
131impl Error for KrakenError {}
132
133impl Display for KrakenError {
134 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
135 match self {
136 KrakenError::PermissionDenied => write!(f, "PermissionDenied"),
137 KrakenError::InvalidKey => write!(f, "InvalidKey"),
138 KrakenError::UnknownAssetPair => write!(f, "UnknownAssetPair"),
139 KrakenError::InvalidArguments(s) => write!(f, "{s}"),
140 KrakenError::InvalidSignature => write!(f, "InvalidSignature"),
141 KrakenError::InvalidNonce => write!(f, "InvalidNonce"),
142 KrakenError::InvalidSession => write!(f, "InvalidSession"),
143 KrakenError::BadRequest => write!(f, "BadRequest"),
144 KrakenError::UnknownMethod => write!(f, "UnknownMethod"),
145 KrakenError::RateLimitExceeded => write!(f, "RateLimitExceeded"),
146 KrakenError::TradingRateLimitExceeded => write!(f, "TradingRateLimitExceeded"),
147 KrakenError::TemporaryLockout => write!(f, "TemporaryLockout"),
148 KrakenError::ServiceUnavailable => write!(f, "ServiceUnavailable"),
149 KrakenError::ServiceBusy => write!(f, "ServiceBusy"),
150 KrakenError::InternalError => write!(f, "InternalError"),
151 KrakenError::TradeLocked => write!(f, "TradeLocked"),
152 KrakenError::FeatureDisabled => write!(f, "FeatureDisabled"),
153 }
154 }
155}
156
157impl TryFrom<&String> for KrakenError {
159 type Error = ();
160
161 fn try_from(value: &String) -> Result<Self, Self::Error> {
162 if value.starts_with("EGeneral:Permission denied") {
163 Ok(KrakenError::PermissionDenied)
164 } else if value.starts_with("EAPI:Invalid key") {
165 Ok(KrakenError::InvalidKey)
166 } else if value.starts_with("EQuery:Unknown asset pair") {
167 Ok(KrakenError::UnknownAssetPair)
168 } else if value.starts_with("EGeneral:Invalid arguments") {
169 Ok(KrakenError::InvalidArguments(value.clone()))
170 } else if value.starts_with("EAPI:Invalid signature") {
171 Ok(KrakenError::InvalidSignature)
172 } else if value.starts_with("EAPI:Invalid nonce") {
173 Ok(KrakenError::InvalidNonce)
174 } else if value.starts_with("ESession:Invalid session") {
175 Ok(KrakenError::InvalidSession)
176 } else if value.starts_with("EAPI:Bad request") {
177 Ok(KrakenError::BadRequest)
178 } else if value.starts_with("EGeneral:Unknown Method") {
179 Ok(KrakenError::UnknownMethod)
180 } else if value.starts_with("EAPI:Rate limit exceeded") {
181 Ok(KrakenError::RateLimitExceeded)
182 } else if value.starts_with("EOrder:Rate limit exceeded") {
183 Ok(KrakenError::TradingRateLimitExceeded)
184 } else if value.starts_with("EGeneral:Temporary lockout") {
185 Ok(KrakenError::TemporaryLockout)
186 } else if value.starts_with("EService:Unavailable") {
187 Ok(KrakenError::ServiceUnavailable)
188 } else if value.starts_with("EService:Busy") {
189 Ok(KrakenError::ServiceBusy)
190 } else if value.starts_with("EGeneral:Internal error") {
191 Ok(KrakenError::InternalError)
192 } else if value.starts_with("ETrade:Locked") {
193 Ok(KrakenError::TradeLocked)
194 } else if value.starts_with("EAPI:Feature disabled") {
195 Ok(KrakenError::FeatureDisabled)
196 } else {
197 Err(())
198 }
199 }
200}