From aed851c51ff65818480da962bd720da02ac70b0f Mon Sep 17 00:00:00 2001 From: KnowWhoami Date: Fri, 27 Sep 2024 14:34:18 +0530 Subject: [PATCH 1/5] customize log settings for taker binary. --- src/bin/directory-cli.rs | 2 +- src/bin/directoryd.rs | 2 +- src/bin/maker-cli.rs | 2 +- src/bin/makerd.rs | 2 +- src/utill.rs | 12 +++++------- tests/test_framework/mod.rs | 2 +- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/bin/directory-cli.rs b/src/bin/directory-cli.rs index 39c6ec63..40996585 100644 --- a/src/bin/directory-cli.rs +++ b/src/bin/directory-cli.rs @@ -40,7 +40,7 @@ fn send_rpc_req(req: &RpcMsgReq) { } fn main() { - setup_logger(); + setup_logger(log::LevelFilter::Info); let cli = App::parse(); match cli.command { diff --git a/src/bin/directoryd.rs b/src/bin/directoryd.rs index c599d288..8267df25 100644 --- a/src/bin/directoryd.rs +++ b/src/bin/directoryd.rs @@ -19,7 +19,7 @@ struct Cli { } fn main() { - setup_logger(); + setup_logger(log::LevelFilter::Info); let args = Cli::parse(); diff --git a/src/bin/maker-cli.rs b/src/bin/maker-cli.rs index 3b6d8989..9b64a9c2 100644 --- a/src/bin/maker-cli.rs +++ b/src/bin/maker-cli.rs @@ -40,7 +40,7 @@ enum Commands { } fn main() -> Result<(), MakerError> { - setup_logger(); + setup_logger(log::LevelFilter::Info); let cli = App::parse(); match cli.command { diff --git a/src/bin/makerd.rs b/src/bin/makerd.rs index 1ee8adac..b4a03008 100644 --- a/src/bin/makerd.rs +++ b/src/bin/makerd.rs @@ -53,7 +53,7 @@ struct Cli { } fn main() -> std::io::Result<()> { - setup_logger(); + setup_logger(log::LevelFilter::Info); let args = Cli::parse(); diff --git a/src/utill.rs b/src/utill.rs index b6b1c606..8c390645 100644 --- a/src/utill.rs +++ b/src/utill.rs @@ -17,6 +17,7 @@ use bitcoin::{ }, Network, PublicKey, ScriptBuf, WitnessProgram, WitnessVersion, }; +use log::LevelFilter; use log4rs::{ append::{console::ConsoleAppender, file::FileAppender}, config::{Appender, Logger, Root}, @@ -120,7 +121,8 @@ pub fn seed_phrase_to_unique_id(seed: &str) -> String { } /// Setup function that will only run once, even if called multiple times. -pub fn setup_logger() { +/// Takes an optional log level to set the desired logging verbosity for taker binary. +pub fn setup_logger(taker_log_level: LevelFilter) { Once::new().call_once(|| { env::set_var("RUST_LOG", "coinswap=info"); let taker_log_dir = get_taker_dir().join("debug.log"); @@ -139,7 +141,7 @@ pub fn setup_logger() { .logger( Logger::builder() .appender("taker") - .build("coinswap::taker", log::LevelFilter::Info), + .build("coinswap::taker", taker_log_level), ) .logger( Logger::builder() @@ -151,11 +153,7 @@ pub fn setup_logger() { .appender("directory") .build("coinswap::market", log::LevelFilter::Info), ) - .build( - Root::builder() - .appender("stdout") - .build(log::LevelFilter::Info), - ) + .build(Root::builder().appender("stdout").build(taker_log_level)) .unwrap(); log4rs::init_config(config).unwrap(); }); diff --git a/tests/test_framework/mod.rs b/tests/test_framework/mod.rs index 5e015954..2411663b 100644 --- a/tests/test_framework/mod.rs +++ b/tests/test_framework/mod.rs @@ -81,7 +81,7 @@ impl TestFramework { if cfg!(feature = "tor") && connection_type == ConnectionType::TOR { coinswap::tor::setup_mitosis(); } - setup_logger(); + setup_logger(log::LevelFilter::Info); // Setup directory let temp_dir = get_random_tmp_dir(); // Remove if previously existing From e23496da5867ced87c4733a471dbfc23d862f14a Mon Sep 17 00:00:00 2001 From: KnowWhoami Date: Fri, 27 Sep 2024 14:35:06 +0530 Subject: [PATCH 2/5] create send-to-address taker cli command. --- src/bin/taker.rs | 66 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/src/bin/taker.rs b/src/bin/taker.rs index cec27ab1..be923d89 100644 --- a/src/bin/taker.rs +++ b/src/bin/taker.rs @@ -1,6 +1,4 @@ -use std::path::PathBuf; - -use bitcoin::Amount; +use bitcoin::{Address, Amount}; use bitcoind::bitcoincore_rpc::{json::ListUnspentResultEntry, Auth}; use clap::Parser; use coinswap::{ @@ -8,8 +6,9 @@ use coinswap::{ utill::{ parse_proxy_auth, read_bitcoin_network_string, read_connection_network_string, setup_logger, }, - wallet::RPCConfig, + wallet::{Destination, RPCConfig, SendAmount}, }; +use std::{path::PathBuf, str::FromStr}; /// taker-cli is a command line app to use taker client API's. #[derive(Parser, Debug)] @@ -82,6 +81,18 @@ enum Commands { TotalBalance, /// Returns a new address GetNewAddress, + /// Send to an external wallet address. + SendToAddress { + /// Recipient address + #[clap(name = "address")] + address: String, + /// Amount to be sent (in sats) + #[clap(name = "amount")] + amount: u64, + /// Fee of a Tx(in sats) + #[clap(name = "fee")] + fee: u64, + }, /// Sync the offer book SyncOfferBook, /// Initiate the coinswap process @@ -89,8 +100,8 @@ enum Commands { } fn main() { - setup_logger(); let args = Cli::parse(); + let rpc_network = read_bitcoin_network_string(&args.rpc_network).unwrap(); let connection_type = read_connection_network_string(&args.network).unwrap(); let rpc_config = RPCConfig { @@ -117,11 +128,20 @@ fn main() { ) .unwrap(); + let log_level = match args.command { + Commands::DoCoinswap | Commands::SyncOfferBook | Commands::SendToAddress { .. } => { + log::LevelFilter::Info + } + _ => log::LevelFilter::Off, + }; + + setup_logger(log_level); + match args.command { Commands::SeedUtxo => { let utxos: Vec = taker .get_wallet() - .list_live_contract_spend_info(None) + .list_descriptor_utxo_spend_info(None) .unwrap() .iter() .map(|(l, _)| l.clone()) @@ -168,6 +188,40 @@ fn main() { let address = taker.get_wallet_mut().get_next_external_address().unwrap(); println!("{:?}", address); } + Commands::SendToAddress { + address, + amount, + fee, + } => { + let fee = Amount::from_sat(fee); + + let amount = Amount::from_sat(amount); + + let coins_to_spend = taker.get_wallet().coin_select(amount + fee).unwrap(); + + let destination = + Destination::Address(Address::from_str(&address).unwrap().assume_checked()); + + // create a signed tx + let tx = taker + .get_wallet_mut() + .spend_from_wallet( + fee, + SendAmount::Amount(amount), + destination, + &coins_to_spend, + ) + .unwrap(); + + let calculated_fee_rate = fee / (tx.weight()); + + println!( + "transaction_hex : {:?}", + bitcoin::consensus::encode::serialize_hex(&tx) + ); + println!("Calculated FeeRate : {:#}", calculated_fee_rate); + } + Commands::SyncOfferBook => { taker.sync_offerbook(args.maker_count).unwrap(); } From 3f5f49697070b967487780a8dc335459efbfab76 Mon Sep 17 00:00:00 2001 From: KnowWhoami Date: Fri, 27 Sep 2024 14:36:40 +0530 Subject: [PATCH 3/5] Write integration test for taker cli app. --- tests/taker_cli.rs | 250 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 tests/taker_cli.rs diff --git a/tests/taker_cli.rs b/tests/taker_cli.rs new file mode 100644 index 00000000..4edf9c14 --- /dev/null +++ b/tests/taker_cli.rs @@ -0,0 +1,250 @@ +use bitcoin::{address::NetworkChecked, Address, Amount, Transaction}; +use bitcoind::{bitcoincore_rpc::RpcApi, tempfile::env::temp_dir, BitcoinD, Conf}; + +use std::{ + fs, + path::{Path, PathBuf}, + process::Command, + str::FromStr, +}; + +/// The taker-cli command struct +/// Use it to perform all taker-cli operations +struct TakerCli { + data_dir: PathBuf, + /// Bitcoind instance + bitcoind: BitcoinD, +} + +impl TakerCli { + /// Construct a new [`TakerCli`] struct that also include initiating bitcoind. + fn new() -> TakerCli { + // Initiate the bitcoind backend. + + let temp_dir = temp_dir().join(".coinswap"); + + // Remove if previously existing + if temp_dir.exists() { + fs::remove_dir_all::(temp_dir.clone()).unwrap(); + } + + let mut conf = Conf::default(); + + conf.args.push("-txindex=1"); //txindex is must, or else wallet sync won't work. + conf.staticdir = Some(temp_dir.join(".bitcoin")); + + log::info!("bitcoind configuration: {:?}", conf.args); + + let os = std::env::consts::OS; + let arch = std::env::consts::ARCH; + let key = "BITCOIND_EXE"; + let curr_dir_path = std::env::current_dir().unwrap(); + + let bitcoind_path = match (os, arch) { + ("macos", "aarch64") => curr_dir_path.join("bin").join("bitcoind_macos"), + _ => curr_dir_path.join("bin").join("bitcoind"), + }; + std::env::set_var(key, bitcoind_path); + let exe_path = bitcoind::exe_path().unwrap(); + + log::info!("Executable path: {:?}", exe_path); + + let bitcoind = BitcoinD::with_conf(exe_path, &conf).unwrap(); + + // Generate initial 101 blocks + let mining_address = bitcoind + .client + .get_new_address(None, None) + .unwrap() + .require_network(bitcoind::bitcoincore_rpc::bitcoin::Network::Regtest) + .unwrap(); + bitcoind + .client + .generate_to_address(101, &mining_address) + .unwrap(); + + // derive data directory + let data_dir = temp_dir.join("taker"); + + TakerCli { data_dir, bitcoind } + } + + // Build a cli-command + fn execute(&self, cmd: &[&str]) -> String { + let mut args = vec![ + "--data-directory", + self.data_dir.as_os_str().to_str().unwrap(), + "--bitcoin-network", + "regtest", + "--connection-type", + "clearnet", + ]; + + // RPC authentication (user:password) from the cookie file + // + // get rpc_auth + // Path to the cookie file + let cookie_file_path = Path::new(&self.bitcoind.params.cookie_file); + + // Read the contents of the cookie file + let rpc_auth = fs::read_to_string(cookie_file_path).expect("failed to read from file"); + + args.push("--USER:PASSWORD"); + args.push(&rpc_auth); + + // Full node address for RPC connection + let rpc_address = self.bitcoind.params.rpc_socket.to_string(); + args.push("--ADDRESS:PORT"); + args.push(&rpc_address); + + // Wallet name + args.push("--WALLET"); + args.push("test_wallet"); + + // Custom arguments for the taker-cli command + + // makers count + args.push("3"); + + // tx_count + args.push("3"); + + // fee_rate + args.push("1000"); + + // Final command to execute + for arg in cmd { + args.push(arg); + } + + // Execute the command + let output = Command::new("./target/debug/taker") + .args(args) + .output() + .unwrap(); + + let mut value = output.stdout; + let error = output.stderr; + + if !error.is_empty() { + panic!("Error: {:?}", String::from_utf8(error).unwrap()); + } + + value.pop(); // Remove `\n` at the end + + // Get the output string from bytes + let output_string = std::str::from_utf8(&value).unwrap().to_string(); + + output_string + } + + /// Generate Blocks in regtest node. + pub fn generate_blocks(&self, n: u64) { + let mining_address = self + .bitcoind + .client + .get_new_address(None, None) + .unwrap() + .require_network(bitcoind::bitcoincore_rpc::bitcoin::Network::Regtest) + .unwrap(); + self.bitcoind + .client + .generate_to_address(n, &mining_address) + .unwrap(); + } +} + +#[test] +fn test_taker_cli() { + // create taker_cli instance + let taker_cli = TakerCli::new(); + + // Fund the taker with 3 utxos of 1 BTC each. + for _ in 0..3 { + // derive the address + let taker_address = taker_cli.execute(&["get-new-address"]); + + let taker_address: Address = + Address::from_str(&taker_address).unwrap().assume_checked(); + + // fund 1 BTC to derived address + taker_cli + .bitcoind + .client + .send_to_address( + &taker_address, + Amount::ONE_BTC, + None, + None, + None, + None, + None, + None, + ) + .unwrap(); + } + + // confirm balance( Generate blocks) + taker_cli.generate_blocks(10); + + // Assert that total_balance & seed_balance must be 3 BTC + let seed_balance = taker_cli.execute(&["seed-balance"]); + let total_balance = taker_cli.execute(&["total-balance"]); + + assert_eq!("300000000 SAT", seed_balance); + assert_eq!("300000000 SAT", total_balance); + + // Assert that total no of seed-utxos are 3. + let seed_utxos = taker_cli.execute(&["seed-utxo"]); + + let no_of_seed_utxos = seed_utxos.matches("ListUnspentResultEntry {").count(); + assert_eq!(3, no_of_seed_utxos); + + // Send 100,000 satoshis to a new address within the wallet, with a fee of 1,000 satoshis. + + // get new external address + let new_address = taker_cli.execute(&["get-new-address"]); + + let response = taker_cli.execute(&["send-to-address", &new_address, "100000", "1000"]); + + // Extract Transaction hex string + let tx_hex_start = response.find("transaction_hex").unwrap() + "transaction_hex : \"".len(); + let tx_hex_end = response.find("\"\n").unwrap(); + + let tx_hex = &response[tx_hex_start..tx_hex_end]; + + // Extract FeeRate + let fee_rate_start = response.find("FeeRate").unwrap() + "FeeRate : ".len(); + let fee_rate_end = response.find(" sat").unwrap(); + + let _fee_rate = &response[fee_rate_start..fee_rate_end]; + // TODO: Determine if asserts are needed for the calculated fee rate. + + let tx: Transaction = bitcoin::consensus::encode::deserialize_hex(tx_hex).unwrap(); + + // broadcast signed transaction + taker_cli.bitcoind.client.send_raw_transaction(&tx).unwrap(); + + // confirm balances + taker_cli.generate_blocks(10); + + // Assert the total_amount & seed_amount must be initial (balance -fee) + let seed_balance = taker_cli.execute(&["seed-balance"]); + let total_balance = taker_cli.execute(&["total-balance"]); + + // Since the amount is sent back to our wallet, the transaction fee is deducted from the balance. + assert_eq!("299999000 SAT", seed_balance); + assert_eq!("299999000 SAT", total_balance); + + // Assert that no of seed utxos are 2 + let seed_utxos = taker_cli.execute(&["seed-utxo"]); + + let no_of_seed_utxos = seed_utxos.matches("ListUnspentResultEntry {").count(); + assert_eq!(4, no_of_seed_utxos); + + // stopping Bitcoind + taker_cli.bitcoind.client.stop().unwrap(); + + // Wait for some time for successfull shutdown of bitcoind. + std::thread::sleep(std::time::Duration::from_secs(10)); +} From e18d7674cab3136fdf4db99bfcc6a48d89cb3949 Mon Sep 17 00:00:00 2001 From: KnowWhoami Date: Sat, 28 Sep 2024 19:06:42 +0530 Subject: [PATCH 4/5] create `verbosity` argument and some quick fixes. --- src/bin/taker.rs | 22 +++++++++++++++++----- src/utill.rs | 2 +- tests/taker_cli.rs | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/bin/taker.rs b/src/bin/taker.rs index be923d89..deb20275 100644 --- a/src/bin/taker.rs +++ b/src/bin/taker.rs @@ -8,6 +8,7 @@ use coinswap::{ }, wallet::{Destination, RPCConfig, SendAmount}, }; +use log::LevelFilter; use std::{path::PathBuf, str::FromStr}; /// taker-cli is a command line app to use taker client API's. @@ -43,6 +44,10 @@ struct Cli { /// Sets the taker wallet's name. If the wallet file already exists at data-directory, it will load that wallet. #[clap(name = "WALLET", long, short = 'w', default_value = "taker")] pub wallet_name: String, + /// Sets the verbosity level of logs. + /// Default: Determined by the command passed. + #[clap(long, short = 'v', possible_values = &["off", "error", "warn", "info", "debug", "trace"])] + pub verbosity: Option, /// Sets the maker count to initiate coinswap with. #[clap(name = "maker_count", default_value = "2")] pub maker_count: usize, @@ -128,11 +133,18 @@ fn main() { ) .unwrap(); - let log_level = match args.command { - Commands::DoCoinswap | Commands::SyncOfferBook | Commands::SendToAddress { .. } => { - log::LevelFilter::Info - } - _ => log::LevelFilter::Off, + // Determines the log level based on the verbosity argument or the command. + // + // If verbosity is provided, it converts the string to a `LevelFilter`. + // If verbosity is `None`, the log level is set according to the command. + let log_level = match args.verbosity { + Some(level) => LevelFilter::from_str(&level).unwrap(), + None => match args.command { + Commands::DoCoinswap | Commands::SyncOfferBook | Commands::SendToAddress { .. } => { + log::LevelFilter::Info + } + _ => log::LevelFilter::Off, + }, }; setup_logger(log_level); diff --git a/src/utill.rs b/src/utill.rs index 8c390645..42656939 100644 --- a/src/utill.rs +++ b/src/utill.rs @@ -121,7 +121,7 @@ pub fn seed_phrase_to_unique_id(seed: &str) -> String { } /// Setup function that will only run once, even if called multiple times. -/// Takes an optional log level to set the desired logging verbosity for taker binary. +/// Takes log level to set the desired logging verbosity for taker binary. pub fn setup_logger(taker_log_level: LevelFilter) { Once::new().call_once(|| { env::set_var("RUST_LOG", "coinswap=info"); diff --git a/tests/taker_cli.rs b/tests/taker_cli.rs index 4edf9c14..c957ecbc 100644 --- a/tests/taker_cli.rs +++ b/tests/taker_cli.rs @@ -246,5 +246,5 @@ fn test_taker_cli() { taker_cli.bitcoind.client.stop().unwrap(); // Wait for some time for successfull shutdown of bitcoind. - std::thread::sleep(std::time::Duration::from_secs(10)); + std::thread::sleep(std::time::Duration::from_secs(3)); } From 3d39c730ae8312112a21883a96f125eca856c5ae Mon Sep 17 00:00:00 2001 From: KnowWhoami Date: Tue, 1 Oct 2024 21:57:22 +0530 Subject: [PATCH 5/5] doc fixes --- src/bin/directoryd.rs | 1 - src/bin/taker.rs | 29 +++++++++++++++++++---------- src/market/directory.rs | 1 - src/utill.rs | 8 ++++---- tests/taker_cli.rs | 32 ++++++++------------------------ 5 files changed, 31 insertions(+), 40 deletions(-) diff --git a/src/bin/directoryd.rs b/src/bin/directoryd.rs index 8267df25..2dec8e0b 100644 --- a/src/bin/directoryd.rs +++ b/src/bin/directoryd.rs @@ -8,7 +8,6 @@ use std::{path::PathBuf, sync::Arc}; #[derive(Parser)] #[clap(version = option_env ! ("CARGO_PKG_VERSION").unwrap_or("unknown"), author = option_env ! ("CARGO_PKG_AUTHORS").unwrap_or(""))] - struct Cli { /// Optional network type. #[clap(long, short = 'n', default_value = "clearnet", possible_values = &["tor", "clearnet"])] diff --git a/src/bin/taker.rs b/src/bin/taker.rs index deb20275..c272b4b1 100644 --- a/src/bin/taker.rs +++ b/src/bin/taker.rs @@ -17,8 +17,8 @@ use std::{path::PathBuf, str::FromStr}; author = option_env ! ("CARGO_PKG_AUTHORS").unwrap_or(""))] struct Cli { /// Optional Connection Network Type - #[clap(long, default_value = "clearnet",possible_values = &["tor","clearnet"])] - network: String, + #[clap(long, default_value = "clearnet",short= 'c', possible_values = &["tor","clearnet"])] + connection_type: String, /// Optional DNS data directory. Default value : "~/.coinswap/taker" #[clap(long, short = 'd')] data_directory: Option, @@ -35,12 +35,11 @@ struct Cli { pub auth: (String, String), /// Sets the full node network, this should match with the network of the running node. #[clap( - name = "NETWORK", long, - short = 'n', + short = 'b', default_value = "regtest", possible_values = &["regtest", "signet", "mainnet"] )] - pub rpc_network: String, + pub bitcoin_network: String, /// Sets the taker wallet's name. If the wallet file already exists at data-directory, it will load that wallet. #[clap(name = "WALLET", long, short = 'w', default_value = "taker")] pub wallet_name: String, @@ -88,7 +87,6 @@ enum Commands { GetNewAddress, /// Send to an external wallet address. SendToAddress { - /// Recipient address #[clap(name = "address")] address: String, /// Amount to be sent (in sats) @@ -107,8 +105,8 @@ enum Commands { fn main() { let args = Cli::parse(); - let rpc_network = read_bitcoin_network_string(&args.rpc_network).unwrap(); - let connection_type = read_connection_network_string(&args.network).unwrap(); + let rpc_network = read_bitcoin_network_string(&args.bitcoin_network).unwrap(); + let connection_type = read_connection_network_string(&args.connection_type).unwrap(); let rpc_config = RPCConfig { url: args.rpc, auth: Auth::UserPass(args.auth.0, args.auth.1), @@ -136,7 +134,7 @@ fn main() { // Determines the log level based on the verbosity argument or the command. // // If verbosity is provided, it converts the string to a `LevelFilter`. - // If verbosity is `None`, the log level is set according to the command. + // Otherwise, the log level is set based on the command. let log_level = match args.verbosity { Some(level) => LevelFilter::from_str(&level).unwrap(), None => match args.command { @@ -205,6 +203,17 @@ fn main() { amount, fee, } => { + // NOTE: + // + // Currently, we take `fee` instead of `fee_rate` because we cannot calculate the fee for a + // transaction that hasn't been created yet when only a `fee_rate` is provided. + // + // As a result, the user must supply the fee as a parameter, and the function will return the + // transaction hex and the calculated `fee_rate`. + // This allows the user to infer what fee is needed for a successful transaction. + // + // This approach will be improved in the future BDK integration. + let fee = Amount::from_sat(fee); let amount = Amount::from_sat(amount); @@ -214,7 +223,6 @@ fn main() { let destination = Destination::Address(Address::from_str(&address).unwrap().assume_checked()); - // create a signed tx let tx = taker .get_wallet_mut() .spend_from_wallet( @@ -225,6 +233,7 @@ fn main() { ) .unwrap(); + // Derive fee rate from given `fee` argument. let calculated_fee_rate = fee / (tx.weight()); println!( diff --git a/src/market/directory.rs b/src/market/directory.rs index 95d41d66..ed3ae3f3 100644 --- a/src/market/directory.rs +++ b/src/market/directory.rs @@ -63,7 +63,6 @@ impl DirectoryServer { /// /// Default data-dir for linux: `~/.coinswap/` /// Default config locations: `~/.coinswap/dns/config.toml`. - pub fn new( config_path: Option, connection_type: Option, diff --git a/src/utill.rs b/src/utill.rs index 42656939..301b73a5 100644 --- a/src/utill.rs +++ b/src/utill.rs @@ -121,8 +121,8 @@ pub fn seed_phrase_to_unique_id(seed: &str) -> String { } /// Setup function that will only run once, even if called multiple times. -/// Takes log level to set the desired logging verbosity for taker binary. -pub fn setup_logger(taker_log_level: LevelFilter) { +/// Takes log level to set the desired logging verbosity +pub fn setup_logger(filter: LevelFilter) { Once::new().call_once(|| { env::set_var("RUST_LOG", "coinswap=info"); let taker_log_dir = get_taker_dir().join("debug.log"); @@ -141,7 +141,7 @@ pub fn setup_logger(taker_log_level: LevelFilter) { .logger( Logger::builder() .appender("taker") - .build("coinswap::taker", taker_log_level), + .build("coinswap::taker", filter), ) .logger( Logger::builder() @@ -153,7 +153,7 @@ pub fn setup_logger(taker_log_level: LevelFilter) { .appender("directory") .build("coinswap::market", log::LevelFilter::Info), ) - .build(Root::builder().appender("stdout").build(taker_log_level)) + .build(Root::builder().appender("stdout").build(filter)) .unwrap(); log4rs::init_config(config).unwrap(); }); diff --git a/tests/taker_cli.rs b/tests/taker_cli.rs index c957ecbc..73cb7601 100644 --- a/tests/taker_cli.rs +++ b/tests/taker_cli.rs @@ -9,10 +9,8 @@ use std::{ }; /// The taker-cli command struct -/// Use it to perform all taker-cli operations struct TakerCli { data_dir: PathBuf, - /// Bitcoind instance bitcoind: BitcoinD, } @@ -63,13 +61,12 @@ impl TakerCli { .generate_to_address(101, &mining_address) .unwrap(); - // derive data directory let data_dir = temp_dir.join("taker"); TakerCli { data_dir, bitcoind } } - // Build a cli-command + // Execute a cli-command fn execute(&self, cmd: &[&str]) -> String { let mut args = vec![ "--data-directory", @@ -81,14 +78,8 @@ impl TakerCli { ]; // RPC authentication (user:password) from the cookie file - // - // get rpc_auth - // Path to the cookie file let cookie_file_path = Path::new(&self.bitcoind.params.cookie_file); - - // Read the contents of the cookie file let rpc_auth = fs::read_to_string(cookie_file_path).expect("failed to read from file"); - args.push("--USER:PASSWORD"); args.push(&rpc_auth); @@ -97,12 +88,9 @@ impl TakerCli { args.push("--ADDRESS:PORT"); args.push(&rpc_address); - // Wallet name args.push("--WALLET"); args.push("test_wallet"); - // Custom arguments for the taker-cli command - // makers count args.push("3"); @@ -112,27 +100,28 @@ impl TakerCli { // fee_rate args.push("1000"); - // Final command to execute for arg in cmd { args.push(arg); } - // Execute the command let output = Command::new("./target/debug/taker") .args(args) .output() .unwrap(); + // Capture the standard output and error from the command execution let mut value = output.stdout; let error = output.stderr; + // Panic if there is any error output if !error.is_empty() { panic!("Error: {:?}", String::from_utf8(error).unwrap()); } - value.pop(); // Remove `\n` at the end + // Remove the `\n` at the end of the output + value.pop(); - // Get the output string from bytes + // Convert the output bytes to a UTF-8 string let output_string = std::str::from_utf8(&value).unwrap().to_string(); output_string @@ -156,18 +145,15 @@ impl TakerCli { #[test] fn test_taker_cli() { - // create taker_cli instance let taker_cli = TakerCli::new(); // Fund the taker with 3 utxos of 1 BTC each. for _ in 0..3 { - // derive the address let taker_address = taker_cli.execute(&["get-new-address"]); let taker_address: Address = Address::from_str(&taker_address).unwrap().assume_checked(); - // fund 1 BTC to derived address taker_cli .bitcoind .client @@ -184,7 +170,7 @@ fn test_taker_cli() { .unwrap(); } - // confirm balance( Generate blocks) + // confirm balance taker_cli.generate_blocks(10); // Assert that total_balance & seed_balance must be 3 BTC @@ -200,7 +186,7 @@ fn test_taker_cli() { let no_of_seed_utxos = seed_utxos.matches("ListUnspentResultEntry {").count(); assert_eq!(3, no_of_seed_utxos); - // Send 100,000 satoshis to a new address within the wallet, with a fee of 1,000 satoshis. + // Send 100,000 sats to a new address within the wallet, with a fee of 1,000 sats. // get new external address let new_address = taker_cli.execute(&["get-new-address"]); @@ -225,7 +211,6 @@ fn test_taker_cli() { // broadcast signed transaction taker_cli.bitcoind.client.send_raw_transaction(&tx).unwrap(); - // confirm balances taker_cli.generate_blocks(10); // Assert the total_amount & seed_amount must be initial (balance -fee) @@ -242,7 +227,6 @@ fn test_taker_cli() { let no_of_seed_utxos = seed_utxos.matches("ListUnspentResultEntry {").count(); assert_eq!(4, no_of_seed_utxos); - // stopping Bitcoind taker_cli.bitcoind.client.stop().unwrap(); // Wait for some time for successfull shutdown of bitcoind.