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("NegativeAmount")]
82    NegativeAmount,
83
84    /// Error from fern logger
85    #[cfg(not(target_arch = "wasm32"))]
86    #[serde(serialize_with = "display_string")]
87    #[error("LoggerInit error: {0}")]
88    LoggerInit(fern_logger::Error),
89
90    /// Error occurs in sdk backend (api)
91    #[error("BackendApi error: {0}")]
92    #[serde(serialize_with = "debug_string")]
93    BackendApi(#[from] ApiError),
94
95    /// Error occurs in sdk types
96    #[error("Type error: {0}")]
97    #[serde(serialize_with = "debug_string")]
98    Type(#[from] TypeError),
99
100    /// Error occurs in sdk wallet
101    #[error("Wallet error: {0}")]
102    #[serde(serialize_with = "debug_string")]
103    Wallet(#[from] WalletError),
104
105    /// Viviswap related errors
106    #[error("Viviswap error: {0}")]
107    #[serde(serialize_with = "debug_string")]
108    Viviswap(ViviswapError),
109}
110
111impl From<rust_decimal::Error> for Error {
112    fn from(value: rust_decimal::Error) -> Self {
113        Self::Decimal(value)
114    }
115}
116
117impl std::fmt::Debug for Error {
118    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
119        error_chain_fmt(self, f)
120    }
121}
122
123/// Writes an entire error chain to the provided formatter
124fn error_chain_fmt(e: &impl std::error::Error, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125    writeln!(f, "{}\n", e)?;
126    let mut current = e.source();
127    while let Some(cause) = current {
128        writeln!(f, "Caused by:\n\t{}", cause)?;
129        current = cause.source();
130    }
131    Ok(())
132}
133
134/// Use this to serialize Error variants that implements Debug but not Serialize
135fn display_string<T, S>(value: &T, serializer: S) -> std::result::Result<S::Ok, S::Error>
136where
137    T: Display,
138    S: Serializer,
139{
140    value.to_string().serialize(serializer)
141}
142
143fn debug_string<T, S>(value: &T, serializer: S) -> std::result::Result<S::Ok, S::Error>
144where
145    T: std::fmt::Debug,
146    S: Serializer,
147{
148    format!("{:?}", value).serialize(serializer)
149}