From 0945b3540a55ae7cc31338580d41486f4fe99eec Mon Sep 17 00:00:00 2001 From: David Caseria Date: Wed, 7 Aug 2024 08:53:05 -0400 Subject: [PATCH] Add proxy support (#272) * Add proxy support --- Cargo.toml | 1 + crates/cdk-cli/Cargo.toml | 1 + crates/cdk-cli/src/main.rs | 12 ++++++-- crates/cdk-cli/src/sub_commands/mint_info.rs | 8 ++++-- crates/cdk/Cargo.toml | 3 +- crates/cdk/src/wallet/client.rs | 29 ++++++++++++++++++++ crates/cdk/src/wallet/mod.rs | 5 ++++ 7 files changed, 54 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6076b6ac..7bf15895 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ uuid = { version = "1", features = ["v4"] } lightning-invoice = { version = "0.31", features = ["serde"] } home = "0.5.9" rand = "0.8.5" +url = "2.3" [profile] diff --git a/crates/cdk-cli/Cargo.toml b/crates/cdk-cli/Cargo.toml index 87ced3a8..14d7fc77 100644 --- a/crates/cdk-cli/Cargo.toml +++ b/crates/cdk-cli/Cargo.toml @@ -29,3 +29,4 @@ nostr-sdk = { version = "0.33.0", default-features = false, features = [ "nip04", "nip44" ]} +url.workspace = true diff --git a/crates/cdk-cli/src/main.rs b/crates/cdk-cli/src/main.rs index 6ecb7cd3..0cde9e96 100644 --- a/crates/cdk-cli/src/main.rs +++ b/crates/cdk-cli/src/main.rs @@ -7,6 +7,7 @@ use anyhow::{bail, Result}; use bip39::Mnemonic; use cdk::cdk_database; use cdk::cdk_database::WalletDatabase; +use cdk::wallet::client::HttpClient; use cdk::wallet::{MultiMintWallet, Wallet}; use cdk_redb::WalletRedbDatabase; use cdk_sqlite::WalletSqliteDatabase; @@ -14,6 +15,7 @@ use clap::{Parser, Subcommand}; use rand::Rng; use tracing::Level; use tracing_subscriber::EnvFilter; +use url::Url; mod sub_commands; @@ -35,6 +37,9 @@ struct Cli { /// Logging level #[arg(short, long, default_value = "error")] log_level: Level, + /// NWS Proxy + #[arg(short, long)] + proxy: Option, #[command(subcommand)] command: Commands, } @@ -130,13 +135,16 @@ async fn main() -> Result<()> { let mints = localstore.get_mints().await?; for (mint, _) in mints { - let wallet = Wallet::new( + let mut wallet = Wallet::new( &mint.to_string(), cdk::nuts::CurrencyUnit::Sat, localstore.clone(), &mnemonic.to_seed_normalized(""), None, ); + if let Some(proxy_url) = args.proxy.as_ref() { + wallet.set_client(HttpClient::with_proxy(proxy_url.clone(), None, true)?); + } wallets.push(wallet); } @@ -167,7 +175,7 @@ async fn main() -> Result<()> { sub_commands::check_spent::check_spent(&multi_mint_wallet).await } Commands::MintInfo(sub_command_args) => { - sub_commands::mint_info::mint_info(sub_command_args).await + sub_commands::mint_info::mint_info(args.proxy, sub_command_args).await } Commands::Mint(sub_command_args) => { sub_commands::mint::mint( diff --git a/crates/cdk-cli/src/sub_commands/mint_info.rs b/crates/cdk-cli/src/sub_commands/mint_info.rs index 5b09cf13..5bcddc66 100644 --- a/crates/cdk-cli/src/sub_commands/mint_info.rs +++ b/crates/cdk-cli/src/sub_commands/mint_info.rs @@ -2,6 +2,7 @@ use anyhow::Result; use cdk::url::UncheckedUrl; use cdk::HttpClient; use clap::Args; +use url::Url; #[derive(Args)] pub struct MintInfoSubcommand { @@ -9,8 +10,11 @@ pub struct MintInfoSubcommand { mint_url: UncheckedUrl, } -pub async fn mint_info(sub_command_args: &MintInfoSubcommand) -> Result<()> { - let client = HttpClient::default(); +pub async fn mint_info(proxy: Option, sub_command_args: &MintInfoSubcommand) -> Result<()> { + let client = match proxy { + Some(proxy) => HttpClient::with_proxy(proxy, None, true)?, + None => HttpClient::new(), + }; let info = client .get_mint_info(sub_command_args.mint_url.clone().try_into()?) diff --git a/crates/cdk/Cargo.toml b/crates/cdk/Cargo.toml index c3f3ee40..9fabae3b 100644 --- a/crates/cdk/Cargo.toml +++ b/crates/cdk/Cargo.toml @@ -28,6 +28,7 @@ bitcoin = { workspace = true, features = [ ciborium = { version = "0.2.2", default-features = false, features = ["std"] } lightning-invoice.workspace = true once_cell = "1.19" +regex = "1" reqwest = { version = "0.12", default-features = false, features = [ "json", "rustls-tls", @@ -40,7 +41,7 @@ serde_with = "3.4" tracing.workspace = true thiserror.workspace = true futures = { workspace = true, optional = true } -url = "2.3" +url.workspace = true uuid.workspace = true [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/crates/cdk/src/wallet/client.rs b/crates/cdk/src/wallet/client.rs index 18f5c7fd..eb0ac81e 100644 --- a/crates/cdk/src/wallet/client.rs +++ b/crates/cdk/src/wallet/client.rs @@ -56,6 +56,35 @@ impl HttpClient { } } + #[cfg(not(target_arch = "wasm32"))] + /// Create new [`HttpClient`] with a proxy for specific TLDs. + /// Specifying `None` for `host_matcher` will use the proxy for all requests. + pub fn with_proxy( + proxy: Url, + host_matcher: Option<&str>, + accept_invalid_certs: bool, + ) -> Result { + let regex = host_matcher + .map(regex::Regex::new) + .transpose() + .map_err(|e| Error::Custom(e.to_string()))?; + let client = reqwest::Client::builder() + .proxy(reqwest::Proxy::custom(move |url| { + if let Some(matcher) = regex.as_ref() { + if let Some(host) = url.host_str() { + if matcher.is_match(host) { + return Some(proxy.clone()); + } + } + } + None + })) + .danger_accept_invalid_certs(accept_invalid_certs) // Allow self-signed certs + .build()?; + + Ok(Self { inner: client }) + } + /// Get Active Mint Keys [NUT-01] #[instrument(skip(self), fields(mint_url = %mint_url))] pub async fn get_mint_keys(&self, mint_url: Url) -> Result, Error> { diff --git a/crates/cdk/src/wallet/mod.rs b/crates/cdk/src/wallet/mod.rs index f018f20e..78e7ad5d 100644 --- a/crates/cdk/src/wallet/mod.rs +++ b/crates/cdk/src/wallet/mod.rs @@ -75,6 +75,11 @@ impl Wallet { } } + /// Change HTTP client + pub fn set_client(&mut self, client: HttpClient) { + self.client = client; + } + /// Fee required for proof set #[instrument(skip_all)] pub async fn get_proofs_fee(&self, proofs: &Proofs) -> Result {