diff --git a/src/apps/common/display_address.py b/src/apps/common/display_address.py index 531ad62881..8d8eb74ca8 100644 --- a/src/apps/common/display_address.py +++ b/src/apps/common/display_address.py @@ -10,10 +10,11 @@ from trezor.utils import chunks async def show_address(ctx, address: str): lines = split_address(address) - content = Text('Confirm address', ui.ICON_RECEIVE, ui.MONO, *lines, icon_color=ui.GREEN) + text = Text('Confirm address', ui.ICON_RECEIVE, icon_color=ui.GREEN) + text.mono(*lines) return await confirm( ctx, - content, + text, code=ButtonRequestType.Address, cancel='QR', cancel_style=ui.BTN_KEY) @@ -24,9 +25,9 @@ async def show_qr(ctx, address: str): qr_y = const(115) qr_coef = const(4) - content = Container( - Qr(address, (qr_x, qr_y), qr_coef), - Text('Confirm address', ui.ICON_RECEIVE, ui.MONO, icon_color=ui.GREEN)) + qr = Qr(address, (qr_x, qr_y), qr_coef) + text = Text('Confirm address', ui.ICON_RECEIVE, icon_color=ui.GREEN) + content = Container(qr, text) return await confirm( ctx, content, diff --git a/src/apps/common/request_passphrase.py b/src/apps/common/request_passphrase.py index d5518ebc0e..36e44a341a 100644 --- a/src/apps/common/request_passphrase.py +++ b/src/apps/common/request_passphrase.py @@ -13,9 +13,8 @@ from apps.common.cache import get_state @ui.layout async def request_passphrase_entry(ctx): - text = Text( - 'Enter passphrase', ui.ICON_CONFIG, - 'Where to enter your', 'passphrase?') + text = Text('Enter passphrase', ui.ICON_CONFIG) + text.type('Where to enter your', 'passphrase?') text.render() ack = await ctx.call( @@ -32,9 +31,8 @@ async def request_passphrase_entry(ctx): @ui.layout async def request_passphrase_ack(ctx, on_device): if not on_device: - text = Text( - 'Passphrase entry', ui.ICON_CONFIG, - 'Please, type passphrase', 'on connected host.') + text = Text('Passphrase entry', ui.ICON_CONFIG) + text.type('Please, type passphrase', 'on connected host.') text.render() req = PassphraseRequest(on_device=on_device) diff --git a/src/apps/ethereum/layout.py b/src/apps/ethereum/layout.py index 5bd429d9da..00854414f9 100644 --- a/src/apps/ethereum/layout.py +++ b/src/apps/ethereum/layout.py @@ -12,26 +12,25 @@ from apps.ethereum.get_address import _ethereum_address_hex async def require_confirm_tx(ctx, to, value, chain_id, token=None, tx_type=None): if to: - str_to = _ethereum_address_hex(to, networks.by_chain_id(chain_id)) + to_str = _ethereum_address_hex(to, networks.by_chain_id(chain_id)) else: - str_to = 'new contract?' - content = Text('Confirm sending', ui.ICON_SEND, - ui.BOLD, format_ethereum_amount(value, token, chain_id, tx_type), - ui.NORMAL, 'to', - ui.MONO, *split_address(str_to), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.SignTx) # we use SignTx, not ConfirmOutput, for compatibility with T1 + to_str = 'new contract?' + text = Text('Confirm sending', ui.ICON_SEND, icon_color=ui.GREEN) + text.bold(format_ethereum_amount(value, token, chain_id, tx_type)) + text.type('to') + text.mono(*split_address(to_str)) + # we use SignTx, not ConfirmOutput, for compatibility with T1 + await require_confirm(ctx, text, ButtonRequestType.SignTx) async def require_confirm_fee(ctx, spending, gas_price, gas_limit, chain_id, token=None, tx_type=None): - content = Text('Confirm transaction', ui.ICON_SEND, - ui.BOLD, format_ethereum_amount(spending, token, chain_id, tx_type), - ui.NORMAL, 'Gas price:', - ui.BOLD, format_ethereum_amount(gas_price, None, chain_id, tx_type), - ui.NORMAL, 'Maximum fee:', - ui.BOLD, format_ethereum_amount(gas_price * gas_limit, None, chain_id, tx_type), - icon_color=ui.GREEN) - await require_hold_to_confirm(ctx, content, ButtonRequestType.SignTx) + text = Text('Confirm transaction', ui.ICON_SEND, icon_color=ui.GREEN) + text.bold(format_ethereum_amount(spending, token, chain_id, tx_type)) + text.type('Gas price:') + text.bold(format_ethereum_amount(gas_price, None, chain_id, tx_type)) + text.type('Maximum fee:') + text.bold(format_ethereum_amount(gas_price * gas_limit, None, chain_id, tx_type)) + await require_hold_to_confirm(ctx, text, ButtonRequestType.SignTx) def split_data(data): @@ -39,14 +38,14 @@ def split_data(data): async def require_confirm_data(ctx, data, data_total): - str_data = hexlify(data[:36]).decode() + data_str = hexlify(data[:36]).decode() if data_total > 36: - str_data = str_data[:-2] + '..' - content = Text('Confirm data', ui.ICON_SEND, - ui.BOLD, 'Size: %d bytes' % data_total, - ui.MONO, *split_data(str_data), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.SignTx) # we use SignTx, not ConfirmOutput, for compatibility with T1 + data_str = data_str[:-2] + '..' + text = Text('Confirm data', ui.ICON_SEND, icon_color=ui.GREEN) + text.bold('Size: %d bytes' % data_total) + text.mono(*split_data(data_str)) + # we use SignTx, not ConfirmOutput, for compatibility with T1 + await require_confirm(ctx, text, ButtonRequestType.SignTx) def split_address(address): diff --git a/src/apps/ethereum/sign_message.py b/src/apps/ethereum/sign_message.py index 45076c0289..a7ae1b16d9 100644 --- a/src/apps/ethereum/sign_message.py +++ b/src/apps/ethereum/sign_message.py @@ -37,5 +37,6 @@ async def ethereum_sign_message(ctx, msg): async def require_confirm_sign_message(ctx, message): message = split_message(message) - content = Text('Sign ETH message', ui.ICON_DEFAULT, max_lines=5, *message) - await require_confirm(ctx, content) + text = Text('Sign ETH message', ui.ICON_DEFAULT) + text.type(*message) + await require_confirm(ctx, text) diff --git a/src/apps/ethereum/verify_message.py b/src/apps/ethereum/verify_message.py index 53b5458f16..63f337ed7c 100644 --- a/src/apps/ethereum/verify_message.py +++ b/src/apps/ethereum/verify_message.py @@ -32,10 +32,10 @@ async def ethereum_verify_message(ctx, msg): async def require_confirm_verify_message(ctx, address, message): - lines = split_address(address) - content = Text('Confirm address', ui.ICON_DEFAULT, ui.MONO, *lines) - await require_confirm(ctx, content) + text = Text('Confirm address', ui.ICON_DEFAULT) + text.mono(*split_address(address)) + await require_confirm(ctx, text) - message = split_message(message) - content = Text('Verify message', ui.ICON_DEFAULT, max_lines=5, *message) - await require_confirm(ctx, content) + text = Text('Verify message', ui.ICON_DEFAULT) + text.mono(*split_message(message)) + await require_confirm(ctx, text) diff --git a/src/apps/fido_u2f/__init__.py b/src/apps/fido_u2f/__init__.py index 158a9d80c4..13ca1fd71f 100644 --- a/src/apps/fido_u2f/__init__.py +++ b/src/apps/fido_u2f/__init__.py @@ -391,12 +391,8 @@ class ConfirmState: from trezor.ui.text import Text if bytes(self.app_id) == _BOGUS_APPID: - text = Text( - 'U2F mismatch', ui.ICON_WRONG, - 'Another U2F device', - 'was used to register', - 'in this application.', - icon_color=ui.RED) + text = Text('U2F mismatch', ui.ICON_WRONG, icon_color=ui.RED) + text.type('Another U2F device', 'was used to register', 'in this application.') text.render() await loop.sleep(3 * 1000 * 1000) self.confirmed = True diff --git a/src/apps/lisk/layout.py b/src/apps/lisk/layout.py index 7964674e19..4a50001aa3 100644 --- a/src/apps/lisk/layout.py +++ b/src/apps/lisk/layout.py @@ -9,28 +9,25 @@ from .helpers import get_vote_tx_text async def require_confirm_tx(ctx, to, value): - content = Text('Confirm sending', ui.ICON_SEND, - ui.BOLD, format_amount(value), - ui.NORMAL, 'to', - ui.MONO, *split_address(to), - icon_color=ui.GREEN) - return await require_confirm(ctx, content, ButtonRequestType.SignTx) + text = Text('Confirm sending', ui.ICON_SEND, icon_color=ui.GREEN) + text.bold(format_amount(value)) + text.type('to') + text.mono(*split_address(to)) + return await require_confirm(ctx, text, ButtonRequestType.SignTx) async def require_confirm_delegate_registration(ctx, delegate_name): - content = Text('Confirm transaction', ui.ICON_SEND, - 'Do you really want to', - 'register a delegate?', - ui.BOLD, *chunks(delegate_name, 20), - icon_color=ui.GREEN) - return await require_confirm(ctx, content, ButtonRequestType.SignTx) + text = Text('Confirm transaction', ui.ICON_SEND, icon_color=ui.GREEN) + text.type('Do you really want to') + text.type('register a delegate?') + text.bold(*chunks(delegate_name, 20)) + return await require_confirm(ctx, text, ButtonRequestType.SignTx) async def require_confirm_vote_tx(ctx, votes): - content = Text('Confirm transaction', ui.ICON_SEND, - *get_vote_tx_text(votes), - icon_color=ui.GREEN) - return await require_confirm(ctx, content, ButtonRequestType.SignTx) + text = Text('Confirm transaction', ui.ICON_SEND, icon_color=ui.GREEN) + text.type(*get_vote_tx_text(votes)) + return await require_confirm(ctx, text, ButtonRequestType.SignTx) async def require_confirm_public_key(ctx, public_key): @@ -38,21 +35,19 @@ async def require_confirm_public_key(ctx, public_key): async def require_confirm_multisig(ctx, multisignature): - content = Text('Confirm transaction', ui.ICON_SEND, - ('Keys group length: %s' % len(multisignature.keys_group)), - ('Life time: %s' % multisignature.life_time), - ('Min: %s' % multisignature.min), - icon_color=ui.GREEN) - return await require_confirm(ctx, content, ButtonRequestType.SignTx) + text = Text('Confirm transaction', ui.ICON_SEND, icon_color=ui.GREEN) + text.type('Keys group length: %s' % len(multisignature.keys_group)) + text.type('Life time: %s' % multisignature.life_time) + text.type('Min: %s' % multisignature.min) + return await require_confirm(ctx, text, ButtonRequestType.SignTx) async def require_confirm_fee(ctx, value, fee): - content = Text('Confirm transaction', ui.ICON_SEND, - ui.BOLD, format_amount(value), - ui.NORMAL, 'fee:', - ui.BOLD, format_amount(fee), - icon_color=ui.GREEN) - await require_hold_to_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text('Confirm transaction', ui.ICON_SEND, icon_color=ui.GREEN) + text.bold(format_amount(value)) + text.type('fee:') + text.bold(format_amount(fee)) + await require_hold_to_confirm(ctx, text, ButtonRequestType.ConfirmOutput) def format_amount(value): diff --git a/src/apps/lisk/sign_message.py b/src/apps/lisk/sign_message.py index 65dfaf29cc..4dfa143616 100644 --- a/src/apps/lisk/sign_message.py +++ b/src/apps/lisk/sign_message.py @@ -39,6 +39,6 @@ async def lisk_sign_message(ctx, msg): async def require_confirm_sign_message(ctx, message): - message = split_message(message) - content = Text('Sign Lisk message', ui.ICON_DEFAULT, max_lines=5, *message) - await require_confirm(ctx, content) + text = Text('Sign Lisk message', ui.ICON_DEFAULT) + text.type(*split_message(message)) + await require_confirm(ctx, text) diff --git a/src/apps/management/apply_settings.py b/src/apps/management/apply_settings.py index bc42099fd9..a144d4fb0f 100644 --- a/src/apps/management/apply_settings.py +++ b/src/apps/management/apply_settings.py @@ -13,40 +13,16 @@ async def apply_settings(ctx, msg): if msg.homescreen is not None: if len(msg.homescreen) > storage.HOMESCREEN_MAXSIZE: raise wire.DataError('Homescreen is too complex') - await require_confirm(ctx, Text( - 'Change homescreen', ui.ICON_CONFIG, - 'Do you really want to', 'change homescreen?'), - code=ButtonRequestType.ProtectCall) + await require_confirm_change_homescreen(ctx) - # TODO: split label (bold) and '?' (normal) once we support mixed styles on one line if msg.label is not None: - await require_confirm(ctx, Text( - 'Change label', ui.ICON_CONFIG, - 'Do you really want to', 'change label to', - ui.BOLD, '%s?' % msg.label), - code=ButtonRequestType.ProtectCall) + await require_confirm_change_label(ctx, msg.label) if msg.use_passphrase is not None: - await require_confirm(ctx, Text( - 'Enable passphrase' if msg.use_passphrase else 'Disable passphrase', - ui.ICON_CONFIG, - 'Do you really want to', - 'enable passphrase' if msg.use_passphrase else 'disable passphrase', - 'encryption?'), - code=ButtonRequestType.ProtectCall) + await require_confirm_change_passphrase(ctx, msg.use_passphrase) if msg.passphrase_source is not None: - if msg.passphrase_source == PassphraseSourceType.DEVICE: - desc = 'ON DEVICE' - elif msg.passphrase_source == PassphraseSourceType.HOST: - desc = 'ON HOST' - else: - desc = 'ASK' - await require_confirm(ctx, Text( - 'Passphrase source', ui.ICON_CONFIG, - 'Do you really want to', 'change the passphrase', 'source to', - ui.BOLD, 'ALWAYS %s?' % desc), - code=ButtonRequestType.ProtectCall) + await require_confirm_change_passphrase_source(ctx, msg.passphrase_source) storage.load_settings(label=msg.label, use_passphrase=msg.use_passphrase, @@ -54,3 +30,37 @@ async def apply_settings(ctx, msg): passphrase_source=msg.passphrase_source) return Success(message='Settings applied') + + +async def require_confirm_change_homescreen(ctx): + text = Text('Change homescreen', ui.ICON_CONFIG) + text.type('Do you really want to', 'change homescreen?') + await require_confirm(ctx, text, code=ButtonRequestType.ProtectCall) + + +async def require_confirm_change_label(ctx, label): + text = Text('Change label', ui.ICON_CONFIG) + text.type('Do you really want to', 'change label to') + text.bold('%s?' % label) + await require_confirm(ctx, text, code=ButtonRequestType.ProtectCall) + + +async def require_confirm_change_passphrase(ctx, use): + text = Text('Enable passphrase' if use else 'Disable passphrase', ui.ICON_CONFIG) + text.type('Do you really want to') + text.type('enable passphrase' if use else 'disable passphrase') + text.type('encryption?') + await require_confirm(ctx, text, code=ButtonRequestType.ProtectCall) + + +async def require_confirm_change_passphrase_source(ctx, source): + if source == PassphraseSourceType.DEVICE: + desc = 'ON DEVICE' + elif source == PassphraseSourceType.HOST: + desc = 'ON HOST' + else: + desc = 'ASK' + text = Text('Passphrase source', ui.ICON_CONFIG) + text.type('Do you really want to', 'change the passphrase', 'source to') + text.bold('ALWAYS %s?' % desc) + await require_confirm(ctx, text, code=ButtonRequestType.ProtectCall) diff --git a/src/apps/management/change_pin.py b/src/apps/management/change_pin.py index a46e2963c2..505f253a83 100644 --- a/src/apps/management/change_pin.py +++ b/src/apps/management/change_pin.py @@ -42,22 +42,22 @@ def require_confirm_change_pin(ctx, msg): has_pin = config.has_pin() if msg.remove and has_pin: # removing pin - return require_confirm(ctx, Text( - 'Remove PIN', ui.ICON_CONFIG, - 'Do you really want to', ui.BOLD, - 'remove current PIN?')) + text = Text('Remove PIN', ui.ICON_CONFIG) + text.type('Do you really want to') + text.bold('remove current PIN?') + return require_confirm(ctx, text) if not msg.remove and has_pin: # changing pin - return require_confirm(ctx, Text( - 'Change PIN', ui.ICON_CONFIG, - 'Do you really want to', ui.BOLD, - 'change current PIN?')) + text = Text('Remove PIN', ui.ICON_CONFIG) + text.type('Do you really want to') + text.bold('change current PIN?') + return require_confirm(ctx, text) if not msg.remove and not has_pin: # setting new pin - return require_confirm(ctx, Text( - 'Change PIN', ui.ICON_CONFIG, - 'Do you really want to', ui.BOLD, - 'set new PIN?')) + text = Text('Remove PIN', ui.ICON_CONFIG) + text.type('Do you really want to') + text.bold('set new PIN?') + return require_confirm(ctx, text) async def request_pin_confirm(ctx, *args, **kwargs): @@ -79,11 +79,9 @@ async def request_pin_ack(ctx, *args, **kwargs): @ui.layout async def pin_mismatch(): - text = Text( - 'PIN mismatch', ui.ICON_WRONG, - 'Entered PINs do not', - 'match each other.', - '', - 'Please, try again...', icon_color=ui.RED) + text = Text('PIN mismatch', ui.ICON_WRONG, icon_color=ui.RED) + text.type('Entered PINs do not', 'match each other.') + text.type('') + text.type('Please, try again...') text.render() await loop.sleep(3 * 1000 * 1000) diff --git a/src/apps/management/load_device.py b/src/apps/management/load_device.py index cd2aa461dd..1eb609da0a 100644 --- a/src/apps/management/load_device.py +++ b/src/apps/management/load_device.py @@ -18,10 +18,10 @@ async def load_device(ctx, msg): if not msg.skip_checksum and not bip39.check(msg.mnemonic): raise wire.ProcessError('Mnemonic is not valid') - await require_confirm(ctx, Text( - 'Loading seed', ui.ICON_DEFAULT, - ui.BOLD, 'Loading private seed', 'is not recommended.', - ui.NORMAL, 'Continue only if you', 'know what you are doing!')) + text = Text('Loading seed', ui.ICON_DEFAULT) + text.bold('Loading private seed', 'is not recommended.') + text.type('Continue only if you', 'know what you are doing!') + await require_confirm(ctx, text) storage.load_mnemonic( mnemonic=msg.mnemonic, needs_backup=True) diff --git a/src/apps/management/recovery_device.py b/src/apps/management/recovery_device.py index 45269340a6..98a7adb1ce 100644 --- a/src/apps/management/recovery_device.py +++ b/src/apps/management/recovery_device.py @@ -61,9 +61,9 @@ async def recovery_device(ctx, msg): async def request_wordcount(ctx): await ctx.call(ButtonRequest(code=MnemonicWordCount), ButtonAck) - content = Text('Device recovery', ui.ICON_RECOVERY, 'Number of words?') - select = WordSelector(content) - count = await ctx.wait(select) + text = Text('Device recovery', ui.ICON_RECOVERY) + text.type('Number of words?') + count = await ctx.wait(WordSelector(text)) return count diff --git a/src/apps/management/reset_device.py b/src/apps/management/reset_device.py index a3d6906f17..30c10e6182 100644 --- a/src/apps/management/reset_device.py +++ b/src/apps/management/reset_device.py @@ -88,56 +88,57 @@ def generate_mnemonic(strength: int, async def show_warning(ctx): - content = Text( - 'Backup your seed', ui.ICON_NOCOPY, + text = Text('Backup your seed', ui.ICON_NOCOPY) + text.type( 'Never make a digital', 'copy of your recovery', 'seed and never upload', 'it online!') await require_confirm( ctx, - content, + text, ButtonRequestType.ResetDevice, confirm='I understand', cancel=None) async def show_wrong_entry(ctx): - content = Text( - 'Wrong entry!', ui.ICON_WRONG, + text = Text('Wrong entry!', ui.ICON_WRONG, icon_color=ui.RED) + text.type( 'You have entered', 'wrong seed word.', - 'Please check again.', icon_color=ui.RED) + 'Please check again.') await require_confirm( ctx, - content, + text, ButtonRequestType.ResetDevice, confirm='Check again', cancel=None) async def show_success(ctx): - content = Text( - 'Backup is done!', ui.ICON_CONFIRM, + text = Text('Backup is done!', ui.ICON_CONFIRM, icon_color=ui.GREEN) + text.type( 'Never make a digital', 'copy of your recovery', 'seed and never upload', - 'it online!', icon_color=ui.GREEN) + 'it online!') await require_confirm( ctx, - content, + text, ButtonRequestType.ResetDevice, confirm='Finish setup', cancel=None) async def show_entropy(ctx, entropy: bytes): - estr = hexlify(entropy).decode() - lines = chunks(estr, 16) - content = Text('Internal entropy', ui.ICON_RESET, ui.MONO, *lines) + entropy_str = hexlify(entropy).decode() + lines = chunks(entropy_str, 16) + text = Text('Internal entropy', ui.ICON_RESET) + text.mono(*lines) await require_confirm( ctx, - content, + text, ButtonRequestType.ResetDevice) @@ -158,8 +159,9 @@ async def show_mnemonic_page(page: int, page_count: int, pages: list): debug.reset_current_words = [word for _, word in pages[page]] lines = ['%2d. %s' % (wi + 1, word) for wi, word in pages[page]] - content = Text('Recovery seed', ui.ICON_RESET, ui.MONO, *lines) - content = Scrollpage(content, page, page_count) + text = Text('Recovery seed', ui.ICON_RESET) + text.mono(*lines) + content = Scrollpage(text, page, page_count) if page + 1 == page_count: await HoldToConfirmDialog(content) diff --git a/src/apps/management/set_u2f_counter.py b/src/apps/management/set_u2f_counter.py index 343f48374d..6815f275ea 100644 --- a/src/apps/management/set_u2f_counter.py +++ b/src/apps/management/set_u2f_counter.py @@ -10,12 +10,10 @@ async def set_u2f_counter(ctx, msg): if msg.u2f_counter is None: raise wire.ProcessError('No value provided') - await require_confirm(ctx, Text( - 'Set U2F counter', ui.ICON_CONFIG, - 'Do you really want to', - 'set the U2F counter', - ui.BOLD, 'to %d?' % msg.u2f_counter), - code=ButtonRequestType.ProtectCall) + text = Text('Set U2F counter', ui.ICON_CONFIG) + text.type('Do you really want to', 'set the U2F counter') + text.bold('to %d?' % msg.u2f_counter) + await require_confirm(ctx, text, code=ButtonRequestType.ProtectCall) storage.set_u2f_counter(msg.u2f_counter) diff --git a/src/apps/management/wipe_device.py b/src/apps/management/wipe_device.py index 9fbc88d6a7..56e1efdf86 100644 --- a/src/apps/management/wipe_device.py +++ b/src/apps/management/wipe_device.py @@ -8,12 +8,11 @@ from apps.common.confirm import require_hold_to_confirm async def wipe_device(ctx, msg): - await require_hold_to_confirm(ctx, Text( - 'Wipe device', - ui.ICON_WIPE, - ui.NORMAL, 'Do you really want to', 'wipe the device?', - ui.NORMAL, '', 'All data will be lost.', - icon_color=ui.RED), + text = Text('Wipe device', ui.ICON_WIPE, icon_color=ui.RED) + text.type('Do you really want to', 'wipe the device?', '') + text.bold('All data will be lost.') + + await require_hold_to_confirm(ctx, text, code=ButtonRequestType.WipeDevice, button_style=ui.BTN_CANCEL, loader_style=ui.LDR_DANGER) diff --git a/src/apps/nem/get_address.py b/src/apps/nem/get_address.py index fd53b3e11e..94151ce0e2 100644 --- a/src/apps/nem/get_address.py +++ b/src/apps/nem/get_address.py @@ -30,9 +30,7 @@ async def get_address(ctx, msg): async def _show_address(ctx, address: str, network: int): lines = split_address(address) - content = Text( - 'Confirm address', ui.ICON_RECEIVE, - ui.NORMAL, '%s network' % get_network_str(network), - ui.MONO, *lines, - icon_color=ui.GREEN) - return await confirm(ctx, content, code=ButtonRequestType.Address, cancel='QR', cancel_style=ui.BTN_KEY) + text = Text('Confirm address', ui.ICON_RECEIVE, icon_color=ui.GREEN) + text.type('%s network' % get_network_str(network)) + text.mono(*lines) + return await confirm(ctx, text, code=ButtonRequestType.Address, cancel='QR', cancel_style=ui.BTN_KEY) diff --git a/src/apps/nem/layout.py b/src/apps/nem/layout.py index ce9a64a860..918f81f242 100644 --- a/src/apps/nem/layout.py +++ b/src/apps/nem/layout.py @@ -22,19 +22,18 @@ async def require_confirm_fee(ctx, action: str, fee: int): async def require_confirm_content(ctx, headline: str, content: list): - text = Text(headline, ui.ICON_SEND, *content, icon_color=ui.GREEN) + text = Text(headline, ui.ICON_SEND, icon_color=ui.GREEN) + text.type(*content) await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def require_confirm_final(ctx, fee: int): - content = Text( - 'Final confirm', ui.ICON_SEND, - ui.NORMAL, 'Sign this transaction', - ui.BOLD, 'and pay %s XEM' % format_amount(fee, NEM_MAX_DIVISIBILITY), - ui.NORMAL, 'for network fee?', - icon_color=ui.GREEN) + text = Text('Final confirm', ui.ICON_SEND, icon_color=ui.GREEN) + text.type('Sign this transaction') + text.bold('and pay %s XEM' % format_amount(fee, NEM_MAX_DIVISIBILITY)) + text.type('for network fee?') # we use SignTx, not ConfirmOutput, for compatibility with T1 - await require_hold_to_confirm(ctx, content, ButtonRequestType.SignTx) + await require_hold_to_confirm(ctx, text, ButtonRequestType.SignTx) def split_address(address: str): diff --git a/src/apps/nem/mosaic/layout.py b/src/apps/nem/mosaic/layout.py index 2670dcdcb4..640912d8cb 100644 --- a/src/apps/nem/mosaic/layout.py +++ b/src/apps/nem/mosaic/layout.py @@ -67,57 +67,68 @@ async def _show_page(page: int, page_count: int, content): def _get_mosaic_properties(definition: NEMMosaicDefinition): properties = [] + + # description if definition.description: - t = Text('Confirm properties', ui.ICON_SEND, - ui.BOLD, 'Description:', - ui.NORMAL, *split_words(trim(definition.description, 70), 22)) + t = Text('Confirm properties', ui.ICON_SEND) + t.bold('Description:') + t.type(*split_words(trim(definition.description, 70), 22)) properties.append(t) + + # transferable if definition.transferable: transferable = 'Yes' else: transferable = 'No' - t = Text('Confirm properties', ui.ICON_SEND, - ui.BOLD, 'Transferable?', - ui.NORMAL, transferable) + t = Text('Confirm properties', ui.ICON_SEND) + t.bold('Transferable?') + t.type(transferable) properties.append(t) + + # mutable_supply if definition.mutable_supply: imm = 'mutable' else: imm = 'immutable' if definition.supply: - t = Text('Confirm properties', ui.ICON_SEND, - ui.BOLD, 'Initial supply:', - ui.NORMAL, str(definition.supply), - ui.NORMAL, imm) + t = Text('Confirm properties', ui.ICON_SEND) + t.bold('Initial supply:') + t.type(str(definition.supply), imm) else: - t = Text('Confirm properties', ui.ICON_SEND, - ui.BOLD, 'Initial supply:', - ui.NORMAL, imm) + t = Text('Confirm properties', ui.ICON_SEND) + t.bold('Initial supply:') + t.type(imm) properties.append(t) + + # levy if definition.levy: - t = Text('Confirm properties', ui.ICON_SEND, - ui.BOLD, 'Levy recipient:', - ui.MONO, *split_address(definition.levy_address)) + + t = Text('Confirm properties', ui.ICON_SEND) + t.bold('Levy recipient:') + t.mono(*split_address(definition.levy_address)) properties.append(t) - t = Text('Confirm properties', ui.ICON_SEND, - ui.BOLD, 'Levy fee:', - ui.NORMAL, str(definition.fee), - ui.BOLD, 'Levy divisibility:', - ui.NORMAL, str(definition.divisibility)) + + t = Text('Confirm properties', ui.ICON_SEND) + t.bold('Levy fee:') + t.type(str(definition.fee)) + t.bold('Levy divisibility:') + t.type(str(definition.divisibility)) properties.append(t) - t = Text('Confirm properties', ui.ICON_SEND, - ui.BOLD, 'Levy namespace:', - ui.NORMAL, definition.levy_namespace, - ui.BOLD, 'Levy mosaic:', - ui.NORMAL, definition.levy_mosaic) + + t = Text('Confirm properties', ui.ICON_SEND) + t.bold('Levy namespace:') + t.type(definition.levy_namespace) + t.bold('Levy mosaic:') + t.type(definition.levy_mosaic) properties.append(t) + if definition.levy == NEMMosaicLevy.MosaicLevy_Absolute: levy_type = 'absolute' else: levy_type = 'percentile' - t = Text('Confirm properties', ui.ICON_SEND, - ui.BOLD, 'Levy type:', - ui.NORMAL, levy_type) + t = Text('Confirm properties', ui.ICON_SEND) + t.bold('Levy type:') + t.type(levy_type) properties.append(t) return properties diff --git a/src/apps/nem/multisig/layout.py b/src/apps/nem/multisig/layout.py index ff800dde04..00bbfcf7a5 100644 --- a/src/apps/nem/multisig/layout.py +++ b/src/apps/nem/multisig/layout.py @@ -42,8 +42,7 @@ async def ask_aggregate_modification(ctx, common: NEMTransactionCommon, mod: NEM async def _require_confirm_address(ctx, action: str, address: str): - content = Text('Confirm address', ui.ICON_SEND, - ui.NORMAL, action, - ui.MONO, *split_address(address), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text('Confirm address', ui.ICON_SEND, icon_color=ui.GREEN) + text.type(action) + text.mono(*split_address(address)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) diff --git a/src/apps/nem/transfer/layout.py b/src/apps/nem/transfer/layout.py index 5d459c1db6..ff2c268b56 100644 --- a/src/apps/nem/transfer/layout.py +++ b/src/apps/nem/transfer/layout.py @@ -30,38 +30,31 @@ async def ask_transfer_mosaic(ctx, common: NEMTransactionCommon, transfer: NEMTr mosaic_quantity = mosaic.quantity * transfer.amount / NEM_MOSAIC_AMOUNT_DIVISOR if definition: - msg = Text('Confirm mosaic', ui.ICON_SEND, - 'Confirm transfer of', - ui.BOLD, format_amount(mosaic_quantity, definition['divisibility']) + definition['ticker'], - ui.NORMAL, 'of', - ui.BOLD, definition['name'], - icon_color=ui.GREEN) - + msg = Text('Confirm mosaic', ui.ICON_SEND, icon_color=ui.GREEN) + msg.type('Confirm transfer of') + msg.bold(format_amount(mosaic_quantity, definition['divisibility']) + definition['ticker']) + msg.type('of') + msg.bold(definition['name']) await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput) if 'levy' in definition and 'fee' in definition: levy_msg = _get_levy_msg(definition, mosaic_quantity, common.network) - msg = Text('Confirm mosaic', ui.ICON_SEND, - 'Confirm mosaic', - 'levy fee of', - ui.BOLD, levy_msg, - icon_color=ui.GREEN) - + msg = Text('Confirm mosaic', ui.ICON_SEND, icon_color=ui.GREEN) + msg.type('Confirm mosaic', 'levy fee of') + msg.bold(levy_msg) await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput) else: - msg = Text('Confirm mosaic', ui.ICON_SEND, - ui.BOLD, 'Unknown mosaic!', - ui.NORMAL, *split_words('Divisibility and levy cannot be shown for unknown mosaics', 22), - icon_color=ui.RED) + msg = Text('Confirm mosaic', ui.ICON_SEND, icon_color=ui.RED) + msg.bold('Unknown mosaic!') + msg.type(*split_words('Divisibility and levy cannot be shown for unknown mosaics', 22)) await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput) - msg = Text('Confirm mosaic', ui.ICON_SEND, - ui.NORMAL, 'Confirm transfer of', - ui.BOLD, '%s raw units' % mosaic_quantity, - ui.NORMAL, 'of', - ui.BOLD, '%s.%s' % (mosaic.namespace, mosaic.mosaic), - icon_color=ui.GREEN) + msg = Text('Confirm mosaic', ui.ICON_SEND, icon_color=ui.GREEN) + msg.type('Confirm transfer of') + msg.bold('%s raw units' % mosaic_quantity) + msg.type('of') + msg.bold('%s.%s' % (mosaic.namespace, mosaic.mosaic)) await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput) @@ -102,12 +95,11 @@ async def ask_importance_transfer(ctx, common: NEMTransactionCommon, imp: NEMImp async def _require_confirm_transfer(ctx, recipient, value): - content = Text('Confirm transfer', ui.ICON_SEND, - ui.BOLD, 'Send %s XEM' % format_amount(value, NEM_MAX_DIVISIBILITY), - ui.NORMAL, 'to', - ui.MONO, *split_address(recipient), - icon_color=ui.GREEN) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text('Confirm transfer', ui.ICON_SEND, icon_color=ui.GREEN) + text.bold('Send %s XEM' % format_amount(value, NEM_MAX_DIVISIBILITY)) + text.type('to') + text.mono(*split_address(recipient)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def _require_confirm_payload(ctx, payload: bytes, encrypt=False): @@ -116,13 +108,11 @@ async def _require_confirm_payload(ctx, payload: bytes, encrypt=False): if len(payload) > 48: payload = payload[:48] + '..' if encrypt: - content = Text('Confirm payload', ui.ICON_SEND, - ui.BOLD, 'Encrypted:', - ui.NORMAL, *split_words(payload, 22), - icon_color=ui.GREEN) + text = Text('Confirm payload', ui.ICON_SEND, icon_color=ui.GREEN) + text.bold('Encrypted:') + text.type(*split_words(payload, 22)) else: - content = Text('Confirm payload', ui.ICON_SEND, - ui.BOLD, 'Unencrypted:', - ui.NORMAL, *split_words(payload, 22), - icon_color=ui.RED) - await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text('Confirm payload', ui.ICON_SEND, icon_color=ui.RED) + text.bold('Unencrypted:') + text.type(*split_words(payload, 22)) + await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) diff --git a/src/apps/wallet/cipher_key_value.py b/src/apps/wallet/cipher_key_value.py index 82adc13ba8..9cc8fcfab4 100644 --- a/src/apps/wallet/cipher_key_value.py +++ b/src/apps/wallet/cipher_key_value.py @@ -20,8 +20,9 @@ async def cipher_key_value(ctx, msg): title = 'Encrypt value' else: title = 'Decrypt value' - lines = split_words(msg.key, ui.WIDTH - 2 * TEXT_MARGIN_LEFT, metric=lambda x: ui.display.text_width(x, ui.NORMAL)) - await require_confirm(ctx, Text(title, ui.ICON_DEFAULT, max_lines=5, *lines)) + text = Text(title, ui.ICON_DEFAULT) + text.type(msg.key) + await require_confirm(ctx, text) node = await seed.derive_node(ctx, msg.address_n) value = compute_cipher_key_value(msg, node.private_key()) diff --git a/src/apps/wallet/ecdh.py b/src/apps/wallet/ecdh.py index c40f3c2387..1d8ffb1885 100644 --- a/src/apps/wallet/ecdh.py +++ b/src/apps/wallet/ecdh.py @@ -30,9 +30,9 @@ async def get_ecdh_session_key(ctx, msg): async def require_confirm_ecdh_session_key(ctx, identity): lines = chunks(serialize_identity_without_proto(identity), 18) proto = identity.proto.upper() if identity.proto else 'identity' - header = 'Decrypt %s' % (proto,) - content = Text(header, ui.ICON_DEFAULT, ui.MONO, *lines, max_lines=5) - await require_confirm(ctx, content) + text = Text('Decrypt %s' % proto, ui.ICON_DEFAULT) + text.mono(*lines) + await require_confirm(ctx, text) def get_ecdh_path(identity: str, index: int): diff --git a/src/apps/wallet/get_entropy.py b/src/apps/wallet/get_entropy.py index c726473bf2..a406219208 100644 --- a/src/apps/wallet/get_entropy.py +++ b/src/apps/wallet/get_entropy.py @@ -8,11 +8,10 @@ from apps.common.confirm import require_confirm async def get_entropy(ctx, msg): - await require_confirm(ctx, Text( - 'Confirm entropy', ui.ICON_DEFAULT, - ui.BOLD, 'Do you really want', 'to send entropy?', - ui.NORMAL, 'Continue only if you', 'know what you are doing!'), - code=ButtonRequestType.ProtectCall) + text = Text('Confirm entropy', ui.ICON_DEFAULT) + text.bold('Do you really want', 'to send entropy?') + text.type('Continue only if you', 'know what you are doing!') + await require_confirm(ctx, text, code=ButtonRequestType.ProtectCall) size = min(msg.size, 1024) entropy = random.bytes(size) diff --git a/src/apps/wallet/get_public_key.py b/src/apps/wallet/get_public_key.py index 1c2fd79637..eb49b8b398 100644 --- a/src/apps/wallet/get_public_key.py +++ b/src/apps/wallet/get_public_key.py @@ -38,8 +38,9 @@ async def get_public_key(ctx, msg): async def _show_pubkey(ctx, pubkey: bytes): lines = chunks(hexlify(pubkey).decode(), 18) - content = Text('Confirm public key', ui.ICON_RECEIVE, ui.MONO, *lines, icon_color=ui.GREEN) + text = Text('Confirm public key', ui.ICON_RECEIVE, icon_color=ui.GREEN) + text.mono(*lines) return await require_confirm( ctx, - content, + text, code=ButtonRequestType.PublicKey) diff --git a/src/apps/wallet/sign_identity.py b/src/apps/wallet/sign_identity.py index 7d2b238aa2..31bfde0ba4 100644 --- a/src/apps/wallet/sign_identity.py +++ b/src/apps/wallet/sign_identity.py @@ -53,9 +53,9 @@ async def require_confirm_sign_identity(ctx, identity, challenge_visual): lines.extend(chunks(serialize_identity_without_proto(identity), 18)) proto = identity.proto.upper() if identity.proto else 'identity' - header = 'Sign %s' % proto - content = Text(header, ui.ICON_DEFAULT, *lines, max_lines=5) - await require_confirm(ctx, content) + text = Text('Sign %s' % proto, ui.ICON_DEFAULT) + text.type(*lines) + await require_confirm(ctx, text) def serialize_identity(identity): diff --git a/src/apps/wallet/sign_message.py b/src/apps/wallet/sign_message.py index dc6b0b696f..2f49a42441 100644 --- a/src/apps/wallet/sign_message.py +++ b/src/apps/wallet/sign_message.py @@ -39,5 +39,6 @@ async def sign_message(ctx, msg): async def require_confirm_sign_message(ctx, message): message = split_message(message) - content = Text('Sign message', ui.ICON_DEFAULT, max_lines=5, *message) - await require_confirm(ctx, content) + text = Text('Sign message', ui.ICON_DEFAULT) + text.type(*message) + await require_confirm(ctx, text) diff --git a/src/apps/wallet/sign_tx/layout.py b/src/apps/wallet/sign_tx/layout.py index d8824a2334..14e8353133 100644 --- a/src/apps/wallet/sign_tx/layout.py +++ b/src/apps/wallet/sign_tx/layout.py @@ -26,40 +26,38 @@ async def confirm_output(ctx, output, coin): data = hexlify(output.op_return_data).decode() if len(data) >= 18 * 5: data = data[:(18 * 5 - 3)] + '...' - content = Text('OP_RETURN', ui.ICON_SEND, - ui.MONO, *split_op_return(data), icon_color=ui.GREEN) + text = Text('OP_RETURN', ui.ICON_SEND, icon_color=ui.GREEN) + text.mono(*split_op_return(data)) else: address = output.address address_short = addresses.address_short(coin, address) - content = Text('Confirm sending', ui.ICON_SEND, - ui.NORMAL, format_coin_amount(output.amount, coin) + ' to', - ui.MONO, *split_address(address_short), icon_color=ui.GREEN) - return await confirm(ctx, content, ButtonRequestType.ConfirmOutput) + text = Text('Confirm sending', ui.ICON_SEND, icon_color=ui.GREEN) + text.type(format_coin_amount(output.amount, coin) + ' to') + text.mono(*split_address(address_short)) + return await confirm(ctx, text, ButtonRequestType.ConfirmOutput) async def confirm_total(ctx, spending, fee, coin): - content = Text('Confirm transaction', ui.ICON_SEND, - 'Total amount:', - ui.BOLD, format_coin_amount(spending, coin), - ui.NORMAL, 'including fee:', - ui.BOLD, format_coin_amount(fee, coin), icon_color=ui.GREEN) - return await hold_to_confirm(ctx, content, ButtonRequestType.SignTx) + text = Text('Confirm transaction', ui.ICON_SEND, icon_color=ui.GREEN) + text.type('Total amount:') + text.bold(format_coin_amount(spending, coin)) + text.type('including fee:') + text.bold(format_coin_amount(fee, coin)) + return await hold_to_confirm(ctx, text, ButtonRequestType.SignTx) async def confirm_feeoverthreshold(ctx, fee, coin): - content = Text('High fee', ui.ICON_SEND, - 'The fee of', - ui.BOLD, format_coin_amount(fee, coin), - ui.NORMAL, 'is unexpectedly high.', - 'Continue?', icon_color=ui.GREEN) - - return await confirm(ctx, content, ButtonRequestType.FeeOverThreshold) + text = Text('High fee', ui.ICON_SEND, icon_color=ui.GREEN) + text.type('The fee of') + text.bold(format_coin_amount(fee, coin)) + text.type('is unexpectedly high.', 'Continue?') + return await confirm(ctx, text, ButtonRequestType.FeeOverThreshold) async def confirm_foreign_address(ctx, address_n, coin): - content = Text('Confirm sending', ui.ICON_SEND, - 'Trying to spend', - 'coins from another chain.', - 'Continue?', icon_color=ui.RED) - - return await confirm(ctx, content, ButtonRequestType.SignTx) + text = Text('Confirm sending', ui.ICON_SEND, icon_color=ui.RED) + text.type( + 'Trying to spend', + 'coins from another chain.', + 'Continue?') + return await confirm(ctx, text, ButtonRequestType.SignTx) diff --git a/src/apps/wallet/verify_message.py b/src/apps/wallet/verify_message.py index cd5ea10cf6..016225c9dd 100644 --- a/src/apps/wallet/verify_message.py +++ b/src/apps/wallet/verify_message.py @@ -57,10 +57,10 @@ async def verify_message(ctx, msg): async def require_confirm_verify_message(ctx, address, message): - lines = split_address(address) - content = Text('Confirm address', ui.ICON_DEFAULT, ui.MONO, *lines) - await require_confirm(ctx, content) + text = Text('Confirm address', ui.ICON_DEFAULT) + text.mono(*split_address(address)) + await require_confirm(ctx, text) - message = split_message(message) - content = Text('Verify message', ui.ICON_DEFAULT, max_lines=5, *message) - await require_confirm(ctx, content) + text = Text('Verify message', ui.ICON_DEFAULT) + text.type(*split_message(message)) + await require_confirm(ctx, text)