use std::fmt;
use std::string::FromUtf8Error;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Value;
use thiserror::Error;
use crate::util::hex;
#[derive(Debug, Error)]
pub enum Error {
#[error("No Key for Amount")]
AmountKey,
#[error("Not enough input proofs spent")]
InsufficientInputProofs,
#[error("Database error")]
DatabaseError,
#[error("Unit unsupported")]
UnsupportedUnit,
#[error("Payment failed")]
PaymentFailed,
#[error("Melt request is not valid")]
MeltRequestInvalid,
#[error("Request already paid")]
RequestAlreadyPaid,
#[error("Amount miss match")]
Amount,
#[error("Token already spent")]
TokenSpent,
#[error("Token not verified")]
TokenNotVerified,
#[error("Invalid payment request")]
InvalidPaymentRequest,
#[error("Invoice Amount undefined")]
InvoiceAmountUndefined,
#[error("Proof missing required field")]
MissingProofField,
#[error("No valid point found")]
NoValidPoint,
#[error("Split Values must be less then or equal to amount")]
SplitValuesGreater,
#[error(transparent)]
Secp256k1(#[from] bitcoin::secp256k1::Error),
#[error(transparent)]
Secret(#[from] super::secret::Error),
#[error(transparent)]
Bip32(#[from] bitcoin::bip32::Error),
#[error(transparent)]
ParseInt(#[from] std::num::ParseIntError),
#[error(transparent)]
UrlParseError(#[from] url::ParseError),
#[error(transparent)]
Utf8ParseError(#[from] FromUtf8Error),
#[error(transparent)]
SerdeJsonError(#[from] serde_json::Error),
#[error(transparent)]
Base64Error(#[from] base64::DecodeError),
#[error(transparent)]
HexError(#[from] hex::Error),
#[cfg(feature = "wallet")]
#[error(transparent)]
ReqwestError(#[from] reqwest::Error),
#[error(transparent)]
NUT01(#[from] crate::nuts::nut01::Error),
#[error(transparent)]
NUT02(#[from] crate::nuts::nut02::Error),
#[error(transparent)]
NUT11(#[from] crate::nuts::nut11::Error),
#[error("`{0}`")]
CustomError(String),
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ErrorResponse {
pub code: ErrorCode,
pub error: Option<String>,
pub detail: Option<String>,
}
impl fmt::Display for ErrorResponse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"code: {}, error: {}, detail: {}",
self.code,
self.error.clone().unwrap_or_default(),
self.detail.clone().unwrap_or_default()
)
}
}
impl ErrorResponse {
pub fn new(code: ErrorCode, error: Option<String>, detail: Option<String>) -> Self {
Self {
code,
error,
detail,
}
}
pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
let value: Value = serde_json::from_str(json)?;
Self::from_value(value)
}
pub fn from_value(value: Value) -> Result<Self, serde_json::Error> {
match serde_json::from_value::<ErrorResponse>(value.clone()) {
Ok(res) => Ok(res),
Err(_) => Ok(Self {
code: ErrorCode::Unknown(999),
error: Some(value.to_string()),
detail: None,
}),
}
}
}
impl From<Error> for ErrorResponse {
fn from(err: Error) -> ErrorResponse {
match err {
Error::TokenSpent => ErrorResponse {
code: ErrorCode::TokenAlreadySpent,
error: Some(err.to_string()),
detail: None,
},
_ => ErrorResponse {
code: ErrorCode::Unknown(9999),
error: Some(err.to_string()),
detail: None,
},
}
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
pub enum ErrorCode {
TokenAlreadySpent,
QuoteNotPaid,
KeysetNotFound,
Unknown(u16),
}
impl Serialize for ErrorCode {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let code = match self {
ErrorCode::TokenAlreadySpent => 11001,
ErrorCode::QuoteNotPaid => 20001,
ErrorCode::KeysetNotFound => 12001,
ErrorCode::Unknown(code) => *code,
};
serializer.serialize_u16(code)
}
}
impl<'de> Deserialize<'de> for ErrorCode {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let code = u16::deserialize(deserializer)?;
let error_code = match code {
11001 => ErrorCode::TokenAlreadySpent,
20001 => ErrorCode::QuoteNotPaid,
12001 => ErrorCode::KeysetNotFound,
c => ErrorCode::Unknown(c),
};
Ok(error_code)
}
}
impl fmt::Display for ErrorCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let code = match self {
Self::TokenAlreadySpent => 11001,
Self::QuoteNotPaid => 20001,
Self::KeysetNotFound => 12001,
Self::Unknown(code) => *code,
};
write!(f, "{}", code)
}
}