From d9e36838a501825d2f8ff2446269cec1e640f207 Mon Sep 17 00:00:00 2001 From: raphjaph Date: Wed, 25 Jan 2023 01:11:49 +0100 Subject: [PATCH] Use JSON for `wallet` command output (#1359) --- src/lib.rs | 2 +- src/rarity.rs | 63 ++++++++++++++++++++++++++- src/sat.rs | 2 +- src/sat_point.rs | 25 +++++++++++ src/subcommand.rs | 2 +- src/subcommand/wallet.rs | 14 +++--- src/subcommand/wallet/balance.rs | 7 ++- src/subcommand/wallet/inscriptions.rs | 10 ++--- src/subcommand/wallet/outputs.rs | 16 ++++++- src/subcommand/wallet/receive.rs | 7 ++- src/subcommand/wallet/sats.rs | 34 +++++++++++++-- src/subcommand/wallet/send.rs | 7 ++- src/subcommand/wallet/transactions.rs | 14 +++++- tests/lib.rs | 2 +- tests/wallet/balance.rs | 46 +++++++++++-------- tests/wallet/inscriptions.rs | 54 ++++++++++------------- tests/wallet/outputs.rs | 18 +++++--- tests/wallet/receive.rs | 9 ++-- tests/wallet/sats.rs | 28 ++++++------ tests/wallet/send.rs | 26 ++++++++--- tests/wallet/transactions.rs | 37 ++++++++++------ 21 files changed, 301 insertions(+), 122 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 2cf877b543..fb329abe83 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -115,7 +115,7 @@ mod rarity; mod representation; mod sat; mod sat_point; -mod subcommand; +pub mod subcommand; mod tally; mod templates; diff --git a/src/rarity.rs b/src/rarity.rs index d6837ab901..6ca21e2117 100644 --- a/src/rarity.rs +++ b/src/rarity.rs @@ -1,7 +1,7 @@ use super::*; #[derive(Debug, PartialEq, PartialOrd)] -pub(crate) enum Rarity { +pub enum Rarity { Common, Uncommon, Rare, @@ -52,6 +52,40 @@ impl From for Rarity { } } +impl FromStr for Rarity { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s { + "common" => Ok(Self::Common), + "uncommon" => Ok(Self::Uncommon), + "rare" => Ok(Self::Rare), + "epic" => Ok(Self::Epic), + "legendary" => Ok(Self::Legendary), + "mythic" => Ok(Self::Mythic), + _ => Err(anyhow!("invalid rarity: {s}")), + } + } +} + +impl Serialize for Rarity { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.collect_str(self) + } +} + +impl<'de> Deserialize<'de> for Rarity { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(DeserializeFromStr::deserialize(deserializer)?.0) + } +} + #[cfg(test)] mod tests { use super::*; @@ -95,4 +129,31 @@ mod tests { assert_eq!(Sat(2067187500000000).rarity(), Rarity::Legendary); assert_eq!(Sat(2067187500000000 + 1).rarity(), Rarity::Common); } + + #[test] + fn from_str_and_deserialize_ok() { + #[track_caller] + fn case(s: &str, expected: Rarity) { + let actual = s.parse::().unwrap(); + assert_eq!(actual, expected); + let round_trip = actual.to_string().parse::().unwrap(); + assert_eq!(round_trip, expected); + let serialized = serde_json::to_string(&expected).unwrap(); + assert!(serde_json::from_str::(&serialized).is_ok()); + } + + case("common", Rarity::Common); + case("uncommon", Rarity::Uncommon); + case("rare", Rarity::Rare); + case("epic", Rarity::Epic); + case("legendary", Rarity::Legendary); + case("mythic", Rarity::Mythic); + } + + #[test] + fn from_str_err() { + "abc".parse::().unwrap_err(); + + "".parse::().unwrap_err(); + } } diff --git a/src/sat.rs b/src/sat.rs index b4070f7181..9444a0ae22 100644 --- a/src/sat.rs +++ b/src/sat.rs @@ -2,7 +2,7 @@ use super::*; #[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Ord, PartialOrd, Deserialize, Serialize)] #[serde(transparent)] -pub(crate) struct Sat(pub(crate) u64); +pub struct Sat(pub(crate) u64); impl Sat { pub(crate) const LAST: Self = Self(Self::SUPPLY - 1); diff --git a/src/sat_point.rs b/src/sat_point.rs index b01c6ca626..bb1365d905 100644 --- a/src/sat_point.rs +++ b/src/sat_point.rs @@ -39,6 +39,15 @@ impl Serialize for SatPoint { } } +impl<'de> Deserialize<'de> for SatPoint { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(DeserializeFromStr::deserialize(deserializer)?.0) + } +} + impl FromStr for SatPoint { type Err = Error; @@ -87,4 +96,20 @@ mod tests { .parse::() .unwrap_err(); } + + #[test] + fn deserialize_ok() { + assert_eq!( + serde_json::from_str::( + "\"1111111111111111111111111111111111111111111111111111111111111111:1:1\"" + ) + .unwrap(), + SatPoint { + outpoint: "1111111111111111111111111111111111111111111111111111111111111111:1" + .parse() + .unwrap(), + offset: 1, + } + ); + } } diff --git a/src/subcommand.rs b/src/subcommand.rs index ab384d7d7a..c4b7b49af1 100644 --- a/src/subcommand.rs +++ b/src/subcommand.rs @@ -11,7 +11,7 @@ mod server; mod subsidy; mod supply; mod traits; -pub(crate) mod wallet; +pub mod wallet; fn print_json(output: impl Serialize) -> Result { serde_json::to_writer_pretty(io::stdout(), &output)?; diff --git a/src/subcommand/wallet.rs b/src/subcommand/wallet.rs index 02ef7955f5..1f54689ef1 100644 --- a/src/subcommand/wallet.rs +++ b/src/subcommand/wallet.rs @@ -14,17 +14,17 @@ use { transaction_builder::TransactionBuilder, }; -mod balance; +pub mod balance; pub(crate) mod create; pub(crate) mod inscribe; -mod inscriptions; -mod outputs; -mod receive; +pub mod inscriptions; +pub mod outputs; +pub mod receive; mod restore; -mod sats; -mod send; +pub mod sats; +pub mod send; pub(crate) mod transaction_builder; -mod transactions; +pub mod transactions; #[derive(Debug, Parser)] pub(crate) enum Wallet { diff --git a/src/subcommand/wallet/balance.rs b/src/subcommand/wallet/balance.rs index 6df2d827a5..746286df34 100644 --- a/src/subcommand/wallet/balance.rs +++ b/src/subcommand/wallet/balance.rs @@ -1,6 +1,11 @@ use super::*; use std::collections::BTreeSet; +#[derive(Serialize, Deserialize)] +pub struct Output { + pub cardinal: u64, +} + pub(crate) fn run(options: Options) -> Result { let index = Index::open(&options)?; index.update()?; @@ -18,7 +23,7 @@ pub(crate) fn run(options: Options) -> Result { } } - println!("{}", balance); + print_json(Output { cardinal: balance })?; Ok(()) } diff --git a/src/subcommand/wallet/inscriptions.rs b/src/subcommand/wallet/inscriptions.rs index d649e1670a..657b96faf1 100644 --- a/src/subcommand/wallet/inscriptions.rs +++ b/src/subcommand/wallet/inscriptions.rs @@ -1,10 +1,10 @@ use super::*; -#[derive(Serialize)] -struct Output { - inscription: InscriptionId, - location: SatPoint, - explorer: String, +#[derive(Serialize, Deserialize)] +pub struct Output { + pub inscription: InscriptionId, + pub location: SatPoint, + pub explorer: String, } pub(crate) fn run(options: Options) -> Result { diff --git a/src/subcommand/wallet/outputs.rs b/src/subcommand/wallet/outputs.rs index 7716b72613..a7579f73f3 100644 --- a/src/subcommand/wallet/outputs.rs +++ b/src/subcommand/wallet/outputs.rs @@ -1,9 +1,21 @@ use super::*; +#[derive(Serialize, Deserialize)] +pub struct Output { + pub output: OutPoint, + pub amount: u64, +} + pub(crate) fn run(options: Options) -> Result { - for (outpoint, amount) in get_unspent_outputs(&options)? { - println!("{outpoint}\t{}", amount.to_sat()); + let mut outputs = Vec::new(); + for (output, amount) in get_unspent_outputs(&options)? { + outputs.push(Output { + output, + amount: amount.to_sat(), + }); } + print_json(outputs)?; + Ok(()) } diff --git a/src/subcommand/wallet/receive.rs b/src/subcommand/wallet/receive.rs index e0684f138c..78726b8156 100644 --- a/src/subcommand/wallet/receive.rs +++ b/src/subcommand/wallet/receive.rs @@ -1,11 +1,16 @@ use super::*; +#[derive(Deserialize, Serialize)] +pub struct Output { + pub address: Address, +} + pub(crate) fn run(options: Options) -> Result { let address = options .bitcoin_rpc_client_for_wallet_command(false)? .get_new_address(None, Some(bitcoincore_rpc::json::AddressType::Bech32m))?; - println!("{}", address); + print_json(Output { address })?; Ok(()) } diff --git a/src/subcommand/wallet/sats.rs b/src/subcommand/wallet/sats.rs index eb6f4de2e5..2f653d3061 100644 --- a/src/subcommand/wallet/sats.rs +++ b/src/subcommand/wallet/sats.rs @@ -9,6 +9,20 @@ pub(crate) struct Sats { tsv: Option, } +#[derive(Serialize, Deserialize)] +pub struct OutputTsv { + pub sat: String, + pub output: OutPoint, +} + +#[derive(Serialize, Deserialize)] +pub struct OutputRare { + pub sat: Sat, + pub output: OutPoint, + pub offset: u64, + pub rarity: Rarity, +} + impl Sats { pub(crate) fn run(&self, options: Options) -> Result { let index = Index::open(&options)?; @@ -17,17 +31,29 @@ impl Sats { let utxos = get_unspent_output_ranges(&options, &index)?; if let Some(path) = &self.tsv { - for (output, sat) in sats_from_tsv( + let mut output = Vec::new(); + for (outpoint, sat) in sats_from_tsv( utxos, &fs::read_to_string(path) .with_context(|| format!("I/O error reading `{}`", path.display()))?, )? { - println!("{output}\t{sat}"); + output.push(OutputTsv { + sat: sat.into(), + output: outpoint, + }); } + print_json(output)?; } else { - for (output, sat, offset, rarity) in rare_sats(utxos) { - println!("{output}\t{sat}\t{offset}\t{rarity}"); + let mut output = Vec::new(); + for (outpoint, sat, offset, rarity) in rare_sats(utxos) { + output.push(OutputRare { + sat, + output: outpoint, + offset, + rarity, + }); } + print_json(output)?; } Ok(()) diff --git a/src/subcommand/wallet/send.rs b/src/subcommand/wallet/send.rs index e41fa3045d..d953d6dfe4 100644 --- a/src/subcommand/wallet/send.rs +++ b/src/subcommand/wallet/send.rs @@ -12,6 +12,11 @@ pub(crate) struct Send { fee_rate: FeeRate, } +#[derive(Serialize, Deserialize)] +pub struct Output { + pub transaction: Txid, +} + impl Send { pub(crate) fn run(self, options: Options) -> Result { let client = options.bitcoin_rpc_client_for_wallet_command(false)?; @@ -62,7 +67,7 @@ impl Send { let txid = client.send_to_address(&self.address, amount, None, None, None, None, None, None)?; - println!("{txid}"); + print_json(Output { transaction: txid })?; return Ok(()); } diff --git a/src/subcommand/wallet/transactions.rs b/src/subcommand/wallet/transactions.rs index c9e027b799..9e5961f911 100644 --- a/src/subcommand/wallet/transactions.rs +++ b/src/subcommand/wallet/transactions.rs @@ -6,8 +6,15 @@ pub(crate) struct Transactions { limit: Option, } +#[derive(Serialize, Deserialize)] +pub struct Output { + pub transaction: Txid, + pub confirmations: i32, +} + impl Transactions { pub(crate) fn run(self, options: Options) -> Result { + let mut output = Vec::new(); for tx in options .bitcoin_rpc_client_for_wallet_command(false)? .list_transactions( @@ -17,9 +24,14 @@ impl Transactions { None, )? { - println!("{}\t{}", tx.info.txid, tx.info.confirmations); + output.push(Output { + transaction: tx.info.txid, + confirmations: tx.info.confirmations, + }); } + print_json(output)?; + Ok(()) } } diff --git a/tests/lib.rs b/tests/lib.rs index ed77ecd780..8ee8659842 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -3,7 +3,7 @@ use { self::{command_builder::CommandBuilder, expected::Expected, test_server::TestServer}, bip39::Mnemonic, - bitcoin::{blockdata::constants::COIN_VALUE, Address, Network, OutPoint, Txid}, + bitcoin::{blockdata::constants::COIN_VALUE, Network, OutPoint, Txid}, executable_path::executable_path, pretty_assertions::assert_eq as pretty_assert_eq, regex::Regex, diff --git a/tests/wallet/balance.rs b/tests/wallet/balance.rs index 46f941d685..87b187b600 100644 --- a/tests/wallet/balance.rs +++ b/tests/wallet/balance.rs @@ -1,21 +1,27 @@ -use super::*; +use {super::*, ord::subcommand::wallet::balance::Output}; #[test] fn wallet_balance() { let rpc_server = test_bitcoincore_rpc::spawn(); create_wallet(&rpc_server); - CommandBuilder::new("wallet balance") - .rpc_server(&rpc_server) - .expected_stdout("0\n") - .run(); + assert_eq!( + CommandBuilder::new("wallet balance") + .rpc_server(&rpc_server) + .output::() + .cardinal, + 0 + ); rpc_server.mine_blocks(1); - CommandBuilder::new("wallet balance") - .rpc_server(&rpc_server) - .expected_stdout("5000000000\n") - .run(); + assert_eq!( + CommandBuilder::new("wallet balance") + .rpc_server(&rpc_server) + .output::() + .cardinal, + 50 * COIN_VALUE + ); } #[test] @@ -23,15 +29,21 @@ fn wallet_balance_only_counts_cardinal_utxos() { let rpc_server = test_bitcoincore_rpc::spawn(); create_wallet(&rpc_server); - CommandBuilder::new("wallet balance") - .rpc_server(&rpc_server) - .expected_stdout("0\n") - .run(); + assert_eq!( + CommandBuilder::new("wallet balance") + .rpc_server(&rpc_server) + .output::() + .cardinal, + 0 + ); inscribe(&rpc_server); - CommandBuilder::new("wallet balance") - .rpc_server(&rpc_server) - .expected_stdout(format!("{}\n", 100 * COIN_VALUE - 10_000)) - .run(); + assert_eq!( + CommandBuilder::new("wallet balance") + .rpc_server(&rpc_server) + .output::() + .cardinal, + 100 * COIN_VALUE - 10_000 + ); } diff --git a/tests/wallet/inscriptions.rs b/tests/wallet/inscriptions.rs index 9a7fe8f0cf..aeb2458c9f 100644 --- a/tests/wallet/inscriptions.rs +++ b/tests/wallet/inscriptions.rs @@ -1,11 +1,7 @@ -use super::*; - -#[derive(Deserialize)] -struct Inscription { - inscription: String, - location: String, - explorer: String, -} +use { + super::*, + ord::subcommand::wallet::{inscriptions::Output, receive}, +}; #[test] fn inscriptions() { @@ -19,26 +15,22 @@ fn inscriptions() { .. } = inscribe(&rpc_server); - let inscriptions = CommandBuilder::new("wallet inscriptions") + let output = CommandBuilder::new("wallet inscriptions") .rpc_server(&rpc_server) - .expected_stdout(format!("{inscription}\t{reveal}:0:0\n")) - .output::>(); + .output::>(); - assert_eq!(inscriptions.len(), 1); - assert_eq!(inscriptions[0].inscription, inscription); - assert_eq!(inscriptions[0].location, format!("{reveal}:0:0")); + assert_eq!(output.len(), 1); + assert_eq!(output[0].inscription, inscription.parse().unwrap()); + assert_eq!(output[0].location, format!("{reveal}:0:0").parse().unwrap()); assert_eq!( - inscriptions[0].explorer, + output[0].explorer, format!("https://ordinals.com/inscription/{inscription}") ); - let stdout = CommandBuilder::new("wallet receive") + let address = CommandBuilder::new("wallet receive") .rpc_server(&rpc_server) - .expected_exit_code(0) - .stdout_regex(".*") - .run(); - - let address = stdout.trim(); + .output::() + .address; let stdout = CommandBuilder::new(format!("wallet send {address} {inscription}")) .rpc_server(&rpc_server) @@ -50,13 +42,13 @@ fn inscriptions() { let txid = Txid::from_str(stdout.trim()).unwrap(); - let inscriptions = CommandBuilder::new("wallet inscriptions") + let output = CommandBuilder::new("wallet inscriptions") .rpc_server(&rpc_server) - .output::>(); + .output::>(); - assert_eq!(inscriptions.len(), 1); - assert_eq!(inscriptions[0].inscription, inscription); - assert_eq!(inscriptions[0].location, format!("{txid}:0:0")); + assert_eq!(output.len(), 1); + assert_eq!(output[0].inscription, inscription.parse().unwrap()); + assert_eq!(output[0].location, format!("{txid}:0:0").parse().unwrap()); } #[test] @@ -79,11 +71,11 @@ fn inscriptions_includes_locked_utxos() { vout: 0, }); - let inscriptions = CommandBuilder::new("wallet inscriptions") + let output = CommandBuilder::new("wallet inscriptions") .rpc_server(&rpc_server) - .output::>(); + .output::>(); - assert_eq!(inscriptions.len(), 1); - assert_eq!(inscriptions[0].inscription, inscription); - assert_eq!(inscriptions[0].location, format!("{reveal}:0:0")); + assert_eq!(output.len(), 1); + assert_eq!(output[0].inscription, inscription.parse().unwrap()); + assert_eq!(output[0].location, format!("{reveal}:0:0").parse().unwrap()); } diff --git a/tests/wallet/outputs.rs b/tests/wallet/outputs.rs index f4e85d33ef..9a13489229 100644 --- a/tests/wallet/outputs.rs +++ b/tests/wallet/outputs.rs @@ -1,4 +1,4 @@ -use super::*; +use {super::*, ord::subcommand::wallet::outputs::Output}; #[test] fn outputs() { @@ -9,10 +9,12 @@ fn outputs() { let outpoint = OutPoint::new(coinbase_tx.txid(), 0); let amount = coinbase_tx.output[0].value; - CommandBuilder::new("wallet outputs") + let output = CommandBuilder::new("wallet outputs") .rpc_server(&rpc_server) - .expected_stdout(format!("{outpoint}\t{amount}\n")) - .run(); + .output::>(); + + assert_eq!(output[0].output, outpoint); + assert_eq!(output[0].amount, amount); } #[test] @@ -26,8 +28,10 @@ fn outputs_includes_locked_outputs() { rpc_server.lock(outpoint); - CommandBuilder::new("wallet outputs") + let output = CommandBuilder::new("wallet outputs") .rpc_server(&rpc_server) - .expected_stdout(format!("{outpoint}\t{amount}\n")) - .run(); + .output::>(); + + assert_eq!(output[0].output, outpoint); + assert_eq!(output[0].amount, amount); } diff --git a/tests/wallet/receive.rs b/tests/wallet/receive.rs index e7c7e3f747..b86834a314 100644 --- a/tests/wallet/receive.rs +++ b/tests/wallet/receive.rs @@ -1,14 +1,13 @@ -use super::*; +use {super::*, ord::subcommand::wallet::receive::Output}; #[test] fn receive() { let rpc_server = test_bitcoincore_rpc::spawn(); create_wallet(&rpc_server); - let stdout = CommandBuilder::new("wallet receive") + let output = CommandBuilder::new("wallet receive") .rpc_server(&rpc_server) - .stdout_regex(".*") - .run(); + .output::(); - assert!(Address::from_str(stdout.trim()).is_ok()); + assert!(output.address.is_valid_for_network(Network::Bitcoin)); } diff --git a/tests/wallet/sats.rs b/tests/wallet/sats.rs index 83b970f074..86a8b568aa 100644 --- a/tests/wallet/sats.rs +++ b/tests/wallet/sats.rs @@ -1,4 +1,7 @@ -use super::*; +use { + super::*, + ord::subcommand::wallet::sats::{OutputRare, OutputTsv}, +}; #[test] fn sats() { @@ -6,14 +9,12 @@ fn sats() { create_wallet(&rpc_server); let second_coinbase = rpc_server.mine_blocks(1)[0].txdata[0].txid(); - CommandBuilder::new("--index-sats wallet sats") + let output = CommandBuilder::new("--index-sats wallet sats") .rpc_server(&rpc_server) - .expected_stdout(format!( - "{}\t{}\t0\tuncommon\n", - OutPoint::new(second_coinbase, 0), - 50 * COIN_VALUE, - )) - .run(); + .output::>(); + + assert_eq!(output[0].sat, 50 * COIN_VALUE); + assert_eq!(output[0].output.to_string(), format!("{second_coinbase}:0")); } #[test] @@ -22,14 +23,13 @@ fn sats_from_tsv_success() { create_wallet(&rpc_server); let second_coinbase = rpc_server.mine_blocks(1)[0].txdata[0].txid(); - CommandBuilder::new("--index-sats wallet sats --tsv foo.tsv") + let output = CommandBuilder::new("--index-sats wallet sats --tsv foo.tsv") .write("foo.tsv", "nvtcsezkbtg") .rpc_server(&rpc_server) - .expected_stdout(format!( - "{}\tnvtcsezkbtg\n", - OutPoint::new(second_coinbase, 0), - )) - .run(); + .output::>(); + + assert_eq!(output[0].sat, "nvtcsezkbtg"); + assert_eq!(output[0].output.to_string(), format!("{second_coinbase}:0")); } #[test] diff --git a/tests/wallet/send.rs b/tests/wallet/send.rs index 223771f956..e4a51664d3 100644 --- a/tests/wallet/send.rs +++ b/tests/wallet/send.rs @@ -1,4 +1,4 @@ -use super::*; +use {super::*, ord::subcommand::wallet::send::Output}; #[test] fn inscriptions_can_be_sent() { @@ -236,10 +236,16 @@ fn send_btc() { rpc_server.mine_blocks(1); - CommandBuilder::new("wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 1btc") + let output = CommandBuilder::new("wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 1btc") .rpc_server(&rpc_server) - .expected_stdout("0000000000000000000000000000000000000000000000000000000000000000\n") - .run(); + .output::(); + + assert_eq!( + output.transaction, + "0000000000000000000000000000000000000000000000000000000000000000" + .parse() + .unwrap() + ); assert_eq!( rpc_server.sent(), @@ -262,10 +268,16 @@ fn send_btc_locks_inscriptions() { let Inscribe { reveal, .. } = inscribe(&rpc_server); - CommandBuilder::new("wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 1btc") + let output = CommandBuilder::new("wallet send bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 1btc") .rpc_server(&rpc_server) - .expected_stdout("0000000000000000000000000000000000000000000000000000000000000000\n") - .run(); + .output::(); + + assert_eq!( + output.transaction, + "0000000000000000000000000000000000000000000000000000000000000000" + .parse() + .unwrap() + ); assert_eq!( rpc_server.sent(), diff --git a/tests/wallet/transactions.rs b/tests/wallet/transactions.rs index da5c5091ad..860daeeb04 100644 --- a/tests/wallet/transactions.rs +++ b/tests/wallet/transactions.rs @@ -1,4 +1,4 @@ -use super::*; +use {super::*, ord::subcommand::wallet::transactions::Output}; #[test] fn transactions() { @@ -9,17 +9,19 @@ fn transactions() { CommandBuilder::new("wallet transactions") .rpc_server(&rpc_server) - .run(); + .output::>(); assert_eq!(rpc_server.loaded_wallets().len(), 1); assert_eq!(rpc_server.loaded_wallets().first().unwrap(), "ord"); rpc_server.mine_blocks(1); - CommandBuilder::new("wallet transactions") + let output = CommandBuilder::new("wallet transactions") .rpc_server(&rpc_server) - .stdout_regex("[[:xdigit:]]{64}\t1\n") - .run(); + .output::>(); + + assert_regex_match!(output[0].transaction.to_string(), "[[:xdigit:]]{64}"); + assert_eq!(output[0].confirmations, 1); } #[test] @@ -29,24 +31,31 @@ fn transactions_with_limit() { CommandBuilder::new("wallet transactions") .rpc_server(&rpc_server) + .stdout_regex(".*") .run(); rpc_server.mine_blocks(1); - CommandBuilder::new("wallet transactions") + let output = CommandBuilder::new("wallet transactions") .rpc_server(&rpc_server) - .stdout_regex("[[:xdigit:]]{64}\t1\n") - .run(); + .output::>(); + + assert_regex_match!(output[0].transaction.to_string(), "[[:xdigit:]]{64}"); + assert_eq!(output[0].confirmations, 1); rpc_server.mine_blocks(1); - CommandBuilder::new("wallet transactions") + let output = CommandBuilder::new("wallet transactions") .rpc_server(&rpc_server) - .stdout_regex("[[:xdigit:]]{64}\t1\n[[:xdigit:]]{64}\t2\n") - .run(); + .output::>(); - CommandBuilder::new("wallet transactions --limit 1") + assert_regex_match!(output[1].transaction.to_string(), "[[:xdigit:]]{64}"); + assert_eq!(output[1].confirmations, 2); + + let output = CommandBuilder::new("wallet transactions --limit 1") .rpc_server(&rpc_server) - .stdout_regex("[[:xdigit:]]{64}\t1\n") - .run(); + .output::>(); + + assert_regex_match!(output[0].transaction.to_string(), "[[:xdigit:]]{64}"); + assert_eq!(output[0].confirmations, 1); }