diff --git a/liana-gui/src/app/state/mod.rs b/liana-gui/src/app/state/mod.rs index 19a1d59d..e76c274b 100644 --- a/liana-gui/src/app/state/mod.rs +++ b/liana-gui/src/app/state/mod.rs @@ -29,7 +29,7 @@ use super::{ pub const HISTORY_EVENT_PAGE_SIZE: u64 = 20; -use crate::daemon::model::LabelsLoader; +use crate::daemon::model::{coin_is_owned, LabelsLoader}; use crate::daemon::{ model::{remaining_sequence, Coin, HistoryTransaction, Payment}, Daemon, @@ -94,7 +94,7 @@ fn coins_summary( for coin in coins { if coin.spend_info.is_none() { // Include unconfirmed coins from self in confirmed balance. - if coin.block_height.is_some() || coin.is_from_self { + if coin_is_owned(coin) { balance += coin.amount; // Only consider confirmed coins for remaining seq // (they would not be considered as expiring so we can also skip that part) diff --git a/liana-gui/src/app/state/spend/step.rs b/liana-gui/src/app/state/spend/step.rs index e1079c4d..504966e4 100644 --- a/liana-gui/src/app/state/spend/step.rs +++ b/liana-gui/src/app/state/spend/step.rs @@ -21,7 +21,7 @@ use liana_ui::{component::form, widget::Element}; use crate::{ app::{cache::Cache, error::Error, message::Message, state::psbt, view, wallet::Wallet}, daemon::{ - model::{remaining_sequence, Coin, CreateSpendResult, SpendTx}, + model::{coin_is_owned, remaining_sequence, Coin, CreateSpendResult, SpendTx}, Daemon, }, }; @@ -283,8 +283,11 @@ impl DefineSpend { } outpoints } else if self.send_max_to_recipient.is_some() { - // If user has not selected coins, send the max available from all coins. - self.coins.iter().map(|(c, _)| c.outpoint).collect() + // If user has not selected coins, send the max available from all owned coins. + self.coins + .iter() + .filter_map(|(c, _)| coin_is_owned(c).then_some(c.outpoint)) + .collect() } else { Vec::new() // pass empty list for auto-selection }; @@ -354,13 +357,15 @@ impl DefineSpend { ); } } - // For coin selection error (insufficient funds), do not make any changes to - // selected coins on screen and just show user how much is left to select. - // User can then either: - // - modify recipient amounts and/or feerate and let coin selection run again, or - // - select coins manually. Ok(CreateSpendResult::InsufficientFunds { missing }) => { self.amount_left_to_select = Some(Amount::from_sat(missing)); + if !self.is_user_coin_selection { + // The missing amount is based on all candidates for coin selection + // being used, which are all owned coins. + for (coin, selected) in &mut self.coins { + *selected = coin_is_owned(coin); + } + } if let Some((i, recipient)) = recipient_with_max { let amount = Amount::from_sat(if destinations.is_empty() { // If there are no other recipients, then the missing value will diff --git a/liana-gui/src/daemon/model.rs b/liana-gui/src/daemon/model.rs index c4657ba9..9bbb0b94 100644 --- a/liana-gui/src/daemon/model.rs +++ b/liana-gui/src/daemon/model.rs @@ -29,6 +29,13 @@ pub fn remaining_sequence(coin: &Coin, blockheight: u32, timelock: u16) -> u32 { } } +/// Whether the coin is owned by this wallet. +/// This comprises all confirmed coins together with those +/// unconfirmed coins from self. +pub fn coin_is_owned(coin: &Coin) -> bool { + coin.block_height.is_some() || coin.is_from_self +} + #[derive(Debug, Clone)] pub struct SpendTx { pub network: Network,