mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 22:38:08 +00:00
feat(core/rust): add account and address labels into send flow
[no changelog]
This commit is contained in:
parent
570ffe2c0d
commit
64236e699f
@ -16,10 +16,12 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR___dict__;
|
||||
MP_QSTR___name__;
|
||||
MP_QSTR_account;
|
||||
MP_QSTR_account_label;
|
||||
MP_QSTR_accounts;
|
||||
MP_QSTR_action;
|
||||
MP_QSTR_active;
|
||||
MP_QSTR_address;
|
||||
MP_QSTR_address_label;
|
||||
MP_QSTR_address_title;
|
||||
MP_QSTR_allow_cancel;
|
||||
MP_QSTR_amount;
|
||||
|
@ -522,6 +522,7 @@ extern "C" fn new_confirm_modify_output(n_args: usize, args: *const Obj, kwargs:
|
||||
extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = |_args: &[Obj], kwargs: &Map| {
|
||||
let address: StrBuffer = kwargs.get(Qstr::MP_QSTR_address)?.try_into()?;
|
||||
let address_label: StrBuffer = kwargs.get(Qstr::MP_QSTR_address_label)?.try_into()?;
|
||||
let amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount)?.try_into()?;
|
||||
let address_title: StrBuffer = kwargs.get(Qstr::MP_QSTR_address_title)?.try_into()?;
|
||||
let address_title_clone = address_title.clone();
|
||||
@ -532,23 +533,27 @@ extern "C" fn new_confirm_output(n_args: usize, args: *const Obj, kwargs: *mut M
|
||||
match page_index {
|
||||
0 => {
|
||||
// RECIPIENT + address
|
||||
let btn_layout = ButtonLayout::cancel_none_text("CONFIRM".into());
|
||||
let btn_layout = ButtonLayout::cancel_none_text("CONTINUE".into());
|
||||
let btn_actions = ButtonActions::cancel_none_next();
|
||||
// Not putting hyphens in the address
|
||||
let ops = OpTextLayout::new(theme::TEXT_MONO)
|
||||
.line_breaking(LineBreaking::BreakWordsNoHyphen)
|
||||
.text_mono(address.clone());
|
||||
let formatted = FormattedText::new(ops);
|
||||
// Not putting hyphens in the address.
|
||||
// Potentially adding address label in different font.
|
||||
let mut ops = OpTextLayout::new(theme::TEXT_MONO)
|
||||
.line_breaking(LineBreaking::BreakWordsNoHyphen);
|
||||
if !address_label.is_empty() {
|
||||
ops = ops.text_normal(address_label.clone()).newline();
|
||||
}
|
||||
ops = ops.text_mono(address.clone());
|
||||
let formatted =
|
||||
FormattedText::new(ops).vertically_aligned(geometry::Alignment::Center);
|
||||
Page::new(btn_layout, btn_actions, formatted).with_title(address_title.clone())
|
||||
}
|
||||
1 => {
|
||||
// AMOUNT + amount
|
||||
let btn_layout = ButtonLayout::up_arrow_none_text("CONFIRM".into());
|
||||
let btn_actions = ButtonActions::prev_none_confirm();
|
||||
let ops = OpTextLayout::new(theme::TEXT_MONO)
|
||||
.newline()
|
||||
.text_mono(amount.clone());
|
||||
let formatted = FormattedText::new(ops);
|
||||
let ops = OpTextLayout::new(theme::TEXT_MONO).text_mono(amount.clone());
|
||||
let formatted =
|
||||
FormattedText::new(ops).vertically_aligned(geometry::Alignment::Center);
|
||||
Page::new(btn_layout, btn_actions, formatted).with_title(amount_title.clone())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@ -569,34 +574,75 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
|
||||
let fee_rate_amount: Option<StrBuffer> = kwargs
|
||||
.get(Qstr::MP_QSTR_fee_rate_amount)?
|
||||
.try_into_option()?;
|
||||
let account_label: Option<StrBuffer> =
|
||||
kwargs.get(Qstr::MP_QSTR_account_label)?.try_into_option()?;
|
||||
let total_label: StrBuffer = kwargs.get(Qstr::MP_QSTR_total_label)?.try_into()?;
|
||||
let fee_label: StrBuffer = kwargs.get(Qstr::MP_QSTR_fee_label)?.try_into()?;
|
||||
|
||||
let get_page = move |page_index| {
|
||||
// Total amount + fee
|
||||
assert!(page_index == 0);
|
||||
match page_index {
|
||||
0 => {
|
||||
// Total amount + fee
|
||||
let btn_layout = ButtonLayout::cancel_armed_info("CONFIRM".into());
|
||||
let btn_actions = ButtonActions::cancel_confirm_next();
|
||||
|
||||
let btn_layout = ButtonLayout::cancel_none_htc("HOLD TO CONFIRM".into());
|
||||
let btn_actions = ButtonActions::cancel_none_confirm();
|
||||
let ops = OpTextLayout::new(theme::TEXT_MONO)
|
||||
.text_bold(total_label.clone())
|
||||
.newline()
|
||||
.text_mono(total_amount.clone())
|
||||
.newline()
|
||||
.newline()
|
||||
.text_bold(fee_label.clone())
|
||||
.newline()
|
||||
.text_mono(fee_amount.clone());
|
||||
|
||||
let mut ops = OpTextLayout::new(theme::TEXT_MONO)
|
||||
.text_bold(total_label.clone())
|
||||
.newline()
|
||||
.text_mono(total_amount.clone())
|
||||
.newline()
|
||||
.text_bold(fee_label.clone())
|
||||
.newline()
|
||||
.text_mono(fee_amount.clone());
|
||||
let formatted = FormattedText::new(ops);
|
||||
Page::new(btn_layout, btn_actions, formatted)
|
||||
}
|
||||
1 => {
|
||||
// Fee rate info
|
||||
let btn_layout = ButtonLayout::arrow_none_arrow();
|
||||
let btn_actions = ButtonActions::prev_none_next();
|
||||
|
||||
// Fee rate amount might not be there
|
||||
if let Some(fee_rate_amount) = fee_rate_amount.clone() {
|
||||
ops = ops.newline().text_mono(fee_rate_amount)
|
||||
let fee_rate_amount = fee_rate_amount.clone().unwrap_or_default();
|
||||
|
||||
let ops = OpTextLayout::new(theme::TEXT_MONO)
|
||||
.text_bold("FEE INFORMATION".into())
|
||||
.newline()
|
||||
.newline()
|
||||
.newline_half()
|
||||
.text_bold("Fee rate:".into())
|
||||
.newline()
|
||||
.text_mono(fee_rate_amount);
|
||||
|
||||
let formatted = FormattedText::new(ops);
|
||||
Page::new(btn_layout, btn_actions, formatted)
|
||||
}
|
||||
2 => {
|
||||
// Wallet and account info
|
||||
let btn_layout = ButtonLayout::arrow_none_none();
|
||||
let btn_actions = ButtonActions::prev_none_none();
|
||||
|
||||
let account_label = account_label.clone().unwrap_or_default();
|
||||
|
||||
// TODO: include wallet info when available
|
||||
|
||||
let ops = OpTextLayout::new(theme::TEXT_MONO)
|
||||
.text_bold("SENDING FROM".into())
|
||||
.newline()
|
||||
.newline()
|
||||
.newline_half()
|
||||
.text_bold("Account:".into())
|
||||
.newline()
|
||||
.text_mono(account_label);
|
||||
|
||||
let formatted = FormattedText::new(ops);
|
||||
Page::new(btn_layout, btn_actions, formatted)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
|
||||
let formatted = FormattedText::new(ops);
|
||||
Page::new(btn_layout, btn_actions, formatted)
|
||||
};
|
||||
let pages = FlowPages::new(get_page, 1);
|
||||
let pages = FlowPages::new(get_page, 3);
|
||||
|
||||
let obj = LayoutObj::new(Flow::new(pages))?;
|
||||
Ok(obj.into())
|
||||
@ -612,7 +658,7 @@ extern "C" fn new_confirm_address(n_args: usize, args: *const Obj, kwargs: *mut
|
||||
let get_page = move |page_index| {
|
||||
assert!(page_index == 0);
|
||||
|
||||
let btn_layout = ButtonLayout::cancel_armed_text("CONFIRM".into(), "i".into());
|
||||
let btn_layout = ButtonLayout::cancel_armed_info("CONFIRM".into());
|
||||
let btn_actions = ButtonActions::cancel_confirm_info();
|
||||
let ops = OpTextLayout::new(theme::TEXT_MONO)
|
||||
.line_breaking(LineBreaking::BreakWordsNoHyphen)
|
||||
@ -1354,6 +1400,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// def confirm_output(
|
||||
/// *,
|
||||
/// address: str,
|
||||
/// address_label: str,
|
||||
/// amount: str,
|
||||
/// address_title: str,
|
||||
/// amount_title: str,
|
||||
@ -1366,6 +1413,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// total_amount: str,
|
||||
/// fee_amount: str,
|
||||
/// fee_rate_amount: str | None,
|
||||
/// account_label: str | None,
|
||||
/// total_label: str,
|
||||
/// fee_label: str,
|
||||
/// ) -> object:
|
||||
|
@ -123,6 +123,7 @@ def confirm_modify_output(
|
||||
def confirm_output(
|
||||
*,
|
||||
address: str,
|
||||
address_label: str,
|
||||
amount: str,
|
||||
address_title: str,
|
||||
amount_title: str,
|
||||
@ -136,6 +137,7 @@ def confirm_total(
|
||||
total_amount: str,
|
||||
fee_amount: str,
|
||||
fee_rate_amount: str | None,
|
||||
account_label: str | None,
|
||||
total_label: str,
|
||||
fee_label: str,
|
||||
) -> object:
|
||||
|
@ -693,15 +693,13 @@ async def confirm_output(
|
||||
)
|
||||
amount_title = "AMOUNT" if output_index is None else f"AMOUNT #{output_index + 1}"
|
||||
|
||||
# TODO: implement `hold` to be consistent with `TT`?
|
||||
# TODO: incorporate label? - label = f" ({address_label})" if address_label else ""
|
||||
|
||||
await raise_if_not_confirmed(
|
||||
interact(
|
||||
ctx,
|
||||
RustLayout(
|
||||
trezorui2.confirm_output(
|
||||
address=address,
|
||||
address_label=address_label or "",
|
||||
address_title=address_title,
|
||||
amount_title=amount_title,
|
||||
amount=amount,
|
||||
@ -944,13 +942,11 @@ async def confirm_total(
|
||||
fee_rate_amount: str | None = None,
|
||||
title: str = "SENDING",
|
||||
total_label: str = "TOTAL AMOUNT",
|
||||
fee_label: str = "INCLUDING FEE",
|
||||
fee_label: str = "Including fee:",
|
||||
account_label: str | None = None,
|
||||
br_type: str = "confirm_total",
|
||||
br_code: ButtonRequestType = ButtonRequestType.SignTx,
|
||||
) -> None:
|
||||
# TODO: incorporate account_label
|
||||
# f"From {account_label}\r\n{total_label}" if account_label else total_label,
|
||||
await raise_if_not_confirmed(
|
||||
interact(
|
||||
ctx,
|
||||
@ -960,8 +956,9 @@ async def confirm_total(
|
||||
total_amount=total_amount, # type: ignore [No parameter named]
|
||||
fee_amount=fee_amount, # type: ignore [No parameter named]
|
||||
fee_rate_amount=fee_rate_amount, # type: ignore [No parameter named]
|
||||
account_label=account_label, # type: ignore [No parameter named]
|
||||
total_label=total_label.upper(), # type: ignore [No parameter named]
|
||||
fee_label=fee_label.upper(), # type: ignore [No parameter named]
|
||||
fee_label=fee_label, # type: ignore [No parameter named]
|
||||
)
|
||||
),
|
||||
br_type,
|
||||
|
@ -104,7 +104,6 @@ def test_autolock_interrupts_signing(device_handler: "BackgroundDeviceHandler"):
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
assert "Total amount: 0.0039 BTC" in layout.text_content()
|
||||
elif debug.model == "R":
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right(wait=True)
|
||||
layout = debug.press_right(wait=True)
|
||||
assert "TOTAL AMOUNT 0.0039 BTC" in layout.text_content()
|
||||
@ -165,7 +164,7 @@ def test_autolock_does_not_interrupt_signing(device_handler: "BackgroundDeviceHa
|
||||
if debug.model == "T":
|
||||
debug.click(buttons.OK)
|
||||
elif debug.model == "R":
|
||||
debug.press_right_htc(1200)
|
||||
debug.press_middle()
|
||||
|
||||
signatures, tx = device_handler.result()
|
||||
assert len(signatures) == 1
|
||||
|
@ -27,6 +27,10 @@ from ...input_flows import (
|
||||
InputFlowLockTimeBlockHeight,
|
||||
InputFlowLockTimeDatetime,
|
||||
InputFlowSignTxHighFee,
|
||||
InputFlowSignTxInformation,
|
||||
InputFlowSignTxInformationCancel,
|
||||
InputFlowSignTxInformationMixed,
|
||||
InputFlowSignTxInformationReplacement,
|
||||
)
|
||||
from ...tx_cache import TxCache
|
||||
from .signtx import (
|
||||
@ -1524,7 +1528,6 @@ def test_lock_time_datetime(client: Client, lock_time_str: str):
|
||||
|
||||
|
||||
@pytest.mark.skip_t1(reason="Cannot test layouts on T1")
|
||||
@pytest.mark.skip_tr(reason="Not implemented yet")
|
||||
def test_information(client: Client):
|
||||
# input tx: 0dac366fd8a67b2a89fbb0d31086e7acded7a5bbf9ef9daa935bc873229ef5b5
|
||||
|
||||
@ -1542,29 +1545,9 @@ def test_information(client: Client):
|
||||
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.text_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)
|
||||
IF = InputFlowSignTxInformation(client)
|
||||
client.set_input_flow(IF.get())
|
||||
client.watch_layout(True)
|
||||
|
||||
btc.sign_tx(
|
||||
@ -1577,7 +1560,6 @@ def test_information(client: Client):
|
||||
|
||||
|
||||
@pytest.mark.skip_t1(reason="Cannot test layouts on T1")
|
||||
@pytest.mark.skip_tr(reason="Not implemented yet")
|
||||
def test_information_mixed(client: Client):
|
||||
inp1 = messages.TxInputType(
|
||||
address_n=parse_path("m/44h/1h/0h/0/0"), # mvbu1Gdy8SUjTenqerxUaZyYjmveZvt33q
|
||||
@ -1599,29 +1581,9 @@ def test_information_mixed(client: Client):
|
||||
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.text_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)
|
||||
IF = InputFlowSignTxInformationMixed(client)
|
||||
client.set_input_flow(IF.get())
|
||||
client.watch_layout(True)
|
||||
|
||||
btc.sign_tx(
|
||||
@ -1634,7 +1596,6 @@ def test_information_mixed(client: Client):
|
||||
|
||||
|
||||
@pytest.mark.skip_t1(reason="Cannot test layouts on T1")
|
||||
@pytest.mark.skip_tr(reason="Not implemented yet")
|
||||
def test_information_cancel(client: Client):
|
||||
# input tx: 0dac366fd8a67b2a89fbb0d31086e7acded7a5bbf9ef9daa935bc873229ef5b5
|
||||
|
||||
@ -1652,24 +1613,9 @@ def test_information_cancel(client: Client):
|
||||
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)
|
||||
IF = InputFlowSignTxInformationCancel(client)
|
||||
client.set_input_flow(IF.get())
|
||||
client.watch_layout(True)
|
||||
|
||||
btc.sign_tx(
|
||||
@ -1682,7 +1628,6 @@ def test_information_cancel(client: Client):
|
||||
|
||||
|
||||
@pytest.mark.skip_t1(reason="Cannot test layouts on T1")
|
||||
@pytest.mark.skip_tr(reason="Input flow different on TR")
|
||||
def test_information_replacement(client: Client):
|
||||
# Use the change output and an external output to bump the fee.
|
||||
# Originally fee was 3780, now 108060 (94280 from change and 10000 from external).
|
||||
@ -1715,25 +1660,9 @@ def test_information_replacement(client: Client):
|
||||
orig_index=0,
|
||||
)
|
||||
|
||||
def input_flow():
|
||||
yield # confirm txid
|
||||
client.debug.press_yes()
|
||||
yield # confirm address
|
||||
client.debug.press_yes()
|
||||
# go back to address
|
||||
client.debug.press_no()
|
||||
# confirm address
|
||||
client.debug.press_yes()
|
||||
yield # confirm amount
|
||||
client.debug.press_yes()
|
||||
|
||||
yield # transaction summary, press info
|
||||
client.debug.press_info(wait=True)
|
||||
client.debug.click(CORNER_BUTTON, wait=True)
|
||||
client.debug.press_yes()
|
||||
|
||||
with client:
|
||||
client.set_input_flow(input_flow)
|
||||
IF = InputFlowSignTxInformationReplacement(client)
|
||||
client.set_input_flow(IF.get())
|
||||
client.watch_layout(True)
|
||||
|
||||
btc.sign_tx(
|
||||
|
@ -446,6 +446,140 @@ class InputFlowSignTxHighFee(InputFlowBase):
|
||||
yield from self.go_through_all_screens(screens)
|
||||
|
||||
|
||||
def sign_tx_go_to_info(client: Client) -> Generator[None, None, str]:
|
||||
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.text_content().lower()
|
||||
|
||||
client.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
|
||||
return content
|
||||
|
||||
|
||||
def sign_tx_go_to_info_tr(
|
||||
client: Client,
|
||||
) -> Generator[None, None, str]:
|
||||
yield # confirm output
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_right() # CONTINUE
|
||||
client.debug.wait_layout()
|
||||
client.debug.press_right() # CONFIRM
|
||||
|
||||
screen_texts: list[str] = []
|
||||
|
||||
yield # confirm total
|
||||
layout = client.debug.press_right(wait=True)
|
||||
screen_texts.append(layout.text_content())
|
||||
|
||||
layout = client.debug.press_right(wait=True)
|
||||
screen_texts.append(layout.text_content())
|
||||
|
||||
client.debug.press_left()
|
||||
client.debug.press_left()
|
||||
|
||||
return "\n".join(screen_texts)
|
||||
|
||||
|
||||
class InputFlowSignTxInformation(InputFlowBase):
|
||||
def __init__(self, client: Client):
|
||||
super().__init__(client)
|
||||
|
||||
def assert_content(self, content: str) -> None:
|
||||
assert "sending from" in content
|
||||
assert "legacy #6" in content
|
||||
assert "fee rate" in content
|
||||
assert "71.56 sat" in content
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
content = yield from sign_tx_go_to_info(self.client)
|
||||
self.assert_content(content)
|
||||
self.client.debug.press_yes()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
content = yield from sign_tx_go_to_info_tr(self.client)
|
||||
self.assert_content(content.lower())
|
||||
self.client.debug.press_yes()
|
||||
|
||||
|
||||
class InputFlowSignTxInformationMixed(InputFlowBase):
|
||||
def __init__(self, client: Client):
|
||||
super().__init__(client)
|
||||
|
||||
def assert_content(self, content: str) -> None:
|
||||
assert "sending from" in content
|
||||
assert "multiple accounts" in content
|
||||
assert "fee rate" in content
|
||||
assert "18.33 sat" in content
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
content = yield from sign_tx_go_to_info(self.client)
|
||||
self.assert_content(content)
|
||||
self.client.debug.press_yes()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
content = yield from sign_tx_go_to_info_tr(self.client)
|
||||
self.assert_content(content.lower())
|
||||
self.client.debug.press_yes()
|
||||
|
||||
|
||||
class InputFlowSignTxInformationCancel(InputFlowBase):
|
||||
def __init__(self, client: Client):
|
||||
super().__init__(client)
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield from sign_tx_go_to_info(self.client)
|
||||
self.client.debug.press_no()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield from sign_tx_go_to_info_tr(self.client)
|
||||
self.client.debug.press_left()
|
||||
|
||||
|
||||
class InputFlowSignTxInformationReplacement(InputFlowBase):
|
||||
def __init__(self, client: Client):
|
||||
super().__init__(client)
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield # confirm txid
|
||||
self.client.debug.press_yes()
|
||||
yield # confirm address
|
||||
self.client.debug.press_yes()
|
||||
# go back to address
|
||||
self.client.debug.press_no()
|
||||
# confirm address
|
||||
self.client.debug.press_yes()
|
||||
yield # confirm amount
|
||||
self.client.debug.press_yes()
|
||||
|
||||
yield # transaction summary, press info
|
||||
self.client.debug.press_info(wait=True)
|
||||
self.client.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
self.client.debug.press_yes()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield # confirm txid
|
||||
self.client.debug.press_right()
|
||||
self.client.debug.press_right()
|
||||
yield # confirm address
|
||||
self.client.debug.press_right()
|
||||
self.client.debug.press_right()
|
||||
self.client.debug.press_right()
|
||||
yield # confirm amount
|
||||
self.client.debug.press_right()
|
||||
self.client.debug.press_right()
|
||||
self.client.debug.press_right()
|
||||
|
||||
|
||||
def lock_time_input_flow_tt(
|
||||
debug: DebugLink,
|
||||
layout_assert_func: Callable[[DebugLink], None],
|
||||
|
Loading…
Reference in New Issue
Block a user