forked from bitcoin-teleport/teleport-transactions
-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
write integration test for taker cli app.
- Loading branch information
1 parent
f1f4317
commit c0bcbd7
Showing
3 changed files
with
265 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
use bitcoin::{address::NetworkChecked, Address, Amount}; | ||
use bitcoind::{bitcoincore_rpc::RpcApi, tempfile::tempdir, 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 { | ||
/// taker-cli binary path | ||
target: String, | ||
rpc_network: String, | ||
/// Connection type | ||
network: String, | ||
data_dir: PathBuf, | ||
/// Bitcoind instance | ||
bitcoind: BitcoinD, | ||
fee_rate: u64, | ||
/// no of makers in coinswap | ||
makers_count: usize, | ||
/// no of funding tx created in each swap | ||
tx_count: u32, | ||
} | ||
|
||
impl TakerCli { | ||
/// Construct a new [`TakerCli`] struct that also include initiating bitcoind. | ||
fn new( | ||
rpc_network: &str, | ||
network: &str, | ||
fee_rate: u64, | ||
makers_count: usize, | ||
tx_count: u32, | ||
) -> TakerCli { | ||
// Initiate the bitcoind backend. | ||
|
||
let temp_dir = tempdir().unwrap().into_path(); | ||
|
||
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(".coinswap/taker/"); | ||
|
||
TakerCli { | ||
target: "./target/debug/taker".to_string(), | ||
rpc_network: rpc_network.to_string(), | ||
network: network.to_string(), | ||
data_dir, | ||
bitcoind, | ||
fee_rate, | ||
makers_count, | ||
tx_count, | ||
} | ||
} | ||
|
||
// Build a cli-command | ||
fn execute(&self, cmd: &[&str]) -> String { | ||
let mut args = Vec::new(); | ||
|
||
// Data directory | ||
args.push("--data-directory"); | ||
args.push(&self.data_dir.as_os_str().to_str().unwrap()); | ||
|
||
// Full node network | ||
args.push("--NETWORK"); | ||
args.push(&self.rpc_network); | ||
|
||
// Connection network type (clearnet/tor) | ||
args.push("--network"); | ||
args.push(&self.network); | ||
|
||
// 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 | ||
let maker_count = self.makers_count.to_string(); | ||
args.push(&maker_count); | ||
|
||
// tx_count | ||
let tx_count = self.tx_count.to_string(); | ||
args.push(&tx_count); | ||
|
||
// fee_rate | ||
let fee_rate = self.fee_rate.to_string(); | ||
args.push(&fee_rate); | ||
|
||
// Final command to execute | ||
for arg in cmd { | ||
args.push(arg); | ||
} | ||
|
||
// Execute the command | ||
let output = Command::new(&self.target).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 mut output_string = std::str::from_utf8(&value).unwrap().to_string(); | ||
|
||
// `output_string` contains the log statements along with the required output -> removing the logs. | ||
let end_pos = output_string.rfind("\n").expect("must not fail"); | ||
output_string.replace_range(0..end_pos + 1, ""); | ||
|
||
output_string | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_taker_cli() { | ||
// create taker_cli instance | ||
let taker_cli = TakerCli::new("regtest", "clearnet", 1000, 3, 3); | ||
|
||
// 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<NetworkChecked> = | ||
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) | ||
let mining_address = taker_cli | ||
.bitcoind | ||
.client | ||
.get_new_address(None, None) | ||
.unwrap() | ||
.require_network(bitcoind::bitcoincore_rpc::bitcoin::Network::Regtest) | ||
.unwrap(); | ||
|
||
taker_cli | ||
.bitcoind | ||
.client | ||
.generate_to_address(1, &mining_address) | ||
.unwrap(); | ||
|
||
// 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 1000 Sats to wallet itself via send-to-address | ||
|
||
// get new external address | ||
let new_address = taker_cli.execute(&["get-new-address"]); | ||
|
||
// TODO: unexpected string is getting. | ||
taker_cli.execute(&["send-to-address", &new_address, "1000"]); | ||
|
||
// Generate initial 101 blocks | ||
let mining_address = taker_cli | ||
.bitcoind | ||
.client | ||
.get_new_address(None, None) | ||
.unwrap() | ||
.require_network(bitcoind::bitcoincore_rpc::bitcoin::Network::Regtest) | ||
.unwrap(); | ||
taker_cli | ||
.bitcoind | ||
.client | ||
.generate_to_address(101, &mining_address) | ||
.unwrap(); | ||
|
||
// 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"]); | ||
|
||
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!(2, no_of_seed_utxos); | ||
} |