mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-05 20:31:01 +00:00
refactor(core): convert apps.cardano to layouts
This commit is contained in:
parent
ffb400180d
commit
ddac852acf
@ -1,8 +1,9 @@
|
|||||||
from trezor import log, wire
|
from trezor import log, wire
|
||||||
from trezor.messages import CardanoAddress
|
from trezor.messages import CardanoAddress
|
||||||
|
from trezor.ui.layouts import show_address
|
||||||
|
|
||||||
from apps.common import paths
|
from apps.common import paths
|
||||||
from apps.common.layout import address_n_to_str, show_qr
|
from apps.common.layout import address_n_to_str
|
||||||
|
|
||||||
from . import seed
|
from . import seed
|
||||||
from .address import derive_human_readable_address, validate_address_parameters
|
from .address import derive_human_readable_address, validate_address_parameters
|
||||||
@ -10,7 +11,7 @@ from .helpers import protocol_magics, staking_use_cases
|
|||||||
from .helpers.paths import SCHEMA_ADDRESS
|
from .helpers.paths import SCHEMA_ADDRESS
|
||||||
from .helpers.utils import to_account_path
|
from .helpers.utils import to_account_path
|
||||||
from .layout import (
|
from .layout import (
|
||||||
show_address,
|
ADDRESS_TYPE_NAMES,
|
||||||
show_warning_address_foreign_staking_key,
|
show_warning_address_foreign_staking_key,
|
||||||
show_warning_address_pointer,
|
show_warning_address_pointer,
|
||||||
)
|
)
|
||||||
@ -70,19 +71,15 @@ async def _display_address(
|
|||||||
if not protocol_magics.is_mainnet(protocol_magic):
|
if not protocol_magics.is_mainnet(protocol_magic):
|
||||||
network_name = protocol_magics.to_ui_string(protocol_magic)
|
network_name = protocol_magics.to_ui_string(protocol_magic)
|
||||||
|
|
||||||
while True:
|
address_n = address_n_to_str(address_parameters.address_n)
|
||||||
if await show_address(
|
await show_address(
|
||||||
ctx,
|
ctx,
|
||||||
address,
|
address=address,
|
||||||
address_parameters.address_type,
|
title="%s address" % ADDRESS_TYPE_NAMES[address_parameters.address_type],
|
||||||
address_parameters.address_n,
|
network=network_name,
|
||||||
network=network_name,
|
address_extra=address_n,
|
||||||
):
|
title_qr=address_n,
|
||||||
break
|
)
|
||||||
if await show_qr(
|
|
||||||
ctx, address, desc=address_n_to_str(address_parameters.address_n)
|
|
||||||
):
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
async def _show_staking_warnings(
|
async def _show_staking_warnings(
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import math
|
|
||||||
from ubinascii import hexlify
|
from ubinascii import hexlify
|
||||||
|
|
||||||
from trezor import ui
|
from trezor import ui
|
||||||
from trezor.enums import ButtonRequestType, CardanoAddressType, CardanoCertificateType
|
from trezor.enums import ButtonRequestType, CardanoAddressType, CardanoCertificateType
|
||||||
from trezor.strings import format_amount
|
from trezor.strings import format_amount
|
||||||
from trezor.ui.components.tt.button import ButtonDefault
|
from trezor.ui.layouts import (
|
||||||
from trezor.ui.components.tt.scroll import Paginated
|
confirm_metadata,
|
||||||
from trezor.ui.components.tt.text import Text
|
confirm_output,
|
||||||
from trezor.utils import chunks
|
confirm_path_warning,
|
||||||
|
confirm_properties,
|
||||||
|
)
|
||||||
|
|
||||||
from apps.common.confirm import confirm, require_confirm, require_hold_to_confirm
|
|
||||||
from apps.common.layout import address_n_to_str
|
from apps.common.layout import address_n_to_str
|
||||||
|
|
||||||
from . import seed
|
from . import seed
|
||||||
@ -55,9 +55,6 @@ CERTIFICATE_TYPE_NAMES = {
|
|||||||
CardanoCertificateType.STAKE_POOL_REGISTRATION: "Stakepool registration",
|
CardanoCertificateType.STAKE_POOL_REGISTRATION: "Stakepool registration",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Maximum number of characters per line in monospace font.
|
|
||||||
_MAX_MONO_LINE = 18
|
|
||||||
|
|
||||||
|
|
||||||
def format_coin_amount(amount: int) -> str:
|
def format_coin_amount(amount: int) -> str:
|
||||||
return "%s %s" % (format_amount(amount, 6), "ADA")
|
return "%s %s" % (format_amount(amount, 6), "ADA")
|
||||||
@ -75,73 +72,72 @@ async def confirm_sending(
|
|||||||
) -> None:
|
) -> None:
|
||||||
await confirm_sending_token_bundle(ctx, token_bundle)
|
await confirm_sending_token_bundle(ctx, token_bundle)
|
||||||
|
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_output(
|
||||||
page1.normal("Confirm sending:")
|
ctx,
|
||||||
page1.bold(format_coin_amount(ada_amount))
|
|
||||||
page1.normal("to")
|
|
||||||
|
|
||||||
pages = _paginate_text(
|
|
||||||
page1,
|
|
||||||
"Confirm transaction",
|
|
||||||
ui.ICON_SEND,
|
|
||||||
to,
|
to,
|
||||||
lines_per_page=4,
|
format_coin_amount(ada_amount),
|
||||||
lines_used_on_first_page=3,
|
title="Confirm transaction",
|
||||||
|
subtitle="Confirm sending:",
|
||||||
|
font_amount=ui.BOLD,
|
||||||
|
width_paginated=17,
|
||||||
|
to_str="\nto\n",
|
||||||
|
to_paginated=True,
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
)
|
)
|
||||||
|
|
||||||
await require_confirm(ctx, Paginated(pages))
|
|
||||||
|
|
||||||
|
|
||||||
async def confirm_sending_token_bundle(
|
async def confirm_sending_token_bundle(
|
||||||
ctx: wire.Context, token_bundle: list[CardanoAssetGroupType]
|
ctx: wire.Context, token_bundle: list[CardanoAssetGroupType]
|
||||||
) -> None:
|
) -> None:
|
||||||
for token_group in token_bundle:
|
for token_group in token_bundle:
|
||||||
for token in token_group.tokens:
|
for token in token_group.tokens:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_properties(
|
||||||
page1.normal("Asset fingerprint:")
|
ctx,
|
||||||
page1.bold(
|
"confirm_token",
|
||||||
format_asset_fingerprint(
|
title="Confirm transaction",
|
||||||
policy_id=token_group.policy_id,
|
props=[
|
||||||
asset_name_bytes=token.asset_name_bytes,
|
(
|
||||||
)
|
"Asset fingerprint:",
|
||||||
|
format_asset_fingerprint(
|
||||||
|
policy_id=token_group.policy_id,
|
||||||
|
asset_name_bytes=token.asset_name_bytes,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("Amount sent:", format_amount(token.amount, 0)),
|
||||||
|
],
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
)
|
)
|
||||||
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
|
||||||
page2.normal("Amount sent:")
|
|
||||||
page2.bold(format_amount(token.amount, 0))
|
|
||||||
await require_confirm(ctx, Paginated([page1, page2]))
|
|
||||||
|
|
||||||
|
|
||||||
async def show_warning_tx_output_contains_tokens(ctx: wire.Context) -> None:
|
async def show_warning_tx_output_contains_tokens(ctx: wire.Context) -> None:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_metadata(
|
||||||
page1.normal("The following")
|
ctx,
|
||||||
page1.normal("transaction output")
|
"confirm_tokens",
|
||||||
page1.normal("contains tokens.")
|
title="Confirm transaction",
|
||||||
page1.br_half()
|
content="The following\ntransaction output\ncontains tokens.",
|
||||||
page1.normal("Continue?")
|
larger_vspace=True,
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
await require_confirm(ctx, page1)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def show_warning_path(ctx: wire.Context, path: list[int], title: str) -> None:
|
async def show_warning_path(ctx: wire.Context, path: list[int], title: str) -> None:
|
||||||
page1 = Text("Confirm path", ui.ICON_WRONG, ui.RED)
|
await confirm_path_warning(ctx, address_n_to_str(path), path_type=title)
|
||||||
page1.normal(title)
|
|
||||||
page1.bold(address_n_to_str(path))
|
|
||||||
page1.normal("is unknown.")
|
|
||||||
page1.normal("Are you sure?")
|
|
||||||
await require_confirm(ctx, page1)
|
|
||||||
|
|
||||||
|
|
||||||
async def show_warning_tx_no_staking_info(
|
async def show_warning_tx_no_staking_info(
|
||||||
ctx: wire.Context, address_type: CardanoAddressType, amount: int
|
ctx: wire.Context, address_type: CardanoAddressType, amount: int
|
||||||
) -> None:
|
) -> None:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
atype = ADDRESS_TYPE_NAMES[address_type].lower()
|
||||||
page1.normal("Change " + ADDRESS_TYPE_NAMES[address_type].lower())
|
content = "Change %s address has no stake rights.\nChange amount:\n{}" % atype
|
||||||
page1.normal("address has no stake")
|
await confirm_metadata(
|
||||||
page1.normal("rights.")
|
ctx,
|
||||||
page1.normal("Change amount:")
|
"warning_staking",
|
||||||
page1.bold(format_coin_amount(amount))
|
title="Confirm transaction",
|
||||||
|
content=content,
|
||||||
await require_confirm(ctx, page1)
|
param=format_coin_amount(amount),
|
||||||
|
hide_continue=True,
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def show_warning_tx_pointer_address(
|
async def show_warning_tx_pointer_address(
|
||||||
@ -149,21 +145,25 @@ async def show_warning_tx_pointer_address(
|
|||||||
pointer: CardanoBlockchainPointerType,
|
pointer: CardanoBlockchainPointerType,
|
||||||
amount: int,
|
amount: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_properties(
|
||||||
page1.normal("Change address has a")
|
ctx,
|
||||||
page1.normal("pointer with staking")
|
"warning_pointer",
|
||||||
page1.normal("rights.")
|
title="Confirm transaction",
|
||||||
|
props=[
|
||||||
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
("Change address has a\npointer with staking\nrights.\n\n\n", None),
|
||||||
page2.normal("Pointer:")
|
(
|
||||||
page2.bold(
|
"Pointer:",
|
||||||
"%s, %s, %s"
|
"%s, %s, %s"
|
||||||
% (pointer.block_index, pointer.tx_index, pointer.certificate_index)
|
% (
|
||||||
|
pointer.block_index,
|
||||||
|
pointer.tx_index,
|
||||||
|
pointer.certificate_index,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("Change amount:", format_coin_amount(amount)),
|
||||||
|
],
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
)
|
)
|
||||||
page2.normal("Change amount:")
|
|
||||||
page2.bold(format_coin_amount(amount))
|
|
||||||
|
|
||||||
await require_confirm(ctx, Paginated([page1, page2]))
|
|
||||||
|
|
||||||
|
|
||||||
async def show_warning_tx_different_staking_account(
|
async def show_warning_tx_different_staking_account(
|
||||||
@ -171,18 +171,23 @@ async def show_warning_tx_different_staking_account(
|
|||||||
staking_account_path: list[int],
|
staking_account_path: list[int],
|
||||||
amount: int,
|
amount: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_properties(
|
||||||
page1.normal("Change address staking")
|
ctx,
|
||||||
page1.normal("rights do not match")
|
"warning_differentstaking",
|
||||||
page1.normal("the current account.")
|
title="Confirm transaction",
|
||||||
|
props=[
|
||||||
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
(
|
||||||
page2.normal("Staking account %s:" % format_account_number(staking_account_path))
|
"Change address staking rights do not match the current account.\n\n",
|
||||||
page2.bold(address_n_to_str(staking_account_path))
|
None,
|
||||||
page2.normal("Change amount:")
|
),
|
||||||
page2.bold(format_coin_amount(amount))
|
(
|
||||||
|
"Staking account %s:" % format_account_number(staking_account_path),
|
||||||
await require_confirm(ctx, Paginated([page1, page2]))
|
address_n_to_str(staking_account_path),
|
||||||
|
),
|
||||||
|
("Change amount:", format_coin_amount(amount)),
|
||||||
|
],
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def show_warning_tx_staking_key_hash(
|
async def show_warning_tx_staking_key_hash(
|
||||||
@ -190,20 +195,19 @@ async def show_warning_tx_staking_key_hash(
|
|||||||
staking_key_hash: bytes,
|
staking_key_hash: bytes,
|
||||||
amount: int,
|
amount: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
props = [
|
||||||
page1.normal("Change address staking")
|
("Change address staking rights do not match the current account.\n\n", None),
|
||||||
page1.normal("rights do not match")
|
("Staking key hash:", hexlify(staking_key_hash).decode()),
|
||||||
page1.normal("the current account.")
|
("Change amount:", format_coin_amount(amount)),
|
||||||
|
]
|
||||||
|
|
||||||
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_properties(
|
||||||
page2.normal("Staking key hash:")
|
ctx,
|
||||||
page2.mono(*chunks(hexlify(staking_key_hash).decode(), 17))
|
"confirm_different_stakingrights",
|
||||||
|
title="Confirm transaction",
|
||||||
page3 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
props=props,
|
||||||
page3.normal("Change amount:")
|
br_code=ButtonRequestType.Other,
|
||||||
page3.bold(format_coin_amount(amount))
|
)
|
||||||
|
|
||||||
await require_confirm(ctx, Paginated([page1, page2, page3]))
|
|
||||||
|
|
||||||
|
|
||||||
async def confirm_transaction(
|
async def confirm_transaction(
|
||||||
@ -215,24 +219,27 @@ async def confirm_transaction(
|
|||||||
validity_interval_start: int | None,
|
validity_interval_start: int | None,
|
||||||
is_network_id_verifiable: bool,
|
is_network_id_verifiable: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
pages: list[ui.Component] = []
|
props = [
|
||||||
|
("Transaction amount:", format_coin_amount(amount)),
|
||||||
|
("Transaction fee:", format_coin_amount(fee)),
|
||||||
|
]
|
||||||
|
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
|
||||||
page1.normal("Transaction amount:")
|
|
||||||
page1.bold(format_coin_amount(amount))
|
|
||||||
page1.normal("Transaction fee:")
|
|
||||||
page1.bold(format_coin_amount(fee))
|
|
||||||
pages.append(page1)
|
|
||||||
|
|
||||||
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
|
||||||
if is_network_id_verifiable:
|
if is_network_id_verifiable:
|
||||||
page2.normal("Network:")
|
props.append(("Network:", protocol_magics.to_ui_string(protocol_magic)))
|
||||||
page2.bold(protocol_magics.to_ui_string(protocol_magic))
|
|
||||||
page2.normal("Valid since: %s" % format_optional_int(validity_interval_start))
|
|
||||||
page2.normal("TTL: %s" % format_optional_int(ttl))
|
|
||||||
pages.append(page2)
|
|
||||||
|
|
||||||
await require_hold_to_confirm(ctx, Paginated(pages))
|
props.append(
|
||||||
|
("Valid since: %s" % format_optional_int(validity_interval_start), None)
|
||||||
|
)
|
||||||
|
props.append(("TTL: %s" % format_optional_int(ttl), None))
|
||||||
|
|
||||||
|
await confirm_properties(
|
||||||
|
ctx,
|
||||||
|
"confirm_total",
|
||||||
|
title="Confirm transaction",
|
||||||
|
props=props,
|
||||||
|
hold=True,
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def confirm_certificate(
|
async def confirm_certificate(
|
||||||
@ -242,23 +249,24 @@ async def confirm_certificate(
|
|||||||
# in this call
|
# in this call
|
||||||
assert certificate.type != CardanoCertificateType.STAKE_POOL_REGISTRATION
|
assert certificate.type != CardanoCertificateType.STAKE_POOL_REGISTRATION
|
||||||
|
|
||||||
pages: list[ui.Component] = []
|
props = [
|
||||||
|
("Confirm:", CERTIFICATE_TYPE_NAMES[certificate.type]),
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
(
|
||||||
page1.normal("Confirm:")
|
"for account %s:" % format_account_number(certificate.path),
|
||||||
page1.bold(CERTIFICATE_TYPE_NAMES[certificate.type])
|
address_n_to_str(to_account_path(certificate.path)),
|
||||||
page1.normal("for account %s:" % format_account_number(certificate.path))
|
),
|
||||||
page1.bold(address_n_to_str(to_account_path(certificate.path)))
|
]
|
||||||
pages.append(page1)
|
|
||||||
|
|
||||||
if certificate.type == CardanoCertificateType.STAKE_DELEGATION:
|
if certificate.type == CardanoCertificateType.STAKE_DELEGATION:
|
||||||
assert certificate.pool is not None # validate_certificate
|
assert certificate.pool is not None # validate_certificate
|
||||||
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
props.append(("to pool:", format_stake_pool_id(certificate.pool)))
|
||||||
page2.normal("to pool:")
|
|
||||||
page2.bold(format_stake_pool_id(certificate.pool))
|
|
||||||
pages.append(page2)
|
|
||||||
|
|
||||||
await require_confirm(ctx, Paginated(pages))
|
await confirm_properties(
|
||||||
|
ctx,
|
||||||
|
"confirm_certificate",
|
||||||
|
title="Confirm transaction",
|
||||||
|
props=props,
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def confirm_stake_pool_parameters(
|
async def confirm_stake_pool_parameters(
|
||||||
@ -267,25 +275,31 @@ async def confirm_stake_pool_parameters(
|
|||||||
network_id: int,
|
network_id: int,
|
||||||
protocol_magic: int,
|
protocol_magic: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
|
||||||
page1.bold("Stake pool registration")
|
|
||||||
page1.normal("Pool ID:")
|
|
||||||
page1.bold(format_stake_pool_id(pool_parameters.pool_id))
|
|
||||||
|
|
||||||
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
|
||||||
page2.normal("Pool reward account:")
|
|
||||||
page2.bold(pool_parameters.reward_account)
|
|
||||||
|
|
||||||
page3 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
|
||||||
page3.normal("Pledge: " + format_coin_amount(pool_parameters.pledge))
|
|
||||||
page3.normal("Cost: " + format_coin_amount(pool_parameters.cost))
|
|
||||||
margin_percentage = (
|
margin_percentage = (
|
||||||
100.0 * pool_parameters.margin_numerator / pool_parameters.margin_denominator
|
100.0 * pool_parameters.margin_numerator / pool_parameters.margin_denominator
|
||||||
)
|
)
|
||||||
percentage_formatted = ("%f" % margin_percentage).rstrip("0").rstrip(".")
|
percentage_formatted = ("%f" % margin_percentage).rstrip("0").rstrip(".")
|
||||||
page3.normal("Margin: %s%%" % percentage_formatted)
|
await confirm_properties(
|
||||||
|
ctx,
|
||||||
await require_confirm(ctx, Paginated([page1, page2, page3]))
|
"confirm_pool_registration",
|
||||||
|
title="Confirm transaction",
|
||||||
|
props=[
|
||||||
|
(
|
||||||
|
"Stake pool registration\nPool ID:",
|
||||||
|
format_stake_pool_id(pool_parameters.pool_id),
|
||||||
|
),
|
||||||
|
("Pool reward account:", pool_parameters.reward_account),
|
||||||
|
(
|
||||||
|
"Pledge: {}\nCost: {}\nMargin: {}%".format(
|
||||||
|
format_coin_amount(pool_parameters.pledge),
|
||||||
|
format_coin_amount(pool_parameters.cost),
|
||||||
|
percentage_formatted,
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def confirm_stake_pool_owners(
|
async def confirm_stake_pool_owners(
|
||||||
@ -294,56 +308,67 @@ async def confirm_stake_pool_owners(
|
|||||||
owners: list[CardanoPoolOwnerType],
|
owners: list[CardanoPoolOwnerType],
|
||||||
network_id: int,
|
network_id: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
pages: list[ui.Component] = []
|
props: list[tuple[str, str | None]] = []
|
||||||
for index, owner in enumerate(owners, 1):
|
for index, owner in enumerate(owners, 1):
|
||||||
page = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
|
||||||
page.normal("Pool owner #%d:" % (index))
|
|
||||||
|
|
||||||
if owner.staking_key_path:
|
if owner.staking_key_path:
|
||||||
page.bold(address_n_to_str(owner.staking_key_path))
|
props.append(
|
||||||
page.normal(
|
("Pool owner #%d:" % index, address_n_to_str(owner.staking_key_path))
|
||||||
encode_human_readable_address(
|
)
|
||||||
pack_reward_address_bytes(
|
props.append(
|
||||||
get_public_key_hash(keychain, owner.staking_key_path),
|
(
|
||||||
network_id,
|
encode_human_readable_address(
|
||||||
)
|
pack_reward_address_bytes(
|
||||||
|
get_public_key_hash(keychain, owner.staking_key_path),
|
||||||
|
network_id,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
assert owner.staking_key_hash is not None # validate_pool_owners
|
assert owner.staking_key_hash is not None # validate_pool_owners
|
||||||
page.bold(
|
props.append(
|
||||||
encode_human_readable_address(
|
(
|
||||||
pack_reward_address_bytes(owner.staking_key_hash, network_id)
|
"Pool owner #%d:" % index,
|
||||||
|
encode_human_readable_address(
|
||||||
|
pack_reward_address_bytes(owner.staking_key_hash, network_id)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
pages.append(page)
|
await confirm_properties(
|
||||||
|
ctx,
|
||||||
await require_confirm(ctx, Paginated(pages))
|
"confirm_pool_owners",
|
||||||
|
title="Confirm transaction",
|
||||||
|
props=props,
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def confirm_stake_pool_metadata(
|
async def confirm_stake_pool_metadata(
|
||||||
ctx: wire.Context,
|
ctx: wire.Context,
|
||||||
metadata: CardanoPoolMetadataType | None,
|
metadata: CardanoPoolMetadataType | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
if metadata is None:
|
if metadata is None:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_properties(
|
||||||
page1.normal("Pool has no metadata")
|
ctx,
|
||||||
page1.normal("(anonymous pool)")
|
"confirm_pool_metadata",
|
||||||
|
title="Confirm transaction",
|
||||||
await require_confirm(ctx, page1)
|
props=[("Pool has no metadata (anonymous pool)", None)],
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_properties(
|
||||||
page1.normal("Pool metadata url:")
|
ctx,
|
||||||
page1.bold(metadata.url)
|
"confirm_pool_metadata",
|
||||||
|
title="Confirm transaction",
|
||||||
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
props=[
|
||||||
page2.normal("Pool metadata hash:")
|
("Pool metadata url:", metadata.url),
|
||||||
page2.bold(hexlify(metadata.hash).decode())
|
("Pool metadata hash:", hexlify(metadata.hash).decode()),
|
||||||
|
],
|
||||||
await require_confirm(ctx, Paginated([page1, page2]))
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def confirm_transaction_network_ttl(
|
async def confirm_transaction_network_ttl(
|
||||||
@ -352,36 +377,53 @@ async def confirm_transaction_network_ttl(
|
|||||||
ttl: int | None,
|
ttl: int | None,
|
||||||
validity_interval_start: int | None,
|
validity_interval_start: int | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_properties(
|
||||||
page1.normal("Network:")
|
ctx,
|
||||||
page1.bold(protocol_magics.to_ui_string(protocol_magic))
|
"confirm_pool_network",
|
||||||
page1.normal("Valid since: %s" % format_optional_int(validity_interval_start))
|
title="Confirm transaction",
|
||||||
page1.normal("TTL: %s" % format_optional_int(ttl))
|
props=[
|
||||||
|
("Network:", protocol_magics.to_ui_string(protocol_magic)),
|
||||||
await require_confirm(ctx, page1)
|
(
|
||||||
|
"Valid since: %s" % format_optional_int(validity_interval_start),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
("TTL: %s" % format_optional_int(ttl), None),
|
||||||
|
],
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def confirm_stake_pool_registration_final(
|
async def confirm_stake_pool_registration_final(
|
||||||
ctx: wire.Context,
|
ctx: wire.Context,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
await confirm_metadata(
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
ctx,
|
||||||
page1.normal("Confirm signing the stake pool registration as an owner")
|
"confirm_pool_final",
|
||||||
|
title="Confirm transaction",
|
||||||
await require_hold_to_confirm(ctx, page1)
|
content="Confirm signing the stake pool registration as an owner",
|
||||||
|
hide_continue=True,
|
||||||
|
hold=True,
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def confirm_withdrawal(
|
async def confirm_withdrawal(
|
||||||
ctx: wire.Context, withdrawal: CardanoTxWithdrawalType
|
ctx: wire.Context, withdrawal: CardanoTxWithdrawalType
|
||||||
) -> None:
|
) -> None:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_properties(
|
||||||
page1.normal("Confirm withdrawal")
|
ctx,
|
||||||
page1.normal("for account %s:" % format_account_number(withdrawal.path))
|
"confirm_withdrawal",
|
||||||
page1.bold(address_n_to_str(to_account_path(withdrawal.path)))
|
title="Confirm transaction",
|
||||||
page1.normal("Amount:")
|
props=[
|
||||||
page1.bold(format_coin_amount(withdrawal.amount))
|
(
|
||||||
|
"Confirm withdrawal\nfor account %s:"
|
||||||
await require_confirm(ctx, page1)
|
% format_account_number(withdrawal.path),
|
||||||
|
address_n_to_str(to_account_path(withdrawal.path)),
|
||||||
|
),
|
||||||
|
("Amount:", format_coin_amount(withdrawal.amount)),
|
||||||
|
],
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def confirm_catalyst_registration(
|
async def confirm_catalyst_registration(
|
||||||
@ -391,166 +433,98 @@ async def confirm_catalyst_registration(
|
|||||||
reward_address: str,
|
reward_address: str,
|
||||||
nonce: int,
|
nonce: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
pages: list[ui.Component] = []
|
await confirm_properties(
|
||||||
|
ctx,
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
"confirm_catalyst_registration",
|
||||||
page1.bold("Catalyst voting key")
|
title="Confirm transaction",
|
||||||
page1.bold("registration")
|
props=[
|
||||||
pages.append(page1)
|
("Catalyst voting key registration", None),
|
||||||
|
("Voting public key:", public_key),
|
||||||
page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
(
|
||||||
page2.normal("Voting public key:")
|
"Staking key for account %s:" % format_account_number(staking_path),
|
||||||
page2.bold(*chunks(public_key, 17))
|
address_n_to_str(staking_path),
|
||||||
pages.append(page2)
|
),
|
||||||
|
("Rewards go to:", reward_address),
|
||||||
page3 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
("Nonce:", str(nonce)),
|
||||||
page3.normal("Staking key for")
|
],
|
||||||
page3.normal("account %s:" % format_account_number(staking_path))
|
br_code=ButtonRequestType.Other,
|
||||||
page3.bold(address_n_to_str(staking_path))
|
|
||||||
pages.append(page3)
|
|
||||||
|
|
||||||
page4 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
|
||||||
page4.normal("Rewards go to:")
|
|
||||||
|
|
||||||
pages.extend(
|
|
||||||
_paginate_text(page4, "Confirm transaction", ui.ICON_SEND, reward_address)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
last_page = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
|
||||||
last_page.normal("Nonce: %s" % nonce)
|
|
||||||
pages.append(last_page)
|
|
||||||
|
|
||||||
await require_confirm(ctx, Paginated(pages))
|
|
||||||
|
|
||||||
|
|
||||||
async def show_auxiliary_data_hash(
|
async def show_auxiliary_data_hash(
|
||||||
ctx: wire.Context, auxiliary_data_hash: bytes
|
ctx: wire.Context, auxiliary_data_hash: bytes
|
||||||
) -> None:
|
) -> None:
|
||||||
page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
|
await confirm_properties(
|
||||||
page1.normal("Auxiliary data hash:")
|
|
||||||
page1.bold(hexlify(auxiliary_data_hash).decode())
|
|
||||||
|
|
||||||
await require_confirm(ctx, page1)
|
|
||||||
|
|
||||||
|
|
||||||
async def show_address(
|
|
||||||
ctx: wire.Context,
|
|
||||||
address: str,
|
|
||||||
address_type: CardanoAddressType,
|
|
||||||
path: list[int],
|
|
||||||
network: str | None = None,
|
|
||||||
) -> bool:
|
|
||||||
"""
|
|
||||||
Custom show_address function is needed because cardano addresses don't
|
|
||||||
fit on a single screen.
|
|
||||||
"""
|
|
||||||
|
|
||||||
address_type_label = "%s address" % ADDRESS_TYPE_NAMES[address_type]
|
|
||||||
page1 = Text(address_type_label, ui.ICON_RECEIVE, ui.GREEN)
|
|
||||||
|
|
||||||
lines_per_page = 5
|
|
||||||
lines_used_on_first_page = 0
|
|
||||||
|
|
||||||
# assemble first page to be displayed (path + network + whatever part of the address fits)
|
|
||||||
if network is not None:
|
|
||||||
page1.normal("%s network" % network)
|
|
||||||
lines_used_on_first_page += 1
|
|
||||||
|
|
||||||
path_str = address_n_to_str(path)
|
|
||||||
page1.mono(path_str)
|
|
||||||
lines_used_on_first_page = min(
|
|
||||||
lines_used_on_first_page + math.ceil(len(path_str) / _MAX_MONO_LINE),
|
|
||||||
lines_per_page,
|
|
||||||
)
|
|
||||||
|
|
||||||
pages = _paginate_text(
|
|
||||||
page1,
|
|
||||||
address_type_label,
|
|
||||||
ui.ICON_RECEIVE,
|
|
||||||
address,
|
|
||||||
lines_per_page=lines_per_page,
|
|
||||||
lines_used_on_first_page=lines_used_on_first_page,
|
|
||||||
)
|
|
||||||
|
|
||||||
return await confirm(
|
|
||||||
ctx,
|
ctx,
|
||||||
Paginated(pages),
|
"confirm_auxiliary_data",
|
||||||
code=ButtonRequestType.Address,
|
title="Confirm transaction",
|
||||||
cancel="QR",
|
props=[("Auxiliary data hash:", hexlify(auxiliary_data_hash).decode())],
|
||||||
cancel_style=ButtonDefault,
|
br_code=ButtonRequestType.Other,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _paginate_text(
|
|
||||||
first_page: Text,
|
|
||||||
page_desc: str,
|
|
||||||
page_icon: str,
|
|
||||||
text: str,
|
|
||||||
lines_per_page: int = 5,
|
|
||||||
lines_used_on_first_page: int = 1,
|
|
||||||
) -> list[ui.Component]:
|
|
||||||
lines = list(chunks(text, 17))
|
|
||||||
|
|
||||||
offset = lines_per_page - lines_used_on_first_page
|
|
||||||
|
|
||||||
for text_line in lines[:offset]:
|
|
||||||
first_page.bold(text_line)
|
|
||||||
|
|
||||||
pages: list[ui.Component] = [first_page]
|
|
||||||
if len(lines) > offset:
|
|
||||||
to_pages = list(chunks(lines[offset:], lines_per_page))
|
|
||||||
for page in to_pages:
|
|
||||||
t = Text(page_desc, page_icon, ui.GREEN)
|
|
||||||
for line in page:
|
|
||||||
t.bold(line)
|
|
||||||
pages.append(t)
|
|
||||||
|
|
||||||
return pages
|
|
||||||
|
|
||||||
|
|
||||||
async def show_warning_address_foreign_staking_key(
|
async def show_warning_address_foreign_staking_key(
|
||||||
ctx: wire.Context,
|
ctx: wire.Context,
|
||||||
account_path: list[int],
|
account_path: list[int],
|
||||||
staking_account_path: list[int],
|
staking_account_path: list[int],
|
||||||
staking_key_hash: bytes | None,
|
staking_key_hash: bytes | None,
|
||||||
) -> None:
|
) -> None:
|
||||||
page1 = Text("Warning", ui.ICON_WRONG, ui.RED)
|
props: list[tuple[str, str | None]] = [
|
||||||
page1.normal("Stake rights associated")
|
(
|
||||||
page1.normal("with this address do")
|
"Stake rights associated with this address do not match your account %s:"
|
||||||
page1.normal("not match your")
|
% format_account_number(account_path),
|
||||||
page1.normal("account %s:" % format_account_number(account_path))
|
address_n_to_str(account_path),
|
||||||
page1.bold(address_n_to_str(account_path))
|
)
|
||||||
|
]
|
||||||
|
|
||||||
page2 = Text("Warning", ui.ICON_WRONG, ui.RED)
|
|
||||||
if staking_account_path:
|
if staking_account_path:
|
||||||
page2.normal("Stake account %s:" % format_account_number(staking_account_path))
|
props.append(
|
||||||
page2.bold(address_n_to_str(staking_account_path))
|
(
|
||||||
page2.br_half()
|
"Stake account %s:" % format_account_number(staking_account_path),
|
||||||
|
address_n_to_str(staking_account_path),
|
||||||
|
)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
assert staking_key_hash is not None # _validate_base_address_staking_info
|
assert staking_key_hash is not None # _validate_base_address_staking_info
|
||||||
page2.normal("Staking key:")
|
props.append(("Staking key:", hexlify(staking_key_hash).decode()))
|
||||||
page2.bold(hexlify(staking_key_hash).decode())
|
props.append(("Continue?", None))
|
||||||
page2.normal("Continue?")
|
|
||||||
|
|
||||||
await require_confirm(ctx, Paginated([page1, page2]))
|
await confirm_properties(
|
||||||
|
ctx,
|
||||||
|
"warning_foreign_stakingkey",
|
||||||
|
title="Warning",
|
||||||
|
props=props,
|
||||||
|
icon=ui.ICON_WRONG,
|
||||||
|
icon_color=ui.RED,
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def show_warning_tx_network_unverifiable(ctx: wire.Context) -> None:
|
async def show_warning_tx_network_unverifiable(ctx: wire.Context) -> None:
|
||||||
page1 = Text("Warning", ui.ICON_SEND, ui.GREEN)
|
await confirm_metadata(
|
||||||
page1.normal("Transaction has no outputs, network cannot be verified.")
|
ctx,
|
||||||
page1.br_half()
|
"warning_no_outputs",
|
||||||
page1.normal("Continue?")
|
title="Warning",
|
||||||
|
content="Transaction has no outputs, network cannot be verified.",
|
||||||
await require_confirm(ctx, page1)
|
larger_vspace=True,
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def show_warning_address_pointer(
|
async def show_warning_address_pointer(
|
||||||
ctx: wire.Context, pointer: CardanoBlockchainPointerType
|
ctx: wire.Context, pointer: CardanoBlockchainPointerType
|
||||||
) -> None:
|
) -> None:
|
||||||
text = Text("Warning", ui.ICON_WRONG, ui.RED)
|
content = "Pointer address:\nBlock: %s\nTransaction: %s\nCertificate: %s" % (
|
||||||
text.normal("Pointer address:")
|
pointer.block_index,
|
||||||
text.normal("Block: %s" % pointer.block_index)
|
pointer.tx_index,
|
||||||
text.normal("Transaction: %s" % pointer.tx_index)
|
pointer.certificate_index,
|
||||||
text.normal("Certificate: %s" % pointer.certificate_index)
|
)
|
||||||
text.normal("Continue?")
|
await confirm_metadata(
|
||||||
await require_confirm(ctx, text)
|
ctx,
|
||||||
|
"warning_pointer",
|
||||||
|
title="Warning",
|
||||||
|
icon=ui.ICON_WRONG,
|
||||||
|
icon_color=ui.RED,
|
||||||
|
content=content,
|
||||||
|
br_code=ButtonRequestType.Other,
|
||||||
|
)
|
||||||
|
@ -1,42 +1,9 @@
|
|||||||
from micropython import const
|
|
||||||
|
|
||||||
from trezor import ui
|
|
||||||
from trezor.enums import ButtonRequestType
|
|
||||||
from trezor.ui.components.tt.button import ButtonDefault
|
|
||||||
from trezor.ui.components.tt.text import Text
|
|
||||||
from trezor.ui.container import Container
|
|
||||||
from trezor.ui.qr import Qr
|
|
||||||
from trezor.utils import chunks
|
from trezor.utils import chunks
|
||||||
|
|
||||||
from apps.common import HARDENED
|
from apps.common import HARDENED
|
||||||
from apps.common.confirm import confirm
|
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
from typing import Iterable, Iterator
|
from typing import Iterable, Iterator
|
||||||
from trezor import wire
|
|
||||||
|
|
||||||
|
|
||||||
async def show_qr(
|
|
||||||
ctx: wire.Context,
|
|
||||||
address: str,
|
|
||||||
desc: str = "Confirm address",
|
|
||||||
cancel: str = "Address",
|
|
||||||
) -> bool:
|
|
||||||
QR_X = const(120)
|
|
||||||
QR_Y = const(115)
|
|
||||||
QR_SIZE_THRESHOLD = const(63)
|
|
||||||
QR_COEF = const(4) if len(address) < QR_SIZE_THRESHOLD else const(3)
|
|
||||||
qr = Qr(address, QR_X, QR_Y, QR_COEF)
|
|
||||||
text = Text(desc, ui.ICON_RECEIVE, ui.GREEN)
|
|
||||||
content = Container(qr, text)
|
|
||||||
|
|
||||||
return await confirm(
|
|
||||||
ctx,
|
|
||||||
content,
|
|
||||||
code=ButtonRequestType.Address,
|
|
||||||
cancel=cancel,
|
|
||||||
cancel_style=ButtonDefault,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def split_address(address: str) -> Iterator[str]:
|
def split_address(address: str) -> Iterator[str]:
|
||||||
|
@ -10,7 +10,7 @@ from .swipe import SWIPE_DOWN, SWIPE_UP, SWIPE_VERTICAL, Swipe
|
|||||||
from .text import TEXT_MAX_LINES, Span, Text
|
from .text import TEXT_MAX_LINES, Span, Text
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
from typing import Iterable, Any
|
from typing import Callable, Iterable
|
||||||
|
|
||||||
from ..common.text import TextContent
|
from ..common.text import TextContent
|
||||||
|
|
||||||
@ -266,7 +266,8 @@ def paginate_text(
|
|||||||
header_icon: str = ui.ICON_DEFAULT,
|
header_icon: str = ui.ICON_DEFAULT,
|
||||||
icon_color: int = ui.ORANGE_ICON,
|
icon_color: int = ui.ORANGE_ICON,
|
||||||
break_words: bool = False,
|
break_words: bool = False,
|
||||||
) -> Confirm | Paginated:
|
confirm: Callable[[ui.Component], ui.Layout] = Confirm,
|
||||||
|
) -> ui.Layout:
|
||||||
span = Span(text, 0, font, break_words=break_words)
|
span = Span(text, 0, font, break_words=break_words)
|
||||||
if span.count_lines() <= TEXT_MAX_LINES:
|
if span.count_lines() <= TEXT_MAX_LINES:
|
||||||
result = Text(
|
result = Text(
|
||||||
@ -277,7 +278,7 @@ def paginate_text(
|
|||||||
break_words=break_words,
|
break_words=break_words,
|
||||||
)
|
)
|
||||||
result.content = [font, text]
|
result.content = [font, text]
|
||||||
return Confirm(result)
|
return confirm(result)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
pages: list[ui.Component] = []
|
pages: list[ui.Component] = []
|
||||||
@ -305,7 +306,7 @@ def paginate_text(
|
|||||||
for _ in range(TEXT_MAX_LINES - 1):
|
for _ in range(TEXT_MAX_LINES - 1):
|
||||||
span.next_line()
|
span.next_line()
|
||||||
|
|
||||||
pages[-1] = Confirm(pages[-1])
|
pages[-1] = confirm(pages[-1])
|
||||||
return Paginated(pages)
|
return Paginated(pages)
|
||||||
|
|
||||||
|
|
||||||
@ -315,8 +316,8 @@ def paginate_paragraphs(
|
|||||||
header_icon: str = ui.ICON_DEFAULT,
|
header_icon: str = ui.ICON_DEFAULT,
|
||||||
icon_color: int = ui.ORANGE_ICON,
|
icon_color: int = ui.ORANGE_ICON,
|
||||||
break_words: bool = False,
|
break_words: bool = False,
|
||||||
confirm_kwargs: Dict[str, Any] = {},
|
confirm: Callable[[ui.Component], ui.Layout] = Confirm,
|
||||||
) -> Union[Confirm, Paginated]:
|
) -> ui.Layout:
|
||||||
span = Span("", 0, ui.NORMAL, break_words=break_words)
|
span = Span("", 0, ui.NORMAL, break_words=break_words)
|
||||||
lines = 0
|
lines = 0
|
||||||
content: list[TextContent] = []
|
content: list[TextContent] = []
|
||||||
@ -343,7 +344,7 @@ def paginate_paragraphs(
|
|||||||
result.content.append("\n")
|
result.content.append("\n")
|
||||||
result.content.append(font)
|
result.content.append(font)
|
||||||
result.content.append(text)
|
result.content.append(text)
|
||||||
return Confirm(result, **confirm_kwargs)
|
return confirm(result)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
pages: list[ui.Component] = []
|
pages: list[ui.Component] = []
|
||||||
@ -373,5 +374,5 @@ def paginate_paragraphs(
|
|||||||
else:
|
else:
|
||||||
lines_left -= 1
|
lines_left -= 1
|
||||||
|
|
||||||
pages[-1] = Confirm(pages[-1], **confirm_kwargs)
|
pages[-1] = confirm(pages[-1])
|
||||||
return Paginated(pages)
|
return Paginated(pages)
|
||||||
|
@ -25,15 +25,18 @@ from .common import interact
|
|||||||
|
|
||||||
if False:
|
if False:
|
||||||
from typing import (
|
from typing import (
|
||||||
|
Awaitable,
|
||||||
Iterator,
|
Iterator,
|
||||||
|
NoReturn,
|
||||||
|
Optional,
|
||||||
Sequence,
|
Sequence,
|
||||||
|
Tuple,
|
||||||
Type,
|
Type,
|
||||||
Union,
|
Union,
|
||||||
Awaitable,
|
|
||||||
NoReturn,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
ExceptionType = Union[BaseException, Type[BaseException]]
|
ExceptionType = Union[BaseException, Type[BaseException]]
|
||||||
|
PropertyType = Tuple[str, Optional[str]]
|
||||||
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
@ -52,6 +55,7 @@ __all__ = (
|
|||||||
"confirm_output",
|
"confirm_output",
|
||||||
"confirm_decred_sstx_submission",
|
"confirm_decred_sstx_submission",
|
||||||
"confirm_hex",
|
"confirm_hex",
|
||||||
|
"confirm_properties",
|
||||||
"confirm_total",
|
"confirm_total",
|
||||||
"confirm_total_ethereum",
|
"confirm_total_ethereum",
|
||||||
"confirm_total_ripple",
|
"confirm_total_ripple",
|
||||||
@ -182,9 +186,11 @@ async def confirm_backup(ctx: wire.GenericContext) -> bool:
|
|||||||
return confirmed
|
return confirmed
|
||||||
|
|
||||||
|
|
||||||
async def confirm_path_warning(ctx: wire.GenericContext, path: str) -> None:
|
async def confirm_path_warning(
|
||||||
|
ctx: wire.GenericContext, path: str, path_type: str = "Path"
|
||||||
|
) -> None:
|
||||||
text = Text("Confirm path", ui.ICON_WRONG, ui.RED)
|
text = Text("Confirm path", ui.ICON_WRONG, ui.RED)
|
||||||
text.normal("Path")
|
text.normal(path_type)
|
||||||
text.mono(*break_path_to_lines(path, MONO_ADDR_PER_LINE))
|
text.mono(*break_path_to_lines(path, MONO_ADDR_PER_LINE))
|
||||||
text.normal("is unknown.", "Are you sure?")
|
text.normal("is unknown.", "Are you sure?")
|
||||||
await raise_if_cancelled(
|
await raise_if_cancelled(
|
||||||
@ -237,8 +243,11 @@ def _show_address(
|
|||||||
address: str,
|
address: str,
|
||||||
title: str,
|
title: str,
|
||||||
network: str | None = None,
|
network: str | None = None,
|
||||||
) -> Confirm | Paginated:
|
extra: str | None = None,
|
||||||
|
) -> ui.Layout:
|
||||||
para = [(ui.NORMAL, "%s network" % network)] if network is not None else []
|
para = [(ui.NORMAL, "%s network" % network)] if network is not None else []
|
||||||
|
if extra is not None:
|
||||||
|
para.append((ui.BOLD, extra))
|
||||||
para.extend(
|
para.extend(
|
||||||
(ui.MONO, address_line) for address_line in chunks(address, MONO_ADDR_PER_LINE)
|
(ui.MONO, address_line) for address_line in chunks(address, MONO_ADDR_PER_LINE)
|
||||||
)
|
)
|
||||||
@ -247,7 +256,9 @@ def _show_address(
|
|||||||
header=title,
|
header=title,
|
||||||
header_icon=ui.ICON_RECEIVE,
|
header_icon=ui.ICON_RECEIVE,
|
||||||
icon_color=ui.GREEN,
|
icon_color=ui.GREEN,
|
||||||
confirm_kwargs={"cancel": "QR", "cancel_style": ButtonDefault},
|
confirm=lambda content: Confirm(
|
||||||
|
content, cancel="QR", cancel_style=ButtonDefault
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -290,6 +301,8 @@ async def show_address(
|
|||||||
network: str | None = None,
|
network: str | None = None,
|
||||||
multisig_index: int | None = None,
|
multisig_index: int | None = None,
|
||||||
xpubs: Sequence[str] = [],
|
xpubs: Sequence[str] = [],
|
||||||
|
address_extra: str | None = None,
|
||||||
|
title_qr: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
is_multisig = len(xpubs) > 0
|
is_multisig = len(xpubs) > 0
|
||||||
while True:
|
while True:
|
||||||
@ -300,6 +313,7 @@ async def show_address(
|
|||||||
address,
|
address,
|
||||||
title,
|
title,
|
||||||
network,
|
network,
|
||||||
|
extra=address_extra,
|
||||||
),
|
),
|
||||||
"show_address",
|
"show_address",
|
||||||
ButtonRequestType.Address,
|
ButtonRequestType.Address,
|
||||||
@ -311,7 +325,7 @@ async def show_address(
|
|||||||
ctx,
|
ctx,
|
||||||
_show_qr(
|
_show_qr(
|
||||||
address if address_qr is None else address_qr,
|
address if address_qr is None else address_qr,
|
||||||
title,
|
title if title_qr is None else title_qr,
|
||||||
cancel="XPUBs" if is_multisig else "Address",
|
cancel="XPUBs" if is_multisig else "Address",
|
||||||
),
|
),
|
||||||
"show_qr",
|
"show_qr",
|
||||||
@ -455,19 +469,29 @@ async def confirm_output(
|
|||||||
address: str,
|
address: str,
|
||||||
amount: str,
|
amount: str,
|
||||||
font_amount: int = ui.NORMAL, # TODO cleanup @ redesign
|
font_amount: int = ui.NORMAL, # TODO cleanup @ redesign
|
||||||
|
title: str = "Confirm sending",
|
||||||
|
subtitle: str | None = None, # TODO cleanup @ redesign
|
||||||
color_to: int = ui.FG, # TODO cleanup @ redesign
|
color_to: int = ui.FG, # TODO cleanup @ redesign
|
||||||
to_str: str = " to\n", # TODO cleanup @ redesign
|
to_str: str = " to\n", # TODO cleanup @ redesign
|
||||||
|
to_paginated: bool = False, # TODO cleanup @ redesign
|
||||||
width: int = MONO_ADDR_PER_LINE,
|
width: int = MONO_ADDR_PER_LINE,
|
||||||
width_paginated: int = MONO_ADDR_PER_LINE - 1,
|
width_paginated: int = MONO_ADDR_PER_LINE - 1,
|
||||||
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
|
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
|
||||||
) -> None:
|
) -> None:
|
||||||
title = "Confirm sending"
|
header_lines = to_str.count("\n") + int(subtitle is not None)
|
||||||
if len(address) > (TEXT_MAX_LINES - 1) * width:
|
if len(address) > (TEXT_MAX_LINES - header_lines) * width:
|
||||||
para = [(font_amount, amount)]
|
para = []
|
||||||
|
if subtitle is not None:
|
||||||
|
para.append((ui.NORMAL, subtitle))
|
||||||
|
para.append((font_amount, amount))
|
||||||
|
if to_paginated:
|
||||||
|
para.append((ui.NORMAL, "to"))
|
||||||
para.extend((ui.MONO, line) for line in chunks(address, width_paginated))
|
para.extend((ui.MONO, line) for line in chunks(address, width_paginated))
|
||||||
content: ui.Layout = paginate_paragraphs(para, title, ui.ICON_SEND, ui.GREEN)
|
content: ui.Layout = paginate_paragraphs(para, title, ui.ICON_SEND, ui.GREEN)
|
||||||
else:
|
else:
|
||||||
text = Text(title, ui.ICON_SEND, ui.GREEN, new_lines=False)
|
text = Text(title, ui.ICON_SEND, ui.GREEN, new_lines=False)
|
||||||
|
if subtitle is not None:
|
||||||
|
text.normal(subtitle, "\n")
|
||||||
text.content = [font_amount, amount, ui.NORMAL, color_to, to_str, ui.FG]
|
text.content = [font_amount, amount, ui.NORMAL, color_to, to_str, ui.FG]
|
||||||
text.mono(*chunks_intersperse(address, width))
|
text.mono(*chunks_intersperse(address, width))
|
||||||
content = Confirm(text)
|
content = Confirm(text)
|
||||||
@ -552,6 +576,28 @@ async def confirm_hex(
|
|||||||
await raise_if_cancelled(interact(ctx, content, br_type, br_code))
|
await raise_if_cancelled(interact(ctx, content, br_type, br_code))
|
||||||
|
|
||||||
|
|
||||||
|
# TODO keep name and value on the same page if possible
|
||||||
|
async def confirm_properties(
|
||||||
|
ctx: wire.GenericContext,
|
||||||
|
br_type: str,
|
||||||
|
title: str,
|
||||||
|
props: Sequence[PropertyType],
|
||||||
|
icon: str = ui.ICON_SEND, # TODO cleanup @ redesign
|
||||||
|
icon_color: int = ui.GREEN, # TODO cleanup @ redesign
|
||||||
|
hold: bool = False,
|
||||||
|
br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
|
||||||
|
) -> None:
|
||||||
|
para = []
|
||||||
|
for p in props:
|
||||||
|
para.append((ui.NORMAL, p[0]))
|
||||||
|
if p[1] is not None:
|
||||||
|
para.append((ui.BOLD, p[1]))
|
||||||
|
content = paginate_paragraphs(
|
||||||
|
para, title, icon, icon_color, confirm=HoldToConfirm if hold else Confirm
|
||||||
|
)
|
||||||
|
await raise_if_cancelled(interact(ctx, content, br_type, br_code))
|
||||||
|
|
||||||
|
|
||||||
async def confirm_total(
|
async def confirm_total(
|
||||||
ctx: wire.GenericContext,
|
ctx: wire.GenericContext,
|
||||||
total_amount: str,
|
total_amount: str,
|
||||||
@ -630,6 +676,7 @@ async def confirm_metadata(
|
|||||||
param_font: int = ui.BOLD,
|
param_font: int = ui.BOLD,
|
||||||
icon: str = ui.ICON_SEND, # TODO cleanup @ redesign
|
icon: str = ui.ICON_SEND, # TODO cleanup @ redesign
|
||||||
icon_color: int = ui.GREEN, # TODO cleanup @ redesign
|
icon_color: int = ui.GREEN, # TODO cleanup @ redesign
|
||||||
|
larger_vspace: bool = False, # TODO cleanup @ redesign
|
||||||
) -> None:
|
) -> None:
|
||||||
text = Text(title, icon, icon_color, new_lines=False)
|
text = Text(title, icon, icon_color, new_lines=False)
|
||||||
text.format_parametrized(
|
text.format_parametrized(
|
||||||
@ -638,6 +685,8 @@ async def confirm_metadata(
|
|||||||
|
|
||||||
if not hide_continue:
|
if not hide_continue:
|
||||||
text.br()
|
text.br()
|
||||||
|
if larger_vspace:
|
||||||
|
text.br_half()
|
||||||
text.normal("Continue?")
|
text.normal("Continue?")
|
||||||
|
|
||||||
cls = HoldToConfirm if hold else Confirm
|
cls = HoldToConfirm if hold else Confirm
|
||||||
|
@ -107,7 +107,6 @@ def test_cardano_sign_tx_with_multiple_chunks(client, parameters, result):
|
|||||||
# If that changes, we'll need to figure out something else.
|
# If that changes, we'll need to figure out something else.
|
||||||
messages.ButtonRequest(page_number=1),
|
messages.ButtonRequest(page_number=1),
|
||||||
messages.ButtonRequest(page_number=2),
|
messages.ButtonRequest(page_number=2),
|
||||||
messages.ButtonRequest(page_number=3),
|
|
||||||
messages.ButtonRequest(page_number=1),
|
messages.ButtonRequest(page_number=1),
|
||||||
messages.ButtonRequest(page_number=2),
|
messages.ButtonRequest(page_number=2),
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user