etopay_sdk/
error.rs

1//! Error handling
2//!
3//! Handles all kinds of errors generated by either iota
4//! wallet or iota client or the sdk itself
5//!
6//!
7
8use crate::{
9    backend::error::ApiError, core::viviswap::ViviswapError, types::error::TypeError, user::error::UserKvStorageError,
10    wallet::error::WalletError,
11};
12use serde::{Serialize, ser::Serializer};
13use std::fmt::Display;
14
15/// A [`core::result::Result`] with [`Error`] as its error variant.
16pub type Result<T> = core::result::Result<T, Error>;
17
18/// Wrapper type for all SDK errors.
19#[derive(thiserror::Error, Serialize)]
20#[serde(tag = "type", content = "error", rename_all = "camelCase")]
21pub enum Error {
22    /// Error occurs if the config is missing
23    #[error("No config is set. Please use the set_config function.")]
24    MissingConfig,
25
26    /// Error occurs if the network is missing
27    #[error("No network is set. Please use the set_network function.")]
28    MissingNetwork,
29
30    /// Error occurs if the network is unavailable
31    #[error("Network with id {0} is unavailable.")]
32    NetworkUnavailable(String),
33
34    /// Error occurs if the chain id for evm network is missing
35    #[error("Chain ID cannot be empty for EVM network type.")]
36    EmptyChainIdForEvm,
37
38    /// Error occurs when the config is not initialized or there are missing fields
39    #[error("Error while setting the configuration: {0}")]
40    SetConfig(String),
41
42    /// Error occurs when user is not initialized
43    #[error("User is not initialized")]
44    UserNotInitialized,
45
46    /// Error occurs when the user repository is not initialized
47    #[error("User repositry is not initialized")]
48    UserRepoNotInitialized,
49
50    /// Error caused by conversions to/from Decimal and f64
51    #[error("Decimal error: {0}")]
52    #[serde(serialize_with = "display_string")]
53    Decimal(rust_decimal::Error),
54
55    /// User repository error
56    #[error("User repository error: {0}")]
57    #[serde(serialize_with = "display_string")]
58    UserRepository(#[from] UserKvStorageError),
59
60    /// Error raises if user is already kyc verified
61    #[error("User is already kyc verified")]
62    UserAlreadyKycVerified,
63
64    /// Error raises if authentication token is outdated or invalid
65    #[error("Unauthorized: Missing Access Token")]
66    MissingAccessToken,
67
68    /// Error occurs if chain id is not defined in configuration
69    #[error("Chain id is not defined")]
70    ChainIdNotDefined,
71
72    /// Error raises if chain_id cannot be converted
73    #[error("ParseChainIdError: {0}")]
74    ParseChainIdError(String),
75
76    /// Error raises if something failed to parse
77    #[error("Parse error: {0}")]
78    Parse(String),
79
80    /// User provided a negative invalid amount to send or create a purchase request with
81    #[error("CryptoAmount: {0}")]
82    #[serde(serialize_with = "debug_string")]
83    CryptoAmount(#[from] etopay_wallet::types::CryptoAmountError),
84
85    /// Error from fern logger
86    #[cfg(not(target_arch = "wasm32"))]
87    #[serde(serialize_with = "display_string")]
88    #[error("LoggerInit error: {0}")]
89    LoggerInit(fern_logger::Error),
90
91    /// Error occurs in sdk backend (api)
92    #[error("BackendApi error: {0}")]
93    #[serde(serialize_with = "debug_string")]
94    BackendApi(#[from] ApiError),
95
96    /// Error occurs in sdk types
97    #[error("Type error: {0}")]
98    #[serde(serialize_with = "debug_string")]
99    Type(#[from] TypeError),
100
101    /// Error occurs in sdk wallet
102    #[error("Wallet error: {0}")]
103    #[serde(serialize_with = "debug_string")]
104    Wallet(#[from] WalletError),
105
106    /// Error from the wallet impl
107    #[error("WalletImplError: {0}")]
108    #[serde(serialize_with = "debug_string")]
109    WalletImplError(#[from] etopay_wallet::WalletError),
110
111    /// Viviswap related errors
112    #[error("Viviswap error: {0}")]
113    #[serde(serialize_with = "debug_string")]
114    Viviswap(ViviswapError),
115}
116
117impl From<rust_decimal::Error> for Error {
118    fn from(value: rust_decimal::Error) -> Self {
119        Self::Decimal(value)
120    }
121}
122
123impl std::fmt::Debug for Error {
124    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125        error_chain_fmt(self, f)
126    }
127}
128
129/// Writes an entire error chain to the provided formatter
130fn error_chain_fmt(e: &impl std::error::Error, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131    writeln!(f, "{}\n", e)?;
132    let mut current = e.source();
133    while let Some(cause) = current {
134        writeln!(f, "Caused by:\n\t{}", cause)?;
135        current = cause.source();
136    }
137    Ok(())
138}
139
140/// Use this to serialize Error variants that implements Debug but not Serialize
141fn display_string<T, S>(value: &T, serializer: S) -> std::result::Result<S::Ok, S::Error>
142where
143    T: Display,
144    S: Serializer,
145{
146    value.to_string().serialize(serializer)
147}
148
149fn debug_string<T, S>(value: &T, serializer: S) -> std::result::Result<S::Ok, S::Error>
150where
151    T: std::fmt::Debug,
152    S: Serializer,
153{
154    format!("{:?}", value).serialize(serializer)
155}