barter_execution/
error.rs

1use barter_instrument::{
2    asset::{AssetIndex, name::AssetNameExchange},
3    exchange::ExchangeId,
4    instrument::{InstrumentIndex, name::InstrumentNameExchange},
5};
6use barter_integration::error::SocketError;
7use serde::{Deserialize, Serialize};
8use thiserror::Error;
9
10/// Type alias for a [`ClientError`] that is keyed on [`AssetNameExchange`] and
11/// [`InstrumentNameExchange`] (yet to be indexed).
12pub type UnindexedClientError = ClientError<AssetNameExchange, InstrumentNameExchange>;
13
14/// Type alias for a [`ApiError`] that is keyed on [`AssetNameExchange`] and
15/// [`InstrumentNameExchange`] (yet to be indexed).
16pub type UnindexedApiError = ApiError<AssetNameExchange, InstrumentNameExchange>;
17
18/// Type alias for a [`OrderError`] that is keyed on [`AssetNameExchange`] and
19/// [`InstrumentNameExchange`] (yet to be indexed).
20pub type UnindexedOrderError = OrderError<AssetNameExchange, InstrumentNameExchange>;
21
22/// Represents all errors produced by an [`ExecutionClient`](super::client::ExecutionClient).
23#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Error)]
24pub enum ClientError<AssetKey = AssetIndex, InstrumentKey = InstrumentIndex> {
25    /// Connectivity based error.
26    ///
27    /// eg/ Timeout.
28    #[error("Connectivity: {0}")]
29    Connectivity(#[from] ConnectivityError),
30
31    /// API based error.
32    ///
33    /// eg/ RateLimit.
34    #[error("API: {0}")]
35    Api(#[from] ApiError<AssetKey, InstrumentKey>),
36
37    /// Failed to fetch an AccountSnapshot.
38    #[error("failed to fetch AccountSnapshot: {0}")]
39    AccountSnapshot(String),
40
41    /// Failed to initialise an AccountStream.
42    #[error("failed to init AccountStream: {0}")]
43    AccountStream(String),
44}
45
46/// Represents all connectivity-centric errors.
47///
48/// Connectivity errors are generally intermittent / non-deterministic (eg/ Timeout).
49#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Error)]
50pub enum ConnectivityError {
51    /// Indicates an exchange is offline, likely due to maintenance.
52    #[error("Exchange offline: {0}")]
53    ExchangeOffline(ExchangeId),
54
55    /// Indicates an ExecutionRequest timed out before a response was received.
56    #[error("ExecutionRequest timed out")]
57    Timeout,
58
59    /// Represents a [`SocketError`] generated by an execution integration.
60    #[error("{0}")]
61    Socket(String),
62}
63
64impl From<SocketError> for ConnectivityError {
65    fn from(value: SocketError) -> Self {
66        Self::Socket(value.to_string())
67    }
68}
69
70/// Represents all API errors generated by an exchange.
71///
72/// These typically indicate a request is invalid for some reason (eg/ BalanceInsufficient).
73#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Error)]
74pub enum ApiError<AssetKey = AssetIndex, InstrumentKey = InstrumentIndex> {
75    /// Provided asset identifier is invalid or not supported.
76    ///
77    /// For example:
78    /// - The [`AssetNameExchange`] was an invalid format.
79    #[error("asset {0} invalid: {1}")]
80    AssetInvalid(AssetKey, String),
81
82    /// Provided instrument identifier is invalid or not supported.
83    ///
84    /// For example:
85    /// - The exchange does not have a market for an instrument.
86    /// - The [`InstrumentNameExchange`] was an invalid format.
87    #[error("instrument {0} invalid: {1}")]
88    InstrumentInvalid(InstrumentKey, String),
89
90    #[error("rate limit exceeded")]
91    RateLimit,
92    #[error("asset {0} balance insufficient: {1}")]
93    BalanceInsufficient(AssetKey, String),
94    #[error("order rejected: {0}")]
95    OrderRejected(String),
96    #[error("order already cancelled")]
97    OrderAlreadyCancelled,
98    #[error("order already fully filled")]
99    OrderAlreadyFullyFilled,
100}
101
102/// Represents all errors that can be generated when cancelling or opening orders.
103#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Error)]
104pub enum OrderError<AssetKey = AssetIndex, InstrumentKey = InstrumentIndex> {
105    /// Connectivity based error.
106    ///
107    /// eg/ Timeout.
108    #[error("connectivity: {0}")]
109    Connectivity(#[from] ConnectivityError),
110
111    /// API based error.
112    ///
113    /// eg/ RateLimit.
114    #[error("order rejected: {0}")]
115    Rejected(#[from] ApiError<AssetKey, InstrumentKey>),
116}
117
118/// Represents errors related to exchange, asset and instrument identifier key lookups.
119#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deserialize, Serialize, Error)]
120pub enum KeyError {
121    /// Indicates an [`ExchangeId`] was encountered that was not indexed, so does not have a
122    /// corresponding `ExchangeIndex`.
123    #[error("ExchangeId: {0}")]
124    ExchangeId(String),
125
126    /// Indicates an [`AssetNameExchange`] was encountered that was not indexed, so does not have a
127    /// corresponding [`AssetIndex`].
128    #[error("AssetKey: {0}")]
129    AssetKey(String),
130
131    /// Indicates an [`InstrumentNameExchange`] was encountered that was no indexed, so does
132    /// not have a corresponding [`InstrumentIndex`].
133    #[error("InstrumentKey: {0}")]
134    InstrumentKey(String),
135}