diff --git a/tests/bitcoind.rs b/tests/bitcoind.rs index 41534fd..d6ec82c 100644 --- a/tests/bitcoind.rs +++ b/tests/bitcoind.rs @@ -1,8 +1,40 @@ -use bitcoind::bitcoincore_rpc; +//! Test PSBT crate against Bitcoin Core using [`bitcoind`]. + +mod client; + +use client::Client; +use psbt_v2::bitcoin::Amount; + +#[track_caller] +fn client() -> Client { + let client = Client::new().expect("failed to create client"); + // Sanity check. + assert_eq!(0, client.get_blockchain_info().unwrap().blocks); + + client.fund().expect("failed to fund client"); + client +} #[test] -fn bitcoind_get_blockchain_info() { - use bitcoincore_rpc::RpcApi; - let bitcoind = bitcoind::BitcoinD::from_downloaded().expect("failed to init bitcoind"); - assert_eq!(0, bitcoind.client.get_blockchain_info().unwrap().blocks); +fn bitcoind_get_core_wallet_controlled_address() { + let client = client(); + let address = client.core_wallet_controlled_address().expect("get_new_address failed"); + println!("address: {}", address); +} + +#[test] +fn bitcoind_fund_core_controlled_wallet() { + let client = client(); + assert!(client.fund().is_ok()) +} + +#[test] +fn bitcoind_send() { + let client = client(); + + let address = client.core_wallet_controlled_address().expect("get_new_address failed"); + let amount = Amount::ONE_BTC; + + let txid = client.send(amount, &address).expect("send failed"); + println!("txid: {}", txid); } diff --git a/tests/client.rs b/tests/client.rs new file mode 100644 index 0000000..073964d --- /dev/null +++ b/tests/client.rs @@ -0,0 +1,70 @@ +use bitcoind::bitcoincore_rpc::bitcoincore_rpc_json::{AddressType, GetBlockchainInfoResult}; +use bitcoind::bitcoincore_rpc::RpcApi; +use bitcoind::BitcoinD; +use psbt_v2::bitcoin::{Address, Amount, Network, Txid}; + +const NETWORK: Network = Network::Regtest; + +/// A custom bitcoind client. +pub struct Client { + bitcoind: BitcoinD, +} + +impl Client { + /// Creates a new [`Client`]. + pub fn new() -> anyhow::Result { + let bitcoind = BitcoinD::from_downloaded()?; + let client = Client { bitcoind }; + + Ok(client) + } + + /// Calls through to bitcoincore_rpc client. + pub fn get_blockchain_info(&self) -> anyhow::Result { + let client = &self.bitcoind.client; + Ok(client.get_blockchain_info()?) + } + + /// Gets an address controlled by the currently loaded Bitcoin Core wallet (via `bitcoind`). + pub fn core_wallet_controlled_address(&self) -> anyhow::Result
{ + let client = &self.bitcoind.client; + let label = None; + let address_type = Some(AddressType::Bech32m); + let address = client.get_new_address(label, address_type)?.require_network(NETWORK)?; + Ok(address) + } + + /// Funds the bitcoind wallet with a spendable 50 BTC utxo. + pub fn fund(&self) -> anyhow::Result<()> { + let client = &self.bitcoind.client; + // Generate to an address controlled by the bitcoind wallet and wait for funds to mature. + let address = self.core_wallet_controlled_address()?; + let _ = client.generate_to_address(101, &address)?; + + Ok(()) + } + + /// Send `amount` to `address` setting all other `bitcoincore_prc::send_to_address` args to `None`. + pub fn send(&self, amount: Amount, address: &Address) -> anyhow::Result { + let client = &self.bitcoind.client; + + let comment = None; + let comment_to = None; + let subtract_fee = None; + let replacable = None; + let confirmation_target = None; + let estimate_mode = None; + + let txid = client.send_to_address( + address, + amount, + comment, + comment_to, + subtract_fee, + replacable, + confirmation_target, + estimate_mode, + )?; + Ok(txid) + } +}