From e42812ba3722c45c3e5a4a28cdd89f2b6fbff5d4 Mon Sep 17 00:00:00 2001 From: rishflab Date: Fri, 1 Oct 2021 10:36:08 +1000 Subject: [PATCH] Add subcommand to print internal bitcoin wallet descriptor Example: cargo run --package swap --bin swap -- export-bitcoin-wallet {"descriptor":"wpkh(xprv9s21ZrQH143K2q85eUf2ppCtti2Zar6aDCW5dCC5DG9VvutJ3cpe3Qf9wZpQeraNf9JEuGem1RyJZQMEWCN2DpWyL5WbsvmSW6wbL7Jq53H/84'/0'/0'/0/*)","blockheight":0,"label":"cli-bitcoin"} --- CHANGELOG.md | 2 ++ swap/src/asb/command.rs | 12 ++++++++++++ swap/src/bin/asb.rs | 5 +++++ swap/src/bin/swap.rs | 17 +++++++++++++++++ swap/src/bitcoin/wallet.rs | 13 +++++++++++++ swap/src/cli/command.rs | 25 +++++++++++++++++++++++++ 6 files changed, 74 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a266e81..6a88db8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,8 @@ It is possible to migrate critical data from the old db to the sqlite but there - Added a `disable-timestamp` flag to the ASB that disables timestamps from logs. - A `config` subcommand that prints the current configuration including the data directory location. This feature should alleviate difficulties users were having when finding where xmr-btc-swap was storing data. +- Added `export-bitcoin-wallet` subcommand to the CLI and ASB, to print the internal bitcoin wallet descriptor. + This will allow users to transact and monitor using external wallets. ## [0.8.3] - 2021-09-03 diff --git a/swap/src/asb/command.rs b/swap/src/asb/command.rs index 403320c1..fba13667 100644 --- a/swap/src/asb/command.rs +++ b/swap/src/asb/command.rs @@ -74,6 +74,15 @@ where env_config: env_config(testnet), cmd: Command::Config, }, + RawCommand::ExportBitcoinWallet => Arguments { + testnet, + json, + sled, + disable_timestamp, + config_path: config_path(config, testnet)?, + env_config: env_config(testnet), + cmd: Command::ExportBitcoinWallet, + }, RawCommand::ManualRecovery(ManualRecovery::Redeem { redeem_params: RecoverCommandParams { swap_id }, do_not_await_finality, @@ -222,6 +231,7 @@ pub enum Command { SafelyAbort { swap_id: Uuid, }, + ExportBitcoinWallet, } #[derive(structopt::StructOpt, Debug)] @@ -296,6 +306,8 @@ pub enum RawCommand { about = "Prints the Bitcoin and Monero balance. Requires the monero-wallet-rpc to be running." )] Balance, + #[structopt(about = "Print the internal bitcoin wallet descriptor.")] + ExportBitcoinWallet, #[structopt(about = "Contains sub-commands for recovering a swap manually.")] ManualRecovery(ManualRecovery), } diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index 796d0355..be8e2fcf 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -301,6 +301,11 @@ async fn main() -> Result<()> { tracing::info!("Redeem transaction successfully published with id {}", txid); } + Command::ExportBitcoinWallet => { + let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; + let wallet_export = bitcoin_wallet.wallet_export("asb").await?; + println!("{}", wallet_export.to_string()) + } } Ok(()) diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index a8d7b3f9..047a3cc6 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -409,6 +409,23 @@ async fn main() -> Result<()> { println!("{}", table); } } + Command::ExportBitcoinWallet { + bitcoin_electrum_rpc_url, + bitcoin_target_block, + } => { + let seed = Seed::from_file_or_generate(data_dir.as_path()) + .context("Failed to read in seed file")?; + let bitcoin_wallet = init_bitcoin_wallet( + bitcoin_electrum_rpc_url, + &seed, + data_dir.clone(), + env_config, + bitcoin_target_block, + ) + .await?; + let wallet_export = bitcoin_wallet.wallet_export("cli").await?; + println!("{}", wallet_export.to_string()) + } }; Ok(()) } diff --git a/swap/src/bitcoin/wallet.rs b/swap/src/bitcoin/wallet.rs index fb746b10..1fa3d625 100644 --- a/swap/src/bitcoin/wallet.rs +++ b/swap/src/bitcoin/wallet.rs @@ -9,6 +9,7 @@ use bdk::database::BatchDatabase; use bdk::descriptor::Segwitv0; use bdk::electrum_client::{ElectrumApi, GetHistoryRes}; use bdk::keys::DerivableKey; +use bdk::wallet::export::WalletExport; use bdk::wallet::AddressIndex; use bdk::{FeeRate, KeychainKind, SignOptions}; use bitcoin::{Network, Script}; @@ -174,6 +175,18 @@ impl Wallet { sub } + + pub async fn wallet_export(&self, role: &str) -> Result { + let wallet = self.wallet.lock().await; + match bdk::wallet::export::WalletExport::export_wallet( + &wallet, + &format!("{}-{}", role, self.network), + true, + ) { + Ok(wallet_export) => Ok(wallet_export), + Err(err_msg) => Err(anyhow::Error::msg(err_msg)), + } + } } fn print_status_change(txid: Txid, old: Option, new: ScriptStatus) -> ScriptStatus { diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index b7d68e78..0f0736b3 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -239,6 +239,22 @@ where tor_socks5_port, }, }, + RawCommand::ExportBitcoinWallet { bitcoin } => { + let (bitcoin_electrum_rpc_url, bitcoin_target_block) = + bitcoin.apply_defaults(is_testnet)?; + + Arguments { + env_config: env_config_from(is_testnet), + debug, + json, + sled, + data_dir: data::data_dir_from(data, is_testnet)?, + cmd: Command::ExportBitcoinWallet { + bitcoin_electrum_rpc_url, + bitcoin_target_block, + }, + } + } }; Ok(ParseResult::Arguments(arguments)) @@ -289,6 +305,10 @@ pub enum Command { namespace: XmrBtcNamespace, tor_socks5_port: u16, }, + ExportBitcoinWallet { + bitcoin_electrum_rpc_url: Url, + bitcoin_target_block: usize, + }, } #[derive(structopt::StructOpt, Debug)] @@ -427,6 +447,11 @@ enum RawCommand { #[structopt(flatten)] tor: Tor, }, + /// Print the internal bitcoin wallet descriptor + ExportBitcoinWallet { + #[structopt(flatten)] + bitcoin: Bitcoin, + }, } #[derive(structopt::StructOpt, Debug)]