Merge #940: gui(spend): display warnings for draft PSBTs
85f5a68ed3b9bfee1488fceddb8a78321d1583a2 gui(spend): display warnings for draft PSBTs (jp1ac4) Pull request description: This is to complete #811. It displays any warnings generated by `createspend` on the draft PSBT view, which could currently be those from https://github.com/wizardsardine/liana/pull/905 and https://github.com/wizardsardine/liana/pull/873. Once the PSBT has been saved, these warnings will no longer be shown. Below are some screenshots. With a warning:   Without a warning:   ACKs for top commit: edouardparis: ACK 85f5a68ed3b9bfee1488fceddb8a78321d1583a2 Tree-SHA512: b9875801f7607f6f824ad9ab5182e93aa533ba2bbb8f9a4168c4a2a779a8f39cf77dc0b24eac7c99a0fce36c486c126144d23b0cb7ecec27ebc145ea2ffdb212
This commit is contained in:
commit
7801fc779c
@ -29,7 +29,7 @@ pub enum Message {
|
|||||||
Coins(Result<Vec<Coin>, Error>),
|
Coins(Result<Vec<Coin>, Error>),
|
||||||
Labels(Result<HashMap<String, String>, Error>),
|
Labels(Result<HashMap<String, String>, Error>),
|
||||||
SpendTxs(Result<Vec<SpendTx>, Error>),
|
SpendTxs(Result<Vec<SpendTx>, Error>),
|
||||||
Psbt(Result<Psbt, Error>),
|
Psbt(Result<(Psbt, Vec<String>), Error>),
|
||||||
RbfPsbt(Result<Txid, Error>),
|
RbfPsbt(Result<Txid, Error>),
|
||||||
Recovery(Result<SpendTx, Error>),
|
Recovery(Result<SpendTx, Error>),
|
||||||
Signed(Fingerprint, Result<Psbt, Error>),
|
Signed(Fingerprint, Result<Psbt, Error>),
|
||||||
|
|||||||
@ -29,7 +29,7 @@ pub struct TransactionDraft {
|
|||||||
network: Network,
|
network: Network,
|
||||||
inputs: Vec<Coin>,
|
inputs: Vec<Coin>,
|
||||||
recipients: Vec<Recipient>,
|
recipients: Vec<Recipient>,
|
||||||
generated: Option<Psbt>,
|
generated: Option<(Psbt, Vec<String>)>,
|
||||||
batch_label: Option<String>,
|
batch_label: Option<String>,
|
||||||
labels: HashMap<String, String>,
|
labels: HashMap<String, String>,
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ pub struct DefineSpend {
|
|||||||
batch_label: form::Value<String>,
|
batch_label: form::Value<String>,
|
||||||
amount_left_to_select: Option<Amount>,
|
amount_left_to_select: Option<Amount>,
|
||||||
feerate: form::Value<String>,
|
feerate: form::Value<String>,
|
||||||
generated: Option<Psbt>,
|
generated: Option<(Psbt, Vec<String>)>,
|
||||||
warning: Option<Error>,
|
warning: Option<Error>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +351,9 @@ impl Step for DefineSpend {
|
|||||||
.create_spend_tx(&inputs, &outputs, feerate_vb, None)
|
.create_spend_tx(&inputs, &outputs, feerate_vb, None)
|
||||||
.map_err(|e| e.into())
|
.map_err(|e| e.into())
|
||||||
.and_then(|res| match res {
|
.and_then(|res| match res {
|
||||||
CreateSpendResult::Success { psbt, .. } => Ok(psbt),
|
CreateSpendResult::Success { psbt, warnings } => {
|
||||||
|
Ok((psbt, warnings))
|
||||||
|
}
|
||||||
CreateSpendResult::InsufficientFunds { missing } => {
|
CreateSpendResult::InsufficientFunds { missing } => {
|
||||||
Err(SpendCreationError::CoinSelection(
|
Err(SpendCreationError::CoinSelection(
|
||||||
liana::spend::InsufficientFunds { missing },
|
liana::spend::InsufficientFunds { missing },
|
||||||
@ -405,7 +407,7 @@ impl Step for DefineSpend {
|
|||||||
.filter_map(|(coin, selected)| if *selected { Some(coin) } else { None })
|
.filter_map(|(coin, selected)| if *selected { Some(coin) } else { None })
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
if let Some(psbt) = &self.generated {
|
if let Some((psbt, _)) = &self.generated {
|
||||||
draft.labels = self.coins_labels.clone();
|
draft.labels = self.coins_labels.clone();
|
||||||
for (i, output) in psbt.unsigned_tx.output.iter().enumerate() {
|
for (i, output) in psbt.unsigned_tx.output.iter().enumerate() {
|
||||||
if let Some(label) = self
|
if let Some(label) = self
|
||||||
@ -550,7 +552,7 @@ impl Recipient {
|
|||||||
|
|
||||||
pub struct SaveSpend {
|
pub struct SaveSpend {
|
||||||
wallet: Arc<Wallet>,
|
wallet: Arc<Wallet>,
|
||||||
spend: Option<psbt::PsbtState>,
|
spend: Option<(psbt::PsbtState, Vec<String>)>,
|
||||||
curve: secp256k1::Secp256k1<secp256k1::VerifyOnly>,
|
curve: secp256k1::Secp256k1<secp256k1::VerifyOnly>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,7 +568,7 @@ impl SaveSpend {
|
|||||||
|
|
||||||
impl Step for SaveSpend {
|
impl Step for SaveSpend {
|
||||||
fn load(&mut self, draft: &TransactionDraft) {
|
fn load(&mut self, draft: &TransactionDraft) {
|
||||||
let psbt = draft.generated.clone().unwrap();
|
let (psbt, warnings) = draft.generated.clone().unwrap();
|
||||||
let mut tx = SpendTx::new(
|
let mut tx = SpendTx::new(
|
||||||
None,
|
None,
|
||||||
psbt,
|
psbt,
|
||||||
@ -590,12 +592,15 @@ impl Step for SaveSpend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.spend = Some(psbt::PsbtState::new(self.wallet.clone(), tx, false));
|
self.spend = Some((
|
||||||
|
psbt::PsbtState::new(self.wallet.clone(), tx, false),
|
||||||
|
warnings,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subscription(&self) -> Subscription<Message> {
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
if let Some(spend) = &self.spend {
|
if let Some((psbt_state, _)) = &self.spend {
|
||||||
spend.subscription()
|
psbt_state.subscription()
|
||||||
} else {
|
} else {
|
||||||
Subscription::none()
|
Subscription::none()
|
||||||
}
|
}
|
||||||
@ -607,26 +612,27 @@ impl Step for SaveSpend {
|
|||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
message: Message,
|
message: Message,
|
||||||
) -> Command<Message> {
|
) -> Command<Message> {
|
||||||
if let Some(spend) = &mut self.spend {
|
if let Some((psbt_state, _)) = &mut self.spend {
|
||||||
spend.update(daemon, cache, message)
|
psbt_state.update(daemon, cache, message)
|
||||||
} else {
|
} else {
|
||||||
Command::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view<'a>(&'a self, cache: &'a Cache) -> Element<'a, view::Message> {
|
fn view<'a>(&'a self, cache: &'a Cache) -> Element<'a, view::Message> {
|
||||||
let spend = self.spend.as_ref().unwrap();
|
let (psbt_state, warnings) = self.spend.as_ref().unwrap();
|
||||||
let content = view::spend::spend_view(
|
let content = view::spend::spend_view(
|
||||||
cache,
|
cache,
|
||||||
&spend.tx,
|
&psbt_state.tx,
|
||||||
spend.saved,
|
warnings,
|
||||||
&spend.desc_policy,
|
psbt_state.saved,
|
||||||
&spend.wallet.keys_aliases,
|
&psbt_state.desc_policy,
|
||||||
spend.labels_edited.cache(),
|
&psbt_state.wallet.keys_aliases,
|
||||||
|
psbt_state.labels_edited.cache(),
|
||||||
cache.network,
|
cache.network,
|
||||||
spend.warning.as_ref(),
|
psbt_state.warning.as_ref(),
|
||||||
);
|
);
|
||||||
if let Some(action) = &spend.action {
|
if let Some(action) = &psbt_state.action {
|
||||||
action.as_ref().view(content)
|
action.as_ref().view(content)
|
||||||
} else {
|
} else {
|
||||||
content
|
content
|
||||||
|
|||||||
@ -33,6 +33,7 @@ use crate::{
|
|||||||
pub fn spend_view<'a>(
|
pub fn spend_view<'a>(
|
||||||
cache: &'a Cache,
|
cache: &'a Cache,
|
||||||
tx: &'a SpendTx,
|
tx: &'a SpendTx,
|
||||||
|
spend_warnings: &'a Vec<String>,
|
||||||
saved: bool,
|
saved: bool,
|
||||||
desc_info: &'a LianaPolicy,
|
desc_info: &'a LianaPolicy,
|
||||||
key_aliases: &'a HashMap<Fingerprint, String>,
|
key_aliases: &'a HashMap<Fingerprint, String>,
|
||||||
@ -48,6 +49,21 @@ pub fn spend_view<'a>(
|
|||||||
.spacing(20)
|
.spacing(20)
|
||||||
.push(Container::new(h3("Send")).width(Length::Fill))
|
.push(Container::new(h3("Send")).width(Length::Fill))
|
||||||
.push(psbt::spend_header(tx, labels_editing))
|
.push(psbt::spend_header(tx, labels_editing))
|
||||||
|
.push_maybe(if spend_warnings.is_empty() || saved {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(spend_warnings.iter().fold(
|
||||||
|
Column::new().padding(15).spacing(5),
|
||||||
|
|col, warning| {
|
||||||
|
col.push(
|
||||||
|
Row::new()
|
||||||
|
.spacing(5)
|
||||||
|
.push(icon::warning_icon().style(color::ORANGE))
|
||||||
|
.push(text(warning).style(color::ORANGE)),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
))
|
||||||
|
})
|
||||||
.push(psbt::spend_overview_view(tx, desc_info, key_aliases))
|
.push(psbt::spend_overview_view(tx, desc_info, key_aliases))
|
||||||
.push(
|
.push(
|
||||||
Column::new()
|
Column::new()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user