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