use adapters::generics::{
http::{ApiError, AuthError, HandleError, IpError, RequestError},
ws::WsError,
};
use v_utils::{
prelude::*,
trades::Timeframe,
utils::{Sysexit, SysexitCode},
};
use crate::{ExchangeName, Instrument};
pub type ExchangeResult<T> = Result<T, Error>;
impl From<RequestError> for Error {
fn from(e: RequestError) -> Self {
match e {
RequestError::HandleResponse(HandleError::Api(ApiError::Auth(auth))) => Self::Auth(auth),
RequestError::HandleResponse(HandleError::Api(ApiError::Ip(ip))) => Self::Ip(ip),
other => Self::Request(other),
}
}
}
pub use Error as ExchangeError;
#[derive(Debug, miette::Diagnostic, derive_more::Display, thiserror::Error, derive_more::From)]
pub enum Error {
#[diagnostic(transparent)]
#[from(skip)]
Request(RequestError),
#[diagnostic(transparent)]
Ws(WsError),
#[diagnostic(transparent)]
Timeframe(UnsupportedTimeframeError),
#[diagnostic(transparent)]
Range(RequestRangeError),
#[diagnostic(transparent)]
Auth(AuthError),
#[diagnostic(transparent)]
Ip(IpError),
#[diagnostic(transparent)]
Method(MethodError),
#[diagnostic(code(v_exchanges::other))]
Other(Report),
}
impl SysexitCode for Error {
fn sysexit(&self) -> Sysexit {
match self {
Self::Auth(_) | Self::Ip(_) => Sysexit::NoPerm,
_ => Sysexit::None,
}
}
}
#[derive(Debug, miette::Diagnostic, thiserror::Error, derive_new::new)]
#[error("Chosen exchange does not support the requested timeframe. Provided: {provided}, allowed: {allowed:?}")]
#[diagnostic(code(v_exchanges::unsupported_timeframe), help("Use one of the allowed timeframes for this exchange."))]
pub struct UnsupportedTimeframeError {
provided: Timeframe,
allowed: Vec<Timeframe>,
}
#[derive(Debug, miette::Diagnostic, thiserror::Error, derive_new::new)]
pub enum MethodError {
#[error("Method not implemented for the requested exchange and instrument: ({exchange}, {instrument})")]
#[diagnostic(
code(v_exchanges::method::not_implemented),
help("This method is not expected to be implemented for this exchange/instrument combination.")
)]
MethodNotImplemented { exchange: ExchangeName, instrument: Instrument },
#[error("Requested exchange does not support the method for chosen instrument: ({exchange}, {instrument})")]
#[diagnostic(code(v_exchanges::method::not_supported), help("This exchange does not support this method for the specified instrument type."))]
MethodNotSupported { exchange: ExchangeName, instrument: Instrument },
}
#[derive(Debug, miette::Diagnostic, derive_more::Display, thiserror::Error, derive_more::From)]
pub enum RequestRangeError {
#[diagnostic(transparent)]
OutOfRange(OutOfRangeError),
#[diagnostic(code(v_exchanges::range::other))]
Others(Report),
}
#[derive(derive_more::Debug, miette::Diagnostic, thiserror::Error, derive_new::new)]
#[diagnostic(code(v_exchanges::range::out_of_range), help("Adjust the request parameters to fall within the allowed range."))]
pub struct OutOfRangeError {
allowed: std::ops::RangeInclusive<u32>,
provided: u32,
}
impl std::fmt::Display for OutOfRangeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Effective provided limit is out of range (could be translated from Start:End / tf). Allowed: {:?}, provided: {}",
self.allowed, self.provided
)
}
}