2018-06-21 14:28:34 +00:00
|
|
|
# This file is part of the Trezor project.
|
|
|
|
#
|
2019-05-29 16:44:09 +00:00
|
|
|
# Copyright (C) 2012-2019 SatoshiLabs and contributors
|
2018-06-21 14:28:34 +00:00
|
|
|
#
|
|
|
|
# This library is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU Lesser General Public License version 3
|
|
|
|
# as published by the Free Software Foundation.
|
|
|
|
#
|
|
|
|
# This library is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU Lesser General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the License along with this library.
|
|
|
|
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
|
|
|
|
2018-03-15 15:14:24 +00:00
|
|
|
import json
|
2018-08-13 16:21:24 +00:00
|
|
|
|
2018-03-15 15:14:24 +00:00
|
|
|
from . import messages as proto
|
2018-08-13 16:21:24 +00:00
|
|
|
from .tools import CallException, expect
|
2018-03-15 15:14:24 +00:00
|
|
|
|
2018-03-28 15:25:53 +00:00
|
|
|
TYPE_TRANSACTION_TRANSFER = 0x0101
|
2018-03-15 15:14:24 +00:00
|
|
|
TYPE_IMPORTANCE_TRANSFER = 0x0801
|
2018-03-28 15:25:53 +00:00
|
|
|
TYPE_AGGREGATE_MODIFICATION = 0x1001
|
|
|
|
TYPE_MULTISIG_SIGNATURE = 0x1002
|
|
|
|
TYPE_MULTISIG = 0x1004
|
2018-03-15 15:14:24 +00:00
|
|
|
TYPE_PROVISION_NAMESPACE = 0x2001
|
2018-03-28 15:25:53 +00:00
|
|
|
TYPE_MOSAIC_CREATION = 0x4001
|
2018-03-15 15:14:24 +00:00
|
|
|
TYPE_MOSAIC_SUPPLY_CHANGE = 0x4002
|
|
|
|
|
|
|
|
|
|
|
|
def create_transaction_common(transaction):
|
|
|
|
msg = proto.NEMTransactionCommon()
|
|
|
|
msg.network = (transaction["version"] >> 24) & 0xFF
|
|
|
|
msg.timestamp = transaction["timeStamp"]
|
|
|
|
msg.fee = transaction["fee"]
|
|
|
|
msg.deadline = transaction["deadline"]
|
|
|
|
|
2018-04-10 12:50:01 +00:00
|
|
|
if "signer" in transaction:
|
2018-09-12 22:44:08 +00:00
|
|
|
msg.signer = bytes.fromhex(transaction["signer"])
|
2018-03-15 15:14:24 +00:00
|
|
|
|
|
|
|
return msg
|
|
|
|
|
|
|
|
|
|
|
|
def create_transfer(transaction):
|
|
|
|
msg = proto.NEMTransfer()
|
|
|
|
msg.recipient = transaction["recipient"]
|
|
|
|
msg.amount = transaction["amount"]
|
|
|
|
|
|
|
|
if "payload" in transaction["message"]:
|
2018-09-12 22:44:08 +00:00
|
|
|
msg.payload = bytes.fromhex(transaction["message"]["payload"])
|
2018-03-15 15:14:24 +00:00
|
|
|
|
|
|
|
if transaction["message"]["type"] == 0x02:
|
2018-09-12 22:44:08 +00:00
|
|
|
msg.public_key = bytes.fromhex(transaction["message"]["publicKey"])
|
2018-03-15 15:14:24 +00:00
|
|
|
|
|
|
|
if "mosaics" in transaction:
|
2018-08-13 16:21:24 +00:00
|
|
|
msg.mosaics = [
|
|
|
|
proto.NEMMosaic(
|
|
|
|
namespace=mosaic["mosaicId"]["namespaceId"],
|
|
|
|
mosaic=mosaic["mosaicId"]["name"],
|
|
|
|
quantity=mosaic["quantity"],
|
|
|
|
)
|
|
|
|
for mosaic in transaction["mosaics"]
|
|
|
|
]
|
2018-03-15 15:14:24 +00:00
|
|
|
|
|
|
|
return msg
|
|
|
|
|
|
|
|
|
|
|
|
def create_aggregate_modification(transactions):
|
|
|
|
msg = proto.NEMAggregateModification()
|
2018-08-13 16:21:24 +00:00
|
|
|
msg.modifications = [
|
|
|
|
proto.NEMCosignatoryModification(
|
|
|
|
type=modification["modificationType"],
|
2018-09-12 22:44:08 +00:00
|
|
|
public_key=bytes.fromhex(modification["cosignatoryAccount"]),
|
2018-08-13 16:21:24 +00:00
|
|
|
)
|
|
|
|
for modification in transactions["modifications"]
|
|
|
|
]
|
2018-03-15 15:14:24 +00:00
|
|
|
|
|
|
|
if "minCosignatories" in transactions:
|
|
|
|
msg.relative_change = transactions["minCosignatories"]["relativeChange"]
|
|
|
|
|
|
|
|
return msg
|
|
|
|
|
|
|
|
|
|
|
|
def create_provision_namespace(transaction):
|
|
|
|
msg = proto.NEMProvisionNamespace()
|
|
|
|
msg.namespace = transaction["newPart"]
|
|
|
|
|
|
|
|
if transaction["parent"]:
|
|
|
|
msg.parent = transaction["parent"]
|
|
|
|
|
|
|
|
msg.sink = transaction["rentalFeeSink"]
|
|
|
|
msg.fee = transaction["rentalFee"]
|
2018-03-27 14:41:13 +00:00
|
|
|
return msg
|
2018-03-15 15:14:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
def create_mosaic_creation(transaction):
|
|
|
|
definition = transaction["mosaicDefinition"]
|
|
|
|
msg = proto.NEMMosaicCreation()
|
|
|
|
msg.definition = proto.NEMMosaicDefinition()
|
|
|
|
msg.definition.namespace = definition["id"]["namespaceId"]
|
|
|
|
msg.definition.mosaic = definition["id"]["name"]
|
|
|
|
|
|
|
|
if definition["levy"]:
|
|
|
|
msg.definition.levy = definition["levy"]["type"]
|
|
|
|
msg.definition.fee = definition["levy"]["fee"]
|
|
|
|
msg.definition.levy_address = definition["levy"]["recipient"]
|
|
|
|
msg.definition.levy_namespace = definition["levy"]["mosaicId"]["namespaceId"]
|
|
|
|
msg.definition.levy_mosaic = definition["levy"]["mosaicId"]["name"]
|
|
|
|
|
|
|
|
msg.definition.description = definition["description"]
|
|
|
|
|
|
|
|
for property in definition["properties"]:
|
|
|
|
name = property["name"]
|
|
|
|
value = json.loads(property["value"])
|
|
|
|
|
|
|
|
if name == "divisibility":
|
|
|
|
msg.definition.divisibility = value
|
|
|
|
elif name == "initialSupply":
|
|
|
|
msg.definition.supply = value
|
|
|
|
elif name == "supplyMutable":
|
|
|
|
msg.definition.mutable_supply = value
|
|
|
|
elif name == "transferable":
|
|
|
|
msg.definition.transferable = value
|
|
|
|
|
|
|
|
msg.sink = transaction["creationFeeSink"]
|
|
|
|
msg.fee = transaction["creationFee"]
|
|
|
|
return msg
|
|
|
|
|
|
|
|
|
|
|
|
def create_supply_change(transaction):
|
|
|
|
msg = proto.NEMMosaicSupplyChange()
|
|
|
|
msg.namespace = transaction["mosaicId"]["namespaceId"]
|
|
|
|
msg.mosaic = transaction["mosaicId"]["name"]
|
|
|
|
msg.type = transaction["supplyType"]
|
|
|
|
msg.delta = transaction["delta"]
|
|
|
|
return msg
|
|
|
|
|
|
|
|
|
2018-03-29 10:43:54 +00:00
|
|
|
def create_importance_transfer(transaction):
|
|
|
|
msg = proto.NEMImportanceTransfer()
|
|
|
|
msg.mode = transaction["importanceTransfer"]["mode"]
|
2018-09-12 22:44:08 +00:00
|
|
|
msg.public_key = bytes.fromhex(transaction["importanceTransfer"]["publicKey"])
|
2018-03-29 10:43:54 +00:00
|
|
|
return msg
|
|
|
|
|
|
|
|
|
2018-08-21 13:57:50 +00:00
|
|
|
def fill_transaction_by_type(msg, transaction):
|
2018-03-28 15:25:53 +00:00
|
|
|
if transaction["type"] == TYPE_TRANSACTION_TRANSFER:
|
2018-03-15 15:14:24 +00:00
|
|
|
msg.transfer = create_transfer(transaction)
|
2018-03-28 15:25:53 +00:00
|
|
|
elif transaction["type"] == TYPE_AGGREGATE_MODIFICATION:
|
2018-03-15 15:14:24 +00:00
|
|
|
msg.aggregate_modification = create_aggregate_modification(transaction)
|
|
|
|
elif transaction["type"] == TYPE_PROVISION_NAMESPACE:
|
|
|
|
msg.provision_namespace = create_provision_namespace(transaction)
|
2018-03-28 15:25:53 +00:00
|
|
|
elif transaction["type"] == TYPE_MOSAIC_CREATION:
|
2018-03-15 15:14:24 +00:00
|
|
|
msg.mosaic_creation = create_mosaic_creation(transaction)
|
|
|
|
elif transaction["type"] == TYPE_MOSAIC_SUPPLY_CHANGE:
|
2018-03-28 15:25:53 +00:00
|
|
|
msg.supply_change = create_supply_change(transaction)
|
2018-03-29 10:43:54 +00:00
|
|
|
elif transaction["type"] == TYPE_IMPORTANCE_TRANSFER:
|
|
|
|
msg.importance_transfer = create_importance_transfer(transaction)
|
2018-03-15 15:14:24 +00:00
|
|
|
else:
|
|
|
|
raise ValueError("Unknown transaction type")
|
|
|
|
|
2018-08-21 13:57:50 +00:00
|
|
|
|
|
|
|
def create_sign_tx(transaction):
|
|
|
|
msg = proto.NEMSignTx()
|
|
|
|
msg.transaction = create_transaction_common(transaction)
|
|
|
|
msg.cosigning = transaction["type"] == TYPE_MULTISIG_SIGNATURE
|
|
|
|
|
|
|
|
if transaction["type"] in (TYPE_MULTISIG_SIGNATURE, TYPE_MULTISIG):
|
|
|
|
other_trans = transaction["otherTrans"]
|
|
|
|
msg.multisig = create_transaction_common(other_trans)
|
|
|
|
fill_transaction_by_type(msg, other_trans)
|
|
|
|
elif "otherTrans" in transaction:
|
|
|
|
raise ValueError("Transaction does not support inner transaction")
|
|
|
|
else:
|
|
|
|
fill_transaction_by_type(msg, transaction)
|
|
|
|
|
2018-03-15 15:14:24 +00:00
|
|
|
return msg
|
2018-06-13 17:04:18 +00:00
|
|
|
|
|
|
|
|
2018-08-10 14:05:14 +00:00
|
|
|
# ====== Client functions ====== #
|
2018-06-13 17:04:18 +00:00
|
|
|
|
|
|
|
|
2018-06-25 15:51:09 +00:00
|
|
|
@expect(proto.NEMAddress, field="address")
|
2018-06-13 17:04:18 +00:00
|
|
|
def get_address(client, n, network, show_display=False):
|
2018-08-13 16:21:24 +00:00
|
|
|
return client.call(
|
|
|
|
proto.NEMGetAddress(address_n=n, network=network, show_display=show_display)
|
|
|
|
)
|
2018-06-13 17:04:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
@expect(proto.NEMSignedTx)
|
|
|
|
def sign_tx(client, n, transaction):
|
|
|
|
try:
|
|
|
|
msg = create_sign_tx(transaction)
|
|
|
|
except ValueError as e:
|
|
|
|
raise CallException(e.args)
|
|
|
|
|
|
|
|
assert msg.transaction is not None
|
|
|
|
msg.transaction.address_n = n
|
|
|
|
return client.call(msg)
|