feat(core/ui): sending transaction style update

[no changelog]
pull/2934/head
Martin Milata 1 year ago
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(
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",
layout = RustLayout(
trezorui2.confirm_total(
title=title,
items=[
(total_label, total_amount),
(fee_label, fee_amount),
],
info_button=account_label is not None,
)
)
await confirm_value(
await button_request(
ctx,
title,
total_amount,
f"From {account_label}\r\n{total_label}" if account_label else total_label,
br_type,
br_code,
hold=True,
pages=layout.page_count(),
)
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…
Cancel
Save