Skip to content

Commit

Permalink
Improve Http client
Browse files Browse the repository at this point in the history
Store the HTTP response as string instead of parsing as a json::Value and
cloning it several times.
  • Loading branch information
crodas authored and thesimplekid committed Nov 19, 2024
1 parent c8f82b2 commit 5dd196d
Showing 1 changed file with 42 additions and 80 deletions.
122 changes: 42 additions & 80 deletions crates/cdk/src/wallet/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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) => <ErrorResponse as Into<Error>>::into(ok),
Err(err) => err.into(),
}
})
};
}

/// Http Client
#[derive(Debug, Clone)]
pub struct HttpClient {
Expand Down Expand Up @@ -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<Vec<KeySet>, Error> {
let url = mint_url.join_paths(&["v1", "keys"])?;
let keys = self.inner.get(url).send().await?.json::<Value>().await?;
let keys = self.inner.get(url).send().await?.text().await?;

match serde_json::from_value::<KeysResponse>(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<KeySet, Error> {
let url = mint_url.join_paths(&["v1", "keys", &keyset_id.to_string()])?;
let keys = self.inner.get(url).send().await?.json::<Value>().await?;
let keys = self.inner.get(url).send().await?.text().await?;

match serde_json::from_value::<KeysResponse>(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<KeysetResponse, Error> {
let url = mint_url.join_paths(&["v1", "keysets"])?;
let res = self.inner.get(url).send().await?.json::<Value>().await?;
let res = self.inner.get(url).send().await?.text().await?;

match serde_json::from_value::<KeysetResponse>(res.clone()) {
Ok(keyset_response) => Ok(keyset_response),
Err(_) => Err(ErrorResponse::from_value(res)?.into()),
}
convert_http_response!(KeysetResponse, res)
}

/// Mint Quote [NUT-04]
Expand All @@ -123,16 +129,10 @@ impl HttpClientMethods for HttpClient {
.json(&request)
.send()
.await?
.json::<Value>()
.text()
.await?;

match serde_json::from_value::<MintQuoteBolt11Response>(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
Expand All @@ -144,15 +144,9 @@ impl HttpClientMethods for HttpClient {
) -> Result<MintQuoteBolt11Response, Error> {
let url = mint_url.join_paths(&["v1", "mint", "quote", "bolt11", quote_id])?;

let res = self.inner.get(url).send().await?.json::<Value>().await?;
let res = self.inner.get(url).send().await?.text().await?;

match serde_json::from_value::<MintQuoteBolt11Response>(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]
Expand All @@ -170,13 +164,10 @@ impl HttpClientMethods for HttpClient {
.json(&request)
.send()
.await?
.json::<Value>()
.text()
.await?;

match serde_json::from_value::<MintBolt11Response>(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]
Expand All @@ -194,13 +185,10 @@ impl HttpClientMethods for HttpClient {
.json(&request)
.send()
.await?
.json::<Value>()
.text()
.await?;

match serde_json::from_value::<MeltQuoteBolt11Response>(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
Expand All @@ -212,12 +200,9 @@ impl HttpClientMethods for HttpClient {
) -> Result<MeltQuoteBolt11Response, Error> {
let url = mint_url.join_paths(&["v1", "melt", "quote", "bolt11", quote_id])?;

let res = self.inner.get(url).send().await?.json::<Value>().await?;
let res = self.inner.get(url).send().await?.text().await?;

match serde_json::from_value::<MeltQuoteBolt11Response>(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]
Expand All @@ -236,18 +221,10 @@ impl HttpClientMethods for HttpClient {
.json(&request)
.send()
.await?
.json::<Value>()
.text()
.await?;

match serde_json::from_value::<MeltQuoteBolt11Response>(res.clone()) {
Ok(melt_quote_response) => Ok(melt_quote_response),
Err(_) => {
if let Ok(res) = serde_json::from_value::<MeltQuoteBolt11Response>(res.clone()) {
return Ok(res);
}
Err(ErrorResponse::from_value(res)?.into())
}
}
convert_http_response!(MeltQuoteBolt11Response, res)
}

/// Swap Token [NUT-03]
Expand All @@ -265,29 +242,20 @@ impl HttpClientMethods for HttpClient {
.json(&swap_request)
.send()
.await?
.json::<Value>()
.text()
.await?;

match serde_json::from_value::<SwapResponse>(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]
#[instrument(skip(self), fields(mint_url = %mint_url))]
async fn get_mint_info(&self, mint_url: MintUrl) -> Result<MintInfo, Error> {
let url = mint_url.join_paths(&["v1", "info"])?;

let res = self.inner.get(url).send().await?.json::<Value>().await?;
let res = self.inner.get(url).send().await?.text().await?;

match serde_json::from_value::<MintInfo>(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]
Expand All @@ -305,13 +273,10 @@ impl HttpClientMethods for HttpClient {
.json(&request)
.send()
.await?
.json::<Value>()
.text()
.await?;

match serde_json::from_value::<CheckStateResponse>(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]
Expand All @@ -329,13 +294,10 @@ impl HttpClientMethods for HttpClient {
.json(&request)
.send()
.await?
.json::<Value>()
.text()
.await?;

match serde_json::from_value::<RestoreResponse>(res.clone()) {
Ok(melt_quote_response) => Ok(melt_quote_response),
Err(_) => Err(ErrorResponse::from_value(res)?.into()),
}
convert_http_response!(RestoreResponse, res)
}
}

Expand Down

0 comments on commit 5dd196d

Please sign in to comment.