diff --git a/CHANGELOG.md b/CHANGELOG.md index df1ad9e..d672348 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,64 +6,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Project - -#### Added -- `CliSubCommand::Compile` enum variant and `handle_compile_subcommand()` function - -#### Changed -- Make repl and electrum default features +- Update repl feature to not include electrum - Upgrade to `bdk` v0.7.x - -### `bdk-cli` bin - -#### Added -- New top level command "Compile" which compiles a miniscript policy to an output descriptor -- `CompactFilterOpts` to `WalletOpts` to enable compact-filter blockchain configuration - -#### Changed -- Remove unwraps while handling CLI commands +- Add top level command "Compile" which compiles a miniscript policy to an output descriptor +- Add `CompactFilterOpts` to `WalletOpts` to enable compact-filter blockchain configuration +- Add `verbose` option to `WalletOpts` to display PSBTs also in JSON format +- Add `blockchain_client` to `WalletOpts` to select blockchain client to use ## [0.2.0] -### Project - -#### Added - Add support for `wasm` -- `CliOpts` struct and `CliSubCommand` enum representing top level cli options and commands -- `KeySubCommand` enum -- `handle_key_subcommand` function - -#### Changed - Upgrade `bdk` to `0.4.0` and `bdk-macros` to `0.3.0` -- Renamed `WalletOpt` struct to `WalletOpts` -- `WalletSubCommand` enum split into `OfflineWalletSubCommand` and `OnlineWalletSubCommand` -- Split `handle_wallet_subcommand` into two functions, `handle_offline_wallet_subcommand` and `handle_online_wallet_subcommand` - A wallet without a `Blockchain` is used when handling offline wallet sub-commands - -### `bdk-cli` bin - -#### Added -- Top level commands "wallet", "key", and "repl" -- "key" sub-commands to "generate" and "restore" a master private key -- "key" sub-command to "derive" an extended public key from a master private key +- Add top level commands "wallet", "key", and "repl" +- Add "key" sub-commands to "generate" and "restore" a master private key +- Add "key" sub-command to "derive" an extended public key from a master private key - "repl" command now has an "exit" sub-command - -#### Changed - "wallet" sub-commands and options must be proceeded by "wallet" command - "repl" command loop now includes both "wallet" and "key" sub-commands ## [0.1.0] -### Project -#### Added - Add CONTRIBUTING.md - Add CI and code coverage Discord badges to the README - Add CI and code coverage github actions workflows - Add scheduled audit check in CI - Add CHANGELOG.md - -#### Changed - If an invalid network name return an error instead of defaulting to `testnet` ## [0.1.0-beta.1] diff --git a/Cargo.toml b/Cargo.toml index 7f85af4..65e8ffd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ structopt = "^0.3" serde_json = { version = "^1.0" } log = "^0.4" base64 = "^0.11" +zeroize = { version = "<1.4.0" } # Optional dependencies rustyline = { version = "6.0", optional = true } diff --git a/src/bdk_cli.rs b/src/bdk_cli.rs index 25df3b7..8a88150 100644 --- a/src/bdk_cli.rs +++ b/src/bdk_cli.rs @@ -44,7 +44,7 @@ use bdk::sled; use bdk::sled::Tree; use bdk::Wallet; use bdk::{bitcoin, Error}; -use bdk_cli::WalletSubCommand; +use bdk_cli::{BlockchainClient, WalletSubCommand}; use bdk_cli::{ CliOpts, CliSubCommand, KeySubCommand, OfflineWalletSubCommand, OnlineWalletSubCommand, WalletOpts, @@ -104,58 +104,42 @@ fn new_online_wallet( where D: BatchDatabase, { - // Try to use Esplora config if "esplora" feature is enabled - #[cfg(feature = "esplora")] - let config_esplora: Option = { - let esplora_concurrency = wallet_opts.esplora_opts.esplora_concurrency; - wallet_opts.esplora_opts.esplora.clone().map(|base_url| { - AnyBlockchainConfig::Esplora(EsploraBlockchainConfig { - base_url, - concurrency: Some(esplora_concurrency), - }) - }) - }; - #[cfg(not(feature = "esplora"))] - let config_esplora = None; - - let config_electrum = AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig { - url: wallet_opts.electrum_opts.electrum.clone(), - socks5: wallet_opts.proxy_opts.proxy.clone(), - retry: wallet_opts.proxy_opts.retries, - timeout: wallet_opts.electrum_opts.timeout, - }); - - #[cfg(feature = "compact_filters")] - let config_compact_filters: Option = { - let mut peers = vec![]; - for addrs in wallet_opts.compactfilter_opts.address.clone() { - for _ in 0..wallet_opts.compactfilter_opts.conn_count { - peers.push(BitcoinPeerConfig { - address: addrs.clone(), - socks5: wallet_opts.proxy_opts.proxy.clone(), - socks5_credentials: wallet_opts.proxy_opts.proxy_auth.clone(), - }) + // Create requested blockchain client config + let config = match wallet_opts.blockchain_client { + #[cfg(feature = "electrum")] + BlockchainClient::Electrum => AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig { + url: wallet_opts.electrum_opts.electrum.clone(), + socks5: wallet_opts.proxy_opts.proxy.clone(), + retry: wallet_opts.proxy_opts.retries, + timeout: wallet_opts.electrum_opts.timeout, + }), + #[cfg(feature = "esplora")] + BlockchainClient::Esplora => AnyBlockchainConfig::Esplora(EsploraBlockchainConfig { + base_url: wallet_opts.esplora_opts.esplora.clone(), + concurrency: Some(wallet_opts.esplora_opts.esplora_concurrency), + }), + #[cfg(feature = "compact_filters")] + BlockchainClient::CompactFilters => { + let mut peers = vec![]; + for addrs in wallet_opts.compactfilter_opts.address.clone() { + for _ in 0..wallet_opts.compactfilter_opts.conn_count { + peers.push(BitcoinPeerConfig { + address: addrs.clone(), + socks5: wallet_opts.proxy_opts.proxy.clone(), + socks5_credentials: wallet_opts.proxy_opts.proxy_auth.clone(), + }) + } } - } - Some(AnyBlockchainConfig::CompactFilters( - CompactFiltersBlockchainConfig { + AnyBlockchainConfig::CompactFilters(CompactFiltersBlockchainConfig { peers, network, storage_dir: prepare_home_dir().into_os_string().into_string().unwrap(), skip_blocks: Some(wallet_opts.compactfilter_opts.skip_blocks), - }, - )) + }) + } }; - #[cfg(not(feature = "compact_filters"))] - let config_compact_filters = None; - - // Fall back to Electrum config if Esplora or Compact Filter config isn't provided - let config = config_esplora - .or(config_compact_filters) - .unwrap_or(config_electrum); - let descriptor = wallet_opts.descriptor.as_str(); let change_descriptor = wallet_opts.change_descriptor.as_deref(); let wallet = Wallet::new( diff --git a/src/lib.rs b/src/lib.rs index 872cd9e..54a3667 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -138,9 +138,11 @@ use bdk::{FeeRate, KeychainKind, Wallet}; /// # Example /// /// ``` +/// # #[cfg(feature = "electrum")] +/// # { /// # use bdk::bitcoin::Network; /// # use structopt::StructOpt; -/// # use bdk_cli::{CliOpts, WalletOpts, CliSubCommand, WalletSubCommand}; +/// # use bdk_cli::{CliOpts, WalletOpts, CliSubCommand, WalletSubCommand, BlockchainClient}; /// # #[cfg(feature = "electrum")] /// # use bdk_cli::ElectrumOpts; /// # #[cfg(feature = "esplora")] @@ -167,14 +169,14 @@ use bdk::{FeeRate, KeychainKind, Wallet}; /// verbose: false, /// descriptor: "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/44'/1'/0'/0/*)".to_string(), /// change_descriptor: None, -/// #[cfg(feature = "electrum")] +/// blockchain_client: BlockchainClient::Electrum, /// electrum_opts: ElectrumOpts { /// timeout: None, /// electrum: "ssl://electrum.blockstream.info:60002".to_string(), /// }, /// #[cfg(feature = "esplora")] /// esplora_opts: EsploraOpts { -/// esplora: None, +/// esplora: "https://blockstream.info/api/".to_string(), /// esplora_concurrency: 4, /// }, /// #[cfg(feature = "compact_filters")] @@ -183,7 +185,6 @@ use bdk::{FeeRate, KeychainKind, Wallet}; /// conn_count: 4, /// skip_blocks: 0, /// }, -/// #[cfg(any(feature="compact_filters", feature="electrum"))] /// proxy_opts: ProxyOpts{ /// proxy: None, /// proxy_auth: None, @@ -197,6 +198,7 @@ use bdk::{FeeRate, KeychainKind, Wallet}; /// }; /// /// assert_eq!(expected_cli_opts, cli_opts); +/// # } /// ``` #[derive(Debug, StructOpt, Clone, PartialEq)] #[structopt(name = "BDK CLI", @@ -283,9 +285,11 @@ pub enum WalletSubCommand { /// # Example /// /// ``` +/// # #[cfg(feature = "electrum")] +/// # { /// # use bdk::bitcoin::Network; /// # use structopt::StructOpt; -/// # use bdk_cli::WalletOpts; +/// # use bdk_cli::{WalletOpts, BlockchainClient}; /// # #[cfg(feature = "electrum")] /// # use bdk_cli::ElectrumOpts; /// # #[cfg(feature = "esplora")] @@ -308,14 +312,14 @@ pub enum WalletSubCommand { /// verbose: false, /// descriptor: "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/44'/1'/0'/0/*)".to_string(), /// change_descriptor: None, -/// #[cfg(feature = "electrum")] +/// blockchain_client: BlockchainClient::Electrum, /// electrum_opts: ElectrumOpts { /// timeout: None, /// electrum: "ssl://electrum.blockstream.info:60002".to_string(), /// }, /// #[cfg(feature = "esplora")] /// esplora_opts: EsploraOpts { -/// esplora: None, +/// esplora: "https://blockstream.info/api/".to_string(), /// esplora_concurrency: 4, /// }, /// #[cfg(feature = "compact_filters")] @@ -324,7 +328,6 @@ pub enum WalletSubCommand { /// conn_count: 4, /// skip_blocks: 0, /// }, -/// #[cfg(any(feature="compact_filters", feature="electrum"))] /// proxy_opts: ProxyOpts{ /// proxy: None, /// proxy_auth: None, @@ -333,6 +336,7 @@ pub enum WalletSubCommand { /// }; /// /// assert_eq!(expected_wallet_opts, wallet_opts); +/// # } /// ``` #[derive(Debug, StructOpt, Clone, PartialEq)] pub struct WalletOpts { @@ -353,6 +357,16 @@ pub struct WalletOpts { /// Sets the descriptor to use for internal addresses #[structopt(name = "CHANGE_DESCRIPTOR", short = "c", long = "change_descriptor")] pub change_descriptor: Option, + /// Blockchain client protocol + #[structopt(name = "BLOCKCHAIN_CLIENT", + short = "b", + long = "blockchain_client", + default_value = "electrum", + possible_values = &["electrum", "esplora", "compact_filters"], + parse(try_from_str = parse_blockchain_client), + )] + #[cfg(any(feature = "electrum", feature = "esplora", feature = "compact_filters"))] + pub blockchain_client: BlockchainClient, #[cfg(feature = "electrum")] #[structopt(flatten)] pub electrum_opts: ElectrumOpts, @@ -367,21 +381,52 @@ pub struct WalletOpts { pub proxy_opts: ProxyOpts, } +#[derive(Debug, StructOpt, Clone, PartialEq)] +#[structopt(rename_all = "snake")] +pub enum BlockchainClient { + #[cfg(feature = "electrum")] + /// Electrum server + Electrum, + #[cfg(feature = "esplora")] + /// Esplora server + Esplora, + #[cfg(feature = "compact_filters")] + /// Bitcoin Peers serving compact filters + CompactFilters, +} + +fn parse_blockchain_client(s: &str) -> Result { + match s { + #[cfg(feature = "electrum")] + "electrum" => Ok(BlockchainClient::Electrum), + #[cfg(feature = "esplora")] + "esplora" => Ok(BlockchainClient::Esplora), + #[cfg(feature = "compact_filters")] + "compact_filters" => Ok(BlockchainClient::CompactFilters), + _ => Err("Invalid blockchain client name".to_string()), + } +} + /// Proxy Server options /// /// Only activated for `compact_filters` or `electrum` #[cfg(any(feature = "compact_filters", feature = "electrum"))] #[derive(Debug, StructOpt, Clone, PartialEq)] pub struct ProxyOpts { - /// Sets the SOCKS5 proxy for Blockchain backend + /// Blockchain client SOCKS5 proxy #[structopt(name = "PROXY_ADDRS:PORT", long = "proxy", short = "p")] pub proxy: Option, - /// Sets the SOCKS5 proxy credential - #[structopt(name="PROXY_USER:PASSWD", long="proxy_auth", short="a", parse(try_from_str = parse_proxy_auth))] + /// Blockchain client SOCKS5 proxy credential + #[structopt(name="PROXY_USER:PASSWD", + long="proxy_auth", + short="a", + hide_env_values = true, + parse(try_from_str = parse_proxy_auth), + )] pub proxy_auth: Option<(String, String)>, - /// Sets the SOCKS5 proxy retries for the Electrum client + /// Blockchain client SOCKS5 proxy retries #[structopt( name = "PROXY_RETRIES", short = "r", @@ -397,7 +442,7 @@ pub struct ProxyOpts { #[cfg(feature = "compact_filters")] #[derive(Debug, StructOpt, Clone, PartialEq)] pub struct CompactFilterOpts { - /// Sets the full node network address + /// Compact filters blockchain client peer full node IP address:port #[structopt( name = "ADDRESS:PORT", short = "n", @@ -406,11 +451,11 @@ pub struct CompactFilterOpts { )] pub address: Vec, - /// Sets the number of parallel node connections + /// Compact filters blockchain client number of parallel node connections #[structopt(name = "CONNECTIONS", long = "conn_count", default_value = "4")] pub conn_count: usize, - /// Optionally skip initial `skip_blocks` blocks + /// Compact filters blockchain client skip initial blocks #[structopt( name = "SKIP_BLOCKS", short = "k", @@ -426,10 +471,10 @@ pub struct CompactFilterOpts { #[cfg(feature = "electrum")] #[derive(Debug, StructOpt, Clone, PartialEq)] pub struct ElectrumOpts { - /// Sets the SOCKS5 proxy timeout for the Electrum client + /// Electrum blockchain client SOCKS5 proxy timeout #[structopt(name = "PROXY_TIMEOUT", short = "t", long = "timeout")] pub timeout: Option, - /// Sets the Electrum server to use + /// Electrum blockchain client server url #[structopt( name = "SERVER:PORT", short = "s", @@ -445,10 +490,15 @@ pub struct ElectrumOpts { #[cfg(feature = "esplora")] #[derive(Debug, StructOpt, Clone, PartialEq)] pub struct EsploraOpts { - /// Use the esplora server if given as parameter - #[structopt(name = "ESPLORA_URL", short = "e", long = "esplora")] - pub esplora: Option, - /// Concurrency of requests made to the esplora server + /// Esplora blockchain client server url + #[structopt( + name = "ESPLORA_URL", + short = "e", + long = "esplora", + default_value = "https://blockstream.info/api/" + )] + pub esplora: String, + /// Esplora blockchain client request concurrency #[structopt( name = "ESPLORA_CONCURRENCY", long = "esplora_concurrency", @@ -938,7 +988,12 @@ pub enum KeySubCommand { )] word_count: usize, /// Seed password - #[structopt(name = "PASSWORD", short = "p", long = "password")] + #[structopt( + name = "PASSWORD", + short = "p", + long = "password", + hide_env_values = true + )] password: Option, }, /// Restore a master extended key from seed backup mnemonic words @@ -947,7 +1002,12 @@ pub enum KeySubCommand { #[structopt(name = "MNEMONIC", short = "m", long = "mnemonic")] mnemonic: String, /// Seed password - #[structopt(name = "PASSWORD", short = "p", long = "password")] + #[structopt( + name = "PASSWORD", + short = "p", + long = "password", + hide_env_values = true + )] password: Option, }, /// Derive a child key pair from a master extended key and a derivation path string (eg. "m/84'/1'/0'/0" or "m/84h/1h/0h/0") @@ -1054,7 +1114,7 @@ pub fn handle_compile_subcommand( #[cfg(test)] mod test { - use super::{CliOpts, WalletOpts}; + use super::{BlockchainClient, CliOpts, WalletOpts}; #[cfg(feature = "compiler")] use crate::handle_compile_subcommand; #[cfg(feature = "compact_filters")] @@ -1074,6 +1134,7 @@ mod test { use std::str::FromStr; use structopt::StructOpt; + #[cfg(feature = "electrum")] #[test] fn test_parse_wallet_get_new_address() { let cli_args = vec!["bdk-cli", "--network", "bitcoin", "wallet", @@ -1091,6 +1152,7 @@ mod test { verbose: false, descriptor: "wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)".to_string(), change_descriptor: Some("wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/1/*)".to_string()), + blockchain_client: BlockchainClient::Electrum, #[cfg(feature = "electrum")] electrum_opts: ElectrumOpts { timeout: None, @@ -1098,7 +1160,7 @@ mod test { }, #[cfg(feature = "esplora")] esplora_opts: EsploraOpts { - esplora: None, + esplora: "https://blockstream.info/api/".to_string(), esplora_concurrency: 4 }, #[cfg(feature = "compact_filters")] @@ -1141,6 +1203,7 @@ mod test { verbose: false, descriptor: "wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)".to_string(), change_descriptor: Some("wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/1/*)".to_string()), + blockchain_client: BlockchainClient::Electrum, #[cfg(feature = "electrum")] electrum_opts: ElectrumOpts { timeout: Some(10), @@ -1148,7 +1211,7 @@ mod test { }, #[cfg(feature = "esplora")] esplora_opts: EsploraOpts { - esplora: None, + esplora: "https://blockstream.info/api/".to_string(), esplora_concurrency: 4, }, #[cfg(feature = "compact_filters")] @@ -1177,7 +1240,7 @@ mod test { let cli_args = vec!["bdk-cli", "--network", "bitcoin", "wallet", "--descriptor", "wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)", "--change_descriptor", "wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/1/*)", - "--esplora", "https://blockstream.info/api/", + "--blockchain_client", "esplora", "--esplora_concurrency", "5", "get_new_address"]; @@ -1191,6 +1254,7 @@ mod test { verbose: false, descriptor: "wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)".to_string(), change_descriptor: Some("wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/1/*)".to_string()), + blockchain_client: BlockchainClient::Esplora, #[cfg(feature = "electrum")] electrum_opts: ElectrumOpts { timeout: None, @@ -1198,7 +1262,7 @@ mod test { }, #[cfg(feature = "esplora")] esplora_opts: EsploraOpts { - esplora: Some("https://blockstream.info/api/".to_string()), + esplora: "https://blockstream.info/api/".to_string(), esplora_concurrency: 5, }, #[cfg(feature = "compact_filters")] @@ -1226,7 +1290,8 @@ mod test { fn test_parse_wallet_compact_filters() { let cli_args = vec!["bdk-cli", "--network", "bitcoin", "wallet", "--descriptor", "wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)", - "--change_descriptor", "wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/1/*)", + "--change_descriptor", "wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/1/*)", + "--blockchain_client", "compact_filters", "--proxy", "127.0.0.1:9005", "--proxy_auth", "random_user:random_passwd", "--node", "127.0.0.1:18444", "127.2.3.1:19695", @@ -1244,6 +1309,7 @@ mod test { verbose: false, descriptor: "wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)".to_string(), change_descriptor: Some("wpkh(xpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/1/*)".to_string()), + blockchain_client: BlockchainClient::CompactFilters, #[cfg(feature = "electrum")] electrum_opts: ElectrumOpts { timeout: None, @@ -1251,7 +1317,7 @@ mod test { }, #[cfg(feature = "esplora")] esplora_opts: EsploraOpts { - esplora: None, + esplora: "https://blockstream.info/api/".to_string(), esplora_concurrency: 4, }, #[cfg(feature = "compact_filters")] @@ -1274,6 +1340,7 @@ mod test { assert_eq!(expected_cli_opts, cli_opts); } + #[cfg(feature = "electrum")] #[test] fn test_parse_wallet_sync() { let cli_args = vec!["bdk-cli", "--network", "testnet", "wallet", @@ -1290,6 +1357,7 @@ mod test { verbose: false, descriptor: "wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)".to_string(), change_descriptor: None, + blockchain_client: BlockchainClient::Electrum, #[cfg(feature = "electrum")] electrum_opts: ElectrumOpts { timeout: None, @@ -1297,7 +1365,7 @@ mod test { }, #[cfg(feature = "esplora")] esplora_opts: EsploraOpts { - esplora: None, + esplora: "https://blockstream.info/api/".to_string(), esplora_concurrency: 4, }, #[cfg(feature = "compact_filters")] @@ -1322,6 +1390,7 @@ mod test { assert_eq!(expected_cli_opts, cli_opts); } + #[cfg(feature = "electrum")] #[test] fn test_parse_wallet_create_tx() { let cli_args = vec!["bdk-cli", "--network", "testnet", "wallet", @@ -1356,6 +1425,7 @@ mod test { verbose: false, descriptor: "wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)".to_string(), change_descriptor: Some("wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/1/*)".to_string()), + blockchain_client: BlockchainClient::Electrum, #[cfg(feature = "electrum")] electrum_opts: ElectrumOpts { timeout: None, @@ -1363,7 +1433,7 @@ mod test { }, #[cfg(feature = "esplora")] esplora_opts: EsploraOpts { - esplora: None, + esplora: "https://blockstream.info/api/".to_string(), esplora_concurrency: 4, }, #[cfg(feature = "compact_filters")] @@ -1396,6 +1466,7 @@ mod test { assert_eq!(expected_cli_opts, cli_opts); } + #[cfg(feature = "electrum")] #[test] fn test_parse_wallet_broadcast() { let cli_args = vec!["bdk-cli", "--network", "testnet", "wallet", @@ -1413,6 +1484,7 @@ mod test { verbose: false, descriptor: "wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)".to_string(), change_descriptor: None, + blockchain_client: BlockchainClient::Electrum, #[cfg(feature = "electrum")] electrum_opts: ElectrumOpts { timeout: None, @@ -1420,7 +1492,7 @@ mod test { }, #[cfg(feature = "esplora")] esplora_opts: EsploraOpts { - esplora: None, + esplora: "https://blockstream.info/api/".to_string(), esplora_concurrency: 4, }, #[cfg(feature = "compact_filters")]