diff --git a/trezorctl b/trezorctl index e4addc168..d864e6c0b 100755 --- a/trezorctl +++ b/trezorctl @@ -42,6 +42,7 @@ from trezorlib import ( log, messages as proto, misc, + monero, nem, ontology, protobuf, @@ -1393,6 +1394,40 @@ def lisk_verify_message(connect, pubkey, signature, message): return lisk.verify_message(connect(), pubkey, signature, message) +# +# Monero functions +# + + +@cli.command(help="Get Monero address for specified path.") +@click.option("-n", "--address", required=True, help="BIP-32 path, e.g. m/44'/128'/0'") +@click.option("-d", "--show-display", is_flag=True) +@click.option( + "-t", "--network-type", type=click.Choice(["0", "1", "2", "3"]), default="0" +) +@click.pass_obj +def monero_get_address(connect, address, show_display, network_type): + client = connect() + address_n = tools.parse_path(address) + network_type = int(network_type) + return monero.get_address(client, address_n, show_display, network_type) + + +@cli.command(help="Get Monero watch key for specified path.") +@click.option("-n", "--address", required=True, help="BIP-32 path, e.g. m/44'/128'/0'") +@click.option( + "-t", "--network-type", type=click.Choice(["0", "1", "2", "3"]), default="0" +) +@click.pass_obj +def monero_get_watch_key(connect, address, network_type): + client = connect() + address_n = tools.parse_path(address) + network_type = int(network_type) + res = monero.get_watch_key(client, address_n, network_type) + output = {"address": res.address.decode(), "watch_key": res.watch_key.hex()} + return output + + # # CoSi functions # diff --git a/trezorlib/monero.py b/trezorlib/monero.py new file mode 100644 index 000000000..270cc748e --- /dev/null +++ b/trezorlib/monero.py @@ -0,0 +1,19 @@ +from . import messages as proto +from .tools import expect + +# MAINNET = 0 +# TESTNET = 1 +# STAGENET = 2 +# FAKECHAIN = 3 + + +@expect(proto.MoneroAddress, field="address") +def get_address(client, n, show_display=False, network_type=0): + return client.call( + proto.MoneroGetAddress(address_n=n, show_display=show_display, network_type=network_type) + ) + + +@expect(proto.MoneroWatchKey) +def get_watch_key(client, n, network_type=0): + return client.call(proto.MoneroGetWatchKey(address_n=n, network_type=network_type)) diff --git a/trezorlib/tests/device_tests/test_msg_monero_getaddress.py b/trezorlib/tests/device_tests/test_msg_monero_getaddress.py new file mode 100644 index 000000000..ff61d6323 --- /dev/null +++ b/trezorlib/tests/device_tests/test_msg_monero_getaddress.py @@ -0,0 +1,41 @@ +# This file is part of the Trezor project. +# +# Copyright (C) 2012-2018 SatoshiLabs and contributors +# +# 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 . + +import pytest + +from trezorlib import monero +from trezorlib.tools import parse_path + +from .common import TrezorTest + + +@pytest.mark.monero +@pytest.mark.skip_t1 +class TestMsgMoneroGetaddress(TrezorTest): + def test_monero_getaddress(self): + self.setup_mnemonic_nopin_nopassphrase() + assert ( + monero.get_address(self.client, parse_path("m/44h/128h/0h")) + == b"4Ahp23WfMrMFK3wYL2hLWQFGt87ZTeRkufS6JoQZu6MEFDokAQeGWmu9MA3GFq1yVLSJQbKJqVAn9F9DLYGpRzRAEXqAXKM" + ) + assert ( + monero.get_address(self.client, parse_path("m/44h/128h/1h")) + == b"44iAazhoAkv5a5RqLNVyh82a1n3ceNggmN4Ho7bUBJ14WkEVR8uFTe9f7v5rNnJ2kEbVXxfXiRzsD5Jtc6NvBi4D6WNHPie" + ) + assert ( + monero.get_address(self.client, parse_path("m/44h/128h/2h")) + == b"47ejhmbZ4wHUhXaqA4b7PN667oPMkokf4ZkNdWrMSPy9TNaLVr7vLqVUQHh2MnmaAEiyrvLsX8xUf99q3j1iAeMV8YvSFcH" + ) diff --git a/trezorlib/tests/device_tests/test_msg_monero_getwatchkey.py b/trezorlib/tests/device_tests/test_msg_monero_getwatchkey.py new file mode 100644 index 000000000..f6bd5ce1f --- /dev/null +++ b/trezorlib/tests/device_tests/test_msg_monero_getwatchkey.py @@ -0,0 +1,56 @@ +# This file is part of the Trezor project. +# +# Copyright (C) 2012-2018 SatoshiLabs and contributors +# +# 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 . + +import pytest + +from trezorlib import monero +from trezorlib.tools import parse_path + +from .common import TrezorTest + + +@pytest.mark.monero +@pytest.mark.skip_t1 +class TestMsgMoneroGetwatchkey(TrezorTest): + def test_monero_getwatchkey(self): + self.setup_mnemonic_nopin_nopassphrase() + res = monero.get_watch_key(self.client, parse_path("m/44h/128h/0h")) + assert ( + res.address + == b"4Ahp23WfMrMFK3wYL2hLWQFGt87ZTeRkufS6JoQZu6MEFDokAQeGWmu9MA3GFq1yVLSJQbKJqVAn9F9DLYGpRzRAEXqAXKM" + ) + assert ( + res.watch_key.hex() + == "8722520a581e2a50cc1adab4a1692401effd37b0d63b9d9b60fd7f34ea2b950e" + ) + res = monero.get_watch_key(self.client, parse_path("m/44h/128h/1h")) + assert ( + res.address + == b"44iAazhoAkv5a5RqLNVyh82a1n3ceNggmN4Ho7bUBJ14WkEVR8uFTe9f7v5rNnJ2kEbVXxfXiRzsD5Jtc6NvBi4D6WNHPie" + ) + assert ( + res.watch_key.hex() + == "1f70b7d9e86c11b7a5bee883b75c43d6be189c8f812726ea1ecd94b06bb7db04" + ) + res = monero.get_watch_key(self.client, parse_path("m/44h/128h/2h")) + assert ( + res.address + == b"47ejhmbZ4wHUhXaqA4b7PN667oPMkokf4ZkNdWrMSPy9TNaLVr7vLqVUQHh2MnmaAEiyrvLsX8xUf99q3j1iAeMV8YvSFcH" + ) + assert ( + res.watch_key.hex() + == "e0671fbed2c9231fe4f286962862813a4a4d153c793bf5d0e3742119723f3000" + )