Browse Source

feat: error response

thesimplekid 1 year ago
parent
commit
b663228cd2

+ 1 - 0
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"] }

+ 8 - 7
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()),
         }
     }
 }

+ 9 - 32
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<Self, Error> {
-        if let Ok(mint_res) = serde_json::from_str::<MintErrorResponse>(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<ErrorResponse> for Error {
+    fn from(err: ErrorResponse) -> Error {
+        Self::UnknownErrorResponse(err)
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
-pub struct MintErrorResponse {
-    code: u32,
-    error: Option<String>,
-    detail: Option<String>,
-}
-
 #[async_trait(?Send)]
 pub trait Client {
     async fn get_mint_keys(&self, mint_url: Url) -> Result<Vec<KeySet>, Error>;
@@ -159,6 +134,7 @@ fn join_url(url: Url, paths: &[&str]) -> Result<Url, Error> {
 
 #[cfg(test)]
 mod tests {
+    /*
     use super::*;
 
     #[test]
@@ -181,4 +157,5 @@ mod tests {
             _ => panic!("Wrong error"),
         }
     }
+    */
 }

+ 1 - 0
crates/cashu-sdk/src/error.rs

@@ -0,0 +1 @@
+

+ 22 - 4
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<Error> for ErrorResponse {
+    fn from(_err: Error) -> ErrorResponse {
+        ErrorResponse {
+            code: 9999,
+            error: None,
+            detail: None,
+        }
+    }
+}
+
+impl From<Error> 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<Option<KeysResponse>, Error> {
+    pub async fn keyset_pubkeys(&self, keyset_id: &Id) -> Result<KeysResponse, Error> {
         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

+ 0 - 2
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;
 

+ 17 - 2
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<String>,
+    pub detail: Option<String>,
+}
+
+impl ErrorResponse {
+    pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
+        serde_json::from_str(json)
+    }
 }
 
 #[cfg(feature = "wallet")]