diff --git a/gui/src/app/mod.rs b/gui/src/app/mod.rs index 37114dd7..9403f27a 100644 --- a/gui/src/app/mod.rs +++ b/gui/src/app/mod.rs @@ -75,6 +75,7 @@ impl App { self.config.clone(), &self.cache.coins, self.daemon.config().main_descriptor.timelock_value(), + self.cache.blockheight as u32, ) .into(), }; diff --git a/gui/src/app/state/spend/mod.rs b/gui/src/app/state/spend/mod.rs index 67afbab9..0bef2239 100644 --- a/gui/src/app/state/spend/mod.rs +++ b/gui/src/app/state/spend/mod.rs @@ -104,13 +104,17 @@ pub struct CreateSpendPanel { } impl CreateSpendPanel { - pub fn new(config: Config, coins: &[Coin], timelock: u32) -> Self { + pub fn new(config: Config, coins: &[Coin], timelock: u32, blockheight: u32) -> Self { Self { draft: step::TransactionDraft::default(), current: 0, steps: vec![ Box::new(step::ChooseRecipients::default()), - Box::new(step::ChooseCoins::new(coins.to_vec(), timelock)), + Box::new(step::ChooseCoins::new( + coins.to_vec(), + timelock, + blockheight, + )), Box::new(step::ChooseFeerate::default()), Box::new(step::SaveSpend::new(config)), ], diff --git a/gui/src/app/state/spend/step.rs b/gui/src/app/state/spend/step.rs index 1342fd0b..04d869c5 100644 --- a/gui/src/app/state/spend/step.rs +++ b/gui/src/app/state/spend/step.rs @@ -12,7 +12,7 @@ use crate::{ cache::Cache, config::Config, error::Error, message::Message, state::spend::detail, view, }, daemon::{ - model::{Coin, SpendTx}, + model::{remaining_sequence, Coin, SpendTx}, Daemon, }, ui::component::form, @@ -258,19 +258,31 @@ pub struct ChooseCoins { } impl ChooseCoins { - pub fn new(coins: Vec, timelock: u32) -> Self { + pub fn new(coins: Vec, timelock: u32, blockheight: u32) -> Self { + let mut coins: Vec<(Coin, bool)> = coins + .into_iter() + .filter_map(|c| { + if c.spend_info.is_none() { + Some((c, false)) + } else { + None + } + }) + .collect(); + coins.sort_by(|(a, _), (b, _)| { + if remaining_sequence(a, blockheight, timelock) + == remaining_sequence(b, blockheight, timelock) + { + // bigger amount first + b.amount.cmp(&a.amount) + } else { + // smallest blockheight (remaining_sequence) first + a.block_height.cmp(&b.block_height) + } + }); Self { timelock, - coins: coins - .into_iter() - .filter_map(|c| { - if c.spend_info.is_none() { - Some((c, false)) - } else { - None - } - }) - .collect(), + coins, is_valid: false, total_needed: None, } diff --git a/gui/src/app/view/spend/step.rs b/gui/src/app/view/spend/step.rs index c3743117..67cbe38f 100644 --- a/gui/src/app/view/spend/step.rs +++ b/gui/src/app/view/spend/step.rs @@ -40,6 +40,7 @@ pub fn choose_recipients_view( button::transparent(Some(icon::plus_icon()), "Add recipient") .on_press(Message::CreateSpend(CreateSpendMessage::AddRecipient)), ) + .padding(10) .max_width(1000) .spacing(10), ) @@ -152,6 +153,7 @@ pub fn choose_coins_view<'a>( .push(text("Choose coins").bold().size(50)) .push( Column::new() + .padding(10) .spacing(10) .push(coins.iter().enumerate().fold( Column::new().spacing(10), diff --git a/gui/src/daemon/model.rs b/gui/src/daemon/model.rs index e33c252a..f4ef62fc 100644 --- a/gui/src/daemon/model.rs +++ b/gui/src/daemon/model.rs @@ -8,6 +8,18 @@ pub use liana::{ pub type Coin = ListCoinsEntry; +pub fn remaining_sequence(coin: &Coin, blockheight: u32, timelock: u32) -> u32 { + if let Some(coin_blockheight) = coin.block_height { + if blockheight > coin_blockheight as u32 + timelock { + 0 + } else { + coin_blockheight as u32 + timelock - blockheight + } + } else { + timelock + } +} + #[derive(Debug, Clone)] pub struct SpendTx { pub coins: Vec,