Пример #1
0
async def confirm_output(
    ctx: wire.GenericContext,
    address: str,
    amount: str,
    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
    to_str: str = " to\n",  # TODO cleanup @ redesign
    to_paginated: bool = False,  # TODO cleanup @ redesign
    width: int = MONO_ADDR_PER_LINE,
    width_paginated: int = MONO_ADDR_PER_LINE - 1,
    br_code: ButtonRequestType = ButtonRequestType.ConfirmOutput,
    icon: str = ui.ICON_SEND,
) -> None:
    header_lines = to_str.count("\n") + int(subtitle is not None)
    if len(address) > (TEXT_MAX_LINES - header_lines) * width:
        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))
        content: ui.Layout = paginate_paragraphs(para, title, icon, ui.GREEN)
    else:
        text = Text(title, icon, 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.mono(*chunks_intersperse(address, width))
        content = Confirm(text)

    await raise_if_cancelled(interact(ctx, content, "confirm_output", br_code))
Пример #2
0
async def confirm_blob(
    ctx: wire.GenericContext,
    br_type: str,
    title: str,
    data: bytes | str,
    description: str | None = None,
    hold: bool = False,
    br_code: ButtonRequestType = ButtonRequestType.Other,
    icon: str = ui.ICON_SEND,  # TODO cleanup @ redesign
    icon_color: int = ui.GREEN,  # TODO cleanup @ redesign
    ask_pagination: bool = False,
) -> None:
    """Confirm data blob.

    Applicable for public keys, signatures, hashes. In general, any kind of
    data that is not human-readable, and can be wrapped at any character.

    For addresses, use `confirm_address`.

    Displays in monospace font. Paginates automatically.
    If data is provided as bytes or bytearray, it is converted to hex.
    """
    if isinstance(data, (bytes, bytearray)):
        data_str = hexlify(data).decode()
    else:
        data_str = data

    span = Span()
    lines = 0
    if description is not None:
        span.reset(description, 0, ui.NORMAL)
        lines += span.count_lines()
    data_lines = (len(data_str) + MONO_HEX_PER_LINE - 1) // MONO_HEX_PER_LINE
    lines += data_lines

    if lines <= TEXT_MAX_LINES:
        text = Text(title, icon, icon_color, new_lines=False)
        if description is not None:
            text.normal(description)
            text.br()

        # special case:
        if len(data_str) % 16 == 0:
            # sanity checks:
            # (a) we must not exceed MONO_HEX_PER_LINE
            assert MONO_HEX_PER_LINE > 16
            # (b) we must not increase number of lines
            assert (len(data_str) // 16) <= data_lines
            # the above holds true for MONO_HEX_PER_LINE == 18 and TEXT_MAX_LINES == 5
            per_line = 16

        else:
            per_line = MONO_HEX_PER_LINE
        text.mono(ui.FG, *chunks_intersperse(data_str, per_line))
        content: ui.Layout = HoldToConfirm(text) if hold else Confirm(text)
        return await raise_if_cancelled(
            interact(ctx, content, br_type, br_code))

    elif ask_pagination:
        para = [(ui.MONO, line)
                for line in chunks(data_str, MONO_HEX_PER_LINE - 2)]

        para_truncated = []
        if description is not None:
            para_truncated.append((ui.NORMAL, description))
        para_truncated.extend(para[:TEXT_MAX_LINES])

        return await _confirm_ask_pagination(ctx, br_type, title, para,
                                             para_truncated, br_code, icon,
                                             icon_color)

    else:
        para = []
        if description is not None:
            para.append((ui.NORMAL, description))
        para.extend((ui.MONO, line)
                    for line in chunks(data_str, MONO_HEX_PER_LINE - 2))

        paginated = paginate_paragraphs(
            para,
            title,
            icon,
            icon_color,
            confirm=HoldToConfirm if hold else Confirm)
        return await raise_if_cancelled(
            interact(ctx, paginated, br_type, br_code))