Skip to content

Commit

Permalink
refactor: use reqwest client
Browse files Browse the repository at this point in the history
Using reqwest reduced code duplication since it can be used for both
wasm and non wasm targets.
  • Loading branch information
thesimplekid committed Apr 12, 2024
1 parent ce20795 commit 391692e
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 504 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ jobs:
build-args:
[
-p cdk,
-p cdk --no-default-features,
-p cdk --no-default-features --features wallet,
-p cdk --no-default-features --features all-nuts,
]
steps:
- name: Checkout
Expand Down
6 changes: 2 additions & 4 deletions crates/cdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ license.workspace = true
[features]
default = ["mint", "wallet", "all-nuts", "redb"]
mint = ["dep:bip39"]
wallet = ["nut13", "dep:minreq", "dep:bip39"]
gloo = ["dep:gloo"]
wallet = ["nut13", "dep:bip39", "dep:reqwest"]
all-nuts = ["nut13"]
nut13 = ["dep:bip39"]
redb = ["dep:redb"]
Expand All @@ -32,13 +31,12 @@ url = "2.3.1"
tracing = { version = "0.1", default-features = false }
thiserror = "1.0.50"
async-trait = "0.1.74"
gloo = { version = "0.11.0", optional = true, features = ["net"] }
http = "1.0.0"
uuid = { version = "1.6", features = ["v4"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "socks"], optional = true }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { workspace = true, features = ["rt-multi-thread", "time", "macros", "sync"] }
minreq = { version = "2.7.0", optional = true, features = ["json-using-serde", "https"] }
redb = { version = "2.0.0", optional = true }

[target.'cfg(target_arch = "wasm32")'.dependencies]
Expand Down
141 changes: 92 additions & 49 deletions crates/cdk/src/client/minreq_client.rs → crates/cdk/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
//! Minreq http Client
use async_trait::async_trait;
use reqwest::Client;
use serde_json::Value;
use tracing::warn;
use url::Url;

use super::join_url;
use crate::client::{Client, Error};
use crate::error::ErrorResponse;
use crate::error::{Error, ErrorResponse};
use crate::nuts::{
BlindedMessage, CheckStateRequest, CheckStateResponse, CurrencyUnit, Id, KeySet, KeysResponse,
KeysetResponse, MeltBolt11Request, MeltBolt11Response, MeltQuoteBolt11Request,
Expand All @@ -17,34 +12,71 @@ use crate::nuts::{
};
use crate::{Amount, Bolt11Invoice};

fn join_url(url: Url, paths: &[&str]) -> Result<Url, Error> {
let mut url = url;
for path in paths {
if !url.path().ends_with('/') {
url.path_segments_mut()
.map_err(|_| Error::CustomError("Url Path Segmants".to_string()))?
.push(path);
} else {
url.path_segments_mut()
.map_err(|_| Error::CustomError("Url Path Segmants".to_string()))?
.pop()
.push(path);
}
}

Ok(url)
}

#[derive(Debug, Clone)]
pub struct HttpClient {}
pub struct HttpClient {
inner: Client,
}

impl Default for HttpClient {
fn default() -> Self {
Self::new()
}
}

impl HttpClient {
pub fn new() -> Self {
Self {
inner: Client::new(),
}
}

#[async_trait(?Send)]
impl Client for HttpClient {
/// Get Active Mint Keys [NUT-01]
async fn get_mint_keys(&self, mint_url: Url) -> Result<Vec<KeySet>, Error> {
pub async fn get_mint_keys(&self, mint_url: Url) -> Result<Vec<KeySet>, Error> {
let url = join_url(mint_url, &["v1", "keys"])?;
let keys = minreq::get(url).send()?.json::<Value>()?;
let keys = self.inner.get(url).send().await?.json::<Value>().await?;

let keys: KeysResponse = serde_json::from_value(keys)?;
Ok(keys.keysets)
}

/// Get Keyset Keys [NUT-01]
async fn get_mint_keyset(&self, mint_url: Url, keyset_id: Id) -> Result<KeySet, Error> {
pub async fn get_mint_keyset(&self, mint_url: Url, keyset_id: Id) -> Result<KeySet, Error> {
let url = join_url(mint_url, &["v1", "keys", &keyset_id.to_string()])?;
let keys = minreq::get(url).send()?.json::<KeysResponse>()?;
let keys = self
.inner
.get(url)
.send()
.await?
.json::<KeysResponse>()
.await?;

// let keys: KeysResponse = serde_json::from_value(keys)?; //
// serde_json::from_str(&keys.to_string())?;
Ok(keys.keysets[0].clone())
}

/// Get Keysets [NUT-02]
async fn get_mint_keysets(&self, mint_url: Url) -> Result<KeysetResponse, Error> {
pub async fn get_mint_keysets(&self, mint_url: Url) -> Result<KeysetResponse, Error> {
let url = join_url(mint_url, &["v1", "keysets"])?;
let res = minreq::get(url).send()?.json::<Value>()?;
let res = self.inner.get(url).send().await?.json::<Value>().await?;

let response: Result<KeysetResponse, serde_json::Error> =
serde_json::from_value(res.clone());
Expand All @@ -56,7 +88,7 @@ impl Client for HttpClient {
}

/// Mint Quote [NUT-04]
async fn post_mint_quote(
pub async fn post_mint_quote(
&self,
mint_url: Url,
amount: Amount,
Expand All @@ -66,22 +98,21 @@ impl Client for HttpClient {

let request = MintQuoteBolt11Request { amount, unit };

let res = minreq::post(url).with_json(&request)?.send()?;
let res = self.inner.post(url).json(&request).send().await?;

let status = res.status();

let response: Result<MintQuoteBolt11Response, serde_json::Error> =
serde_json::from_value(res.json()?);
serde_json::from_value(res.json().await?);

match response {
Ok(res) => Ok(res),
Err(_) => {
warn!("Bolt11 Mint Quote Unexpected response: {:?}", res);
Err(ErrorResponse::from_json(&res.status_code.to_string())?.into())
}
Err(_) => Err(ErrorResponse::from_json(&status.to_string())?.into()),
}
}

/// Mint Tokens [NUT-04]
async fn post_mint(
pub async fn post_mint(
&self,
mint_url: Url,
quote: &str,
Expand All @@ -94,10 +125,14 @@ impl Client for HttpClient {
outputs: premint_secrets.blinded_messages(),
};

let res = minreq::post(url)
.with_json(&request)?
.send()?
.json::<Value>()?;
let res = self
.inner
.post(url)
.json(&request)
.send()
.await?
.json::<Value>()
.await?;

let response: Result<MintBolt11Response, serde_json::Error> =
serde_json::from_value(res.clone());
Expand All @@ -109,7 +144,7 @@ impl Client for HttpClient {
}

/// Melt Quote [NUT-05]
async fn post_melt_quote(
pub async fn post_melt_quote(
&self,
mint_url: Url,
unit: CurrencyUnit,
Expand All @@ -119,9 +154,9 @@ impl Client for HttpClient {

let request = MeltQuoteBolt11Request { request, unit };

let value = minreq::post(url).with_json(&request)?.send()?;
let value = self.inner.post(url).json(&request).send().await?;

let value = value.json::<Value>()?;
let value = value.json::<Value>().await?;

let response: Result<MeltQuoteBolt11Response, serde_json::Error> =
serde_json::from_value(value.clone());
Expand All @@ -134,7 +169,7 @@ impl Client for HttpClient {

/// Melt [NUT-05]
/// [Nut-08] Lightning fee return if outputs defined
async fn post_melt(
pub async fn post_melt(
&self,
mint_url: Url,
quote: String,
Expand All @@ -149,9 +184,9 @@ impl Client for HttpClient {
outputs,
};

let value = minreq::post(url).with_json(&request)?.send()?;
let value = self.inner.post(url).json(&request).send().await?;

let value = value.json::<Value>()?;
let value = value.json::<Value>().await?;
let response: Result<MeltBolt11Response, serde_json::Error> =
serde_json::from_value(value.clone());

Expand All @@ -162,16 +197,16 @@ impl Client for HttpClient {
}

/// Split Token [NUT-06]
async fn post_swap(
pub async fn post_swap(
&self,
mint_url: Url,
swap_request: SwapRequest,
) -> Result<SwapResponse, Error> {
let url = join_url(mint_url, &["v1", "swap"])?;

let res = minreq::post(url).with_json(&swap_request)?.send()?;
let res = self.inner.post(url).json(&swap_request).send().await?;

let value = res.json::<Value>()?;
let value = res.json::<Value>().await?;
let response: Result<SwapResponse, serde_json::Error> =
serde_json::from_value(value.clone());

Expand All @@ -182,10 +217,10 @@ impl Client for HttpClient {
}

/// Get Mint Info [NUT-06]
async fn get_mint_info(&self, mint_url: Url) -> Result<MintInfo, Error> {
pub async fn get_mint_info(&self, mint_url: Url) -> Result<MintInfo, Error> {
let url = join_url(mint_url, &["v1", "info"])?;

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

let response: Result<MintInfo, serde_json::Error> = serde_json::from_value(res.clone());

Expand All @@ -196,18 +231,22 @@ impl Client for HttpClient {
}

/// Spendable check [NUT-07]
async fn post_check_state(
pub async fn post_check_state(
&self,
mint_url: Url,
ys: Vec<PublicKey>,
) -> Result<CheckStateResponse, Error> {
let url = join_url(mint_url, &["v1", "checkstate"])?;
let request = CheckStateRequest { ys };

let res = minreq::post(url)
.with_json(&request)?
.send()?
.json::<Value>()?;
let res = self
.inner
.post(url)
.json(&request)
.send()
.await?
.json::<Value>()
.await?;

let response: Result<CheckStateResponse, serde_json::Error> =
serde_json::from_value(res.clone());
Expand All @@ -218,17 +257,21 @@ impl Client for HttpClient {
}
}

async fn post_restore(
pub async fn post_restore(
&self,
mint_url: Url,
request: RestoreRequest,
) -> Result<RestoreResponse, Error> {
let url = join_url(mint_url, &["v1", "restore"])?;

let res = minreq::post(url)
.with_json(&request)?
.send()?
.json::<Value>()?;
let res = self
.inner
.post(url)
.json(&request)
.send()
.await?
.json::<Value>()
.await?;

let response: Result<RestoreResponse, serde_json::Error> =
serde_json::from_value(res.clone());
Expand Down
Loading

0 comments on commit 391692e

Please sign in to comment.