mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-05 05:06:14 +01:00
fix: client join urls without trailing '/'
This commit is contained in:
@@ -19,6 +19,7 @@ use gloo::net::http::Request;
|
||||
use serde_json::Value;
|
||||
use url::Url;
|
||||
|
||||
use super::join_url;
|
||||
use crate::client::{Client, Error};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -27,8 +28,8 @@ pub struct HttpClient {}
|
||||
#[async_trait(?Send)]
|
||||
impl Client for HttpClient {
|
||||
/// Get Mint Keys [NUT-01]
|
||||
async fn get_mint_keys(&self, mint_url: &Url) -> Result<Keys, Error> {
|
||||
let url = mint_url.join("keys")?;
|
||||
async fn get_mint_keys(&self, mint_url: Url) -> Result<Keys, Error> {
|
||||
let url = join_url(mint_url, "keys")?;
|
||||
let keys = Request::get(url.as_str())
|
||||
.send()
|
||||
.await
|
||||
@@ -42,8 +43,8 @@ impl Client for HttpClient {
|
||||
}
|
||||
|
||||
/// Get Keysets [NUT-02]
|
||||
async fn get_mint_keysets(&self, mint_url: &Url) -> Result<nut02::Response, Error> {
|
||||
let url = mint_url.join("keysets")?;
|
||||
async fn get_mint_keysets(&self, mint_url: Url) -> Result<nut02::Response, Error> {
|
||||
let url = join_url(mint_url, "keysets")?;
|
||||
let res = Request::get(url.as_str())
|
||||
.send()
|
||||
.await
|
||||
@@ -64,10 +65,10 @@ impl Client for HttpClient {
|
||||
/// Request Mint [NUT-03]
|
||||
async fn get_request_mint(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
amount: Amount,
|
||||
) -> Result<RequestMintResponse, Error> {
|
||||
let mut url = mint_url.join("mint")?;
|
||||
let mut url = join_url(mint_url, "mint")?;
|
||||
url.query_pairs_mut()
|
||||
.append_pair("amount", &amount.to_sat().to_string());
|
||||
|
||||
@@ -91,11 +92,11 @@ impl Client for HttpClient {
|
||||
/// Mint Tokens [NUT-04]
|
||||
async fn post_mint(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
blinded_messages: BlindedMessages,
|
||||
hash: &str,
|
||||
) -> Result<PostMintResponse, Error> {
|
||||
let mut url = mint_url.join("mint")?;
|
||||
let mut url = join_url(mint_url, "mint")?;
|
||||
url.query_pairs_mut().append_pair("hash", hash);
|
||||
|
||||
let request = MintRequest {
|
||||
@@ -124,10 +125,10 @@ impl Client for HttpClient {
|
||||
/// Check Max expected fee [NUT-05]
|
||||
async fn post_check_fees(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
invoice: Bolt11Invoice,
|
||||
) -> Result<CheckFeesResponse, Error> {
|
||||
let url = mint_url.join("checkfees")?;
|
||||
let url = join_url(mint_url, "checkfees")?;
|
||||
|
||||
let request = CheckFeesRequest { pr: invoice };
|
||||
|
||||
@@ -154,12 +155,12 @@ impl Client for HttpClient {
|
||||
/// [Nut-08] Lightning fee return if outputs defined
|
||||
async fn post_melt(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
proofs: Vec<Proof>,
|
||||
invoice: Bolt11Invoice,
|
||||
outputs: Option<Vec<BlindedMessage>>,
|
||||
) -> Result<MeltResponse, Error> {
|
||||
let url = mint_url.join("melt")?;
|
||||
let url = join_url(mint_url, "melt")?;
|
||||
|
||||
let request = MeltRequest {
|
||||
proofs,
|
||||
@@ -189,10 +190,10 @@ impl Client for HttpClient {
|
||||
/// Split Token [NUT-06]
|
||||
async fn post_split(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
split_request: SplitRequest,
|
||||
) -> Result<SplitResponse, Error> {
|
||||
let url = mint_url.join("split")?;
|
||||
let url = join_url(mint_url, "split")?;
|
||||
|
||||
let res = Request::post(url.as_str())
|
||||
.json(&split_request)
|
||||
@@ -217,10 +218,10 @@ impl Client for HttpClient {
|
||||
#[cfg(feature = "nut07")]
|
||||
async fn post_check_spendable(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
proofs: Vec<nut00::mint::Proof>,
|
||||
) -> Result<CheckSpendableResponse, Error> {
|
||||
let url = mint_url.join("check")?;
|
||||
let url = join_url(mint_url, "check")?;
|
||||
let request = CheckSpendableRequest {
|
||||
proofs: proofs.to_owned(),
|
||||
};
|
||||
@@ -246,8 +247,8 @@ impl Client for HttpClient {
|
||||
|
||||
/// Get Mint Info [NUT-09]
|
||||
#[cfg(feature = "nut09")]
|
||||
async fn get_mint_info(&self, mint_url: &Url) -> Result<MintInfo, Error> {
|
||||
let url = mint_url.join("info")?;
|
||||
async fn get_mint_info(&self, mint_url: Url) -> Result<MintInfo, Error> {
|
||||
let url = join_url(mint_url, "info")?;
|
||||
let res = Request::get(url.as_str())
|
||||
.send()
|
||||
.await
|
||||
|
||||
@@ -18,6 +18,7 @@ use cashu::{Amount, Bolt11Invoice};
|
||||
use serde_json::Value;
|
||||
use url::Url;
|
||||
|
||||
use super::join_url;
|
||||
use crate::client::{Client, Error};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -26,8 +27,8 @@ pub struct HttpClient {}
|
||||
#[async_trait(?Send)]
|
||||
impl Client for HttpClient {
|
||||
/// Get Mint Keys [NUT-01]
|
||||
async fn get_mint_keys(&self, mint_url: &Url) -> Result<Keys, Error> {
|
||||
let url = mint_url.join("keys")?;
|
||||
async fn get_mint_keys(&self, mint_url: Url) -> Result<Keys, Error> {
|
||||
let url = join_url(mint_url, "keys")?;
|
||||
let keys = minreq::get(url).send()?.json::<Value>()?;
|
||||
|
||||
let keys: Keys = serde_json::from_str(&keys.to_string())?;
|
||||
@@ -35,8 +36,8 @@ impl Client for HttpClient {
|
||||
}
|
||||
|
||||
/// Get Keysets [NUT-02]
|
||||
async fn get_mint_keysets(&self, mint_url: &Url) -> Result<nut02::Response, Error> {
|
||||
let url = mint_url.join("keysets")?;
|
||||
async fn get_mint_keysets(&self, mint_url: Url) -> Result<nut02::Response, Error> {
|
||||
let url = join_url(mint_url, "keysets")?;
|
||||
let res = minreq::get(url).send()?.json::<Value>()?;
|
||||
|
||||
let response: Result<nut02::Response, serde_json::Error> =
|
||||
@@ -51,10 +52,10 @@ impl Client for HttpClient {
|
||||
/// Request Mint [NUT-03]
|
||||
async fn get_request_mint(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
amount: Amount,
|
||||
) -> Result<RequestMintResponse, Error> {
|
||||
let mut url = mint_url.join("mint")?;
|
||||
let mut url = join_url(mint_url, "mint")?;
|
||||
url.query_pairs_mut()
|
||||
.append_pair("amount", &amount.to_sat().to_string());
|
||||
|
||||
@@ -72,11 +73,11 @@ impl Client for HttpClient {
|
||||
/// Mint Tokens [NUT-04]
|
||||
async fn post_mint(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
blinded_messages: BlindedMessages,
|
||||
hash: &str,
|
||||
) -> Result<PostMintResponse, Error> {
|
||||
let mut url = mint_url.join("mint")?;
|
||||
let mut url = join_url(mint_url, "mint")?;
|
||||
url.query_pairs_mut().append_pair("hash", hash);
|
||||
|
||||
let request = MintRequest {
|
||||
@@ -100,10 +101,10 @@ impl Client for HttpClient {
|
||||
/// Check Max expected fee [NUT-05]
|
||||
async fn post_check_fees(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
invoice: Bolt11Invoice,
|
||||
) -> Result<CheckFeesResponse, Error> {
|
||||
let url = mint_url.join("checkfees")?;
|
||||
let url = join_url(mint_url, "checkfees")?;
|
||||
|
||||
let request = CheckFeesRequest { pr: invoice };
|
||||
|
||||
@@ -125,12 +126,12 @@ impl Client for HttpClient {
|
||||
/// [Nut-08] Lightning fee return if outputs defined
|
||||
async fn post_melt(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
proofs: Vec<Proof>,
|
||||
invoice: Bolt11Invoice,
|
||||
outputs: Option<Vec<BlindedMessage>>,
|
||||
) -> Result<MeltResponse, Error> {
|
||||
let url = mint_url.join("melt")?;
|
||||
let url = join_url(mint_url, "melt")?;
|
||||
|
||||
let request = MeltRequest {
|
||||
proofs,
|
||||
@@ -155,10 +156,10 @@ impl Client for HttpClient {
|
||||
/// Split Token [NUT-06]
|
||||
async fn post_split(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
split_request: SplitRequest,
|
||||
) -> Result<SplitResponse, Error> {
|
||||
let url = mint_url.join("split")?;
|
||||
let url = join_url(mint_url, "split")?;
|
||||
|
||||
let res = minreq::post(url)
|
||||
.with_json(&split_request)?
|
||||
@@ -178,10 +179,10 @@ impl Client for HttpClient {
|
||||
#[cfg(feature = "nut07")]
|
||||
async fn post_check_spendable(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
proofs: Vec<nut00::mint::Proof>,
|
||||
) -> Result<CheckSpendableResponse, Error> {
|
||||
let url = mint_url.join("check")?;
|
||||
let url = join_url(mint_url, "check")?;
|
||||
let request = CheckSpendableRequest { proofs };
|
||||
|
||||
let res = minreq::post(url)
|
||||
@@ -200,8 +201,9 @@ impl Client for HttpClient {
|
||||
|
||||
/// Get Mint Info [NUT-09]
|
||||
#[cfg(feature = "nut09")]
|
||||
async fn get_mint_info(&self, mint_url: &Url) -> Result<MintInfo, Error> {
|
||||
let url = mint_url.join("info")?;
|
||||
async fn get_mint_info(&self, mint_url: Url) -> Result<MintInfo, Error> {
|
||||
let url = join_url(mint_url, "info")?;
|
||||
|
||||
let res = minreq::get(url).send()?.json::<Value>()?;
|
||||
|
||||
let response: Result<MintInfo, serde_json::Error> = serde_json::from_value(res.clone());
|
||||
|
||||
@@ -84,33 +84,33 @@ pub struct MintErrorResponse {
|
||||
|
||||
#[async_trait(?Send)]
|
||||
pub trait Client {
|
||||
async fn get_mint_keys(&self, mint_url: &Url) -> Result<Keys, Error>;
|
||||
async fn get_mint_keys(&self, mint_url: Url) -> Result<Keys, Error>;
|
||||
|
||||
async fn get_mint_keysets(&self, mint_url: &Url) -> Result<nut02::Response, Error>;
|
||||
async fn get_mint_keysets(&self, mint_url: Url) -> Result<nut02::Response, Error>;
|
||||
|
||||
async fn get_request_mint(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
amount: Amount,
|
||||
) -> Result<RequestMintResponse, Error>;
|
||||
|
||||
// TODO: Hash should have a type
|
||||
async fn post_mint(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
blinded_messages: BlindedMessages,
|
||||
hash: &str,
|
||||
) -> Result<PostMintResponse, Error>;
|
||||
|
||||
async fn post_check_fees(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
invoice: Bolt11Invoice,
|
||||
) -> Result<CheckFeesResponse, Error>;
|
||||
|
||||
async fn post_melt(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
proofs: Vec<Proof>,
|
||||
invoice: Bolt11Invoice,
|
||||
outputs: Option<Vec<BlindedMessage>>,
|
||||
@@ -121,19 +121,36 @@ pub trait Client {
|
||||
// in but in check spendable and melt the compants are passed in
|
||||
async fn post_split(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
split_request: SplitRequest,
|
||||
) -> Result<SplitResponse, Error>;
|
||||
|
||||
#[cfg(feature = "nut07")]
|
||||
async fn post_check_spendable(
|
||||
&self,
|
||||
mint_url: &Url,
|
||||
mint_url: Url,
|
||||
proofs: Vec<nut00::mint::Proof>,
|
||||
) -> Result<CheckSpendableResponse, Error>;
|
||||
|
||||
#[cfg(feature = "nut09")]
|
||||
async fn get_mint_info(&self, mint_url: &Url) -> Result<MintInfo, Error>;
|
||||
async fn get_mint_info(&self, mint_url: Url) -> Result<MintInfo, Error>;
|
||||
}
|
||||
|
||||
#[cfg(any(not(target_arch = "wasm32"), feature = "gloo"))]
|
||||
fn join_url(url: Url, path: &str) -> Result<Url, Error> {
|
||||
let mut url = url;
|
||||
if !url.path().ends_with('/') {
|
||||
url.path_segments_mut()
|
||||
.map_err(|_| Error::Custom("Url Path Segmants".to_string()))?
|
||||
.push(path);
|
||||
} else {
|
||||
url.path_segments_mut()
|
||||
.map_err(|_| Error::Custom("Url Path Segmants".to_string()))?
|
||||
.pop()
|
||||
.push(path);
|
||||
}
|
||||
|
||||
Ok(url)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -62,7 +62,7 @@ impl<C: Client> Wallet<C> {
|
||||
) -> Result<ProofsStatus, Error> {
|
||||
let spendable = self
|
||||
.client
|
||||
.post_check_spendable(&self.mint_url.clone().try_into()?, proofs.clone())
|
||||
.post_check_spendable(self.mint_url.clone().try_into()?, proofs.clone())
|
||||
.await?;
|
||||
|
||||
// Separate proofs in spent and unspent based on mint response
|
||||
@@ -81,7 +81,7 @@ impl<C: Client> Wallet<C> {
|
||||
pub async fn request_mint(&self, amount: Amount) -> Result<RequestMintResponse, Error> {
|
||||
Ok(self
|
||||
.client
|
||||
.get_request_mint(&self.mint_url.clone().try_into()?, amount)
|
||||
.get_request_mint(self.mint_url.clone().try_into()?, amount)
|
||||
.await?)
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ impl<C: Client> Wallet<C> {
|
||||
let mint_res = self
|
||||
.client
|
||||
.post_mint(
|
||||
&self.mint_url.clone().try_into()?,
|
||||
self.mint_url.clone().try_into()?,
|
||||
blinded_messages.clone(),
|
||||
hash,
|
||||
)
|
||||
@@ -119,7 +119,7 @@ impl<C: Client> Wallet<C> {
|
||||
pub async fn check_fee(&self, invoice: Bolt11Invoice) -> Result<Amount, Error> {
|
||||
Ok(self
|
||||
.client
|
||||
.post_check_fees(&self.mint_url.clone().try_into()?, invoice)
|
||||
.post_check_fees(self.mint_url.clone().try_into()?, invoice)
|
||||
.await?
|
||||
.fee)
|
||||
}
|
||||
@@ -137,7 +137,7 @@ impl<C: Client> Wallet<C> {
|
||||
let keys = if token.mint.to_string().eq(&self.mint_url.to_string()) {
|
||||
self.mint_keys.clone()
|
||||
} else {
|
||||
self.client.get_mint_keys(&token.mint.try_into()?).await?
|
||||
self.client.get_mint_keys(token.mint.try_into()?).await?
|
||||
};
|
||||
|
||||
// Sum amount of all proofs
|
||||
@@ -148,7 +148,7 @@ impl<C: Client> Wallet<C> {
|
||||
let split_response = self
|
||||
.client
|
||||
.post_split(
|
||||
&self.mint_url.clone().try_into()?,
|
||||
self.mint_url.clone().try_into()?,
|
||||
split_payload.split_payload,
|
||||
)
|
||||
.await?;
|
||||
@@ -255,7 +255,7 @@ impl<C: Client> Wallet<C> {
|
||||
let split_response = self
|
||||
.client
|
||||
.post_split(
|
||||
&self.mint_url.clone().try_into()?,
|
||||
self.mint_url.clone().try_into()?,
|
||||
split_payload.split_payload,
|
||||
)
|
||||
.await?;
|
||||
@@ -299,7 +299,7 @@ impl<C: Client> Wallet<C> {
|
||||
let melt_response = self
|
||||
.client
|
||||
.post_melt(
|
||||
&self.mint_url.clone().try_into()?,
|
||||
self.mint_url.clone().try_into()?,
|
||||
proofs,
|
||||
invoice,
|
||||
Some(blinded.blinded_messages),
|
||||
|
||||
Reference in New Issue
Block a user