Add unconfirmed balance to home
This commit is contained in:
parent
956b7901c1
commit
36d4968ebb
@ -47,6 +47,7 @@ pub trait State {
|
||||
pub struct Home {
|
||||
wallet: Arc<Wallet>,
|
||||
balance: Amount,
|
||||
unconfirmed_balance: Amount,
|
||||
recovery_warning: Option<(Amount, usize)>,
|
||||
recovery_alert: Option<(Amount, usize)>,
|
||||
pending_events: Vec<HistoryTransaction>,
|
||||
@ -57,21 +58,22 @@ pub struct Home {
|
||||
|
||||
impl Home {
|
||||
pub fn new(wallet: Arc<Wallet>, coins: &[Coin]) -> Self {
|
||||
let (balance, unconfirmed_balance) = coins.iter().fold(
|
||||
(Amount::from_sat(0), Amount::from_sat(0)),
|
||||
|(balance, unconfirmed_balance), coin| {
|
||||
if coin.spend_info.is_some() {
|
||||
(balance, unconfirmed_balance)
|
||||
} else if coin.block_height.is_some() {
|
||||
(balance + coin.amount, unconfirmed_balance)
|
||||
} else {
|
||||
(balance, unconfirmed_balance + coin.amount)
|
||||
}
|
||||
},
|
||||
);
|
||||
Self {
|
||||
wallet,
|
||||
balance: Amount::from_sat(
|
||||
coins
|
||||
.iter()
|
||||
.map(|coin| {
|
||||
// If the coin is not spent and is its transaction is confirmed
|
||||
if coin.spend_info.is_none() && coin.block_height.is_some() {
|
||||
coin.amount.to_sat()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
})
|
||||
.sum(),
|
||||
),
|
||||
balance,
|
||||
unconfirmed_balance,
|
||||
recovery_alert: None,
|
||||
recovery_warning: None,
|
||||
selected_event: None,
|
||||
@ -103,6 +105,7 @@ impl State for Home {
|
||||
None,
|
||||
view::home::home_view(
|
||||
&self.balance,
|
||||
&self.unconfirmed_balance,
|
||||
self.recovery_warning.as_ref(),
|
||||
self.recovery_alert.as_ref(),
|
||||
&self.pending_events,
|
||||
@ -123,19 +126,25 @@ impl State for Home {
|
||||
Ok(coins) => {
|
||||
self.warning = None;
|
||||
self.balance = Amount::from_sat(0);
|
||||
self.unconfirmed_balance = Amount::from_sat(0);
|
||||
let mut recovery_warning = (Amount::from_sat(0), 0);
|
||||
let mut recovery_alert = (Amount::from_sat(0), 0);
|
||||
for coin in coins {
|
||||
if coin.spend_info.is_none() && coin.block_height.is_some() {
|
||||
self.balance += coin.amount;
|
||||
let timelock = self.wallet.main_descriptor.first_timelock_value();
|
||||
let seq = remaining_sequence(&coin, cache.blockheight as u32, timelock);
|
||||
if seq == 0 {
|
||||
recovery_alert.0 += coin.amount;
|
||||
recovery_alert.1 += 1;
|
||||
} else if seq < timelock as u32 * 10 / 100 {
|
||||
recovery_warning.0 += coin.amount;
|
||||
recovery_warning.1 += 1;
|
||||
if coin.spend_info.is_none() {
|
||||
if coin.block_height.is_some() {
|
||||
self.balance += coin.amount;
|
||||
let timelock = self.wallet.main_descriptor.first_timelock_value();
|
||||
let seq =
|
||||
remaining_sequence(&coin, cache.blockheight as u32, timelock);
|
||||
if seq == 0 {
|
||||
recovery_alert.0 += coin.amount;
|
||||
recovery_alert.1 += 1;
|
||||
} else if seq < timelock as u32 * 10 / 100 {
|
||||
recovery_warning.0 += coin.amount;
|
||||
recovery_warning.1 += 1;
|
||||
}
|
||||
} else {
|
||||
self.unconfirmed_balance += coin.amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,15 +62,12 @@ fn coin_list_view(
|
||||
.push(badge::coin())
|
||||
.push(if coin.spend_info.is_some() {
|
||||
badge::spent()
|
||||
} else if coin.block_height.is_none() {
|
||||
badge::unconfirmed()
|
||||
} else {
|
||||
let seq = remaining_sequence(coin, blockheight, timelock);
|
||||
coin_sequence_label(seq, timelock as u32)
|
||||
})
|
||||
.push_maybe(if coin.block_height.is_none() {
|
||||
Some(badge::unconfirmed())
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.width(Length::Fill),
|
||||
@ -208,31 +205,28 @@ pub fn coin_sequence_label<'a, T: 'a>(seq: u32, timelock: u32) -> Container<'a,
|
||||
/// returns y,m,d,h,m
|
||||
pub fn expire_message(sequence: u32) -> String {
|
||||
let mut n_minutes = sequence * 10;
|
||||
let n_years = n_minutes / 525960;
|
||||
n_minutes -= n_years * 525960;
|
||||
let n_months = n_minutes / 43830;
|
||||
n_minutes -= n_months * 43830;
|
||||
let n_days = n_minutes / 1440;
|
||||
n_minutes -= n_days * 1440;
|
||||
let n_hours = n_minutes / 60;
|
||||
n_minutes -= n_hours * 60;
|
||||
if n_minutes <= 1440 {
|
||||
"Expires today".to_string()
|
||||
} else if n_minutes <= 2 * 1440 {
|
||||
"Expires in ≈ 2 days".to_string()
|
||||
} else {
|
||||
let n_years = n_minutes / 525960;
|
||||
n_minutes -= n_years * 525960;
|
||||
let n_months = n_minutes / 43830;
|
||||
n_minutes -= n_months * 43830;
|
||||
let n_days = n_minutes / 1440;
|
||||
|
||||
let units: Vec<String> = [
|
||||
(n_years, "year"),
|
||||
(n_months, "month"),
|
||||
(n_days, "day"),
|
||||
(n_hours, "hour"),
|
||||
(n_minutes, "minute"),
|
||||
]
|
||||
.iter()
|
||||
.filter_map(|(n, u)| {
|
||||
if *n != 0 {
|
||||
Some(format!("{} {}{}", n, u, if *n > 1 { "s" } else { "" }))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let units: Vec<String> = [(n_years, "year"), (n_months, "month"), (n_days, "day")]
|
||||
.iter()
|
||||
.filter_map(|(n, u)| {
|
||||
if *n != 0 {
|
||||
Some(format!("{} {}{}", n, u, if *n > 1 { "s" } else { "" }))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
format!("Expires in {}", units.join(","))
|
||||
format!("Expires in {}", units.join(","))
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ pub const HISTORY_EVENT_PAGE_SIZE: u64 = 20;
|
||||
|
||||
pub fn home_view<'a>(
|
||||
balance: &'a bitcoin::Amount,
|
||||
unconfirmed_balance: &'a bitcoin::Amount,
|
||||
recovery_warning: Option<&(bitcoin::Amount, usize)>,
|
||||
recovery_alert: Option<&(bitcoin::Amount, usize)>,
|
||||
pending_events: &[HistoryTransaction],
|
||||
@ -24,7 +25,21 @@ pub fn home_view<'a>(
|
||||
) -> Element<'a, Message> {
|
||||
Column::new()
|
||||
.push(h3("Balance"))
|
||||
.push(amount_with_size(balance, H1_SIZE))
|
||||
.push(
|
||||
Column::new()
|
||||
.push(amount_with_size(balance, H1_SIZE))
|
||||
.push_maybe(if unconfirmed_balance.to_sat() != 0 {
|
||||
Some(
|
||||
Row::new()
|
||||
.spacing(10)
|
||||
.push(text("+").size(H3_SIZE).style(color::GREY_3))
|
||||
.push(unconfirmed_amount_with_size(unconfirmed_balance, H3_SIZE))
|
||||
.push(text("unconfirmed").size(H3_SIZE).style(color::GREY_3)),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}),
|
||||
)
|
||||
.push_maybe(recovery_warning.map(|(a, c)| {
|
||||
Row::new()
|
||||
.spacing(15)
|
||||
|
||||
@ -209,15 +209,12 @@ fn coin_list_view<'a>(
|
||||
.push(badge::coin())
|
||||
.push(if coin.spend_info.is_some() {
|
||||
badge::spent()
|
||||
} else if coin.block_height.is_none() {
|
||||
badge::unconfirmed()
|
||||
} else {
|
||||
let seq = remaining_sequence(coin, blockheight, timelock);
|
||||
coins::coin_sequence_label(seq, timelock as u32)
|
||||
})
|
||||
.push_maybe(if coin.block_height.is_none() {
|
||||
Some(badge::unconfirmed())
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.spacing(10)
|
||||
.align_items(Alignment::Center)
|
||||
.width(Length::Fill),
|
||||
|
||||
@ -12,9 +12,9 @@ pub fn amount_with_size<'a, T: 'a>(a: &Amount, size: u16) -> Row<'a, T> {
|
||||
assert!(sats.len() >= 9);
|
||||
let row = Row::new()
|
||||
.spacing(spacing)
|
||||
.push(split_digits(sats[0..sats.len() - 6].to_string(), size).into())
|
||||
.push(split_digits(sats[0..sats.len() - 6].to_string(), size, true).into())
|
||||
.push(if a.to_sat() < 1_000_000 {
|
||||
split_digits(sats[sats.len() - 6..sats.len() - 3].to_string(), size).into()
|
||||
split_digits(sats[sats.len() - 6..sats.len() - 3].to_string(), size, true).into()
|
||||
} else {
|
||||
Row::new()
|
||||
.push(
|
||||
@ -25,7 +25,7 @@ pub fn amount_with_size<'a, T: 'a>(a: &Amount, size: u16) -> Row<'a, T> {
|
||||
.into()
|
||||
})
|
||||
.push(if a.to_sat() < 1000 {
|
||||
split_digits(sats[sats.len() - 3..sats.len()].to_string(), size).into()
|
||||
split_digits(sats[sats.len() - 3..sats.len()].to_string(), size, true).into()
|
||||
} else {
|
||||
Row::new()
|
||||
.push(
|
||||
@ -44,7 +44,42 @@ pub fn amount_with_size<'a, T: 'a>(a: &Amount, size: u16) -> Row<'a, T> {
|
||||
.align_items(iced::Alignment::Center)
|
||||
}
|
||||
|
||||
fn split_digits<'a, T: 'a>(mut s: String, size: u16) -> impl Into<Element<'a, T>> {
|
||||
pub fn unconfirmed_amount_with_size<'a, T: 'a>(a: &Amount, size: u16) -> Row<'a, T> {
|
||||
let spacing = if size > P1_SIZE { 10 } else { 5 };
|
||||
let sats = format!("{:.8}", a.to_btc());
|
||||
assert!(sats.len() >= 9);
|
||||
let row = Row::new()
|
||||
.spacing(spacing)
|
||||
.push(split_digits(sats[0..sats.len() - 6].to_string(), size, false).into())
|
||||
.push(if a.to_sat() < 1_000_000 {
|
||||
split_digits(
|
||||
sats[sats.len() - 6..sats.len() - 3].to_string(),
|
||||
size,
|
||||
false,
|
||||
)
|
||||
.into()
|
||||
} else {
|
||||
Row::new()
|
||||
.push(text(sats[sats.len() - 6..sats.len() - 3].to_string()).size(size))
|
||||
.into()
|
||||
})
|
||||
.push(if a.to_sat() < 1000 {
|
||||
split_digits(sats[sats.len() - 3..sats.len()].to_string(), size, false).into()
|
||||
} else {
|
||||
Row::new()
|
||||
.push(text(sats[sats.len() - 3..sats.len()].to_string()).size(size))
|
||||
.into()
|
||||
});
|
||||
|
||||
Row::with_children(vec![
|
||||
row.into(),
|
||||
text("BTC").size(size).style(color::GREY_3).into(),
|
||||
])
|
||||
.spacing(spacing)
|
||||
.align_items(iced::Alignment::Center)
|
||||
}
|
||||
|
||||
fn split_digits<'a, T: 'a>(mut s: String, size: u16, bold: bool) -> impl Into<Element<'a, T>> {
|
||||
let prefixes = vec!["0.00", "0.0", "0.", "000", "00", "0"];
|
||||
for prefix in prefixes {
|
||||
if s.starts_with(prefix) {
|
||||
@ -53,10 +88,16 @@ fn split_digits<'a, T: 'a>(mut s: String, size: u16) -> impl Into<Element<'a, T>
|
||||
.push(text(s).size(size).style(color::GREY_3))
|
||||
.push_maybe(if right.is_empty() {
|
||||
None
|
||||
} else {
|
||||
} else if bold {
|
||||
Some(text(right).bold().size(size))
|
||||
} else {
|
||||
Some(text(right).size(size))
|
||||
});
|
||||
}
|
||||
}
|
||||
Row::new().push(text(s).bold().size(size))
|
||||
if bold {
|
||||
Row::new().push(text(s).bold().size(size))
|
||||
} else {
|
||||
Row::new().push(text(s).size(size))
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user