Merge #314: gui: change path signature details
56d3522f8c74ff774cb3ecdbf76b48dd216497f9 gui: change path signature details (edouard) Pull request description:    ACKs for top commit: edouardparis: Self-ACK 56d3522f8c74ff774cb3ecdbf76b48dd216497f9 Tree-SHA512: 72c0ee502f8f8475b38cf3ee6619e02f9a0920373cc1542cdd37f7d79f83ac489cef444c1f4f79df45ffca4e8b3a1857606994392238ec77a8457d0af117ea63
This commit is contained in:
commit
66e37a2cdf
@ -287,26 +287,54 @@ pub fn signatures<'a>(
|
|||||||
keys_aliases: &'a HashMap<Fingerprint, String>,
|
keys_aliases: &'a HashMap<Fingerprint, String>,
|
||||||
) -> Element<'a, Message> {
|
) -> Element<'a, Message> {
|
||||||
Column::new()
|
Column::new()
|
||||||
.push(Collapse::new(
|
.push(
|
||||||
|
if let Some(sigs) = tx.path_ready() {
|
||||||
|
Container::new(
|
||||||
|
Scrollable::new(
|
||||||
|
Row::new()
|
||||||
|
.spacing(5)
|
||||||
|
.align_items(Alignment::Center)
|
||||||
|
.push(icon::circle_check_icon().style(color::SUCCESS))
|
||||||
|
.push(text("Ready").bold().style(color::SUCCESS))
|
||||||
|
.push(text(", signed by"))
|
||||||
|
.push(
|
||||||
|
sigs.signed_pubkeys
|
||||||
|
.keys()
|
||||||
|
.fold(Row::new().spacing(5), |row, value| {
|
||||||
|
row.push(if let Some(alias) = keys_aliases.get(value) {
|
||||||
|
Container::new(
|
||||||
|
tooltip::Tooltip::new(
|
||||||
|
Container::new(text(alias))
|
||||||
|
.padding(3)
|
||||||
|
.style(badge::PillStyle::Simple),
|
||||||
|
value.to_string(),
|
||||||
|
tooltip::Position::Bottom,
|
||||||
|
)
|
||||||
|
.style(card::SimpleCardStyle),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Container::new(text(value.to_string()))
|
||||||
|
.padding(3)
|
||||||
|
.style(badge::PillStyle::Simple)
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
).horizontal_scroll(scrollable::Properties::new().width(2).scroller_width(2))
|
||||||
|
).padding(15)
|
||||||
|
} else{
|
||||||
|
Container::new(
|
||||||
|
Collapse::new(
|
||||||
move || {
|
move || {
|
||||||
Button::new(
|
Button::new(
|
||||||
Row::new()
|
Row::new()
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.push(if tx.is_ready() {
|
.push(Row::new()
|
||||||
Row::new()
|
|
||||||
.spacing(5)
|
|
||||||
.align_items(Alignment::Center)
|
|
||||||
.push(icon::circle_check_icon().style(color::SUCCESS))
|
|
||||||
.push(text("Ready").bold().style(color::SUCCESS))
|
|
||||||
.width(Length::Fill)
|
|
||||||
} else {
|
|
||||||
Row::new()
|
|
||||||
.spacing(5)
|
.spacing(5)
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.push(icon::circle_cross_icon())
|
.push(icon::circle_cross_icon())
|
||||||
.push(text("Not ready").bold())
|
.push(text("Not ready").bold())
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
})
|
)
|
||||||
.push(icon::collapse_icon()),
|
.push(icon::collapse_icon()),
|
||||||
)
|
)
|
||||||
.padding(15)
|
.padding(15)
|
||||||
@ -317,21 +345,14 @@ pub fn signatures<'a>(
|
|||||||
Button::new(
|
Button::new(
|
||||||
Row::new()
|
Row::new()
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.push(if tx.is_ready() {
|
.push(
|
||||||
Row::new()
|
|
||||||
.spacing(5)
|
|
||||||
.align_items(Alignment::Center)
|
|
||||||
.push(icon::circle_check_icon().style(color::SUCCESS))
|
|
||||||
.push(text("Ready").bold().style(color::SUCCESS))
|
|
||||||
.width(Length::Fill)
|
|
||||||
} else {
|
|
||||||
Row::new()
|
Row::new()
|
||||||
.spacing(5)
|
.spacing(5)
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.push(icon::circle_cross_icon())
|
.push(icon::circle_cross_icon())
|
||||||
.push(text("Not ready").bold())
|
.push(text("Not ready").bold())
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
})
|
)
|
||||||
.push(icon::collapsed_icon()),
|
.push(icon::collapsed_icon()),
|
||||||
)
|
)
|
||||||
.padding(15)
|
.padding(15)
|
||||||
@ -344,6 +365,11 @@ pub fn signatures<'a>(
|
|||||||
Column::new()
|
Column::new()
|
||||||
.padding(15)
|
.padding(15)
|
||||||
.spacing(10)
|
.spacing(10)
|
||||||
|
.push(text(if tx.sigs.recovery_path().is_some() {
|
||||||
|
"2 spending paths available. Finalizing this transaction requires either:"
|
||||||
|
} else {
|
||||||
|
"1 spending path available. Finalizing this transaction requires:"
|
||||||
|
}))
|
||||||
.push(path_view(
|
.push(path_view(
|
||||||
desc_info.primary_path(),
|
desc_info.primary_path(),
|
||||||
tx.sigs.primary_path(),
|
tx.sigs.primary_path(),
|
||||||
@ -356,14 +382,14 @@ pub fn signatures<'a>(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
))
|
))})
|
||||||
.push_maybe(if tx.status == SpendStatus::Pending {
|
.push_maybe(if tx.status == SpendStatus::Pending {
|
||||||
Some(
|
Some(
|
||||||
Column::new().push(separation().width(Length::Fill)).push(
|
Column::new().push(separation().width(Length::Fill)).push(
|
||||||
Container::new(
|
Container::new(
|
||||||
Row::new()
|
Row::new()
|
||||||
.push(Space::with_width(Length::Fill))
|
.push(Space::with_width(Length::Fill))
|
||||||
.push_maybe(if !tx.is_ready() {
|
.push_maybe(if tx.path_ready().is_some() {
|
||||||
Some(
|
Some(
|
||||||
button::primary(None, "Sign")
|
button::primary(None, "Sign")
|
||||||
.on_press(Message::Spend(SpendTxMessage::Sign))
|
.on_press(Message::Spend(SpendTxMessage::Sign))
|
||||||
@ -394,29 +420,62 @@ pub fn path_view<'a>(
|
|||||||
key_aliases: &'a HashMap<Fingerprint, String>,
|
key_aliases: &'a HashMap<Fingerprint, String>,
|
||||||
) -> Element<'a, Message> {
|
) -> Element<'a, Message> {
|
||||||
let mut keys: Vec<Fingerprint> = path.thresh_fingerprints().1.into_iter().collect();
|
let mut keys: Vec<Fingerprint> = path.thresh_fingerprints().1.into_iter().collect();
|
||||||
|
let missing_signatures = if sigs.sigs_count >= sigs.threshold {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
sigs.threshold - sigs.sigs_count
|
||||||
|
};
|
||||||
keys.sort();
|
keys.sort();
|
||||||
Scrollable::new(
|
Scrollable::new(
|
||||||
Row::new()
|
Row::new()
|
||||||
.spacing(5)
|
|
||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.push(if sigs.signed_pubkeys.len() >= sigs.threshold {
|
.push(if sigs.sigs_count >= sigs.threshold {
|
||||||
icon::circle_check_icon().style(color::SUCCESS)
|
icon::circle_check_icon().style(color::SUCCESS)
|
||||||
} else {
|
} else {
|
||||||
icon::circle_cross_icon()
|
icon::circle_cross_icon()
|
||||||
})
|
})
|
||||||
.push(
|
.push(text(format!(" {}", missing_signatures)).bold())
|
||||||
Container::new(text(format!(" {} ", sigs.threshold))).style(
|
|
||||||
if sigs.signed_pubkeys.len() >= sigs.threshold {
|
|
||||||
badge::PillStyle::Success
|
|
||||||
} else {
|
|
||||||
badge::PillStyle::Simple
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.push(text(format!(
|
.push(text(format!(
|
||||||
"signature{} out of",
|
" more signature{}",
|
||||||
if sigs.threshold > 1 { "s" } else { "" }
|
if missing_signatures > 1 {
|
||||||
|
"s from "
|
||||||
|
} else if missing_signatures == 0 {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
" from "
|
||||||
|
}
|
||||||
)))
|
)))
|
||||||
|
.push_maybe(if keys.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(keys.iter().fold(Row::new().spacing(5), |row, &value| {
|
||||||
|
row.push_maybe(if !sigs.signed_pubkeys.contains_key(&value) {
|
||||||
|
Some(if let Some(alias) = key_aliases.get(&value) {
|
||||||
|
Container::new(
|
||||||
|
tooltip::Tooltip::new(
|
||||||
|
Container::new(text(alias))
|
||||||
|
.padding(3)
|
||||||
|
.style(badge::PillStyle::Simple),
|
||||||
|
value.to_string(),
|
||||||
|
tooltip::Position::Bottom,
|
||||||
|
)
|
||||||
|
.style(card::SimpleCardStyle),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Container::new(text(value.to_string()))
|
||||||
|
.padding(3)
|
||||||
|
.style(badge::PillStyle::Simple)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
.push_maybe(if sigs.signed_pubkeys.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(text(", already signed by "))
|
||||||
|
})
|
||||||
.push(
|
.push(
|
||||||
sigs.signed_pubkeys
|
sigs.signed_pubkeys
|
||||||
.keys()
|
.keys()
|
||||||
@ -426,7 +485,7 @@ pub fn path_view<'a>(
|
|||||||
tooltip::Tooltip::new(
|
tooltip::Tooltip::new(
|
||||||
Container::new(text(alias))
|
Container::new(text(alias))
|
||||||
.padding(3)
|
.padding(3)
|
||||||
.style(badge::PillStyle::Success),
|
.style(badge::PillStyle::Simple),
|
||||||
value.to_string(),
|
value.to_string(),
|
||||||
tooltip::Position::Bottom,
|
tooltip::Position::Bottom,
|
||||||
)
|
)
|
||||||
@ -435,32 +494,10 @@ pub fn path_view<'a>(
|
|||||||
} else {
|
} else {
|
||||||
Container::new(text(value.to_string()))
|
Container::new(text(value.to_string()))
|
||||||
.padding(3)
|
.padding(3)
|
||||||
.style(badge::PillStyle::Success)
|
.style(badge::PillStyle::Simple)
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
)
|
),
|
||||||
.push(keys.iter().fold(Row::new().spacing(5), |row, &value| {
|
|
||||||
row.push_maybe(if !sigs.signed_pubkeys.contains_key(&value) {
|
|
||||||
Some(if let Some(alias) = key_aliases.get(&value) {
|
|
||||||
Container::new(
|
|
||||||
tooltip::Tooltip::new(
|
|
||||||
Container::new(text(alias))
|
|
||||||
.padding(3)
|
|
||||||
.style(badge::PillStyle::Simple),
|
|
||||||
value.to_string(),
|
|
||||||
tooltip::Position::Bottom,
|
|
||||||
)
|
|
||||||
.style(card::SimpleCardStyle),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Container::new(text(value.to_string()))
|
|
||||||
.padding(3)
|
|
||||||
.style(badge::PillStyle::Simple)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
})
|
|
||||||
})),
|
|
||||||
)
|
)
|
||||||
.horizontal_scroll(scrollable::Properties::new().width(2).scroller_width(2))
|
.horizontal_scroll(scrollable::Properties::new().width(2).scroller_width(2))
|
||||||
.into()
|
.into()
|
||||||
|
|||||||
@ -121,8 +121,8 @@ fn spend_tx_list_view<'a>(i: usize, tx: &SpendTx) -> Element<'a, Message> {
|
|||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.push(text(format!(
|
.push(text(format!(
|
||||||
"{}/{}",
|
"{}/{}",
|
||||||
if sigs.signed_pubkeys.len() <= sigs.threshold {
|
if sigs.sigs_count <= sigs.threshold {
|
||||||
sigs.signed_pubkeys.len()
|
sigs.sigs_count
|
||||||
} else {
|
} else {
|
||||||
sigs.threshold
|
sigs.threshold
|
||||||
},
|
},
|
||||||
@ -142,8 +142,8 @@ fn spend_tx_list_view<'a>(i: usize, tx: &SpendTx) -> Element<'a, Message> {
|
|||||||
.align_items(Alignment::Center)
|
.align_items(Alignment::Center)
|
||||||
.push(text(format!(
|
.push(text(format!(
|
||||||
"{}/{}",
|
"{}/{}",
|
||||||
if sigs.signed_pubkeys.len() <= sigs.threshold {
|
if sigs.sigs_count <= sigs.threshold {
|
||||||
sigs.signed_pubkeys.len()
|
sigs.sigs_count
|
||||||
} else {
|
} else {
|
||||||
sigs.threshold
|
sigs.threshold
|
||||||
},
|
},
|
||||||
|
|||||||
@ -3,7 +3,7 @@ pub use liana::{
|
|||||||
CreateSpendResult, GetAddressResult, GetInfoResult, ListCoinsEntry, ListCoinsResult,
|
CreateSpendResult, GetAddressResult, GetInfoResult, ListCoinsEntry, ListCoinsResult,
|
||||||
ListSpendEntry, ListSpendResult, ListTransactionsResult, TransactionInfo,
|
ListSpendEntry, ListSpendResult, ListTransactionsResult, TransactionInfo,
|
||||||
},
|
},
|
||||||
descriptors::PartialSpendInfo,
|
descriptors::{PartialSpendInfo, PathSpendInfo},
|
||||||
miniscript::bitcoin::{util::psbt::Psbt, Amount, Transaction},
|
miniscript::bitcoin::{util::psbt::Psbt, Amount, Transaction},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,17 +78,18 @@ impl SpendTx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_ready(&self) -> bool {
|
/// Returns the path ready if it exists.
|
||||||
|
pub fn path_ready(&self) -> Option<&PathSpendInfo> {
|
||||||
let path = self.sigs.primary_path();
|
let path = self.sigs.primary_path();
|
||||||
if path.signed_pubkeys.len() >= path.threshold {
|
if path.sigs_count >= path.threshold {
|
||||||
return true;
|
return Some(path);
|
||||||
}
|
}
|
||||||
if let Some(path) = self.sigs.recovery_path() {
|
if let Some(path) = self.sigs.recovery_path() {
|
||||||
if path.signed_pubkeys.len() >= path.threshold {
|
if path.sigs_count >= path.threshold {
|
||||||
return true;
|
return Some(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user