From b663228cd2ba0015b5ea55b010c7b021c19a94ad Mon Sep 17 00:00:00 2001 From: thesimplekid Date: Thu, 15 Feb 2024 22:40:15 +0000 Subject: [PATCH] feat: error response --- crates/cashu-sdk/Cargo.toml | 1 + crates/cashu-sdk/src/client/minreq_client.rs | 15 +++---- crates/cashu-sdk/src/client/mod.rs | 41 +++++--------------- crates/cashu-sdk/src/error.rs | 1 + crates/cashu-sdk/src/mint/mod.rs | 26 +++++++++++-- crates/cashu/src/dhke.rs | 2 - crates/cashu/src/error.rs | 19 ++++++++- 7 files changed, 58 insertions(+), 47 deletions(-) create mode 100644 crates/cashu-sdk/src/error.rs diff --git a/crates/cashu-sdk/Cargo.toml b/crates/cashu-sdk/Cargo.toml index 0d2ef9bd..8a078cb6 100644 --- a/crates/cashu-sdk/Cargo.toml +++ b/crates/cashu-sdk/Cargo.toml @@ -32,6 +32,7 @@ once_cell = { version = "1.17", optional = true } thiserror = { workspace = true } async-trait = "0.1.74" gloo = { version = "0.10.0", optional = true, features = ["net"] } +http = "1.0.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] tokio = { workspace = true, features = ["rt-multi-thread", "time", "macros", "sync"] } diff --git a/crates/cashu-sdk/src/client/minreq_client.rs b/crates/cashu-sdk/src/client/minreq_client.rs index 5eeb5509..2b3ed37a 100644 --- a/crates/cashu-sdk/src/client/minreq_client.rs +++ b/crates/cashu-sdk/src/client/minreq_client.rs @@ -1,6 +1,7 @@ //! Minreq http Client use async_trait::async_trait; +use cashu::error::ErrorResponse; use cashu::nuts::{ BlindedMessage, CurrencyUnit, Id, KeySet, KeysResponse, KeysetResponse, MeltBolt11Request, MeltBolt11Response, MeltQuoteBolt11Request, MeltQuoteBolt11Response, MintBolt11Request, @@ -53,7 +54,7 @@ impl Client for HttpClient { match response { Ok(res) => Ok(res), - Err(_) => Err(Error::from_json(&res.to_string())?), + Err(_) => Err(ErrorResponse::from_json(&res.to_string())?.into()), } } @@ -77,7 +78,7 @@ impl Client for HttpClient { Ok(res) => Ok(res), Err(_) => { warn!("Bolt11 Mint Quote Unexpected response: {:?}", res); - Err(Error::from_json(&res.status_code.to_string())?) + Err(ErrorResponse::from_json(&res.status_code.to_string())?.into()) } } } @@ -106,7 +107,7 @@ impl Client for HttpClient { match response { Ok(res) => Ok(res), - Err(_) => Err(Error::from_json(&res.to_string())?), + Err(_) => Err(ErrorResponse::from_json(&res.to_string())?.into()), } } @@ -130,7 +131,7 @@ impl Client for HttpClient { match response { Ok(res) => Ok(res), - Err(_) => Err(Error::from_json(&value.to_string())?), + Err(_) => Err(ErrorResponse::from_json(&value.to_string())?.into()), } } @@ -159,7 +160,7 @@ impl Client for HttpClient { match response { Ok(res) => Ok(res), - Err(_) => Err(Error::from_json(&value.to_string())?), + Err(_) => Err(ErrorResponse::from_json(&value.to_string())?.into()), } } @@ -204,7 +205,7 @@ impl Client for HttpClient { match response { Ok(res) => Ok(res), - Err(_) => Err(Error::from_json(&res.to_string())?), + Err(_) => Err(ErrorResponse::from_json(&res.to_string())?.into()), } } @@ -218,7 +219,7 @@ impl Client for HttpClient { match response { Ok(res) => Ok(res), - Err(_) => Err(Error::from_json(&res.to_string())?), + Err(_) => Err(ErrorResponse::from_json(&res.to_string())?.into()), } } } diff --git a/crates/cashu-sdk/src/client/mod.rs b/crates/cashu-sdk/src/client/mod.rs index b5b32bca..55031035 100644 --- a/crates/cashu-sdk/src/client/mod.rs +++ b/crates/cashu-sdk/src/client/mod.rs @@ -1,6 +1,7 @@ //! Client to connet to mint use async_trait::async_trait; +use cashu::error::ErrorResponse; #[cfg(feature = "nut07")] use cashu::nuts::CheckStateResponse; use cashu::nuts::{ @@ -10,8 +11,7 @@ use cashu::nuts::{ }; #[cfg(feature = "nut07")] use cashu::secret::Secret; -use cashu::{utils, Amount}; -use serde::{Deserialize, Serialize}; +use cashu::Amount; use thiserror::Error; use url::Url; @@ -44,44 +44,19 @@ pub enum Error { #[cfg(feature = "gloo")] #[error("`{0}`")] Gloo(String), + #[error("Unknown Error response")] + UnknownErrorResponse(cashu::error::ErrorResponse), /// Custom Error #[error("`{0}`")] Custom(String), } -impl Error { - pub fn from_json(json: &str) -> Result { - if let Ok(mint_res) = serde_json::from_str::(json) { - let err = mint_res - .error - .as_deref() - .or(mint_res.detail.as_deref()) - .unwrap_or_default(); - - let mint_error = match err { - error if error.starts_with("Lightning invoice not paid yet.") => { - Error::InvoiceNotPaid - } - error if error.starts_with("Lightning wallet not responding") => { - let mint = utils::extract_url_from_error(error); - Error::LightingWalletNotResponding(mint) - } - error => Error::Custom(error.to_owned()), - }; - Ok(mint_error) - } else { - Ok(Error::Custom(json.to_string())) - } +impl From for Error { + fn from(err: ErrorResponse) -> Error { + Self::UnknownErrorResponse(err) } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct MintErrorResponse { - code: u32, - error: Option, - detail: Option, -} - #[async_trait(?Send)] pub trait Client { async fn get_mint_keys(&self, mint_url: Url) -> Result, Error>; @@ -159,6 +134,7 @@ fn join_url(url: Url, paths: &[&str]) -> Result { #[cfg(test)] mod tests { + /* use super::*; #[test] @@ -181,4 +157,5 @@ mod tests { _ => panic!("Wrong error"), } } + */ } diff --git a/crates/cashu-sdk/src/error.rs b/crates/cashu-sdk/src/error.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/crates/cashu-sdk/src/error.rs @@ -0,0 +1 @@ + diff --git a/crates/cashu-sdk/src/mint/mod.rs b/crates/cashu-sdk/src/mint/mod.rs index 772cf66b..fc8b862c 100644 --- a/crates/cashu-sdk/src/mint/mod.rs +++ b/crates/cashu-sdk/src/mint/mod.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; use std::sync::Arc; use cashu::dhke::{sign_message, verify_message}; +use cashu::error::ErrorResponse; #[cfg(feature = "nut07")] use cashu::nuts::nut07::{ProofState, State}; use cashu::nuts::{ @@ -13,6 +14,7 @@ use cashu::nuts::{CheckStateRequest, CheckStateResponse}; use cashu::secret::Secret; use cashu::types::{MeltQuote, MintQuote}; use cashu::Amount; +use http::StatusCode; use serde::{Deserialize, Serialize}; use thiserror::Error; use tracing::{debug, error, info}; @@ -56,6 +58,22 @@ pub enum Error { MultipleUnits, } +impl From for ErrorResponse { + fn from(_err: Error) -> ErrorResponse { + ErrorResponse { + code: 9999, + error: None, + detail: None, + } + } +} + +impl From for (StatusCode, ErrorResponse) { + fn from(err: Error) -> (StatusCode, ErrorResponse) { + (StatusCode::NOT_FOUND, err.into()) + } +} + #[derive(Clone)] pub struct Mint { // pub pubkey: PublicKey @@ -177,17 +195,17 @@ impl Mint { /// Retrieve the public keys of the active keyset for distribution to /// wallet clients - pub async fn keyset_pubkeys(&self, keyset_id: &Id) -> Result, Error> { + pub async fn keyset_pubkeys(&self, keyset_id: &Id) -> Result { let keyset = match self.localstore.get_keyset(keyset_id).await? { Some(keyset) => keyset.clone(), None => { - return Ok(None); + return Err(Error::UnknownKeySet); } }; - Ok(Some(KeysResponse { + Ok(KeysResponse { keysets: vec![keyset.into()], - })) + }) } /// Retrieve the public keys of the active keyset for distribution to diff --git a/crates/cashu/src/dhke.rs b/crates/cashu/src/dhke.rs index 59b71159..ec7887b1 100644 --- a/crates/cashu/src/dhke.rs +++ b/crates/cashu/src/dhke.rs @@ -144,8 +144,6 @@ mod mint { #[cfg(test)] mod tests { - use core::panic; - use hex::decode; use k256::elliptic_curve::scalar::ScalarPrimitive; diff --git a/crates/cashu/src/error.rs b/crates/cashu/src/error.rs index 6f805aed..09f7c519 100644 --- a/crates/cashu/src/error.rs +++ b/crates/cashu/src/error.rs @@ -1,5 +1,6 @@ use std::string::FromUtf8Error; +use serde::{Deserialize, Serialize}; use thiserror::Error; #[derive(Debug, Error)] @@ -16,8 +17,6 @@ pub enum Error { /// Base64 error #[error("`{0}`")] Base64Error(#[from] base64::DecodeError), - #[error("`{0}`")] - CustomError(String), /// From hex error #[error("`{0}`")] HexError(#[from] hex::FromHexError), @@ -35,6 +34,22 @@ pub enum Error { InvoiceAmountUndefined, #[error("Proof missing required field")] MissingProofField, + /// Custom error + #[error("`{0}`")] + CustomError(String), +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct ErrorResponse { + pub code: u32, + pub error: Option, + pub detail: Option, +} + +impl ErrorResponse { + pub fn from_json(json: &str) -> Result { + serde_json::from_str(json) + } } #[cfg(feature = "wallet")]