Skip to content

Commit ce1c3d1

Browse files
committed
Align CLI with main-address policy and fix sync prompt/spinner order
1 parent 7b76cd4 commit ce1c3d1

17 files changed

Lines changed: 200 additions & 67 deletions

src/commands/account.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::cli::{AccountAction, AccountArgs, Cli};
22
use crate::error::AppError;
3+
use crate::output::CommandOutput;
34
use crate::wallet_service::{now_unix, AccountState};
45
use crate::{load_wallet_session, profile_path, read_profile, write_profile};
5-
use crate::output::CommandOutput;
66
use zinc_core::Account;
77

88
pub async fn run(cli: &Cli, args: &AccountArgs) -> Result<CommandOutput, AppError> {

src/commands/address.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::cli::{AddressArgs, AddressKind, Cli};
22
use crate::error::AppError;
3+
use crate::output::CommandOutput;
34
use crate::wallet_service::map_wallet_error;
45
use crate::{load_wallet_session, persist_wallet_session};
5-
use crate::output::CommandOutput;
66

77
pub async fn run(cli: &Cli, args: &AddressArgs) -> Result<CommandOutput, AppError> {
88
let mut session = load_wallet_session(cli)?;

src/commands/doctor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::cli::Cli;
22
use crate::error::AppError;
3-
use crate::{profile_path, read_profile};
43
use crate::output::CommandOutput;
4+
use crate::{profile_path, read_profile};
55
use zinc_core::{OrdClient, ZincWallet};
66

77
pub async fn run(cli: &Cli) -> Result<CommandOutput, AppError> {

src/commands/inscription.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ pub async fn run(cli: &Cli, _args: &InscriptionArgs) -> Result<CommandOutput, Ap
1212
let display_items = if !cli.thumb_enabled() {
1313
None
1414
} else {
15-
Some(get_inscription_display_items(
16-
&session.profile.ord_url,
17-
&sorted_inscriptions,
18-
)
19-
.await)
15+
Some(get_inscription_display_items(&session.profile.ord_url, &sorted_inscriptions).await)
2016
};
2117

2218
Ok(CommandOutput::InscriptionList {

src/commands/lock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::cli::{Cli, LockAction, LockArgs};
22
use crate::error::AppError;
3+
use crate::output::CommandOutput;
34
use crate::wallet_service::now_unix;
45
use crate::{confirm, profile_lock_path, read_lock_metadata};
5-
use crate::output::CommandOutput;
66
use std::fs;
77

88
pub async fn run(cli: &Cli, args: &LockArgs) -> Result<CommandOutput, AppError> {

src/commands/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ pub mod setup;
1212
pub mod snapshot;
1313
pub mod sync;
1414
pub mod tx;
15+
pub mod version;
1516
pub mod wait;
1617
pub mod wallet;
17-
pub mod version;

src/commands/offer.rs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,23 @@ pub async fn run(cli: &Cli, args: &OfferArgs) -> Result<CommandOutput, AppError>
9292
})?;
9393
let expires_unix = i64::try_from(expires_u64)
9494
.map_err(|_| AppError::Invalid("expires_at_unix is out of range".to_string()))?;
95+
let main_payment_address = session
96+
.wallet
97+
.peek_payment_address(0)
98+
.map(|address| address.to_string())
99+
.ok_or_else(|| {
100+
AppError::Internal("wallet main payment address unavailable".to_string())
101+
})?;
102+
let resolved_seller_payout_address = resolve_seller_payout_address(
103+
&main_payment_address,
104+
seller_payout_address.as_deref(),
105+
)?;
95106

96107
let request = CreateOfferRequest {
97108
inscription_id: inscription.clone(),
98109
seller_outpoint: inscription_details.satpoint.outpoint,
99110
seller_input_address: output_details.address.clone(),
100-
seller_payout_address: seller_payout_address
101-
.clone()
102-
.unwrap_or_else(|| output_details.address.clone()),
111+
seller_payout_address: resolved_seller_payout_address,
103112
seller_output_value_sats: postage_sats,
104113
ask_sats: *amount,
105114
fee_rate_sat_vb: *fee_rate,
@@ -639,6 +648,21 @@ fn assert_offer_expectations(
639648
Ok(())
640649
}
641650

651+
fn resolve_seller_payout_address(
652+
main_payment_address: &str,
653+
provided: Option<&str>,
654+
) -> Result<String, AppError> {
655+
if let Some(provided) = provided {
656+
if !provided.eq_ignore_ascii_case(main_payment_address) {
657+
return Err(AppError::Invalid(format!(
658+
"--seller-payout-address must match wallet main payment address {}",
659+
main_payment_address
660+
)));
661+
}
662+
}
663+
Ok(main_payment_address.to_string())
664+
}
665+
642666
fn assert_offer_network_matches_profile(
643667
offer: &OfferEnvelopeV1,
644668
network: NetworkArg,
@@ -685,7 +709,10 @@ fn map_offer_error<E: ToString>(err: E) -> AppError {
685709

686710
#[cfg(test)]
687711
mod tests {
688-
use super::{abbreviate, assert_offer_expectations, map_offer_error, resolve_offer_source};
712+
use super::{
713+
abbreviate, assert_offer_expectations, map_offer_error, resolve_offer_source,
714+
resolve_seller_payout_address,
715+
};
689716
use crate::error::AppError;
690717
use std::path::Path;
691718
use zinc_core::OfferEnvelopeV1;
@@ -761,4 +788,26 @@ mod tests {
761788
let short = abbreviate(value, 6, 4);
762789
assert_eq!(short, "123456...cdef");
763790
}
791+
792+
#[test]
793+
fn resolve_seller_payout_address_defaults_to_main_payment() {
794+
let resolved =
795+
resolve_seller_payout_address("bcrt1pmainpayment", None).expect("should resolve");
796+
assert_eq!(resolved, "bcrt1pmainpayment");
797+
}
798+
799+
#[test]
800+
fn resolve_seller_payout_address_rejects_non_main_address() {
801+
let err =
802+
resolve_seller_payout_address("bcrt1pmainpayment", Some("bcrt1pdifferentpayment"))
803+
.expect_err("must reject");
804+
assert!(matches!(err, AppError::Invalid(_)));
805+
}
806+
807+
#[test]
808+
fn resolve_seller_payout_address_accepts_case_insensitive_match() {
809+
let resolved = resolve_seller_payout_address("bc1pmainpayment", Some("BC1PMAINPAYMENT"))
810+
.expect("should resolve");
811+
assert_eq!(resolved, "bc1pmainpayment");
812+
}
764813
}

src/commands/scenario.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::cli::{Cli, ScenarioAction, ScenarioArgs};
22
use crate::error::AppError;
3+
use crate::output::CommandOutput;
34
use crate::utils::run_bitcoin_cli;
45
use crate::wallet_service::NetworkArg;
56
use crate::{confirm, load_wallet_session, persist_wallet_session, snapshot_dir};
6-
use crate::output::CommandOutput;
77
use std::fs;
88

99
pub async fn run(cli: &Cli, args: &ScenarioArgs) -> Result<CommandOutput, AppError> {
@@ -121,9 +121,7 @@ pub async fn run(cli: &Cli, args: &ScenarioArgs) -> Result<CommandOutput, AppErr
121121
}
122122
}
123123

124-
CommandOutput::ScenarioReset {
125-
removed,
126-
}
124+
CommandOutput::ScenarioReset { removed }
127125
}
128126
};
129127

src/commands/setup.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ pub async fn run(cli: &Cli, args: &SetupArgs) -> Result<CommandOutput, AppError>
129129

130130
let profile = Profile {
131131
version: 1,
132+
scan_policy_version: crate::config::SCAN_POLICY_VERSION_MAIN_ONLY,
132133
network,
133134
scheme,
134135
account_index: 0,

src/commands/snapshot.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::cli::{Cli, SnapshotAction, SnapshotArgs};
22
use crate::error::AppError;
3-
use crate::{confirm, profile_path, read_profile, snapshot_dir, write_bytes_atomic};
43
use crate::output::CommandOutput;
4+
use crate::{confirm, profile_path, read_profile, snapshot_dir, write_bytes_atomic};
55
use std::fs;
66

77
pub async fn run(cli: &Cli, args: &SnapshotArgs) -> Result<CommandOutput, AppError> {
@@ -22,7 +22,9 @@ pub async fn run(cli: &Cli, args: &SnapshotArgs) -> Result<CommandOutput, AppErr
2222
let bytes = serde_json::to_vec_pretty(&source)
2323
.map_err(|e| AppError::Internal(format!("snapshot serialize failed: {e}")))?;
2424
write_bytes_atomic(&destination, &bytes, "snapshot")?;
25-
Ok(CommandOutput::SnapshotSave { snapshot: destination.display().to_string() })
25+
Ok(CommandOutput::SnapshotSave {
26+
snapshot: destination.display().to_string(),
27+
})
2628
}
2729
SnapshotAction::Restore { name } => {
2830
if !confirm(&format!("Are you sure you want to restore snapshot '{name}'? This will overwrite your current profile."), cli) {
@@ -38,7 +40,9 @@ pub async fn run(cli: &Cli, args: &SnapshotArgs) -> Result<CommandOutput, AppErr
3840
let data = fs::read(&source)
3941
.map_err(|e| AppError::Config(format!("failed to read snapshot: {e}")))?;
4042
write_bytes_atomic(&profile_path, &data, "profile restore")?;
41-
Ok(CommandOutput::SnapshotRestore { restored: source.display().to_string() })
43+
Ok(CommandOutput::SnapshotRestore {
44+
restored: source.display().to_string(),
45+
})
4246
}
4347
SnapshotAction::List => {
4448
let mut names = Vec::new();

0 commit comments

Comments
 (0)