]> Untitled Git - bdk-cli/commitdiff
fix(proxy_opts): add saving and reading proxy_opts
authorVihiga Tyonum <withtvpeter@gmail.com>
Thu, 25 Jun 2026 17:58:41 +0000 (18:58 +0100)
committerVihiga Tyonum <withtvpeter@gmail.com>
Wed, 8 Jul 2026 21:49:31 +0000 (22:49 +0100)
- add saving proxy_opts for electrum and esplora
clients to config and reading values
- fix prepare_home_dir util fn

src/commands.rs
src/config.rs
src/handlers/config.rs
src/handlers/offline.rs
src/utils/common.rs

index 529ef26b952b971774d87c4a24a9149130fb4218..1d920ad8718ab45ac68f2b5502e78fb9e94edfee 100644 (file)
@@ -281,6 +281,9 @@ pub struct WalletOpts {
     #[cfg(feature = "cbf")]
     #[clap(flatten)]
     pub compactfilter_opts: CompactFilterOpts,
+    #[cfg(any(feature = "electrum", feature = "esplora"))]
+    #[command(flatten)]
+    pub proxy_opts: ProxyOpts,
 }
 
 /// Options to configure a SOCKS5 proxy for a blockchain client connection.
@@ -288,11 +291,11 @@ pub struct WalletOpts {
 #[derive(Debug, Args, Clone, PartialEq, Eq)]
 pub struct ProxyOpts {
     /// Sets the SOCKS5 proxy for a blockchain client.
-    #[arg(env = "PROXY_ADDRS:PORT", long = "proxy", short = 'p')]
+    #[arg(env = "PROXY_ADDRS:PORT", long = "proxy")]
     pub proxy: Option<String>,
 
     /// Sets the SOCKS5 proxy credential.
-    #[arg(env = "PROXY_USER:PASSWD", long="proxy_auth", short='a', value_parser = parse_proxy_auth)]
+    #[arg(env = "PROXY_USER:PASSWD", long="proxy_auth", value_parser = parse_proxy_auth)]
     pub proxy_auth: Option<(String, String)>,
 
     /// Sets the SOCKS5 proxy retries for the blockchain client.
index 6865ee0915d7e65b5d3847b9007ae7eeaa0216d6..60580037c5f5f31add881450d15c9452e0d59d8d 100644 (file)
@@ -50,6 +50,21 @@ pub struct WalletConfigInner {
     pub parallel_requests: Option<usize>,
     #[cfg(feature = "rpc")]
     pub cookie: Option<String>,
+    #[cfg(any(feature = "electrum", feature = "esplora"))]
+    #[serde(default)]
+    pub proxy: Option<String>,
+    #[cfg(any(feature = "electrum", feature = "esplora"))]
+    #[serde(default)]
+    pub proxy_auth: Option<String>,
+    #[cfg(any(feature = "electrum", feature = "esplora"))]
+    #[serde(default)]
+    pub proxy_retries: Option<u8>,
+    #[cfg(any(feature = "electrum", feature = "esplora"))]
+    #[serde(default)]
+    pub proxy_timeout: Option<u8>,
+    #[cfg(feature = "cbf")]
+    #[serde(default)]
+    pub conn_count: Option<u8>,
 }
 
 impl WalletConfig {
@@ -93,7 +108,7 @@ impl TryFrom<&WalletConfigInner> for WalletOpts {
     type Error = Error;
 
     fn try_from(config: &WalletConfigInner) -> Result<Self, Self::Error> {
-        let _network = Network::from_str(&config.network)
+        Network::from_str(&config.network)
             .map_err(|_| Error::Generic("Invalid network".to_string()))?;
 
         #[cfg(any(feature = "sqlite", feature = "redb"))]
@@ -155,8 +170,21 @@ impl TryFrom<&WalletConfigInner> for WalletOpts {
             #[cfg(feature = "rpc")]
             cookie: config.cookie.clone(),
 
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy_opts: crate::commands::ProxyOpts {
+                proxy: config.proxy.clone(),
+                proxy_auth: match &config.proxy_auth {
+                    Some(s) => Some(crate::utils::parse_proxy_auth(s)?),
+                    None => None,
+                },
+                retries: config.proxy_retries.unwrap_or(5),
+                timeout: config.proxy_timeout,
+            },
+
             #[cfg(feature = "cbf")]
-            compactfilter_opts: crate::commands::CompactFilterOpts { conn_count: 2 },
+            compactfilter_opts: crate::commands::CompactFilterOpts {
+                conn_count: config.conn_count.unwrap_or(2),
+            },
         })
     }
 }
@@ -218,6 +246,16 @@ mod tests {
             rpc_password: None,
             #[cfg(feature = "rpc")]
             cookie: None,
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy: None,
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy_auth: None,
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy_retries: None,
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy_timeout: None,
+            #[cfg(feature = "cbf")]
+            conn_count: None,
         };
 
         let opts: WalletOpts = (&wallet_config)
@@ -293,6 +331,16 @@ mod tests {
             rpc_password: None,
             #[cfg(feature = "rpc")]
             cookie: None,
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy: None,
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy_auth: None,
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy_retries: None,
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy_timeout: None,
+            #[cfg(feature = "cbf")]
+            conn_count: None,
         };
 
         let result: Result<WalletOpts, Error> = (&inner).try_into();
index 55649693247b59d06f26a1251402d4f2065fbb23..f3b9d00078f91497c8ad561429b40b219f5f5c9c 100644 (file)
@@ -124,6 +124,22 @@ impl AppCommand<AppContext<Init>> for SaveConfigCommand {
             parallel_requests: Some(self.wallet_opts.parallel_requests),
             #[cfg(feature = "rpc")]
             cookie: self.wallet_opts.cookie.clone(),
+
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy: self.wallet_opts.proxy_opts.proxy.clone(),
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy_auth: self
+                .wallet_opts
+                .proxy_opts
+                .proxy_auth
+                .as_ref()
+                .map(|(u, p)| format!("{u}:{p}")),
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy_retries: Some(self.wallet_opts.proxy_opts.retries),
+            #[cfg(any(feature = "electrum", feature = "esplora"))]
+            proxy_timeout: self.wallet_opts.proxy_opts.timeout,
+            #[cfg(feature = "cbf")]
+            conn_count: Some(self.wallet_opts.compactfilter_opts.conn_count),
         };
 
         config.wallets.insert(wallet_name.clone(), wallet_config);
index fc2e0878f9ea9ad3ab6d64a486931740a4994ba7..6853194e2d2b9beb2725d006ab739aaee2e4623b 100644 (file)
@@ -16,7 +16,6 @@ use bdk_wallet::{KeychainKind, SignOptions};
 use clap::Parser;
 use serde_json::json;
 use std::collections::BTreeMap;
-use std::str::FromStr;
 #[cfg(feature = "silent-payments")]
 use {
     crate::utils::common::parse_sp_code_value_pairs,
@@ -542,7 +541,7 @@ impl AppCommand<AppContext<OfflineOperations<'_>>> for CreateSpTxCommand {
 pub struct BumpFeeCommand {
     /// TXID of the transaction to update.
     #[arg(env = "TXID", long = "txid")]
-    pub txid: String,
+    pub txid: Txid,
 
     /// Allows the wallet to reduce the amount to the specified address in order to increase fees.
     #[arg(env = "SHRINK_ADDRESS", long = "shrink", value_parser = parse_address)]
@@ -576,9 +575,7 @@ impl AppCommand<AppContext<OfflineOperations<'_>>> for BumpFeeCommand {
     fn execute(&self, ctx: &mut AppContext<OfflineOperations<'_>>) -> Result<Self::Output, Error> {
         let wallet = &mut ctx.state.wallet;
 
-        let txid = Txid::from_str(self.txid.as_str())?;
-
-        let mut tx_builder = wallet.build_fee_bump(txid)?;
+        let mut tx_builder = wallet.build_fee_bump(self.txid)?;
         let fee_rate =
             FeeRate::from_sat_per_vb(self.fee_rate as u64).unwrap_or(FeeRate::BROADCAST_MIN);
         tx_builder.fee_rate(fee_rate);
index d93ff0232c6b9a85eb65967a043105931665a8b1..e28666177ba027a69e02997f7829254aec5fdb9c 100644 (file)
@@ -95,19 +95,18 @@ pub(crate) fn parse_address(address_str: &str) -> Result<Address, Error> {
 /// If not the default home directory is created at `~/.bdk-bitcoin`.
 #[allow(dead_code)]
 pub(crate) fn prepare_home_dir(home_path: Option<PathBuf>) -> Result<PathBuf, Error> {
-    let dir = home_path.unwrap_or_else(|| {
-        let mut dir = PathBuf::new();
-        dir.push(
-            dirs::home_dir()
-                .ok_or_else(|| Error::Generic("home dir not found".to_string()))
-                .unwrap(),
-        );
-        dir.push(".bdk-bitcoin");
-        dir
-    });
+    let dir = match home_path {
+        Some(dir) => dir,
+        None => {
+            let mut dir =
+                dirs::home_dir().ok_or_else(|| Error::Generic("Home dir not found".to_string()))?;
+            dir.push(".bdk-bitcoin");
+            dir
+        }
+    };
 
     if !dir.exists() {
-        std::fs::create_dir(&dir).map_err(|e| Error::Generic(e.to_string()))?;
+        std::fs::create_dir_all(&dir).map_err(|e| Error::Generic(e.to_string()))?;
     }
 
     Ok(dir)
@@ -171,14 +170,8 @@ pub fn load_wallet_config(
             "Wallet '{wallet_name}' not found in config"
         )))?;
 
-    let network = match wallet_config.network.as_str() {
-        "bitcoin" => Ok(Network::Bitcoin),
-        "testnet" => Ok(Network::Testnet),
-        "regtest" => Ok(Network::Regtest),
-        "signet" => Ok(Network::Signet),
-        "testnet4" => Ok(Network::Testnet4),
-        _ => Err(Error::Generic("Invalid network in config".to_string())),
-    }?;
+    let network = Network::from_str(&wallet_config.network)
+        .map_err(|_| Error::Generic("Invalid network in config".to_string()))?;
 
     Ok((wallet_opts, network))
 }