1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-06-07 08:38:46 +00:00

refactor(core): convert apps.eos to layouts

This commit is contained in:
Martin Milata 2021-03-11 16:38:51 +01:00 committed by matejcik
parent 3ffbae5d17
commit dd3b689ded
3 changed files with 228 additions and 208 deletions

View File

@ -1,14 +1,10 @@
from micropython import const
from ubinascii import hexlify from ubinascii import hexlify
from trezor import ui from trezor import ui
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
from trezor.ui.components.tt.scroll import Paginated from trezor.ui.layouts import confirm_properties
from trezor.ui.components.tt.text import Text
from trezor.utils import chunks
from .. import helpers from .. import helpers
from ..layout import require_confirm
if False: if False:
from trezor import wire from trezor import wire
@ -30,108 +26,105 @@ if False:
EosAuthorization, EosAuthorization,
) )
_LINE_LENGTH = const(17)
_LINE_PLACEHOLDER = "{:<" + str(_LINE_LENGTH) + "}"
_FIRST_PAGE = const(0)
_TWO_FIELDS_PER_PAGE = const(2)
_THREE_FIELDS_PER_PAGE = const(3)
_FOUR_FIELDS_PER_PAGE = const(4)
_FIVE_FIELDS_PER_PAGE = const(5)
async def _require_confirm_paginated(
ctx: wire.Context, header: str, fields: list[str], per_page: int
) -> None:
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)
async def confirm_action_buyram(ctx: wire.Context, msg: EosActionBuyRam) -> None: async def confirm_action_buyram(ctx: wire.Context, msg: EosActionBuyRam) -> None:
text = "Buy RAM" await confirm_properties(
fields = [] ctx,
fields.append("Payer:") "confirm_buyram",
fields.append(helpers.eos_name_to_string(msg.payer)) title="Buy RAM",
fields.append("Receiver:") props=[
fields.append(helpers.eos_name_to_string(msg.receiver)) ("Payer:", helpers.eos_name_to_string(msg.payer)),
fields.append("Amount:") ("Receiver:", helpers.eos_name_to_string(msg.receiver)),
fields.append(helpers.eos_asset_to_string(msg.quantity)) ("Amount:", helpers.eos_asset_to_string(msg.quantity)),
await _require_confirm_paginated(ctx, text, fields, _FOUR_FIELDS_PER_PAGE) ],
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_buyrambytes( async def confirm_action_buyrambytes(
ctx: wire.Context, msg: EosActionBuyRamBytes ctx: wire.Context, msg: EosActionBuyRamBytes
) -> None: ) -> None:
text = "Buy RAM" await confirm_properties(
fields = [] ctx,
fields.append("Payer:") "confirm_buyrambytes",
fields.append(helpers.eos_name_to_string(msg.payer)) title="Buy RAM",
fields.append("Receiver:") props=[
fields.append(helpers.eos_name_to_string(msg.receiver)) ("Payer:", helpers.eos_name_to_string(msg.payer)),
fields.append("Bytes:") ("Receiver:", helpers.eos_name_to_string(msg.receiver)),
fields.append(str(msg.bytes)) ("Bytes:", str(msg.bytes)),
await _require_confirm_paginated(ctx, text, fields, _FOUR_FIELDS_PER_PAGE) ],
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_delegate(ctx: wire.Context, msg: EosActionDelegate) -> None: async def confirm_action_delegate(ctx: wire.Context, msg: EosActionDelegate) -> None:
text = "Delegate" props = [
fields = [] ("Sender:", helpers.eos_name_to_string(msg.sender)),
fields.append("Sender:") ("Receiver:", helpers.eos_name_to_string(msg.receiver)),
fields.append(helpers.eos_name_to_string(msg.sender)) ("CPU:", helpers.eos_asset_to_string(msg.cpu_quantity)),
fields.append("Receiver:") ("NET:", helpers.eos_asset_to_string(msg.net_quantity)),
fields.append(helpers.eos_name_to_string(msg.receiver)) ]
fields.append("CPU:")
fields.append(helpers.eos_asset_to_string(msg.cpu_quantity))
fields.append("NET:")
fields.append(helpers.eos_asset_to_string(msg.net_quantity))
if msg.transfer: if msg.transfer:
fields.append("Transfer: Yes") props.append(("Transfer:", "Yes"))
fields.append("Receiver:") props.append(("Receiver:", helpers.eos_name_to_string(msg.receiver)))
fields.append(helpers.eos_name_to_string(msg.receiver))
else: else:
fields.append("Transfer: No") props.append(("Transfer:", "No"))
await _require_confirm_paginated(ctx, text, fields, _FOUR_FIELDS_PER_PAGE) await confirm_properties(
ctx,
"confirm_delegate",
title="Delegate",
props=props,
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_sellram(ctx: wire.Context, msg: EosActionSellRam) -> None: async def confirm_action_sellram(ctx: wire.Context, msg: EosActionSellRam) -> None:
text = "Sell RAM" await confirm_properties(
fields = [] ctx,
fields.append("Receiver:") "confirm_sellram",
fields.append(helpers.eos_name_to_string(msg.account)) title="Sell RAM",
fields.append("Bytes:") props=[
fields.append(str(msg.bytes)) ("Receiver:", helpers.eos_name_to_string(msg.account)),
await _require_confirm_paginated(ctx, text, fields, _TWO_FIELDS_PER_PAGE) ("Bytes:", str(msg.bytes)),
],
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_undelegate( async def confirm_action_undelegate(
ctx: wire.Context, msg: EosActionUndelegate ctx: wire.Context, msg: EosActionUndelegate
) -> None: ) -> None:
text = "Undelegate" await confirm_properties(
fields = [] ctx,
fields.append("Sender:") "confirm_undelegate",
fields.append(helpers.eos_name_to_string(msg.sender)) title="Undelegate",
fields.append("Receiver:") props=[
fields.append(helpers.eos_name_to_string(msg.receiver)) ("Sender:", helpers.eos_name_to_string(msg.sender)),
fields.append("CPU:") ("Receiver:", helpers.eos_name_to_string(msg.receiver)),
fields.append(helpers.eos_asset_to_string(msg.cpu_quantity)) ("CPU:", helpers.eos_asset_to_string(msg.cpu_quantity)),
fields.append("NET:") ("NET:", helpers.eos_asset_to_string(msg.net_quantity)),
fields.append(helpers.eos_asset_to_string(msg.net_quantity)) ],
await _require_confirm_paginated(ctx, text, fields, _FOUR_FIELDS_PER_PAGE) icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_refund(ctx: wire.Context, msg: EosActionRefund) -> None: async def confirm_action_refund(ctx: wire.Context, msg: EosActionRefund) -> None:
text = Text("Refund", ui.ICON_CONFIRM, icon_color=ui.GREEN) await confirm_properties(
text.normal("Owner:") ctx,
text.normal(helpers.eos_name_to_string(msg.owner)) "confirm_refund",
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) title="Refund",
props=[
("Owner:", helpers.eos_name_to_string(msg.owner)),
],
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_voteproducer( async def confirm_action_voteproducer(
@ -139,138 +132,175 @@ async def confirm_action_voteproducer(
) -> None: ) -> None:
if msg.proxy and not msg.producers: if msg.proxy and not msg.producers:
# PROXY # PROXY
text = Text("Vote for proxy", ui.ICON_CONFIRM, icon_color=ui.GREEN) await confirm_properties(
text.normal("Voter:") ctx,
text.normal(helpers.eos_name_to_string(msg.voter)) "confirm_voteproducer",
text.normal("Proxy:") title="Vote for proxy",
text.normal(helpers.eos_name_to_string(msg.proxy)) props=[
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) ("Voter:", helpers.eos_name_to_string(msg.voter)),
("Proxy:", helpers.eos_name_to_string(msg.proxy)),
],
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
elif msg.producers: elif msg.producers:
# PRODUCERS # PRODUCERS
text = "Vote for producers" await confirm_properties(
fields = [ ctx,
"{:2d}. {}".format(wi + 1, helpers.eos_name_to_string(producer)) "confirm_voteproducer",
for wi, producer in enumerate(msg.producers) title="Vote for producers",
] props=(
await _require_confirm_paginated(ctx, text, fields, _FIVE_FIELDS_PER_PAGE) ("{:2d}. {}".format(wi + 1, helpers.eos_name_to_string(producer)), None)
for wi, producer in enumerate(msg.producers)
),
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
else: else:
# Cancel vote # Cancel vote
text = Text("Cancel vote", ui.ICON_CONFIRM, icon_color=ui.GREEN) await confirm_properties(
text.normal("Voter:") ctx,
text.normal(helpers.eos_name_to_string(msg.voter)) "confirm_voteproducer",
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) title="Cancel vote",
props=[
("Voter:", helpers.eos_name_to_string(msg.voter)),
],
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_transfer( async def confirm_action_transfer(
ctx: wire.Context, msg: EosActionTransfer, account: str ctx: wire.Context, msg: EosActionTransfer, account: str
) -> None: ) -> None:
text = "Transfer" props = [
fields = [] ("From:", helpers.eos_name_to_string(msg.sender)),
fields.append("From:") ("To:", helpers.eos_name_to_string(msg.receiver)),
fields.append(helpers.eos_name_to_string(msg.sender)) ("Amount:", helpers.eos_asset_to_string(msg.quantity)),
fields.append("To:") ("Contract:", account),
fields.append(helpers.eos_name_to_string(msg.receiver)) ]
fields.append("Amount:")
fields.append(helpers.eos_asset_to_string(msg.quantity))
fields.append("Contract:")
fields.append(account)
if msg.memo is not None: if msg.memo is not None:
fields.append("Memo:") props.append(("Memo", msg.memo[:512]))
fields.extend(split_data(msg.memo[:512])) await confirm_properties(
ctx,
await _require_confirm_paginated(ctx, text, fields, _FOUR_FIELDS_PER_PAGE) "confirm_transfer",
title="Transfer",
props=props,
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_updateauth( async def confirm_action_updateauth(
ctx: wire.Context, msg: EosActionUpdateAuth ctx: wire.Context, msg: EosActionUpdateAuth
) -> None: ) -> None:
text = "Update Auth" props = [
fields = [] ("Account:", helpers.eos_name_to_string(msg.account)),
fields.append("Account:") ("Permission:", helpers.eos_name_to_string(msg.permission)),
fields.append(helpers.eos_name_to_string(msg.account)) ("Parent:", helpers.eos_name_to_string(msg.parent)),
fields.append("Permission:") ]
fields.append(helpers.eos_name_to_string(msg.permission)) props.extend(authorization_fields(msg.auth))
fields.append("Parent:") await confirm_properties(
fields.append(helpers.eos_name_to_string(msg.parent)) ctx,
fields.extend(authorization_fields(msg.auth)) "confirm_updateauth",
await _require_confirm_paginated(ctx, text, fields, _FOUR_FIELDS_PER_PAGE) title="Update Auth",
props=props,
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_deleteauth( async def confirm_action_deleteauth(
ctx: wire.Context, msg: EosActionDeleteAuth ctx: wire.Context, msg: EosActionDeleteAuth
) -> None: ) -> None:
text = Text("Delete auth", ui.ICON_CONFIRM, icon_color=ui.GREEN) await confirm_properties(
text.normal("Account:") ctx,
text.normal(helpers.eos_name_to_string(msg.account)) "confirm_deleteauth",
text.normal("Permission:") title="Delete Auth",
text.normal(helpers.eos_name_to_string(msg.permission)) props=[
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput) ("Account:", helpers.eos_name_to_string(msg.account)),
("Permission:", helpers.eos_name_to_string(msg.permission)),
],
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_linkauth(ctx: wire.Context, msg: EosActionLinkAuth) -> None: async def confirm_action_linkauth(ctx: wire.Context, msg: EosActionLinkAuth) -> None:
text = "Link Auth" await confirm_properties(
fields = [] ctx,
fields.append("Account:") "confirm_linkauth",
fields.append(helpers.eos_name_to_string(msg.account)) title="Link Auth",
fields.append("Code:") props=[
fields.append(helpers.eos_name_to_string(msg.code)) ("Account:", helpers.eos_name_to_string(msg.account)),
fields.append("Type:") ("Code:", helpers.eos_name_to_string(msg.code)),
fields.append(helpers.eos_name_to_string(msg.type)) ("Type:", helpers.eos_name_to_string(msg.type)),
fields.append("Requirement:") ("Requirement:", helpers.eos_name_to_string(msg.requirement)),
fields.append(helpers.eos_name_to_string(msg.requirement)) ],
await _require_confirm_paginated(ctx, text, fields, _FOUR_FIELDS_PER_PAGE) icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_unlinkauth( async def confirm_action_unlinkauth(
ctx: wire.Context, msg: EosActionUnlinkAuth ctx: wire.Context, msg: EosActionUnlinkAuth
) -> None: ) -> None:
text = "Unlink Auth" await confirm_properties(
fields = [] ctx,
fields.append("Account:") "confirm_unlinkauth",
fields.append(helpers.eos_name_to_string(msg.account)) title="Unlink Auth",
fields.append("Code:") props=[
fields.append(helpers.eos_name_to_string(msg.code)) ("Account:", helpers.eos_name_to_string(msg.account)),
fields.append("Type:") ("Code:", helpers.eos_name_to_string(msg.code)),
fields.append(helpers.eos_name_to_string(msg.type)) ("Type:", helpers.eos_name_to_string(msg.type)),
await _require_confirm_paginated(ctx, text, fields, _FOUR_FIELDS_PER_PAGE) ],
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_newaccount( async def confirm_action_newaccount(
ctx: wire.Context, msg: EosActionNewAccount ctx: wire.Context, msg: EosActionNewAccount
) -> None: ) -> None:
text = "New Account" props = [
fields = [] ("Creator:", helpers.eos_name_to_string(msg.creator)),
fields.append("Creator:") ("Name:", helpers.eos_name_to_string(msg.name)),
fields.append(helpers.eos_name_to_string(msg.creator)) ]
fields.append("Name:") props.extend(authorization_fields(msg.owner))
fields.append(helpers.eos_name_to_string(msg.name)) props.extend(authorization_fields(msg.active))
fields.extend(authorization_fields(msg.owner)) await confirm_properties(
fields.extend(authorization_fields(msg.active)) ctx,
await _require_confirm_paginated(ctx, text, fields, _FOUR_FIELDS_PER_PAGE) "confirm_newaccount",
title="New Account",
props=props,
icon=ui.ICON_CONFIRM,
br_code=ButtonRequestType.ConfirmOutput,
)
async def confirm_action_unknown( async def confirm_action_unknown(
ctx: wire.Context, action: EosActionCommon, checksum: bytes ctx: wire.Context, action: EosActionCommon, checksum: bytes
) -> None: ) -> None:
text = "Arbitrary data" await confirm_properties(
ctx,
"confirm_unknown",
title="Arbitrary data",
props=[
("Contract:", helpers.eos_name_to_string(action.account)),
("Action Name:", helpers.eos_name_to_string(action.name)),
("Checksum:", hexlify(checksum).decode("ascii")),
],
icon=ui.ICON_WIPE,
icon_color=ui.RED,
br_code=ButtonRequestType.ConfirmOutput,
)
def authorization_fields(auth: EosAuthorization) -> list[tuple[str, str | None]]:
fields = [] fields = []
fields.append("Contract:") fields.append(("Threshold:", str(auth.threshold)))
fields.append(helpers.eos_name_to_string(action.account))
fields.append("Action Name:")
fields.append(helpers.eos_name_to_string(action.name))
fields.append("Checksum: ")
fields.extend(split_data(hexlify(checksum).decode("ascii")))
await _require_confirm_paginated(ctx, text, fields, _FIVE_FIELDS_PER_PAGE)
def authorization_fields(auth: EosAuthorization) -> list[str]:
fields = []
fields.append("Threshold:")
fields.append(str(auth.threshold))
for i, key in enumerate(auth.keys): for i, key in enumerate(auth.keys):
_key = helpers.public_key_to_wif(bytes(key.key)) _key = helpers.public_key_to_wif(bytes(key.key))
@ -278,10 +308,9 @@ def authorization_fields(auth: EosAuthorization) -> list[str]:
header = "Key #{}:".format(i + 1) header = "Key #{}:".format(i + 1)
w_header = "Key #{} Weight:".format(i + 1) w_header = "Key #{} Weight:".format(i + 1)
fields.append(header)
fields += split_data(_key) fields.append((header, _key))
fields.append(w_header) fields.append((w_header, _weight))
fields.append(_weight)
for i, account in enumerate(auth.accounts): for i, account in enumerate(auth.accounts):
_account = helpers.eos_name_to_string(account.account.actor) _account = helpers.eos_name_to_string(account.account.actor)
@ -291,12 +320,9 @@ def authorization_fields(auth: EosAuthorization) -> list[str]:
p_header = "Acc Permission #{}:".format(i + 1) p_header = "Acc Permission #{}:".format(i + 1)
w_header = "Account #{} weight:".format(i + 1) w_header = "Account #{} weight:".format(i + 1)
fields.append(a_header) fields.append((a_header, _account))
fields.append(_account) fields.append((p_header, _permission))
fields.append(p_header) fields.append((w_header, str(account.weight)))
fields.append(_permission)
fields.append(w_header)
fields.append(str(account.weight))
for i, wait in enumerate(auth.waits): for i, wait in enumerate(auth.waits):
_wait = str(wait.wait_sec) _wait = str(wait.wait_sec)
@ -304,17 +330,7 @@ def authorization_fields(auth: EosAuthorization) -> list[str]:
header = "Delay #{}".format(i + 1) header = "Delay #{}".format(i + 1)
w_header = "Delay #{} weight:".format(i + 1) w_header = "Delay #{} weight:".format(i + 1)
fields.append(header) fields.append((header, "{} sec".format(_wait)))
fields.append("{} sec".format(_wait)) fields.append((w_header, _weight))
fields.append(w_header)
fields.append(_weight)
return fields return fields
def split_data(data: str) -> list[str]:
lines = []
while data:
lines.append("{} ".format(data[:_LINE_LENGTH]))
data = data[_LINE_LENGTH:]
return lines

View File

@ -1,19 +1,21 @@
from trezor import ui, wire from trezor import ui, wire
from trezor.enums import ButtonRequestType from trezor.enums import ButtonRequestType
from trezor.ui.components.tt.text import Text from trezor.strings import format_plural
from trezor.ui.layouts import confirm_action, show_pubkey
from apps.common.confirm import require_confirm
async def require_get_public_key(ctx: wire.Context, public_key: str) -> None: async def require_get_public_key(ctx: wire.Context, public_key: str) -> None:
text = Text("Confirm public key", ui.ICON_RECEIVE, ui.GREEN) await show_pubkey(ctx, public_key)
text.normal(public_key)
await require_confirm(ctx, text, ButtonRequestType.PublicKey)
async def require_sign_tx(ctx: wire.Context, num_actions: int) -> None: async def require_sign_tx(ctx: wire.Context, num_actions: int) -> None:
text = Text("Sign transaction", ui.ICON_SEND, ui.GREEN) await confirm_action(
text.normal("You are about") ctx,
text.normal("to sign {}".format(num_actions)) "confirm_tx",
text.normal("action(s).") title="Sign transaction",
await require_confirm(ctx, text, ButtonRequestType.SignTx) description="You are about to sign {}.",
description_param=format_plural("{count} {plural}", num_actions, "action"),
icon=ui.ICON_SEND,
icon_color=ui.GREEN,
br_code=ButtonRequestType.SignTx,
)

View File

@ -28,7 +28,9 @@ from ..common import MNEMONIC12
class TestMsgEosGetpublickey: class TestMsgEosGetpublickey:
@pytest.mark.setup_client(mnemonic=MNEMONIC12) @pytest.mark.setup_client(mnemonic=MNEMONIC12)
def test_eos_get_public_key(self, client): def test_eos_get_public_key(self, client):
public_key = get_public_key(client, parse_path("m/44'/194'/0'/0/0")) public_key = get_public_key(
client, parse_path("m/44'/194'/0'/0/0"), show_display=True
)
assert ( assert (
public_key.wif_public_key public_key.wif_public_key
== "EOS4u6Sfnzj4Sh2pEQnkXyZQJqH3PkKjGByDCbsqqmyq6PttM9KyB" == "EOS4u6Sfnzj4Sh2pEQnkXyZQJqH3PkKjGByDCbsqqmyq6PttM9KyB"