1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-23 18:49:13 +00:00

refactor(python): move Screen Buttons to debuglink

This commit is contained in:
Lukas Bielesch 2025-03-11 11:45:55 +01:00 committed by Lukáš Bielesch
parent 1eeab2ffd2
commit 17603ffe41
18 changed files with 526 additions and 632 deletions

View File

@ -0,0 +1 @@
Add screen buttons and button actions to Debuglink.

View File

@ -59,6 +59,7 @@ if TYPE_CHECKING:
]
AnyDict = Dict[str, Any]
Coords = Tuple[int, int]
class InputFunc(Protocol):
def __call__(
@ -470,6 +471,14 @@ class DebugLink:
assert self.model is not None
return LayoutType.from_model(self.model)
@property
def screen_buttons(self) -> ScreenButtons:
return ScreenButtons(self.layout_type)
@property
def button_actions(self) -> ButtonActions:
return ButtonActions(self.layout_type)
def open(self) -> None:
self.transport.begin_session()
@ -1385,3 +1394,303 @@ def _is_emulator(debug_client: "TrezorClientDebugLink") -> bool:
def optiga_set_sec_max(client: "TrezorClient") -> None:
client.call(messages.DebugLinkOptigaSetSecMax(), expect=messages.Success)
class ScreenButtons:
def __init__(self, layout_type: LayoutType):
assert layout_type in (LayoutType.Bolt, LayoutType.Delizia)
self.layout_type = layout_type
def _width(self) -> int:
return 240
def _height(self) -> int:
return 240
def _grid(self, dim: int, grid_cells: int, cell: int) -> int:
assert cell < grid_cells
step = dim // grid_cells
ofs = step // 2
return cell * step + ofs
# 3 columns, 4 rows, 1st row is input area
def _grid35(self, x: int, y: int) -> Coords:
return self._grid(self._width(), 3, x), self._grid(self._height(), 5, y)
# TODO: do not expose this
# 3 columns, 3 rows, 1st row is input area
def grid34(self, x: int, y: int) -> Coords:
return self._grid(self._width(), 3, x), self._grid(self._height(), 4, y)
# Horizontal coordinates
def _left(self) -> int:
return self._grid(self._width(), 3, 0)
def _mid(self) -> int:
return self._grid(self._width(), 3, 1)
def _right(self) -> int:
return self._grid(self._width(), 3, 2)
# Vertical coordinates
def _top(self) -> int:
return self._grid(self._height(), 6, 0)
def _bottom(self) -> int:
return self._grid(self._height(), 6, 5)
# Buttons
# Right bottom
def ok(self) -> Coords:
return (self._right(), self._bottom())
# Left bottom
def cancel(self) -> Coords:
return (self._left(), self._bottom())
# Mid bottom
def info(self) -> Coords:
return (self._mid(), self._bottom())
# Menu/close menu button
def menu(self) -> Coords:
if self.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
return (215, 25)
else:
raise ValueError("Wrong layout type")
# Center of the screen
def tap_to_confirm(self) -> Coords:
assert self.layout_type is LayoutType.Delizia
return (self._grid(self._width(), 1, 0), self._grid(self._width(), 1, 0))
# Yes/No decision component
def ui_yes(self) -> Coords:
assert self.layout_type is LayoutType.Delizia
return self.grid34(2, 2)
def ui_no(self) -> Coords:
assert self.layout_type is LayoutType.Delizia
return self.grid34(0, 2)
# +/- buttons in number input component
def number_input_minus(self) -> Coords:
if self.layout_type is LayoutType.Bolt:
return (self._left(), self._grid(self._height(), 5, 1))
elif self.layout_type is LayoutType.Delizia:
return (self._left(), self._grid(self._height(), 5, 3))
else:
raise ValueError("Wrong layout type")
def number_input_plus(self) -> Coords:
if self.layout_type is LayoutType.Bolt:
return (self._right(), self._grid(self._height(), 5, 1))
elif self.layout_type is LayoutType.Delizia:
return (self._right(), self._grid(self._height(), 5, 3))
else:
raise ValueError("Wrong layout type")
def word_count_all_word(self, word_count: int) -> Coords:
assert word_count in (12, 18, 20, 24, 33)
if self.layout_type is LayoutType.Bolt:
coords_map = {
12: self.grid34(0, 2),
18: self.grid34(1, 2),
20: self.grid34(2, 2),
24: self.grid34(1, 3),
33: self.grid34(2, 3),
}
elif self.layout_type is LayoutType.Delizia:
coords_map = {
12: self.grid34(0, 1),
18: self.grid34(2, 1),
20: self.grid34(0, 2),
24: self.grid34(2, 2),
33: self.grid34(2, 3),
}
else:
raise ValueError("Wrong layout type")
return coords_map[word_count]
def word_count_all_cancel(self) -> Coords:
if self.layout_type is LayoutType.Bolt:
return self.grid34(0, 3)
elif self.layout_type is LayoutType.Delizia:
return self.grid34(0, 3)
else:
raise ValueError("Wrong layout type")
def word_count_repeated_word(self, word_count: int) -> Coords:
assert word_count in (20, 33)
if self.layout_type is LayoutType.Bolt:
coords_map = {
20: self.grid34(1, 2),
33: self.grid34(2, 2),
}
elif self.layout_type is LayoutType.Delizia:
coords_map = {
20: self.grid34(0, 1),
33: self.grid34(2, 1),
}
else:
raise ValueError("Wrong layout type")
return coords_map[word_count]
def word_count_repeated_cancel(self) -> Coords:
if self.layout_type is LayoutType.Bolt:
return self.grid34(0, 2)
elif self.layout_type is LayoutType.Delizia:
return self.grid34(0, 3)
else:
raise ValueError("Wrong layout type")
# select word component buttons
def word_check_words(self) -> "list[Coords]":
if self.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
return [
(self._mid(), self._grid(self._height(), 5, 2)),
(self._mid(), self._grid(self._height(), 5, 3)),
(self._mid(), self._grid(self._height(), 5, 4)),
]
else:
raise ValueError("Wrong layout type")
# vertical menu buttons
def vertical_menu_items(self) -> "list[Coords]":
assert self.layout_type is LayoutType.Delizia
return [
(self._mid(), self._grid(self._height(), 4, 1)),
(self._mid(), self._grid(self._height(), 4, 2)),
(self._mid(), self._grid(self._height(), 4, 3)),
]
# Pin/passphrase keyboards
def pin_passphrase_index(self, idx: int) -> Coords:
assert idx < 10
if idx == 9:
idx = 10 # last digit is in the middle
return self.pin_passphrase_grid(idx % 3, idx // 3)
def pin_passphrase_grid(self, x: int, y: int) -> Coords:
assert x < 3, y < 4
y += 1 # first line is empty
return self._grid35(x, y)
# PIN/passphrase input
def pin_passphrase_input(self) -> Coords:
return (self._mid(), self._top())
def pin_passphrase_erase(self) -> Coords:
return self.pin_passphrase_grid(0, 3)
def passphrase_confirm(self) -> Coords:
if self.layout_type is LayoutType.Bolt:
return self.pin_passphrase_grid(2, 3)
elif self.layout_type is LayoutType.Delizia:
return (215, 25)
else:
raise ValueError("Wrong layout type")
def pin_confirm(self) -> Coords:
return self.pin_passphrase_grid(2, 3)
# Mnemonic keyboard
def mnemonic_from_index(self, idx: int) -> Coords:
return self.mnemonic_grid(idx)
def mnemonic_grid(self, idx: int) -> Coords:
assert idx < 9
grid_x = idx % 3
grid_y = idx // 3 + 1 # first line is empty
return self.grid34(grid_x, grid_y)
def mnemonic_erase(self) -> Coords:
return (self._left(), self._top())
def mnemonic_confirm(self) -> Coords:
return (self._mid(), self._top())
BUTTON_LETTERS_BIP39 = ("abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz")
BUTTON_LETTERS_SLIP39 = ("ab", "cd", "ef", "ghij", "klm", "nopq", "rs", "tuv", "wxyz")
# fmt: off
PASSPHRASE_LOWERCASE_BOLT = (" ", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz", "*#")
PASSPHRASE_LOWERCASE_DELIZIA = ("abc", "def", "ghi", "jkl", "mno", "pq", "rst", "uvw", "xyz", " *#")
PASSPHRASE_UPPERCASE_BOLT = (" ", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ", "*#")
PASSPHRASE_UPPERCASE_DELIZIA = ("ABC", "DEF", "GHI", "JKL", "MNO", "PQ", "RST", "UVW", "XYZ", " *#")
PASSPHRASE_DIGITS = ("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
PASSPHRASE_SPECIAL = ("_<>", ".:@", "/|\\", "!()", "+%&", "-[]", "?{}", ",'`", ";\"~", "$^=")
# fmt: on
class ButtonActions:
def __init__(self, layout_type: LayoutType):
self.buttons = ScreenButtons(layout_type)
def _passphrase_choices(self, char: str) -> "tuple[str, ...]":
if char in " *#" or char.islower():
if self.buttons.layout_type is LayoutType.Bolt:
return PASSPHRASE_LOWERCASE_BOLT
elif self.buttons.layout_type is LayoutType.Delizia:
return PASSPHRASE_LOWERCASE_DELIZIA
else:
raise ValueError("Wrong layout type")
elif char.isupper():
if self.buttons.layout_type is LayoutType.Bolt:
return PASSPHRASE_UPPERCASE_BOLT
elif self.buttons.layout_type is LayoutType.Delizia:
return PASSPHRASE_UPPERCASE_DELIZIA
else:
raise ValueError("Wrong layout type")
elif char.isdigit():
return PASSPHRASE_DIGITS
else:
return PASSPHRASE_SPECIAL
def passphrase(self, char: str) -> Tuple[Coords, int]:
choices = self._passphrase_choices(char)
idx = next(i for i, letters in enumerate(choices) if char in letters)
click_amount = choices[idx].index(char) + 1
return self.buttons.pin_passphrase_index(idx), click_amount
def type_word(self, word: str, is_slip39: bool = False) -> Iterator[Coords]:
if is_slip39:
yield from self._type_word_slip39(word)
else:
yield from self._type_word_bip39(word)
def _type_word_slip39(self, word: str) -> Iterator[Coords]:
for l in word:
idx = next(
i for i, letters in enumerate(BUTTON_LETTERS_SLIP39) if l in letters
)
yield self.buttons.mnemonic_from_index(idx)
def _type_word_bip39(self, word: str) -> Iterator[Coords]:
coords_prev: Coords | None = None
for letter in word:
time.sleep(0.1) # not being so quick to miss something
coords, amount = self._letter_coords_and_amount(letter)
# If the button is the same as for the previous letter,
# waiting a second before pressing it again.
if coords == coords_prev:
time.sleep(1.1)
coords_prev = coords
for _ in range(amount):
yield coords
def _letter_coords_and_amount(self, letter: str) -> Tuple[Coords, int]:
idx = next(
i for i, letters in enumerate(BUTTON_LETTERS_BIP39) if letter in letters
)
click_amount = BUTTON_LETTERS_BIP39[idx].index(letter) + 1
return self.buttons.mnemonic_from_index(idx), click_amount

View File

@ -1,306 +0,0 @@
import time
from typing import Iterator, Tuple
from trezorlib.debuglink import LayoutType
Coords = Tuple[int, int]
class ScreenButtons:
def __init__(self, layout_type: LayoutType):
assert layout_type in (LayoutType.Bolt, LayoutType.Delizia)
self.layout_type = layout_type
def _width(self) -> int:
return 240
def _height(self) -> int:
return 240
def _grid(self, dim: int, grid_cells: int, cell: int) -> int:
assert cell < grid_cells
step = dim // grid_cells
ofs = step // 2
return cell * step + ofs
# 3 columns, 4 rows, 1st row is input area
def _grid35(self, x: int, y: int) -> Coords:
return self._grid(self._width(), 3, x), self._grid(self._height(), 5, y)
# TODO: do not expose this
# 3 columns, 3 rows, 1st row is input area
def grid34(self, x: int, y: int) -> Coords:
return self._grid(self._width(), 3, x), self._grid(self._height(), 4, y)
# Horizontal coordinates
def _left(self) -> int:
return self._grid(self._width(), 3, 0)
def _mid(self) -> int:
return self._grid(self._width(), 3, 1)
def _right(self) -> int:
return self._grid(self._width(), 3, 2)
# Vertical coordinates
def _top(self) -> int:
return self._grid(self._height(), 6, 0)
def _bottom(self) -> int:
return self._grid(self._height(), 6, 5)
# Buttons
# Right bottom
def ok(self) -> Coords:
return (self._right(), self._bottom())
# Left bottom
def cancel(self) -> Coords:
return (self._left(), self._bottom())
# Mid bottom
def info(self) -> Coords:
return (self._mid(), self._bottom())
# Menu/close menu button
def menu(self) -> Coords:
if self.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
return (215, 25)
else:
raise ValueError("Wrong layout type")
# Center of the screen
def tap_to_confirm(self) -> Coords:
assert self.layout_type is LayoutType.Delizia
return (self._grid(self._width(), 1, 0), self._grid(self._width(), 1, 0))
# Yes/No decision component
def ui_yes(self) -> Coords:
assert self.layout_type is LayoutType.Delizia
return self.grid34(2, 2)
def ui_no(self) -> Coords:
assert self.layout_type is LayoutType.Delizia
return self.grid34(0, 2)
# +/- buttons in number input component
def number_input_minus(self) -> Coords:
if self.layout_type is LayoutType.Bolt:
return (self._left(), self._grid(self._height(), 5, 1))
elif self.layout_type is LayoutType.Delizia:
return (self._left(), self._grid(self._height(), 5, 3))
else:
raise ValueError("Wrong layout type")
def number_input_plus(self) -> Coords:
if self.layout_type is LayoutType.Bolt:
return (self._right(), self._grid(self._height(), 5, 1))
elif self.layout_type is LayoutType.Delizia:
return (self._right(), self._grid(self._height(), 5, 3))
else:
raise ValueError("Wrong layout type")
def word_count_all_word(self, word_count: int) -> Coords:
assert word_count in (12, 18, 20, 24, 33)
if self.layout_type is LayoutType.Bolt:
coords_map = {
12: self.grid34(0, 2),
18: self.grid34(1, 2),
20: self.grid34(2, 2),
24: self.grid34(1, 3),
33: self.grid34(2, 3),
}
elif self.layout_type is LayoutType.Delizia:
coords_map = {
12: self.grid34(0, 1),
18: self.grid34(2, 1),
20: self.grid34(0, 2),
24: self.grid34(2, 2),
33: self.grid34(2, 3),
}
else:
raise ValueError("Wrong layout type")
return coords_map[word_count]
def word_count_all_cancel(self) -> Coords:
if self.layout_type is LayoutType.Bolt:
return self.grid34(0, 3)
elif self.layout_type is LayoutType.Delizia:
return self.grid34(0, 3)
else:
raise ValueError("Wrong layout type")
def word_count_repeated_word(self, word_count: int) -> Coords:
assert word_count in (20, 33)
if self.layout_type is LayoutType.Bolt:
coords_map = {
20: self.grid34(1, 2),
33: self.grid34(2, 2),
}
elif self.layout_type is LayoutType.Delizia:
coords_map = {
20: self.grid34(0, 1),
33: self.grid34(2, 1),
}
else:
raise ValueError("Wrong layout type")
return coords_map[word_count]
def word_count_repeated_cancel(self) -> Coords:
if self.layout_type is LayoutType.Bolt:
return self.grid34(0, 2)
elif self.layout_type is LayoutType.Delizia:
return self.grid34(0, 3)
else:
raise ValueError("Wrong layout type")
# select word component buttons
def word_check_words(self) -> "list[Coords]":
if self.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
return [
(self._mid(), self._grid(self._height(), 5, 2)),
(self._mid(), self._grid(self._height(), 5, 3)),
(self._mid(), self._grid(self._height(), 5, 4)),
]
else:
raise ValueError("Wrong layout type")
# vertical menu buttons
def vertical_menu_items(self) -> "list[Coords]":
assert self.layout_type is LayoutType.Delizia
return [
(self._mid(), self._grid(self._height(), 4, 1)),
(self._mid(), self._grid(self._height(), 4, 2)),
(self._mid(), self._grid(self._height(), 4, 3)),
]
# Pin/passphrase keyboards
def pin_passphrase_index(self, idx: int) -> Coords:
assert idx < 10
if idx == 9:
idx = 10 # last digit is in the middle
return self.pin_passphrase_grid(idx % 3, idx // 3)
def pin_passphrase_grid(self, x: int, y: int) -> Coords:
assert x < 3, y < 4
y += 1 # first line is empty
return self._grid35(x, y)
# PIN/passphrase input
def pin_passphrase_input(self) -> Coords:
return (self._mid(), self._top())
def pin_passphrase_erase(self) -> Coords:
return self.pin_passphrase_grid(0, 3)
def passphrase_confirm(self) -> Coords:
if self.layout_type is LayoutType.Bolt:
return self.pin_passphrase_grid(2, 3)
elif self.layout_type is LayoutType.Delizia:
return (215, 25)
else:
raise ValueError("Wrong layout type")
def pin_confirm(self) -> Coords:
return self.pin_passphrase_grid(2, 3)
# Mnemonic keyboard
def mnemonic_from_index(self, idx: int) -> Coords:
return self.mnemonic_grid(idx)
def mnemonic_grid(self, idx: int) -> Coords:
assert idx < 9
grid_x = idx % 3
grid_y = idx // 3 + 1 # first line is empty
return self.grid34(grid_x, grid_y)
def mnemonic_erase(self) -> Coords:
return (self._left(), self._top())
def mnemonic_confirm(self) -> Coords:
return (self._mid(), self._top())
BUTTON_LETTERS_BIP39 = ("abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz")
BUTTON_LETTERS_SLIP39 = ("ab", "cd", "ef", "ghij", "klm", "nopq", "rs", "tuv", "wxyz")
# fmt: off
PASSPHRASE_LOWERCASE_BOLT = (" ", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz", "*#")
PASSPHRASE_LOWERCASE_DELIZIA = ("abc", "def", "ghi", "jkl", "mno", "pq", "rst", "uvw", "xyz", " *#")
PASSPHRASE_UPPERCASE_BOLT = (" ", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ", "*#")
PASSPHRASE_UPPERCASE_DELIZIA = ("ABC", "DEF", "GHI", "JKL", "MNO", "PQ", "RST", "UVW", "XYZ", " *#")
PASSPHRASE_DIGITS = ("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
PASSPHRASE_SPECIAL = ("_<>", ".:@", "/|\\", "!()", "+%&", "-[]", "?{}", ",'`", ";\"~", "$^=")
# fmt: on
class ButtonActions:
def __init__(self, layout_type: LayoutType):
self.buttons = ScreenButtons(layout_type)
def _passphrase_choices(self, char: str) -> tuple[str, ...]:
if char in " *#" or char.islower():
if self.layout_type is LayoutType.Bolt:
return PASSPHRASE_LOWERCASE_BOLT
elif self.layout_type is LayoutType.Delizia:
return PASSPHRASE_LOWERCASE_DELIZIA
else:
raise ValueError("Wrong layout type")
elif char.isupper():
if self.layout_type is LayoutType.Bolt:
return PASSPHRASE_UPPERCASE_BOLT
elif self.layout_type is LayoutType.Delizia:
return PASSPHRASE_UPPERCASE_DELIZIA
else:
raise ValueError("Wrong layout type")
elif char.isdigit():
return PASSPHRASE_DIGITS
else:
return PASSPHRASE_SPECIAL
def passphrase(self, char: str) -> Tuple[Coords, int]:
choices = self._passphrase_choices(char)
idx = next(i for i, letters in enumerate(choices) if char in letters)
click_amount = choices[idx].index(char) + 1
return self.buttons.pin_passphrase_index(idx), click_amount
def type_word(self, word: str, is_slip39: bool = False) -> Iterator[Coords]:
if is_slip39:
yield from self._type_word_slip39(word)
else:
yield from self._type_word_bip39(word)
def _type_word_slip39(self, word: str) -> Iterator[Coords]:
for l in word:
idx = next(
i for i, letters in enumerate(BUTTON_LETTERS_SLIP39) if l in letters
)
yield self.buttons.mnemonic_from_index(idx)
def _type_word_bip39(self, word: str) -> Iterator[Coords]:
coords_prev: Coords | None = None
for letter in word:
time.sleep(0.1) # not being so quick to miss something
coords, amount = self._letter_coords_and_amount(letter)
# If the button is the same as for the previous letter,
# waiting a second before pressing it again.
if coords == coords_prev:
time.sleep(1.1)
coords_prev = coords
for _ in range(amount):
yield coords
def _letter_coords_and_amount(self, letter: str) -> Tuple[Coords, int]:
idx = next(
i for i, letters in enumerate(BUTTON_LETTERS_BIP39) if letter in letters
)
click_amount = BUTTON_LETTERS_BIP39[idx].index(letter) + 1
return self.buttons.mnemonic_from_index(idx), click_amount

View File

@ -5,7 +5,6 @@ from enum import Enum
from trezorlib.debuglink import LayoutType
from .. import buttons
from .. import translations as TR
if t.TYPE_CHECKING:
@ -49,8 +48,7 @@ def get_char_category(char: str) -> PassphraseCategory:
def go_next(debug: "DebugLink") -> LayoutContent:
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
elif debug.layout_type is LayoutType.Caesar:
debug.press_right()
elif debug.layout_type is LayoutType.Delizia:
@ -62,8 +60,7 @@ def go_next(debug: "DebugLink") -> LayoutContent:
def go_back(debug: "DebugLink", r_middle: bool = False) -> LayoutContent:
if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.cancel())
debug.click(debug.screen_buttons.cancel())
elif debug.layout_type is LayoutType.Caesar:
if r_middle:
debug.press_middle()
@ -118,13 +115,11 @@ def _carousel_steps(current_index: int, wanted_index: int, length: int) -> int:
def unlock_gesture(debug: "DebugLink") -> LayoutContent:
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
elif debug.layout_type is LayoutType.Caesar:
debug.press_right()
elif debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
else:
raise RuntimeError("Unknown model")
return debug.read_layout()

View File

@ -10,7 +10,6 @@ import inspect
import sys
import threading
import time
from pathlib import Path
import click
@ -35,12 +34,6 @@ from trezorlib.cli.trezorctl import cli as main
from trezorlib import cli, debuglink, protobuf # isort:skip
# make /tests part of sys.path so that we can import buttons.py as a module
ROOT = Path(__file__).resolve().parent.parent
sys.path.append(str(ROOT))
import buttons # isort:skip
MODULES = (
binance,
btc,
@ -142,34 +135,24 @@ def send_clicks(dest):
elif key.startswith("m"):
x, y = [int(s) - 1 for s in key[1:].split(",")]
output = (
f"debug.click(ScreenButtons(layout_type).mnemonic_grid({x}, {y}))"
)
DEBUGLINK.click(
buttons.ScreenButtons(DEBUGLINK.layout_type).mnemonic_grid(x, y)
f"debug.click(DEBUGLINK.screen_buttons.mnemonic_grid({x}, {y}))"
)
DEBUGLINK.click(DEBUGLINK.screen_buttons.mnemonic_grid(x, y))
elif key.startswith("p"):
x, y = [int(s) - 1 for s in key[1:].split(",")]
output = f"debug.click(ScreenButtons(layout_type).pin_passphrase_grid({x}, {y}))"
DEBUGLINK.click(
buttons.ScreenButtons(DEBUGLINK.layout_type).pin_passphrase_grid(
x, y
)
)
output = f"debug.click(DEBUGLINK.screen_buttons.pin_passphrase_grid({x}, {y}))"
DEBUGLINK.click(DEBUGLINK.screen_buttons.pin_passphrase_grid(x, y))
elif key == "y":
output = "debug.click(ScreenButtons(layout_type).ok())"
DEBUGLINK.click(buttons.ScreenButtons(DEBUGLINK.layout_type).ok())
output = "debug.click(DEBUGLINK.screen_buttons.ok())"
DEBUGLINK.click(DEBUGLINK.screen_buttons.ok())
elif key == "n":
output = "debug.click(ScreenButtons(layout_type).cancel())"
DEBUGLINK.click(buttons.ScreenButtons(DEBUGLINK.layout_type).cancel())
output = "debug.click(DEBUGLINK.screen_buttons.cancel())"
DEBUGLINK.click(DEBUGLINK.screen_buttons.cancel())
elif key in "0123456789":
index = int(key)
output = f"debug.click(ScreenButtons(layout_type).pin_passphrase_index({index}))"
DEBUGLINK.click(
buttons.ScreenButtons(DEBUGLINK.layout_type).pin_passphrase_index(
index
)
)
output = f"debug.click(DEBUGLINK.screen_buttons.pin_passphrase_index({index}))"
DEBUGLINK.click(DEBUGLINK.screen_buttons.pin_passphrase_index(index))
elif key == "stop":
return
else:

View File

@ -2,7 +2,6 @@ from typing import TYPE_CHECKING
from trezorlib.debuglink import LayoutType
from .. import buttons
from .. import translations as TR
from .common import go_next
@ -17,15 +16,13 @@ def enter_word(
debug: "DebugLink", word: str, is_slip39: bool = False
) -> "LayoutContent":
if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
btns = buttons.ScreenButtons(debug.layout_type)
actions = buttons.ButtonActions(debug.layout_type)
typed_word = word[:4]
for coords in actions.type_word(typed_word, is_slip39=is_slip39):
for coords in debug.button_actions.type_word(typed_word, is_slip39=is_slip39):
debug.click(coords)
if debug.layout_type is LayoutType.Delizia and not is_slip39 and len(word) > 4:
# T3T1 (delizia) BIP39 keyboard allows to "confirm" only if the word is fully written, you need to click the word to auto-complete
debug.click(btns.mnemonic_confirm())
debug.click(btns.mnemonic_confirm())
debug.click(debug.screen_buttons.mnemonic_confirm())
debug.click(debug.screen_buttons.mnemonic_confirm())
return debug.read_layout()
elif debug.layout_type is LayoutType.Caesar:
letter_index = 0
@ -57,8 +54,7 @@ def confirm_recovery(debug: "DebugLink", title: str = "recovery__title") -> None
layout = debug.read_layout()
assert TR.translate(title) == layout.title()
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
elif debug.layout_type is LayoutType.Delizia:
debug.swipe_up()
elif debug.layout_type is LayoutType.Caesar:
@ -71,13 +67,12 @@ def cancel_select_number_of_words(
unlock_repeated_backup=False,
) -> None:
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
assert debug.read_layout().text_content() == TR.recovery__num_of_words
# click the button from ValuePad
if unlock_repeated_backup:
coords = btns.word_count_repeated_cancel()
coords = debug.screen_buttons.word_count_repeated_cancel()
else:
coords = btns.word_count_all_cancel()
coords = debug.screen_buttons.word_count_all_cancel()
debug.click(coords)
elif debug.layout_type is LayoutType.Caesar:
debug.press_right()
@ -86,12 +81,11 @@ def cancel_select_number_of_words(
# navigate to the number and confirm it
debug.press_left()
elif debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
# click the button from ValuePad
if unlock_repeated_backup:
coords = btns.word_count_repeated_cancel()
coords = debug.screen_buttons.word_count_repeated_cancel()
else:
coords = btns.word_count_all_cancel()
coords = debug.screen_buttons.word_count_all_cancel()
debug.click(coords)
else:
raise ValueError("Unknown model")
@ -106,12 +100,11 @@ def select_number_of_words(
assert TR.recovery__num_of_words in layout.text_content()
def select_bolt() -> "LayoutContent":
btns = buttons.ScreenButtons(debug.layout_type)
# click the button from ValuePad
if unlock_repeated_backup:
coords = btns.word_count_repeated_word(num_of_words)
coords = debug.screen_buttons.word_count_repeated_word(num_of_words)
else:
coords = btns.word_count_all_word(num_of_words)
coords = debug.screen_buttons.word_count_all_word(num_of_words)
debug.click(coords)
return debug.read_layout()
@ -126,12 +119,11 @@ def select_number_of_words(
return debug.read_layout()
def select_delizia() -> "LayoutContent":
btns = buttons.ScreenButtons(debug.layout_type)
# click the button from ValuePad
if unlock_repeated_backup:
coords = btns.word_count_repeated_word(num_of_words)
coords = debug.screen_buttons.word_count_repeated_word(num_of_words)
else:
coords = btns.word_count_all_word(num_of_words)
coords = debug.screen_buttons.word_count_all_word(num_of_words)
debug.click(coords)
return debug.read_layout()
@ -186,9 +178,8 @@ def enter_share(
debug.swipe_up()
layout = debug.read_layout()
else:
btns = buttons.ScreenButtons(debug.layout_type)
assert TR.translate(before_title) in debug.read_layout().title()
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
layout = debug.read_layout()
assert "MnemonicKeyboard" in layout.all_components()
@ -263,10 +254,9 @@ def enter_seed_previous_correct(
if go_back:
go_back = False
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.swipe_right()
for _ in range(len(bad_word)):
debug.click(btns.mnemonic_erase())
debug.click(debug.screen_buttons.mnemonic_erase())
elif debug.layout_type is LayoutType.Caesar:
layout = debug.read_layout()
@ -283,10 +273,9 @@ def enter_seed_previous_correct(
debug.press_middle()
layout = debug.read_layout()
elif debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.mnemonic_erase()) # Top-left
debug.click(debug.screen_buttons.mnemonic_erase()) # Top-left
for _ in range(len(bad_word)):
debug.click(btns.mnemonic_erase())
debug.click(debug.screen_buttons.mnemonic_erase())
continue
if i in bad_indexes:
@ -311,8 +300,7 @@ def prepare_enter_seed(
or TR.translate(layout_text) in debug.read_layout().text_content()
)
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
elif debug.layout_type is LayoutType.Delizia:
debug.swipe_up()
debug.swipe_up()
@ -338,11 +326,10 @@ def cancel_recovery(debug: "DebugLink", recovery_type: str = "dry_run") -> None:
assert title in layout.title()
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.cancel())
debug.click(debug.screen_buttons.cancel())
layout = debug.read_layout()
assert cancel_title in layout.title()
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
elif debug.layout_type is LayoutType.Caesar:
debug.press_left()
layout = debug.read_layout()
@ -350,14 +337,13 @@ def cancel_recovery(debug: "DebugLink", recovery_type: str = "dry_run") -> None:
for _ in range(layout.page_count()):
debug.press_right()
elif debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
# go to menu
debug.click(btns.menu())
debug.click(debug.screen_buttons.menu())
layout = debug.read_layout()
assert (
TR.translate(f"recovery__cancel_{recovery_type}") in layout.text_content()
)
debug.click(btns.vertical_menu_items()[0])
debug.click(debug.screen_buttons.vertical_menu_items()[0])
else:
raise ValueError("Unknown model")

View File

@ -5,7 +5,6 @@ from shamir_mnemonic import shamir # type: ignore
from trezorlib.debuglink import LayoutType
from .. import buttons
from .. import translations as TR
if TYPE_CHECKING:
@ -15,12 +14,10 @@ if TYPE_CHECKING:
def confirm_new_wallet(debug: "DebugLink") -> None:
assert debug.read_layout().title() == TR.reset__title_create_wallet
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
elif debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
debug.swipe_up()
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
elif debug.layout_type is LayoutType.Caesar:
debug.press_right()
debug.press_right()
@ -34,8 +31,7 @@ def confirm_new_wallet(debug: "DebugLink") -> None:
def confirm_read(debug: "DebugLink", middle_r: bool = False) -> None:
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
elif debug.layout_type is LayoutType.Delizia:
debug.swipe_up()
elif debug.layout_type is LayoutType.Caesar:
@ -53,16 +49,14 @@ def cancel_backup(
debug: "DebugLink", middle_r: bool = False, confirm: bool = False
) -> None:
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.cancel())
debug.click(btns.cancel())
debug.click(debug.screen_buttons.cancel())
debug.click(debug.screen_buttons.cancel())
elif debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.menu())
debug.click(btns.vertical_menu_items()[0])
debug.click(debug.screen_buttons.menu())
debug.click(debug.screen_buttons.vertical_menu_items()[0])
if confirm:
debug.swipe_up()
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
elif debug.layout_type is LayoutType.Caesar:
debug.press_left()
debug.press_left()
@ -70,16 +64,19 @@ def cancel_backup(
def set_selection(debug: "DebugLink", diff: int) -> None:
if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
btns = buttons.ScreenButtons(debug.layout_type)
assert "NumberInputDialog" in debug.read_layout().all_components()
button = btns.number_input_minus() if diff < 0 else btns.number_input_plus()
button = (
debug.screen_buttons.number_input_minus()
if diff < 0
else debug.screen_buttons.number_input_plus()
)
diff = abs(diff)
for _ in range(diff):
debug.click(button)
if debug.layout_type is LayoutType.Bolt:
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
else:
debug.swipe_up()
elif debug.layout_type is LayoutType.Caesar:
@ -125,11 +122,9 @@ def read_words(debug: "DebugLink", do_htc: bool = True) -> list[str]:
# There is hold-to-confirm button
if do_htc:
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.ok(), hold_ms=1500)
debug.click(debug.screen_buttons.ok(), hold_ms=1500)
elif debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
elif debug.layout_type is LayoutType.Caesar:
debug.press_right(hold_ms=1200)
else:
@ -146,7 +141,6 @@ def confirm_words(debug: "DebugLink", words: list[str]) -> None:
layout = debug.read_layout()
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
assert TR.regexp("reset__select_word_x_of_y_template").match(
layout.text_content()
)
@ -162,10 +156,9 @@ def confirm_words(debug: "DebugLink", words: list[str]) -> None:
]
wanted_word = words[word_pos - 1].lower()
button_pos = btn_texts.index(wanted_word)
debug.click(btns.word_check_words()[button_pos])
debug.click(debug.screen_buttons.word_check_words()[button_pos])
layout = debug.read_layout()
elif debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
assert TR.regexp("reset__select_word_x_of_y_template").match(layout.subtitle())
for _ in range(3):
# "Select word 3 of 20"
@ -179,7 +172,7 @@ def confirm_words(debug: "DebugLink", words: list[str]) -> None:
]
wanted_word = words[word_pos - 1].lower()
button_pos = btn_texts.index(wanted_word)
debug.click(btns.vertical_menu_items()[button_pos])
debug.click(debug.screen_buttons.vertical_menu_items()[button_pos])
layout = debug.read_layout()
elif debug.layout_type is LayoutType.Caesar:
assert TR.reset__select_correct_word in layout.text_content()

View File

@ -25,7 +25,7 @@ from trezorlib.debuglink import DebugLink, LayoutType
from trezorlib.protobuf import MessageType
from trezorlib.tools import parse_path
from .. import buttons, common
from .. import common
from .. import translations as TR
from ..device_tests.bitcoin.payment_req import make_coinjoin_request
from ..tx_cache import TxCache
@ -54,16 +54,14 @@ PIN4 = "1234"
def _passphrase_j(debug: DebugLink) -> Tuple[int, int]:
btns = buttons.ScreenButtons(debug.layout_type)
if debug.layout_type is LayoutType.Bolt:
return btns.pin_passphrase_grid(1, 1)
return debug.screen_buttons.pin_passphrase_grid(1, 1)
else:
return btns.pin_passphrase_grid(0, 1)
return debug.screen_buttons.pin_passphrase_grid(0, 1)
def _center_button(debug: DebugLink) -> Tuple[int, int]:
btns = buttons.ScreenButtons(debug.layout_type)
return btns.pin_passphrase_grid(1, 1)
return debug.screen_buttons.pin_passphrase_grid(1, 1)
def set_autolock_delay(device_handler: "BackgroundDeviceHandler", delay_ms: int):
@ -81,8 +79,7 @@ def set_autolock_delay(device_handler: "BackgroundDeviceHandler", delay_ms: int)
layout = go_next(debug)
if debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
layout = debug.read_layout()
assert layout.main_component() == "Homescreen"
device_handler.result()
@ -117,9 +114,8 @@ def test_autolock_interrupts_signing(device_handler: "BackgroundDeviceHandler"):
)
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.ok())
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
debug.click(debug.screen_buttons.ok())
layout = debug.read_layout()
assert TR.send__total_amount in layout.text_content()
assert "0.0039 BTC" in layout.text_content()
@ -173,14 +169,12 @@ def test_autolock_does_not_interrupt_signing(device_handler: "BackgroundDeviceHa
)
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.ok())
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
debug.click(debug.screen_buttons.ok())
layout = debug.read_layout()
assert TR.send__total_amount in layout.text_content()
assert "0.0039 BTC" in layout.text_content()
elif debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
debug.swipe_up()
debug.swipe_up()
layout = debug.read_layout()
@ -203,9 +197,9 @@ def test_autolock_does_not_interrupt_signing(device_handler: "BackgroundDeviceHa
device_handler.client.set_filter(messages.TxAck, sleepy_filter)
# confirm transaction
if debug.layout_type is LayoutType.Bolt:
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
elif debug.layout_type is LayoutType.Delizia:
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
elif debug.layout_type is LayoutType.Caesar:
debug.press_middle()
@ -245,8 +239,7 @@ def test_autolock_passphrase_keyboard(device_handler: "BackgroundDeviceHandler")
# Send the passphrase to the client (TT has it clicked already, TR needs to input it)
if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.passphrase_confirm())
debug.click(debug.screen_buttons.passphrase_confirm())
elif debug.layout_type is LayoutType.Caesar:
debug.input("j" * 8)
@ -368,33 +361,29 @@ def test_dryrun_enter_word_slowly(device_handler: "BackgroundDeviceHandler"):
recovery.select_number_of_words(debug, 20)
if debug.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(debug.layout_type)
actions = buttons.ButtonActions(debug.layout_type)
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
layout = debug.read_layout()
assert layout.main_component() == "MnemonicKeyboard"
# type the word OCEAN slowly
for coords in actions.type_word("ocea", is_slip39=True):
for coords in debug.button_actions.type_word("ocea", is_slip39=True):
time.sleep(9)
debug.click(coords)
debug.click(btns.mnemonic_confirm())
debug.click(debug.screen_buttons.mnemonic_confirm())
layout = debug.read_layout()
# should not have locked, even though we took 9 seconds to type each letter
assert layout.main_component() == "MnemonicKeyboard"
elif debug.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(debug.layout_type)
actions = buttons.ButtonActions(debug.layout_type)
debug.swipe_up()
layout = debug.read_layout()
assert layout.main_component() == "MnemonicKeyboard"
# type the word OCEAN slowly
for coords in actions.type_word("ocea", is_slip39=True):
for coords in debug.button_actions.type_word("ocea", is_slip39=True):
time.sleep(9)
debug.click(coords)
debug.click(btns.mnemonic_confirm())
debug.click(debug.screen_buttons.mnemonic_confirm())
layout = debug.read_layout()
# should not have locked, even though we took 9 seconds to type each letter
assert layout.main_component() == "MnemonicKeyboard"

View File

@ -22,7 +22,7 @@ import pytest
from trezorlib import models
from trezorlib.debuglink import LayoutType
from .. import buttons, common
from .. import common
if TYPE_CHECKING:
from ..device_handler import BackgroundDeviceHandler
@ -81,8 +81,7 @@ def test_hold_to_lock(device_handler: "BackgroundDeviceHandler"):
if debug.layout_type is LayoutType.Caesar:
debug.press_right()
else:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.info())
debug.click(debug.screen_buttons.info())
layout = debug.read_layout()
assert "PinKeyboard" in layout.all_components()
debug.input("1234")

View File

@ -22,7 +22,6 @@ import pytest
from trezorlib.debuglink import LayoutType
from .. import buttons
from ..common import get_test_address
from .common import CommonPass, PassphraseCategory, get_char_category
@ -50,7 +49,7 @@ KEYBOARD_CATEGORIES_DELIZIA = [
# TODO: better read this from the trace
KEYBOARD_CATEGORY = PassphraseCategory.LOWERCASE
COORDS_PREV: buttons.Coords = (0, 0)
COORDS_PREV: tuple[int, int] = (0, 0)
# Testing the maximum length is really 50
@ -131,8 +130,7 @@ def press_char(debug: "DebugLink", char: str) -> None:
go_to_category(debug, char_category)
actions = buttons.ButtonActions(debug.layout_type)
coords, amount = actions.passphrase(char)
coords, amount = debug.button_actions.passphrase(char)
# If the button is the same as for the previous char,
# waiting a second before pressing it again.
# (not for a space in Bolt layout)
@ -158,16 +156,14 @@ def input_passphrase(debug: "DebugLink", passphrase: str, check: bool = True) ->
def enter_passphrase(debug: "DebugLink") -> None:
"""Enter a passphrase"""
is_empty: bool = len(debug.read_layout().passphrase()) == 0
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.passphrase_confirm())
debug.click(debug.screen_buttons.passphrase_confirm())
if is_empty and debug.layout_type is LayoutType.Delizia:
debug.click(btns.ui_yes())
debug.click(debug.screen_buttons.ui_yes())
def delete_char(debug: "DebugLink") -> None:
"""Deletes the last char"""
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.pin_passphrase_erase())
debug.click(debug.screen_buttons.pin_passphrase_erase())
VECTORS = ( # passphrase, address
@ -239,8 +235,7 @@ def test_passphrase_loop_all_characters(device_handler: "BackgroundDeviceHandler
debug.read_layout()
enter_passphrase(debug)
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.passphrase_confirm())
debug.click(debug.screen_buttons.passphrase_confirm())
@pytest.mark.setup_client(passphrase=True)
@ -248,8 +243,7 @@ def test_passphrase_click_same_button_many_times(
device_handler: "BackgroundDeviceHandler",
):
with prepare_passphrase_dialogue(device_handler) as debug:
actions = buttons.ButtonActions(debug.layout_type)
a_coords, _ = actions.passphrase("a")
a_coords, _ = debug.button_actions.passphrase("a")
for _ in range(10):
debug.click(a_coords)

View File

@ -24,7 +24,6 @@ import pytest
from trezorlib import device, exceptions
from trezorlib.debuglink import LayoutType
from .. import buttons
from .. import translations as TR
from .common import go_back, go_next, navigate_to_action_and_press
@ -138,9 +137,8 @@ def prepare(
yield debug
if debug.layout_type is LayoutType.Delizia and tap:
btns = buttons.ScreenButtons(debug.layout_type)
go_next(debug)
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
else:
go_next(debug)
@ -156,11 +154,10 @@ def _input_pin(debug: "DebugLink", pin: str, check: bool = False) -> None:
if check:
before = debug.read_layout().pin()
if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
btns = buttons.ScreenButtons(debug.layout_type)
digits_order = debug.read_layout().tt_pin_digits_order()
for digit in pin:
digit_index = digits_order.index(digit)
coords = btns.pin_passphrase_index(digit_index)
coords = debug.screen_buttons.pin_passphrase_index(digit_index)
debug.click(coords)
elif debug.layout_type is LayoutType.Caesar:
for digit in pin:
@ -174,8 +171,7 @@ def _input_pin(debug: "DebugLink", pin: str, check: bool = False) -> None:
def _see_pin(debug: "DebugLink") -> None:
"""Navigate to "SHOW" and press it"""
if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.pin_passphrase_input())
debug.click(debug.screen_buttons.pin_passphrase_input())
elif debug.layout_type is LayoutType.Caesar:
navigate_to_action_and_press(debug, SHOW, TR_PIN_ACTIONS)
@ -187,8 +183,7 @@ def _delete_pin(debug: "DebugLink", digits_to_delete: int, check: bool = True) -
for _ in range(digits_to_delete):
if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.pin_passphrase_erase())
debug.click(debug.screen_buttons.pin_passphrase_erase())
elif debug.layout_type is LayoutType.Caesar:
navigate_to_action_and_press(debug, DELETE, TR_PIN_ACTIONS)
@ -200,9 +195,8 @@ def _delete_pin(debug: "DebugLink", digits_to_delete: int, check: bool = True) -
def _delete_all(debug: "DebugLink", check: bool = True) -> None:
"""Navigate to "DELETE" and hold it until all digits are deleted"""
if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(
btns.pin_passphrase_erase(),
debug.screen_buttons.pin_passphrase_erase(),
hold_ms=1500,
)
elif debug.layout_type is LayoutType.Caesar:
@ -228,8 +222,7 @@ def _cancel_pin(debug: "DebugLink") -> None:
def _confirm_pin(debug: "DebugLink") -> None:
"""Navigate to "ENTER" and press it"""
if debug.layout_type in (LayoutType.Bolt, LayoutType.Delizia):
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.pin_confirm())
debug.click(debug.screen_buttons.pin_confirm())
elif debug.layout_type is LayoutType.Caesar:
navigate_to_action_and_press(debug, ENTER, TR_PIN_ACTIONS)

View File

@ -20,7 +20,6 @@ import pytest
from trezorlib import device
from .. import buttons
from .. import translations as TR
if TYPE_CHECKING:
@ -36,11 +35,10 @@ pytestmark = [
def test_tutorial_ignore_menu(device_handler: "BackgroundDeviceHandler"):
debug = device_handler.debuglink()
btns = buttons.ScreenButtons(debug.layout_type)
device_handler.run(device.show_device_tutorial)
assert debug.read_layout().title() == TR.tutorial__welcome_safe5
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
assert debug.read_layout().title() == TR.tutorial__title_lets_begin
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_easy_navigation
@ -48,7 +46,7 @@ def test_tutorial_ignore_menu(device_handler: "BackgroundDeviceHandler"):
assert debug.read_layout().title() == TR.tutorial__title_handy_menu
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_hold
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
assert debug.read_layout().title() == TR.tutorial__title_well_done
debug.swipe_up()
@ -57,25 +55,24 @@ def test_tutorial_ignore_menu(device_handler: "BackgroundDeviceHandler"):
def test_tutorial_menu_open_close(device_handler: "BackgroundDeviceHandler"):
debug = device_handler.debuglink()
btns = buttons.ScreenButtons(debug.layout_type)
device_handler.run(device.show_device_tutorial)
assert debug.read_layout().title() == TR.tutorial__welcome_safe5
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
assert debug.read_layout().title() == TR.tutorial__title_lets_begin
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_easy_navigation
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_handy_menu
debug.click(btns.menu())
debug.click(debug.screen_buttons.menu())
assert TR.tutorial__did_you_know in debug.read_layout().text_content()
debug.click(btns.menu())
debug.click(debug.screen_buttons.menu())
assert debug.read_layout().title() == TR.tutorial__title_handy_menu
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_hold
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
assert debug.read_layout().title() == TR.tutorial__title_well_done
debug.swipe_up()
@ -84,22 +81,21 @@ def test_tutorial_menu_open_close(device_handler: "BackgroundDeviceHandler"):
def test_tutorial_menu_exit(device_handler: "BackgroundDeviceHandler"):
debug = device_handler.debuglink()
btns = buttons.ScreenButtons(debug.layout_type)
device_handler.run(device.show_device_tutorial)
assert debug.read_layout().title() == TR.tutorial__welcome_safe5
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
assert debug.read_layout().title() == TR.tutorial__title_lets_begin
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_easy_navigation
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_handy_menu
debug.click(btns.menu())
debug.click(debug.screen_buttons.menu())
assert TR.tutorial__did_you_know in debug.read_layout().text_content()
debug.click(btns.vertical_menu_items()[2])
debug.click(debug.screen_buttons.vertical_menu_items()[2])
assert TR.instructions__hold_to_exit_tutorial in debug.read_layout().footer()
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
assert debug.read_layout().title() == TR.tutorial__title_well_done
debug.swipe_up()
@ -108,20 +104,19 @@ def test_tutorial_menu_exit(device_handler: "BackgroundDeviceHandler"):
def test_tutorial_menu_repeat(device_handler: "BackgroundDeviceHandler"):
debug = device_handler.debuglink()
btns = buttons.ScreenButtons(debug.layout_type)
device_handler.run(device.show_device_tutorial)
assert debug.read_layout().title() == TR.tutorial__welcome_safe5
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
assert debug.read_layout().title() == TR.tutorial__title_lets_begin
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_easy_navigation
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_handy_menu
debug.click(btns.menu())
debug.click(debug.screen_buttons.menu())
assert TR.tutorial__did_you_know in debug.read_layout().text_content()
debug.click(btns.vertical_menu_items()[1])
debug.click(debug.screen_buttons.vertical_menu_items()[1])
assert debug.read_layout().title() == TR.tutorial__title_lets_begin
debug.swipe_up()
@ -130,7 +125,7 @@ def test_tutorial_menu_repeat(device_handler: "BackgroundDeviceHandler"):
assert debug.read_layout().title() == TR.tutorial__title_handy_menu
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_hold
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
assert debug.read_layout().title() == TR.tutorial__title_well_done
debug.swipe_up()
@ -139,32 +134,31 @@ def test_tutorial_menu_repeat(device_handler: "BackgroundDeviceHandler"):
def test_tutorial_menu_funfact(device_handler: "BackgroundDeviceHandler"):
debug = device_handler.debuglink()
btns = buttons.ScreenButtons(debug.layout_type)
device_handler.run(device.show_device_tutorial)
assert debug.read_layout().title() == TR.tutorial__welcome_safe5
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
assert debug.read_layout().title() == TR.tutorial__title_lets_begin
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_easy_navigation
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_handy_menu
debug.click(btns.menu())
debug.click(debug.screen_buttons.menu())
assert TR.tutorial__did_you_know in debug.read_layout().text_content()
debug.click(btns.vertical_menu_items()[0])
debug.click(debug.screen_buttons.vertical_menu_items()[0])
assert debug.read_layout().text_content() in TR.tutorial__first_wallet.replace(
"\n", " "
)
debug.click(btns.menu())
debug.click(debug.screen_buttons.menu())
assert TR.tutorial__did_you_know in debug.read_layout().text_content()
debug.click(btns.menu())
debug.click(debug.screen_buttons.menu())
assert debug.read_layout().title() == TR.tutorial__title_handy_menu
debug.swipe_up()
assert debug.read_layout().title() == TR.tutorial__title_hold
debug.click(btns.tap_to_confirm())
debug.click(debug.screen_buttons.tap_to_confirm())
assert debug.read_layout().title() == TR.tutorial__title_well_done
debug.swipe_up()

View File

@ -28,8 +28,6 @@ import pytest
from trezorlib import btc, messages, models, tools
from trezorlib.debuglink import LayoutType
from . import buttons
if TYPE_CHECKING:
from _pytest.mark.structures import MarkDecorator
@ -323,13 +321,12 @@ def click_info_button_bolt(debug: "DebugLink") -> Generator[Any, Any, ButtonRequ
def click_info_button_delizia(debug: "DebugLink"):
"""Click Shamir backup info button and return back."""
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.menu())
debug.click(debug.screen_buttons.menu())
layout = debug.read_layout()
assert "VerticalMenu" in layout.all_components()
debug.click(btns.vertical_menu_items()[0])
debug.click(btns.menu())
debug.click(btns.menu())
debug.click(debug.screen_buttons.vertical_menu_items()[0])
debug.click(debug.screen_buttons.menu())
debug.click(debug.screen_buttons.menu())
def check_pin_backoff_time(attempts: int, start: float) -> None:

View File

@ -21,7 +21,7 @@ from trezorlib.debuglink import LayoutType
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import TrezorFailure
from ...common import buttons, parametrize_using_common_fixtures
from ...common import parametrize_using_common_fixtures
from ...input_flows import InputFlowConfirmAllWarnings
pytestmark = [
@ -41,10 +41,9 @@ def show_details_input_flow(client: Client):
# Caesar - right button for "Show all"
client.debug.press_yes()
elif client.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(client.layout_type)
# Delizia - "Show all" button from context menu
client.debug.click(btns.menu())
client.debug.click(btns.vertical_menu_items()[0])
client.debug.click(client.debug.screen_buttons.menu())
client.debug.click(client.debug.screen_buttons.vertical_menu_items()[0])
else:
raise NotImplementedError
# reset ui flow to continue "automatically"

View File

@ -22,7 +22,6 @@ from trezorlib.debuglink import LayoutType
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.exceptions import Cancelled, TrezorFailure
from .. import buttons
from ..input_flows import (
InputFlowCodeChangeFail,
InputFlowNewCodeMismatch,
@ -187,18 +186,17 @@ def test_change_invalid_current(client: Client):
def test_pin_menu_cancel_setup(client: Client):
def cancel_pin_setup_input_flow():
yield
btns = buttons.ScreenButtons(client.layout_type)
# enter context menu
client.debug.click(btns.menu())
client.debug.click(client.debug.screen_buttons.menu())
client.debug.synchronize_at("VerticalMenu")
# click "Cancel PIN setup"
client.debug.click(btns.vertical_menu_items()[0])
client.debug.click(client.debug.screen_buttons.vertical_menu_items()[0])
client.debug.synchronize_at("Paragraphs")
# swipe through info screen
client.debug.swipe_up()
client.debug.synchronize_at("PromptScreen")
# tap to confirm
client.debug.click(btns.tap_to_confirm())
client.debug.click(client.debug.screen_buttons.tap_to_confirm())
with client, pytest.raises(Cancelled):
client.set_input_flow(cancel_pin_setup_input_flow)

View File

@ -19,7 +19,6 @@ from trezorlib.debuglink import DebugLink, LayoutContent, LayoutType
from trezorlib.debuglink import TrezorClientDebugLink as Client
from trezorlib.debuglink import multipage_content
from . import buttons
from . import translations as TR
from .common import (
BRGeneratorType,
@ -316,13 +315,12 @@ class InputFlowSignVerifyMessageLong(InputFlowBase):
layouts: list[LayoutContent] = []
br = yield # confirm address
btns = buttons.ScreenButtons(self.client.layout_type)
self.debug.read_layout()
self.debug.press_yes()
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0])
br = yield
self.debug.read_layout()
@ -352,9 +350,8 @@ class InputFlowSignMessageInfo(InputFlowBase):
def input_flow_bolt(self) -> BRGeneratorType:
yield
# signing address/message info
btns = buttons.ScreenButtons(self.client.layout_type)
self.debug.click(btns.menu())
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# signing address "x"
self.debug.press_no()
self.debug.synchronize_at("IconDialog")
@ -365,11 +362,10 @@ class InputFlowSignMessageInfo(InputFlowBase):
def input_flow_delizia(self) -> BRGeneratorType:
yield
# show address/message info
btns = buttons.ScreenButtons(self.client.layout_type)
self.debug.click(btns.menu())
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(btns.menu())
self.debug.click(btns.vertical_menu_items()[1])
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0])
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1])
# address mismatch? yes!
self.debug.swipe_up()
yield
@ -381,15 +377,14 @@ class InputFlowShowAddressQRCode(InputFlowBase):
def input_flow_bolt(self) -> BRGeneratorType:
yield
btns = buttons.ScreenButtons(self.client.layout_type)
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# synchronize; TODO get rid of this once we have single-global-layout
self.debug.synchronize_at("SimplePage")
self.debug.swipe_left()
self.debug.swipe_right()
self.debug.swipe_left()
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.press_no()
self.debug.press_no()
self.debug.press_yes()
@ -417,27 +412,26 @@ class InputFlowShowAddressQRCode(InputFlowBase):
def input_flow_delizia(self) -> BRGeneratorType:
yield
btns = buttons.ScreenButtons(self.client.layout_type)
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# synchronize; TODO get rid of this once we have single-global-layout
self.debug.synchronize_at("VerticalMenu")
# menu
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0])
self.debug.synchronize_at("Qr")
# qr code
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# menu
self.debug.click(btns.vertical_menu_items()[1])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1])
# address details
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# menu
self.debug.click(btns.vertical_menu_items()[2])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[2])
# cancel
self.debug.swipe_up()
# really cancel
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# menu
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
layout = self.debug.read_layout()
while "PromptScreen" not in layout.all_components():
@ -445,7 +439,7 @@ class InputFlowShowAddressQRCode(InputFlowBase):
layout = self.debug.read_layout()
self.debug.synchronize_at("PromptScreen")
# tap to confirm
self.debug.click(btns.tap_to_confirm())
self.debug.click(self.client.debug.screen_buttons.tap_to_confirm())
class InputFlowShowAddressQRCodeCancel(InputFlowBase):
@ -454,13 +448,12 @@ class InputFlowShowAddressQRCodeCancel(InputFlowBase):
def input_flow_bolt(self) -> BRGeneratorType:
yield
btns = buttons.ScreenButtons(self.client.layout_type)
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# synchronize; TODO get rid of this once we have single-global-layout
self.debug.synchronize_at("SimplePage")
self.debug.swipe_left()
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.press_no()
self.debug.press_yes()
@ -481,26 +474,25 @@ class InputFlowShowAddressQRCodeCancel(InputFlowBase):
def input_flow_delizia(self) -> BRGeneratorType:
yield
btns = buttons.ScreenButtons(self.client.layout_type)
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# synchronize; TODO get rid of this once we have single-global-layout
self.debug.synchronize_at("VerticalMenu")
# menu
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0])
self.debug.synchronize_at("Qr")
# qr code
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# menu
self.debug.click(btns.vertical_menu_items()[1])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1])
# address details
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# menu
self.debug.click(btns.vertical_menu_items()[2])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[2])
# cancel
self.debug.swipe_up()
self.debug.synchronize_at("PromptScreen")
# really cancel
self.debug.click(btns.tap_to_confirm())
self.debug.click(self.client.debug.screen_buttons.tap_to_confirm())
class InputFlowShowMultisigXPUBs(InputFlowBase):
@ -520,7 +512,6 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
def input_flow_bolt(self) -> BRGeneratorType:
yield # multisig address warning
btns = buttons.ScreenButtons(self.client.layout_type)
self.debug.press_yes()
yield # show address
@ -529,7 +520,7 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
assert "(MULTISIG)" in layout.title()
assert layout.text_content().replace(" ", "") == self.address
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
assert "Qr" in self.all_components()
self.debug.swipe_left()
@ -546,7 +537,7 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
content = layout.text_content().replace(" ", "")
assert self.xpubs[xpub_num] in content
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# show address
self.debug.press_no()
# address mismatch
@ -598,27 +589,26 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
def input_flow_delizia(self) -> BRGeneratorType:
yield # multisig address warning
btns = buttons.ScreenButtons(self.client.layout_type)
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(btns.vertical_menu_items()[1])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1])
yield # show address
layout = self.debug.read_layout()
assert TR.address__title_receive_address in layout.title()
assert layout.text_content().replace(" ", "") == self.address
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
assert "VerticalMenu" in self.all_components()
# menu
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0])
self.debug.synchronize_at("Qr")
# qr code
assert "Qr" in self.all_components()
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# menu
assert "VerticalMenu" in self.all_components()
self.debug.click(btns.vertical_menu_items()[1])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1])
layout = self.debug.synchronize_at("AddressDetails")
# address details
assert "Multisig 2 of 3" in layout.screen_content()
@ -629,17 +619,17 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
self.debug.swipe_left()
self.debug.swipe_left()
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
# menu
self.debug.click(btns.vertical_menu_items()[2])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[2])
# cancel
self.debug.swipe_up()
# really cancel
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
# menu
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
layout = self.debug.synchronize_at("Paragraphs")
# address
while "PromptScreen" not in layout.all_components():
@ -656,7 +646,6 @@ class InputFlowShowXpubQRCode(InputFlowBase):
self.passphrase = passphrase
def input_flow_bolt(self) -> BRGeneratorType:
btns = buttons.ScreenButtons(self.client.layout_type)
if self.passphrase:
yield
self.debug.press_yes()
@ -669,14 +658,14 @@ class InputFlowShowXpubQRCode(InputFlowBase):
self.debug.press_yes()
br = yield
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# synchronize; TODO get rid of this once we have single-global-layout
self.debug.synchronize_at("SimplePage")
self.debug.swipe_left()
self.debug.swipe_right()
self.debug.swipe_left()
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.press_no()
self.debug.press_no()
for _ in range(br.pages - 1):
@ -711,7 +700,6 @@ class InputFlowShowXpubQRCode(InputFlowBase):
self.debug.press_middle()
def input_flow_delizia(self) -> BRGeneratorType:
btns = buttons.ScreenButtons(self.client.layout_type)
if self.passphrase:
yield
self.debug.press_yes()
@ -727,32 +715,32 @@ class InputFlowShowXpubQRCode(InputFlowBase):
assert layout.title() in (TR.address__public_key, "XPUB")
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
assert "VerticalMenu" in self.all_components()
# menu
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0])
self.debug.synchronize_at("Qr")
# qr code
assert "Qr" in self.all_components()
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
# menu
assert "VerticalMenu" in self.all_components()
self.debug.click(btns.vertical_menu_items()[1])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[1])
layout = self.debug.synchronize_at("AddressDetails")
# address details
assert TR.address_details__derivation_path in layout.screen_content()
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
layout = self.debug.synchronize_at("VerticalMenu")
# menu
self.debug.click(btns.vertical_menu_items()[2])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[2])
# cancel
self.debug.swipe_up()
# really cancel
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
layout = self.debug.synchronize_at("VerticalMenu")
# menu
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
layout = self.debug.synchronize_at("Paragraphs")
# address
while "PromptScreen" not in layout.all_components():
@ -865,7 +853,6 @@ class InputFlowSignTxHighFee(InputFlowBase):
def sign_tx_go_to_info(client: Client) -> Generator[None, messages.ButtonRequest, str]:
btns = buttons.ScreenButtons(client.layout_type)
yield # confirm output
client.debug.read_layout()
client.debug.press_yes()
@ -880,7 +867,7 @@ def sign_tx_go_to_info(client: Client) -> Generator[None, messages.ButtonRequest
layout = client.debug.read_layout()
content = layout.text_content()
client.debug.click(btns.menu())
client.debug.click(client.debug.screen_buttons.menu())
return content
@ -888,7 +875,6 @@ def sign_tx_go_to_info(client: Client) -> Generator[None, messages.ButtonRequest
def sign_tx_go_to_info_t3t1(
client: Client, multi_account: bool = False
) -> Generator[None, messages.ButtonRequest, str]:
btns = buttons.ScreenButtons(client.layout_type)
yield # confirm output
client.debug.read_layout()
client.debug.swipe_up()
@ -903,22 +889,22 @@ def sign_tx_go_to_info_t3t1(
yield # confirm transaction
client.debug.read_layout()
client.debug.click(btns.menu())
client.debug.click(client.debug.screen_buttons.menu())
client.debug.synchronize_at("VerticalMenu")
client.debug.click(btns.vertical_menu_items()[0])
client.debug.click(client.debug.screen_buttons.vertical_menu_items()[0])
layout = client.debug.read_layout()
content = layout.text_content()
client.debug.click(btns.menu())
client.debug.click(client.debug.screen_buttons.menu())
client.debug.synchronize_at("VerticalMenu")
client.debug.click(btns.vertical_menu_items()[1])
client.debug.click(client.debug.screen_buttons.vertical_menu_items()[1])
layout = client.debug.read_layout()
content += " " + layout.text_content()
client.debug.click(btns.menu())
client.debug.click(btns.menu())
client.debug.click(client.debug.screen_buttons.menu())
client.debug.click(client.debug.screen_buttons.menu())
return content
@ -1031,12 +1017,11 @@ class InputFlowSignTxInformationCancel(InputFlowBase):
self.debug.press_left()
def input_flow_delizia(self) -> BRGeneratorType:
btns = buttons.ScreenButtons(self.client.layout_type)
yield from sign_tx_go_to_info_t3t1(self.client)
self.debug.click(btns.menu())
self.debug.click(btns.vertical_menu_items()[2])
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[2])
self.debug.synchronize_at("PromptScreen")
self.debug.click(btns.tap_to_confirm())
self.debug.click(self.client.debug.screen_buttons.tap_to_confirm())
class InputFlowSignTxInformationReplacement(InputFlowBase):
@ -1044,7 +1029,6 @@ class InputFlowSignTxInformationReplacement(InputFlowBase):
super().__init__(client)
def input_flow_bolt(self) -> BRGeneratorType:
btns = buttons.ScreenButtons(self.client.layout_type)
yield # confirm txid
self.debug.press_yes()
yield # confirm address
@ -1058,8 +1042,8 @@ class InputFlowSignTxInformationReplacement(InputFlowBase):
self.debug.press_yes()
yield # transaction summary, press info
self.debug.click(btns.menu())
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.press_yes()
def input_flow_caesar(self) -> BRGeneratorType:
@ -2341,18 +2325,17 @@ class InputFlowResetSkipBackup(InputFlowBase):
self.debug.press_no()
def input_flow_delizia(self) -> BRGeneratorType:
btns = buttons.ScreenButtons(self.client.layout_type)
yield from self.BAK.confirm_new_wallet()
yield # Skip Backup
assert TR.backup__new_wallet_created in self.text_content()
self.debug.swipe_up()
yield
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.client.debug.screen_buttons.vertical_menu_items()[0])
self.debug.swipe_up()
self.debug.synchronize_at("PromptScreen")
self.debug.click(btns.tap_to_confirm())
self.debug.click(self.client.debug.screen_buttons.tap_to_confirm())
class InputFlowConfirmAllWarnings(InputFlowBase):
@ -2371,7 +2354,6 @@ class InputFlowConfirmAllWarnings(InputFlowBase):
return self.input_flow_bolt()
def input_flow_delizia(self) -> BRGeneratorType:
btns = buttons.ScreenButtons(self.client.layout_type)
br = yield
while True:
# wait for homescreen to go away
@ -2389,9 +2371,11 @@ class InputFlowConfirmAllWarnings(InputFlowBase):
TR.send__cancel_sign,
)
if any(needle.lower() in text for needle in hi_prio):
self.debug.click(btns.menu())
self.debug.click(self.client.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(btns.vertical_menu_items()[1])
self.debug.click(
self.client.debug.screen_buttons.vertical_menu_items()[1]
)
elif "PromptScreen" in layout.all_components():
self.debug.press_yes()
elif "SwipeContent" in layout.all_components():
@ -2415,8 +2399,7 @@ class InputFlowFidoConfirm(InputFlowBase):
yield from self.input_flow_bolt()
def input_flow_delizia(self) -> BRGeneratorType:
btns = buttons.ScreenButtons(self.client.layout_type)
while True:
yield
self.debug.swipe_up()
self.debug.click(btns.tap_to_confirm())
self.debug.click(self.client.debug.screen_buttons.tap_to_confirm())

View File

@ -4,7 +4,6 @@ from trezorlib import messages
from trezorlib.debuglink import LayoutType
from trezorlib.debuglink import TrezorClientDebugLink as Client
from . import buttons
from . import translations as TR
from .click_tests.common import go_next
from .common import BRGeneratorType, get_text_possible_pagination
@ -143,14 +142,13 @@ class RecoveryFlow:
else:
self.debug.press_no()
elif self.client.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(self.client.layout_type)
assert TR.recovery__enter_each_word in self._text_content()
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
if confirm:
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
else:
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
else:
assert TR.recovery__enter_any_share in self._text_content()
self.debug.press_no()
@ -176,15 +174,14 @@ class RecoveryFlow:
assert TR.regexp("recovery__x_of_y_entered_template").search(
self._text_content()
)
btns = buttons.ScreenButtons(self.client.layout_type)
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
assert (yield).name == "abort_recovery"
self.debug.swipe_up()
layout = self.debug.read_layout()
assert layout.title() == TR.recovery__title_cancel_recovery
self.debug.click(btns.tap_to_confirm())
self.debug.click(self.debug.screen_buttons.tap_to_confirm())
else:
assert TR.regexp("recovery__x_of_y_entered_template").search(
self._text_content()
@ -339,17 +336,16 @@ class RecoveryFlow:
self.debug.press_yes()
def click_info_delizia(self) -> BRGeneratorType:
btns = buttons.ScreenButtons(self.client.layout_type)
# Moving through the menu into the show_shares screen
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
br = yield
assert br.name == "show_shares"
assert br.code == B.Other
# Getting back to the homepage
self.debug.click(btns.menu())
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.click(self.debug.screen_buttons.menu())
class EthereumFlow:
@ -464,7 +460,6 @@ class EthereumFlow:
def _confirm_tx_delizia(
self, cancel: bool, info: bool, go_back_from_summary: bool
) -> BRGeneratorType:
btns = buttons.ScreenButtons(self.client.layout_type)
assert (yield).name == "confirm_output"
title = self.debug.read_layout().title()
assert TR.words__address in title
@ -485,17 +480,17 @@ class EthereumFlow:
self.debug.press_yes()
assert (yield).name == "confirm_ethereum_tx"
if info:
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
text = self.debug.read_layout().text_content()
assert TR.ethereum__gas_limit in text
assert TR.ethereum__gas_price in text
self.debug.click(btns.menu())
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.swipe_up()
self.debug.read_layout()
self.debug.click(btns.tap_to_confirm())
self.debug.click(self.debug.screen_buttons.tap_to_confirm())
assert (yield).name == "confirm_ethereum_tx"
def confirm_tx(
@ -531,11 +526,10 @@ class EthereumFlow:
TR.ethereum__staking_claim_intro,
)
if self.client.layout_type is LayoutType.Bolt:
btns = buttons.ScreenButtons(self.client.layout_type)
# confirm intro
if info:
self.debug.click(
btns.menu(),
self.debug.screen_buttons.menu(),
)
assert self.debug.read_layout().title() in (
TR.ethereum__staking_stake_address,
@ -557,18 +551,17 @@ class EthereumFlow:
self.debug.press_yes()
elif self.client.layout_type is LayoutType.Delizia:
btns = buttons.ScreenButtons(self.client.layout_type)
# confirm intro
if info:
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
assert self.debug.read_layout().title() in (
TR.ethereum__staking_stake_address,
TR.ethereum__staking_claim_address,
)
self.debug.click(btns.menu())
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.swipe_up()
br = yield
@ -577,13 +570,13 @@ class EthereumFlow:
# confirm summary
if info:
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.synchronize_at("VerticalMenu")
self.debug.click(btns.vertical_menu_items()[0])
self.debug.click(self.debug.screen_buttons.vertical_menu_items()[0])
assert TR.ethereum__gas_limit in self.debug.read_layout().text_content()
assert TR.ethereum__gas_price in self.debug.read_layout().text_content()
self.debug.click(btns.menu())
self.debug.click(btns.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.click(self.debug.screen_buttons.menu())
self.debug.swipe_up()
# br = yield # FIXME: no BR on sign transaction

View File

@ -1,7 +1,5 @@
from typing import TYPE_CHECKING
from .. import buttons
if TYPE_CHECKING:
from trezorlib.debuglink import DebugLink, LayoutContent
@ -10,45 +8,41 @@ def _enter_word(
debug: "DebugLink", word: str, is_slip39: bool = False
) -> "LayoutContent":
typed_word = word[:4]
actions = buttons.ButtonActions(debug.layout_type)
btns = buttons.ScreenButtons(debug.layout_type)
for coords in actions.type_word(typed_word, is_slip39=is_slip39):
for coords in debug.button_actions.type_word(typed_word, is_slip39=is_slip39):
debug.click(coords)
debug.read_layout(wait=False)
debug.click(btns.mnemonic_confirm())
debug.click(debug.screen_buttons.mnemonic_confirm())
return debug.read_layout(wait=True)
def confirm_recovery(debug: "DebugLink") -> None:
btns = buttons.ScreenButtons(debug.layout_type)
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
debug.read_layout(wait=True)
def select_number_of_words(
debug: "DebugLink", tag_version: tuple | None, num_of_words: int = 20
) -> None:
btns = buttons.ScreenButtons(debug.layout_type)
if "SelectWordCount" not in debug.read_layout().all_components():
debug.click(btns.ok())
debug.click(debug.screen_buttons.ok())
debug.read_layout(wait=True)
if tag_version is None or tag_version > (2, 8, 8):
# layout changed after adding the cancel button
coords = btns.word_count_all_word(num_of_words)
coords = debug.screen_buttons.word_count_all_word(num_of_words)
else:
word_option_offset = 6
word_options = (12, 18, 20, 24, 33)
index = word_option_offset + word_options.index(
num_of_words
) # raises if num of words is invalid
coords = btns.grid34(index % 3, index // 3)
coords = debug.screen_buttons.grid34(index % 3, index // 3)
debug.click(coords)
debug.read_layout(wait=True)
def enter_share(debug: "DebugLink", share: str) -> "LayoutContent":
debug.click(buttons.ScreenButtons(debug.layout_type).ok())
debug.click(debug.screen_buttons.ok())
for word in share.split(" "):
_enter_word(debug, word, is_slip39=True)