From 0aad2aacb9121ea2871e269f6758148441e2d55d Mon Sep 17 00:00:00 2001 From: Cesar Rodas Date: Tue, 19 Nov 2024 18:25:25 -0300 Subject: [PATCH] Improve Http client Store the HTTP response as string instead of parsing as a json::Value and cloning it several times. --- crates/cdk/src/wallet/client.rs | 122 +++++++++++--------------------- 1 file changed, 42 insertions(+), 80 deletions(-) diff --git a/crates/cdk/src/wallet/client.rs b/crates/cdk/src/wallet/client.rs index 4296e6c2..15aefa8c 100644 --- a/crates/cdk/src/wallet/client.rs +++ b/crates/cdk/src/wallet/client.rs @@ -4,7 +4,6 @@ use std::fmt::Debug; use async_trait::async_trait; use reqwest::Client; -use serde_json::Value; use tracing::instrument; use url::Url; @@ -18,6 +17,18 @@ use crate::nuts::{ RestoreResponse, SwapRequest, SwapResponse, }; +macro_rules! convert_http_response { + ($type:ty, $data:ident) => { + serde_json::from_str::<$type>(&$data).map_err(|err| { + tracing::warn!("Http Response error: {}", err); + match ErrorResponse::from_json(&$data) { + Ok(ok) => >::into(ok), + Err(err) => err.into(), + } + }) + }; +} + /// Http Client #[derive(Debug, Clone)] pub struct HttpClient { @@ -76,36 +87,31 @@ impl HttpClientMethods for HttpClient { #[instrument(skip(self), fields(mint_url = %mint_url))] async fn get_mint_keys(&self, mint_url: MintUrl) -> Result, Error> { let url = mint_url.join_paths(&["v1", "keys"])?; - let keys = self.inner.get(url).send().await?.json::().await?; + let keys = self.inner.get(url).send().await?.text().await?; - match serde_json::from_value::(keys.clone()) { - Ok(keys_response) => Ok(keys_response.keysets), - Err(_) => Err(ErrorResponse::from_value(keys)?.into()), - } + Ok(convert_http_response!(KeysResponse, keys)?.keysets) } /// Get Keyset Keys [NUT-01] #[instrument(skip(self), fields(mint_url = %mint_url))] async fn get_mint_keyset(&self, mint_url: MintUrl, keyset_id: Id) -> Result { let url = mint_url.join_paths(&["v1", "keys", &keyset_id.to_string()])?; - let keys = self.inner.get(url).send().await?.json::().await?; + let keys = self.inner.get(url).send().await?.text().await?; - match serde_json::from_value::(keys.clone()) { - Ok(keys_response) => Ok(keys_response.keysets[0].clone()), - Err(_) => Err(ErrorResponse::from_value(keys)?.into()), - } + convert_http_response!(KeysResponse, keys)? + .keysets + .drain(0..1) + .next() + .ok_or_else(|| Error::UnknownKeySet) } /// Get Keysets [NUT-02] #[instrument(skip(self), fields(mint_url = %mint_url))] async fn get_mint_keysets(&self, mint_url: MintUrl) -> Result { let url = mint_url.join_paths(&["v1", "keysets"])?; - let res = self.inner.get(url).send().await?.json::().await?; + let res = self.inner.get(url).send().await?.text().await?; - match serde_json::from_value::(res.clone()) { - Ok(keyset_response) => Ok(keyset_response), - Err(_) => Err(ErrorResponse::from_value(res)?.into()), - } + convert_http_response!(KeysetResponse, res) } /// Mint Quote [NUT-04] @@ -123,16 +129,10 @@ impl HttpClientMethods for HttpClient { .json(&request) .send() .await? - .json::() + .text() .await?; - match serde_json::from_value::(res.clone()) { - Ok(mint_quote_response) => Ok(mint_quote_response), - Err(err) => { - tracing::warn!("{}", err); - Err(ErrorResponse::from_value(res)?.into()) - } - } + convert_http_response!(MintQuoteBolt11Response, res) } /// Mint Quote status @@ -144,15 +144,9 @@ impl HttpClientMethods for HttpClient { ) -> Result { let url = mint_url.join_paths(&["v1", "mint", "quote", "bolt11", quote_id])?; - let res = self.inner.get(url).send().await?.json::().await?; + let res = self.inner.get(url).send().await?.text().await?; - match serde_json::from_value::(res.clone()) { - Ok(mint_quote_response) => Ok(mint_quote_response), - Err(err) => { - tracing::warn!("{}", err); - Err(ErrorResponse::from_value(res)?.into()) - } - } + convert_http_response!(MintQuoteBolt11Response, res) } /// Mint Tokens [NUT-04] @@ -170,13 +164,10 @@ impl HttpClientMethods for HttpClient { .json(&request) .send() .await? - .json::() + .text() .await?; - match serde_json::from_value::(res.clone()) { - Ok(mint_quote_response) => Ok(mint_quote_response), - Err(_) => Err(ErrorResponse::from_value(res)?.into()), - } + convert_http_response!(MintBolt11Response, res) } /// Melt Quote [NUT-05] @@ -194,13 +185,10 @@ impl HttpClientMethods for HttpClient { .json(&request) .send() .await? - .json::() + .text() .await?; - match serde_json::from_value::(res.clone()) { - Ok(melt_quote_response) => Ok(melt_quote_response), - Err(_) => Err(ErrorResponse::from_value(res)?.into()), - } + convert_http_response!(MeltQuoteBolt11Response, res) } /// Melt Quote Status @@ -212,12 +200,9 @@ impl HttpClientMethods for HttpClient { ) -> Result { let url = mint_url.join_paths(&["v1", "melt", "quote", "bolt11", quote_id])?; - let res = self.inner.get(url).send().await?.json::().await?; + let res = self.inner.get(url).send().await?.text().await?; - match serde_json::from_value::(res.clone()) { - Ok(melt_quote_response) => Ok(melt_quote_response), - Err(_) => Err(ErrorResponse::from_value(res)?.into()), - } + convert_http_response!(MeltQuoteBolt11Response, res) } /// Melt [NUT-05] @@ -236,18 +221,10 @@ impl HttpClientMethods for HttpClient { .json(&request) .send() .await? - .json::() + .text() .await?; - match serde_json::from_value::(res.clone()) { - Ok(melt_quote_response) => Ok(melt_quote_response), - Err(_) => { - if let Ok(res) = serde_json::from_value::(res.clone()) { - return Ok(res); - } - Err(ErrorResponse::from_value(res)?.into()) - } - } + convert_http_response!(MeltQuoteBolt11Response, res) } /// Swap Token [NUT-03] @@ -265,13 +242,10 @@ impl HttpClientMethods for HttpClient { .json(&swap_request) .send() .await? - .json::() + .text() .await?; - match serde_json::from_value::(res.clone()) { - Ok(melt_quote_response) => Ok(melt_quote_response), - Err(_) => Err(ErrorResponse::from_value(res)?.into()), - } + convert_http_response!(SwapResponse, res) } /// Get Mint Info [NUT-06] @@ -279,15 +253,9 @@ impl HttpClientMethods for HttpClient { async fn get_mint_info(&self, mint_url: MintUrl) -> Result { let url = mint_url.join_paths(&["v1", "info"])?; - let res = self.inner.get(url).send().await?.json::().await?; + let res = self.inner.get(url).send().await?.text().await?; - match serde_json::from_value::(res.clone()) { - Ok(melt_quote_response) => Ok(melt_quote_response), - Err(err) => { - tracing::error!("Could not get mint info: {}", err); - Err(ErrorResponse::from_value(res)?.into()) - } - } + convert_http_response!(MintInfo, res) } /// Spendable check [NUT-07] @@ -305,13 +273,10 @@ impl HttpClientMethods for HttpClient { .json(&request) .send() .await? - .json::() + .text() .await?; - match serde_json::from_value::(res.clone()) { - Ok(melt_quote_response) => Ok(melt_quote_response), - Err(_) => Err(ErrorResponse::from_value(res)?.into()), - } + convert_http_response!(CheckStateResponse, res) } /// Restore request [NUT-13] @@ -329,13 +294,10 @@ impl HttpClientMethods for HttpClient { .json(&request) .send() .await? - .json::() + .text() .await?; - match serde_json::from_value::(res.clone()) { - Ok(melt_quote_response) => Ok(melt_quote_response), - Err(_) => Err(ErrorResponse::from_value(res)?.into()), - } + convert_http_response!(RestoreResponse, res) } }