from typing import TYPE_CHECKING from trezor import TR, ui from trezor.enums import ( ButtonRequestType, CardanoAddressType, CardanoCertificateType, CardanoNativeScriptType, ) from trezor.strings import format_amount from trezor.ui import layouts from trezor.ui.layouts import confirm_metadata, confirm_properties from apps.common.paths import address_n_to_str from . import addresses from .helpers import bech32, protocol_magics from .helpers.utils import ( format_account_number, format_asset_fingerprint, format_optional_int, format_stake_pool_id, ) if TYPE_CHECKING: from typing import Literal from trezor import messages from trezor.enums import CardanoNativeScriptHashDisplayFormat from trezor.ui.layouts import PropertyType from .helpers.credential import Credential from .seed import Keychain ADDRESS_TYPE_NAMES = { CardanoAddressType.BYRON: TR.cardano__addr_legacy, CardanoAddressType.BASE: TR.cardano__addr_base, CardanoAddressType.BASE_SCRIPT_KEY: TR.cardano__addr_base, CardanoAddressType.BASE_KEY_SCRIPT: TR.cardano__addr_base, CardanoAddressType.BASE_SCRIPT_SCRIPT: TR.cardano__addr_base, CardanoAddressType.POINTER: TR.cardano__addr_pointer, CardanoAddressType.POINTER_SCRIPT: TR.cardano__addr_pointer, CardanoAddressType.ENTERPRISE: TR.cardano__addr_enterprise, CardanoAddressType.ENTERPRISE_SCRIPT: TR.cardano__addr_enterprise, CardanoAddressType.REWARD: TR.cardano__addr_reward, CardanoAddressType.REWARD_SCRIPT: TR.cardano__addr_reward, } SCRIPT_TYPE_NAMES = { CardanoNativeScriptType.PUB_KEY: TR.cardano__script_key, CardanoNativeScriptType.ALL: TR.cardano__script_all, CardanoNativeScriptType.ANY: TR.cardano__script_any, CardanoNativeScriptType.N_OF_K: TR.cardano__script_n_of_k, CardanoNativeScriptType.INVALID_BEFORE: TR.cardano__script_invalid_before, CardanoNativeScriptType.INVALID_HEREAFTER: TR.cardano__script_invalid_hereafter, } CERTIFICATE_TYPE_NAMES = { CardanoCertificateType.STAKE_REGISTRATION: TR.cardano__stake_registration, CardanoCertificateType.STAKE_DEREGISTRATION: TR.cardano__stake_deregistration, CardanoCertificateType.STAKE_DELEGATION: TR.cardano__stake_delegation, CardanoCertificateType.STAKE_POOL_REGISTRATION: TR.cardano__stake_pool_registration, } BRT_Other = ButtonRequestType.Other # global_import_cache CVOTE_REWARD_ELIGIBILITY_WARNING = TR.cardano__reward_eligibility_warning def format_coin_amount(amount: int, network_id: int) -> str: from .helpers import network_ids currency = "ADA" if network_ids.is_mainnet(network_id) else "tADA" return f"{format_amount(amount, 6)} {currency}" async def show_native_script( script: messages.CardanoNativeScript, indices: list[int] | None = None, ) -> None: CNST = CardanoNativeScriptType # local_cache_global script_type = script.type # local_cache_attribute key_path = script.key_path # local_cache_attribute key_hash = script.key_hash # local_cache_attribute scripts = script.scripts # local_cache_attribute script_heading = "Script" if indices is None: indices = [] if indices: script_heading += " " + ".".join(str(i) for i in indices) script_type_name_suffix = "" if script_type == CNST.PUB_KEY: if key_path: script_type_name_suffix = "path" elif key_hash: script_type_name_suffix = "hash" props: list[PropertyType] = [ ( f"{script_heading} - {SCRIPT_TYPE_NAMES[script_type]} {script_type_name_suffix}:", None, ) ] append = props.append # local_cache_attribute if script_type == CNST.PUB_KEY: assert key_hash is not None or key_path # validate_script if key_hash: append((None, bech32.encode(bech32.HRP_SHARED_KEY_HASH, key_hash))) elif key_path: append((address_n_to_str(key_path), None)) elif script_type == CNST.N_OF_K: assert script.required_signatures_count is not None # validate_script append( ( TR.cardano__x_of_y_signatures_template.format( script.required_signatures_count, len(scripts) ), None, ) ) elif script_type == CNST.INVALID_BEFORE: assert script.invalid_before is not None # validate_script append((str(script.invalid_before), None)) elif script_type == CNST.INVALID_HEREAFTER: assert script.invalid_hereafter is not None # validate_script append((str(script.invalid_hereafter), None)) if script_type in ( CNST.ALL, CNST.ANY, CNST.N_OF_K, ): assert scripts # validate_script append((TR.cardano__nested_scripts_template.format(len(scripts)), None)) await confirm_properties( "verify_script", TR.cardano__verify_script, props, br_code=BRT_Other, ) for i, sub_script in enumerate(scripts): await show_native_script(sub_script, indices + [i + 1]) async def show_script_hash( script_hash: bytes, display_format: CardanoNativeScriptHashDisplayFormat, ) -> None: from trezor.enums import CardanoNativeScriptHashDisplayFormat assert display_format in ( CardanoNativeScriptHashDisplayFormat.BECH32, CardanoNativeScriptHashDisplayFormat.POLICY_ID, ) if display_format == CardanoNativeScriptHashDisplayFormat.BECH32: await confirm_properties( "verify_script", TR.cardano__verify_script, ( ( TR.cardano__script_hash, bech32.encode(bech32.HRP_SCRIPT_HASH, script_hash), ), ), br_code=BRT_Other, ) elif display_format == CardanoNativeScriptHashDisplayFormat.POLICY_ID: await layouts.confirm_blob( "verify_script", TR.cardano__verify_script, script_hash, TR.cardano__policy_id, br_code=BRT_Other, ) async def show_tx_init(title: str) -> bool: should_show_details = await layouts.should_show_more( TR.cardano__confirm_transaction, ( ( ui.DEMIBOLD, title, ), (ui.NORMAL, TR.cardano__choose_level_of_details), ), TR.buttons__show_all, confirm=TR.cardano__show_simple, ) return should_show_details async def confirm_input(input: messages.CardanoTxInput) -> None: await confirm_properties( "confirm_input", TR.cardano__confirm_transaction, ( (TR.cardano__input_id, input.prev_hash), (TR.cardano__input_index, str(input.prev_index)), ), br_code=BRT_Other, ) async def confirm_sending( ada_amount: int, to: str, output_type: Literal["address", "change", "collateral-return"], network_id: int, chunkify: bool, ) -> None: if output_type == "address": title = TR.cardano__sending elif output_type == "change": title = TR.cardano__change_output elif output_type == "collateral-return": title = TR.cardano__collateral_return else: raise RuntimeError # should be unreachable await layouts.confirm_output( to, format_coin_amount(ada_amount, network_id), title, br_code=ButtonRequestType.Other, chunkify=chunkify, ) async def confirm_sending_token(policy_id: bytes, token: messages.CardanoToken) -> None: assert token.amount is not None # _validate_token await confirm_properties( "confirm_token", TR.cardano__confirm_transaction, ( ( TR.cardano__asset_fingerprint, format_asset_fingerprint( policy_id=policy_id, asset_name_bytes=token.asset_name_bytes, ), ), (TR.cardano__amount_sent_decimals_unknown, format_amount(token.amount, 0)), ), br_code=BRT_Other, ) async def confirm_datum_hash(datum_hash: bytes) -> None: await confirm_properties( "confirm_datum_hash", TR.cardano__confirm_transaction, ( ( TR.cardano__datum_hash, bech32.encode(bech32.HRP_OUTPUT_DATUM_HASH, datum_hash), ), ), br_code=BRT_Other, ) async def confirm_inline_datum(first_chunk: bytes, inline_datum_size: int) -> None: await _confirm_data_chunk( "confirm_inline_datum", TR.cardano__inline_datum, first_chunk, inline_datum_size, ) async def confirm_reference_script( first_chunk: bytes, reference_script_size: int ) -> None: await _confirm_data_chunk( "confirm_reference_script", TR.cardano__reference_script, first_chunk, reference_script_size, ) async def _confirm_data_chunk( br_type: str, title: str, first_chunk: bytes, data_size: int ) -> None: MAX_DISPLAYED_SIZE = 56 displayed_bytes = first_chunk[:MAX_DISPLAYED_SIZE] bytes_optional_plural = "byte" if data_size == 1 else "bytes" props: list[tuple[str, bytes | None]] = [ ( f"{title} ({data_size} {bytes_optional_plural}):", displayed_bytes, ) ] if data_size > MAX_DISPLAYED_SIZE: props.append(("...", None)) await confirm_properties( br_type, title=TR.cardano__confirm_transaction, props=props, br_code=BRT_Other, ) async def show_credentials( payment_credential: Credential, stake_credential: Credential, ) -> None: intro_text = TR.words__address await _show_credential(payment_credential, intro_text, purpose="address") await _show_credential(stake_credential, intro_text, purpose="address") async def show_change_output_credentials( payment_credential: Credential, stake_credential: Credential, ) -> None: intro_text = TR.cardano__intro_text_change await _show_credential(payment_credential, intro_text, purpose="output") await _show_credential(stake_credential, intro_text, purpose="output") async def show_device_owned_output_credentials( payment_credential: Credential, stake_credential: Credential, show_both_credentials: bool, ) -> None: intro_text = TR.cardano__intro_text_owned_by_device await _show_credential(payment_credential, intro_text, purpose="output") if show_both_credentials: await _show_credential(stake_credential, intro_text, purpose="output") async def show_cvote_registration_payment_credentials( payment_credential: Credential, stake_credential: Credential, show_both_credentials: bool, show_payment_warning: bool, ) -> None: intro_text = TR.cardano__intro_text_registration_payment await _show_credential( payment_credential, intro_text, purpose="cvote_reg_payment_address" ) if show_both_credentials or show_payment_warning: extra_text = CVOTE_REWARD_ELIGIBILITY_WARNING if show_payment_warning else None await _show_credential( stake_credential, intro_text, purpose="cvote_reg_payment_address", extra_text=extra_text, ) async def _show_credential( credential: Credential, intro_text: str, purpose: Literal["address", "output", "cvote_reg_payment_address"], extra_text: str | None = None, ) -> None: title = { "address": f"{ADDRESS_TYPE_NAMES[credential.address_type]} address", "output": TR.cardano__confirm_transaction, "cvote_reg_payment_address": TR.cardano__confirm_transaction, }[purpose] props: list[PropertyType] = [] append = props.append # local_cache_attribute # Credential can be empty in case of enterprise address stake credential # and reward address payment credential. In that case we don't want to # show some of the "props". if credential.is_set(): credential_title = credential.get_title() # TODO: handle translation append( ( f"{intro_text} {credential.type_name} credential is a {credential_title}:", None, ) ) props.extend(credential.format()) if credential.is_unusual_path: append((None, TR.cardano__unusual_path)) if credential.is_mismatch: append((None, TR.cardano__credential_mismatch)) if credential.is_reward and purpose != "cvote_reg_payment_address": # for cvote registrations, this is handled by extra_text at the end append((TR.cardano__reward_address, None)) if credential.is_no_staking: append( ( f"{ADDRESS_TYPE_NAMES[credential.address_type]} {TR.cardano__address_no_staking}", None, ) ) if extra_text: append((extra_text, None)) if len(props) > 0: await confirm_properties( "confirm_credential", title, props, br_code=BRT_Other, ) async def warn_path(path: list[int], title: str) -> None: await layouts.confirm_path_warning(address_n_to_str(path), path_type=title) async def warn_tx_output_contains_tokens(is_collateral_return: bool = False) -> None: content = ( TR.cardano__collateral_output_contains_tokens if is_collateral_return else TR.cardano__transaction_output_contains_tokens ) await confirm_metadata( "confirm_tokens", TR.cardano__confirm_transaction, content, br_code=BRT_Other, ) async def warn_tx_contains_mint() -> None: await confirm_metadata( "confirm_tokens", TR.cardano__confirm_transaction, TR.cardano__transaction_contains_minting_or_burning, br_code=BRT_Other, ) async def warn_tx_output_no_datum() -> None: await confirm_metadata( "confirm_no_datum_hash", TR.cardano__confirm_transaction, TR.cardano__transaction_contains_script_address_no_datum, br_code=BRT_Other, ) async def warn_no_script_data_hash() -> None: await confirm_metadata( "confirm_no_script_data_hash", TR.cardano__confirm_transaction, TR.cardano__transaction_no_script_data_hash, br_code=BRT_Other, ) async def warn_no_collateral_inputs() -> None: await confirm_metadata( "confirm_no_collateral_inputs", TR.cardano__confirm_transaction, TR.cardano__transaction_no_collateral_input, br_code=BRT_Other, ) async def warn_unknown_total_collateral() -> None: await layouts.show_warning( "confirm_unknown_total_collateral", TR.cardano__unknown_collateral_amount, TR.cardano__check_all_items, br_code=BRT_Other, ) async def confirm_witness_request( witness_path: list[int], ) -> None: from . import seed if seed.is_multisig_path(witness_path): path_title = TR.cardano__multisig_path elif seed.is_minting_path(witness_path): path_title = TR.cardano__token_minting_path else: path_title = TR.cardano__path await layouts.confirm_text( "confirm_total", TR.cardano__confirm_transaction, address_n_to_str(witness_path), TR.cardano__sign_tx_path_template.format(path_title), BRT_Other, ) async def confirm_tx( fee: int, network_id: int, protocol_magic: int, ttl: int | None, validity_interval_start: int | None, total_collateral: int | None, is_network_id_verifiable: bool, tx_hash: bytes | None, ) -> None: props: list[PropertyType] = [ (TR.cardano__transaction_fee, format_coin_amount(fee, network_id)), ] append = props.append # local_cache_attribute if total_collateral is not None: append( ( TR.cardano__total_collateral, format_coin_amount(total_collateral, network_id), ) ) if is_network_id_verifiable: append( ( f"{TR.cardano__network} {protocol_magics.to_ui_string(protocol_magic)}", None, ) ) append( ( f"{TR.cardano__valid_since} {format_optional_int(validity_interval_start)}", None, ) ) append((f"{TR.cardano__ttl} {format_optional_int(ttl)}", None)) if tx_hash: append((TR.cardano__transaction_id, tx_hash)) await confirm_properties( "confirm_total", TR.cardano__confirm_transaction, props, hold=True, br_code=BRT_Other, ) async def confirm_certificate(certificate: messages.CardanoTxCertificate) -> None: # stake pool registration requires custom confirmation logic not covered # in this call assert certificate.type != CardanoCertificateType.STAKE_POOL_REGISTRATION props: list[PropertyType] = [ (TR.cardano__confirm, CERTIFICATE_TYPE_NAMES[certificate.type]), _format_stake_credential( certificate.path, certificate.script_hash, certificate.key_hash ), ] if certificate.type == CardanoCertificateType.STAKE_DELEGATION: assert certificate.pool is not None # validate_certificate props.append((TR.cardano__to_pool, format_stake_pool_id(certificate.pool))) await confirm_properties( "confirm_certificate", TR.cardano__confirm_transaction, props, br_code=BRT_Other, ) async def confirm_stake_pool_parameters( pool_parameters: messages.CardanoPoolParametersType, network_id: int, ) -> None: margin_percentage = ( 100.0 * pool_parameters.margin_numerator / pool_parameters.margin_denominator ) percentage_formatted = str(float(margin_percentage)).rstrip("0").rstrip(".") await confirm_properties( "confirm_pool_registration", TR.cardano__confirm_transaction, ( ( TR.cardano__stake_pool_registration_pool_id, format_stake_pool_id(pool_parameters.pool_id), ), (TR.cardano__pool_reward_account, pool_parameters.reward_account), ( f"{TR.cardano__pledge}: {format_coin_amount(pool_parameters.pledge, network_id)}\n" + f"{TR.cardano__cost}: {format_coin_amount(pool_parameters.cost, network_id)}\n" + f"{TR.cardano__margin}: {percentage_formatted}%", None, ), ), br_code=BRT_Other, ) async def confirm_stake_pool_owner( keychain: Keychain, owner: messages.CardanoPoolOwner, protocol_magic: int, network_id: int, ) -> None: from trezor import messages props: list[tuple[str, str | None]] = [] if owner.staking_key_path: props.append((TR.cardano__pool_owner, address_n_to_str(owner.staking_key_path))) props.append( ( addresses.derive_human_readable( keychain, messages.CardanoAddressParametersType( address_type=CardanoAddressType.REWARD, address_n=owner.staking_key_path, ), protocol_magic, network_id, ), None, ) ) else: assert owner.staking_key_hash is not None # validate_pool_owners props.append( ( TR.cardano__pool_owner, addresses.derive_human_readable( keychain, messages.CardanoAddressParametersType( address_type=CardanoAddressType.REWARD, staking_key_hash=owner.staking_key_hash, ), protocol_magic, network_id, ), ) ) await confirm_properties( "confirm_pool_owners", TR.cardano__confirm_transaction, props, br_code=BRT_Other, ) async def confirm_stake_pool_metadata( metadata: messages.CardanoPoolMetadataType | None, ) -> None: if metadata is None: await confirm_properties( "confirm_pool_metadata", TR.cardano__confirm_transaction, ((TR.cardano__anonymous_pool, None),), br_code=BRT_Other, ) return await confirm_properties( "confirm_pool_metadata", TR.cardano__confirm_transaction, ( (TR.cardano__pool_metadata_url, metadata.url), (TR.cardano__pool_metadata_hash, metadata.hash), ), br_code=BRT_Other, ) async def confirm_stake_pool_registration_final( protocol_magic: int, ttl: int | None, validity_interval_start: int | None, ) -> None: await confirm_properties( "confirm_pool_final", TR.cardano__confirm_transaction, ( (TR.cardano__confirm_signing_stake_pool, None), (TR.cardano__network, protocol_magics.to_ui_string(protocol_magic)), ( TR.cardano__valid_since, format_optional_int(validity_interval_start), ), (TR.cardano__ttl, format_optional_int(ttl)), ), hold=True, br_code=BRT_Other, ) async def confirm_withdrawal( withdrawal: messages.CardanoTxWithdrawal, address_bytes: bytes, network_id: int, ) -> None: address_type_name = ( TR.cardano__script_reward if withdrawal.script_hash else TR.cardano__reward ) address = addresses.encode_human_readable(address_bytes) props: list[PropertyType] = [ ( TR.cardano__withdrawal_for_address_template.format(address_type_name), address, ), ] if withdrawal.path: props.append( _format_stake_credential( withdrawal.path, withdrawal.script_hash, withdrawal.key_hash ) ) props.append( (f"{TR.words__amount}:", format_coin_amount(withdrawal.amount, network_id)) ) await confirm_properties( "confirm_withdrawal", TR.cardano__confirm_transaction, props, br_code=BRT_Other, ) def _format_stake_credential( path: list[int], script_hash: bytes | None, key_hash: bytes | None ) -> tuple[str, str]: from .helpers.paths import ADDRESS_INDEX_PATH_INDEX, RECOMMENDED_ADDRESS_INDEX if path: account_number = format_account_number(path) address_index = path[ADDRESS_INDEX_PATH_INDEX] if address_index == RECOMMENDED_ADDRESS_INDEX: return ( TR.cardano__for_account_template.format(account_number), address_n_to_str(path), ) return ( TR.cardano__for_account_and_index_template.format( account_number, address_index ), address_n_to_str(path), ) elif key_hash: return ( TR.cardano__for_key_hash, bech32.encode(bech32.HRP_STAKE_KEY_HASH, key_hash), ) elif script_hash: return ( TR.cardano__for_script, bech32.encode(bech32.HRP_SCRIPT_HASH, script_hash), ) else: # should be unreachable unless there's a bug in validation raise ValueError async def confirm_cvote_registration_delegation( public_key: str, weight: int, ) -> None: props: list[PropertyType] = [ (TR.cardano__vote_key_registration, None), (TR.cardano__delegating_to, public_key), ] if weight is not None: props.append((TR.cardano__weight, str(weight))) await confirm_properties( "confirm_cvote_registration_delegation", title=TR.cardano__confirm_transaction, props=props, br_code=ButtonRequestType.Other, ) async def confirm_cvote_registration_payment_address( payment_address: str, should_show_payment_warning: bool, ) -> None: props = [ (TR.cardano__vote_key_registration, None), (TR.cardano__rewards_go_to, payment_address), ] if should_show_payment_warning: props.append((CVOTE_REWARD_ELIGIBILITY_WARNING, None)) await confirm_properties( "confirm_cvote_registration_payment_address", title=TR.cardano__confirm_transaction, props=props, br_code=ButtonRequestType.Other, ) async def confirm_cvote_registration( vote_public_key: str | None, staking_path: list[int], nonce: int, voting_purpose: int | None, ) -> None: props: list[PropertyType] = [(TR.cardano__vote_key_registration, None)] if vote_public_key is not None: props.append((TR.cardano__vote_public_key, vote_public_key)) props.extend( [ ( f"{TR.cardano__staking_key_for_account} {format_account_number(staking_path)}:", address_n_to_str(staking_path), ), (TR.cardano__nonce, str(nonce)), ] ) if voting_purpose is not None: props.append( ( TR.cardano__voting_purpose, ( TR.cardano__catalyst if voting_purpose == 0 else f"{voting_purpose} ({TR.cardano__other})" ), ) ) await confirm_properties( "confirm_cvote_registration", title=TR.cardano__confirm_transaction, props=props, br_code=ButtonRequestType.Other, ) async def show_auxiliary_data_hash(auxiliary_data_hash: bytes) -> None: await confirm_properties( "confirm_auxiliary_data", TR.cardano__confirm_transaction, ((TR.cardano__auxiliary_data_hash, auxiliary_data_hash),), br_code=BRT_Other, ) async def confirm_token_minting(policy_id: bytes, token: messages.CardanoToken) -> None: assert token.mint_amount is not None # _validate_token await confirm_properties( "confirm_mint", TR.cardano__confirm_transaction, ( ( TR.cardano__asset_fingerprint, format_asset_fingerprint( policy_id, token.asset_name_bytes, ), ), ( ( TR.cardano__amount_minted_decimals_unknown if token.mint_amount >= 0 else TR.cardano__amount_burned_decimals_unknown ), format_amount(token.mint_amount, 0), ), ), br_code=BRT_Other, ) async def warn_tx_network_unverifiable() -> None: await confirm_metadata( "warning_no_outputs", TR.cardano__warning, TR.cardano__no_output_tx, br_code=BRT_Other, ) async def confirm_script_data_hash(script_data_hash: bytes) -> None: await confirm_properties( "confirm_script_data_hash", TR.cardano__confirm_transaction, ( ( TR.cardano__script_data_hash, bech32.encode(bech32.HRP_SCRIPT_DATA_HASH, script_data_hash), ), ), br_code=BRT_Other, ) async def confirm_collateral_input( collateral_input: messages.CardanoTxCollateralInput, ) -> None: await confirm_properties( "confirm_collateral_input", TR.cardano__confirm_transaction, ( (TR.cardano__collateral_input_id, collateral_input.prev_hash), ( TR.cardano__collateral_input_index, str(collateral_input.prev_index), ), ), br_code=BRT_Other, ) async def confirm_reference_input( reference_input: messages.CardanoTxReferenceInput, ) -> None: await confirm_properties( "confirm_reference_input", TR.cardano__confirm_transaction, ( (TR.cardano__reference_input_id, reference_input.prev_hash), (TR.cardano__reference_input_index, str(reference_input.prev_index)), ), br_code=BRT_Other, ) async def confirm_required_signer( required_signer: messages.CardanoTxRequiredSigner, ) -> None: assert ( required_signer.key_hash is not None or required_signer.key_path ) # _validate_required_signer formatted_signer = ( bech32.encode(bech32.HRP_REQUIRED_SIGNER_KEY_HASH, required_signer.key_hash) if required_signer.key_hash is not None else address_n_to_str(required_signer.key_path) ) await confirm_properties( "confirm_required_signer", TR.cardano__confirm_transaction, ((TR.cardano__required_signer, formatted_signer),), br_code=BRT_Other, ) async def show_cardano_address( address_parameters: messages.CardanoAddressParametersType, address: str, protocol_magic: int, chunkify: bool, ) -> None: CAT = CardanoAddressType # local_cache_global network_name = None if not protocol_magics.is_mainnet(protocol_magic): network_name = protocol_magics.to_ui_string(protocol_magic) path = None account = ADDRESS_TYPE_NAMES[address_parameters.address_type] if address_parameters.address_type in ( CAT.BYRON, CAT.BASE, CAT.BASE_KEY_SCRIPT, CAT.POINTER, CAT.ENTERPRISE, CAT.REWARD, ): if address_parameters.address_n: path = address_n_to_str(address_parameters.address_n) elif address_parameters.address_n_staking: path = address_n_to_str(address_parameters.address_n_staking) await layouts.show_address( address, path=path, account=account, network=network_name, chunkify=chunkify, )