mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-16 03:18:09 +00:00
stellar: style and text api changes
This commit is contained in:
parent
b722fddc58
commit
b46ce034d6
@ -1,21 +1,26 @@
|
||||
from trezor.wire import register, protobuf_workflow
|
||||
from trezor.messages.wire_types import StellarGetAddress
|
||||
from trezor.messages.wire_types import StellarGetPublicKey
|
||||
from trezor.messages.wire_types import StellarSignTx
|
||||
from trezor.messages.MessageType import (
|
||||
StellarGetAddress,
|
||||
StellarGetPublicKey,
|
||||
StellarSignTx,
|
||||
)
|
||||
from trezor.wire import protobuf_workflow, register
|
||||
|
||||
|
||||
def dispatch_StellarGetAddress(*args, **kwargs):
|
||||
from .get_address import get_address
|
||||
|
||||
return get_address(*args, **kwargs)
|
||||
|
||||
|
||||
def dispatch_StellarGetPublicKey(*args, **kwargs):
|
||||
from .get_public_key import get_public_key
|
||||
|
||||
return get_public_key(*args, **kwargs)
|
||||
|
||||
|
||||
def dispatch_StellarSignTx(*args, **kwargs):
|
||||
from .sign_tx import sign_tx
|
||||
|
||||
return sign_tx(*args, **kwargs)
|
||||
|
||||
|
||||
|
@ -1,37 +1,38 @@
|
||||
from trezor.messages import wire_types
|
||||
from micropython import const
|
||||
|
||||
STELLAR_CURVE = 'ed25519'
|
||||
TX_TYPE = bytearray('\x00\x00\x00\x02')
|
||||
from trezor.messages import MessageType
|
||||
|
||||
STELLAR_CURVE = "ed25519"
|
||||
TX_TYPE = bytearray("\x00\x00\x00\x02")
|
||||
|
||||
# source: https://github.com/stellar/go/blob/3d2c1defe73dbfed00146ebe0e8d7e07ce4bb1b6/xdr/Stellar-transaction.x#L16
|
||||
# Inflation not supported see https://github.com/trezor/trezor-core/issues/202#issuecomment-393342089
|
||||
op_codes = {
|
||||
'StellarAccountMergeOp': const(8),
|
||||
'StellarAllowTrustOp': const(7),
|
||||
'StellarBumpSequenceOp': const(11),
|
||||
'StellarChangeTrustOp': const(6),
|
||||
'StellarCreateAccountOp': const(0),
|
||||
'StellarCreatePassiveOfferOp': const(4),
|
||||
'StellarManageDataOp': const(10),
|
||||
'StellarManageOfferOp': const(3),
|
||||
'StellarPathPaymentOp': const(2),
|
||||
'StellarPaymentOp': const(1),
|
||||
'StellarSetOptionsOp': const(5),
|
||||
"StellarAccountMergeOp": const(8),
|
||||
"StellarAllowTrustOp": const(7),
|
||||
"StellarBumpSequenceOp": const(11),
|
||||
"StellarChangeTrustOp": const(6),
|
||||
"StellarCreateAccountOp": const(0),
|
||||
"StellarCreatePassiveOfferOp": const(4),
|
||||
"StellarManageDataOp": const(10),
|
||||
"StellarManageOfferOp": const(3),
|
||||
"StellarPathPaymentOp": const(2),
|
||||
"StellarPaymentOp": const(1),
|
||||
"StellarSetOptionsOp": const(5),
|
||||
}
|
||||
|
||||
op_wire_types = [
|
||||
wire_types.StellarAccountMergeOp,
|
||||
wire_types.StellarAllowTrustOp,
|
||||
wire_types.StellarBumpSequenceOp,
|
||||
wire_types.StellarChangeTrustOp,
|
||||
wire_types.StellarCreateAccountOp,
|
||||
wire_types.StellarCreatePassiveOfferOp,
|
||||
wire_types.StellarManageDataOp,
|
||||
wire_types.StellarManageOfferOp,
|
||||
wire_types.StellarPathPaymentOp,
|
||||
wire_types.StellarPaymentOp,
|
||||
wire_types.StellarSetOptionsOp,
|
||||
MessageType.StellarAccountMergeOp,
|
||||
MessageType.StellarAllowTrustOp,
|
||||
MessageType.StellarBumpSequenceOp,
|
||||
MessageType.StellarChangeTrustOp,
|
||||
MessageType.StellarCreateAccountOp,
|
||||
MessageType.StellarCreatePassiveOfferOp,
|
||||
MessageType.StellarManageDataOp,
|
||||
MessageType.StellarManageOfferOp,
|
||||
MessageType.StellarPathPaymentOp,
|
||||
MessageType.StellarPaymentOp,
|
||||
MessageType.StellarSetOptionsOp,
|
||||
]
|
||||
|
||||
# https://github.com/stellar/go/blob/e0ffe19f58879d3c31e2976b97a5bf10e13a337b/xdr/xdr_generated.go#L584
|
||||
@ -44,8 +45,8 @@ ASSET_TYPE_ALPHANUM12 = const(2)
|
||||
AMOUNT_DIVISIBILITY = const(7)
|
||||
|
||||
# https://github.com/stellar/go/blob/master/network/main.go
|
||||
NETWORK_PASSPHRASE_PUBLIC = 'Public Global Stellar Network ; September 2015'
|
||||
NETWORK_PASSPHRASE_TESTNET = 'Test SDF Network ; September 2015'
|
||||
NETWORK_PASSPHRASE_PUBLIC = "Public Global Stellar Network ; September 2015"
|
||||
NETWORK_PASSPHRASE_TESTNET = "Test SDF Network ; September 2015"
|
||||
|
||||
# https://www.stellar.org/developers/guides/concepts/accounts.html#flags
|
||||
FLAG_AUTH_REQUIRED = const(1)
|
||||
@ -68,5 +69,5 @@ SIGN_TYPE_HASH = const(2)
|
||||
|
||||
def get_op_code(msg) -> int:
|
||||
if msg.__qualname__ not in op_codes:
|
||||
raise ValueError('Stellar: op code unknown')
|
||||
raise ValueError("Stellar: op code unknown")
|
||||
return op_codes[msg.__qualname__]
|
||||
|
@ -1,8 +1,9 @@
|
||||
from trezor.messages.StellarAddress import StellarAddress
|
||||
from trezor.messages.StellarGetAddress import StellarGetAddress
|
||||
|
||||
from apps.common import seed
|
||||
from apps.common.display_address import show_address, show_qr
|
||||
from apps.stellar import helpers
|
||||
from trezor.messages.StellarAddress import StellarAddress
|
||||
from trezor.messages.StellarGetAddress import StellarGetAddress
|
||||
|
||||
|
||||
async def get_address(ctx, msg: StellarGetAddress):
|
||||
|
@ -1,13 +1,15 @@
|
||||
from ubinascii import hexlify
|
||||
|
||||
from trezor import ui
|
||||
from trezor.messages import ButtonRequestType
|
||||
from trezor.messages.StellarGetPublicKey import StellarGetPublicKey
|
||||
from trezor.messages.StellarPublicKey import StellarPublicKey
|
||||
from trezor.ui.text import Text
|
||||
|
||||
from apps.common import seed
|
||||
from apps.common.confirm import confirm
|
||||
from apps.common.display_address import split_address
|
||||
from apps.stellar import helpers
|
||||
from trezor import ui
|
||||
from trezor.messages.StellarPublicKey import StellarPublicKey
|
||||
from trezor.messages.StellarGetPublicKey import StellarGetPublicKey
|
||||
from trezor.messages import ButtonRequestType
|
||||
from trezor.ui.text import Text
|
||||
from ubinascii import hexlify
|
||||
|
||||
|
||||
async def get_public_key(ctx, msg: StellarGetPublicKey):
|
||||
@ -24,13 +26,16 @@ async def get_public_key(ctx, msg: StellarGetPublicKey):
|
||||
|
||||
async def _show(ctx, pubkey: bytes):
|
||||
lines = split_address(hexlify(pubkey))
|
||||
content = Text('Export Stellar ID', ui.ICON_RECEIVE,
|
||||
ui.NORMAL, 'Share public account ID?', # todo only two lines are displayed
|
||||
ui.MONO, *lines,
|
||||
icon_color=ui.GREEN)
|
||||
content = Text(
|
||||
"Export Stellar ID",
|
||||
ui.ICON_RECEIVE,
|
||||
ui.NORMAL,
|
||||
"Share public account ID?", # todo only two lines are displayed
|
||||
ui.MONO,
|
||||
*lines,
|
||||
icon_color=ui.GREEN
|
||||
)
|
||||
|
||||
return await confirm(
|
||||
ctx,
|
||||
content,
|
||||
code=ButtonRequestType.Address,
|
||||
cancel_style=ui.BTN_KEY)
|
||||
ctx, content, code=ButtonRequestType.Address, cancel_style=ui.BTN_KEY
|
||||
)
|
||||
|
@ -1,8 +1,9 @@
|
||||
from trezor.crypto import base32
|
||||
from trezor.wire import ProcessError
|
||||
import ustruct
|
||||
|
||||
STELLAR_CURVE = 'ed25519'
|
||||
from trezor.crypto import base32
|
||||
from trezor.wire import ProcessError
|
||||
|
||||
STELLAR_CURVE = "ed25519"
|
||||
|
||||
|
||||
def public_key_from_address(address: str) -> bytes:
|
||||
@ -27,7 +28,7 @@ def address_from_public_key(pubkey: bytes):
|
||||
|
||||
def _crc16_checksum_verify(data: bytes, checksum: bytes):
|
||||
if _crc16_checksum(data) != checksum:
|
||||
raise ProcessError('Invalid address checksum')
|
||||
raise ProcessError("Invalid address checksum")
|
||||
|
||||
|
||||
def _crc16_checksum(data: bytes) -> bytes:
|
||||
@ -42,8 +43,8 @@ def _crc16_checksum(data: bytes) -> bytes:
|
||||
|
||||
for byte in data:
|
||||
for i in range(8):
|
||||
bit = ((byte >> (7 - i) & 1) == 1)
|
||||
c15 = ((crc >> 15 & 1) == 1)
|
||||
bit = (byte >> (7 - i) & 1) == 1
|
||||
c15 = (crc >> 15 & 1) == 1
|
||||
crc <<= 1
|
||||
if c15 ^ bit:
|
||||
crc ^= polynomial
|
||||
|
@ -1,63 +1,59 @@
|
||||
from apps.common.confirm import require_confirm, require_hold_to_confirm
|
||||
from apps.stellar import consts
|
||||
from trezor import ui
|
||||
from trezor import ui, utils
|
||||
from trezor.messages import ButtonRequestType
|
||||
from trezor.ui.text import Text
|
||||
from trezor import utils
|
||||
|
||||
from apps.common.confirm import require_confirm, require_hold_to_confirm
|
||||
from apps.stellar import consts
|
||||
|
||||
|
||||
async def require_confirm_init(ctx, address: str, network_passphrase: str):
|
||||
content = Text('Confirm Stellar', ui.ICON_SEND,
|
||||
ui.NORMAL, 'Initialize singing with',
|
||||
ui.MONO, *split(address),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm Stellar", ui.ICON_SEND, icon_color=ui.GREEN)
|
||||
text.normal("Initialize singing with")
|
||||
text.mono(*split(address))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
network = get_network_warning(network_passphrase)
|
||||
if network:
|
||||
content = Text('Confirm network', ui.ICON_CONFIRM,
|
||||
ui.NORMAL, 'Transaction is on',
|
||||
ui.BOLD, network,
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm network", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.normal("Transaction is on")
|
||||
text.bold(network)
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
|
||||
|
||||
async def require_confirm_memo(ctx, memo_type: int, memo_text: str):
|
||||
if memo_type == consts.MEMO_TYPE_TEXT:
|
||||
title = 'Memo (TEXT)'
|
||||
title = "Memo (TEXT)"
|
||||
elif memo_type == consts.MEMO_TYPE_ID:
|
||||
title = 'Memo (ID)'
|
||||
title = "Memo (ID)"
|
||||
elif memo_type == consts.MEMO_TYPE_HASH:
|
||||
title = 'Memo (HASH)'
|
||||
title = "Memo (HASH)"
|
||||
elif memo_type == consts.MEMO_TYPE_RETURN:
|
||||
title = 'Memo (RETURN)'
|
||||
title = "Memo (RETURN)"
|
||||
else: # MEMO_TYPE_NONE
|
||||
title = 'No memo set!' # todo format this as ui.NORMAL not MONO
|
||||
memo_text = 'Important: Many exchanges require a memo when depositing'
|
||||
content = Text('Confirm memo', ui.ICON_CONFIRM,
|
||||
ui.BOLD, title,
|
||||
ui.MONO, *split(memo_text),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
title = "No memo set!" # todo format this as ui.NORMAL not MONO
|
||||
memo_text = "Important: Many exchanges require a memo when depositing"
|
||||
text = Text("Confirm memo", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold(title)
|
||||
text.mono(*split(memo_text))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
|
||||
|
||||
async def require_confirm_final(ctx, fee: int, num_operations: int):
|
||||
op_str = str(num_operations) + ' operation'
|
||||
op_str = str(num_operations) + " operation"
|
||||
if num_operations > 1:
|
||||
op_str += 's'
|
||||
content = Text('Final confirm', ui.ICON_SEND,
|
||||
ui.NORMAL, 'Sign this transaction',
|
||||
ui.NORMAL, 'made up of ' + op_str,
|
||||
ui.BOLD, 'and pay ' + format_amount(fee),
|
||||
ui.NORMAL, 'for fee?',
|
||||
icon_color=ui.GREEN)
|
||||
op_str += "s"
|
||||
text = Text("Final confirm", ui.ICON_SEND, icon_color=ui.GREEN)
|
||||
text.normal("Sign this transaction")
|
||||
text.normal("made up of " + op_str)
|
||||
text.bold("and pay " + format_amount(fee))
|
||||
text.normal("for fee?")
|
||||
# we use SignTx, not ConfirmOutput, for compatibility with T1
|
||||
await require_hold_to_confirm(ctx, content, ButtonRequestType.SignTx)
|
||||
await require_hold_to_confirm(ctx, text, ButtonRequestType.SignTx)
|
||||
|
||||
|
||||
def format_amount(amount: int, ticker=True) -> str:
|
||||
t = ''
|
||||
t = ""
|
||||
if ticker:
|
||||
t = ' XLM'
|
||||
t = " XLM"
|
||||
return utils.format_amount(amount, consts.AMOUNT_DIVISIBILITY) + t
|
||||
|
||||
|
||||
@ -70,13 +66,13 @@ def split(text):
|
||||
def trim(payload: str, length: int, dots=True) -> str:
|
||||
if len(payload) > length:
|
||||
if dots:
|
||||
return payload[:length - 2] + '..'
|
||||
return payload[:length - 2]
|
||||
return payload[: length - 2] + ".."
|
||||
return payload[: length - 2]
|
||||
return payload
|
||||
|
||||
|
||||
# todo merge with nem
|
||||
def trim_to_rows(payload: str, rows: int=1) -> str:
|
||||
def trim_to_rows(payload: str, rows: int = 1) -> str:
|
||||
return trim(payload, rows * 17)
|
||||
|
||||
|
||||
@ -84,5 +80,5 @@ def get_network_warning(network_passphrase: str):
|
||||
if network_passphrase == consts.NETWORK_PASSPHRASE_PUBLIC:
|
||||
return None
|
||||
if network_passphrase == consts.NETWORK_PASSPHRASE_TESTNET:
|
||||
return 'testnet network'
|
||||
return 'private network'
|
||||
return "testnet network"
|
||||
return "private network"
|
||||
|
@ -1,7 +1,5 @@
|
||||
from apps.stellar.operations import serialize
|
||||
from apps.stellar.operations import layout
|
||||
from apps.stellar import consts
|
||||
from apps.stellar import writers
|
||||
from apps.stellar import consts, writers
|
||||
from apps.stellar.operations import layout, serialize
|
||||
|
||||
|
||||
async def operation(ctx, w, op):
|
||||
@ -43,4 +41,4 @@ async def operation(ctx, w, op):
|
||||
await layout.confirm_set_options_op(ctx, op)
|
||||
serialize.serialize_set_options_op(w, op)
|
||||
else:
|
||||
raise ValueError('serialize.Stellar: unknown operation')
|
||||
raise ValueError("serialize.Stellar: unknown operation")
|
||||
|
@ -1,10 +1,9 @@
|
||||
from apps.stellar.layout import split, format_amount, ui, trim_to_rows, require_confirm
|
||||
from apps.stellar import consts
|
||||
from ubinascii import hexlify
|
||||
|
||||
from trezor.messages import ButtonRequestType
|
||||
from trezor.ui.text import Text
|
||||
from trezor.messages.StellarAccountMergeOp import StellarAccountMergeOp
|
||||
from trezor.messages.StellarAssetType import StellarAssetType
|
||||
from trezor.messages.StellarAllowTrustOp import StellarAllowTrustOp
|
||||
from trezor.messages.StellarAssetType import StellarAssetType
|
||||
from trezor.messages.StellarBumpSequenceOp import StellarBumpSequenceOp
|
||||
from trezor.messages.StellarChangeTrustOp import StellarChangeTrustOp
|
||||
from trezor.messages.StellarCreateAccountOp import StellarCreateAccountOp
|
||||
@ -14,252 +13,238 @@ from trezor.messages.StellarManageOfferOp import StellarManageOfferOp
|
||||
from trezor.messages.StellarPathPaymentOp import StellarPathPaymentOp
|
||||
from trezor.messages.StellarPaymentOp import StellarPaymentOp
|
||||
from trezor.messages.StellarSetOptionsOp import StellarSetOptionsOp
|
||||
from trezor.ui.text import Text
|
||||
from trezor.wire import ProcessError
|
||||
from ubinascii import hexlify
|
||||
|
||||
from apps.stellar import consts
|
||||
from apps.stellar.layout import format_amount, require_confirm, split, trim_to_rows, ui
|
||||
|
||||
|
||||
async def confirm_source_account(ctx, source_account: bytes):
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Source account:',
|
||||
ui.MONO, *split(source_account),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Source account:")
|
||||
text.mono(*split(source_account))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
|
||||
|
||||
async def confirm_allow_trust_op(ctx, op: StellarAllowTrustOp):
|
||||
if op.is_authorized:
|
||||
text = 'Allow Trust'
|
||||
text = "Allow Trust"
|
||||
else:
|
||||
text = 'Revoke Trust'
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, text,
|
||||
ui.NORMAL, 'of %s by:' % op.asset_code,
|
||||
ui.MONO, *split(trim_to_rows(op.trusted_account, 3)),
|
||||
icon_color=ui.GREEN)
|
||||
text = "Revoke Trust"
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold(text)
|
||||
text.normal("of %s by:" % op.asset_code)
|
||||
text.mono(*split(trim_to_rows(op.trusted_account, 3)))
|
||||
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
|
||||
|
||||
async def confirm_account_merge_op(ctx, op: StellarAccountMergeOp):
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Account Merge',
|
||||
ui.NORMAL, 'All XLM will be sent to:',
|
||||
ui.MONO, *split(trim_to_rows(op.destination_account, 3)),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Account Merge")
|
||||
text.normal("All XLM will be sent to:")
|
||||
text.mono(*split(trim_to_rows(op.destination_account, 3)))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
|
||||
|
||||
async def confirm_bump_sequence_op(ctx, op: StellarBumpSequenceOp):
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Bump Sequence',
|
||||
ui.NORMAL, 'Set sequence to',
|
||||
ui.MONO, str(op.bump_to),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Bump Sequence")
|
||||
text.normal("Set sequence to")
|
||||
text.mono(str(op.bump_to))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
|
||||
|
||||
async def confirm_change_trust_op(ctx, op: StellarChangeTrustOp):
|
||||
if op.limit == 0:
|
||||
text = 'Delete Trust'
|
||||
text = "Delete Trust"
|
||||
else:
|
||||
text = 'Add Trust'
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, text,
|
||||
ui.NORMAL, 'Asset: %s' % op.asset.code,
|
||||
ui.NORMAL, 'Amount: %s' % format_amount(op.limit, ticker=False),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = "Add Trust"
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold(text)
|
||||
text.normal("Asset: %s" % op.asset.code)
|
||||
text.normal("Amount: %s" % format_amount(op.limit, ticker=False))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
await confirm_asset_issuer(ctx, op.asset)
|
||||
|
||||
|
||||
async def confirm_create_account_op(ctx, op: StellarCreateAccountOp):
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Create Account',
|
||||
ui.NORMAL, 'with %s' % format_amount(op.starting_balance),
|
||||
ui.MONO, *split(trim_to_rows(op.new_account, 3)),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Create Account")
|
||||
text.normal("with %s" % format_amount(op.starting_balance))
|
||||
text.mono(*split(trim_to_rows(op.new_account, 3)))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
|
||||
|
||||
async def confirm_create_passive_offer_op(ctx, op: StellarCreatePassiveOfferOp):
|
||||
if op.amount == 0:
|
||||
text = 'Delete Passive Offer'
|
||||
text = "Delete Passive Offer"
|
||||
else:
|
||||
text = 'New Passive Offer'
|
||||
text = "New Passive Offer"
|
||||
await _confirm_offer(ctx, text, op)
|
||||
|
||||
|
||||
async def confirm_manage_offer_op(ctx, op: StellarManageOfferOp):
|
||||
if op.offer_id == 0:
|
||||
text = 'New Offer'
|
||||
text = "New Offer"
|
||||
else:
|
||||
if op.amount == 0:
|
||||
text = 'Delete'
|
||||
text = "Delete"
|
||||
else:
|
||||
text = 'Update'
|
||||
text += ' #%d' % op.offer_id
|
||||
text = "Update"
|
||||
text += " #%d" % op.offer_id
|
||||
await _confirm_offer(ctx, text, op)
|
||||
|
||||
|
||||
async def _confirm_offer(ctx, text, op):
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, text,
|
||||
ui.NORMAL, 'Sell %s %s' % (format_amount(op.amount, ticker=False), op.selling_asset.code),
|
||||
ui.NORMAL, 'For %f' % (op.price_n / op.price_d),
|
||||
ui.NORMAL, 'Per %s' % format_asset_code(op.buying_asset),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold(text)
|
||||
text.normal(
|
||||
"Sell %s %s" % (format_amount(op.amount, ticker=False), op.selling_asset.code)
|
||||
)
|
||||
text.normal("For %f" % (op.price_n / op.price_d))
|
||||
text.normal("Per %s" % format_asset_code(op.buying_asset))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
await confirm_asset_issuer(ctx, op.selling_asset)
|
||||
await confirm_asset_issuer(ctx, op.buying_asset)
|
||||
|
||||
|
||||
async def confirm_manage_data_op(ctx, op: StellarManageDataOp):
|
||||
from trezor.crypto.hashlib import sha256
|
||||
|
||||
if op.value:
|
||||
title = 'Set'
|
||||
title = "Set"
|
||||
else:
|
||||
title = 'Clear'
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, '%s data value key' % title,
|
||||
ui.MONO, *split(op.key),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
title = "Clear"
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("%s data value key" % title)
|
||||
text.mono(*split(op.key))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
if op.value:
|
||||
digest = sha256(op.value).digest()
|
||||
digest_str = hexlify(digest).decode()
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Value (SHA-256):',
|
||||
ui.MONO, *split(digest_str),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Value (SHA-256):")
|
||||
text.mono(*split(digest_str))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
|
||||
|
||||
async def confirm_path_payment_op(ctx, op: StellarPathPaymentOp):
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Path Pay %s' % format_amount(op.destination_amount, ticker=False),
|
||||
ui.BOLD, '%s to:' % format_asset_code(op.destination_asset),
|
||||
ui.MONO, *split(trim_to_rows(op.destination_account, 3)),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Path Pay %s" % format_amount(op.destination_amount, ticker=False))
|
||||
text.bold("%s to:" % format_asset_code(op.destination_asset))
|
||||
text.mono(*split(trim_to_rows(op.destination_account, 3)))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
await confirm_asset_issuer(ctx, op.destination_asset)
|
||||
# confirm what the sender is using to pay
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.NORMAL, 'Pay using',
|
||||
ui.BOLD, format_amount(op.send_max, ticker=False),
|
||||
ui.BOLD, format_asset_code(op.send_asset),
|
||||
ui.NORMAL, 'This amount is debited',
|
||||
ui.NORMAL, 'from your account.',
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.normal("Pay using")
|
||||
text.bold(format_amount(op.send_max, ticker=False))
|
||||
text.bold(format_asset_code(op.send_asset))
|
||||
text.normal("This amount is debited")
|
||||
text.normal("from your account.")
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
await confirm_asset_issuer(ctx, op.send_asset)
|
||||
|
||||
|
||||
async def confirm_payment_op(ctx, op: StellarPaymentOp):
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Pay %s' % format_amount(op.amount, ticker=False),
|
||||
ui.BOLD, '%s to:' % format_asset_code(op.asset),
|
||||
ui.MONO, *split(trim_to_rows(op.destination_account, 3)),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Pay %s" % format_amount(op.amount, ticker=False))
|
||||
text.bold("%s to:" % format_asset_code(op.asset))
|
||||
text.mono(*split(trim_to_rows(op.destination_account, 3)))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
await confirm_asset_issuer(ctx, op.asset)
|
||||
|
||||
|
||||
async def confirm_set_options_op(ctx, op: StellarSetOptionsOp):
|
||||
if op.inflation_destination_account:
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Set Inflation Destination',
|
||||
ui.MONO, *split(op.inflation_destination_account),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Set Inflation Destination")
|
||||
text.mono(*split(op.inflation_destination_account))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
if op.clear_flags:
|
||||
text = _format_flags(op.clear_flags)
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Clear Flags',
|
||||
ui.MONO, *text,
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Clear Flags")
|
||||
text.mono(*text)
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
if op.set_flags:
|
||||
text = _format_flags(op.set_flags)
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Set Flags',
|
||||
ui.MONO, *text,
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Set Flags")
|
||||
text.mono(*text)
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
thresholds = _format_thresholds(op)
|
||||
if thresholds:
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Account Thresholds',
|
||||
ui.MONO, *thresholds,
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Account Thresholds")
|
||||
text.mono(*thresholds)
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
if op.home_domain:
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, 'Home Domain',
|
||||
ui.MONO, *split(op.home_domain),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("Home Domain")
|
||||
text.mono(*split(op.home_domain))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
if op.signer_type is not None:
|
||||
if op.signer_weight > 0:
|
||||
text = 'Add Signer (%s)'
|
||||
text = "Add Signer (%s)"
|
||||
else:
|
||||
text = 'Remove Signer (%s)'
|
||||
text = "Remove Signer (%s)"
|
||||
if op.signer_type == consts.SIGN_TYPE_ACCOUNT:
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, text % 'acc',
|
||||
ui.MONO, *split(op.signer_key),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold(text % "acc")
|
||||
text.mono(*split(op.signer_key))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
elif op.signer_type in (consts.SIGN_TYPE_PRE_AUTH, consts.SIGN_TYPE_HASH):
|
||||
if op.signer_type == consts.SIGN_TYPE_PRE_AUTH:
|
||||
signer_type = 'auth'
|
||||
signer_type = "auth"
|
||||
else:
|
||||
signer_type = 'hash'
|
||||
content = Text('Confirm operation', ui.ICON_CONFIRM,
|
||||
ui.BOLD, text % signer_type,
|
||||
ui.MONO, *split(hexlify(op.signer_key).decode()),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
signer_type = "hash"
|
||||
text = Text("Confirm operation", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold(text % signer_type)
|
||||
text.mono(*split(hexlify(op.signer_key).decode()))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
else:
|
||||
raise ProcessError('Stellar: invalid signer type')
|
||||
raise ProcessError("Stellar: invalid signer type")
|
||||
|
||||
|
||||
def _format_thresholds(op: StellarSetOptionsOp) -> tuple:
|
||||
text = ()
|
||||
if op.master_weight is not None:
|
||||
text += ('Master Weight: %d' % op.master_weight, )
|
||||
text += ("Master Weight: %d" % op.master_weight,)
|
||||
if op.low_threshold is not None:
|
||||
text += ('Low: %d' % op.low_threshold, )
|
||||
text += ("Low: %d" % op.low_threshold,)
|
||||
if op.medium_threshold is not None:
|
||||
text += ('Medium: %d' % op.medium_threshold, )
|
||||
text += ("Medium: %d" % op.medium_threshold,)
|
||||
if op.high_threshold is not None:
|
||||
text += ('High: %d' % op.high_threshold, )
|
||||
text += ("High: %d" % op.high_threshold,)
|
||||
return text
|
||||
|
||||
|
||||
def _format_flags(flags: int) -> tuple:
|
||||
if flags > consts.FLAGS_MAX_SIZE:
|
||||
raise ProcessError('Stellar: invalid flags')
|
||||
raise ProcessError("Stellar: invalid flags")
|
||||
text = ()
|
||||
if flags & consts.FLAG_AUTH_REQUIRED:
|
||||
text += ('AUTH_REQUIRED', )
|
||||
text += ("AUTH_REQUIRED",)
|
||||
if flags & consts.FLAG_AUTH_REVOCABLE:
|
||||
text += ('AUTH_REVOCABLE', )
|
||||
text += ("AUTH_REVOCABLE",)
|
||||
if flags & consts.FLAG_AUTH_IMMUTABLE:
|
||||
text += ('AUTH_IMMUTABLE', )
|
||||
text += ("AUTH_IMMUTABLE",)
|
||||
return text
|
||||
|
||||
|
||||
def format_asset_code(asset: StellarAssetType) -> str:
|
||||
if asset is None or asset.type == consts.ASSET_TYPE_NATIVE:
|
||||
return 'XLM (native)'
|
||||
return "XLM (native)"
|
||||
return asset.code
|
||||
|
||||
|
||||
async def confirm_asset_issuer(ctx, asset: StellarAssetType):
|
||||
if asset is None or asset.type == consts.ASSET_TYPE_NATIVE:
|
||||
return
|
||||
content = Text('Confirm issuer', ui.ICON_CONFIRM,
|
||||
ui.BOLD, '%s issuer:' % asset.code,
|
||||
ui.MONO, *split(asset.issuer),
|
||||
icon_color=ui.GREEN)
|
||||
await require_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||
text = Text("Confirm issuer", ui.ICON_CONFIRM, icon_color=ui.GREEN)
|
||||
text.bold("%s issuer:" % asset.code)
|
||||
text.mono(*split(asset.issuer))
|
||||
await require_confirm(ctx, text, ButtonRequestType.ConfirmOutput)
|
||||
|
@ -1,8 +1,6 @@
|
||||
from apps.stellar import writers
|
||||
from apps.stellar import consts
|
||||
from trezor.messages.StellarAccountMergeOp import StellarAccountMergeOp
|
||||
from trezor.messages.StellarAssetType import StellarAssetType
|
||||
from trezor.messages.StellarAllowTrustOp import StellarAllowTrustOp
|
||||
from trezor.messages.StellarAssetType import StellarAssetType
|
||||
from trezor.messages.StellarBumpSequenceOp import StellarBumpSequenceOp
|
||||
from trezor.messages.StellarChangeTrustOp import StellarChangeTrustOp
|
||||
from trezor.messages.StellarCreateAccountOp import StellarCreateAccountOp
|
||||
@ -14,6 +12,8 @@ from trezor.messages.StellarPaymentOp import StellarPaymentOp
|
||||
from trezor.messages.StellarSetOptionsOp import StellarSetOptionsOp
|
||||
from trezor.wire import ProcessError
|
||||
|
||||
from apps.stellar import consts, writers
|
||||
|
||||
|
||||
def serialize_account_merge_op(w, msg: StellarAccountMergeOp):
|
||||
writers.write_pubkey(w, msg.destination_account)
|
||||
@ -52,7 +52,7 @@ def serialize_create_passive_offer_op(w, msg: StellarCreatePassiveOfferOp):
|
||||
|
||||
def serialize_manage_data_op(w, msg: StellarManageDataOp):
|
||||
if len(msg.key) > 64:
|
||||
raise ProcessError('Stellar: max length of a key is 64 bytes')
|
||||
raise ProcessError("Stellar: max length of a key is 64 bytes")
|
||||
writers.write_string(w, msg.key)
|
||||
writers.write_bool(w, bool(msg.value))
|
||||
if msg.value:
|
||||
@ -124,7 +124,7 @@ def serialize_set_options_op(w, msg: StellarSetOptionsOp):
|
||||
writers.write_bool(w, bool(msg.home_domain))
|
||||
if msg.home_domain:
|
||||
if len(msg.home_domain) > 32:
|
||||
raise ProcessError('Stellar: max length of a home domain is 32 bytes')
|
||||
raise ProcessError("Stellar: max length of a home domain is 32 bytes")
|
||||
writers.write_string(w, msg.home_domain)
|
||||
|
||||
# signer
|
||||
@ -154,7 +154,7 @@ def _serialize_asset_code(w, asset_type: int, asset_code: str):
|
||||
# pad with zeros to 12 chars
|
||||
writers.write_bytes(w, code + bytearray([0] * (12 - len(code))))
|
||||
else:
|
||||
raise ProcessError('Stellar: invalid asset type')
|
||||
raise ProcessError("Stellar: invalid asset type")
|
||||
|
||||
|
||||
def _serialize_asset(w, asset: StellarAssetType):
|
||||
|
@ -1,21 +1,20 @@
|
||||
from apps.common import seed
|
||||
from apps.stellar import writers
|
||||
from apps.stellar.operations import operation
|
||||
from apps.stellar import helpers
|
||||
from apps.stellar import layout
|
||||
from apps.stellar import consts
|
||||
from trezor.wire import ProcessError
|
||||
from trezor.messages.StellarSignTx import StellarSignTx
|
||||
from trezor.messages.StellarTxOpRequest import StellarTxOpRequest
|
||||
from trezor.messages.StellarSignedTx import StellarSignedTx
|
||||
from ubinascii import hexlify
|
||||
|
||||
from trezor.crypto.curve import ed25519
|
||||
from trezor.crypto.hashlib import sha256
|
||||
from ubinascii import hexlify
|
||||
from trezor.messages.StellarSignedTx import StellarSignedTx
|
||||
from trezor.messages.StellarSignTx import StellarSignTx
|
||||
from trezor.messages.StellarTxOpRequest import StellarTxOpRequest
|
||||
from trezor.wire import ProcessError
|
||||
|
||||
from apps.common import seed
|
||||
from apps.stellar import consts, helpers, layout, writers
|
||||
from apps.stellar.operations import operation
|
||||
|
||||
|
||||
async def sign_tx(ctx, msg: StellarSignTx):
|
||||
if msg.num_operations == 0:
|
||||
raise ProcessError('Stellar: At least one operation is required')
|
||||
raise ProcessError("Stellar: At least one operation is required")
|
||||
|
||||
node = await seed.derive_node(ctx, msg.address_n, consts.STELLAR_CURVE)
|
||||
pubkey = seed.remove_ed25519_prefix(node.public_key())
|
||||
@ -50,7 +49,7 @@ async def _init(ctx, w: bytearray, pubkey: bytes, msg: StellarSignTx):
|
||||
address = helpers.address_from_public_key(pubkey)
|
||||
writers.write_pubkey(w, address)
|
||||
if helpers.public_key_from_address(msg.source_account) != pubkey:
|
||||
raise ProcessError('Stellar: source account does not match address_n')
|
||||
raise ProcessError("Stellar: source account does not match address_n")
|
||||
writers.write_uint32(w, msg.fee)
|
||||
writers.write_uint64(w, msg.sequence_number)
|
||||
|
||||
@ -80,11 +79,11 @@ async def _memo(ctx, w: bytearray, msg: StellarSignTx):
|
||||
writers.write_uint32(w, msg.memo_type)
|
||||
if msg.memo_type == consts.MEMO_TYPE_NONE:
|
||||
# nothing is serialized
|
||||
memo_confirm_text = ''
|
||||
memo_confirm_text = ""
|
||||
elif msg.memo_type == consts.MEMO_TYPE_TEXT:
|
||||
# Text: 4 bytes (size) + up to 28 bytes
|
||||
if len(msg.memo_text) > 28:
|
||||
raise ProcessError('Stellar: max length of a memo text is 28 bytes')
|
||||
raise ProcessError("Stellar: max length of a memo text is 28 bytes")
|
||||
writers.write_string(w, msg.memo_text)
|
||||
memo_confirm_text = msg.memo_text
|
||||
elif msg.memo_type == consts.MEMO_TYPE_ID:
|
||||
@ -96,7 +95,7 @@ async def _memo(ctx, w: bytearray, msg: StellarSignTx):
|
||||
writers.write_bytes(w, bytearray(msg.memo_hash))
|
||||
memo_confirm_text = hexlify(msg.memo_hash).decode()
|
||||
else:
|
||||
raise ProcessError('Stellar invalid memo type')
|
||||
raise ProcessError("Stellar invalid memo type")
|
||||
await layout.require_confirm_memo(ctx, msg.memo_type, memo_confirm_text)
|
||||
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
import ustruct
|
||||
|
||||
from .helpers import public_key_from_address
|
||||
|
||||
|
||||
def write_uint32(w, n: int):
|
||||
write_bytes(w, ustruct.pack('>L', n))
|
||||
write_bytes(w, ustruct.pack(">L", n))
|
||||
|
||||
|
||||
def write_uint64(w, n: int):
|
||||
write_bytes(w, ustruct.pack('>Q', n))
|
||||
write_bytes(w, ustruct.pack(">Q", n))
|
||||
|
||||
|
||||
def write_string(w, s: str):
|
||||
|
Loading…
Reference in New Issue
Block a user