mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-04-24 02:59:03 +00:00
feat(core): new design of recovery dialogs
[no changelog]
This commit is contained in:
parent
03f77c50e9
commit
bc502287fc
core
embed/rust
mocks/generated
src
apps/management/recovery_device
storage
trezor/ui/layouts
tests
@ -146,6 +146,7 @@ static void _librust_qstrs(void) {
|
||||
MP_QSTR_value;
|
||||
MP_QSTR_verb;
|
||||
MP_QSTR_verb_cancel;
|
||||
MP_QSTR_warning;
|
||||
MP_QSTR_words;
|
||||
MP_QSTR_wrong_pin;
|
||||
MP_QSTR_xpubs;
|
||||
|
@ -24,8 +24,7 @@ use crate::{
|
||||
},
|
||||
ComponentExt, FormattedText, LineBreaking, Timeout,
|
||||
},
|
||||
display,
|
||||
geometry::{self, Alignment},
|
||||
display, geometry,
|
||||
layout::{
|
||||
obj::{ComponentMsgObj, LayoutObj},
|
||||
result::{CANCELLED, CONFIRMED, INFO},
|
||||
@ -805,33 +804,6 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_show_error(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
|
||||
let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
|
||||
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
||||
|
||||
let get_page = move |page_index| {
|
||||
assert!(page_index == 0);
|
||||
|
||||
let btn_layout = ButtonLayout::none_armed_none(button.clone());
|
||||
let btn_actions = ButtonActions::none_confirm_none();
|
||||
let ops = OpTextLayout::<StrBuffer>::new(theme::TEXT_NORMAL)
|
||||
.alignment(Alignment::Center)
|
||||
.text_bold(title.clone())
|
||||
.newline()
|
||||
.text_normal(description.clone());
|
||||
let formatted = FormattedText::new(ops).vertically_aligned(Alignment::Center);
|
||||
Page::new(btn_layout, btn_actions, formatted)
|
||||
};
|
||||
let pages = FlowPages::new(get_page, 1);
|
||||
|
||||
let obj = LayoutObj::new(Flow::new(pages))?;
|
||||
Ok(obj.into())
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_confirm_modify_fee(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let sign: i32 = kwargs.get(Qstr::MP_QSTR_sign)?.try_into()?;
|
||||
@ -914,7 +886,7 @@ extern "C" fn new_multiple_pages_texts(n_args: usize, args: *const Obj, kwargs:
|
||||
};
|
||||
|
||||
let ops = OpTextLayout::new(theme::TEXT_NORMAL).text_normal(text);
|
||||
let formatted = FormattedText::new(ops).vertically_aligned(Alignment::Center);
|
||||
let formatted = FormattedText::new(ops).vertically_centered();
|
||||
|
||||
Page::new(btn_layout, btn_actions, formatted)
|
||||
};
|
||||
@ -990,6 +962,35 @@ extern "C" fn new_confirm_fido(n_args: usize, args: *const Obj, kwargs: *mut Map
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_show_warning(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
|
||||
let warning: StrBuffer = kwargs.get(Qstr::MP_QSTR_warning)?.try_into()?;
|
||||
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
||||
|
||||
let get_page = move |page_index| {
|
||||
assert!(page_index == 0);
|
||||
|
||||
let btn_layout = ButtonLayout::none_armed_none(button.clone());
|
||||
let btn_actions = ButtonActions::none_confirm_none();
|
||||
let mut ops = OpTextLayout::<StrBuffer>::new(theme::TEXT_NORMAL);
|
||||
ops = ops.alignment(geometry::Alignment::Center);
|
||||
if !warning.is_empty() {
|
||||
ops = ops.text_bold(warning.clone()).newline().newline();
|
||||
}
|
||||
if !description.is_empty() {
|
||||
ops = ops.text_normal(description.clone());
|
||||
}
|
||||
let formatted = FormattedText::new(ops).vertically_centered();
|
||||
Page::new(btn_layout, btn_actions, formatted)
|
||||
};
|
||||
let pages = FlowPages::new(get_page, 1);
|
||||
let obj = LayoutObj::new(Flow::new(pages))?;
|
||||
Ok(obj.into())
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
|
||||
extern "C" fn new_show_info(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()?;
|
||||
@ -1267,16 +1268,32 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
|
||||
let description: StrBuffer = kwargs.get(Qstr::MP_QSTR_description)?.try_into()?;
|
||||
let button: StrBuffer = kwargs.get(Qstr::MP_QSTR_button)?.try_into()?;
|
||||
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?;
|
||||
let show_info: bool = kwargs.get(Qstr::MP_QSTR_show_info)?.try_into()?;
|
||||
|
||||
let paragraphs = Paragraphs::new([Paragraph::new(&theme::TEXT_NORMAL, description)]);
|
||||
let mut paragraphs = ParagraphVecShort::new();
|
||||
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, description));
|
||||
if show_info {
|
||||
let first = "You'll only have to select the first 2-3 letters of each word.";
|
||||
let second =
|
||||
"Position of the cursor will change between entries for enhanced security.";
|
||||
paragraphs
|
||||
.add(Paragraph::new(&theme::TEXT_NORMAL, first.into()))
|
||||
.add(Paragraph::new(&theme::TEXT_NORMAL, second.into()));
|
||||
}
|
||||
|
||||
let title = if dry_run {
|
||||
"SEED CHECK"
|
||||
"BACKUP CHECK"
|
||||
} else {
|
||||
"WALLET RECOVERY"
|
||||
"RECOVER WALLET"
|
||||
};
|
||||
|
||||
content_in_button_page(title.into(), paragraphs, button, Some("".into()), false)
|
||||
content_in_button_page(
|
||||
title.into(),
|
||||
paragraphs.into_paragraphs(),
|
||||
button,
|
||||
Some("".into()),
|
||||
false,
|
||||
)
|
||||
};
|
||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||
}
|
||||
@ -1561,15 +1578,6 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// """Show user how to interact with the device."""
|
||||
Qstr::MP_QSTR_tutorial => obj_fn_kw!(0, tutorial).as_obj(),
|
||||
|
||||
/// def show_error(
|
||||
/// *,
|
||||
/// title: str,
|
||||
/// description: str,
|
||||
/// button: str,
|
||||
/// ) -> object:
|
||||
/// """Show a popup with text centered both vertically and horizontally. With just a middle button."""
|
||||
Qstr::MP_QSTR_show_error => obj_fn_kw!(0, new_show_error).as_obj(),
|
||||
|
||||
/// def confirm_modify_fee(
|
||||
/// *,
|
||||
/// title: str, # ignored
|
||||
@ -1603,6 +1611,15 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// """Show multiple texts, each on its own page."""
|
||||
Qstr::MP_QSTR_multiple_pages_texts => obj_fn_kw!(0, new_multiple_pages_texts).as_obj(),
|
||||
|
||||
/// def show_warning(
|
||||
/// *,
|
||||
/// button: str,
|
||||
/// warning: str,
|
||||
/// description: str,
|
||||
/// ) -> object:
|
||||
/// """Warning modal with middle button and centered text."""
|
||||
Qstr::MP_QSTR_show_warning => obj_fn_kw!(0, new_show_warning).as_obj(),
|
||||
|
||||
/// def show_info(
|
||||
/// *,
|
||||
/// title: str,
|
||||
@ -1717,6 +1734,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
||||
/// button: str,
|
||||
/// dry_run: bool,
|
||||
/// info_button: bool, # unused on TR
|
||||
/// show_info: bool,
|
||||
/// ) -> object:
|
||||
/// """Device recovery homescreen."""
|
||||
Qstr::MP_QSTR_confirm_recovery => obj_fn_kw!(0, new_confirm_recovery).as_obj(),
|
||||
|
@ -1399,7 +1399,7 @@ extern "C" fn new_confirm_recovery(n_args: usize, args: *const Obj, kwargs: *mut
|
||||
.with_spacing(theme::RECOVERY_SPACING);
|
||||
|
||||
let notification = if dry_run {
|
||||
"SEED CHECK"
|
||||
"BACKUP CHECK"
|
||||
} else {
|
||||
"RECOVERY MODE"
|
||||
};
|
||||
@ -1427,9 +1427,9 @@ extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mu
|
||||
let block = move |_args: &[Obj], kwargs: &Map| {
|
||||
let dry_run: bool = kwargs.get(Qstr::MP_QSTR_dry_run)?.try_into()?;
|
||||
let title = if dry_run {
|
||||
"SEED CHECK"
|
||||
"BACKUP CHECK"
|
||||
} else {
|
||||
"WALLET RECOVERY"
|
||||
"RECOVER WALLET"
|
||||
};
|
||||
|
||||
let paragraphs = Paragraphs::new(
|
||||
|
@ -1,19 +1,17 @@
|
||||
from typing import *
|
||||
|
||||
CONFIRMED: object
|
||||
CANCELLED: object
|
||||
INFO: object
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def disable_animation(disable: bool) -> None:
|
||||
"""Disable animations, debug builds only."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def toif_info(data: bytes) -> tuple[int, int, bool]:
|
||||
"""Get TOIF image dimensions and format (width: int, height: int, is_grayscale: bool)."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_action(
|
||||
*,
|
||||
@ -28,7 +26,6 @@ def confirm_action(
|
||||
) -> object:
|
||||
"""Confirm action."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_blob(
|
||||
*,
|
||||
@ -42,7 +39,6 @@ def confirm_blob(
|
||||
) -> object:
|
||||
"""Confirm byte sequence data."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_address(
|
||||
*,
|
||||
@ -53,7 +49,6 @@ def confirm_address(
|
||||
) -> object:
|
||||
"""Confirm address."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_properties(
|
||||
*,
|
||||
@ -65,7 +60,6 @@ def confirm_properties(
|
||||
the value is to be rendered as binary with monospace font, False otherwise.
|
||||
This only concerns the text style, you need to decode the value to UTF-8 in python."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_reset_device(
|
||||
*,
|
||||
@ -74,12 +68,10 @@ def confirm_reset_device(
|
||||
) -> object:
|
||||
"""Confirm TOS before device setup."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_backup() -> object:
|
||||
"""Strongly recommend user to do backup."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_address_details(
|
||||
*,
|
||||
@ -91,7 +83,6 @@ def show_address_details(
|
||||
) -> object:
|
||||
"""Show address details - QR code, account, path, cosigner xpubs."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_value(
|
||||
*,
|
||||
@ -103,7 +94,6 @@ def confirm_value(
|
||||
) -> object:
|
||||
"""Confirm value."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_joint_total(
|
||||
*,
|
||||
@ -112,7 +102,6 @@ def confirm_joint_total(
|
||||
) -> object:
|
||||
"""Confirm total if there are external inputs."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_modify_output(
|
||||
*,
|
||||
@ -123,7 +112,6 @@ def confirm_modify_output(
|
||||
) -> object:
|
||||
"""Decrease or increase amount for given address."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_output(
|
||||
*,
|
||||
@ -135,7 +123,6 @@ def confirm_output(
|
||||
) -> object:
|
||||
"""Confirm output."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_total(
|
||||
*,
|
||||
@ -148,12 +135,10 @@ def confirm_total(
|
||||
) -> object:
|
||||
"""Confirm summary of a transaction."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def tutorial() -> object:
|
||||
"""Show user how to interact with the device."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_error(
|
||||
*,
|
||||
@ -163,7 +148,6 @@ def show_error(
|
||||
) -> object:
|
||||
"""Show a popup with text centered both vertically and horizontally. With just a middle button."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_modify_fee(
|
||||
*,
|
||||
@ -175,7 +159,6 @@ def confirm_modify_fee(
|
||||
) -> object:
|
||||
"""Decrease or increase transaction fee."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_fido(
|
||||
*,
|
||||
@ -188,7 +171,6 @@ def confirm_fido(
|
||||
Returns page index in case of confirmation and CANCELLED otherwise.
|
||||
"""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def multiple_pages_texts(
|
||||
*,
|
||||
@ -198,6 +180,13 @@ def multiple_pages_texts(
|
||||
) -> object:
|
||||
"""Show multiple texts, each on its own page."""
|
||||
|
||||
def show_warning(
|
||||
*,
|
||||
button: str,
|
||||
warning: str,
|
||||
description: str,
|
||||
) -> object:
|
||||
"""Warning modal with middle button and centered text."""
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_info(
|
||||
@ -208,17 +197,14 @@ def show_info(
|
||||
) -> object:
|
||||
"""Info modal."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_passphrase() -> object:
|
||||
"""Show passphrase on host dialog."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_mismatch() -> object:
|
||||
"""Warning modal, receiving address mismatch."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_with_info(
|
||||
*,
|
||||
@ -230,7 +216,6 @@ def confirm_with_info(
|
||||
"""Confirm given items but with third button. Always single page
|
||||
without scrolling."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_coinjoin(
|
||||
*,
|
||||
@ -239,7 +224,6 @@ def confirm_coinjoin(
|
||||
) -> object:
|
||||
"""Confirm coinjoin authorization."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def request_pin(
|
||||
*,
|
||||
@ -250,7 +234,6 @@ def request_pin(
|
||||
) -> str | object:
|
||||
"""Request pin on device."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def request_passphrase(
|
||||
*,
|
||||
@ -259,7 +242,6 @@ def request_passphrase(
|
||||
) -> str | object:
|
||||
"""Get passphrase."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def request_bip39(
|
||||
*,
|
||||
@ -267,14 +249,12 @@ def request_bip39(
|
||||
) -> str:
|
||||
"""Get recovery word for BIP39."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def request_slip39(
|
||||
*,
|
||||
prompt: str,
|
||||
) -> str:
|
||||
"""SLIP39 word input keyboard."""
|
||||
|
||||
"""SLIP39 word input keyboard."""
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def select_word(
|
||||
@ -283,9 +263,8 @@ def select_word(
|
||||
description: str,
|
||||
words: Iterable[str],
|
||||
) -> int:
|
||||
"""Select mnemonic word from three possibilities - seed check after backup. The
|
||||
iterable must be of exact size. Returns index in range `0..3`."""
|
||||
|
||||
"""Select mnemonic word from three possibilities - seed check after backup. The
|
||||
iterable must be of exact size. Returns index in range `0..3`."""
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_share_words(
|
||||
@ -294,7 +273,6 @@ def show_share_words(
|
||||
) -> object:
|
||||
"""Shows a backup seed."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def request_number(
|
||||
*,
|
||||
@ -304,8 +282,7 @@ def request_number(
|
||||
max_count: int,
|
||||
description: Callable[[int], str] | None = None, # unused on TR
|
||||
) -> object:
|
||||
"""Number input with + and - buttons, description, and info button."""
|
||||
|
||||
"""Number input with + and - buttons, description, and info button."""
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_checklist(
|
||||
@ -315,9 +292,8 @@ def show_checklist(
|
||||
active: int,
|
||||
button: str,
|
||||
) -> object:
|
||||
"""Checklist of backup steps. Active index is highlighted, previous items have check
|
||||
mark next to them."""
|
||||
|
||||
"""Checklist of backup steps. Active index is highlighted, previous items have check
|
||||
mark next to them."""
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def confirm_recovery(
|
||||
@ -327,25 +303,23 @@ def confirm_recovery(
|
||||
button: str,
|
||||
dry_run: bool,
|
||||
info_button: bool, # unused on TR
|
||||
show_info: bool,
|
||||
) -> object:
|
||||
"""Device recovery homescreen."""
|
||||
|
||||
"""Device recovery homescreen."""
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def select_word_count(
|
||||
*,
|
||||
dry_run: bool, # unused on TR
|
||||
) -> int | str: # TR returns str
|
||||
"""Select mnemonic word count from (12, 18, 20, 24, 33)."""
|
||||
|
||||
"""Select mnemonic word count from (12, 18, 20, 24, 33)."""
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_group_share_success(
|
||||
*,
|
||||
lines: Iterable[str],
|
||||
) -> int:
|
||||
"""Shown after successfully finishing a group."""
|
||||
|
||||
"""Shown after successfully finishing a group."""
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_progress(
|
||||
@ -354,10 +328,9 @@ def show_progress(
|
||||
indeterminate: bool = False,
|
||||
description: str = "",
|
||||
) -> object:
|
||||
"""Show progress loader. Please note that the number of lines reserved on screen for
|
||||
description is determined at construction time. If you want multiline descriptions
|
||||
make sure the initial description has at least that amount of lines."""
|
||||
|
||||
"""Show progress loader. Please note that the number of lines reserved on screen for
|
||||
description is determined at construction time. If you want multiline descriptions
|
||||
make sure the initial description has at least that amount of lines."""
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_progress_coinjoin(
|
||||
@ -367,9 +340,8 @@ def show_progress_coinjoin(
|
||||
time_ms: int = 0,
|
||||
skip_first_paint: bool = False,
|
||||
) -> object:
|
||||
"""Show progress loader for coinjoin. Returns CANCELLED after a specified time when
|
||||
time_ms timeout is passed."""
|
||||
|
||||
"""Show progress loader for coinjoin. Returns CANCELLED after a specified time when
|
||||
time_ms timeout is passed."""
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_homescreen(
|
||||
@ -382,7 +354,6 @@ def show_homescreen(
|
||||
) -> CANCELLED:
|
||||
"""Idle homescreen."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def show_lockscreen(
|
||||
*,
|
||||
@ -392,30 +363,26 @@ def show_lockscreen(
|
||||
) -> CANCELLED:
|
||||
"""Homescreen for locked device."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tr/layout.rs
|
||||
def draw_welcome_screen() -> None:
|
||||
"""Show logo icon with the model name at the bottom and return."""
|
||||
|
||||
CONFIRMED: object
|
||||
CANCELLED: object
|
||||
INFO: object
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def disable_animation(disable: bool) -> None:
|
||||
"""Disable animations, debug builds only."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def jpeg_info(data: bytes) -> tuple[int, int, int]:
|
||||
"""Get JPEG image dimensions (width: int, height: int, mcu_height: int)."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def jpeg_test(data: bytes) -> bool:
|
||||
"""Test JPEG image."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_action(
|
||||
*,
|
||||
@ -430,7 +397,6 @@ def confirm_action(
|
||||
) -> object:
|
||||
"""Confirm action."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_emphasized(
|
||||
*,
|
||||
@ -441,7 +407,6 @@ def confirm_emphasized(
|
||||
"""Confirm formatted text that has been pre-split in python. For tuples
|
||||
the first component is a bool indicating whether this part is emphasized."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_homescreen(
|
||||
*,
|
||||
@ -450,7 +415,6 @@ def confirm_homescreen(
|
||||
) -> object:
|
||||
"""Confirm homescreen."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_blob(
|
||||
*,
|
||||
@ -464,7 +428,6 @@ def confirm_blob(
|
||||
) -> object:
|
||||
"""Confirm byte sequence data."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_address(
|
||||
*,
|
||||
@ -476,7 +439,6 @@ def confirm_address(
|
||||
"""Confirm address. Similar to `confirm_blob` but has corner info button
|
||||
and allows left swipe which does the same thing as the button."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_properties(
|
||||
*,
|
||||
@ -487,7 +449,6 @@ def confirm_properties(
|
||||
"""Confirm list of key-value pairs. The third component in the tuple should be True if
|
||||
the value is to be rendered as binary with monospace font, False otherwise."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_reset_device(
|
||||
*,
|
||||
@ -496,7 +457,6 @@ def confirm_reset_device(
|
||||
) -> object:
|
||||
"""Confirm TOS before device setup."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_address_details(
|
||||
*,
|
||||
@ -508,7 +468,6 @@ def show_address_details(
|
||||
) -> object:
|
||||
"""Show address details - QR code, account, path, cosigner xpubs."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_spending_details(
|
||||
*,
|
||||
@ -519,7 +478,6 @@ def show_spending_details(
|
||||
) -> object:
|
||||
"""Show metadata when for outgoing transaction."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_value(
|
||||
*,
|
||||
@ -534,7 +492,6 @@ def confirm_value(
|
||||
) -> object:
|
||||
"""Confirm value. Merge of confirm_total and confirm_output."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_total(
|
||||
*,
|
||||
@ -544,7 +501,6 @@ def confirm_total(
|
||||
) -> object:
|
||||
"""Transaction summary. Always hold to confirm."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_modify_output(
|
||||
*,
|
||||
@ -555,7 +511,6 @@ def confirm_modify_output(
|
||||
) -> object:
|
||||
"""Decrease or increase amount for given address."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_modify_fee(
|
||||
*,
|
||||
@ -567,7 +522,6 @@ def confirm_modify_fee(
|
||||
) -> object:
|
||||
"""Decrease or increase transaction fee."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_fido(
|
||||
*,
|
||||
@ -580,7 +534,6 @@ def confirm_fido(
|
||||
Returns page index in case of confirmation and CANCELLED otherwise.
|
||||
"""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_error(
|
||||
*,
|
||||
@ -592,7 +545,6 @@ def show_error(
|
||||
) -> object:
|
||||
"""Error modal. No buttons shown when `button` is empty string."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_warning(
|
||||
*,
|
||||
@ -604,7 +556,6 @@ def show_warning(
|
||||
) -> object:
|
||||
"""Warning modal. No buttons shown when `button` is empty string."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_success(
|
||||
*,
|
||||
@ -616,7 +567,6 @@ def show_success(
|
||||
) -> object:
|
||||
"""Success modal. No buttons shown when `button` is empty string."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_info(
|
||||
*,
|
||||
@ -628,12 +578,10 @@ def show_info(
|
||||
) -> object:
|
||||
"""Info modal. No buttons shown when `button` is empty string."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_mismatch() -> object:
|
||||
"""Warning modal, receiving address mismatch."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_simple(
|
||||
*,
|
||||
@ -643,7 +591,6 @@ def show_simple(
|
||||
) -> object:
|
||||
"""Simple dialog with text and one button."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_with_info(
|
||||
*,
|
||||
@ -655,7 +602,6 @@ def confirm_with_info(
|
||||
"""Confirm given items but with third button. Always single page
|
||||
without scrolling."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_more(
|
||||
*,
|
||||
@ -666,7 +612,6 @@ def confirm_more(
|
||||
"""Confirm long content with the possibility to go back from any page.
|
||||
Meant to be used with confirm_with_info."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_coinjoin(
|
||||
*,
|
||||
@ -675,7 +620,6 @@ def confirm_coinjoin(
|
||||
) -> object:
|
||||
"""Confirm coinjoin authorization."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def request_pin(
|
||||
*,
|
||||
@ -686,7 +630,6 @@ def request_pin(
|
||||
) -> str | object:
|
||||
"""Request pin on device."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def request_passphrase(
|
||||
*,
|
||||
@ -695,7 +638,6 @@ def request_passphrase(
|
||||
) -> str | object:
|
||||
"""Passphrase input keyboard."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def request_bip39(
|
||||
*,
|
||||
@ -703,7 +645,6 @@ def request_bip39(
|
||||
) -> str:
|
||||
"""BIP39 word input keyboard."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def request_slip39(
|
||||
*,
|
||||
@ -711,7 +652,6 @@ def request_slip39(
|
||||
) -> str:
|
||||
"""SLIP39 word input keyboard."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def select_word(
|
||||
*,
|
||||
@ -720,8 +660,7 @@ def select_word(
|
||||
words: Iterable[str],
|
||||
) -> int:
|
||||
"""Select mnemonic word from three possibilities - seed check after backup. The
|
||||
iterable must be of exact size. Returns index in range `0..3`."""
|
||||
|
||||
iterable must be of exact size. Returns index in range `0..3`."""
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_share_words(
|
||||
@ -731,7 +670,6 @@ def show_share_words(
|
||||
) -> object:
|
||||
"""Show mnemonic for backup. Expects the words pre-divided into individual pages."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def request_number(
|
||||
*,
|
||||
@ -743,7 +681,6 @@ def request_number(
|
||||
) -> object:
|
||||
"""Number input with + and - buttons, description, and info button."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_checklist(
|
||||
*,
|
||||
@ -753,8 +690,7 @@ def show_checklist(
|
||||
button: str,
|
||||
) -> object:
|
||||
"""Checklist of backup steps. Active index is highlighted, previous items have check
|
||||
mark next to them."""
|
||||
|
||||
mark next to them."""
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def confirm_recovery(
|
||||
@ -767,7 +703,6 @@ def confirm_recovery(
|
||||
) -> object:
|
||||
"""Device recovery homescreen."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def select_word_count(
|
||||
*,
|
||||
@ -775,15 +710,10 @@ def select_word_count(
|
||||
) -> int | str: # TT returns int
|
||||
"""Select mnemonic word count from (12, 18, 20, 24, 33)."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_group_share_success(
|
||||
*,
|
||||
lines: Iterable[str]
|
||||
) -> int:
|
||||
def show_group_share_success(*, lines: Iterable[str]) -> int:
|
||||
"""Shown after successfully finishing a group."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_remaining_shares(
|
||||
*,
|
||||
@ -791,7 +721,6 @@ def show_remaining_shares(
|
||||
) -> int:
|
||||
"""Shows SLIP39 state after info button is pressed on `confirm_recovery`."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_progress(
|
||||
*,
|
||||
@ -800,9 +729,8 @@ def show_progress(
|
||||
description: str = "",
|
||||
) -> object:
|
||||
"""Show progress loader. Please note that the number of lines reserved on screen for
|
||||
description is determined at construction time. If you want multiline descriptions
|
||||
make sure the initial description has at least that amount of lines."""
|
||||
|
||||
description is determined at construction time. If you want multiline descriptions
|
||||
make sure the initial description has at least that amount of lines."""
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_progress_coinjoin(
|
||||
@ -813,8 +741,7 @@ def show_progress_coinjoin(
|
||||
skip_first_paint: bool = False,
|
||||
) -> object:
|
||||
"""Show progress loader for coinjoin. Returns CANCELLED after a specified time when
|
||||
time_ms timeout is passed."""
|
||||
|
||||
time_ms timeout is passed."""
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_homescreen(
|
||||
@ -827,7 +754,6 @@ def show_homescreen(
|
||||
) -> CANCELLED:
|
||||
"""Idle homescreen."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def show_lockscreen(
|
||||
*,
|
||||
@ -837,7 +763,6 @@ def show_lockscreen(
|
||||
) -> CANCELLED:
|
||||
"""Homescreen for locked device."""
|
||||
|
||||
|
||||
# rust/src/ui/model_tt/layout.rs
|
||||
def draw_welcome_screen() -> None:
|
||||
"""Show logo icon with the model name at the bottom and return."""
|
||||
|
@ -56,11 +56,11 @@ async def recovery_device(msg: RecoveryDevice) -> Success:
|
||||
# --------------------------------------------------------
|
||||
# _continue_dialog
|
||||
if not dry_run:
|
||||
await confirm_reset_device("Wallet recovery", recovery=True)
|
||||
await confirm_reset_device("Recover wallet", recovery=True)
|
||||
else:
|
||||
await confirm_action(
|
||||
"confirm_seedcheck",
|
||||
"Seed check",
|
||||
"Backup check",
|
||||
description="Do you really want to check the recovery seed?",
|
||||
br_code=ButtonRequestType.ProtectCall,
|
||||
)
|
||||
|
@ -2,6 +2,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import storage.device as storage_device
|
||||
import storage.recovery as storage_recovery
|
||||
import storage.recovery_shares as storage_recovery_shares
|
||||
from trezor import wire
|
||||
from trezor.messages import Success
|
||||
|
||||
@ -62,7 +63,9 @@ async def _continue_recovery_process() -> Success:
|
||||
if is_first_step:
|
||||
# If we are starting recovery, ask for word count first...
|
||||
# _request_word_count
|
||||
await layout.homescreen_dialog("Select", "Select number of words")
|
||||
await layout.homescreen_dialog(
|
||||
"Continue", "Select the number of words in your backup."
|
||||
)
|
||||
# ask for the number of words
|
||||
word_count = await layout.request_word_count(dry_run)
|
||||
# ...and only then show the starting screen with word count.
|
||||
@ -150,7 +153,7 @@ async def _finish_recovery(secret: bytes, backup_type: BackupType) -> Success:
|
||||
|
||||
storage_recovery.end_progress()
|
||||
|
||||
await show_success("success_recovery", "You have finished recovering your wallet.")
|
||||
await show_success("success_recovery", "Wallet recovered successfully.")
|
||||
return Success(message="Device recovered")
|
||||
|
||||
|
||||
@ -181,11 +184,17 @@ async def _request_share_first_screen(word_count: int) -> None:
|
||||
await _request_share_next_screen()
|
||||
else:
|
||||
await layout.homescreen_dialog(
|
||||
"Enter share", "Enter any share", f"({word_count} words)"
|
||||
"Enter share",
|
||||
"Enter any share",
|
||||
f"({word_count} words)",
|
||||
show_info=True,
|
||||
)
|
||||
else: # BIP-39
|
||||
await layout.homescreen_dialog(
|
||||
"Enter seed", "Enter recovery seed", f"({word_count} words)"
|
||||
"Continue",
|
||||
"Enter your backup.",
|
||||
f"({word_count} words)",
|
||||
show_info=True,
|
||||
)
|
||||
|
||||
|
||||
@ -205,8 +214,16 @@ async def _request_share_next_screen() -> None:
|
||||
info_func=_show_remaining_groups_and_shares,
|
||||
)
|
||||
else:
|
||||
text = strings.format_plural("{count} more {plural}", remaining[0], "share")
|
||||
await layout.homescreen_dialog("Enter share", text, "needed to enter")
|
||||
still_needed_shares = remaining[0]
|
||||
already_entered_shares = len(storage_recovery_shares.fetch_group(0))
|
||||
overall_needed = still_needed_shares + already_entered_shares
|
||||
entered = (
|
||||
f"{already_entered_shares} of {overall_needed} shares entered successfully."
|
||||
)
|
||||
needed = strings.format_plural(
|
||||
"{count} more {plural} needed.", still_needed_shares, "share"
|
||||
)
|
||||
await layout.homescreen_dialog("Enter share", entered, needed)
|
||||
|
||||
|
||||
async def _show_remaining_groups_and_shares() -> None:
|
||||
@ -214,7 +231,6 @@ async def _show_remaining_groups_and_shares() -> None:
|
||||
Show info dialog for Slip39 Advanced - what shares are to be entered.
|
||||
"""
|
||||
from trezor.crypto import slip39
|
||||
import storage.recovery_shares as storage_recovery_shares
|
||||
|
||||
shares_remaining = storage_recovery.fetch_slip39_remaining_shares()
|
||||
# should be stored at this point
|
||||
|
@ -20,8 +20,8 @@ async def _confirm_abort(dry_run: bool = False) -> None:
|
||||
if dry_run:
|
||||
await confirm_action(
|
||||
"abort_recovery",
|
||||
"Abort seed check",
|
||||
description="Do you really want to abort the seed check?",
|
||||
"Abort backup check",
|
||||
description="Do you really want to abort the backup check?",
|
||||
br_code=ButtonRequestType.ProtectCall,
|
||||
)
|
||||
else:
|
||||
@ -41,9 +41,6 @@ async def request_mnemonic(
|
||||
from . import word_validity
|
||||
from trezor.ui.layouts.common import button_request
|
||||
from trezor.ui.layouts.recovery import request_word
|
||||
from trezor.ui.layouts import mnemonic_word_entering
|
||||
|
||||
await mnemonic_word_entering()
|
||||
|
||||
await button_request("mnemonic", code=ButtonRequestType.MnemonicInput)
|
||||
|
||||
@ -60,7 +57,8 @@ async def request_mnemonic(
|
||||
# show_share_already_added
|
||||
await show_recovery_warning(
|
||||
"warning_known_share",
|
||||
"Share already entered, please enter a different share.",
|
||||
"Share already entered",
|
||||
"Please enter a different share.",
|
||||
)
|
||||
return None
|
||||
except word_validity.IdentifierMismatch:
|
||||
@ -74,7 +72,8 @@ async def request_mnemonic(
|
||||
# show_group_threshold_reached
|
||||
await show_recovery_warning(
|
||||
"warning_group_threshold",
|
||||
"Threshold of this group has been reached. Input share from different group.",
|
||||
"Group threshold reached.",
|
||||
"Enter share from a different group.",
|
||||
)
|
||||
return None
|
||||
|
||||
@ -97,19 +96,21 @@ async def show_dry_run_result(result: bool, is_slip39: bool) -> None:
|
||||
text = "The entered recovery shares are valid but do not match what is currently in the device."
|
||||
else:
|
||||
text = "The entered recovery seed is valid but does not match the one in the device."
|
||||
await show_recovery_warning("warning_dry_recovery", text, button="Continue")
|
||||
await show_recovery_warning("warning_dry_recovery", "", text, button="Continue")
|
||||
|
||||
|
||||
async def show_invalid_mnemonic(word_count: int) -> None:
|
||||
if backup_types.is_slip39_word_count(word_count):
|
||||
await show_recovery_warning(
|
||||
"warning_invalid_share",
|
||||
"You have entered an invalid recovery share.",
|
||||
"Invalid recovery share entered.",
|
||||
"Please try again",
|
||||
)
|
||||
else:
|
||||
await show_recovery_warning(
|
||||
"warning_invalid_seed",
|
||||
"You have entered an invalid recovery seed.",
|
||||
"Invalid recovery seed entered.",
|
||||
"Please try again",
|
||||
)
|
||||
|
||||
|
||||
@ -118,6 +119,7 @@ async def homescreen_dialog(
|
||||
text: str,
|
||||
subtext: str | None = None,
|
||||
info_func: Callable | None = None,
|
||||
show_info: bool = False,
|
||||
) -> None:
|
||||
from .recover import RecoveryAborted
|
||||
import storage.recovery as storage_recovery
|
||||
@ -126,7 +128,9 @@ async def homescreen_dialog(
|
||||
|
||||
while True:
|
||||
dry_run = storage_recovery.is_dry_run()
|
||||
if await continue_recovery(button_label, text, subtext, info_func, dry_run):
|
||||
if await continue_recovery(
|
||||
button_label, text, subtext, info_func, dry_run, show_info
|
||||
):
|
||||
# go forward in the recovery process
|
||||
break
|
||||
# user has chosen to abort, confirm the choice
|
||||
|
@ -1,7 +1,7 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import storage.recovery as storage_recovery
|
||||
import storage.recovery_shares
|
||||
import storage.recovery_shares as storage_recovery_shares
|
||||
from trezor.crypto import slip39
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -42,7 +42,7 @@ def process_slip39(words: str) -> tuple[bytes | None, slip39.Share]:
|
||||
storage_recovery.set_slip39_iteration_exponent(share.iteration_exponent)
|
||||
storage_recovery.set_slip39_identifier(share.identifier)
|
||||
storage_recovery.set_slip39_remaining_shares(share.threshold - 1, group_index)
|
||||
storage.recovery_shares.set(share.index, group_index, words)
|
||||
storage_recovery_shares.set(share.index, group_index, words)
|
||||
|
||||
# if share threshold and group threshold are 1
|
||||
# we can calculate the secret right away
|
||||
@ -58,7 +58,7 @@ def process_slip39(words: str) -> tuple[bytes | None, slip39.Share]:
|
||||
raise RuntimeError("Slip39: Share identifiers do not match")
|
||||
if share.iteration_exponent != storage_recovery.get_slip39_iteration_exponent():
|
||||
raise RuntimeError("Slip39: Share exponents do not match")
|
||||
if storage.recovery_shares.get(share.index, group_index):
|
||||
if storage_recovery_shares.get(share.index, group_index):
|
||||
raise RuntimeError("Slip39: This mnemonic was already entered")
|
||||
if share.group_count != storage_recovery.get_slip39_group_count():
|
||||
raise RuntimeError("Slip39: Group count does not match")
|
||||
@ -68,7 +68,7 @@ def process_slip39(words: str) -> tuple[bytes | None, slip39.Share]:
|
||||
)
|
||||
storage_recovery.set_slip39_remaining_shares(remaining_for_share - 1, group_index)
|
||||
remaining[group_index] = remaining_for_share - 1
|
||||
storage.recovery_shares.set(share.index, group_index, words)
|
||||
storage_recovery_shares.set(share.index, group_index, words)
|
||||
|
||||
if remaining.count(0) < share.group_threshold:
|
||||
# we need more shares
|
||||
@ -79,11 +79,11 @@ def process_slip39(words: str) -> tuple[bytes | None, slip39.Share]:
|
||||
for i, r in enumerate(remaining):
|
||||
# if we have multiple groups pass only the ones with threshold reached
|
||||
if r == 0:
|
||||
group = storage.recovery_shares.fetch_group(i)
|
||||
group = storage_recovery_shares.fetch_group(i)
|
||||
mnemonics.extend(group)
|
||||
else:
|
||||
# in case of slip39 basic we only need the first and only group
|
||||
mnemonics = storage.recovery_shares.fetch_group(0)
|
||||
mnemonics = storage_recovery_shares.fetch_group(0)
|
||||
|
||||
_, _, secret = slip39.recover_ems(mnemonics)
|
||||
return secret, share
|
||||
@ -111,7 +111,7 @@ def fetch_previous_mnemonics() -> list[list[str]] | None:
|
||||
if not storage_recovery.get_slip39_group_count():
|
||||
return None
|
||||
for i in range(storage_recovery.get_slip39_group_count()):
|
||||
mnemonics.append(storage.recovery_shares.fetch_group(i))
|
||||
mnemonics.append(storage_recovery_shares.fetch_group(i))
|
||||
if not any(p for p in mnemonics):
|
||||
return None
|
||||
return mnemonics
|
||||
|
@ -10,13 +10,13 @@ _NAMESPACE = common.APP_RECOVERY
|
||||
_IN_PROGRESS = const(0x00) # bool
|
||||
_DRY_RUN = const(0x01) # bool
|
||||
_SLIP39_IDENTIFIER = const(0x03) # bytes
|
||||
_SLIP39_THRESHOLD = const(0x04) # int
|
||||
_REMAINING = const(0x05) # int
|
||||
_SLIP39_ITERATION_EXPONENT = const(0x06) # int
|
||||
_SLIP39_GROUP_COUNT = const(0x07) # int
|
||||
|
||||
# Deprecated Keys:
|
||||
# _WORD_COUNT = const(0x02) # int
|
||||
# _SLIP39_THRESHOLD = const(0x04) # int
|
||||
# fmt: on
|
||||
|
||||
# Default values:
|
||||
@ -130,7 +130,6 @@ def end_progress() -> None:
|
||||
_IN_PROGRESS,
|
||||
_DRY_RUN,
|
||||
_SLIP39_IDENTIFIER,
|
||||
_SLIP39_THRESHOLD,
|
||||
_REMAINING,
|
||||
_SLIP39_ITERATION_EXPONENT,
|
||||
_SLIP39_GROUP_COUNT,
|
||||
|
@ -399,6 +399,16 @@ async def confirm_reset_device(
|
||||
)
|
||||
)
|
||||
|
||||
if recovery:
|
||||
await confirm_action(
|
||||
ctx,
|
||||
"recover_device",
|
||||
title,
|
||||
description="It is safe to eject your Trezor anytime and continue later.",
|
||||
verb="CONTINUE",
|
||||
br_code=ButtonRequestType.ProtectCall,
|
||||
)
|
||||
|
||||
|
||||
async def confirm_backup() -> bool:
|
||||
br_type = "backup_device"
|
||||
@ -597,21 +607,23 @@ async def show_error_and_raise(
|
||||
raise exc
|
||||
|
||||
|
||||
def show_warning(
|
||||
async def show_warning(
|
||||
br_type: str,
|
||||
content: str,
|
||||
subheader: str | None = None,
|
||||
button: str = "Try again",
|
||||
button: str = "CONTINUE",
|
||||
br_code: ButtonRequestType = ButtonRequestType.Warning,
|
||||
) -> Awaitable[None]:
|
||||
return _show_modal(
|
||||
) -> None:
|
||||
await interact(
|
||||
RustLayout(
|
||||
trezorui2.show_warning( # type: ignore [Argument missing for parameter "title"]
|
||||
button=button.upper(),
|
||||
warning=content, # type: ignore [No parameter named "warning"]
|
||||
description=subheader or "",
|
||||
)
|
||||
),
|
||||
br_type,
|
||||
"",
|
||||
subheader or "WARNING",
|
||||
content,
|
||||
button_confirm=button,
|
||||
button_cancel=None,
|
||||
br_code=br_code,
|
||||
br_code,
|
||||
)
|
||||
|
||||
|
||||
@ -1160,26 +1172,6 @@ async def confirm_reenter_pin(
|
||||
)
|
||||
|
||||
|
||||
async def show_error(
|
||||
br_type: str,
|
||||
title: str,
|
||||
description: str,
|
||||
button: str,
|
||||
br_code: ButtonRequestType = BR_TYPE_OTHER,
|
||||
) -> None:
|
||||
await interact(
|
||||
RustLayout(
|
||||
trezorui2.show_error(
|
||||
title=title,
|
||||
description=description,
|
||||
button=button,
|
||||
)
|
||||
),
|
||||
br_type,
|
||||
br_code,
|
||||
)
|
||||
|
||||
|
||||
async def confirm_multiple_pages_texts(
|
||||
br_type: str,
|
||||
title: str,
|
||||
@ -1207,7 +1199,7 @@ async def pin_mismatch_popup(
|
||||
) -> None:
|
||||
description = "wipe codes" if is_wipe_code else "PINs"
|
||||
br_code = "wipe_code_mismatch" if is_wipe_code else "pin_mismatch"
|
||||
return await show_error(
|
||||
return await show_warning(
|
||||
br_code,
|
||||
f"Entered {description} do not match!",
|
||||
"Please check again.",
|
||||
@ -1259,14 +1251,3 @@ async def confirm_set_new_pin(
|
||||
"CONTINUE",
|
||||
br_code,
|
||||
)
|
||||
|
||||
|
||||
async def mnemonic_word_entering() -> None:
|
||||
await confirm_action(
|
||||
"request_word",
|
||||
"WORD ENTERING",
|
||||
description="You'll only have to select the first 2-3 letters.",
|
||||
verb="CONTINUE",
|
||||
verb_cancel=None,
|
||||
br_code=ButtonRequestType.MnemonicInput,
|
||||
)
|
||||
|
@ -4,12 +4,11 @@ from trezor.enums import ButtonRequestType
|
||||
|
||||
import trezorui2
|
||||
|
||||
from ..common import button_request, interact
|
||||
from ..common import interact
|
||||
from . import RustLayout, raise_if_not_confirmed, show_warning
|
||||
|
||||
|
||||
async def request_word_count(dry_run: bool) -> int:
|
||||
await button_request("word_count", code=ButtonRequestType.MnemonicWordCount)
|
||||
count = await interact(
|
||||
RustLayout(trezorui2.select_word_count(dry_run=dry_run)),
|
||||
"word_count",
|
||||
@ -66,6 +65,7 @@ async def continue_recovery(
|
||||
subtext: str | None,
|
||||
info_func: Callable | None,
|
||||
dry_run: bool,
|
||||
show_info: bool = False,
|
||||
) -> bool:
|
||||
# TODO: implement info_func?
|
||||
# There is very limited space on the screen
|
||||
@ -82,6 +82,7 @@ async def continue_recovery(
|
||||
button=button_label.upper(),
|
||||
info_button=False,
|
||||
dry_run=dry_run,
|
||||
show_info=show_info, # type: ignore [No parameter named "show_info"]
|
||||
)
|
||||
)
|
||||
result = await interact(
|
||||
|
@ -6,7 +6,7 @@ from trezor.wire import ActionCancelled
|
||||
import trezorui2
|
||||
|
||||
from ..common import interact
|
||||
from . import RustLayout, confirm_action, show_error
|
||||
from . import RustLayout, confirm_action, show_warning
|
||||
|
||||
CONFIRMED = trezorui2.CONFIRMED # global_import_cache
|
||||
|
||||
@ -247,7 +247,7 @@ async def slip39_advanced_prompt_group_threshold(num_of_groups: int) -> int:
|
||||
|
||||
|
||||
async def show_warning_backup(slip39: bool) -> None:
|
||||
await show_error(
|
||||
await show_warning(
|
||||
"backup_warning",
|
||||
"REMEMBER",
|
||||
"Never make a digital copy of your backup or upload it online!",
|
||||
@ -275,7 +275,7 @@ async def show_reset_warning(
|
||||
button: str = "TRY AGAIN",
|
||||
br_code: ButtonRequestType = ButtonRequestType.Warning,
|
||||
) -> None:
|
||||
await show_error(
|
||||
await show_warning(
|
||||
ctx,
|
||||
br_type,
|
||||
button.upper(),
|
||||
|
@ -1238,17 +1238,3 @@ async def confirm_set_new_pin(
|
||||
br_code,
|
||||
)
|
||||
)
|
||||
|
||||
# await confirm_action(
|
||||
# ctx,
|
||||
# br_type,
|
||||
# title,
|
||||
# description=description,
|
||||
# verb="TURN ON",
|
||||
# br_code=br_code,
|
||||
# )
|
||||
|
||||
|
||||
async def mnemonic_word_entering() -> None:
|
||||
"""Not supported for TT."""
|
||||
pass
|
||||
|
@ -102,6 +102,7 @@ async def continue_recovery(
|
||||
subtext: str | None,
|
||||
info_func: Callable | None,
|
||||
dry_run: bool,
|
||||
show_info: bool = False, # unused on TT
|
||||
) -> bool:
|
||||
from ..common import button_request
|
||||
|
||||
|
@ -42,12 +42,16 @@ def confirm_recovery(debug: "DebugLink") -> None:
|
||||
if debug.model == "T":
|
||||
if not debug.legacy_ui and not debug.legacy_debug:
|
||||
layout = debug.wait_layout()
|
||||
assert layout.title().startswith("WALLET RECOVERY")
|
||||
assert layout.title().startswith(
|
||||
("WALLET RECOVERY", "RECOVER WALLET", "BACKUP CHECK")
|
||||
)
|
||||
debug.click(buttons.OK, wait=True)
|
||||
elif debug.model == "R":
|
||||
layout = debug.wait_layout()
|
||||
assert layout.title() == "WALLET RECOVERY"
|
||||
assert layout.title() == "RECOVER WALLET"
|
||||
debug.press_right(wait=True)
|
||||
layout = debug.press_right(wait=True)
|
||||
assert "safe to eject" in layout.text_content()
|
||||
debug.press_right()
|
||||
|
||||
|
||||
@ -66,8 +70,11 @@ def select_number_of_words(
|
||||
elif debug.legacy_debug:
|
||||
assert "SelectWordCount" in layout.json_str
|
||||
else:
|
||||
# Two title options
|
||||
assert layout.title() in ("SEED CHECK", "WALLET RECOVERY")
|
||||
assert layout.title() in (
|
||||
"WALLET RECOVERY",
|
||||
"BACKUP CHECK",
|
||||
"RECOVER WALLET",
|
||||
)
|
||||
|
||||
# click the number
|
||||
word_option_offset = 6
|
||||
@ -96,10 +103,12 @@ def select_number_of_words(
|
||||
if num_of_words in (20, 33):
|
||||
assert "Enter any share" in layout.text_content()
|
||||
else:
|
||||
assert "Enter recovery seed" in layout.text_content()
|
||||
assert "Enter your backup" in layout.text_content()
|
||||
|
||||
|
||||
def enter_share(debug: "DebugLink", share: str) -> "LayoutContent":
|
||||
def enter_share(
|
||||
debug: "DebugLink", share: str, is_first: bool = True
|
||||
) -> "LayoutContent":
|
||||
if debug.model == "T":
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
|
||||
@ -115,10 +124,12 @@ def enter_share(debug: "DebugLink", share: str) -> "LayoutContent":
|
||||
|
||||
return layout
|
||||
elif debug.model == "R":
|
||||
assert "RECOVER WALLET" in debug.wait_layout().title()
|
||||
layout = debug.press_right(wait=True)
|
||||
assert layout.title() == "WORD ENTERING"
|
||||
|
||||
layout = debug.press_right(wait=True)
|
||||
if is_first:
|
||||
# Word entering info
|
||||
debug.press_right()
|
||||
layout = debug.press_right(wait=True)
|
||||
assert "Slip39Entry" in layout.all_components()
|
||||
|
||||
for word in share.split(" "):
|
||||
@ -133,39 +144,32 @@ def enter_shares(debug: "DebugLink", shares: list[str]) -> None:
|
||||
layout = debug.read_layout()
|
||||
expected_text = "Enter any share"
|
||||
remaining = len(shares)
|
||||
for share in shares:
|
||||
for index, share in enumerate(shares):
|
||||
assert expected_text in layout.text_content()
|
||||
layout = enter_share(debug, share)
|
||||
layout = enter_share(debug, share, is_first=index == 0)
|
||||
remaining -= 1
|
||||
expected_text = f"{remaining} more share"
|
||||
|
||||
assert "You have finished recovering your wallet" in layout.text_content()
|
||||
assert "Wallet recovered successfully" in layout.text_content()
|
||||
|
||||
|
||||
def enter_seed(debug: "DebugLink", seed_words: list[str]) -> None:
|
||||
assert "Enter" in debug.read_layout().text_content()
|
||||
if debug.model == "T":
|
||||
assert "Enter" in debug.read_layout().text_content()
|
||||
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
assert layout.main_component() == "MnemonicKeyboard"
|
||||
|
||||
for word in seed_words:
|
||||
layout = enter_word(debug, word, is_slip39=False)
|
||||
|
||||
assert "You have finished recovering your wallet" in layout.text_content()
|
||||
elif debug.model == "R":
|
||||
assert "Enter" in debug.read_layout().text_content()
|
||||
|
||||
layout = debug.press_right(wait=True)
|
||||
assert layout.title() == "WORD ENTERING"
|
||||
assert "RECOVER WALLET" in layout.title()
|
||||
debug.press_right()
|
||||
|
||||
layout = debug.press_right(wait=True)
|
||||
assert "Bip39Entry" in layout.all_components()
|
||||
|
||||
for word in seed_words:
|
||||
layout = enter_word(debug, word, is_slip39=False)
|
||||
for word in seed_words:
|
||||
layout = enter_word(debug, word, is_slip39=False)
|
||||
|
||||
assert "You have finished recovering your wallet" in layout.text_content()
|
||||
assert "Wallet recovered successfully" in layout.text_content() # type: ignore
|
||||
|
||||
|
||||
def finalize(debug: "DebugLink") -> None:
|
||||
|
@ -301,7 +301,8 @@ def test_dryrun_locks_at_word_entry(device_handler: "BackgroundDeviceHandler"):
|
||||
assert layout.main_component() == "MnemonicKeyboard"
|
||||
elif debug.model == "R":
|
||||
layout = debug.press_right(wait=True)
|
||||
assert "WORD ENTERING" in layout.title()
|
||||
assert "RECOVER WALLET" in layout.title()
|
||||
debug.press_right()
|
||||
layout = debug.press_right(wait=True)
|
||||
assert "Slip39Entry" in layout.all_components()
|
||||
|
||||
@ -337,7 +338,8 @@ def test_dryrun_enter_word_slowly(device_handler: "BackgroundDeviceHandler"):
|
||||
assert layout.main_component() == "MnemonicKeyboard"
|
||||
elif debug.model == "R":
|
||||
layout = debug.press_right(wait=True)
|
||||
assert "WORD ENTERING" in layout.title()
|
||||
assert "RECOVER WALLET" in layout.title()
|
||||
debug.press_right()
|
||||
layout = debug.press_right(wait=True)
|
||||
assert "Slip39Entry" in layout.all_components()
|
||||
|
||||
|
@ -227,16 +227,15 @@ def recovery_enter_shares_tr(
|
||||
debug.input(str(word_count))
|
||||
# Homescreen - proceed to share entry
|
||||
yield
|
||||
assert "Enter any share" in debug.wait_layout().text_content()
|
||||
debug.press_right()
|
||||
debug.press_right()
|
||||
debug.press_yes()
|
||||
|
||||
# Enter shares
|
||||
for share in shares:
|
||||
br = yield
|
||||
assert br.code == ButtonRequestType.RecoveryHomepage
|
||||
|
||||
# Word entering
|
||||
yield
|
||||
debug.press_yes()
|
||||
assert br.code == ButtonRequestType.MnemonicInput
|
||||
|
||||
# Enter mnemonic words
|
||||
for word in share.split(" "):
|
||||
@ -368,7 +367,7 @@ def read_and_confirm_mnemonic_tr(
|
||||
return " ".join(mnemonic)
|
||||
|
||||
|
||||
def click_info_button(debug: "DebugLink"):
|
||||
def click_info_button_tt(debug: "DebugLink"):
|
||||
"""Click Shamir backup info button and return back."""
|
||||
debug.press_info()
|
||||
yield # Info screen with text
|
||||
|
@ -30,7 +30,6 @@ def test_tt_pin_passphrase(client: Client):
|
||||
with client:
|
||||
IF = InputFlowBip39RecoveryPIN(client, MNEMONIC12.split(" "))
|
||||
client.set_input_flow(IF.get())
|
||||
client.watch_layout()
|
||||
device.recover(
|
||||
client,
|
||||
pin_protection=True,
|
||||
@ -51,7 +50,6 @@ def test_tt_nopin_nopassphrase(client: Client):
|
||||
with client:
|
||||
IF = InputFlowBip39RecoveryNoPIN(client, MNEMONIC12.split(" "))
|
||||
client.set_input_flow(IF.get())
|
||||
client.watch_layout()
|
||||
device.recover(
|
||||
client,
|
||||
pin_protection=False,
|
||||
|
@ -117,8 +117,6 @@ def test_noabort(client: Client):
|
||||
|
||||
@pytest.mark.setup_client(uninitialized=True)
|
||||
def test_ask_word_number(client: Client):
|
||||
if client.features.model == "R":
|
||||
pytest.skip("Flow is not working correctly for TR")
|
||||
with client:
|
||||
IF = InputFlowSlip39BasicRecoveryRetryFirst(client)
|
||||
client.set_input_flow(IF.get())
|
||||
|
@ -23,7 +23,7 @@ from trezorlib.debuglink import (
|
||||
from . import buttons
|
||||
from .common import (
|
||||
check_pin_backoff_time,
|
||||
click_info_button,
|
||||
click_info_button_tt,
|
||||
click_through,
|
||||
read_and_confirm_mnemonic,
|
||||
recovery_enter_shares,
|
||||
@ -396,14 +396,14 @@ class InputFlowPaymentRequestDetails(InputFlowBase):
|
||||
self.debug.press_info()
|
||||
|
||||
yield # confirm first output
|
||||
assert self.outputs[0].address[:16] in self.layout().text_content()
|
||||
assert self.outputs[0].address[:16] in self.layout().text_content() # type: ignore
|
||||
self.debug.press_yes()
|
||||
yield # confirm first output
|
||||
self.debug.wait_layout()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # confirm second output
|
||||
assert self.outputs[1].address[:16] in self.layout().text_content()
|
||||
assert self.outputs[1].address[:16] in self.layout().text_content() # type: ignore
|
||||
self.debug.press_yes()
|
||||
yield # confirm second output
|
||||
self.debug.wait_layout()
|
||||
@ -503,12 +503,12 @@ class InputFlowSignTxInformation(InputFlowBase):
|
||||
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()
|
||||
self.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()
|
||||
self.debug.press_yes()
|
||||
|
||||
|
||||
class InputFlowSignTxInformationMixed(InputFlowBase):
|
||||
@ -524,12 +524,12 @@ class InputFlowSignTxInformationMixed(InputFlowBase):
|
||||
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()
|
||||
self.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()
|
||||
self.debug.press_yes()
|
||||
|
||||
|
||||
class InputFlowSignTxInformationCancel(InputFlowBase):
|
||||
@ -538,11 +538,11 @@ class InputFlowSignTxInformationCancel(InputFlowBase):
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield from sign_tx_go_to_info(self.client)
|
||||
self.client.debug.press_no()
|
||||
self.debug.press_no()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield from sign_tx_go_to_info_tr(self.client)
|
||||
self.client.debug.press_left()
|
||||
self.debug.press_left()
|
||||
|
||||
|
||||
class InputFlowSignTxInformationReplacement(InputFlowBase):
|
||||
@ -551,15 +551,15 @@ class InputFlowSignTxInformationReplacement(InputFlowBase):
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield # confirm txid
|
||||
self.client.debug.press_yes()
|
||||
self.debug.press_yes()
|
||||
yield # confirm address
|
||||
self.client.debug.press_yes()
|
||||
self.debug.press_yes()
|
||||
# go back to address
|
||||
self.client.debug.press_no()
|
||||
self.debug.press_no()
|
||||
# confirm address
|
||||
self.client.debug.press_yes()
|
||||
self.debug.press_yes()
|
||||
yield # confirm amount
|
||||
self.client.debug.press_yes()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # transaction summary, press info
|
||||
self.client.debug.click(buttons.CORNER_BUTTON, wait=True)
|
||||
@ -568,16 +568,16 @@ class InputFlowSignTxInformationReplacement(InputFlowBase):
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield # confirm txid
|
||||
self.client.debug.press_right()
|
||||
self.client.debug.press_right()
|
||||
self.debug.press_right()
|
||||
self.debug.press_right()
|
||||
yield # confirm address
|
||||
self.client.debug.press_right()
|
||||
self.client.debug.press_right()
|
||||
self.client.debug.press_right()
|
||||
self.debug.press_right()
|
||||
self.debug.press_right()
|
||||
self.debug.press_right()
|
||||
yield # confirm amount
|
||||
self.client.debug.press_right()
|
||||
self.client.debug.press_right()
|
||||
self.client.debug.press_right()
|
||||
self.debug.press_right()
|
||||
self.debug.press_right()
|
||||
self.debug.press_right()
|
||||
|
||||
|
||||
def lock_time_input_flow_tt(
|
||||
@ -1015,13 +1015,13 @@ class InputFlowSlip39BasicBackup(InputFlowBase):
|
||||
yield # 1. Checklist
|
||||
self.debug.press_yes()
|
||||
if self.click_info:
|
||||
yield from click_info_button(self.debug)
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # 2. Number of shares (5)
|
||||
self.debug.press_yes()
|
||||
yield # 3. Checklist
|
||||
self.debug.press_yes()
|
||||
if self.click_info:
|
||||
yield from click_info_button(self.debug)
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # 4. Threshold (3)
|
||||
self.debug.press_yes()
|
||||
yield # 5. Checklist
|
||||
@ -1037,21 +1037,21 @@ class InputFlowSlip39BasicBackup(InputFlowBase):
|
||||
self.debug.press_yes()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield # Checklist
|
||||
yield # 1. Checklist
|
||||
self.debug.press_yes()
|
||||
yield # Number of shares info
|
||||
yield # 1.5 Number of shares info
|
||||
self.debug.press_yes()
|
||||
yield # Number of shares (5)
|
||||
yield # 2. Number of shares (5)
|
||||
self.debug.input("5")
|
||||
yield # Checklist
|
||||
yield # 3. Checklist
|
||||
self.debug.press_yes()
|
||||
yield # Threshold info
|
||||
yield # 3.5 Threshold info
|
||||
self.debug.press_yes()
|
||||
yield # Threshold (3)
|
||||
yield # 4. Threshold (3)
|
||||
self.debug.input("3")
|
||||
yield # Checklist
|
||||
yield # 5. Checklist
|
||||
self.debug.press_yes()
|
||||
yield # Confirm show seeds
|
||||
yield # 6. Confirm show seeds
|
||||
self.debug.press_yes()
|
||||
|
||||
# Mnemonic phrases
|
||||
@ -1143,24 +1143,24 @@ class InputFlowSlip39AdvancedBackup(InputFlowBase):
|
||||
yield # 1. Checklist
|
||||
self.debug.press_yes()
|
||||
if self.click_info:
|
||||
yield from click_info_button(self.debug)
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # 2. Set and confirm group count
|
||||
self.debug.press_yes()
|
||||
yield # 3. Checklist
|
||||
self.debug.press_yes()
|
||||
if self.click_info:
|
||||
yield from click_info_button(self.debug)
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # 4. Set and confirm group threshold
|
||||
self.debug.press_yes()
|
||||
yield # 5. Checklist
|
||||
self.debug.press_yes()
|
||||
for _ in range(5): # for each of 5 groups
|
||||
if self.click_info:
|
||||
yield from click_info_button(self.debug)
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # Set & Confirm number of shares
|
||||
self.debug.press_yes()
|
||||
if self.click_info:
|
||||
yield from click_info_button(self.debug)
|
||||
yield from click_info_button_tt(self.debug)
|
||||
yield # Set & confirm share threshold value
|
||||
self.debug.press_yes()
|
||||
yield # Confirm show seeds
|
||||
@ -1266,7 +1266,9 @@ class InputFlowSlip39AdvancedResetRecovery(InputFlowBase):
|
||||
self.debug.press_yes()
|
||||
|
||||
|
||||
def enter_recovery_seed_dry_run(debug: DebugLink, mnemonic: list[str]) -> GeneratorType:
|
||||
def enter_recovery_seed_dry_run_tt(
|
||||
debug: DebugLink, mnemonic: list[str]
|
||||
) -> GeneratorType:
|
||||
yield
|
||||
assert "check the recovery seed" in debug.wait_layout().text_content()
|
||||
debug.click(buttons.OK)
|
||||
@ -1284,7 +1286,7 @@ def enter_recovery_seed_dry_run(debug: DebugLink, mnemonic: list[str]) -> Genera
|
||||
debug.click(buttons.grid34(index % 3, index // 3))
|
||||
|
||||
yield
|
||||
assert "Enter recovery seed" in debug.wait_layout().text_content()
|
||||
assert "Enter your backup" in debug.wait_layout().text_content()
|
||||
debug.click(buttons.OK)
|
||||
|
||||
yield
|
||||
@ -1299,7 +1301,7 @@ class InputFlowBip39RecoveryDryRun(InputFlowBase):
|
||||
self.mnemonic = mnemonic
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield from enter_recovery_seed_dry_run(self.debug, self.mnemonic)
|
||||
yield from enter_recovery_seed_dry_run_tt(self.debug, self.mnemonic)
|
||||
|
||||
yield
|
||||
self.debug.wait_layout()
|
||||
@ -1310,33 +1312,9 @@ class InputFlowBip39RecoveryDryRun(InputFlowBase):
|
||||
assert "check the recovery seed" in self.layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield
|
||||
assert "number of words" in self.layout().text_content()
|
||||
self.debug.press_yes()
|
||||
yield from enter_recovery_seed_tr(self.debug, self.mnemonic)
|
||||
|
||||
yield
|
||||
yield
|
||||
assert "NUMBER OF WORDS" in self.layout().title()
|
||||
word_options = (12, 18, 20, 24, 33)
|
||||
index = word_options.index(len(self.mnemonic))
|
||||
for _ in range(index):
|
||||
self.debug.press_right()
|
||||
self.debug.input(str(len(self.mnemonic)))
|
||||
|
||||
yield
|
||||
assert "Enter recovery seed" in self.layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield
|
||||
self.debug.press_yes()
|
||||
yield
|
||||
for index, word in enumerate(self.mnemonic):
|
||||
assert "WORD" in self.layout().title()
|
||||
assert str(index + 1) in self.layout().title()
|
||||
self.debug.input(word)
|
||||
|
||||
yield
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
|
||||
|
||||
@ -1346,11 +1324,11 @@ class InputFlowBip39RecoveryDryRunInvalid(InputFlowBase):
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
mnemonic = ["stick"] * 12
|
||||
yield from enter_recovery_seed_dry_run(self.debug, mnemonic)
|
||||
yield from enter_recovery_seed_dry_run_tt(self.debug, mnemonic)
|
||||
|
||||
br = yield
|
||||
assert br.code == messages.ButtonRequestType.Warning
|
||||
assert "invalid recovery seed" in self.layout().text_content()
|
||||
assert "Invalid recovery seed" in self.layout().text_content()
|
||||
self.debug.click(buttons.OK)
|
||||
|
||||
yield # retry screen
|
||||
@ -1358,7 +1336,7 @@ class InputFlowBip39RecoveryDryRunInvalid(InputFlowBase):
|
||||
self.debug.click(buttons.CANCEL)
|
||||
|
||||
yield
|
||||
assert "ABORT SEED CHECK" == self.layout().title()
|
||||
assert "ABORT BACKUP CHECK" == self.layout().title()
|
||||
self.debug.click(buttons.OK)
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
@ -1366,33 +1344,13 @@ class InputFlowBip39RecoveryDryRunInvalid(InputFlowBase):
|
||||
assert "check the recovery seed" in self.layout().text_content()
|
||||
self.debug.press_right()
|
||||
|
||||
yield
|
||||
assert "number of words" in self.layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield
|
||||
yield
|
||||
assert "NUMBER OF WORDS" in self.layout().title()
|
||||
# select 12 words
|
||||
self.debug.press_middle()
|
||||
|
||||
yield
|
||||
assert "Enter recovery seed" in self.layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield
|
||||
assert "WORD ENTERING" in self.layout().title()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield
|
||||
for _ in range(12):
|
||||
assert "WORD" in self.layout().title()
|
||||
self.debug.input("stick")
|
||||
mnemonic = ["stick"] * 12
|
||||
yield from enter_recovery_seed_tr(self.debug, mnemonic)
|
||||
|
||||
br = yield
|
||||
assert br.code == messages.ButtonRequestType.Warning
|
||||
assert "invalid recovery seed" in self.layout().text_content()
|
||||
self.debug.press_right()
|
||||
assert "Invalid recovery seed" in self.layout().text_content()
|
||||
self.debug.press_middle()
|
||||
|
||||
yield # retry screen
|
||||
assert "number of words" in self.layout().text_content()
|
||||
@ -1403,7 +1361,7 @@ class InputFlowBip39RecoveryDryRunInvalid(InputFlowBase):
|
||||
self.debug.press_right()
|
||||
|
||||
|
||||
def bip39_recovery_possible_pin(
|
||||
def bip39_recovery_possible_pin_tt(
|
||||
debug: DebugLink, mnemonic: list[str], pin: Optional[str]
|
||||
) -> GeneratorType:
|
||||
yield
|
||||
@ -1429,7 +1387,7 @@ def bip39_recovery_possible_pin(
|
||||
debug.input(str(len(mnemonic)))
|
||||
|
||||
yield
|
||||
assert "Enter recovery seed" in debug.wait_layout().text_content()
|
||||
assert "Enter your backup" in debug.wait_layout().text_content()
|
||||
debug.press_yes()
|
||||
|
||||
yield
|
||||
@ -1438,65 +1396,76 @@ def bip39_recovery_possible_pin(
|
||||
debug.input(word)
|
||||
|
||||
yield
|
||||
assert (
|
||||
"You have finished recovering your wallet."
|
||||
in debug.wait_layout().text_content()
|
||||
)
|
||||
assert "Wallet recovered successfully" in debug.wait_layout().text_content()
|
||||
debug.press_yes()
|
||||
|
||||
|
||||
def bip39_recovery_possible_pin_tr(
|
||||
debug: DebugLink, mnemonic: list[str], pin: Optional[str]
|
||||
) -> GeneratorType:
|
||||
yield
|
||||
assert "By continuing you agree" in debug.wait_layout().text_content()
|
||||
debug.press_right()
|
||||
assert "trezor.io/tos" in debug.wait_layout().text_content()
|
||||
debug.press_yes()
|
||||
|
||||
yield
|
||||
assert "safe to eject" in debug.wait_layout().text_content()
|
||||
debug.press_yes()
|
||||
|
||||
# PIN when requested
|
||||
if pin is not None:
|
||||
yield
|
||||
debug.input("654")
|
||||
|
||||
yield
|
||||
assert "re-enter to confirm" in debug.wait_layout().text_content()
|
||||
debug.press_right()
|
||||
|
||||
yield
|
||||
debug.input("654")
|
||||
|
||||
yield from enter_recovery_seed_tr(debug, mnemonic)
|
||||
|
||||
yield
|
||||
assert "Wallet recovered successfully" in debug.wait_layout().text_content()
|
||||
debug.press_yes()
|
||||
|
||||
|
||||
def enter_recovery_seed_tr(debug: DebugLink, mnemonic: list[str]) -> GeneratorType:
|
||||
yield
|
||||
assert "number of words" in debug.wait_layout().text_content()
|
||||
debug.press_yes()
|
||||
|
||||
yield
|
||||
assert "NUMBER OF WORDS" in debug.wait_layout().title()
|
||||
debug.input(str(len(mnemonic)))
|
||||
|
||||
yield
|
||||
assert "Enter your backup" in debug.wait_layout().text_content()
|
||||
# Paginate to see info
|
||||
debug.press_right()
|
||||
debug.press_right()
|
||||
debug.press_yes()
|
||||
|
||||
yield
|
||||
for index, word in enumerate(mnemonic):
|
||||
title = debug.wait_layout().title()
|
||||
assert "WORD" in title
|
||||
assert str(index + 1) in title
|
||||
debug.input(word)
|
||||
|
||||
|
||||
class InputFlowBip39RecoveryPIN(InputFlowBase):
|
||||
def __init__(self, client: Client, mnemonic: list[str]):
|
||||
super().__init__(client)
|
||||
self.mnemonic = mnemonic
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield from bip39_recovery_possible_pin(self.debug, self.mnemonic, pin="654")
|
||||
yield from bip39_recovery_possible_pin_tt(self.debug, self.mnemonic, pin="654")
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield
|
||||
assert "By continuing you agree" in self.layout().text_content()
|
||||
self.debug.press_right()
|
||||
assert "trezor.io/tos" in self.layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield
|
||||
self.debug.input("654")
|
||||
|
||||
yield
|
||||
assert "re-enter PIN" in self.layout().text_content()
|
||||
self.debug.press_right()
|
||||
|
||||
yield
|
||||
self.debug.input("654")
|
||||
|
||||
yield
|
||||
assert "number of words" in self.layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield
|
||||
yield
|
||||
assert "NUMBER OF WORDS" in self.layout().title()
|
||||
self.debug.input(str(len(self.mnemonic)))
|
||||
|
||||
yield
|
||||
assert "Enter recovery seed" in self.layout().text_content()
|
||||
self.debug.press_yes()
|
||||
|
||||
yield
|
||||
assert "WORD ENTERING" in self.layout().title()
|
||||
self.debug.press_right()
|
||||
|
||||
yield
|
||||
for word in self.mnemonic:
|
||||
assert "WORD" in self.layout().title()
|
||||
self.debug.input(word)
|
||||
|
||||
yield
|
||||
assert (
|
||||
"You have finished recovering your wallet." in self.layout().text_content()
|
||||
)
|
||||
self.debug.press_yes()
|
||||
yield from bip39_recovery_possible_pin_tr(self.debug, self.mnemonic, pin="654")
|
||||
|
||||
|
||||
class InputFlowBip39RecoveryNoPIN(InputFlowBase):
|
||||
@ -1505,28 +1474,10 @@ class InputFlowBip39RecoveryNoPIN(InputFlowBase):
|
||||
self.mnemonic = mnemonic
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield from bip39_recovery_possible_pin(self.debug, self.mnemonic, pin=None)
|
||||
yield from bip39_recovery_possible_pin_tt(self.debug, self.mnemonic, pin=None)
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield # Confirm recovery
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # Enter word count
|
||||
self.debug.input(str(len(self.mnemonic)))
|
||||
|
||||
yield # Homescreen
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen
|
||||
self.debug.press_yes()
|
||||
yield # Enter words
|
||||
for word in self.mnemonic:
|
||||
self.debug.input(word)
|
||||
|
||||
yield # confirm success
|
||||
self.debug.press_yes()
|
||||
yield
|
||||
yield from bip39_recovery_possible_pin_tr(self.debug, self.mnemonic, pin=None)
|
||||
|
||||
|
||||
class InputFlowSlip39AdvancedRecoveryDryRun(InputFlowBase):
|
||||
@ -1541,6 +1492,18 @@ class InputFlowSlip39AdvancedRecoveryDryRun(InputFlowBase):
|
||||
yield from recovery_enter_shares(self.debug, self.shares, groups=True)
|
||||
|
||||
|
||||
def confirm_recovery(debug: DebugLink) -> GeneratorType:
|
||||
if debug.model == "T":
|
||||
yield # Confirm Recovery
|
||||
debug.press_yes()
|
||||
elif debug.model == "R":
|
||||
yield # Confirm Recovery
|
||||
debug.press_right()
|
||||
debug.press_yes()
|
||||
yield # Safe to eject
|
||||
debug.press_yes()
|
||||
|
||||
|
||||
class InputFlowSlip39AdvancedRecovery(InputFlowBase):
|
||||
def __init__(self, client: Client, shares: list[str], click_info: bool):
|
||||
super().__init__(client)
|
||||
@ -1548,9 +1511,7 @@ class InputFlowSlip39AdvancedRecovery(InputFlowBase):
|
||||
self.click_info = click_info
|
||||
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
# Proceed with recovery
|
||||
yield from confirm_recovery(self.debug)
|
||||
yield from recovery_enter_shares(
|
||||
self.debug, self.shares, groups=True, click_info=self.click_info
|
||||
)
|
||||
@ -1561,8 +1522,7 @@ class InputFlowSlip39AdvancedRecoveryAbort(InputFlowBase):
|
||||
super().__init__(client)
|
||||
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
yield from confirm_recovery(self.debug)
|
||||
yield # Homescreen - abort process
|
||||
self.debug.press_no()
|
||||
yield # Homescreen - confirm abort
|
||||
@ -1575,11 +1535,12 @@ class InputFlowSlip39AdvancedRecoveryNoAbort(InputFlowBase):
|
||||
self.shares = shares
|
||||
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
yield from confirm_recovery(self.debug)
|
||||
yield # Homescreen - abort process
|
||||
self.debug.press_no()
|
||||
yield # Homescreen - go back to process
|
||||
if self.debug.model == "R":
|
||||
self.debug.press_right()
|
||||
self.debug.press_no()
|
||||
yield from recovery_enter_shares(self.debug, self.shares, groups=True)
|
||||
|
||||
@ -1590,18 +1551,9 @@ class InputFlowSlip39AdvancedRecoveryTwoSharesWarning(InputFlowBase):
|
||||
self.first_share = first_share
|
||||
self.second_share = second_share
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen - start process
|
||||
self.debug.press_yes()
|
||||
yield # Enter number of words
|
||||
self.debug.input(str(len(self.first_share)))
|
||||
yield # Homescreen - proceed to share entry
|
||||
self.debug.press_yes()
|
||||
yield # Enter first share
|
||||
for word in self.first_share:
|
||||
self.debug.input(word)
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield from confirm_recovery(self.debug)
|
||||
yield from slip39_recovery_setup_and_first_share(self.debug, self.first_share)
|
||||
|
||||
yield # Continue to next share
|
||||
self.debug.press_yes()
|
||||
@ -1613,38 +1565,6 @@ class InputFlowSlip39AdvancedRecoveryTwoSharesWarning(InputFlowBase):
|
||||
|
||||
br = yield
|
||||
assert br.code == messages.ButtonRequestType.Warning
|
||||
|
||||
self.client.cancel()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen - start process
|
||||
self.debug.press_yes()
|
||||
yield # Enter number of words
|
||||
self.debug.input(str(len(self.first_share)))
|
||||
yield # Homescreen - proceed to share entry
|
||||
self.debug.press_yes()
|
||||
yield # Enter first share
|
||||
self.debug.press_yes()
|
||||
yield # Enter first share
|
||||
for word in self.first_share:
|
||||
self.debug.input(word)
|
||||
|
||||
yield # Continue to next share
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen - next share
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen - next share
|
||||
self.debug.press_yes()
|
||||
yield # Enter next share
|
||||
for word in self.second_share:
|
||||
self.debug.input(word)
|
||||
|
||||
yield
|
||||
br = yield
|
||||
assert br.code == messages.ButtonRequestType.Warning
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
yield
|
||||
|
||||
@ -1655,6 +1575,11 @@ def slip39_recovery_possible_pin(
|
||||
debug: DebugLink, shares: list[str], pin: Optional[str]
|
||||
) -> GeneratorType:
|
||||
yield # Confirm Recovery/Dryrun
|
||||
if debug.model == "R" and "BACKUP CHECK" not in debug.wait_layout().title():
|
||||
# dryruns do not have extra dialogs
|
||||
debug.press_right()
|
||||
debug.press_yes()
|
||||
yield
|
||||
debug.press_yes()
|
||||
|
||||
if pin is not None:
|
||||
@ -1694,8 +1619,7 @@ class InputFlowSlip39BasicRecoveryAbort(InputFlowBase):
|
||||
super().__init__(client)
|
||||
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
yield from confirm_recovery(self.debug)
|
||||
yield # Homescreen - abort process
|
||||
self.debug.press_no()
|
||||
yield # Homescreen - confirm abort
|
||||
@ -1708,11 +1632,12 @@ class InputFlowSlip39BasicRecoveryNoAbort(InputFlowBase):
|
||||
self.shares = shares
|
||||
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
yield from confirm_recovery(self.debug)
|
||||
yield # Homescreen - abort process
|
||||
self.debug.press_no()
|
||||
yield # Homescreen - go back to process
|
||||
if self.debug.model == "R":
|
||||
self.debug.press_right()
|
||||
self.debug.press_no()
|
||||
# run recovery flow
|
||||
yield from recovery_enter_shares(self.debug, self.shares)
|
||||
@ -1726,6 +1651,9 @@ def slip39_recovery_setup_and_first_share(
|
||||
yield # Enter number of words
|
||||
debug.input(str(len(first_share)))
|
||||
yield # Homescreen - proceed to share entry
|
||||
if debug.model == "R":
|
||||
debug.press_right(wait=True)
|
||||
debug.press_right(wait=True)
|
||||
debug.press_yes()
|
||||
yield # Enter first share
|
||||
for word in first_share:
|
||||
@ -1736,9 +1664,8 @@ class InputFlowSlip39BasicRecoveryRetryFirst(InputFlowBase):
|
||||
def __init__(self, client: Client):
|
||||
super().__init__(client)
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield from confirm_recovery(self.debug)
|
||||
|
||||
first_share = ["slush"] * 20
|
||||
yield from slip39_recovery_setup_and_first_share(self.debug, first_share)
|
||||
@ -1757,55 +1684,8 @@ class InputFlowSlip39BasicRecoveryRetryFirst(InputFlowBase):
|
||||
yield # Homescreen
|
||||
self.debug.press_no()
|
||||
yield # Confirm abort
|
||||
self.debug.press_yes()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen - start process
|
||||
self.debug.press_yes()
|
||||
yield # Enter number of words
|
||||
self.debug.input("20")
|
||||
yield # Homescreen - proceed to share entry
|
||||
self.debug.press_yes()
|
||||
yield # Enter first share
|
||||
self.debug.press_yes()
|
||||
for _ in range(20):
|
||||
self.debug.input("slush")
|
||||
|
||||
yield
|
||||
# assert br.code == messages.ButtonRequestType.Warning
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # Homescreen - start process
|
||||
self.debug.press_yes()
|
||||
yield # Enter number of words
|
||||
self.debug.input("33")
|
||||
yield # Homescreen - proceed to share entry
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen - proceed to share entry
|
||||
self.debug.press_yes()
|
||||
yield
|
||||
for _ in range(33):
|
||||
self.debug.input("slush")
|
||||
|
||||
yield
|
||||
self.debug.press_yes()
|
||||
|
||||
yield
|
||||
self.debug.press_no()
|
||||
|
||||
yield
|
||||
self.debug.press_right()
|
||||
|
||||
yield
|
||||
self.debug.press_right()
|
||||
|
||||
yield
|
||||
self.debug.press_right()
|
||||
|
||||
yield
|
||||
if self.debug.model == "R":
|
||||
self.debug.press_right(wait=True)
|
||||
self.debug.press_yes()
|
||||
|
||||
|
||||
@ -1814,9 +1694,8 @@ class InputFlowSlip39BasicRecoveryRetrySecond(InputFlowBase):
|
||||
super().__init__(client)
|
||||
self.shares = shares
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield from confirm_recovery(self.debug)
|
||||
|
||||
# First valid share
|
||||
first_share = self.shares[0].split(" ")
|
||||
@ -1842,45 +1721,8 @@ class InputFlowSlip39BasicRecoveryRetrySecond(InputFlowBase):
|
||||
yield # More shares needed
|
||||
self.debug.press_no()
|
||||
yield # Confirm abort
|
||||
self.debug.press_yes()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen - start process
|
||||
self.debug.press_yes()
|
||||
yield # Enter number of words
|
||||
self.debug.input("20")
|
||||
yield # Homescreen - proceed to share entry
|
||||
self.debug.press_yes()
|
||||
yield # Enter first share
|
||||
self.debug.press_yes()
|
||||
yield # Enter first share
|
||||
share = self.shares[0].split(" ")
|
||||
for word in share:
|
||||
self.debug.input(word)
|
||||
|
||||
yield # More shares needed
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # Enter another share
|
||||
share = share[:3] + ["slush"] * 17
|
||||
for word in share:
|
||||
self.debug.input(word)
|
||||
|
||||
yield # Invalid share
|
||||
# assert br.code == messages.ButtonRequestType.Warning
|
||||
self.debug.press_yes()
|
||||
|
||||
yield # Proceed to next share
|
||||
share = self.shares[1].split(" ")
|
||||
for word in share:
|
||||
self.debug.input(word)
|
||||
|
||||
yield # More shares needed
|
||||
self.debug.press_no()
|
||||
yield # Confirm abort
|
||||
if self.debug.model == "R":
|
||||
self.debug.press_right(wait=True)
|
||||
self.debug.press_yes()
|
||||
|
||||
|
||||
@ -1890,9 +1732,8 @@ class InputFlowSlip39BasicRecoveryWrongNthWord(InputFlowBase):
|
||||
self.share = share
|
||||
self.nth_word = nth_word
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield from confirm_recovery(self.debug)
|
||||
|
||||
# First complete share
|
||||
yield from slip39_recovery_setup_and_first_share(self.debug, self.share)
|
||||
@ -1909,39 +1750,8 @@ class InputFlowSlip39BasicRecoveryWrongNthWord(InputFlowBase):
|
||||
|
||||
br = yield
|
||||
assert br.code == messages.ButtonRequestType.Warning
|
||||
|
||||
self.client.cancel()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen - start process
|
||||
self.debug.press_yes()
|
||||
yield # Enter number of words
|
||||
self.debug.input(str(len(self.share)))
|
||||
yield # Homescreen - proceed to share entry
|
||||
self.debug.press_yes()
|
||||
yield # Enter first share
|
||||
self.debug.press_yes()
|
||||
yield # Enter first share
|
||||
for word in self.share:
|
||||
self.debug.input(word)
|
||||
|
||||
yield # Continue to next share
|
||||
self.debug.press_yes()
|
||||
yield # Enter next share
|
||||
self.debug.press_yes()
|
||||
yield # Enter next share
|
||||
for i, word in enumerate(self.share):
|
||||
if i < self.nth_word:
|
||||
self.debug.input(word)
|
||||
else:
|
||||
self.debug.input(self.share[-1])
|
||||
break
|
||||
|
||||
yield
|
||||
# assert br.code == messages.ButtonRequestType.Warning
|
||||
|
||||
self.client.cancel()
|
||||
|
||||
@ -1952,9 +1762,8 @@ class InputFlowSlip39BasicRecoverySameShare(InputFlowBase):
|
||||
self.first_share = first_share
|
||||
self.second_share = second_share
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_yes()
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield from confirm_recovery(self.debug)
|
||||
|
||||
# First complete share
|
||||
yield from slip39_recovery_setup_and_first_share(self.debug, self.first_share)
|
||||
@ -1967,44 +1776,9 @@ class InputFlowSlip39BasicRecoverySameShare(InputFlowBase):
|
||||
|
||||
br = yield
|
||||
assert br.code == messages.ButtonRequestType.Warning
|
||||
|
||||
# To catch the WARNING screen
|
||||
self.debug.press_yes()
|
||||
|
||||
yield
|
||||
|
||||
self.client.cancel()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen - start process
|
||||
self.debug.press_yes()
|
||||
yield # Enter number of words
|
||||
self.debug.input(str(len(self.first_share)))
|
||||
yield # Homescreen - proceed to share entry
|
||||
self.debug.press_yes()
|
||||
yield # Homescreen - proceed to share entry
|
||||
self.debug.press_yes()
|
||||
yield # Enter first share
|
||||
for word in self.first_share:
|
||||
self.debug.input(word)
|
||||
|
||||
yield # Continue to next share
|
||||
self.debug.press_yes()
|
||||
yield # Continue to next share
|
||||
self.debug.press_yes()
|
||||
yield # Enter next share
|
||||
for word in self.second_share:
|
||||
self.debug.input(word)
|
||||
|
||||
br = yield
|
||||
br = yield
|
||||
assert br.code == messages.ButtonRequestType.Warning
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
yield
|
||||
|
||||
self.client.cancel()
|
||||
|
||||
|
||||
@ -2012,19 +1786,14 @@ class InputFlowResetSkipBackup(InputFlowBase):
|
||||
def __init__(self, client: Client):
|
||||
super().__init__(client)
|
||||
|
||||
def input_flow_tt(self) -> GeneratorType:
|
||||
def input_flow_common(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
if self.debug.model == "R":
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
yield # Skip Backup
|
||||
self.debug.press_no()
|
||||
yield # Confirm skip backup
|
||||
self.debug.press_no()
|
||||
|
||||
def input_flow_tr(self) -> GeneratorType:
|
||||
yield # Confirm Recovery
|
||||
self.debug.press_right()
|
||||
self.debug.press_yes()
|
||||
yield # Skip Backup
|
||||
self.debug.press_no()
|
||||
yield # Confirm skip backup
|
||||
if self.debug.model == "R":
|
||||
self.debug.press_right()
|
||||
self.debug.press_no()
|
||||
|
@ -42,7 +42,7 @@ def test_abort(core_emulator: Emulator):
|
||||
|
||||
device_handler.run(device.recover, pin_protection=False)
|
||||
|
||||
assert debug.wait_layout().title() == "WALLET RECOVERY"
|
||||
assert debug.wait_layout().title() == "RECOVER WALLET"
|
||||
|
||||
layout = debug.click(buttons.OK, wait=True)
|
||||
assert "number of words" in layout.text_content()
|
||||
@ -174,7 +174,7 @@ def test_recovery_multiple_resets(core_emulator: Emulator):
|
||||
expected_text = "You have entered"
|
||||
debug = _restart(device_handler, core_emulator)
|
||||
|
||||
assert "You have finished recovering your wallet" in layout.text_content()
|
||||
assert "Wallet recovered successfully" in layout.text_content()
|
||||
|
||||
device_handler = BackgroundDeviceHandler(core_emulator.client)
|
||||
debug = device_handler.debuglink()
|
||||
|
@ -313,7 +313,10 @@ def test_upgrade_shamir_recovery(gen: str, tag: Optional[str]):
|
||||
recovery.select_number_of_words(debug, wait=not debug.legacy_debug)
|
||||
layout = recovery.enter_share(debug, MNEMONIC_SLIP39_BASIC_20_3of6[0])
|
||||
if not debug.legacy_ui and not debug.legacy_debug:
|
||||
assert "2 more shares" in layout.text_content()
|
||||
assert (
|
||||
"1 of 3 shares entered" in layout.text_content()
|
||||
or "2 more shares" in layout.text_content()
|
||||
)
|
||||
|
||||
device_id = emu.client.features.device_id
|
||||
storage = emu.get_storage()
|
||||
@ -327,11 +330,17 @@ def test_upgrade_shamir_recovery(gen: str, tag: Optional[str]):
|
||||
|
||||
# second share
|
||||
layout = recovery.enter_share(debug, MNEMONIC_SLIP39_BASIC_20_3of6[2])
|
||||
assert "1 more share" in layout.text_content()
|
||||
assert (
|
||||
"2 of 3 shares entered" in layout.text_content()
|
||||
or "1 more share" in layout.text_content()
|
||||
)
|
||||
|
||||
# last one
|
||||
layout = recovery.enter_share(debug, MNEMONIC_SLIP39_BASIC_20_3of6[1])
|
||||
assert "You have finished recovering your wallet" in layout.text_content()
|
||||
assert (
|
||||
"Wallet recovered successfully" in layout.text_content()
|
||||
or "finished recovering" in layout.text_content()
|
||||
)
|
||||
|
||||
# Check the result
|
||||
state = debug.state()
|
||||
|
Loading…
Reference in New Issue
Block a user