mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-11 16:00:57 +00:00
feat(core/ui): sending transaction style update
[no changelog]
This commit is contained in:
parent
229c81fa7e
commit
a44e738d31
@ -26,7 +26,7 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_confirm_properties;
|
||||
MP_QSTR_confirm_coinjoin;
|
||||
MP_QSTR_confirm_fido;
|
||||
MP_QSTR_confirm_joint_total;
|
||||
MP_QSTR_confirm_total;
|
||||
MP_QSTR_confirm_modify_fee;
|
||||
MP_QSTR_confirm_modify_output;
|
||||
MP_QSTR_confirm_reset_device;
|
||||
@ -59,6 +59,7 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_show_progress;
|
||||
MP_QSTR_show_progress_coinjoin;
|
||||
MP_QSTR_show_address_details;
|
||||
MP_QSTR_show_spending_details;
|
||||
|
||||
MP_QSTR_attach_timer_fn;
|
||||
MP_QSTR_touch_event;
|
||||
@ -94,10 +95,9 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_coin_name;
|
||||
MP_QSTR_max_feerate;
|
||||
MP_QSTR_max_rounds;
|
||||
MP_QSTR_spending_amount;
|
||||
MP_QSTR_total_amount;
|
||||
MP_QSTR_total_fee_new;
|
||||
MP_QSTR_user_fee_change;
|
||||
MP_QSTR_fee_rate;
|
||||
MP_QSTR_words;
|
||||
MP_QSTR_pages;
|
||||
MP_QSTR_count;
|
||||
|
@ -10,6 +10,9 @@ pub enum AuxPageMsg {
|
||||
|
||||
/// Page component was configured to react to swipes and user swiped left.
|
||||
SwipeLeft,
|
||||
|
||||
/// Page component was configured to react to swipes and user swiped right.
|
||||
SwipeRight,
|
||||
}
|
||||
|
||||
/// Common message type for pagination components.
|
||||
|
@ -418,7 +418,11 @@ impl<T> Button<T> {
|
||||
|
||||
let left = if let Some(verb) = left {
|
||||
left_is_small = verb.as_ref().len() <= 4;
|
||||
Button::with_text(verb)
|
||||
if verb.as_ref() == "^" {
|
||||
Button::with_icon(Icon::new(theme::ICON_UP))
|
||||
} else {
|
||||
Button::with_text(verb)
|
||||
}
|
||||
} else {
|
||||
left_is_small = right.is_some();
|
||||
Button::with_icon(Icon::new(theme::ICON_CANCEL))
|
||||
|
@ -62,6 +62,7 @@ where
|
||||
button_prev_cancels: ButtonPrevCancels,
|
||||
is_go_back: Option<fn(&U::Msg) -> bool>,
|
||||
swipe_left: bool,
|
||||
swipe_right: bool,
|
||||
fade: Option<u16>,
|
||||
}
|
||||
|
||||
@ -83,6 +84,7 @@ where
|
||||
button_prev_cancels: ButtonPrevCancels::Never,
|
||||
is_go_back: None,
|
||||
swipe_left: false,
|
||||
swipe_right: false,
|
||||
fade: None,
|
||||
}
|
||||
}
|
||||
@ -111,10 +113,16 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_swipe_right(mut self) -> Self {
|
||||
self.swipe_right = true;
|
||||
self
|
||||
}
|
||||
|
||||
fn setup_swipe(&mut self) {
|
||||
self.swipe.allow_up = self.scrollbar.has_next_page();
|
||||
self.swipe.allow_down = self.scrollbar.has_previous_page();
|
||||
self.swipe.allow_left = self.swipe_left;
|
||||
self.swipe.allow_right = self.swipe_right;
|
||||
}
|
||||
|
||||
fn on_page_change(&mut self, ctx: &mut EventCtx) {
|
||||
@ -219,6 +227,9 @@ where
|
||||
SwipeDirection::Left if self.swipe_left => {
|
||||
return Some(PageMsg::Aux(AuxPageMsg::SwipeLeft));
|
||||
}
|
||||
SwipeDirection::Right if self.swipe_right => {
|
||||
return Some(PageMsg::Aux(AuxPageMsg::SwipeRight));
|
||||
}
|
||||
_ => {
|
||||
// Ignore other directions.
|
||||
}
|
||||
@ -394,6 +405,11 @@ where
|
||||
pad: Pad::with_background(background),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_swipe_left(mut self) -> Self {
|
||||
self.inner = self.inner.with_swipe_left();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Component for SwipeHoldPage<T>
|
||||
@ -418,6 +434,7 @@ where
|
||||
return Some(PageMsg::Controls(CancelConfirmMsg::Cancelled))
|
||||
}
|
||||
Some(PageMsg::Controls(CancelHoldMsg::HoldButton(b))) => Some(b),
|
||||
Some(PageMsg::Aux(a)) => return Some(PageMsg::Aux(a)),
|
||||
_ => None,
|
||||
};
|
||||
if handle_hold_event(
|
||||
|
@ -228,6 +228,7 @@ where
|
||||
PageMsg::Controls(msg) => msg.try_into(),
|
||||
PageMsg::Aux(AuxPageMsg::GoBack) => Ok(CANCELLED.as_obj()),
|
||||
PageMsg::Aux(AuxPageMsg::SwipeLeft) => Ok(INFO.as_obj()),
|
||||
PageMsg::Aux(AuxPageMsg::SwipeRight) => Ok(CANCELLED.as_obj()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -240,7 +241,9 @@ where
|
||||
match msg {
|
||||
PageMsg::Content(_) => Err(Error::TypeError),
|
||||
PageMsg::Controls(msg) => msg.try_into(),
|
||||
PageMsg::Aux(_) => Err(Error::TypeError),
|
||||
PageMsg::Aux(AuxPageMsg::GoBack) => Ok(CANCELLED.as_obj()),
|
||||
PageMsg::Aux(AuxPageMsg::SwipeLeft) => Ok(INFO.as_obj()),
|
||||
PageMsg::Aux(AuxPageMsg::SwipeRight) => Ok(CANCELLED.as_obj()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -440,42 +443,98 @@ extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut M
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
fn confirm_blob(
|
||||
struct ConfirmBlobParams {
|
||||
title: StrBuffer,
|
||||
subtitle: Option<StrBuffer>,
|
||||
data: Obj,
|
||||
description: Option<StrBuffer>,
|
||||
extra: Option<StrBuffer>,
|
||||
verb: Option<StrBuffer>,
|
||||
verb_cancel: Option<StrBuffer>,
|
||||
info_button: bool,
|
||||
hold: bool,
|
||||
) -> Result<Obj, Error> {
|
||||
let paragraphs = ConfirmBlob {
|
||||
description: description.unwrap_or_else(StrBuffer::empty),
|
||||
extra: extra.unwrap_or_else(StrBuffer::empty),
|
||||
data: data.try_into()?,
|
||||
description_font: &theme::TEXT_NORMAL,
|
||||
extra_font: &theme::TEXT_DEMIBOLD,
|
||||
data_font: &theme::TEXT_MONO,
|
||||
}
|
||||
.into_paragraphs();
|
||||
}
|
||||
|
||||
let obj = if hold {
|
||||
LayoutObj::new(Frame::left_aligned(
|
||||
theme::label_title(),
|
||||
impl ConfirmBlobParams {
|
||||
fn new(
|
||||
title: StrBuffer,
|
||||
data: Obj,
|
||||
description: Option<StrBuffer>,
|
||||
verb: Option<StrBuffer>,
|
||||
verb_cancel: Option<StrBuffer>,
|
||||
hold: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
title,
|
||||
SwipeHoldPage::new(paragraphs, theme::BG),
|
||||
))?
|
||||
} else if let Some(verb) = verb {
|
||||
let buttons = Button::cancel_confirm_text(verb_cancel, Some(verb));
|
||||
LayoutObj::new(Frame::left_aligned(
|
||||
theme::label_title(),
|
||||
title,
|
||||
SwipePage::new(paragraphs, buttons, theme::BG).with_cancel_on_first_page(),
|
||||
))?
|
||||
} else {
|
||||
panic!("Either `hold=true` or `verb=Some(StrBuffer)` must be specified");
|
||||
};
|
||||
Ok(obj.into())
|
||||
subtitle: None,
|
||||
data,
|
||||
description,
|
||||
extra: None,
|
||||
verb,
|
||||
verb_cancel,
|
||||
info_button: false,
|
||||
hold,
|
||||
}
|
||||
}
|
||||
|
||||
fn with_extra(mut self, extra: Option<StrBuffer>) -> Self {
|
||||
self.extra = extra;
|
||||
self
|
||||
}
|
||||
|
||||
fn with_subtitle(mut self, subtitle: Option<StrBuffer>) -> Self {
|
||||
self.subtitle = subtitle;
|
||||
self
|
||||
}
|
||||
|
||||
fn with_info_button(mut self, info_button: bool) -> Self {
|
||||
self.info_button = info_button;
|
||||
self
|
||||
}
|
||||
|
||||
fn into_layout(self) -> Result<Obj, Error> {
|
||||
let paragraphs = ConfirmBlob {
|
||||
description: self.description.unwrap_or_else(StrBuffer::empty),
|
||||
extra: self.extra.unwrap_or_else(StrBuffer::empty),
|
||||
data: self.data.try_into()?,
|
||||
description_font: &theme::TEXT_NORMAL,
|
||||
extra_font: &theme::TEXT_DEMIBOLD,
|
||||
data_font: &theme::TEXT_MONO,
|
||||
}
|
||||
.into_paragraphs();
|
||||
|
||||
let obj = if self.hold {
|
||||
let mut frame = Frame::left_aligned(
|
||||
theme::label_title(),
|
||||
self.title,
|
||||
SwipeHoldPage::new(paragraphs, theme::BG),
|
||||
);
|
||||
if let Some(subtitle) = self.subtitle {
|
||||
frame = frame.with_subtitle(theme::label_subtitle(), subtitle);
|
||||
}
|
||||
if self.info_button {
|
||||
frame = frame.with_info_button();
|
||||
}
|
||||
LayoutObj::new(frame)?
|
||||
} else if let Some(verb) = self.verb {
|
||||
let buttons = Button::cancel_confirm_text(self.verb_cancel, Some(verb));
|
||||
let mut frame = Frame::left_aligned(
|
||||
theme::label_title(),
|
||||
self.title,
|
||||
SwipePage::new(paragraphs, buttons, theme::BG).with_cancel_on_first_page(),
|
||||
);
|
||||
if let Some(subtitle) = self.subtitle {
|
||||
frame = frame.with_subtitle(theme::label_subtitle(), subtitle);
|
||||
}
|
||||
if self.info_button {
|
||||
frame = frame.with_info_button();
|
||||
}
|
||||
LayoutObj::new(frame)?
|
||||
} else {
|
||||
panic!("Either `hold=true` or `verb=Some(StrBuffer)` must be specified");
|
||||
};
|
||||
Ok(obj.into())
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
@ -495,7 +554,9 @@ extern "C" fn new_confirm_blob(n_args: usize, args: *const Obj, kwargs: *mut Map
|
||||
.try_into_option()?;
|
||||
let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?;
|
||||
|
||||
confirm_blob(title, data, description, extra, verb, verb_cancel, hold)
|
||||
ConfirmBlobParams::new(title, data, description, verb, verb_cancel, hold)
|
||||
.with_extra(extra)
|
||||
.into_layout()
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
@ -671,41 +732,88 @@ extern "C" fn new_show_address_details(n_args: usize, args: *const Obj, kwargs:
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_show_spending_details(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let account: StrBuffer = kwargs.get(Qstr::MP_QSTR_account)?.try_into()?;
|
||||
let fee_rate: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_fee_rate)?.try_into_option()?;
|
||||
|
||||
let mut paragraphs = ParagraphVecShort::new();
|
||||
paragraphs.add(Paragraph::new(
|
||||
&theme::TEXT_NORMAL,
|
||||
"Sending from account:".into(),
|
||||
));
|
||||
paragraphs.add(Paragraph::new(&theme::TEXT_MONO, account));
|
||||
|
||||
if let Some(f) = fee_rate {
|
||||
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, "Fee rate:".into()));
|
||||
paragraphs.add(Paragraph::new(&theme::TEXT_MONO, f));
|
||||
}
|
||||
|
||||
let obj = LayoutObj::new(
|
||||
Frame::left_aligned(
|
||||
theme::label_title(),
|
||||
"INFORMATION",
|
||||
SwipePage::new(paragraphs.into_paragraphs(), Empty, theme::BG).with_swipe_right(),
|
||||
)
|
||||
.with_cancel_button(),
|
||||
)?;
|
||||
Ok(obj.into())
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_confirm_value(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||
let subtitle: Option<StrBuffer> = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into_option()?;
|
||||
let description: Option<StrBuffer> =
|
||||
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
|
||||
let value: Obj = kwargs.get(Qstr::MP_QSTR_value)?;
|
||||
let info_button: bool = unwrap!(kwargs.get_or(Qstr::MP_QSTR_info_button, false));
|
||||
|
||||
let verb: Option<StrBuffer> = kwargs
|
||||
.get(Qstr::MP_QSTR_verb)
|
||||
.unwrap_or_else(|_| Obj::const_none())
|
||||
.try_into_option()?;
|
||||
let verb_cancel: Option<StrBuffer> = kwargs
|
||||
.get(Qstr::MP_QSTR_verb_cancel)
|
||||
.unwrap_or_else(|_| Obj::const_none())
|
||||
.try_into_option()?;
|
||||
let hold: bool = kwargs.get_or(Qstr::MP_QSTR_hold, false)?;
|
||||
|
||||
confirm_blob(title, value, description, None, verb, None, hold)
|
||||
ConfirmBlobParams::new(title, value, description, verb, verb_cancel, hold)
|
||||
.with_subtitle(subtitle)
|
||||
.with_info_button(info_button)
|
||||
.into_layout()
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_confirm_joint_total(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let spending_amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_spending_amount)?.try_into()?;
|
||||
let total_amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_total_amount)?.try_into()?;
|
||||
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
|
||||
let info_button: bool = kwargs.get_or(Qstr::MP_QSTR_info_button, false).unwrap();
|
||||
|
||||
let paragraphs = Paragraphs::new([
|
||||
Paragraph::new(&theme::TEXT_NORMAL, "You are contributing:".into()),
|
||||
Paragraph::new(&theme::TEXT_MONO, spending_amount),
|
||||
Paragraph::new(&theme::TEXT_NORMAL, "To the total amount:".into()),
|
||||
Paragraph::new(&theme::TEXT_MONO, total_amount),
|
||||
]);
|
||||
let mut paragraphs = ParagraphVecShort::new();
|
||||
|
||||
let obj = LayoutObj::new(Frame::left_aligned(
|
||||
theme::label_title(),
|
||||
"JOINT TRANSACTION",
|
||||
SwipeHoldPage::new(paragraphs, theme::BG),
|
||||
))?;
|
||||
let mut iter_buf = IterBuf::new();
|
||||
let iter = Iter::try_from_obj_with_buf(items, &mut iter_buf)?;
|
||||
for pair in iter {
|
||||
let [label, value]: [StrBuffer; 2] = iter_into_array(pair)?;
|
||||
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, label));
|
||||
paragraphs.add(Paragraph::new(&theme::TEXT_MONO, value));
|
||||
}
|
||||
|
||||
let mut page = SwipeHoldPage::new(paragraphs.into_paragraphs(), theme::BG);
|
||||
if info_button {
|
||||
page = page.with_swipe_left();
|
||||
}
|
||||
let mut frame = Frame::left_aligned(theme::label_title(), title, page);
|
||||
if info_button {
|
||||
frame = frame.with_info_button();
|
||||
}
|
||||
let obj = LayoutObj::new(frame)?;
|
||||
Ok(obj.into())
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
@ -1590,24 +1698,36 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// """Show address details - QR code, account, path, cosigner xpubs."""
|
||||
Qstr::MP_QSTR_show_address_details => obj_fn_kw!(0, new_show_address_details).as_obj(),
|
||||
|
||||
/// def show_spending_details(
|
||||
/// *,
|
||||
/// account: str,
|
||||
/// fee_rate: str | None = None,
|
||||
/// ) -> object:
|
||||
/// """Show metadata when for outgoing transaction."""
|
||||
Qstr::MP_QSTR_show_spending_details => obj_fn_kw!(0, new_show_spending_details).as_obj(),
|
||||
|
||||
/// def confirm_value(
|
||||
/// *,
|
||||
/// title: str,
|
||||
/// description: str,
|
||||
/// value: str,
|
||||
/// description: str | None = None,
|
||||
/// subtitle: str | None = None,
|
||||
/// verb: str | None = None,
|
||||
/// verb_cancel: str | None = None,
|
||||
/// info_button: bool = False,
|
||||
/// hold: bool = False,
|
||||
/// ) -> object:
|
||||
/// """Confirm value. Merge of confirm_total and confirm_output."""
|
||||
Qstr::MP_QSTR_confirm_value => obj_fn_kw!(0, new_confirm_value).as_obj(),
|
||||
|
||||
/// def confirm_joint_total(
|
||||
/// def confirm_total(
|
||||
/// *,
|
||||
/// spending_amount: str,
|
||||
/// total_amount: str,
|
||||
/// title: str,
|
||||
/// items: List[Tuple[str, str]],
|
||||
/// info_button: bool = False,
|
||||
/// ) -> object:
|
||||
/// """Confirm total if there are external inputs."""
|
||||
Qstr::MP_QSTR_confirm_joint_total => obj_fn_kw!(0, new_confirm_joint_total).as_obj(),
|
||||
/// """Transaction summary. Always hold to confirm."""
|
||||
Qstr::MP_QSTR_confirm_total => obj_fn_kw!(0, new_confirm_total).as_obj(),
|
||||
|
||||
/// def confirm_modify_output(
|
||||
/// *,
|
||||
|
@ -151,7 +151,7 @@ pub const fn label_title() -> TextStyle {
|
||||
}
|
||||
|
||||
pub const fn label_subtitle() -> TextStyle {
|
||||
TextStyle::new(Font::NORMAL, GREY_LIGHT, BG, GREY_LIGHT, GREY_LIGHT)
|
||||
TextStyle::new(Font::MONO, GREY_LIGHT, BG, GREY_LIGHT, GREY_LIGHT)
|
||||
}
|
||||
|
||||
pub const fn label_coinjoin_progress() -> TextStyle {
|
||||
|
@ -144,25 +144,38 @@ def show_address_details(
|
||||
"""Show address details - QR code, account, path, cosigner xpubs."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_spending_details(
|
||||
*,
|
||||
account: str,
|
||||
fee_rate: str | None = None,
|
||||
) -> object:
|
||||
"""Show metadata when for outgoing transaction."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_value(
|
||||
*,
|
||||
title: str,
|
||||
description: str,
|
||||
value: str,
|
||||
description: str | None = None,
|
||||
subtitle: str | None = None,
|
||||
verb: str | None = None,
|
||||
verb_cancel: str | None = None,
|
||||
info_button: bool = False,
|
||||
hold: bool = False,
|
||||
) -> object:
|
||||
"""Confirm value. Merge of confirm_total and confirm_output."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_joint_total(
|
||||
def confirm_total(
|
||||
*,
|
||||
spending_amount: str,
|
||||
total_amount: str,
|
||||
title: str,
|
||||
items: List[Tuple[str, str]],
|
||||
info_button: bool = False,
|
||||
) -> object:
|
||||
"""Confirm total if there are external inputs."""
|
||||
"""Transaction summary. Always hold to confirm."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
|
@ -53,6 +53,9 @@ class Approver:
|
||||
self.amount_unit = tx.amount_unit
|
||||
self.has_unverified_external_input = False
|
||||
|
||||
# output numbering to be used in confirmation dialogs
|
||||
self.external_output_index = 0
|
||||
|
||||
def is_payjoin(self) -> bool:
|
||||
# A PayJoin is a replacement transaction which manipulates the external inputs of the
|
||||
# original transaction. A replacement transaction is not allowed to remove any inputs from
|
||||
@ -220,7 +223,10 @@ class BasicApprover(Approver):
|
||||
elif txo.payment_req_index is None or self.show_payment_req_details:
|
||||
# Ask user to confirm output, unless it is part of a payment
|
||||
# request, which gets confirmed separately.
|
||||
await helpers.confirm_output(txo, self.coin, self.amount_unit)
|
||||
await helpers.confirm_output(
|
||||
txo, self.coin, self.amount_unit, self.external_output_index
|
||||
)
|
||||
self.external_output_index += 1
|
||||
|
||||
async def add_payment_request(
|
||||
self, msg: TxAckPaymentRequest, keychain: Keychain
|
||||
|
@ -38,13 +38,26 @@ class UiConfirm:
|
||||
|
||||
|
||||
class UiConfirmOutput(UiConfirm):
|
||||
def __init__(self, output: TxOutput, coin: CoinInfo, amount_unit: AmountUnit):
|
||||
def __init__(
|
||||
self,
|
||||
output: TxOutput,
|
||||
coin: CoinInfo,
|
||||
amount_unit: AmountUnit,
|
||||
output_index: int,
|
||||
):
|
||||
self.output = output
|
||||
self.coin = coin
|
||||
self.amount_unit = amount_unit
|
||||
self.output_index = output_index
|
||||
|
||||
def confirm_dialog(self, ctx: Context) -> Awaitable[Any]:
|
||||
return layout.confirm_output(ctx, self.output, self.coin, self.amount_unit)
|
||||
return layout.confirm_output(
|
||||
ctx,
|
||||
self.output,
|
||||
self.coin,
|
||||
self.amount_unit,
|
||||
self.output_index,
|
||||
)
|
||||
|
||||
|
||||
class UiConfirmDecredSSTXSubmission(UiConfirm):
|
||||
@ -222,8 +235,8 @@ class UiConfirmNonDefaultLocktime(UiConfirm):
|
||||
)
|
||||
|
||||
|
||||
def confirm_output(output: TxOutput, coin: CoinInfo, amount_unit: AmountUnit) -> Awaitable[None]: # type: ignore [awaitable-is-generator]
|
||||
return (yield UiConfirmOutput(output, coin, amount_unit))
|
||||
def confirm_output(output: TxOutput, coin: CoinInfo, amount_unit: AmountUnit, output_index: int) -> Awaitable[None]: # type: ignore [awaitable-is-generator]
|
||||
return (yield UiConfirmOutput(output, coin, amount_unit, output_index))
|
||||
|
||||
|
||||
def confirm_decred_sstx_submission(output: TxOutput, coin: CoinInfo, amount_unit: AmountUnit) -> Awaitable[None]: # type: ignore [awaitable-is-generator]
|
||||
|
@ -49,8 +49,21 @@ def format_coin_amount(amount: int, coin: CoinInfo, amount_unit: AmountUnit) ->
|
||||
return f"{format_amount(amount, decimals)} {shortcut}"
|
||||
|
||||
|
||||
def account_label(coin: CoinInfo, address_n: Bip32Path | None) -> str:
|
||||
return (
|
||||
"Multiple accounts"
|
||||
if address_n is None
|
||||
else address_n_to_name(coin, list(address_n) + [0] * BIP32_WALLET_DEPTH)
|
||||
or f"Path {address_n_to_str(address_n)}"
|
||||
)
|
||||
|
||||
|
||||
async def confirm_output(
|
||||
ctx: Context, output: TxOutput, coin: CoinInfo, amount_unit: AmountUnit
|
||||
ctx: Context,
|
||||
output: TxOutput,
|
||||
coin: CoinInfo,
|
||||
amount_unit: AmountUnit,
|
||||
output_index: int,
|
||||
) -> None:
|
||||
from . import omni
|
||||
from trezor.enums import OutputScriptType
|
||||
@ -82,7 +95,7 @@ async def confirm_output(
|
||||
if output.payment_req_index is not None:
|
||||
title = "Confirm details"
|
||||
else:
|
||||
title = "Confirm sending"
|
||||
title = None
|
||||
|
||||
address_label = None
|
||||
if output.address_n and not output.multisig:
|
||||
@ -98,6 +111,7 @@ async def confirm_output(
|
||||
format_coin_amount(output.amount, coin, amount_unit),
|
||||
title=title,
|
||||
address_label=address_label,
|
||||
output_index=output_index,
|
||||
)
|
||||
|
||||
await layout
|
||||
@ -230,18 +244,12 @@ async def confirm_total(
|
||||
address_n: Bip32Path | None,
|
||||
) -> None:
|
||||
|
||||
account_label = (
|
||||
"mixed accounts"
|
||||
if address_n is None
|
||||
else address_n_to_name(coin, list(address_n) + [0] * BIP32_WALLET_DEPTH)
|
||||
or f"path {address_n_to_str(address_n)}"
|
||||
)
|
||||
await layouts.confirm_total(
|
||||
ctx,
|
||||
format_coin_amount(spending, coin, amount_unit),
|
||||
format_coin_amount(fee, coin, amount_unit),
|
||||
fee_rate_amount=format_fee_rate(fee_rate, coin) if fee_rate >= 0 else None,
|
||||
account_label=account_label,
|
||||
account_label=account_label(coin, address_n),
|
||||
)
|
||||
|
||||
|
||||
|
@ -44,8 +44,7 @@ async def ask_transfer(
|
||||
await confirm_output(
|
||||
ctx,
|
||||
transfer.recipient,
|
||||
f"Send {format_amount(_get_xem_amount(transfer), NEM_MAX_DIVISIBILITY)} XEM",
|
||||
"Confirm transfer",
|
||||
f"{format_amount(_get_xem_amount(transfer), NEM_MAX_DIVISIBILITY)} XEM",
|
||||
)
|
||||
|
||||
await require_confirm_final(ctx, common.fee)
|
||||
|
@ -531,37 +531,63 @@ async def confirm_output(
|
||||
ctx: GenericContext,
|
||||
address: str,
|
||||
amount: str,
|
||||
title: str = "SENDING",
|
||||
title: str | None = None,
|
||||
hold: bool = False,
|
||||
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
|
||||
address_label: str | None = None,
|
||||
output_index: int | None = None,
|
||||
) -> None:
|
||||
title = title.upper()
|
||||
if title.startswith("CONFIRM "):
|
||||
title = title[len("CONFIRM ") :]
|
||||
if title is not None:
|
||||
if title.upper().startswith("CONFIRM "):
|
||||
title = title[len("CONFIRM ") :]
|
||||
amount_title = title.upper()
|
||||
recipient_title = title.upper()
|
||||
elif output_index is not None:
|
||||
amount_title = f"AMOUNT #{output_index + 1}"
|
||||
recipient_title = f"RECIPIENT #{output_index + 1}"
|
||||
else:
|
||||
amount_title = "SENDING AMOUNT"
|
||||
recipient_title = "SENDING TO"
|
||||
|
||||
description = f"To your {address_label}:" if address_label else "To:"
|
||||
await confirm_value(
|
||||
ctx,
|
||||
title,
|
||||
address,
|
||||
description,
|
||||
"confirm_output",
|
||||
br_code,
|
||||
verb="NEXT",
|
||||
)
|
||||
while True:
|
||||
result = await interact(
|
||||
ctx,
|
||||
RustLayout(
|
||||
trezorui2.confirm_value(
|
||||
title=recipient_title,
|
||||
subtitle=address_label,
|
||||
description=None,
|
||||
value=address,
|
||||
verb="CONTINUE",
|
||||
hold=False,
|
||||
info_button=False,
|
||||
)
|
||||
),
|
||||
"confirm_output",
|
||||
br_code,
|
||||
)
|
||||
if result is not CONFIRMED:
|
||||
raise ActionCancelled
|
||||
|
||||
# Second screen could be HoldToConfirm if requested
|
||||
await confirm_value(
|
||||
ctx,
|
||||
title,
|
||||
amount,
|
||||
"Amount:",
|
||||
"confirm_output",
|
||||
br_code,
|
||||
verb=None if hold else "NEXT",
|
||||
hold=hold,
|
||||
)
|
||||
result = await interact(
|
||||
ctx,
|
||||
RustLayout(
|
||||
trezorui2.confirm_value(
|
||||
title=amount_title,
|
||||
subtitle=None,
|
||||
description=None,
|
||||
value=amount,
|
||||
verb=None if hold else "CONFIRM",
|
||||
verb_cancel="^",
|
||||
hold=hold,
|
||||
info_button=False,
|
||||
)
|
||||
),
|
||||
"confirm_output",
|
||||
br_code,
|
||||
)
|
||||
if result is CONFIRMED:
|
||||
return
|
||||
|
||||
|
||||
async def confirm_payment_request(
|
||||
@ -780,7 +806,9 @@ def confirm_value(
|
||||
br_code: ButtonRequestType = ButtonRequestType.Other,
|
||||
*,
|
||||
verb: str | None = None,
|
||||
subtitle: str | None = None,
|
||||
hold: bool = False,
|
||||
info_button: bool = False,
|
||||
) -> Awaitable[None]:
|
||||
"""General confirmation dialog, used by many other confirm_* functions."""
|
||||
|
||||
@ -793,10 +821,12 @@ def confirm_value(
|
||||
RustLayout(
|
||||
trezorui2.confirm_value(
|
||||
title=title.upper(),
|
||||
subtitle=subtitle,
|
||||
description=description,
|
||||
value=value,
|
||||
verb=verb,
|
||||
hold=hold,
|
||||
info_button=info_button,
|
||||
)
|
||||
),
|
||||
br_type,
|
||||
@ -837,47 +867,63 @@ async def confirm_total(
|
||||
total_amount: str,
|
||||
fee_amount: str,
|
||||
fee_rate_amount: str | None = None,
|
||||
title: str = "SENDING",
|
||||
title: str = "SUMMARY",
|
||||
total_label: str = "Total amount:",
|
||||
fee_label: str = "Fee:",
|
||||
fee_label: str = "Including fee:",
|
||||
account_label: str | None = None,
|
||||
br_type: str = "confirm_total",
|
||||
br_code: ButtonRequestType = ButtonRequestType.SignTx,
|
||||
) -> None:
|
||||
await confirm_value(
|
||||
layout = RustLayout(
|
||||
trezorui2.confirm_total(
|
||||
title=title,
|
||||
items=[
|
||||
(total_label, total_amount),
|
||||
(fee_label, fee_amount),
|
||||
],
|
||||
info_button=account_label is not None,
|
||||
)
|
||||
)
|
||||
await button_request(
|
||||
ctx,
|
||||
title,
|
||||
f"{fee_amount}\n({fee_rate_amount})"
|
||||
if fee_rate_amount is not None
|
||||
else fee_amount,
|
||||
fee_label,
|
||||
br_type,
|
||||
br_code,
|
||||
verb="NEXT",
|
||||
pages=layout.page_count(),
|
||||
)
|
||||
|
||||
await confirm_value(
|
||||
ctx,
|
||||
title,
|
||||
total_amount,
|
||||
f"From {account_label}\r\n{total_label}" if account_label else total_label,
|
||||
br_type,
|
||||
br_code,
|
||||
hold=True,
|
||||
)
|
||||
while True:
|
||||
result = await ctx.wait(layout)
|
||||
|
||||
if result is CONFIRMED:
|
||||
return
|
||||
elif result is INFO and account_label is not None:
|
||||
result = await ctx.wait(
|
||||
RustLayout(
|
||||
trezorui2.show_spending_details(
|
||||
account=account_label, fee_rate=fee_rate_amount
|
||||
)
|
||||
)
|
||||
)
|
||||
assert result is CANCELLED
|
||||
layout.request_complete_repaint()
|
||||
continue
|
||||
|
||||
raise ActionCancelled
|
||||
|
||||
|
||||
async def confirm_joint_total(
|
||||
ctx: GenericContext, spending_amount: str, total_amount: str
|
||||
) -> None:
|
||||
|
||||
await raise_if_not_confirmed(
|
||||
interact(
|
||||
ctx,
|
||||
RustLayout(
|
||||
trezorui2.confirm_joint_total(
|
||||
spending_amount=spending_amount,
|
||||
total_amount=total_amount,
|
||||
trezorui2.confirm_total(
|
||||
title="JOINT TRANSACTION",
|
||||
items=[
|
||||
("You are contributing:", spending_amount),
|
||||
("To the total amount:", total_amount),
|
||||
],
|
||||
)
|
||||
),
|
||||
"confirm_joint_total",
|
||||
|
@ -95,13 +95,13 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out2)),
|
||||
|
||||
helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1),
|
||||
True,
|
||||
|
||||
helpers.UiConfirmTotal(12300000, 11000, fee_rate, coin, AmountUnit.BITCOIN, inp1.address_n[:3]),
|
||||
@ -229,7 +229,7 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
|
@ -93,13 +93,13 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out2)),
|
||||
|
||||
helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1),
|
||||
True,
|
||||
|
||||
helpers.UiConfirmNonDefaultLocktime(tx.lock_time, lock_time_disabled=False),
|
||||
@ -227,7 +227,7 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
|
@ -92,13 +92,13 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out2)),
|
||||
|
||||
helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1),
|
||||
True,
|
||||
|
||||
helpers.UiConfirmTotal(123445789 + 11000, 11000, fee_rate, coin, AmountUnit.BITCOIN, inp1.address_n[:3]),
|
||||
@ -223,7 +223,7 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
|
||||
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
@ -371,7 +371,7 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
|
@ -93,13 +93,13 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out2)),
|
||||
|
||||
helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out2, coin, AmountUnit.BITCOIN, 1),
|
||||
True,
|
||||
|
||||
helpers.UiConfirmNonDefaultLocktime(tx.lock_time, lock_time_disabled=False),
|
||||
@ -226,7 +226,7 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
|
@ -85,7 +85,7 @@ class TestSignTxFeeThreshold(unittest.TestCase):
|
||||
TxAckPrevOutput(tx=TxAckPrevOutputWrapper(output=pout1)),
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=None),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
helpers.UiConfirmOutput(out1, coin_bitcoin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin_bitcoin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
helpers.UiConfirmFeeOverThreshold(100000, coin_bitcoin),
|
||||
True,
|
||||
@ -146,7 +146,7 @@ class TestSignTxFeeThreshold(unittest.TestCase):
|
||||
True,
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
helpers.UiConfirmOutput(out1, coin_bitcoin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin_bitcoin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
helpers.UiConfirmTotal(300000 + 90000, 90000, fee_rate, coin_bitcoin, AmountUnit.BITCOIN, None),
|
||||
True,
|
||||
|
@ -111,7 +111,7 @@ class TestSignTx(unittest.TestCase):
|
||||
serialized=EMPTY_SERIALIZED,
|
||||
),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
helpers.UiConfirmOutput(out1, coin_bitcoin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin_bitcoin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
helpers.UiConfirmTotal(3_801_747, 50_000, fee_rate, coin_bitcoin, AmountUnit.BITCOIN, inp1.address_n[:3]),
|
||||
True,
|
||||
|
@ -109,7 +109,7 @@ class TestSignTxDecred(unittest.TestCase):
|
||||
),
|
||||
),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
helpers.UiConfirmOutput(out1, coin_decred, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin_decred, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
helpers.UiConfirmTotal(
|
||||
200_000_000, 100_000, fee_rate, coin_decred, AmountUnit.BITCOIN, inp1.address_n[:3]
|
||||
|
@ -70,7 +70,7 @@ class TestSignTx_GRS(unittest.TestCase):
|
||||
TxAckInput(tx=TxAckInputWrapper(input=inp1)),
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAckOutput(tx=TxAckOutputWrapper(output=out1)),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN),
|
||||
helpers.UiConfirmOutput(out1, coin, AmountUnit.BITCOIN, 0),
|
||||
True,
|
||||
helpers.UiConfirmTotal(210016, 192, fee_rate, coin, AmountUnit.BITCOIN, inp1.address_n[:3]),
|
||||
True,
|
||||
|
@ -86,7 +86,6 @@ def test_autolock_interrupts_signing(device_handler: "BackgroundDeviceHandler"):
|
||||
layout = debug.wait_layout()
|
||||
assert "1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1" in layout.get_content().replace(" ", "")
|
||||
|
||||
debug.click(buttons.OK, wait=True)
|
||||
debug.click(buttons.OK, wait=True)
|
||||
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
|
@ -460,7 +460,6 @@ def test_sign_tx_spend(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_output(0),
|
||||
request_output(1),
|
||||
@ -536,7 +535,6 @@ def test_sign_tx_migration(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_2cc3c1),
|
||||
request_input(0, TXHASH_2cc3c1),
|
||||
|
@ -81,7 +81,6 @@ def test_send_bch_change(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_bc37c2),
|
||||
request_input(0, TXHASH_bc37c2),
|
||||
@ -135,7 +134,6 @@ def test_send_bch_nochange(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_502e85),
|
||||
request_input(0, TXHASH_502e85),
|
||||
@ -195,7 +193,6 @@ def test_send_bch_oldaddr(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_502e85),
|
||||
request_input(0, TXHASH_502e85),
|
||||
@ -268,7 +265,6 @@ def test_attack_change_input(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_bd32ff),
|
||||
request_input(0, FAKE_TXHASH_bd32ff),
|
||||
@ -343,7 +339,6 @@ def test_send_bch_multisig_wrongchange(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_062fbd),
|
||||
request_input(0, FAKE_TXHASH_062fbd),
|
||||
@ -414,7 +409,6 @@ def test_send_bch_multisig_change(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_203416),
|
||||
request_input(0, FAKE_TXHASH_203416),
|
||||
@ -454,7 +448,6 @@ def test_send_bch_multisig_change(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_203416),
|
||||
request_input(0, FAKE_TXHASH_203416),
|
||||
|
@ -80,7 +80,6 @@ def test_send_bitcoin_gold_change(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_6f0398),
|
||||
request_input(0, FAKE_TXHASH_6f0398),
|
||||
@ -135,7 +134,6 @@ def test_send_bitcoin_gold_nochange(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_6f0398),
|
||||
request_input(0, FAKE_TXHASH_6f0398),
|
||||
@ -207,7 +205,6 @@ def test_attack_change_input(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_6f0398),
|
||||
request_input(0, FAKE_TXHASH_6f0398),
|
||||
@ -269,7 +266,6 @@ def test_send_btg_multisig_change(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_a63dbe),
|
||||
request_input(0, FAKE_TXHASH_a63dbe),
|
||||
@ -309,7 +305,6 @@ def test_send_btg_multisig_change(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_a63dbe),
|
||||
request_input(0, FAKE_TXHASH_a63dbe),
|
||||
@ -367,7 +362,6 @@ def test_send_p2sh(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_db7239),
|
||||
request_input(0, FAKE_TXHASH_db7239),
|
||||
@ -420,7 +414,6 @@ def test_send_p2sh_witness_change(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_db7239),
|
||||
request_input(0, FAKE_TXHASH_db7239),
|
||||
@ -481,7 +474,6 @@ def test_send_multisig_1(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_7f1f6b),
|
||||
request_input(0, FAKE_TXHASH_7f1f6b),
|
||||
@ -505,7 +497,6 @@ def test_send_multisig_1(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_7f1f6b),
|
||||
request_input(0, FAKE_TXHASH_7f1f6b),
|
||||
|
@ -65,7 +65,6 @@ def test_send_dash(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(inp1.prev_hash),
|
||||
request_input(0, inp1.prev_hash),
|
||||
@ -115,7 +114,6 @@ def test_send_dash_dip2_input(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(inp1.prev_hash),
|
||||
request_input(0, inp1.prev_hash),
|
||||
|
@ -81,7 +81,6 @@ def test_send_decred(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.FeeOverThreshold),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_4d8acd),
|
||||
request_input(0, FAKE_TXHASH_4d8acd),
|
||||
@ -140,7 +139,6 @@ def test_purchase_ticket_decred(client: Client):
|
||||
request_output(1),
|
||||
request_output(2),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_4d8acd),
|
||||
request_input(0, FAKE_TXHASH_4d8acd),
|
||||
@ -205,7 +203,6 @@ def test_spend_from_stake_generation_and_revocation_decred(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_f8e2f2),
|
||||
request_input(0, FAKE_TXHASH_f8e2f2),
|
||||
@ -290,7 +287,6 @@ def test_send_decred_change(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_4d8acd),
|
||||
request_input(0, FAKE_TXHASH_4d8acd),
|
||||
@ -397,7 +393,6 @@ def test_decred_multisig_change(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_9ac7d2),
|
||||
request_input(0, FAKE_TXHASH_9ac7d2),
|
||||
|
@ -70,7 +70,6 @@ def test_one_one_fee_sapling(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_2807c),
|
||||
request_input(0, TXHASH_2807c),
|
||||
@ -139,7 +138,6 @@ def test_one_one_rewards_claim(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_7b28bd),
|
||||
request_input(0, TXHASH_7b28bd),
|
||||
|
@ -89,7 +89,6 @@ def test_2_of_3(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_6b07c1),
|
||||
request_input(0, TXHASH_6b07c1),
|
||||
|
@ -170,7 +170,6 @@ def _responses(
|
||||
|
||||
resp += [
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(INP1.prev_hash),
|
||||
request_input(0, INP1.prev_hash),
|
||||
|
@ -73,7 +73,6 @@ def test_opreturn(client: Client):
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_4075a1),
|
||||
request_input(0, TXHASH_4075a1),
|
||||
|
@ -20,7 +20,7 @@ import pytest
|
||||
|
||||
from trezorlib import btc, device, messages
|
||||
from trezorlib.debuglink import TrezorClientDebugLink as Client
|
||||
from trezorlib.exceptions import TrezorFailure
|
||||
from trezorlib.exceptions import Cancelled, TrezorFailure
|
||||
from trezorlib.tools import H_, parse_path
|
||||
|
||||
from ...tx_cache import TxCache
|
||||
@ -52,6 +52,9 @@ TXHASH_d2dcda = bytes.fromhex(
|
||||
TXHASH_e5040e = bytes.fromhex(
|
||||
"e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd"
|
||||
)
|
||||
TXHASH_ec5194 = bytes.fromhex(
|
||||
"ec519494bea3746bd5fbdd7a15dac5049a873fa674c67e596d46505b9b835425"
|
||||
)
|
||||
TXHASH_50f6f1 = bytes.fromhex(
|
||||
"50f6f1209ca92d7359564be803cb2c932cde7d370f7cee50fd1fad6790f6206d"
|
||||
)
|
||||
@ -87,6 +90,9 @@ TXHASH_1f326f = bytes.fromhex(
|
||||
)
|
||||
|
||||
|
||||
CORNER_BUTTON = (215, 25)
|
||||
|
||||
|
||||
def test_one_one_fee(client: Client):
|
||||
# input tx: 0dac366fd8a67b2a89fbb0d31086e7acded7a5bbf9ef9daa935bc873229ef5b5
|
||||
|
||||
@ -112,7 +118,6 @@ def test_one_one_fee(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_0dac36),
|
||||
request_input(0, TXHASH_0dac36),
|
||||
@ -168,7 +173,6 @@ def test_testnet_one_two_fee(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_e5040e),
|
||||
request_input(0, TXHASH_e5040e),
|
||||
@ -220,7 +224,6 @@ def test_testnet_fee_high_warning(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.FeeOverThreshold),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_25fee5),
|
||||
request_input(0, TXHASH_25fee5),
|
||||
@ -274,7 +277,6 @@ def test_one_two_fee(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_50f6f1),
|
||||
request_input(0, TXHASH_50f6f1),
|
||||
@ -340,7 +342,6 @@ def test_one_three_fee(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(2),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_bb5169),
|
||||
request_input(0, TXHASH_bb5169),
|
||||
@ -410,7 +411,6 @@ def test_two_two(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_ac4ca0),
|
||||
request_input(0, TXHASH_ac4ca0),
|
||||
@ -558,7 +558,6 @@ def test_lots_of_change(client: Client):
|
||||
+ [
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_892d06),
|
||||
request_input(0, TXHASH_892d06),
|
||||
@ -608,7 +607,6 @@ def test_fee_high_warning(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.FeeOverThreshold),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_1f326f),
|
||||
request_input(0, TXHASH_1f326f),
|
||||
@ -666,7 +664,6 @@ def test_fee_high_hardfail(client: Client):
|
||||
B.ConfirmOutput,
|
||||
B.FeeOverThreshold,
|
||||
B.SignTx,
|
||||
B.SignTx,
|
||||
):
|
||||
br = yield
|
||||
assert br.code == expected
|
||||
@ -743,7 +740,6 @@ def test_p2sh(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_58d56a),
|
||||
request_input(0, TXHASH_58d56a),
|
||||
@ -834,7 +830,6 @@ def test_attack_change_outputs(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_ac4ca0),
|
||||
request_input(0, TXHASH_ac4ca0),
|
||||
@ -1003,7 +998,6 @@ def test_attack_change_input_address(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_d2dcda),
|
||||
request_input(0, TXHASH_d2dcda),
|
||||
@ -1054,7 +1048,6 @@ def test_spend_coinbase(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(FAKE_TXHASH_005f6f),
|
||||
request_input(0, FAKE_TXHASH_005f6f),
|
||||
@ -1116,7 +1109,6 @@ def test_two_changes(client: Client):
|
||||
request_output(1),
|
||||
request_output(2),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_e5040e),
|
||||
request_input(0, TXHASH_e5040e),
|
||||
@ -1176,7 +1168,6 @@ def test_change_on_main_chain_allowed(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_e5040e),
|
||||
request_input(0, TXHASH_e5040e),
|
||||
@ -1440,7 +1431,6 @@ def test_lock_time(client: Client, lock_time, sequence):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_0dac36),
|
||||
request_input(0, TXHASH_0dac36),
|
||||
@ -1551,8 +1541,6 @@ def test_lock_time_datetime(client: Client, lock_time_str):
|
||||
|
||||
yield # confirm transaction
|
||||
client.debug.press_yes()
|
||||
yield # confirm transaction
|
||||
client.debug.press_yes()
|
||||
|
||||
lock_time_naive = datetime.strptime(lock_time_str, "%Y-%m-%d %H:%M:%S")
|
||||
lock_time_utc = lock_time_naive.replace(tzinfo=timezone.utc)
|
||||
@ -1570,3 +1558,158 @@ def test_lock_time_datetime(client: Client, lock_time_str):
|
||||
lock_time=lock_time_timestamp,
|
||||
prev_txes=TX_CACHE_MAINNET,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip_t1(reason="Cannot test layouts on T1")
|
||||
def test_information(client: Client):
|
||||
# input tx: 0dac366fd8a67b2a89fbb0d31086e7acded7a5bbf9ef9daa935bc873229ef5b5
|
||||
|
||||
inp1 = messages.TxInputType(
|
||||
address_n=parse_path("m/44h/0h/5h/0/9"), # 1H2CRJBrDMhkvCGZMW7T4oQwYbL8eVuh7p
|
||||
amount=63_988,
|
||||
prev_hash=TXHASH_0dac36,
|
||||
prev_index=0,
|
||||
sequence=0xFFFF_FFFE,
|
||||
)
|
||||
|
||||
out1 = messages.TxOutputType(
|
||||
address="13Hbso8zgV5Wmqn3uA7h3QVtmPzs47wcJ7",
|
||||
amount=50_248,
|
||||
script_type=messages.OutputScriptType.PAYTOADDRESS,
|
||||
)
|
||||
|
||||
def input_flow():
|
||||
yield # confirm output
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_yes()
|
||||
yield # confirm output
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_yes()
|
||||
|
||||
yield # confirm transaction
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_info()
|
||||
|
||||
layout = client.debug.wait_layout()
|
||||
content = layout.get_content().lower()
|
||||
assert "sending from" in content
|
||||
assert "legacy #6" in content
|
||||
assert "fee rate" in content
|
||||
assert "71.56 sat" in content
|
||||
client.debug.click(CORNER_BUTTON, wait=True)
|
||||
client.debug.press_yes()
|
||||
|
||||
with client:
|
||||
client.set_input_flow(input_flow)
|
||||
client.watch_layout(True)
|
||||
|
||||
btc.sign_tx(
|
||||
client,
|
||||
"Bitcoin",
|
||||
[inp1],
|
||||
[out1],
|
||||
prev_txes=TX_CACHE_MAINNET,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip_t1(reason="Cannot test layouts on T1")
|
||||
def test_information_mixed(client: Client):
|
||||
inp1 = messages.TxInputType(
|
||||
address_n=parse_path("m/44h/1h/0h/0/0"), # mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q
|
||||
amount=31_000_000,
|
||||
prev_hash=TXHASH_e5040e,
|
||||
prev_index=0,
|
||||
)
|
||||
inp2 = messages.TxInputType(
|
||||
# tb1pn2d0yjeedavnkd8z8lhm566p0f2utm3lgvxrsdehnl94y34txmts5s7t4c
|
||||
address_n=parse_path("m/86h/1h/0h/1/0"),
|
||||
amount=4_600,
|
||||
prev_hash=TXHASH_ec5194,
|
||||
prev_index=0,
|
||||
script_type=messages.InputScriptType.SPENDTAPROOT,
|
||||
)
|
||||
out1 = messages.TxOutputType(
|
||||
address="msj42CCGruhRsFrGATiUuh25dtxYtnpbTx",
|
||||
amount=31_000_000,
|
||||
script_type=messages.OutputScriptType.PAYTOADDRESS,
|
||||
)
|
||||
|
||||
def input_flow():
|
||||
yield # confirm output
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_yes()
|
||||
yield # confirm output
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_yes()
|
||||
|
||||
yield # confirm transaction
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_info()
|
||||
|
||||
layout = client.debug.wait_layout()
|
||||
content = layout.get_content().lower()
|
||||
assert "sending from" in content
|
||||
assert "multiple accounts" in content
|
||||
assert "fee rate" in content
|
||||
assert "18.33 sat" in content
|
||||
client.debug.click(CORNER_BUTTON, wait=True)
|
||||
client.debug.press_yes()
|
||||
|
||||
with client:
|
||||
client.set_input_flow(input_flow)
|
||||
client.watch_layout(True)
|
||||
|
||||
btc.sign_tx(
|
||||
client,
|
||||
"Testnet",
|
||||
[inp1, inp2],
|
||||
[out1],
|
||||
prev_txes=TX_CACHE_TESTNET,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skip_t1(reason="Cannot test layouts on T1")
|
||||
def test_information_cancel(client: Client):
|
||||
# input tx: 0dac366fd8a67b2a89fbb0d31086e7acded7a5bbf9ef9daa935bc873229ef5b5
|
||||
|
||||
inp1 = messages.TxInputType(
|
||||
address_n=parse_path("m/44h/0h/5h/0/9"), # 1H2CRJBrDMhkvCGZMW7T4oQwYbL8eVuh7p
|
||||
amount=63_988,
|
||||
prev_hash=TXHASH_0dac36,
|
||||
prev_index=0,
|
||||
sequence=0xFFFF_FFFE,
|
||||
)
|
||||
|
||||
out1 = messages.TxOutputType(
|
||||
address="13Hbso8zgV5Wmqn3uA7h3QVtmPzs47wcJ7",
|
||||
amount=50_248,
|
||||
script_type=messages.OutputScriptType.PAYTOADDRESS,
|
||||
)
|
||||
|
||||
def input_flow():
|
||||
yield # confirm output
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_yes()
|
||||
yield # confirm output
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_yes()
|
||||
|
||||
yield # confirm transaction
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_info()
|
||||
|
||||
client.debug.wait_layout()
|
||||
client.debug.click(CORNER_BUTTON, wait=True)
|
||||
client.debug.press_no()
|
||||
|
||||
with client, pytest.raises(Cancelled):
|
||||
client.set_input_flow(input_flow)
|
||||
client.watch_layout(True)
|
||||
|
||||
btc.sign_tx(
|
||||
client,
|
||||
"Bitcoin",
|
||||
[inp1],
|
||||
[out1],
|
||||
prev_txes=TX_CACHE_MAINNET,
|
||||
)
|
||||
|
@ -76,7 +76,6 @@ def test_send_p2sh(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_20912f),
|
||||
request_input(0, TXHASH_20912f),
|
||||
@ -129,7 +128,6 @@ def test_send_p2sh_change(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_20912f),
|
||||
request_input(0, TXHASH_20912f),
|
||||
@ -185,7 +183,6 @@ def test_testnet_segwit_big_amount(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(prev_hash),
|
||||
request_input(0, prev_hash),
|
||||
@ -243,7 +240,6 @@ def test_send_multisig_1(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_338e2d),
|
||||
request_input(0, TXHASH_338e2d),
|
||||
@ -317,7 +313,6 @@ def test_attack_change_input_address(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_20912f),
|
||||
request_input(0, TXHASH_20912f),
|
||||
@ -395,7 +390,6 @@ def test_attack_mixed_inputs(client: Client):
|
||||
(tt, messages.ButtonRequest(code=messages.ButtonRequestType.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=messages.ButtonRequestType.FeeOverThreshold),
|
||||
messages.ButtonRequest(code=messages.ButtonRequestType.SignTx),
|
||||
(tt, messages.ButtonRequest(code=messages.ButtonRequestType.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_e5040e),
|
||||
request_input(0, TXHASH_e5040e),
|
||||
|
@ -92,7 +92,6 @@ def test_send_p2sh(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_20912f),
|
||||
request_input(0, TXHASH_20912f),
|
||||
@ -147,7 +146,6 @@ def test_send_p2sh_change(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_20912f),
|
||||
request_input(0, TXHASH_20912f),
|
||||
@ -204,7 +202,6 @@ def test_send_native(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_b36780),
|
||||
request_input(0, TXHASH_b36780),
|
||||
@ -291,7 +288,6 @@ def test_send_native_change(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_fcb3f5),
|
||||
request_input(0, TXHASH_fcb3f5),
|
||||
@ -366,7 +362,6 @@ def test_send_both(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_65047a),
|
||||
request_input(0, TXHASH_65047a),
|
||||
@ -443,7 +438,6 @@ def test_send_multisig_1(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_b9abfa),
|
||||
request_input(0, TXHASH_b9abfa),
|
||||
@ -522,7 +516,6 @@ def test_send_multisig_2(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_b9abfa),
|
||||
request_input(0, TXHASH_b9abfa),
|
||||
@ -609,7 +602,6 @@ def test_send_multisig_3_change(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_b9abfa),
|
||||
request_input(0, TXHASH_b9abfa),
|
||||
@ -697,7 +689,6 @@ def test_send_multisig_4_change(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_b9abfa),
|
||||
request_input(0, TXHASH_b9abfa),
|
||||
@ -805,7 +796,6 @@ def test_multisig_mismatch_inputs_single(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_1c022d),
|
||||
request_input(0, TXHASH_1c022d),
|
||||
|
@ -86,7 +86,6 @@ def test_send_p2tr(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_output(0),
|
||||
request_input(0),
|
||||
@ -144,7 +143,6 @@ def test_send_two_with_change(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_input(1),
|
||||
request_output(0),
|
||||
@ -249,7 +247,6 @@ def test_send_mixed(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
# verify inputs
|
||||
request_input(0),
|
||||
request_meta(TXHASH_8c3ea7),
|
||||
@ -368,7 +365,6 @@ def test_attack_script_type(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_input(1),
|
||||
request_output(0),
|
||||
|
@ -114,7 +114,6 @@ def test_one_one_fee_sapling(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_e38206),
|
||||
request_input(0, TXHASH_e38206),
|
||||
|
@ -148,7 +148,6 @@ def test_data_streaming(client: Client):
|
||||
messages.ButtonRequest(code=messages.ButtonRequestType.SignTx),
|
||||
(tt, messages.ButtonRequest(code=messages.ButtonRequestType.Other)),
|
||||
(tt, messages.ButtonRequest(code=messages.ButtonRequestType.SignTx)),
|
||||
(tt, messages.ButtonRequest(code=messages.ButtonRequestType.SignTx)),
|
||||
message_filters.EthereumTxRequest(
|
||||
data_length=1_024,
|
||||
signature_r=None,
|
||||
|
@ -365,7 +365,6 @@ def test_signtx(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_meta(TXHASH_50f6f1),
|
||||
request_input(0, TXHASH_50f6f1),
|
||||
|
@ -103,7 +103,6 @@ def test_spend_v4_input(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_output(0),
|
||||
request_finished(),
|
||||
@ -153,7 +152,6 @@ def test_send_to_multisig(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_output(0),
|
||||
request_finished(),
|
||||
@ -202,7 +200,6 @@ def test_spend_v5_input(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_output(0),
|
||||
request_finished(),
|
||||
@ -258,7 +255,6 @@ def test_one_two(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_output(0),
|
||||
request_output(1),
|
||||
@ -318,7 +314,6 @@ def test_unified_address(client: Client):
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
request_output(1),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_output(0),
|
||||
request_output(1),
|
||||
@ -495,7 +490,6 @@ def test_spend_multisig(client: Client):
|
||||
messages.ButtonRequest(code=B.ConfirmOutput),
|
||||
(tt, messages.ButtonRequest(code=B.ConfirmOutput)),
|
||||
messages.ButtonRequest(code=B.SignTx),
|
||||
(tt, messages.ButtonRequest(code=B.SignTx)),
|
||||
request_input(0),
|
||||
request_output(0),
|
||||
request_finished(),
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user