mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-08-04 04:48:48 +00:00
WIP - some feedback from product
This commit is contained in:
parent
cf538e5789
commit
aa4c3551d4
Binary file not shown.
Before Width: | Height: | Size: 135 B After Width: | Height: | Size: 134 B |
@ -10,11 +10,23 @@ pub fn shuffle<T>(slice: &mut [T]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a random number in the range [min, max].
|
||||||
pub fn uniform_between(min: u32, max: u32) -> u32 {
|
pub fn uniform_between(min: u32, max: u32) -> u32 {
|
||||||
assert!(max > min);
|
assert!(max > min);
|
||||||
uniform(max - min + 1) + min
|
uniform(max - min + 1) + min
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a random number in the range [min, max] except one `except` number.
|
||||||
|
pub fn uniform_between_except(min: u32, max: u32, except: u32) -> u32 {
|
||||||
|
// Generate uniform_between as long as it is not except
|
||||||
|
loop {
|
||||||
|
let rand = uniform_between(min, max);
|
||||||
|
if rand != except {
|
||||||
|
return rand;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -27,4 +39,11 @@ mod tests {
|
|||||||
assert!((256..=512).contains(&uniform_between(256, 512)));
|
assert!((256..=512).contains(&uniform_between(256, 512)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn uniform_between_except_test() {
|
||||||
|
for _ in 0..10 {
|
||||||
|
assert!(uniform_between_except(10, 12, 11) != 11);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -545,6 +545,15 @@ impl ButtonLayout {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Left text and right arrow.
|
||||||
|
pub fn text_none_arrow(text: StrBuffer) -> Self {
|
||||||
|
Self::new(
|
||||||
|
Some(ButtonDetails::text(text)),
|
||||||
|
None,
|
||||||
|
Some(ButtonDetails::right_arrow_icon()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Only right text.
|
/// Only right text.
|
||||||
pub fn none_none_text(text: StrBuffer) -> Self {
|
pub fn none_none_text(text: StrBuffer) -> Self {
|
||||||
Self::new(None, None, Some(ButtonDetails::text(text)))
|
Self::new(None, None, Some(ButtonDetails::text(text)))
|
||||||
|
@ -36,13 +36,10 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Aligning the title to the center, instead of the left.
|
/// Aligning the title to the center, instead of the left.
|
||||||
/// Also disabling scrollbar in the positive case, as they are not
|
/// Also disabling scrollbar, as they are not compatible.
|
||||||
/// compatible.
|
pub fn with_title_centered(mut self) -> Self {
|
||||||
pub fn with_title_center(mut self, title_centered: bool) -> Self {
|
self.title_centered = true;
|
||||||
self.title_centered = title_centered;
|
self.account_for_scrollbar = false;
|
||||||
if title_centered {
|
|
||||||
self.account_for_scrollbar = false;
|
|
||||||
}
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,6 +44,17 @@ impl ChoiceItem {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Getting the offset of the icon to center it vertically.
|
||||||
|
/// Depending on its size and used font.
|
||||||
|
fn icon_vertical_offset(&self) -> Offset {
|
||||||
|
if let Some(icon) = self.icon {
|
||||||
|
let height_diff = self.font.text_height() - icon.height();
|
||||||
|
Offset::y(-height_diff / 2)
|
||||||
|
} else {
|
||||||
|
Offset::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Getting the text width in pixels.
|
/// Getting the text width in pixels.
|
||||||
pub fn text_width(&self) -> i16 {
|
pub fn text_width(&self) -> i16 {
|
||||||
self.font.text_width(&self.text)
|
self.font.text_width(&self.text)
|
||||||
@ -88,7 +99,11 @@ impl ChoiceItem {
|
|||||||
/// Showing only the icon, if available, otherwise the text.
|
/// Showing only the icon, if available, otherwise the text.
|
||||||
pub fn render_left(&self, area: Rect) {
|
pub fn render_left(&self, area: Rect) {
|
||||||
if let Some(icon) = self.icon {
|
if let Some(icon) = self.icon {
|
||||||
icon.draw_bottom_right(area.bottom_right(), theme::FG, theme::BG);
|
icon.draw_bottom_right(
|
||||||
|
area.bottom_right() + self.icon_vertical_offset(),
|
||||||
|
theme::FG,
|
||||||
|
theme::BG,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
display_right(area.bottom_right(), &self.text, self.font);
|
display_right(area.bottom_right(), &self.text, self.font);
|
||||||
}
|
}
|
||||||
@ -98,7 +113,11 @@ impl ChoiceItem {
|
|||||||
/// Showing only the icon, if available, otherwise the text.
|
/// Showing only the icon, if available, otherwise the text.
|
||||||
pub fn render_right(&self, area: Rect) {
|
pub fn render_right(&self, area: Rect) {
|
||||||
if let Some(icon) = self.icon {
|
if let Some(icon) = self.icon {
|
||||||
icon.draw_bottom_left(area.bottom_left(), theme::FG, theme::BG);
|
icon.draw_bottom_left(
|
||||||
|
area.bottom_left() + self.icon_vertical_offset(),
|
||||||
|
theme::FG,
|
||||||
|
theme::BG,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
display(area.bottom_left(), &self.text, self.font);
|
display(area.bottom_left(), &self.text, self.font);
|
||||||
}
|
}
|
||||||
@ -135,7 +154,7 @@ impl Choice for ChoiceItem {
|
|||||||
if let Some(icon) = self.icon {
|
if let Some(icon) = self.icon {
|
||||||
let fg_color = if inverse { theme::BG } else { theme::FG };
|
let fg_color = if inverse { theme::BG } else { theme::FG };
|
||||||
let bg_color = if inverse { theme::FG } else { theme::BG };
|
let bg_color = if inverse { theme::FG } else { theme::BG };
|
||||||
icon.draw_bottom_left(baseline, fg_color, bg_color);
|
icon.draw_bottom_left(baseline + self.icon_vertical_offset(), fg_color, bg_color);
|
||||||
baseline = baseline + Offset::x(icon.width() + 2);
|
baseline = baseline + Offset::x(icon.width() + 2);
|
||||||
}
|
}
|
||||||
if inverse {
|
if inverse {
|
||||||
|
@ -193,10 +193,12 @@ impl Component for PinEntry {
|
|||||||
_ => {
|
_ => {
|
||||||
if !self.is_full() {
|
if !self.is_full() {
|
||||||
self.append_new_digit(ctx, page_counter);
|
self.append_new_digit(ctx, page_counter);
|
||||||
// Choosing any random digit to be shown next
|
// Choosing random digit to be shown next, but different
|
||||||
let new_page_counter = random::uniform_between(
|
// from the current choice.
|
||||||
|
let new_page_counter = random::uniform_between_except(
|
||||||
NUMBER_START_INDEX as u32,
|
NUMBER_START_INDEX as u32,
|
||||||
(CHOICE_LENGTH - 1) as u32,
|
(CHOICE_LENGTH - 1) as u32,
|
||||||
|
page_counter as u32,
|
||||||
);
|
);
|
||||||
self.choice_page
|
self.choice_page
|
||||||
.set_page_counter(ctx, new_page_counter as u8);
|
.set_page_counter(ctx, new_page_counter as u8);
|
||||||
|
@ -75,6 +75,13 @@ impl<const N: usize> SimpleChoice<N> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Show choices even when they do not fit entirely.
|
||||||
|
pub fn with_show_incomplete(mut self) -> Self {
|
||||||
|
self.choice_page = self.choice_page.with_incomplete(true);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returning chosen page index instead of the string result.
|
||||||
pub fn with_return_index(mut self) -> Self {
|
pub fn with_return_index(mut self) -> Self {
|
||||||
self.return_index = true;
|
self.return_index = true;
|
||||||
self
|
self
|
||||||
|
@ -149,8 +149,6 @@ impl Loader {
|
|||||||
// NOTE: need to calculate this in `i32`, it would overflow using `i16`
|
// NOTE: need to calculate this in `i32`, it would overflow using `i16`
|
||||||
let invert_from = ((self.area.width() as i32 + 1) * done) / (display::LOADER_MAX as i32);
|
let invert_from = ((self.area.width() as i32 + 1) * done) / (display::LOADER_MAX as i32);
|
||||||
|
|
||||||
// TODO: the text should be moved one pixel to the top so it is centered in the
|
|
||||||
// loader
|
|
||||||
display::bar_with_text_and_fill(
|
display::bar_with_text_and_fill(
|
||||||
self.area,
|
self.area,
|
||||||
Some(&self.text_overlay),
|
Some(&self.text_overlay),
|
||||||
@ -167,7 +165,8 @@ impl Component for Loader {
|
|||||||
|
|
||||||
fn place(&mut self, bounds: Rect) -> Rect {
|
fn place(&mut self, bounds: Rect) -> Rect {
|
||||||
self.area = bounds;
|
self.area = bounds;
|
||||||
let baseline = bounds.bottom_center() + Offset::new(1, -1);
|
// Centering the text in the loader rectangle.
|
||||||
|
let baseline = bounds.bottom_center() + Offset::new(1, -2);
|
||||||
self.text_overlay.place(baseline);
|
self.text_overlay.place(baseline);
|
||||||
self.area
|
self.area
|
||||||
}
|
}
|
||||||
|
@ -414,7 +414,7 @@ extern "C" fn new_show_receive_address(n_args: usize, args: *const Obj, kwargs:
|
|||||||
.text_bold("ADDRESS MISMATCH?".into())
|
.text_bold("ADDRESS MISMATCH?".into())
|
||||||
.newline()
|
.newline()
|
||||||
.newline_half()
|
.newline_half()
|
||||||
.text_mono("Please contact Trezor support on trezor.io/support".into())
|
.text_mono("Please contact Trezor support at trezor.io/support".into())
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
@ -565,7 +565,7 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
|
|||||||
tutorial_screen(
|
tutorial_screen(
|
||||||
"HELLO".into(),
|
"HELLO".into(),
|
||||||
"Welcome to Trezor.\nPress right to continue.".into(),
|
"Welcome to Trezor.\nPress right to continue.".into(),
|
||||||
ButtonLayout::cancel_none_arrow(),
|
ButtonLayout::text_none_arrow("SKIP".into()),
|
||||||
ButtonActions::last_none_next(),
|
ButtonActions::last_none_next(),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -609,7 +609,7 @@ extern "C" fn tutorial(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj
|
|||||||
Font::MONO,
|
Font::MONO,
|
||||||
)
|
)
|
||||||
.newline()
|
.newline()
|
||||||
.text_mono("Tutorial finished.".into())
|
.text_mono("Tutorial complete.".into())
|
||||||
.newline()
|
.newline()
|
||||||
.newline()
|
.newline()
|
||||||
.alignment(Alignment::Center)
|
.alignment(Alignment::Center)
|
||||||
@ -655,10 +655,9 @@ extern "C" fn new_request_number(n_args: usize, args: *const Obj, kwargs: *mut M
|
|||||||
let max_count: u32 = kwargs.get(Qstr::MP_QSTR_max_count)?.try_into()?;
|
let max_count: u32 = kwargs.get(Qstr::MP_QSTR_max_count)?.try_into()?;
|
||||||
let count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?;
|
let count: u32 = kwargs.get(Qstr::MP_QSTR_count)?.try_into()?;
|
||||||
|
|
||||||
let obj = LayoutObj::new(Frame::new(
|
let obj = LayoutObj::new(
|
||||||
title,
|
Frame::new(title, NumberInput::new(min_count, max_count, count)).with_title_centered(),
|
||||||
NumberInput::new(min_count, max_count, count),
|
)?;
|
||||||
))?;
|
|
||||||
Ok(obj.into())
|
Ok(obj.into())
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
@ -736,10 +735,10 @@ extern "C" fn new_select_word(n_args: usize, args: *const Obj, kwargs: *mut Map)
|
|||||||
Frame::new(
|
Frame::new(
|
||||||
title,
|
title,
|
||||||
SimpleChoice::new(words, false)
|
SimpleChoice::new(words, false)
|
||||||
.with_only_one_item()
|
.with_show_incomplete()
|
||||||
.with_return_index(),
|
.with_return_index(),
|
||||||
)
|
)
|
||||||
.with_title_center(true),
|
.with_title_centered(),
|
||||||
)?;
|
)?;
|
||||||
Ok(obj.into())
|
Ok(obj.into())
|
||||||
};
|
};
|
||||||
@ -756,7 +755,9 @@ extern "C" fn new_select_word_count(n_args: usize, args: *const Obj, kwargs: *mu
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let obj = LayoutObj::new(Frame::new(title, SimpleChoice::new(choices, false)))?;
|
let obj = LayoutObj::new(
|
||||||
|
Frame::new(title, SimpleChoice::new(choices, false)).with_title_centered(),
|
||||||
|
)?;
|
||||||
Ok(obj.into())
|
Ok(obj.into())
|
||||||
};
|
};
|
||||||
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
|
||||||
@ -767,7 +768,7 @@ extern "C" fn new_request_bip39(n_args: usize, args: *const Obj, kwargs: *mut Ma
|
|||||||
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
|
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
|
||||||
|
|
||||||
let obj = LayoutObj::new(
|
let obj = LayoutObj::new(
|
||||||
Frame::new(prompt, WordlistEntry::new(WordlistType::Bip39)).with_title_center(true),
|
Frame::new(prompt, WordlistEntry::new(WordlistType::Bip39)).with_title_centered(),
|
||||||
)?;
|
)?;
|
||||||
Ok(obj.into())
|
Ok(obj.into())
|
||||||
};
|
};
|
||||||
@ -779,7 +780,7 @@ extern "C" fn new_request_slip39(n_args: usize, args: *const Obj, kwargs: *mut M
|
|||||||
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
|
let prompt: StrBuffer = kwargs.get(Qstr::MP_QSTR_prompt)?.try_into()?;
|
||||||
|
|
||||||
let obj = LayoutObj::new(
|
let obj = LayoutObj::new(
|
||||||
Frame::new(prompt, WordlistEntry::new(WordlistType::Slip39)).with_title_center(true),
|
Frame::new(prompt, WordlistEntry::new(WordlistType::Slip39)).with_title_centered(),
|
||||||
)?;
|
)?;
|
||||||
Ok(obj.into())
|
Ok(obj.into())
|
||||||
};
|
};
|
||||||
|
Binary file not shown.
@ -48,7 +48,7 @@ pub const ICON_CANCEL: IconAndName = IconAndName::new(
|
|||||||
"cancel",
|
"cancel",
|
||||||
); // 8*8
|
); // 8*8
|
||||||
pub const ICON_DELETE: IconAndName =
|
pub const ICON_DELETE: IconAndName =
|
||||||
IconAndName::new(include_res!("model_tr/res/delete.toif"), "delete"); // 12*8
|
IconAndName::new(include_res!("model_tr/res/delete.toif"), "delete"); // 10*7
|
||||||
pub const ICON_EYE: IconAndName =
|
pub const ICON_EYE: IconAndName =
|
||||||
IconAndName::new(include_res!("model_tr/res/eye_round.toif"), "eye"); // 12*7
|
IconAndName::new(include_res!("model_tr/res/eye_round.toif"), "eye"); // 12*7
|
||||||
pub const ICON_LOCK: IconAndName = IconAndName::new(include_res!("model_tr/res/lock.toif"), "lock"); // 10*10
|
pub const ICON_LOCK: IconAndName = IconAndName::new(include_res!("model_tr/res/lock.toif"), "lock"); // 10*10
|
||||||
|
@ -9,6 +9,7 @@ from trezor.enums import (
|
|||||||
)
|
)
|
||||||
from trezor.strings import format_amount
|
from trezor.strings import format_amount
|
||||||
from trezor.ui import layouts
|
from trezor.ui import layouts
|
||||||
|
from trezor.ui.layouts import confirm_metadata, confirm_properties
|
||||||
|
|
||||||
from apps.common.paths import address_n_to_str
|
from apps.common.paths import address_n_to_str
|
||||||
|
|
||||||
@ -21,9 +22,6 @@ from .helpers.utils import (
|
|||||||
format_stake_pool_id,
|
format_stake_pool_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
confirm_metadata = layouts.confirm_metadata # global_import_cache
|
|
||||||
confirm_properties = layouts.confirm_properties # global_import_cache
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ async def error_pin_invalid(ctx: Context) -> NoReturn:
|
|||||||
await show_error_and_raise(
|
await show_error_and_raise(
|
||||||
ctx,
|
ctx,
|
||||||
"warning_wrong_pin",
|
"warning_wrong_pin",
|
||||||
"The PIN you entered is invalid.",
|
"PIN you have entered is not valid.",
|
||||||
"Wrong PIN", # header
|
"Wrong PIN", # header
|
||||||
exc=wire.PinInvalid,
|
exc=wire.PinInvalid,
|
||||||
)
|
)
|
||||||
|
@ -28,7 +28,11 @@ async def change_pin(ctx: Context, msg: ChangePin) -> Success:
|
|||||||
await _require_confirm_change_pin(ctx, msg)
|
await _require_confirm_change_pin(ctx, msg)
|
||||||
|
|
||||||
# get old pin
|
# get old pin
|
||||||
curpin, salt = await request_pin_and_sd_salt(ctx, "Enter old PIN")
|
if msg.remove:
|
||||||
|
prompt = "Enter PIN"
|
||||||
|
else:
|
||||||
|
prompt = "Enter old PIN"
|
||||||
|
curpin, salt = await request_pin_and_sd_salt(ctx, prompt)
|
||||||
|
|
||||||
# if changing pin, pre-check the entered pin before getting new pin
|
# if changing pin, pre-check the entered pin before getting new pin
|
||||||
if curpin and not msg.remove:
|
if curpin and not msg.remove:
|
||||||
|
@ -90,7 +90,7 @@ def _require_confirm_action(
|
|||||||
title,
|
title,
|
||||||
"enable wipe code?",
|
"enable wipe code?",
|
||||||
[
|
[
|
||||||
"Wipe code will\nbe used to delete this device.",
|
"Wipe code can be used to erase all data from this device.",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -65,7 +65,9 @@ async def _continue_recovery_process(ctx: GenericContext) -> 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(ctx, "Select", "Select number of words")
|
await layout.homescreen_dialog(
|
||||||
|
ctx, "Select", "First select the number of words in your recovery seed"
|
||||||
|
)
|
||||||
# ask for the number of words
|
# ask for the number of words
|
||||||
word_count = await layout.request_word_count(ctx, dry_run)
|
word_count = await layout.request_word_count(ctx, dry_run)
|
||||||
# ...and only then show the starting screen with word count.
|
# ...and only then show the starting screen with word count.
|
||||||
@ -158,7 +160,7 @@ async def _finish_recovery(
|
|||||||
storage_recovery.end_progress()
|
storage_recovery.end_progress()
|
||||||
|
|
||||||
await show_success(
|
await show_success(
|
||||||
ctx, "success_recovery", "You have successfully recovered your wallet."
|
ctx, "success_recovery", "You have finished recovering your wallet."
|
||||||
)
|
)
|
||||||
return Success(message="Device recovered")
|
return Success(message="Device recovered")
|
||||||
|
|
||||||
@ -196,7 +198,7 @@ async def _request_share_first_screen(ctx: GenericContext, word_count: int) -> N
|
|||||||
)
|
)
|
||||||
else: # BIP-39
|
else: # BIP-39
|
||||||
await layout.homescreen_dialog(
|
await layout.homescreen_dialog(
|
||||||
ctx, "Enter seed", "Enter recovery seed", f"({word_count} words)"
|
ctx, "Enter seed", "Now enter your recovery seed", f"({word_count} words)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ async def request_mnemonic(
|
|||||||
ctx,
|
ctx,
|
||||||
"request_word",
|
"request_word",
|
||||||
"WORD ENTERING",
|
"WORD ENTERING",
|
||||||
description="You'll only have to select first 2-3 letters.",
|
description="You'll only have to select the first 2-3 letters.",
|
||||||
verb="CONTINUE",
|
verb="CONTINUE",
|
||||||
verb_cancel=None,
|
verb_cancel=None,
|
||||||
br_code=ButtonRequestType.MnemonicInput,
|
br_code=ButtonRequestType.MnemonicInput,
|
||||||
@ -103,14 +103,7 @@ async def show_dry_run_result(
|
|||||||
from trezor.ui.layouts import show_success
|
from trezor.ui.layouts import show_success
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
if is_slip39:
|
text = "You have finished verifying your recovery seed"
|
||||||
text = text_r(
|
|
||||||
"The entered recovery\nshares are valid and\nmatch what is currently\nin the device."
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
text = text_r(
|
|
||||||
"The entered recovery\nseed is valid and\nmatches the one\nin the device."
|
|
||||||
)
|
|
||||||
await show_success(ctx, "success_dry_recovery", text, button="Continue")
|
await show_success(ctx, "success_dry_recovery", text, button="Continue")
|
||||||
else:
|
else:
|
||||||
if is_slip39:
|
if is_slip39:
|
||||||
|
@ -12,8 +12,6 @@ from trezor.ui.layouts.reset import ( # noqa: F401
|
|||||||
slip39_show_checklist,
|
slip39_show_checklist,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .. import text_r
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Sequence
|
from typing import Sequence
|
||||||
from trezor.wire import GenericContext
|
from trezor.wire import GenericContext
|
||||||
@ -170,8 +168,9 @@ async def show_backup_warning(ctx: GenericContext, slip39: bool = False) -> None
|
|||||||
|
|
||||||
|
|
||||||
async def show_backup_success(ctx: GenericContext) -> None:
|
async def show_backup_success(ctx: GenericContext) -> None:
|
||||||
text = text_r("Use your backup\nwhen you need to\nrecover your wallet.")
|
from trezor.ui.layouts.reset import show_success_backup
|
||||||
await show_success(ctx, "success_backup", text, "Your backup is done.")
|
|
||||||
|
await show_success_backup(ctx)
|
||||||
|
|
||||||
|
|
||||||
# BIP39
|
# BIP39
|
||||||
|
@ -24,11 +24,20 @@ async def cipher_key_value(ctx: Context, msg: CipherKeyValue) -> CipheredKeyValu
|
|||||||
encrypt = msg.encrypt
|
encrypt = msg.encrypt
|
||||||
decrypt = not msg.encrypt
|
decrypt = not msg.encrypt
|
||||||
if (encrypt and msg.ask_on_encrypt) or (decrypt and msg.ask_on_decrypt):
|
if (encrypt and msg.ask_on_encrypt) or (decrypt and msg.ask_on_decrypt):
|
||||||
if encrypt:
|
# Special case for Trezor Suite, which asks for setting up labels
|
||||||
title = "Encrypt value"
|
if msg.key == "Enable labeling?":
|
||||||
|
title = "SUITE LABELING"
|
||||||
|
verb = "ENABLE"
|
||||||
else:
|
else:
|
||||||
title = "Decrypt value"
|
if encrypt:
|
||||||
await confirm_action(ctx, "cipher_key_value", title, description=msg.key)
|
title = "Encrypt value"
|
||||||
|
else:
|
||||||
|
title = "Decrypt value"
|
||||||
|
verb = "CONFIRM"
|
||||||
|
|
||||||
|
await confirm_action(
|
||||||
|
ctx, "cipher_key_value", title, description=msg.key, verb=verb
|
||||||
|
)
|
||||||
|
|
||||||
node = keychain.derive(msg.address_n)
|
node = keychain.derive(msg.address_n)
|
||||||
|
|
||||||
|
@ -510,6 +510,7 @@ async def confirm_action(
|
|||||||
hold: bool = False,
|
hold: bool = False,
|
||||||
hold_danger: bool = False,
|
hold_danger: bool = False,
|
||||||
reverse: bool = False,
|
reverse: bool = False,
|
||||||
|
uppercase_title: bool = True,
|
||||||
exc: ExceptionType = ActionCancelled,
|
exc: ExceptionType = ActionCancelled,
|
||||||
br_code: ButtonRequestType = BR_TYPE_OTHER,
|
br_code: ButtonRequestType = BR_TYPE_OTHER,
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -535,7 +536,7 @@ async def confirm_action(
|
|||||||
ctx,
|
ctx,
|
||||||
RustLayout(
|
RustLayout(
|
||||||
trezorui2.confirm_action(
|
trezorui2.confirm_action(
|
||||||
title=title.upper(),
|
title=title.upper() if uppercase_title else title,
|
||||||
action=action,
|
action=action,
|
||||||
description=description,
|
description=description,
|
||||||
verb=verb,
|
verb=verb,
|
||||||
@ -566,15 +567,12 @@ async def confirm_reset_device(
|
|||||||
if show_tutorial:
|
if show_tutorial:
|
||||||
await tutorial(ctx)
|
await tutorial(ctx)
|
||||||
|
|
||||||
to_show = "By continuing you agree to our terms and conditions.\nMore info at trezor.io/tos."
|
|
||||||
if not recovery:
|
|
||||||
to_show += "\nUse you backup to recover your wallet."
|
|
||||||
|
|
||||||
return await _placeholder_confirm(
|
return await _placeholder_confirm(
|
||||||
ctx,
|
ctx,
|
||||||
"recover_device" if recovery else "setup_device",
|
"recover_device" if recovery else "setup_device",
|
||||||
"WALLET RECOVERY" if recovery else "WALLET BACKUP",
|
"WALLET RECOVERY" if recovery else "WALLET CREATION",
|
||||||
description=to_show,
|
description="By continuing you agree to Trezor Company terms and conditions.\n\rMore info at trezor.io/tos",
|
||||||
|
verb="RECOVER WALLET" if recovery else "CREATE WALLET",
|
||||||
br_code=ButtonRequestType.ProtectCall
|
br_code=ButtonRequestType.ProtectCall
|
||||||
if recovery
|
if recovery
|
||||||
else ButtonRequestType.ResetDevice,
|
else ButtonRequestType.ResetDevice,
|
||||||
@ -587,14 +585,14 @@ async def confirm_backup(ctx: GenericContext) -> bool:
|
|||||||
ctx,
|
ctx,
|
||||||
"backup_device",
|
"backup_device",
|
||||||
"SUCCESS",
|
"SUCCESS",
|
||||||
"New wallet created successfully!\nYou should back up your new wallet right now.",
|
description="New wallet has been created.\nIt should be backed up now!",
|
||||||
verb="BACK UP",
|
verb="BACK UP",
|
||||||
verb_cancel="SKIP",
|
verb_cancel="SKIP",
|
||||||
br_code=ButtonRequestType.ResetDevice,
|
br_code=ButtonRequestType.ResetDevice,
|
||||||
):
|
):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
confirmed = await get_bool(
|
return await get_bool(
|
||||||
ctx,
|
ctx,
|
||||||
"backup_device",
|
"backup_device",
|
||||||
"WARNING",
|
"WARNING",
|
||||||
@ -604,7 +602,6 @@ async def confirm_backup(ctx: GenericContext) -> bool:
|
|||||||
verb_cancel="SKIP",
|
verb_cancel="SKIP",
|
||||||
br_code=ButtonRequestType.ResetDevice,
|
br_code=ButtonRequestType.ResetDevice,
|
||||||
)
|
)
|
||||||
return confirmed
|
|
||||||
|
|
||||||
|
|
||||||
async def confirm_path_warning(
|
async def confirm_path_warning(
|
||||||
@ -771,10 +768,25 @@ def show_success(
|
|||||||
subheader: str | None = None,
|
subheader: str | None = None,
|
||||||
button: str = "Continue",
|
button: str = "Continue",
|
||||||
) -> Awaitable[None]:
|
) -> Awaitable[None]:
|
||||||
|
title = "Success"
|
||||||
|
|
||||||
|
# In case only subheader is supplied, showing it
|
||||||
|
# in regular font, not bold.
|
||||||
|
if not content and subheader:
|
||||||
|
content = subheader
|
||||||
|
subheader = None
|
||||||
|
|
||||||
|
# Special case for Shamir backup - to show everything just on one page
|
||||||
|
# in regular font.
|
||||||
|
if "Continue with" in content:
|
||||||
|
content = f"{subheader}\n{content}"
|
||||||
|
subheader = None
|
||||||
|
title = ""
|
||||||
|
|
||||||
return _show_modal(
|
return _show_modal(
|
||||||
ctx,
|
ctx,
|
||||||
br_type,
|
br_type,
|
||||||
"Success",
|
title,
|
||||||
subheader,
|
subheader,
|
||||||
content,
|
content,
|
||||||
button_confirm=button,
|
button_confirm=button,
|
||||||
@ -1192,7 +1204,7 @@ async def show_popup(
|
|||||||
def request_passphrase_on_host() -> None:
|
def request_passphrase_on_host() -> None:
|
||||||
draw_simple(
|
draw_simple(
|
||||||
trezorui2.show_info(
|
trezorui2.show_info(
|
||||||
title="",
|
title="HIDDEN WALLET",
|
||||||
description="Please type your passphrase on the connected host.",
|
description="Please type your passphrase on the connected host.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -1226,7 +1238,9 @@ async def request_pin_on_device(
|
|||||||
) -> str:
|
) -> str:
|
||||||
from trezor import wire
|
from trezor import wire
|
||||||
|
|
||||||
if attempts_remaining is None:
|
# Not showing the prompt in case user did not enter it badly yet
|
||||||
|
# (has full 16 attempts left)
|
||||||
|
if attempts_remaining is None or attempts_remaining == 16:
|
||||||
subprompt = ""
|
subprompt = ""
|
||||||
elif attempts_remaining == 1:
|
elif attempts_remaining == 1:
|
||||||
subprompt = "Last attempt"
|
subprompt = "Last attempt"
|
||||||
@ -1260,7 +1274,7 @@ async def confirm_reenter_pin(
|
|||||||
ctx,
|
ctx,
|
||||||
br_type,
|
br_type,
|
||||||
"CHECK PIN",
|
"CHECK PIN",
|
||||||
"Please re-enter to confirm.",
|
description="Please re-enter PIN to confirm.",
|
||||||
verb="BEGIN",
|
verb="BEGIN",
|
||||||
br_code=br_code,
|
br_code=br_code,
|
||||||
)
|
)
|
||||||
@ -1294,7 +1308,7 @@ async def confirm_pin_action(
|
|||||||
ctx,
|
ctx,
|
||||||
br_type,
|
br_type,
|
||||||
title,
|
title,
|
||||||
f"{description} {action}",
|
description=f"{description} {action}",
|
||||||
br_code=br_code,
|
br_code=br_code,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1317,21 +1331,22 @@ async def confirm_set_new_pin(
|
|||||||
br_code=br_code,
|
br_code=br_code,
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO: this is a hack to put the next info on new screen in case of wipe code
|
if "wipe_code" in br_type:
|
||||||
# TODO: there should be a possibility to give a list of strings and each of them
|
title = "WIPE CODE INFO"
|
||||||
# would be rendered on a new screen
|
verb = "HODL TO BEGIN" # Easter egg from @Hannsek
|
||||||
if len(information) == 1:
|
else:
|
||||||
information.append("\n")
|
title = "PIN INFORMATION"
|
||||||
|
information.append(
|
||||||
|
"Position of individual numbers will change between entries for enhanced security."
|
||||||
|
)
|
||||||
|
verb = "HOLD TO BEGIN"
|
||||||
|
|
||||||
information.append(
|
|
||||||
"Position of individual numbers will change between entries for more security."
|
|
||||||
)
|
|
||||||
return await confirm_action(
|
return await confirm_action(
|
||||||
ctx,
|
ctx,
|
||||||
br_type,
|
br_type,
|
||||||
title="",
|
title=title,
|
||||||
description="\n".join(information),
|
description="\n".join(information),
|
||||||
verb="HOLD TO BEGIN",
|
verb=verb,
|
||||||
hold=True,
|
hold=True,
|
||||||
br_code=br_code,
|
br_code=br_code,
|
||||||
)
|
)
|
||||||
|
@ -79,7 +79,7 @@ async def continue_recovery(
|
|||||||
if dry_run:
|
if dry_run:
|
||||||
title = "SEED CHECK"
|
title = "SEED CHECK"
|
||||||
else:
|
else:
|
||||||
title = "RECOVERY MODE"
|
title = "WALLET RECOVERY"
|
||||||
|
|
||||||
return await get_bool(
|
return await get_bool(
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -47,18 +47,18 @@ async def show_share_words(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if share_index is None:
|
if share_index is None:
|
||||||
check_title = "CHECK SEED"
|
check_title = "CHECK BACKUP"
|
||||||
elif group_index is None:
|
elif group_index is None:
|
||||||
check_title = f"CHECK SHARE #{share_index + 1}"
|
check_title = f"CHECK SHARE #{share_index + 1}"
|
||||||
else:
|
else:
|
||||||
check_title = f"CHECK G{group_index + 1} - SHARE {share_index + 1}"
|
check_title = f"GROUP {group_index + 1} - SHARE {share_index + 1}"
|
||||||
|
|
||||||
if await get_bool(
|
if await get_bool(
|
||||||
ctx,
|
ctx,
|
||||||
"backup_words",
|
"backup_words",
|
||||||
check_title,
|
check_title,
|
||||||
None,
|
None,
|
||||||
"Select correct words in correct positions.",
|
"Select correct word for each position.",
|
||||||
verb_cancel="SEE AGAIN",
|
verb_cancel="SEE AGAIN",
|
||||||
verb="BEGIN",
|
verb="BEGIN",
|
||||||
br_code=ButtonRequestType.ResetDevice,
|
br_code=ButtonRequestType.ResetDevice,
|
||||||
@ -84,7 +84,7 @@ async def select_word(
|
|||||||
RustLayout(
|
RustLayout(
|
||||||
trezorui2.select_word( # type: ignore [Argument missing for parameter "description"]
|
trezorui2.select_word( # type: ignore [Argument missing for parameter "description"]
|
||||||
title=f"SELECT {format_ordinal(checked_index + 1).upper()} WORD",
|
title=f"SELECT {format_ordinal(checked_index + 1).upper()} WORD",
|
||||||
words=(words[0].upper(), words[1].upper(), words[2].upper()),
|
words=(words[0].lower(), words[1].lower(), words[2].lower()),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -165,10 +165,11 @@ async def slip39_prompt_threshold(
|
|||||||
await confirm_action(
|
await confirm_action(
|
||||||
ctx,
|
ctx,
|
||||||
"slip39_prompt_threshold",
|
"slip39_prompt_threshold",
|
||||||
"Set threshold",
|
"Threshold",
|
||||||
description="= number of shares needed for recovery",
|
description="= number of shares needed for recovery",
|
||||||
verb="BEGIN",
|
verb="BEGIN",
|
||||||
verb_cancel=None,
|
verb_cancel=None,
|
||||||
|
uppercase_title=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
count = num_of_shares // 2 + 1
|
count = num_of_shares // 2 + 1
|
||||||
@ -199,9 +200,10 @@ async def slip39_prompt_number_of_shares(
|
|||||||
ctx,
|
ctx,
|
||||||
"slip39_shares",
|
"slip39_shares",
|
||||||
"Number of shares",
|
"Number of shares",
|
||||||
description="= total number of unique word lists used for wallet backup.",
|
description="= total number of unique word lists used for wallet backup",
|
||||||
verb="BEGIN",
|
verb="BEGIN",
|
||||||
verb_cancel=None,
|
verb_cancel=None,
|
||||||
|
uppercase_title=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
count = 5
|
count = 5
|
||||||
@ -256,21 +258,26 @@ async def slip39_advanced_prompt_group_threshold(
|
|||||||
|
|
||||||
|
|
||||||
async def show_warning_backup(ctx: GenericContext, slip39: bool) -> None:
|
async def show_warning_backup(ctx: GenericContext, slip39: bool) -> None:
|
||||||
if slip39:
|
|
||||||
description = (
|
|
||||||
"Never make a digital copy of your shares and never upload them online."
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
description = (
|
|
||||||
"Never make a digital copy of your seed and never upload it online."
|
|
||||||
)
|
|
||||||
|
|
||||||
await confirm_action(
|
await confirm_action(
|
||||||
ctx,
|
ctx,
|
||||||
"backup_warning",
|
"backup_warning",
|
||||||
"Caution",
|
"SHAMIR BACKUP" if slip39 else "WALLET BACKUP",
|
||||||
description=description,
|
description="You can use your backup to recover your wallet at any time.",
|
||||||
verb="I understand",
|
verb="HOLD TO BEGIN",
|
||||||
verb_cancel=None,
|
hold=True,
|
||||||
br_code=ButtonRequestType.ResetDevice,
|
br_code=ButtonRequestType.ResetDevice,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def show_success_backup(ctx: GenericContext) -> None:
|
||||||
|
from . import confirm_action
|
||||||
|
|
||||||
|
await confirm_action(
|
||||||
|
ctx,
|
||||||
|
"success_backup",
|
||||||
|
"BACKUP IS DONE",
|
||||||
|
description="Keep it safe!",
|
||||||
|
verb="CONTINUE",
|
||||||
|
verb_cancel=None,
|
||||||
|
br_code=ButtonRequestType.Success,
|
||||||
|
)
|
||||||
|
@ -331,3 +331,10 @@ async def show_warning_backup(ctx: GenericContext, slip39: bool) -> None:
|
|||||||
)
|
)
|
||||||
if result != CONFIRMED:
|
if result != CONFIRMED:
|
||||||
raise ActionCancelled
|
raise ActionCancelled
|
||||||
|
|
||||||
|
|
||||||
|
async def show_success_backup(ctx: GenericContext) -> None:
|
||||||
|
from . import show_success
|
||||||
|
|
||||||
|
text = "Use your backup when you need to recover your wallet."
|
||||||
|
await show_success(ctx, "success_backup", text, "Your backup is done.")
|
||||||
|
@ -992,6 +992,7 @@ static secbool decrypt_dek(const uint8_t *kek, const uint8_t *keiv) {
|
|||||||
static void ensure_not_wipe_code(const uint8_t *pin, size_t pin_len) {
|
static void ensure_not_wipe_code(const uint8_t *pin, size_t pin_len) {
|
||||||
if (sectrue != is_not_wipe_code(pin, pin_len)) {
|
if (sectrue != is_not_wipe_code(pin, pin_len)) {
|
||||||
storage_wipe();
|
storage_wipe();
|
||||||
|
// TODO: need to account for smaller model R - smaller font and different copy
|
||||||
error_shutdown("You have entered the", "wipe code. All private",
|
error_shutdown("You have entered the", "wipe code. All private",
|
||||||
"data has been erased.", NULL);
|
"data has been erased.", NULL);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ def select_number_of_words(
|
|||||||
layout = debug.read_layout()
|
layout = debug.read_layout()
|
||||||
|
|
||||||
# select number of words
|
# select number of words
|
||||||
assert "Select number of words" in layout.get_content()
|
assert "select the number of words" in layout.get_content()
|
||||||
layout = debug.click(buttons.OK, wait=True)
|
layout = debug.click(buttons.OK, wait=True)
|
||||||
if legacy_ui:
|
if legacy_ui:
|
||||||
assert layout.text == "WordSelector"
|
assert layout.text == "WordSelector"
|
||||||
|
@ -131,7 +131,7 @@ def test_dryrun_locks_at_number_of_words(device_handler: "BackgroundDeviceHandle
|
|||||||
layout = debug.click(buttons.OK, wait=True)
|
layout = debug.click(buttons.OK, wait=True)
|
||||||
assert layout.text == "< PinKeyboard >"
|
assert layout.text == "< PinKeyboard >"
|
||||||
layout = debug.input(PIN4, wait=True)
|
layout = debug.input(PIN4, wait=True)
|
||||||
assert "Select number of words " in layout.get_content()
|
assert "select the number of words " in layout.get_content()
|
||||||
|
|
||||||
# wait for autolock to trigger
|
# wait for autolock to trigger
|
||||||
time.sleep(10.1)
|
time.sleep(10.1)
|
||||||
@ -146,7 +146,7 @@ def test_dryrun_locks_at_number_of_words(device_handler: "BackgroundDeviceHandle
|
|||||||
layout = debug.input(PIN4, wait=True)
|
layout = debug.input(PIN4, wait=True)
|
||||||
|
|
||||||
# we are back at homescreen
|
# we are back at homescreen
|
||||||
assert "Select number of words" in layout.get_content()
|
assert "select the number of words" in layout.get_content()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.setup_client(pin=PIN4)
|
@pytest.mark.setup_client(pin=PIN4)
|
||||||
|
@ -58,7 +58,7 @@ def do_recover_core(client: Client, mnemonic: List[str], **kwargs: Any):
|
|||||||
client.debug.click(buttons.OK)
|
client.debug.click(buttons.OK)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Select number of words" in layout().get_content()
|
assert "select the number of words" in layout().get_content()
|
||||||
client.debug.click(buttons.OK)
|
client.debug.click(buttons.OK)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -70,7 +70,7 @@ def do_recover_core(client: Client, mnemonic: List[str], **kwargs: Any):
|
|||||||
client.debug.click(buttons.grid34(index % 3, index // 3))
|
client.debug.click(buttons.grid34(index % 3, index // 3))
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Enter recovery seed" in layout().get_content()
|
assert "enter your recovery seed" in layout().get_content()
|
||||||
client.debug.click(buttons.OK)
|
client.debug.click(buttons.OK)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -97,7 +97,7 @@ def do_recover_r(client: Client, mnemonic: List[str], **kwargs: Any):
|
|||||||
client.debug.press_right()
|
client.debug.press_right()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Select number of words" in layout().text
|
assert "select the number of words" in layout().text
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -110,7 +110,7 @@ def do_recover_r(client: Client, mnemonic: List[str], **kwargs: Any):
|
|||||||
client.debug.input(str(len(mnemonic)))
|
client.debug.input(str(len(mnemonic)))
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Enter recovery seed" in layout().text
|
assert "enter your recovery seed" in layout().text
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -173,7 +173,7 @@ def test_invalid_seed_core(client: Client):
|
|||||||
client.debug.click(buttons.OK)
|
client.debug.click(buttons.OK)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Select number of words" in layout().get_content()
|
assert "select the number of words" in layout().get_content()
|
||||||
client.debug.click(buttons.OK)
|
client.debug.click(buttons.OK)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -182,7 +182,7 @@ def test_invalid_seed_core(client: Client):
|
|||||||
client.debug.click(buttons.grid34(0, 2))
|
client.debug.click(buttons.grid34(0, 2))
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Enter recovery seed" in layout().get_content()
|
assert "enter your recovery seed" in layout().get_content()
|
||||||
client.debug.click(buttons.OK)
|
client.debug.click(buttons.OK)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -197,7 +197,7 @@ def test_invalid_seed_core(client: Client):
|
|||||||
|
|
||||||
yield
|
yield
|
||||||
# retry screen
|
# retry screen
|
||||||
assert "Select number of words" in layout().get_content()
|
assert "select the number of words" in layout().get_content()
|
||||||
client.debug.click(buttons.CANCEL)
|
client.debug.click(buttons.CANCEL)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -210,7 +210,7 @@ def test_invalid_seed_core(client: Client):
|
|||||||
client.debug.press_right()
|
client.debug.press_right()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Select number of words" in layout().text
|
assert "select the number of words" in layout().text
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -220,7 +220,7 @@ def test_invalid_seed_core(client: Client):
|
|||||||
client.debug.press_middle()
|
client.debug.press_middle()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Enter recovery seed" in layout().text
|
assert "enter your recovery seed" in layout().text
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -239,7 +239,7 @@ def test_invalid_seed_core(client: Client):
|
|||||||
|
|
||||||
yield
|
yield
|
||||||
# retry screen
|
# retry screen
|
||||||
assert "Select number of words" in layout().text
|
assert "select the number of words" in layout().text
|
||||||
client.debug.press_left()
|
client.debug.press_left()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
@ -43,7 +43,7 @@ def test_tt_pin_passphrase(client: Client):
|
|||||||
client.debug.input("654")
|
client.debug.input("654")
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Select number of words" in layout().get_content()
|
assert "select the number of words" in layout().get_content()
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -51,7 +51,7 @@ def test_tt_pin_passphrase(client: Client):
|
|||||||
client.debug.input(str(len(mnemonic)))
|
client.debug.input(str(len(mnemonic)))
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Enter recovery seed" in layout().get_content()
|
assert "enter your recovery seed" in layout().get_content()
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -75,7 +75,7 @@ def test_tt_pin_passphrase(client: Client):
|
|||||||
client.debug.input("654")
|
client.debug.input("654")
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "re-enter to confirm" in layout().text
|
assert "re-enter PIN to confirm" in layout().text
|
||||||
client.debug.press_right()
|
client.debug.press_right()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -83,7 +83,7 @@ def test_tt_pin_passphrase(client: Client):
|
|||||||
client.debug.input("654")
|
client.debug.input("654")
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Select number of words" in layout().text
|
assert "select the number of words" in layout().text
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -92,7 +92,7 @@ def test_tt_pin_passphrase(client: Client):
|
|||||||
client.debug.input(str(len(mnemonic)))
|
client.debug.input(str(len(mnemonic)))
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Enter recovery seed" in layout().text
|
assert "enter your recovery seed" in layout().text
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -105,7 +105,7 @@ def test_tt_pin_passphrase(client: Client):
|
|||||||
client.debug.input(word)
|
client.debug.input(word)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "You have successfully recovered your wallet." in layout().text
|
assert "You have finished recovering your wallet." in layout().text
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
with client:
|
with client:
|
||||||
@ -141,7 +141,7 @@ def test_tt_nopin_nopassphrase(client: Client):
|
|||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Select number of words" in layout().get_content()
|
assert "select the number of words" in layout().get_content()
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -149,7 +149,7 @@ def test_tt_nopin_nopassphrase(client: Client):
|
|||||||
client.debug.input(str(len(mnemonic)))
|
client.debug.input(str(len(mnemonic)))
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Enter recovery seed" in layout().get_content()
|
assert "enter your recovery seed" in layout().get_content()
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -169,7 +169,7 @@ def test_tt_nopin_nopassphrase(client: Client):
|
|||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Select number of words" in layout().text
|
assert "select the number of words" in layout().text
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -178,7 +178,7 @@ def test_tt_nopin_nopassphrase(client: Client):
|
|||||||
client.debug.input(str(len(mnemonic)))
|
client.debug.input(str(len(mnemonic)))
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "Enter recovery seed" in layout().text
|
assert "enter your recovery seed" in layout().text
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
yield
|
yield
|
||||||
@ -191,7 +191,7 @@ def test_tt_nopin_nopassphrase(client: Client):
|
|||||||
client.debug.input(word)
|
client.debug.input(word)
|
||||||
|
|
||||||
yield
|
yield
|
||||||
assert "You have successfully recovered your wallet." in layout().text
|
assert "You have finished recovering your wallet." in layout().text
|
||||||
client.debug.press_yes()
|
client.debug.press_yes()
|
||||||
|
|
||||||
with client:
|
with client:
|
||||||
|
@ -53,7 +53,7 @@ def test_abort(emulator: Emulator):
|
|||||||
assert layout.get_title() == "RECOVERY MODE"
|
assert layout.get_title() == "RECOVERY MODE"
|
||||||
|
|
||||||
layout = debug.click(buttons.OK, wait=True)
|
layout = debug.click(buttons.OK, wait=True)
|
||||||
assert "Select number of words" in layout.text
|
assert "select the number of words" in layout.text
|
||||||
|
|
||||||
device_handler.restart(emulator)
|
device_handler.restart(emulator)
|
||||||
debug = device_handler.debuglink()
|
debug = device_handler.debuglink()
|
||||||
@ -63,7 +63,7 @@ def test_abort(emulator: Emulator):
|
|||||||
|
|
||||||
# no waiting for layout because layout doesn't change
|
# no waiting for layout because layout doesn't change
|
||||||
layout = debug.read_layout()
|
layout = debug.read_layout()
|
||||||
assert "Select number of words" in layout.text
|
assert "select the number of words" in layout.text
|
||||||
layout = debug.click(buttons.CANCEL, wait=True)
|
layout = debug.click(buttons.CANCEL, wait=True)
|
||||||
|
|
||||||
assert layout.get_title() == "ABORT RECOVERY"
|
assert layout.get_title() == "ABORT RECOVERY"
|
||||||
|
Loading…
Reference in New Issue
Block a user