コード例 #1
0
ファイル: layout.py プロジェクト: romanz/trezor-firmware
async def _slip39_show_share_words(ctx, share_index, share_words):
    first, chunks, last = _slip39_split_share_into_pages(share_words)

    if share_index is None:
        header_title = "Recovery seed"
    else:
        header_title = "Recovery share #%s" % (share_index + 1)
    header_icon = ui.ICON_RESET
    pages = []  # ui page components
    shares_words_check = []  # check we display correct data

    # first page
    text = Text(header_title, header_icon)
    text.bold("Write down these")
    text.bold("%s words:" % len(share_words))
    text.br_half()
    for index, word in first:
        text.mono("%s. %s" % (index + 1, word))
        shares_words_check.append(word)
    pages.append(text)

    # middle pages
    for chunk in chunks:
        text = Text(header_title, header_icon)
        for index, word in chunk:
            text.mono("%s. %s" % (index + 1, word))
            shares_words_check.append(word)
        pages.append(text)

    # last page
    text = Text(header_title, header_icon)
    for index, word in last:
        text.mono("%s. %s" % (index + 1, word))
        shares_words_check.append(word)
    text.br_half()
    text.bold("I confirm that I wrote")
    text.bold("down all %s words." % len(share_words))
    pages.append(text)

    # pagination
    paginated = Paginated(pages)

    if __debug__:

        word_pages = [first] + chunks + [last]

        def export_displayed_words():
            # export currently displayed mnemonic words into debuglink
            debug.reset_current_words = [
                w for _, w in word_pages[paginated.page]
            ]

        paginated.on_change = export_displayed_words
        export_displayed_words()

    # make sure we display correct data
    utils.ensure(share_words == shares_words_check)

    # confirm the share
    await hold_to_confirm(ctx, paginated)  # TODO: customize the loader here
コード例 #2
0
async def show_address(
    ctx: wire.Context,
    address: str,
    address_type: EnumTypeCardanoAddressType,
    path: List[int],
    network: int = None,
) -> bool:
    """
    Custom show_address function is needed because cardano addresses don't
    fit on a single screen.
    """
    path_str = address_n_to_str(path)
    t1 = Text(path_str, ui.ICON_RECEIVE, ui.GREEN)
    if network is not None:
        t1.normal("%s network" % protocol_magics.to_ui_string(network))
    t1.normal("%s address" % ADDRESS_TYPE_NAMES[address_type])

    address_lines = list(chunks(address, 17))
    t1.bold(address_lines[0])
    t1.bold(address_lines[1])
    t1.bold(address_lines[2])

    pages = [t1] + _paginate_lines(address_lines, 3, path_str, ui.ICON_RECEIVE)

    return await confirm(
        ctx,
        Paginated(pages),
        code=ButtonRequestType.Address,
        cancel="QR",
        cancel_style=ButtonDefault,
    )
コード例 #3
0
async def require_confirm_transfer(ctx, msg: BinanceTransferMsg):
    def make_input_output_pages(msg: BinanceInputOutput, direction):
        pages = []
        for coin in msg.coins:
            coin_page = Text("Confirm " + direction,
                             ui.ICON_SEND,
                             icon_color=ui.GREEN)
            coin_page.bold(
                format_amount(coin.amount, helpers.DECIMALS) + " " +
                coin.denom)
            coin_page.normal("to")
            coin_page.mono(*split_address(msg.address))
            pages.append(coin_page)

        return pages

    pages = []
    for txinput in msg.inputs:
        pages.extend(make_input_output_pages(txinput, "input"))

    for txoutput in msg.outputs:
        pages.extend(make_input_output_pages(txoutput, "output"))

    return await hold_to_confirm(ctx, Paginated(pages),
                                 ButtonRequestType.ConfirmOutput)
コード例 #4
0
ファイル: layout.py プロジェクト: zhou-peter/autoSTM32
async def show_remaining_shares(
    ctx: wire.Context,
    groups: List[int, List[str]],  # remaining + list 3 words
    shares_remaining: List[int],
    group_threshold: int,
) -> None:
    pages = []
    for remaining, group in groups:
        if 0 < remaining < MAX_SHARE_COUNT:
            text = Text("Remaining Shares")
            if remaining > 1:
                text.bold("%s more shares starting" % remaining)
            else:
                text.bold("%s more share starting" % remaining)
            for word in group:
                text.normal(word)
            pages.append(text)
        elif (remaining == MAX_SHARE_COUNT
              and shares_remaining.count(0) < group_threshold):
            text = Text("Remaining Shares")
            groups_remaining = group_threshold - shares_remaining.count(0)
            if groups_remaining > 1:
                text.bold("%s more groups starting" % groups_remaining)
            elif groups_remaining > 0:
                text.bold("%s more group starting" % groups_remaining)
            for word in group:
                text.normal(word)
            pages.append(text)

    return await confirm(ctx, Paginated(pages), cancel=None)
コード例 #5
0
ファイル: layout.py プロジェクト: vhud/trezor-firmware
async def confirm_stake_pool_owners(
    ctx: wire.Context,
    keychain: seed.keychain,
    owners: List[CardanoPoolOwnerType],
    network_id: int,
) -> None:
    pages = []
    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:
            page.bold(address_n_to_str(owner.staking_key_path))
            page.normal(
                encode_human_readable_address(
                    pack_reward_address_bytes(
                        get_public_key_hash(keychain, owner.staking_key_path),
                        network_id,
                    )))
        else:
            page.bold(
                encode_human_readable_address(
                    pack_reward_address_bytes(owner.staking_key_hash,
                                              network_id)))

        pages.append(page)

    await require_confirm(ctx, Paginated(pages))
コード例 #6
0
async def show_remaining_shares(
    ctx: wire.GenericContext,
    groups: Iterable[Tuple[int, Tuple[str, ...]]],  # remaining + list 3 words
    shares_remaining: List[int],
    group_threshold: int,
) -> None:
    pages = []  # type: List[ui.Component]
    for remaining, group in groups:
        if 0 < remaining < MAX_SHARE_COUNT:
            text = Text("Remaining Shares")
            text.bold(
                strings.format_plural("{count} more {plural} starting",
                                      remaining, "share"))
            for word in group:
                text.normal(word)
            pages.append(text)
        elif (remaining == MAX_SHARE_COUNT
              and shares_remaining.count(0) < group_threshold):
            text = Text("Remaining Shares")
            groups_remaining = group_threshold - shares_remaining.count(0)
            text.bold(
                strings.format_plural("{count} more {plural} starting",
                                      groups_remaining, "group"))
            for word in group:
                text.normal(word)
            pages.append(text)
    await confirm(ctx, Paginated(pages), cancel=None)
コード例 #7
0
ファイル: layout.py プロジェクト: vhud/trezor-firmware
async def confirm_transaction(ctx, amount: int, fee: int, protocol_magic: int,
                              ttl: int, has_metadata: bool) -> None:
    pages = []

    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)
    page2.normal("Network:")
    page2.bold(protocol_magics.to_ui_string(protocol_magic))
    page2.normal("Transaction TTL:")
    page2.bold(str(ttl))
    pages.append(page2)

    if has_metadata:
        page3 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
        page3.normal("Transaction contains")
        page3.normal("metadata")
        pages.append(page3)

    await require_hold_to_confirm(ctx, Paginated(pages))
コード例 #8
0
async def show_warning_address_foreign_staking_key(
    ctx: wire.Context,
    account_path: List[int],
    staking_account_path: List[int],
    staking_key_hash: bytes,
) -> None:
    page1 = Text("Warning", ui.ICON_WRONG, ui.RED)
    page1.normal("Stake rights associated")
    page1.normal("with this address do")
    page1.normal("not match your")
    page1.normal("account %s:" % format_account_number(account_path))
    page1.bold(address_n_to_str(account_path))

    page2 = Text("Warning", ui.ICON_WRONG, ui.RED)
    if staking_account_path:
        page2.normal("Stake account %s:" %
                     format_account_number(staking_account_path))
        page2.bold(address_n_to_str(staking_account_path))
        page2.br_half()
    else:
        page2.normal("Staking key:")
        page2.bold(hexlify(staking_key_hash).decode())
    page2.normal("Continue?")

    await require_confirm(ctx, Paginated([page1, page2]))
コード例 #9
0
async def confirm_transaction(
    ctx,
    amount: int,
    fee: int,
    protocol_magic: int,
    ttl: Optional[int],
    validity_interval_start: Optional[int],
    has_metadata: bool,
    is_network_id_verifiable: bool,
) -> None:
    pages = []

    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:
        page2.normal("Network:")
        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)

    if has_metadata:
        page3 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
        page3.normal("Transaction contains")
        page3.normal("metadata")
        pages.append(page3)

    await require_hold_to_confirm(ctx, Paginated(pages))
コード例 #10
0
async def confirm_sending_token_hex(ctx: wire.Context, token: CardanoTokenType,
                                    token_number: int) -> None:
    page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    page1.bold("Asset #%s name (hex):" % (token_number))
    page1.mono(hexlify(token.asset_name_bytes).decode())
    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]))
コード例 #11
0
async def _require_confirm_paginated(ctx, header, fields, per_page):
    pages = []
    for page in chunks(fields, per_page):
        if header == "Arbitrary data":
            text = Text(header, ui.ICON_WIPE, ui.RED)
        else:
            text = Text(header, ui.ICON_CONFIRM, ui.GREEN)
        text.mono(*page)
        pages.append(text)
    await require_confirm(ctx, Paginated(pages),
                          ButtonRequestType.ConfirmOutput)
コード例 #12
0
async def _bip39_show_mnemonic(ctx, words: list):
    # split mnemonic words into pages
    PER_PAGE = const(4)
    words = list(enumerate(words))
    words = list(utils.chunks(words, PER_PAGE))

    # display the pages, with a confirmation dialog on the last one
    pages = [_get_mnemonic_page(page) for page in words]
    paginated = Paginated(pages)

    if __debug__:

        def export_displayed_words():
            # export currently displayed mnemonic words into debuglink
            debug.reset_current_words = [w for _, w in words[paginated.page]]

        paginated.on_change = export_displayed_words
        export_displayed_words()

    await hold_to_confirm(ctx, paginated, ButtonRequestType.ResetDevice)
コード例 #13
0
async def _require_confirm_properties(ctx, definition: NEMMosaicDefinition):
    # TODO: we should send a button request here
    pages = _get_mosaic_properties(definition)
    pages[-1] = Confirm(pages[-1])
    paginated = Paginated(pages)

    if __debug__:
        result = await ctx.wait(paginated, confirm_signal)
    else:
        result = await ctx.wait(paginated)
    if result is not CONFIRMED:
        raise wire.ActionCancelled("Action cancelled")
コード例 #14
0
ファイル: __init__.py プロジェクト: zhengger/trezor-firmware
async def confirm_transaction(ctx, amount, fee, network_name):
    t1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t1.normal("Total amount:")
    t1.bold(format_coin_amount(amount))
    t1.normal("including fee:")
    t1.bold(format_coin_amount(fee))

    t2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t2.normal("Network:")
    t2.bold(network_name)

    await require_hold_to_confirm(ctx, Paginated([t1, t2]))
コード例 #15
0
async def confirm_transaction(ctx, amount: int, fee: int, protocol_magic: int):
    t1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t1.normal("Transaction amount:")
    t1.bold(format_coin_amount(amount))
    t1.normal("Transaction fee:")
    t1.bold(format_coin_amount(fee))

    t2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t2.normal("Network:")
    t2.bold(protocol_magics.to_ui_string(protocol_magic))

    await require_hold_to_confirm(ctx, Paginated([t1, t2]))
コード例 #16
0
async def confirm_sending(ctx: wire.Context, amount: int, to: str):
    t1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t1.normal("Confirm sending:")
    t1.bold(format_coin_amount(amount))
    t1.normal("to")

    to_lines = list(chunks(to, 17))
    t1.bold(to_lines[0])

    pages = [t1] + _paginate_lines(to_lines, 1, "Confirm transaction", ui.ICON_SEND)

    await require_confirm(ctx, Paginated(pages))
コード例 #17
0
async def require_confirm_cancel(ctx, msg: BinanceCancelMsg):
    page1 = Text("Confirm cancel 1/2", ui.ICON_SEND, icon_color=ui.GREEN)
    page1.normal("Sender address:")
    page1.bold(msg.sender)
    page1.normal("Pair:")
    page1.bold(msg.symbol)

    page2 = Text("Confirm cancel 2/2", ui.ICON_SEND, icon_color=ui.GREEN)
    page2.normal("Order ID:")
    page2.bold(msg.refid)

    return await hold_to_confirm(ctx, Paginated([page1, page2]),
                                 ButtonRequestType.SignTx)
コード例 #18
0
ファイル: layout.py プロジェクト: vhud/trezor-firmware
async def show_address(
    ctx: wire.Context,
    address: str,
    address_type: EnumTypeCardanoAddressType,
    path: List[int],
    network: str = 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,
    )

    address_lines = list(chunks(address, 17))
    for address_line in address_lines[:lines_per_page -
                                      lines_used_on_first_page]:
        page1.bold(address_line)

    # append remaining pages containing the rest of the address
    pages = [page1] + _paginate_lines(
        address_lines,
        lines_per_page - lines_used_on_first_page,
        address_type_label,
        ui.ICON_RECEIVE,
        lines_per_page,
    )

    return await confirm(
        ctx,
        Paginated(pages),
        code=ButtonRequestType.Address,
        cancel="QR",
        cancel_style=ButtonDefault,
    )
コード例 #19
0
ファイル: layout.py プロジェクト: zcore-dev/trezor-firmware-1
async def show_xpub(ctx: wire.Context, xpub: str, desc: str, cancel: str) -> bool:
    pages = []  # type: List[ui.Component]
    for lines in chunks(list(chunks(xpub, 16)), 5):
        text = Text(desc, ui.ICON_RECEIVE, ui.GREEN)
        text.mono(*lines)
        pages.append(text)

    return await confirm(
        ctx,
        Paginated(pages),
        code=ButtonRequestType.PublicKey,
        cancel=cancel,
        cancel_style=ButtonDefault,
    )
コード例 #20
0
async def require_confirm_proposals(ctx, proposals):
    if len(proposals) > 1:
        title = "Submit proposals"
    else:
        title = "Submit proposal"

    pages = []
    for page, proposal in enumerate(proposals):
        text = Text(title, ui.ICON_SEND, icon_color=ui.PURPLE)
        text.bold("Proposal {}: ".format(page + 1))
        text.mono(*split_proposal(proposal))
        pages.append(text)
    paginated = Paginated(pages)

    await require_confirm(ctx, paginated, ButtonRequestType.SignTx)
コード例 #21
0
async def show_warning_tx_different_staking_account(
    ctx: wire.Context, staking_account_path: List[int], amount: int,
):
    t1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t1.normal("Change address staking")
    t1.normal("rights do not match")
    t1.normal("the current account.")

    t2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t2.normal("Staking account:")
    t2.bold(address_n_to_str(staking_account_path))
    t2.normal("Change amount:")
    t2.bold(format_coin_amount(amount))

    await require_confirm(ctx, Paginated([t1, t2]))
コード例 #22
0
async def show_warning_tx_staking_key_hash(
    ctx: wire.Context, staking_key_hash: bytes, amount: int,
):
    t1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t1.normal("Change address staking")
    t1.normal("rights do not match")
    t1.normal("the current account.")

    t2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t2.normal("Staking key hash:")
    t2.mono(*chunks(hexlify(staking_key_hash), 17))

    t3 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t3.normal("Change amount:")
    t3.bold(format_coin_amount(amount))

    await require_confirm(ctx, Paginated([t1, t2, t3]))
コード例 #23
0
async def confirm_certificate(ctx: wire.Context,
                              certificate: CardanoTxCertificateType) -> bool:
    pages = []

    t1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t1.normal("Confirm:")
    t1.bold(CERTIFICATE_TYPE_NAMES[certificate.type])
    t1.normal("for account:")
    t1.bold(address_n_to_str(to_account_path(certificate.path)))
    pages.append(t1)

    if certificate.type == CardanoCertificateType.STAKE_DELEGATION:
        t2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
        t2.normal("to pool:")
        t2.bold(hexlify(certificate.pool).decode())
        pages.append(t2)

    await require_confirm(ctx, Paginated(pages))
コード例 #24
0
async def show_warning_tx_pointer_address(
    ctx: wire.Context, pointer: CardanoBlockchainPointerType, amount: int,
):
    t1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t1.normal("Change address has a")
    t1.normal("pointer with staking")
    t1.normal("rights.")

    t2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t2.normal("Pointer:")
    t2.bold(
        "%s, %s, %s"
        % (pointer.block_index, pointer.tx_index, pointer.certificate_index)
    )
    t2.normal("Change amount:")
    t2.bold(format_coin_amount(amount))

    await require_confirm(ctx, Paginated([t1, t2]))
コード例 #25
0
def paginate_text(
    text: str,
    header: str,
    font: int = ui.NORMAL,
    header_icon: str = ui.ICON_DEFAULT,
    icon_color: int = ui.ORANGE_ICON,
    break_words: bool = False,
) -> Union[Text, Paginated]:
    span = Span(text, 0, font, break_words=break_words)
    if span.count_lines() <= TEXT_MAX_LINES:
        result = Text(
            header,
            header_icon=header_icon,
            icon_color=icon_color,
            new_lines=False,
        )
        result.content = [font, text]
        return result

    else:
        pages: List[ui.Component] = []
        span.reset(text, 0, font, break_words=break_words, line_width=204)
        while span.has_more_content():
            # advance to first line of the page
            span.next_line()
            page = Text(
                header,
                header_icon=header_icon,
                icon_color=icon_color,
                new_lines=False,
                content_offset=0,
                char_offset=span.start,
                line_width=204,
                render_page_overflow=False,
            )
            page.content = [font, text]
            pages.append(page)

            # roll over the remaining lines on the page
            for _ in range(TEXT_MAX_LINES - 1):
                span.next_line()

        return Paginated(pages)
コード例 #26
0
async def require_confirm_order(ctx, msg: BinanceOrderMsg):
    page1 = Text("Confirm order", ui.ICON_SEND, icon_color=ui.GREEN)
    page1.normal("Sender address:")
    page1.bold(msg.sender)

    page2 = Text("Confirm order", ui.ICON_SEND, icon_color=ui.GREEN)
    page2.normal("side:")
    if msg.side == BinanceOrderSide.BUY:
        page2.bold("buy")
    elif msg.side == BinanceOrderSide.SELL:
        page2.bold("sell")

    page3 = Text("Confirm order", ui.ICON_SEND, icon_color=ui.GREEN)
    page3.normal("Quantity:")
    page3.bold(str(msg.quantity))
    page3.normal("Price:")
    page3.bold(str(msg.price))

    return await hold_to_confirm(ctx, Paginated([page1, page2, page3]),
                                 ButtonRequestType.SignTx)
コード例 #27
0
ファイル: __init__.py プロジェクト: zhengger/trezor-firmware
async def confirm_sending(ctx, amount, to):
    to_lines = list(chunks(to, 17))

    t1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    t1.normal("Confirm sending:")
    t1.bold(format_coin_amount(amount))
    t1.normal("to:")
    t1.bold(to_lines[0])

    PER_PAGE = const(4)
    pages = [t1]
    if len(to_lines) > 1:
        to_pages = list(chunks(to_lines[1:], PER_PAGE))
        for page in to_pages:
            t = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
            for line in page:
                t.bold(line)
            pages.append(t)

    await require_confirm(ctx, Paginated(pages))
コード例 #28
0
async def confirm_sending(
    ctx: wire.Context,
    ada_amount: int,
    token_bundle: List[CardanoAssetGroupType],
    to: str,
) -> None:
    for token_group in token_bundle:
        await confirm_sending_token_group(ctx, token_group)

    page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    page1.normal("Confirm sending:")
    page1.bold(format_coin_amount(ada_amount))
    page1.normal("to")

    to_lines = list(chunks(to, 17))
    page1.bold(to_lines[0])

    pages = [page1] + _paginate_lines(to_lines, 1, "Confirm transaction",
                                      ui.ICON_SEND)

    await require_confirm(ctx, Paginated(pages))
コード例 #29
0
ファイル: layout.py プロジェクト: vhud/trezor-firmware
async def confirm_stake_pool_metadata(
    ctx: wire.Context,
    metadata: Optional[CardanoPoolMetadataType],
) -> None:

    if metadata is None:
        page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
        page1.normal("Pool has no metadata")
        page1.normal("(anonymous pool)")

        await require_confirm(ctx, page1)
        return

    page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    page1.normal("Pool metadata url:")
    page1.bold(metadata.url)

    page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    page2.normal("Pool metadata hash:")
    page2.bold(hexlify(metadata.hash).decode())

    await require_confirm(ctx, Paginated([page1, page2]))
コード例 #30
0
ファイル: layout.py プロジェクト: vhud/trezor-firmware
async def confirm_certificate(ctx: wire.Context,
                              certificate: CardanoTxCertificateType) -> None:
    # stake pool registration requires custom confirmation logic not covered
    # in this call
    assert certificate.type != CardanoCertificateType.STAKE_POOL_REGISTRATION

    pages = []

    page1 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
    page1.normal("Confirm:")
    page1.bold(CERTIFICATE_TYPE_NAMES[certificate.type])
    page1.normal("for account:")
    page1.bold(address_n_to_str(to_account_path(certificate.path)))
    pages.append(page1)

    if certificate.type == CardanoCertificateType.STAKE_DELEGATION:
        page2 = Text("Confirm transaction", ui.ICON_SEND, ui.GREEN)
        page2.normal("to pool:")
        page2.bold(hexlify(certificate.pool).decode())
        pages.append(page2)

    await require_confirm(ctx, Paginated(pages))