You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/src/apps/nem/transfer/layout.py

128 lines
5.0 KiB

from trezor import ui
from trezor.messages import (
ButtonRequestType,
NEMImportanceTransfer,
NEMImportanceTransferMode,
NEMMosaic,
NEMMosaicLevy,
NEMTransactionCommon,
NEMTransfer,
)
from trezor.ui.text import Text
from trezor.utils import format_amount, split_words
from ..helpers import (
NEM_LEVY_PERCENTILE_DIVISOR_ABSOLUTE,
NEM_MAX_DIVISIBILITY,
NEM_MOSAIC_AMOUNT_DIVISOR,
)
from ..layout import require_confirm_final, require_confirm_text, split_address
from ..mosaic.helpers import get_mosaic_definition, is_nem_xem_mosaic
from apps.common.confirm import require_confirm
async def ask_transfer(ctx, common: NEMTransactionCommon, transfer: NEMTransfer, payload: bytes, encrypted: bool):
if payload:
await _require_confirm_payload(ctx, transfer.payload, encrypted)
for mosaic in transfer.mosaics:
await ask_transfer_mosaic(ctx, common, transfer, mosaic)
await _require_confirm_transfer(ctx, transfer.recipient, _get_xem_amount(transfer))
await require_confirm_final(ctx, common.fee)
async def ask_transfer_mosaic(ctx, common: NEMTransactionCommon, transfer: NEMTransfer, mosaic: NEMMosaic):
if is_nem_xem_mosaic(mosaic.namespace, mosaic.mosaic):
return
definition = get_mosaic_definition(mosaic.namespace, mosaic.mosaic, common.network)
mosaic_quantity = mosaic.quantity * transfer.amount / NEM_MOSAIC_AMOUNT_DIVISOR
if definition:
msg = Text('Confirm mosaic', ui.ICON_SEND, icon_color=ui.GREEN)
msg.normal('Confirm transfer of')
msg.bold(format_amount(mosaic_quantity, definition['divisibility']) + definition['ticker'])
msg.normal('of')
msg.bold(definition['name'])
await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput)
if 'levy' in definition and 'fee' in definition:
levy_msg = _get_levy_msg(definition, mosaic_quantity, common.network)
msg = Text('Confirm mosaic', ui.ICON_SEND, icon_color=ui.GREEN)
msg.normal('Confirm mosaic', 'levy fee of')
msg.bold(levy_msg)
await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput)
else:
msg = Text('Confirm mosaic', ui.ICON_SEND, icon_color=ui.RED)
msg.bold('Unknown mosaic!')
msg.normal(*split_words('Divisibility and levy cannot be shown for unknown mosaics', 22))
await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput)
msg = Text('Confirm mosaic', ui.ICON_SEND, icon_color=ui.GREEN)
msg.normal('Confirm transfer of')
msg.bold('%s raw units' % mosaic_quantity)
msg.normal('of')
msg.bold('%s.%s' % (mosaic.namespace, mosaic.mosaic))
await require_confirm(ctx, msg, ButtonRequestType.ConfirmOutput)
def _get_xem_amount(transfer: NEMTransfer):
# if mosaics are empty the transfer.amount denotes the xem amount
if not transfer.mosaics:
return transfer.amount
# otherwise xem amount is taken from the nem xem mosaic if present
for mosaic in transfer.mosaics:
if is_nem_xem_mosaic(mosaic.namespace, mosaic.mosaic):
return mosaic.quantity * transfer.amount / NEM_MOSAIC_AMOUNT_DIVISOR
# if there are mosaics but do not include xem, 0 xem is sent
return 0
def _get_levy_msg(mosaic_definition, quantity: int, network: int) -> str:
levy_definition = get_mosaic_definition(
mosaic_definition['levy_namespace'],
mosaic_definition['levy_mosaic'],
network)
if mosaic_definition['levy'] == NEMMosaicLevy.MosaicLevy_Absolute:
levy_fee = mosaic_definition['fee']
else:
levy_fee = quantity * mosaic_definition['fee'] / NEM_LEVY_PERCENTILE_DIVISOR_ABSOLUTE
return format_amount(
levy_fee,
levy_definition['divisibility']
) + levy_definition['ticker']
async def ask_importance_transfer(ctx, common: NEMTransactionCommon, imp: NEMImportanceTransfer):
if imp.mode == NEMImportanceTransferMode.ImportanceTransfer_Activate:
m = 'Activate'
else:
m = 'Deactivate'
await require_confirm_text(ctx, m + ' remote harvesting?')
await require_confirm_final(ctx, common.fee)
async def _require_confirm_transfer(ctx, recipient, value):
text = Text('Confirm transfer', ui.ICON_SEND, icon_color=ui.GREEN)
text.bold('Send %s XEM' % format_amount(value, NEM_MAX_DIVISIBILITY))
text.normal('to')
text.mono(*split_address(recipient))
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
async def _require_confirm_payload(ctx, payload: bytes, encrypt=False):
payload = str(payload, 'utf-8')
if len(payload) > 48:
payload = payload[:48] + '..'
if encrypt:
text = Text('Confirm payload', ui.ICON_SEND, icon_color=ui.GREEN)
text.bold('Encrypted:')
text.normal(*split_words(payload, 22))
else:
text = Text('Confirm payload', ui.ICON_SEND, icon_color=ui.RED)
text.bold('Unencrypted:')
text.normal(*split_words(payload, 22))
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)