nautilus_kraken/execution/
mod.rs1mod futures;
35mod spot;
36
37pub use futures::KrakenFuturesExecutionClient;
38pub use spot::KrakenSpotExecutionClient;
39
40use crate::http::error::KrakenHttpError;
41
42#[derive(Debug)]
43enum CancelCommandFailure {
44 LocalValidation(String),
45 Ambiguous(String),
46 VenueReject(String),
47}
48
49impl CancelCommandFailure {
50 fn local(message: impl Into<String>) -> Self {
51 Self::LocalValidation(message.into())
52 }
53
54 fn ambiguous(message: impl Into<String>) -> Self {
55 Self::Ambiguous(message.into())
56 }
57
58 fn venue_reject(message: impl Into<String>) -> Self {
59 Self::VenueReject(message.into())
60 }
61}
62
63fn classify_cancel_http_failure(error: KrakenHttpError) -> CancelCommandFailure {
64 match error {
65 KrakenHttpError::AuthenticationError(message) => CancelCommandFailure::local(message),
66 KrakenHttpError::MissingCredentials => CancelCommandFailure::local("Missing credentials"),
67 KrakenHttpError::NetworkError(message) | KrakenHttpError::ParseError(message) => {
68 CancelCommandFailure::ambiguous(message)
69 }
70 KrakenHttpError::ApiError(message) => {
71 CancelCommandFailure::ambiguous(format_cancel_api_errors(&message))
72 }
73 }
74}
75
76fn classify_spot_single_cancel_http_failure(error: KrakenHttpError) -> CancelCommandFailure {
77 match error {
78 KrakenHttpError::ApiError(message) if contains_spot_cancel_rejection(&message) => {
79 CancelCommandFailure::venue_reject(format_cancel_api_errors(&message))
80 }
81 KrakenHttpError::ApiError(message) => {
82 CancelCommandFailure::ambiguous(format_cancel_api_errors(&message))
83 }
84 other => classify_cancel_http_failure(other),
85 }
86}
87
88fn contains_spot_cancel_rejection(errors: &[String]) -> bool {
89 errors.iter().any(|e| e.trim_start().starts_with("EOrder:"))
90}
91
92fn format_cancel_api_errors(errors: &[String]) -> String {
93 if errors.is_empty() {
94 "unknown error (empty error list)".to_string()
95 } else {
96 errors.join(", ")
97 }
98}