Skip to content

Commit

Permalink
Use common code for account retrieval & only require account selectio…
Browse files Browse the repository at this point in the history
…n when there is more than one.
  • Loading branch information
nuttycom committed Dec 14, 2024
1 parent 39b668a commit da444b1
Show file tree
Hide file tree
Showing 10 changed files with 115 additions and 80 deletions.
33 changes: 33 additions & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
use anyhow::anyhow;
use uuid::Uuid;
use zcash_client_backend::data_api::WalletRead;
use zcash_client_sqlite::AccountUuid;

pub(crate) mod balance;
pub(crate) mod enhance;
pub(crate) mod import_ufvk;
Expand All @@ -17,3 +22,31 @@ pub(crate) mod upgrade;

#[cfg(feature = "pczt-qr")]
pub(crate) mod keystone;

pub(crate) fn select_account<DbT: WalletRead<AccountId = AccountUuid>>(
db_data: &DbT,
account_uuid: Option<Uuid>,
) -> Result<DbT::Account, anyhow::Error>
where
DbT::Error: std::error::Error + Sync + Send + 'static,
{
let account_id = match account_uuid {
Some(uuid) => Ok(AccountUuid::from_uuid(uuid)),
None => {
let account_ids = db_data.get_account_ids()?;
if account_ids.len() > 1 {
Err(anyhow!(
"More than one account is available; please specify the account UUID."
))
} else {
account_ids
.first()
.map_or(Err(anyhow!("Wallet contains no accounts.")), |v| Ok(*v))
}
}
}?;

db_data
.get_account(account_id)?
.ok_or(anyhow!("Account missing: {:?}", account_id))
}
23 changes: 12 additions & 11 deletions src/commands/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,25 @@ use iso_currency::Currency;
use rust_decimal::{prelude::FromPrimitive, Decimal};
use tracing::{info, warn};
use uuid::Uuid;
use zcash_client_backend::{data_api::WalletRead, tor};
use zcash_client_sqlite::{AccountUuid, WalletDb};
use zcash_client_backend::{
data_api::{Account as _, WalletRead},
tor,
};
use zcash_client_sqlite::WalletDb;
use zcash_protocol::value::{Zatoshis, COIN};

use crate::{
config::get_wallet_network, data::get_db_paths, error, remote::tor_client, ui::format_zec,
MIN_CONFIRMATIONS,
};

use super::select_account;

// Options accepted for the `balance` command
#[derive(Debug, Options)]
pub(crate) struct Command {
#[options(
free,
required,
help = "the UUID of the account for which to get a balance"
)]
account_id: Uuid,
#[options(free, help = "the UUID of the account for which to get a balance")]
account_id: Option<Uuid>,

#[options(help = "Convert ZEC values into the given currency")]
convert: Option<Currency>,
Expand All @@ -34,10 +35,10 @@ impl Command {

let (_, db_data) = get_db_paths(wallet_dir.as_ref());
let db_data = WalletDb::for_path(db_data, params)?;
let account_id = AccountUuid::from_uuid(self.account_id);
let account = select_account(&db_data, self.account_id)?;

let address = db_data
.get_current_address(account_id)?
.get_current_address(account.id())?
.ok_or(error::Error::InvalidRecipient)?;

let printer = if let Some(currency) = self.convert {
Expand All @@ -50,7 +51,7 @@ impl Command {
if let Some(wallet_summary) = db_data.get_wallet_summary(MIN_CONFIRMATIONS.into())? {
let balance = wallet_summary
.account_balances()
.get(&account_id)
.get(&account.id())
.ok_or_else(|| anyhow!("Missing account 0"))?;

println!("{:#?}", wallet_summary);
Expand Down
15 changes: 7 additions & 8 deletions src/commands/keystone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ use minicbor::data::{Int, Tag};
use qrcode::{render::unicode, QrCode};
use tokio::io::{stdout, AsyncWriteExt};
use uuid::Uuid;
use zcash_client_backend::data_api::{Account, WalletRead};
use zcash_client_sqlite::{AccountUuid, WalletDb};
use zcash_client_backend::data_api::Account;
use zcash_client_sqlite::WalletDb;

use crate::{config::WalletConfig, data::get_db_paths, ShutdownListener};

use super::select_account;

const ZCASH_ACCOUNTS: &str = "zcash-accounts";

#[derive(Debug, Options)]
Expand All @@ -22,8 +24,8 @@ pub(crate) enum Command {
// Options accepted for the `keystone enroll` command
#[derive(Debug, Options)]
pub(crate) struct Enroll {
#[options(free, required, help = "the UUID of the account to enroll")]
account_id: Uuid,
#[options(free, help = "the UUID of the account to enroll")]
account_id: Option<Uuid>,

#[options(
help = "the duration in milliseconds to wait between QR codes (default is 500)",
Expand All @@ -43,10 +45,7 @@ impl Enroll {

let (_, db_data) = get_db_paths(wallet_dir.as_ref());
let db_data = WalletDb::for_path(db_data, params)?;
let account_id = AccountUuid::from_uuid(self.account_id);
let account = db_data
.get_account(account_id)?
.ok_or(anyhow!("Account missing: {:?}", account_id))?;
let account = select_account(&db_data, self.account_id)?;

let key_derivation = account
.source()
Expand Down
17 changes: 7 additions & 10 deletions src/commands/list_addresses.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
use anyhow::anyhow;
use gumdrop::Options;

use uuid::Uuid;
use zcash_client_backend::data_api::{Account, WalletRead};
use zcash_client_sqlite::{AccountUuid, WalletDb};
use zcash_client_backend::data_api::Account;
use zcash_client_sqlite::WalletDb;
use zcash_keys::keys::UnifiedAddressRequest;

use crate::{config::get_wallet_network, data::get_db_paths};
use crate::{commands::select_account, config::get_wallet_network, data::get_db_paths};

// Options accepted for the `list-accounts` command
#[derive(Debug, Options)]
pub(crate) struct Command {
#[options(free, required, help = "the UUID of the account to list addresses for")]
account_id: Uuid,
#[options(free, help = "the UUID of the account to list addresses for")]
account_id: Option<Uuid>,
}

impl Command {
Expand All @@ -21,11 +20,9 @@ impl Command {
let (_, db_data) = get_db_paths(wallet_dir.as_ref());
let db_data = WalletDb::for_path(db_data, params)?;

let account = db_data
.get_account(AccountUuid::from_uuid(self.account_id))?
.ok_or_else(|| anyhow!("No account exists for account id {}", self.account_id))?;
let account = select_account(&db_data, self.account_id)?;

println!("Account {}", self.account_id);
println!("Account {:?}", account.id());
let (ua, _) = account
.uivk()
.default_address(UnifiedAddressRequest::all())?;
Expand Down
18 changes: 8 additions & 10 deletions src/commands/list_unspent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,21 @@ use gumdrop::Options;

use uuid::Uuid;
use zcash_client_backend::{
data_api::{InputSource, WalletRead},
data_api::{Account as _, InputSource, WalletRead},
ShieldedProtocol,
};
use zcash_client_sqlite::{AccountUuid, WalletDb};
use zcash_client_sqlite::WalletDb;
use zcash_protocol::value::{Zatoshis, MAX_MONEY};

use crate::{config::get_wallet_network, data::get_db_paths, error, ui::format_zec};

use super::select_account;

// Options accepted for the `list-unspent` command
#[derive(Debug, Options)]
pub(crate) struct Command {
#[options(
free,
required,
help = "the UUID of the account for which to list unspent funds"
)]
account_id: Uuid,
#[options(free, help = "the UUID of the account for which to list unspent funds")]
account_id: Option<Uuid>,
}

impl Command {
Expand All @@ -28,7 +26,7 @@ impl Command {

let (_, db_data) = get_db_paths(wallet_dir);
let db_data = WalletDb::for_path(db_data, params)?;
let account_id = AccountUuid::from_uuid(self.account_id);
let account = select_account(&db_data, self.account_id)?;

// Use the height of the maximum scanned block as the anchor height, to emulate a
// zero-conf transaction in order to select every note in the wallet.
Expand All @@ -39,7 +37,7 @@ impl Command {
.block_height();

let notes = db_data.select_spendable_notes(
account_id,
account.id(),
Zatoshis::const_from_u64(MAX_MONEY),
&[ShieldedProtocol::Sapling, ShieldedProtocol::Orchard],
anchor_height,
Expand Down
23 changes: 14 additions & 9 deletions src/commands/pczt/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,32 @@ use tokio::io::{stdout, AsyncWriteExt};
use uuid::Uuid;
use zcash_address::ZcashAddress;
use zcash_client_backend::{
data_api::wallet::{
create_pczt_from_proposal, input_selection::GreedyInputSelector, propose_transfer,
data_api::{
wallet::{
create_pczt_from_proposal, input_selection::GreedyInputSelector, propose_transfer,
},
Account as _,
},
fees::{standard::MultiOutputChangeStrategy, DustOutputPolicy, SplitPolicy, StandardFeeRule},
wallet::OvkPolicy,
ShieldedProtocol,
};
use zcash_client_sqlite::{AccountUuid, WalletDb};
use zcash_client_sqlite::WalletDb;
use zcash_protocol::{
memo::{Memo, MemoBytes},
value::Zatoshis,
};
use zip321::{Payment, TransactionRequest};

use crate::{config::WalletConfig, data::get_db_paths, error, MIN_CONFIRMATIONS};
use crate::{
commands::select_account, config::WalletConfig, data::get_db_paths, error, MIN_CONFIRMATIONS,
};

// Options accepted for the `pczt create` command
#[derive(Debug, Options)]
pub(crate) struct Command {
#[options(free, required, help = "the UUID of the account to send funds from")]
account_id: Uuid,
#[options(free, help = "the UUID of the account to send funds from")]
account_id: Option<Uuid>,

#[options(
required,
Expand Down Expand Up @@ -62,7 +67,7 @@ impl Command {

let (_, db_data) = get_db_paths(wallet_dir.as_ref());
let mut db_data = WalletDb::for_path(db_data, params)?;
let account_id = AccountUuid::from_uuid(self.account_id);
let account = select_account(&db_data, self.account_id)?;

// Create the PCZT.
let change_strategy = MultiOutputChangeStrategy::new(
Expand Down Expand Up @@ -95,7 +100,7 @@ impl Command {
let proposal = propose_transfer(
&mut db_data,
&params,
account_id,
account.id(),
&input_selector,
&change_strategy,
request,
Expand All @@ -106,7 +111,7 @@ impl Command {
let pczt = create_pczt_from_proposal(
&mut db_data,
&params,
account_id,
account.id(),
OvkPolicy::Sender,
&proposal,
)
Expand Down
18 changes: 9 additions & 9 deletions src/commands/pczt/shield.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ use zcash_client_backend::{
wallet::{
create_pczt_from_proposal, input_selection::GreedyInputSelector, propose_shielding,
},
WalletRead,
Account as _, WalletRead,
},
fees::{standard::MultiOutputChangeStrategy, DustOutputPolicy, SplitPolicy, StandardFeeRule},
wallet::OvkPolicy,
ShieldedProtocol,
};
use zcash_client_sqlite::{AccountUuid, WalletDb};
use zcash_client_sqlite::WalletDb;
use zcash_protocol::value::Zatoshis;

use crate::{config::WalletConfig, data::get_db_paths, error};
use crate::{commands::select_account, config::WalletConfig, data::get_db_paths, error};

// Options accepted for the `pczt shield` command
#[derive(Debug, Options)]
pub(crate) struct Command {
#[options(free, required, help = "the UUID of the account to shield funds in")]
account_id: Uuid,
#[options(free, help = "the UUID of the account to shield funds in")]
account_id: Option<Uuid>,

#[options(
help = "note management: the number of notes to maintain in the wallet",
Expand All @@ -47,7 +47,7 @@ impl Command {

let (_, db_data) = get_db_paths(wallet_dir.as_ref());
let mut db_data = WalletDb::for_path(db_data, params)?;
let account_id = AccountUuid::from_uuid(self.account_id);
let account = select_account(&db_data, self.account_id)?;

// Create the PCZT.
let change_strategy = MultiOutputChangeStrategy::new(
Expand All @@ -69,7 +69,7 @@ impl Command {
// If we haven't scanned anything, there's nothing to do.
None => return Ok(()),
};
let transparent_balances = db_data.get_transparent_balances(account_id, max_height)?;
let transparent_balances = db_data.get_transparent_balances(account.id(), max_height)?;
let from_addrs = transparent_balances.into_keys().collect::<Vec<_>>();

let proposal = propose_shielding(
Expand All @@ -79,15 +79,15 @@ impl Command {
&change_strategy,
Zatoshis::ZERO,
&from_addrs,
account_id,
account.id(),
0,
)
.map_err(error::Error::Shield)?;

let pczt = create_pczt_from_proposal(
&mut db_data,
&params,
account_id,
account.id(),
OvkPolicy::Sender,
&proposal,
)
Expand Down
Loading

0 comments on commit da444b1

Please sign in to comment.