diff --git a/src/subcommand/wallet/resume.rs b/src/subcommand/wallet/resume.rs index 64c3fcff0b..8e95171e5c 100644 --- a/src/subcommand/wallet/resume.rs +++ b/src/subcommand/wallet/resume.rs @@ -8,6 +8,8 @@ pub struct ResumeOutput { pub(crate) struct Resume { #[arg(long, help = "Don't broadcast transactions.")] pub(crate) dry_run: bool, + #[arg(long, help = "Pending etching to resume.")] + pub(crate) rune: Option, } impl Resume { @@ -18,7 +20,22 @@ impl Resume { break; } - for (rune, entry) in wallet.pending_etchings()? { + let spaced_rune = self.rune; + + let pending_etchings = if let Some(spaced_rune) = spaced_rune { + let pending_etching = wallet.load_etching(spaced_rune.rune)?; + + ensure!( + pending_etching.is_some(), + "rune {spaced_rune} does not correspond to any pending etching." + ); + + vec![(spaced_rune.rune, pending_etching.unwrap())] + } else { + wallet.pending_etchings()? + }; + + for (rune, entry) in pending_etchings { if self.dry_run { etchings.push(batch::Output { reveal_broadcast: false, diff --git a/tests/wallet/resume.rs b/tests/wallet/resume.rs index 3658b789e8..6d1b632f19 100644 --- a/tests/wallet/resume.rs +++ b/tests/wallet/resume.rs @@ -6,17 +6,8 @@ use { }, }; -#[test] -fn wallet_resume() { - let core = mockcore::builder().network(Network::Regtest).build(); - - let ord = TestServer::spawn_with_server_args(&core, &["--regtest", "--index-runes"], &[]); - - create_wallet(&core, &ord); - - core.mine_blocks(1); - - let batchfile = batch::File { +fn get_batchfile() -> batch::File { + batch::File { etching: Some(batch::Etching { divisibility: 0, rune: SpacedRune { @@ -33,53 +24,71 @@ fn wallet_resume() { ..default() }], ..default() - }; + } +} - let tempdir = Arc::new(TempDir::new().unwrap()); +fn inscribe_batch( + batchfile: &batch::File, + tempdir: &Arc, + core: &mockcore::Handle, + ord: &TestServer, +) { + let mut spawn = + CommandBuilder::new("--regtest --index-runes wallet batch --fee-rate 0 --batch batch.yaml") + .temp_dir(tempdir.clone()) + .write("batch.yaml", serde_yaml::to_string(&batchfile).unwrap()) + .write("inscription.jpeg", "inscription") + .core(core) + .ord(ord) + .expected_exit_code(1) + .spawn(); + + let mut buffer = String::new(); - { - let mut spawn = - CommandBuilder::new("--regtest --index-runes wallet batch --fee-rate 0 --batch batch.yaml") - .temp_dir(tempdir.clone()) - .write("batch.yaml", serde_yaml::to_string(&batchfile).unwrap()) - .write("inscription.jpeg", "inscription") - .core(&core) - .ord(&ord) - .expected_exit_code(1) - .spawn(); - - let mut buffer = String::new(); - - BufReader::new(spawn.child.stderr.as_mut().unwrap()) - .read_line(&mut buffer) - .unwrap(); - - assert_regex_match!( - buffer, - "Waiting for rune AAAAAAAAAAAAA commitment [[:xdigit:]]{64} to mature…\n" - ); - - core.mine_blocks(1); - - signal::kill( - Pid::from_raw(spawn.child.id().try_into().unwrap()), - Signal::SIGINT, - ) + BufReader::new(spawn.child.stderr.as_mut().unwrap()) + .read_line(&mut buffer) .unwrap(); - buffer.clear(); + assert_regex_match!( + buffer, + "Waiting for rune AAAAAAAAAAAAA commitment [[:xdigit:]]{64} to mature…\n" + ); - BufReader::new(spawn.child.stderr.as_mut().unwrap()) - .read_line(&mut buffer) - .unwrap(); + core.mine_blocks(1); - assert_eq!( - buffer, - "Shutting down gracefully. Press again to shutdown immediately.\n" - ); + signal::kill( + Pid::from_raw(spawn.child.id().try_into().unwrap()), + Signal::SIGINT, + ) + .unwrap(); - spawn.child.wait().unwrap(); - } + buffer.clear(); + + BufReader::new(spawn.child.stderr.as_mut().unwrap()) + .read_line(&mut buffer) + .unwrap(); + + assert_eq!( + buffer, + "Shutting down gracefully. Press again to shutdown immediately.\n" + ); + + spawn.child.wait().unwrap(); +} + +#[test] +fn wallet_resume() { + let core = mockcore::builder().network(Network::Regtest).build(); + let ord = TestServer::spawn_with_server_args(&core, &["--regtest", "--index-runes"], &[]); + + create_wallet(&core, &ord); + + core.mine_blocks(1); + + let batchfile = get_batchfile(); + let tempdir = Arc::new(TempDir::new().unwrap()); + + inscribe_batch(&batchfile, &tempdir, &core, &ord); core.mine_blocks(6); @@ -106,79 +115,79 @@ fn wallet_resume() { } #[test] -fn resume_suspended() { +fn wallet_resume_by_rune_name() { let core = mockcore::builder().network(Network::Regtest).build(); - let ord = TestServer::spawn_with_server_args(&core, &["--regtest", "--index-runes"], &[]); create_wallet(&core, &ord); core.mine_blocks(1); - let batchfile = batch::File { - etching: Some(batch::Etching { - divisibility: 0, - rune: SpacedRune { - rune: Rune(RUNE), - spacers: 0, - }, - supply: "1000".parse().unwrap(), - premine: "1000".parse().unwrap(), - symbol: '¢', - ..default() - }), - inscriptions: vec![batch::Entry { - file: Some("inscription.jpeg".into()), - ..default() - }], - ..default() - }; + let batchfile = get_batchfile(); + let tempdir = Arc::new(TempDir::new().unwrap()); + + inscribe_batch(&batchfile, &tempdir, &core, &ord); + + core.mine_blocks(6); + + let output = CommandBuilder::new("--regtest --index-runes wallet resume --rune AAAAAAAAAAAAA") + .temp_dir(tempdir) + .core(&core) + .ord(&ord) + .run_and_deserialize_output::(); + + assert_eq!( + output + .etchings + .first() + .unwrap() + .rune + .clone() + .unwrap() + .rune + .rune, + Rune(RUNE) + ); + + assert!(output.etchings.first().unwrap().reveal_broadcast); +} + +#[test] +fn wallet_resume_by_rune_not_found() { + let core = mockcore::builder().network(Network::Regtest).build(); + let ord = TestServer::spawn_with_server_args(&core, &["--regtest", "--index-runes"], &[]); + + create_wallet(&core, &ord); + core.mine_blocks(1); + + let batchfile = get_batchfile(); let tempdir = Arc::new(TempDir::new().unwrap()); - { - let mut spawn = - CommandBuilder::new("--regtest --index-runes wallet batch --fee-rate 0 --batch batch.yaml") - .temp_dir(tempdir.clone()) - .write("batch.yaml", serde_yaml::to_string(&batchfile).unwrap()) - .write("inscription.jpeg", "inscription") - .core(&core) - .ord(&ord) - .expected_exit_code(1) - .spawn(); - - let mut buffer = String::new(); - - BufReader::new(spawn.child.stderr.as_mut().unwrap()) - .read_line(&mut buffer) - .unwrap(); - - assert_regex_match!( - buffer, - "Waiting for rune AAAAAAAAAAAAA commitment [[:xdigit:]]{64} to mature…\n" - ); - - core.mine_blocks(1); - - signal::kill( - Pid::from_raw(spawn.child.id().try_into().unwrap()), - Signal::SIGINT, - ) - .unwrap(); + inscribe_batch(&batchfile, &tempdir, &core, &ord); + + core.mine_blocks(6); + + CommandBuilder::new("--regtest --index-runes wallet resume --rune BBBBBBBBBBBBB") + .temp_dir(tempdir) + .core(&core) + .ord(&ord) + .expected_stderr("error: rune BBBBBBBBBBBBB does not correspond to any pending etching."); +} - buffer.clear(); +#[test] +fn resume_suspended() { + let core = mockcore::builder().network(Network::Regtest).build(); + let ord = TestServer::spawn_with_server_args(&core, &["--regtest", "--index-runes"], &[]); - BufReader::new(spawn.child.stderr.as_mut().unwrap()) - .read_line(&mut buffer) - .unwrap(); + create_wallet(&core, &ord); - assert_eq!( - buffer, - "Shutting down gracefully. Press again to shutdown immediately.\n" - ); + core.mine_blocks(1); - spawn.child.wait().unwrap(); - } + let batchfile = get_batchfile(); + let tempdir = Arc::new(TempDir::new().unwrap()); + + inscribe_batch(&batchfile, &tempdir, &core, &ord); let mut spawn = CommandBuilder::new("--regtest --index-runes wallet resume") .temp_dir(tempdir) @@ -216,25 +225,7 @@ fn commitment_output_is_locked() { core.mine_blocks(1); - let batchfile = batch::File { - etching: Some(batch::Etching { - divisibility: 0, - rune: SpacedRune { - rune: Rune(RUNE), - spacers: 0, - }, - supply: "1000".parse().unwrap(), - premine: "1000".parse().unwrap(), - symbol: '¢', - ..default() - }), - inscriptions: vec![batch::Entry { - file: Some("inscription.jpeg".into()), - ..default() - }], - ..default() - }; - + let batchfile = get_batchfile(); let tempdir = Arc::new(TempDir::new().unwrap()); let mut spawn =