feat(common,core,python,tests): add `tron.get_address` support.
What changed, and why it matters
This commit adds support for retrieving Tron cryptocurrency addresses on Trezor hardware wallets. It is a feature addition that extends existing address-derivation infrastructure to a new blockchain. There is no indication in the commit that it fixes a security bug or introduces a vulnerability.
No security action required. Treat as a normal feature review; verify test vectors and that the Tron address encoding matches the official Tron protocol.
Security signals we found
No security-relevant signals detected in the diff.
New address-derivation code reuses standard keychain, curve, path validation, address MAC, and display flows already used by other coins.
No input parsing of untrusted transaction data beyond BIP-32 path and optional display flags.
No buffer-size or memory-safety anomalies visible in the added Python code.
Evidence from the diff
The change implements TronGetAddress / TronAddress protocol messages, a core app (apps/tron/get_address.py), address derivation helpers using secp256k1 and Keccak-256 hashing with a 0x41 prefix and base58check encoding, plus Python/Rust client bindings, CLI support, tests, and UI fixtures. It follows the same patterns used for other altcoins already in the codebase.
Changed components
core/src/apps/tron/get_address.pycore/src/apps/tron/helpers.pycommon/protob/messages-tron.protopython/src/trezorlib/tron.pypython/src/trezorlib/cli/tron.pyrust/trezor-client protobuf bindingsInspect captured patch +898 / −3
diff --git a/common/protob/Makefile b/common/protob/Makefile
index 399665b0..9c5e7890 100644
--- a/common/protob/Makefile
+++ b/common/protob/Makefile
@@ -1,4 +1,4 @@
-check: messages.pb messages-bitcoin.pb messages-ble.pb messages-bootloader.pb messages-cardano.pb messages-common.pb messages-crypto.pb messages-debug.pb messages-ethereum.pb messages-management.pb messages-monero.pb messages-nem.pb messages-ripple.pb messages-stellar.pb messages-tezos.pb messages-eos.pb messages-solana.pb messages-definitions.pb
+check: messages.pb messages-bitcoin.pb messages-ble.pb messages-bootloader.pb messages-cardano.pb messages-common.pb messages-crypto.pb messages-debug.pb messages-ethereum.pb messages-management.pb messages-monero.pb messages-nem.pb messages-ripple.pb messages-stellar.pb messages-tezos.pb messages-tron.pb messages-eos.pb messages-solana.pb messages-definitions.pb
%.pb: %.proto
protoc -I/usr/include -I. $< -o $@
diff --git a/common/protob/messages-tron.proto b/common/protob/messages-tron.proto
new file mode 100644
index 00000000..bb101fba
--- /dev/null
+++ b/common/protob/messages-tron.proto
@@ -0,0 +1,107 @@
+syntax = "proto2";
+package hw.trezor.messages.tron;
+
+// Sugar for easier handling in Java
+option java_package = "com.satoshilabs.trezor.lib.protobuf";
+option java_outer_classname = "TrezorMessageTron";
+
+/**
+ * Request: Ask device for Tron address corresponding to address_n path
+ * @start
+ * @next TronAddress
+ * @next Failure
+ */
+message TronGetAddress {
+ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
+ optional bool show_display = 2; // Optionally show on display before sending the result
+ optional bool chunkify = 3; // display the address in chunks of 4 characters
+}
+
+/**
+ * Response: Contains Tron address derived from device private seed
+ * @end
+ */
+message TronAddress {
+ required string address = 1; // Tron address in base58_checked encoding
+ optional bytes mac = 2; // Address authentication code
+}
+
+/**
+ * Request: ask device to sign Stellar transaction
+ * @start
+ * @next StellarTxOpRequest
+ */
+message TronSignTx {
+ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
+ required bytes ref_block_bytes = 2; // The height of the transaction reference block, using the 6th to 8th (exclusive) bytes of the reference block height, a total of 2 bytes
+ required bytes ref_block_hash = 3; // The hash of the transaction reference block
+ required sint64 expiration = 4; // Transaction expiration time, beyond which the transaction will no longer be packed
+ optional bytes data = 5; // Transaction memo. (256 bytes maximum, this is a Trezor limitation, not a Tron protocol limitation)
+ required sint64 timestamp = 6; // Transaction timestamp, set as the transaction creation time
+ optional sint64 fee_limit = 7; // The maximum energy cost allowed for the execution of smart contract transactions. Only deploying and triggering smart contract transactions need to be set, others not
+}
+
+/**
+ * Response: device is ready for client to send the next operation
+ * @next TronTransferContract
+ */
+message TronContractRequest {
+}
+
+/**
+ * Request: ask device to confirm this operation type
+ * @next TronSignature
+ */
+message TronTransferContract {
+ // https://developers.tron.network/docs/tron-contracttype#2-transfercontract
+ required string owner_address = 1; // Sender's address, base58_checked encoding
+ required string to_address = 2; // Recipient's address, base58_checked encoding
+ required sint64 amount = 3; // Transfer amount (in SUN)
+}
+
+/**
+ * Response: signature for transaction
+ * @end
+ */
+message TronSignature {
+ required bytes signature = 1; // Signature of the transaction
+}
+
+
+/**
+ * TronRawTransaction and embedded messages are used to encode the Tron transaction, not for communication.
+ * @start
+ * @end
+ */
+// https://github.com/tronprotocol/protocol/blob/37bb922a9967bbbef1e84de1c9e5cda56a2d7998/core/Tron.proto#L431-L445
+message TronRawTransaction {
+ required bytes ref_block_bytes = 1;
+ required bytes ref_block_hash = 4;
+ required uint64 expiration = 8;
+ optional bytes data = 10;
+ repeated TronRawContract contract = 11;
+ required uint64 timestamp = 14;
+ optional uint64 fee_limit = 18;
+
+ // https://github.com/tronprotocol/protocol/blob/37bb922a9967bbbef1e84de1c9e5cda56a2d7998/core/Tron.proto#L337-L385
+ message TronRawContract {
+ // https://github.com/tronprotocol/protocol/blob/37bb922a9967bbbef1e84de1c9e5cda56a2d7998/core/contract/balance_contract.proto#L32-L36
+ message TronRawTransferContract {
+ required bytes owner_address = 1;
+ required bytes to_address = 2;
+ required uint64 amount = 3;
+ }
+
+ message TronRawParameter {
+ required string type_url = 1; // e.g., "type.googleapis.com/protocol.TransferContract"
+ required bytes value = 2; // The serialized value of the contract parameter, e.g., TronTransferContract
+ }
+
+ required TronRawContractType type = 1;
+ required TronRawParameter parameter = 2;
+
+ enum TronRawContractType {
+ TransferContract = 1;
+ }
+ }
+}
diff --git a/common/protob/messages.proto b/common/protob/messages.proto
index 082cebb0..69c41ef7 100644
--- a/common/protob/messages.proto
+++ b/common/protob/messages.proto
@@ -348,6 +348,10 @@ enum MessageType {
MessageType_EvoluGetDelegatedIdentityKey = 2104 [(bitcoin_only) = true, (wire_in) = true];
MessageType_EvoluDelegatedIdentityKey = 2105 [(bitcoin_only) = true, (wire_out) = true];
+ // Tron
+ MessageType_TronGetAddress = 3000 [(wire_in) = true];
+ MessageType_TronAddress = 3001 [(wire_out) = true];
+
// Benchmark
MessageType_BenchmarkListNames = 9100 [(bitcoin_only) = true];
MessageType_BenchmarkNames = 9101 [(bitcoin_only) = true];
diff --git a/common/tests/fixtures/tron/get_address.json b/common/tests/fixtures/tron/get_address.json
new file mode 100644
index 00000000..11684049
--- /dev/null
+++ b/common/tests/fixtures/tron/get_address.json
@@ -0,0 +1,48 @@
+{
+ "setup": {
+ "mnemonic": "all all all all all all all all all all all all",
+ "passphrase": ""
+ },
+ "tests": [
+ {
+ "parameters": {
+ "path": "m/44'/195'/0'/0/0"
+ },
+ "result": {
+ "address": "TY72iA3SBtrds3QLYsS7LwYfkzXwAXCRWT"
+ }
+ },
+ {
+ "parameters": {
+ "path": "m/44'/195'/0'/0/1"
+ },
+ "result": {
+ "address": "TFz2CJn9CJb8C4i1Gke3jmZX2fRMJxniH2"
+ }
+ },
+ {
+ "parameters": {
+ "path": "m/44'/195'/0'/0/2"
+ },
+ "result": {
+ "address": "TQSw9qVAigRwfgPdf7aW4wxbG9tFitexg2"
+ }
+ },
+ {
+ "parameters": {
+ "path": "m/44'/195'/1'/0/0"
+ },
+ "result": {
+ "address": "TNPgkSKfz2xS39fcyfrouz7QPbkkJaDLYv"
+ }
+ },
+ {
+ "parameters": {
+ "path": "m/44'/195'/2'/0/0"
+ },
+ "result": {
+ "address": "TUKx4Z56RMrYWzAu1qoiDSHQTNiSgYHYyF"
+ }
+ }
+ ]
+}
diff --git a/common/tools/cointool.py b/common/tools/cointool.py
index 207ed28a..eb03ca06 100755
--- a/common/tools/cointool.py
+++ b/common/tools/cointool.py
@@ -149,6 +149,7 @@ ALTCOIN_PREFIXES = (
"solana",
"stellar",
"tezos",
+ "tron",
"u2f",
)
diff --git a/core/SConscript.firmware b/core/SConscript.firmware
index 9bcf7d29..a0284f3e 100644
--- a/core/SConscript.firmware
+++ b/core/SConscript.firmware
@@ -787,6 +787,9 @@ if FROZEN:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/tezos/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Tezos*.py'))
+ SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/tron/*.py'))
+ SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Tron*.py'))
+
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/zcash/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/webauthn/*.py'))
diff --git a/core/SConscript.unix b/core/SConscript.unix
index 3be06697..2eb3eeed 100644
--- a/core/SConscript.unix
+++ b/core/SConscript.unix
@@ -805,6 +805,8 @@ if FROZEN:
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/tezos/*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Tezos*.py'))
+ SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/tron/*.py'))
+ SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Tron*.py'))
SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/zcash/*.py'))
diff --git a/core/embed/upymod/qstrdefsport.h b/core/embed/upymod/qstrdefsport.h
index a88eb255..b073ad18 100644
--- a/core/embed/upymod/qstrdefsport.h
+++ b/core/embed/upymod/qstrdefsport.h
@@ -647,6 +647,9 @@ Q(apps.tezos.get_public_key)
Q(apps.tezos.helpers)
Q(apps.tezos.layout)
Q(apps.tezos.sign_tx)
+Q(apps.tron)
+Q(apps.tron.get_address)
+Q(apps.tron.helpers)
Q(apps.webauthn)
Q(apps.webauthn.add_resident_credential)
Q(apps.webauthn.common)
@@ -782,6 +785,7 @@ Q(trezor.enums.StellarMemoType)
Q(trezor.enums.StellarSignerType)
Q(trezor.enums.TezosBallotType)
Q(trezor.enums.TezosContractType)
+Q(tron)
Q(tx_ct_key)
Q(tx_ecdh)
Q(tx_prefix)
diff --git a/core/embed/upymod/qstrdefsport.h.mako b/core/embed/upymod/qstrdefsport.h.mako
index 62cd3223..19ac8d12 100644
--- a/core/embed/upymod/qstrdefsport.h.mako
+++ b/core/embed/upymod/qstrdefsport.h.mako
@@ -26,6 +26,7 @@ ALTCOINS = (
"solana",
"stellar",
"tezos",
+ "tron",
"webauthn",
"zcash",
)
diff --git a/core/src/apps/tron/__init__.py b/core/src/apps/tron/__init__.py
new file mode 100644
index 00000000..3c24d6f3
--- /dev/null
+++ b/core/src/apps/tron/__init__.py
@@ -0,0 +1,5 @@
+from apps.common.paths import PATTERN_BIP44
+
+CURVE = "secp256k1"
+SLIP44_ID = 195
+PATTERN = PATTERN_BIP44
diff --git a/core/src/apps/tron/get_address.py b/core/src/apps/tron/get_address.py
new file mode 100644
index 00000000..08ce5df8
--- /dev/null
+++ b/core/src/apps/tron/get_address.py
@@ -0,0 +1,44 @@
+from typing import TYPE_CHECKING
+
+from apps.common.keychain import with_slip44_keychain
+
+from . import CURVE, PATTERN, SLIP44_ID
+
+if TYPE_CHECKING:
+ from trezor.messages import TronAddress, TronGetAddress
+
+ from apps.common.keychain import Keychain
+
+
+@with_slip44_keychain(
+ PATTERN, slip44_id=SLIP44_ID, curve=CURVE, slip21_namespaces=[[b"SLIP-0024"]]
+)
+async def get_address(msg: TronGetAddress, keychain: Keychain) -> TronAddress:
+ from trezor import TR
+ from trezor.crypto.curve import secp256k1
+ from trezor.messages import TronAddress
+ from trezor.ui.layouts import show_address
+
+ from apps.common import paths
+ from apps.common.address_mac import get_address_mac
+
+ from . import helpers
+
+ address_n = msg.address_n
+ await paths.validate_path(keychain, address_n)
+ node = keychain.derive(msg.address_n)
+ public_key = secp256k1.publickey(node.private_key(), False)
+ address = helpers.address_from_public_key(public_key)
+ mac = get_address_mac(address, SLIP44_ID, address_n, keychain)
+
+ if msg.show_display:
+ coin = "Tron"
+ await show_address(
+ address,
+ subtitle=TR.address__coin_address_template.format(coin),
+ path=paths.address_n_to_str(address_n),
+ account=paths.get_account_name(coin, msg.address_n, PATTERN, SLIP44_ID),
+ chunkify=bool(msg.chunkify),
+ )
+
+ return TronAddress(address=address, mac=mac)
diff --git a/core/src/apps/tron/helpers.py b/core/src/apps/tron/helpers.py
new file mode 100644
index 00000000..c7684e88
--- /dev/null
+++ b/core/src/apps/tron/helpers.py
@@ -0,0 +1,7 @@
+from trezor.crypto import base58
+from trezor.crypto.hashlib import sha3_256
+
+
+def address_from_public_key(pubkey: bytes) -> str:
+ address_bytes = b"\x41" + sha3_256(pubkey[1:], keccak=True).digest()[12:]
+ return base58.encode_check(address_bytes)
diff --git a/core/src/apps/workflow_handlers.py b/core/src/apps/workflow_handlers.py
index e8609f3f..4a862739 100644
--- a/core/src/apps/workflow_handlers.py
+++ b/core/src/apps/workflow_handlers.py
@@ -223,6 +223,10 @@ def _find_message_handler_module(msg_type: int) -> str:
if msg_type == MessageType.SolanaSignTx:
return "apps.solana.sign_tx"
+ # tron
+ if msg_type == MessageType.TronGetAddress:
+ return "apps.tron.get_address"
+
raise ValueError
diff --git a/core/src/trezor/enums/MessageType.py b/core/src/trezor/enums/MessageType.py
index 2a4d7a9f..d5e75cdc 100644
--- a/core/src/trezor/enums/MessageType.py
+++ b/core/src/trezor/enums/MessageType.py
@@ -267,3 +267,5 @@ if not utils.BITCOIN_ONLY:
NostrPubkey = 2002
NostrSignEvent = 2003
NostrEventSignature = 2004
+ TronGetAddress = 3001
+ TronAddress = 3002
diff --git a/core/src/trezor/enums/__init__.py b/core/src/trezor/enums/__init__.py
index 77ce6af8..8c4ef06e 100644
--- a/core/src/trezor/enums/__init__.py
+++ b/core/src/trezor/enums/__init__.py
@@ -629,6 +629,8 @@ if TYPE_CHECKING:
EvoluRegistrationRequest = 2103
EvoluGetDelegatedIdentityKey = 2104
EvoluDelegatedIdentityKey = 2105
+ TronGetAddress = 3000
+ TronAddress = 3001
BenchmarkListNames = 9100
BenchmarkNames = 9101
BenchmarkRun = 9102
diff --git a/core/tests/test_apps.tron.address.py b/core/tests/test_apps.tron.address.py
new file mode 100644
index 00000000..b9beb73b
--- /dev/null
+++ b/core/tests/test_apps.tron.address.py
@@ -0,0 +1,34 @@
+# flake8: noqa: F403,F405
+from common import * # isort:skip
+
+if not utils.BITCOIN_ONLY:
+ from apps.tron.helpers import address_from_public_key
+
+
+@unittest.skipUnless(not utils.BITCOIN_ONLY, "altcoin")
+class TestTronAddress(unittest.TestCase):
+ def test_pubkey_to_address(self):
+ addr = address_from_public_key(
+ unhexlify(
+ "04aee772c640a56bfd434cc6c41b661467f0fac8ad922cd0d6f37a25a9faab506c9d687d8d4ad0957ca8a07b15db6b39ab2fa56cc81b49f2f92d44e1cdd2f4f266"
+ )
+ )
+ self.assertEqual(addr, "TY72iA3SBtrds3QLYsS7LwYfkzXwAXCRWT")
+
+ addr = address_from_public_key(
+ unhexlify(
+ "041cc8ed55001c441a9ca7b42129f025f33ff30ea29dfe88fc9f8ad8826582c73b52d47c475c75da0cc9f64a6462ca57e70a8902a79cccc4e769cc0261c691ce4f"
+ )
+ )
+ self.assertEqual(addr, "TVd6xm7E5vn9qnUQZbfoH5SAVZXZ15c4wC")
+
+ addr = address_from_public_key(
+ unhexlify(
+ "04d3df47d402249892f56295cf08cb70c2e37fc6b9eea01e1b163f4b5608f96c8449b3ea69541a33ff7961bb69af6f98bfca558fe53b9429de3fb8054d29f9c917"
+ )
+ )
+ self.assertEqual(addr, "TL4A3PZDdZxZnsk7ZsVgo5ztWaZqWLQT8i")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/core/tools/size/groups.py b/core/tools/size/groups.py
index 93f1782d..abfd8faa 100755
--- a/core/tools/size/groups.py
+++ b/core/tools/size/groups.py
@@ -72,6 +72,7 @@ def _categories_func(row: DataRow) -> str | None:
"src/apps/stellar/",
"src/apps/eos/",
"src/apps/tezos/",
+ "src/apps/tron/",
"src/apps/ripple/",
"src/apps/zcash/",
)
diff --git a/core/tools/translations/validate_strings.py b/core/tools/translations/validate_strings.py
index 59ce79e9..caaede30 100644
--- a/core/tools/translations/validate_strings.py
+++ b/core/tools/translations/validate_strings.py
@@ -30,6 +30,7 @@ ALTCOINS = [
"solana",
"ripple",
"tezos",
+ "tron",
]
SCREEN_TEXT_WIDTHS = {"TT": 240 - 12, "TS3": 128}
diff --git a/legacy/firmware/protob/Makefile b/legacy/firmware/protob/Makefile
index 0bb20148..d933636d 100644
--- a/legacy/firmware/protob/Makefile
+++ b/legacy/firmware/protob/Makefile
@@ -2,7 +2,7 @@ ifneq ($(V),1)
Q := @
endif
-SKIPPED_MESSAGES := Cardano DebugMonero Eos Monero Ontology Ripple SdProtect Tezos WebAuthn \
+SKIPPED_MESSAGES := Cardano DebugMonero Eos Monero Ontology Ripple SdProtect Tezos Tron WebAuthn \
DebugLinkGetPairingInfo DebugLinkPairingInfo DebugLinkGetGcInfo DebugLinkGcInfoItem \
DebugLinkGcInfo DebugLinkRecordScreen DebugLinkEraseSdCard DebugLinkWatchLayout \
DebugLinkLayout DebugLinkResetDebugEvents GetNonce \
diff --git a/python/docs/OPTIONS.rst b/python/docs/OPTIONS.rst
index f3a76aaa..c1e2fd58 100644
--- a/python/docs/OPTIONS.rst
+++ b/python/docs/OPTIONS.rst
@@ -62,6 +62,7 @@ on one page here.
solana Solana commands.
stellar Stellar commands.
tezos Tezos commands.
+ tron Tron commands.
usb-reset Perform USB reset on stuck devices.
version Show version of trezorctl/trezorlib.
wait-for-emulator Wait until Trezor Emulator comes up.
diff --git a/python/src/trezorlib/cli/trezorctl.py b/python/src/trezorlib/cli/trezorctl.py
index aba13b34..781322b5 100755
--- a/python/src/trezorlib/cli/trezorctl.py
+++ b/python/src/trezorlib/cli/trezorctl.py
@@ -53,6 +53,7 @@ from . import (
stellar,
tezos,
with_session,
+ tron,
)
F = TypeVar("F", bound=Callable)
@@ -84,6 +85,7 @@ COMMAND_ALIASES = {
"xrp": ripple.cli,
"xlm": stellar.cli,
"xtz": tezos.cli,
+ "trx": tron.cli,
# firmware aliases:
"fw": firmware.cli,
"update-firmware": firmware.update,
@@ -435,6 +437,7 @@ cli.add_command(settings.cli)
cli.add_command(solana.cli)
cli.add_command(stellar.cli)
cli.add_command(tezos.cli)
+cli.add_command(tron.cli)
cli.add_command(firmware.cli)
cli.add_command(debug.cli)
diff --git a/python/src/trezorlib/cli/tron.py b/python/src/trezorlib/cli/tron.py
new file mode 100644
index 00000000..7bc83c01
--- /dev/null
+++ b/python/src/trezorlib/cli/tron.py
@@ -0,0 +1,35 @@
+from typing import TYPE_CHECKING
+
+import click
+
+from .. import tools, tron
+from . import with_client
+
+if TYPE_CHECKING:
+ from ..client import TrezorClient
+
+PATH_HELP = "BIP-32 path to key, e.g. m/44h/195h/0h/0/0"
+
+
+@click.group(name="tron")
+def cli() -> None:
+ """Tron commands."""
+
+
+@cli.command()
+@click.option(
+ "-n",
+ "--address",
+ required=False,
+ help=PATH_HELP,
+ default=tron.DEFAULT_BIP32_PATH,
+)
+@click.option("-d", "--show-display", is_flag=True)
+@click.option("-C", "--chunkify", is_flag=True)
+@with_client
+def get_address(
+ client: "TrezorClient", address: str, show_display: bool, chunkify: bool
+) -> str:
+ """Get Tron address"""
+ address_n = tools.parse_path(address)
+ return tron.get_address(client, address_n, show_display, chunkify)
diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py
index 36d157cb..426bf735 100644
--- a/python/src/trezorlib/messages.py
+++ b/python/src/trezorlib/messages.py
@@ -682,6 +682,8 @@ class MessageType(IntEnum):
EvoluRegistrationRequest = 2103
EvoluGetDelegatedIdentityKey = 2104
EvoluDelegatedIdentityKey = 2105
+ TronGetAddress = 3000
+ TronAddress = 3001
BenchmarkListNames = 9100
BenchmarkNames = 9101
BenchmarkRun = 9102
diff --git a/python/src/trezorlib/tron.py b/python/src/trezorlib/tron.py
new file mode 100644
index 00000000..364caf3f
--- /dev/null
+++ b/python/src/trezorlib/tron.py
@@ -0,0 +1,27 @@
+from typing import TYPE_CHECKING, Any
+
+from . import messages
+
+if TYPE_CHECKING:
+ from .client import TrezorClient
+ from .tools import Address
+
+DEFAULT_BIP32_PATH = "m/44h/195h/0h/0/0"
+
+
+def get_address(*args: Any, **kwargs: Any) -> str:
+ return get_authenticated_address(*args, **kwargs).address
+
+
+def get_authenticated_address(
+ client: "TrezorClient",
+ address_n: "Address",
+ show_display: bool = False,
+ chunkify: bool = False,
+) -> messages.TronAddress:
+ return client.call(
+ messages.TronGetAddress(
+ address_n=address_n, show_display=show_display, chunkify=chunkify
+ ),
+ expect=messages.TronAddress,
+ )
diff --git a/rust/trezor-client/Cargo.toml b/rust/trezor-client/Cargo.toml
index e37f3b10..9c1f9b48 100644
--- a/rust/trezor-client/Cargo.toml
+++ b/rust/trezor-client/Cargo.toml
@@ -72,4 +72,5 @@ ripple = []
solana = []
stellar = []
tezos = []
+tron = []
webauthn = []
diff --git a/rust/trezor-client/README.md b/rust/trezor-client/README.md
index 0dc9820a..c5c3a409 100644
--- a/rust/trezor-client/README.md
+++ b/rust/trezor-client/README.md
@@ -23,7 +23,7 @@ Last tested with firmware v2.4.2.
## Features
- `bitcoin` and `ethereum`: client implementation and full support;
-- `cardano`, `monero`, `nem`, `ripple`, `stellar` and `tezos`: only protobuf bindings.
+- `cardano`, `monero`, `nem`, `ripple`, `stellar`, `tezos` and `tron`: only protobuf bindings.
## Credits
diff --git a/rust/trezor-client/scripts/build_messages b/rust/trezor-client/scripts/build_messages
index 707830e8..5dfd73f5 100755
--- a/rust/trezor-client/scripts/build_messages
+++ b/rust/trezor-client/scripts/build_messages
@@ -29,6 +29,7 @@ FEATURES = {
"Solana": "solana",
"Stellar": "stellar",
"Tezos": "tezos",
+ "Tron": "tron",
"WebAuthn": "webauthn",
}
MACRO = "trezor_message_impl"
diff --git a/rust/trezor-client/src/messages/generated.rs b/rust/trezor-client/src/messages/generated.rs
index eb0f95b9..32ca32b1 100644
--- a/rust/trezor-client/src/messages/generated.rs
+++ b/rust/trezor-client/src/messages/generated.rs
@@ -307,6 +307,12 @@ trezor_message_impl! {
TezosPublicKey => MessageType_TezosPublicKey,
}
+#[cfg(feature = "tron")]
+trezor_message_impl! {
+ TronGetAddress => MessageType_TronGetAddress,
+ TronAddress => MessageType_TronAddress,
+}
+
#[cfg(feature = "webauthn")]
trezor_message_impl! {
WebAuthnListResidentCredentials => MessageType_WebAuthnListResidentCredentials,
diff --git a/rust/trezor-client/src/protos/generated/messages.rs b/rust/trezor-client/src/protos/generated/messages.rs
index 98bf636c..26ef4d77 100644
--- a/rust/trezor-client/src/protos/generated/messages.rs
+++ b/rust/trezor-client/src/protos/generated/messages.rs
@@ -543,6 +543,10 @@ pub enum MessageType {
MessageType_EvoluGetDelegatedIdentityKey = 2104,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.MessageType.MessageType_EvoluDelegatedIdentityKey)
MessageType_EvoluDelegatedIdentityKey = 2105,
+ // @@protoc_insertion_point(enum_value:hw.trezor.messages.MessageType.MessageType_TronGetAddress)
+ MessageType_TronGetAddress = 3000,
+ // @@protoc_insertion_point(enum_value:hw.trezor.messages.MessageType.MessageType_TronAddress)
+ MessageType_TronAddress = 3001,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.MessageType.MessageType_BenchmarkListNames)
MessageType_BenchmarkListNames = 9100,
// @@protoc_insertion_point(enum_value:hw.trezor.messages.MessageType.MessageType_BenchmarkNames)
@@ -820,6 +824,8 @@ impl ::protobuf::Enum for MessageType {
2103 => ::std::option::Option::Some(MessageType::MessageType_EvoluRegistrationRequest),
2104 => ::std::option::Option::Some(MessageType::MessageType_EvoluGetDelegatedIdentityKey),
2105 => ::std::option::Option::Some(MessageType::MessageType_EvoluDelegatedIdentityKey),
+ 3000 => ::std::option::Option::Some(MessageType::MessageType_TronGetAddress),
+ 3001 => ::std::option::Option::Some(MessageType::MessageType_TronAddress),
9100 => ::std::option::Option::Some(MessageType::MessageType_BenchmarkListNames),
9101 => ::std::option::Option::Some(MessageType::MessageType_BenchmarkNames),
9102 => ::std::option::Option::Some(MessageType::MessageType_BenchmarkRun),
@@ -1088,6 +1094,8 @@ impl ::protobuf::Enum for MessageType {
"MessageType_EvoluRegistrationRequest" => ::std::option::Option::Some(MessageType::MessageType_EvoluRegistrationRequest),
"MessageType_EvoluGetDelegatedIdentityKey" => ::std::option::Option::Some(MessageType::MessageType_EvoluGetDelegatedIdentityKey),
"MessageType_EvoluDelegatedIdentityKey" => ::std::option::Option::Some(MessageType::MessageType_EvoluDelegatedIdentityKey),
+ "MessageType_TronGetAddress" => ::std::option::Option::Some(MessageType::MessageType_TronGetAddress),
+ "MessageType_TronAddress" => ::std::option::Option::Some(MessageType::MessageType_TronAddress),
"MessageType_BenchmarkListNames" => ::std::option::Option::Some(MessageType::MessageType_BenchmarkListNames),
"MessageType_BenchmarkNames" => ::std::option::Option::Some(MessageType::MessageType_BenchmarkNames),
"MessageType_BenchmarkRun" => ::std::option::Option::Some(MessageType::MessageType_BenchmarkRun),
@@ -1355,6 +1363,8 @@ impl ::protobuf::Enum for MessageType {
MessageType::MessageType_EvoluRegistrationRequest,
MessageType::MessageType_EvoluGetDelegatedIdentityKey,
MessageType::MessageType_EvoluDelegatedIdentityKey,
+ MessageType::MessageType_TronGetAddress,
+ MessageType::MessageType_TronAddress,
MessageType::MessageType_BenchmarkListNames,
MessageType::MessageType_BenchmarkNames,
MessageType::MessageType_BenchmarkRun,
diff --git a/rust/trezor-client/src/protos/generated/messages_tron.rs b/rust/trezor-client/src/protos/generated/messages_tron.rs
new file mode 100644
index 00000000..975ec011
--- /dev/null
+++ b/rust/trezor-client/src/protos/generated/messages_tron.rs
@@ -0,0 +1,478 @@
+// This file is generated by rust-protobuf 3.7.2. Do not edit
+// .proto file is parsed by protoc 3.19.6
+// @generated
+
+// https://github.com/rust-lang/rust-clippy/issues/702
+#![allow(unknown_lints)]
+#![allow(clippy::all)]
+
+#![allow(unused_attributes)]
+#![cfg_attr(rustfmt, rustfmt::skip)]
+
+#![allow(dead_code)]
+#![allow(missing_docs)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(non_upper_case_globals)]
+#![allow(trivial_casts)]
+#![allow(unused_results)]
+#![allow(unused_mut)]
+
+//! Generated file from `messages-tron.proto`
+
+/// Generated files are compatible only with the same version
+/// of protobuf runtime.
+const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_7_2;
+
+// @@protoc_insertion_point(message:hw.trezor.messages.tron.TronGetAddress)
+#[derive(PartialEq,Clone,Default,Debug)]
+pub struct TronGetAddress {
+ // message fields
+ // @@protoc_insertion_point(field:hw.trezor.messages.tron.TronGetAddress.address_n)
+ pub address_n: ::std::vec::Vec<u32>,
+ // @@protoc_insertion_point(field:hw.trezor.messages.tron.TronGetAddress.show_display)
+ pub show_display: ::std::option::Option<bool>,
+ // @@protoc_insertion_point(field:hw.trezor.messages.tron.TronGetAddress.chunkify)
+ pub chunkify: ::std::option::Option<bool>,
+ // special fields
+ // @@protoc_insertion_point(special_field:hw.trezor.messages.tron.TronGetAddress.special_fields)
+ pub special_fields: ::protobuf::SpecialFields,
+}
+
+impl<'a> ::std::default::Default for &'a TronGetAddress {
+ fn default() -> &'a TronGetAddress {
+ <TronGetAddress as ::protobuf::Message>::default_instance()
+ }
+}
+
+impl TronGetAddress {
+ pub fn new() -> TronGetAddress {
+ ::std::default::Default::default()
+ }
+
+ // optional bool show_display = 2;
+
+ pub fn show_display(&self) -> bool {
+ self.show_display.unwrap_or(false)
+ }
+
+ pub fn clear_show_display(&mut self) {
+ self.show_display = ::std::option::Option::None;
+ }
+
+ pub fn has_show_display(&self) -> bool {
+ self.show_display.is_some()
+ }
+
+ // Param is passed by value, moved
+ pub fn set_show_display(&mut self, v: bool) {
+ self.show_display = ::std::option::Option::Some(v);
+ }
+
+ // optional bool chunkify = 3;
+
+ pub fn chunkify(&self) -> bool {
+ self.chunkify.unwrap_or(false)
+ }
+
+ pub fn clear_chunkify(&mut self) {
+ self.chunkify = ::std::option::Option::None;
+ }
+
+ pub fn has_chunkify(&self) -> bool {
+ self.chunkify.is_some()
+ }
+
+ // Param is passed by value, moved
+ pub fn set_chunkify(&mut self, v: bool) {
+ self.chunkify = ::std::option::Option::Some(v);
+ }
+
+ fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
+ let mut fields = ::std::vec::Vec::with_capacity(3);
+ let mut oneofs = ::std::vec::Vec::with_capacity(0);
+ fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
+ "address_n",
+ |m: &TronGetAddress| { &m.address_n },
+ |m: &mut TronGetAddress| { &mut m.address_n },
+ ));
+ fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
+ "show_display",
+ |m: &TronGetAddress| { &m.show_display },
+ |m: &mut TronGetAddress| { &mut m.show_display },
+ ));
+ fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
+ "chunkify",
+ |m: &TronGetAddress| { &m.chunkify },
+ |m: &mut TronGetAddress| { &mut m.chunkify },
+ ));
+ ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<TronGetAddress>(
+ "TronGetAddress",
+ fields,
+ oneofs,
+ )
+ }
+}
+
+impl ::protobuf::Message for TronGetAddress {
+ const NAME: &'static str = "TronGetAddress";
+
+ fn is_initialized(&self) -> bool {
+ true
+ }
+
+ fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
+ while let Some(tag) = is.read_raw_tag_or_eof()? {
+ match tag {
+ 10 => {
+ is.read_repeated_packed_uint32_into(&mut self.address_n)?;
+ },
+ 8 => {
+ self.address_n.push(is.read_uint32()?);
+ },
+ 16 => {
+ self.show_display = ::std::option::Option::Some(is.read_bool()?);
+ },
+ 24 => {
+ self.chunkify = ::std::option::Option::Some(is.read_bool()?);
+ },
+ tag => {
+ ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
+ },
+ };
+ }
+ ::std::result::Result::Ok(())
+ }
+
+ // Compute sizes of nested messages
+ #[allow(unused_variables)]
+ fn compute_size(&self) -> u64 {
+ let mut my_size = 0;
+ for value in &self.address_n {
+ my_size += ::protobuf::rt::uint32_size(1, *value);
+ };
+ if let Some(v) = self.show_display {
+ my_size += 1 + 1;
+ }
+ if let Some(v) = self.chunkify {
+ my_size += 1 + 1;
+ }
+ my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
+ self.special_fields.cached_size().set(my_size as u32);
+ my_size
+ }
+
+ fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
+ for v in &self.address_n {
+ os.write_uint32(1, *v)?;
+ };
+ if let Some(v) = self.show_display {
+ os.write_bool(2, v)?;
+ }
+ if let Some(v) = self.chunkify {
+ os.write_bool(3, v)?;
+ }
+ os.write_unknown_fields(self.special_fields.unknown_fields())?;
+ ::std::result::Result::Ok(())
+ }
+
+ fn special_fields(&self) -> &::protobuf::SpecialFields {
+ &self.special_fields
+ }
+
+ fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
+ &mut self.special_fields
+ }
+
+ fn new() -> TronGetAddress {
+ TronGetAddress::new()
+ }
+
+ fn clear(&mut self) {
+ self.address_n.clear();
+ self.show_display = ::std::option::Option::None;
+ self.chunkify = ::std::option::Option::None;
+ self.special_fields.clear();
+ }
+
+ fn default_instance() -> &'static TronGetAddress {
+ static instance: TronGetAddress = TronGetAddress {
+ address_n: ::std::vec::Vec::new(),
+ show_display: ::std::option::Option::None,
+ chunkify: ::std::option::Option::None,
+ special_fields: ::protobuf::SpecialFields::new(),
+ };
+ &instance
+ }
+}
+
+impl ::protobuf::MessageFull for TronGetAddress {
+ fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
+ static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
+ descriptor.get(|| file_descriptor().message_by_package_relative_name("TronGetAddress").unwrap()).clone()
+ }
+}
+
+impl ::std::fmt::Display for TronGetAddress {
+ fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+ ::protobuf::text_format::fmt(self, f)
+ }
+}
+
+impl ::protobuf::reflect::ProtobufValue for TronGetAddress {
+ type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
+}
+
+// @@protoc_insertion_point(message:hw.trezor.messages.tron.TronAddress)
+#[derive(PartialEq,Clone,Default,Debug)]
+pub struct TronAddress {
+ // message fields
+ // @@protoc_insertion_point(field:hw.trezor.messages.tron.TronAddress.address)
+ pub address: ::std::option::Option<::std::string::String>,
+ // @@protoc_insertion_point(field:hw.trezor.messages.tron.TronAddress.mac)
+ pub mac: ::std::option::Option<::std::vec::Vec<u8>>,
+ // special fields
+ // @@protoc_insertion_point(special_field:hw.trezor.messages.tron.TronAddress.special_fields)
+ pub special_fields: ::protobuf::SpecialFields,
+}
+
+impl<'a> ::std::default::Default for &'a TronAddress {
+ fn default() -> &'a TronAddress {
+ <TronAddress as ::protobuf::Message>::default_instance()
+ }
+}
+
+impl TronAddress {
+ pub fn new() -> TronAddress {
+ ::std::default::Default::default()
+ }
+
+ // required string address = 1;
+
+ pub fn address(&self) -> &str {
+ match self.address.as_ref() {
+ Some(v) => v,
+ None => "",
+ }
+ }
+
+ pub fn clear_address(&mut self) {
+ self.address = ::std::option::Option::None;
+ }
+
+ pub fn has_address(&self) -> bool {
+ self.address.is_some()
+ }
+
+ // Param is passed by value, moved
+ pub fn set_address(&mut self, v: ::std::string::String) {
+ self.address = ::std::option::Option::Some(v);
+ }
+
+ // Mutable pointer to the field.
+ // If field is not initialized, it is initialized with default value first.
+ pub fn mut_address(&mut self) -> &mut ::std::string::String {
+ if self.address.is_none() {
+ self.address = ::std::option::Option::Some(::std::string::String::new());
+ }
+ self.address.as_mut().unwrap()
+ }
+
+ // Take field
+ pub fn take_address(&mut self) -> ::std::string::String {
+ self.address.take().unwrap_or_else(|| ::std::string::String::new())
+ }
+
+ // optional bytes mac = 2;
+
+ pub fn mac(&self) -> &[u8] {
+ match self.mac.as_ref() {
+ Some(v) => v,
+ None => &[],
+ }
+ }
+
+ pub fn clear_mac(&mut self) {
+ self.mac = ::std::option::Option::None;
+ }
+
+ pub fn has_mac(&self) -> bool {
+ self.mac.is_some()
+ }
+
+ // Param is passed by value, moved
+ pub fn set_mac(&mut self, v: ::std::vec::Vec<u8>) {
+ self.mac = ::std::option::Option::Some(v);
+ }
+
+ // Mutable pointer to the field.
+ // If field is not initialized, it is initialized with default value first.
+ pub fn mut_mac(&mut self) -> &mut ::std::vec::Vec<u8> {
+ if self.mac.is_none() {
+ self.mac = ::std::option::Option::Some(::std::vec::Vec::new());
+ }
+ self.mac.as_mut().unwrap()
+ }
+
+ // Take field
+ pub fn take_mac(&mut self) -> ::std::vec::Vec<u8> {
+ self.mac.take().unwrap_or_else(|| ::std::vec::Vec::new())
+ }
+
+ fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
+ let mut fields = ::std::vec::Vec::with_capacity(2);
+ let mut oneofs = ::std::vec::Vec::with_capacity(0);
+ fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
+ "address",
+ |m: &TronAddress| { &m.address },
+ |m: &mut TronAddress| { &mut m.address },
+ ));
+ fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
+ "mac",
+ |m: &TronAddress| { &m.mac },
+ |m: &mut TronAddress| { &mut m.mac },
+ ));
+ ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<TronAddress>(
+ "TronAddress",
+ fields,
+ oneofs,
+ )
+ }
+}
+
+impl ::protobuf::Message for TronAddress {
+ const NAME: &'static str = "TronAddress";
+
+ fn is_initialized(&self) -> bool {
+ if self.address.is_none() {
+ return false;
+ }
+ true
+ }
+
+ fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
+ while let Some(tag) = is.read_raw_tag_or_eof()? {
+ match tag {
+ 10 => {
+ self.address = ::std::option::Option::Some(is.read_string()?);
+ },
+ 18 => {
+ self.mac = ::std::option::Option::Some(is.read_bytes()?);
+ },
+ tag => {
+ ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
+ },
+ };
+ }
+ ::std::result::Result::Ok(())
+ }
+
+ // Compute sizes of nested messages
+ #[allow(unused_variables)]
+ fn compute_size(&self) -> u64 {
+ let mut my_size = 0;
+ if let Some(v) = self.address.as_ref() {
+ my_size += ::protobuf::rt::string_size(1, &v);
+ }
+ if let Some(v) = self.mac.as_ref() {
+ my_size += ::protobuf::rt::bytes_size(2, &v);
+ }
+ my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
+ self.special_fields.cached_size().set(my_size as u32);
+ my_size
+ }
+
+ fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
+ if let Some(v) = self.address.as_ref() {
+ os.write_string(1, v)?;
+ }
+ if let Some(v) = self.mac.as_ref() {
+ os.write_bytes(2, v)?;
+ }
+ os.write_unknown_fields(self.special_fields.unknown_fields())?;
+ ::std::result::Result::Ok(())
+ }
+
+ fn special_fields(&self) -> &::protobuf::SpecialFields {
+ &self.special_fields
+ }
+
+ fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
+ &mut self.special_fields
+ }
+
+ fn new() -> TronAddress {
+ TronAddress::new()
+ }
+
+ fn clear(&mut self) {
+ self.address = ::std::option::Option::None;
+ self.mac = ::std::option::Option::None;
+ self.special_fields.clear();
+ }
+
+ fn default_instance() -> &'static TronAddress {
+ static instance: TronAddress = TronAddress {
+ address: ::std::option::Option::None,
+ mac: ::std::option::Option::None,
+ special_fields: ::protobuf::SpecialFields::new(),
+ };
+ &instance
+ }
+}
+
+impl ::protobuf::MessageFull for TronAddress {
+ fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
+ static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
+ descriptor.get(|| file_descriptor().message_by_package_relative_name("TronAddress").unwrap()).clone()
+ }
+}
+
+impl ::std::fmt::Display for TronAddress {
+ fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
+ ::protobuf::text_format::fmt(self, f)
+ }
+}
+
+impl ::protobuf::reflect::ProtobufValue for TronAddress {
+ type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+ \n\x13messages-tron.proto\x12\x17hw.trezor.messages.tron\"l\n\x0eTronGet\
+ Address\x12\x1b\n\taddress_n\x18\x01\x20\x03(\rR\x08addressN\x12!\n\x0cs\
+ how_display\x18\x02\x20\x01(\x08R\x0bshowDisplay\x12\x1a\n\x08chunkify\
+ \x18\x03\x20\x01(\x08R\x08chunkify\"9\n\x0bTronAddress\x12\x18\n\x07addr\
+ ess\x18\x01\x20\x02(\tR\x07address\x12\x10\n\x03mac\x18\x02\x20\x01(\x0c\
+ R\x03macB8\n#com.satoshilabs.trezor.lib.protobufB\x11TrezorMessageTron\
+";
+
+/// `FileDescriptorProto` object which was a source for this generated file
+fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
+ static file_descriptor_proto_lazy: ::protobuf::rt::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::Lazy::new();
+ file_descriptor_proto_lazy.get(|| {
+ ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
+ })
+}
+
+/// `FileDescriptor` object which allows dynamic access to files
+pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
+ static generated_file_descriptor_lazy: ::protobuf::rt::Lazy<::protobuf::reflect::GeneratedFileDescriptor> = ::protobuf::rt::Lazy::new();
+ static file_descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::FileDescriptor> = ::protobuf::rt::Lazy::new();
+ file_descriptor.get(|| {
+ let generated_file_descriptor = generated_file_descriptor_lazy.get(|| {
+ let mut deps = ::std::vec::Vec::with_capacity(0);
+ let mut messages = ::std::vec::Vec::with_capacity(2);
+ messages.push(TronGetAddress::generated_message_descriptor_data());
+ messages.push(TronAddress::generated_message_descriptor_data());
+ let mut enums = ::std::vec::Vec::with_capacity(0);
+ ::protobuf::reflect::GeneratedFileDescriptor::new_generated(
+ file_descriptor_proto(),
+ deps,
+ messages,
+ enums,
+ )
+ });
+ ::protobuf::reflect::FileDescriptor::new_generated_2(generated_file_descriptor)
+ })
+}
diff --git a/rust/trezor-client/src/protos/mod.rs b/rust/trezor-client/src/protos/mod.rs
index 70d1b5fe..3a04f0ac 100644
--- a/rust/trezor-client/src/protos/mod.rs
+++ b/rust/trezor-client/src/protos/mod.rs
@@ -40,6 +40,7 @@ mod generated {
"solana" => messages_solana
"stellar" => messages_stellar
"tezos" => messages_tezos
+ "tron" => messages_tron
"webauthn" => messages_webauthn
}
}
diff --git a/tests/REGISTERED_MARKERS b/tests/REGISTERED_MARKERS
index 04312043..24d610cb 100644
--- a/tests/REGISTERED_MARKERS
+++ b/tests/REGISTERED_MARKERS
@@ -16,4 +16,5 @@ sd_card
solana
stellar
tezos
+tron
zcash
diff --git a/tests/click_tests/record_layout.py b/tests/click_tests/record_layout.py
index 64be71ab..e4b76d06 100644
--- a/tests/click_tests/record_layout.py
+++ b/tests/click_tests/record_layout.py
@@ -28,6 +28,7 @@ from trezorlib import (
ripple,
stellar,
tezos,
+ tron,
)
from trezorlib.cli.trezorctl import cli as main
@@ -48,6 +49,7 @@ MODULES = (
ripple,
stellar,
tezos,
+ tron,
)
diff --git a/tests/device_tests/tron/__init__.py b/tests/device_tests/tron/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/tests/device_tests/tron/test_get_address.py b/tests/device_tests/tron/test_get_address.py
new file mode 100644
index 00000000..839b34d9
--- /dev/null
+++ b/tests/device_tests/tron/test_get_address.py
@@ -0,0 +1,27 @@
+import pytest
+
+from trezorlib import tron
+from trezorlib.debuglink import TrezorClientDebugLink as Client
+from trezorlib.tools import parse_path
+
+from ...common import parametrize_using_common_fixtures
+from ...input_flows import InputFlowShowAddressQRCode
+
+pytestmark = [pytest.mark.altcoin, pytest.mark.tron, pytest.mark.models("core")]
+
+
+@parametrize_using_common_fixtures("tron/get_address.json")
+def test_get_address(client: Client, parameters, result):
+ address_n = parse_path(parameters["path"])
+ address = tron.get_address(client, address_n, show_display=True)
+ assert address == result["address"]
+
+
+@parametrize_using_common_fixtures("tron/get_address.json")
+def test_get_address_chunkify_details(client: Client, parameters, result):
+ with client:
+ IF = InputFlowShowAddressQRCode(client)
+ client.set_input_flow(IF.get())
+ address_n = parse_path(parameters["path"])
+ address = tron.get_address(client, address_n, show_display=True, chunkify=True)
+ assert address == result["address"]
diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json
index af8bc2a5..a18c145c 100644
--- a/tests/ui_tests/fixtures.json
+++ b/tests/ui_tests/fixtures.json
@@ -5758,6 +5758,16 @@
"T2T1_en_tezos-test_sign_tx.py::test_tezos_smart_contract_delegation": "52b560920aeb19572b8779cd8f01e1c52c918501b795bfdebde4f20e9fe1be01",
"T2T1_en_tezos-test_sign_tx.py::test_tezos_smart_contract_transfer": "dc89195ee58bf9aaea643ba1919b94627aa93f84c14ae65e7ce4072bbe87fe07",
"T2T1_en_tezos-test_sign_tx.py::test_tezos_smart_contract_transfer_to_contract": "53277bbff8dd0cfc963a9caec361e4d714d449dcf973acbd9af3807bfe51af6e",
+"T2T1_en_tron-test_get_address.py::test_get_address[parameters0-result0]": "6cd5dee16026532c5eb4bf5e9c323661b08ebdc3dbf8e9838abdade43e5cdcf9",
+"T2T1_en_tron-test_get_address.py::test_get_address[parameters1-result1]": "35f2a369e3eac90e52af907adf4c34fc4e6d1acdabacbafb56b202a9bbcfdd5f",
+"T2T1_en_tron-test_get_address.py::test_get_address[parameters2-result2]": "6ed20aa9e624647d921be37c30dce728761aa0c34f20f4deae9f12a7bf83998f",
+"T2T1_en_tron-test_get_address.py::test_get_address[parameters3-result3]": "757344d330733592d9759d726cb5b783229a78c27753651900e3e07d0de51c68",
+"T2T1_en_tron-test_get_address.py::test_get_address[parameters4-result4]": "74e587c2f69279e3287374d48c446bd4ab79ee5b0ef29cb63240e70982bd0bde",
+"T2T1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters0-result0]": "40703b2b1eb0bcf56103f3ca5f9de906c0b9081ac52383a0d385388e4294d9b0",
+"T2T1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters1-result1]": "1746a1f26cacad85c43309888ed7916042bb965519f44fdf252bc70079159c49",
+"T2T1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters2-result2]": "45197db18f54011fab988ca06f89248d120b30a2ddc627dc6037d625a9b77e9e",
+"T2T1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters3-result3]": "c2816c52bf151db0e05cd8b516a4e8f3cfdc0f7023663932c7406465fda77348",
+"T2T1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters4-result4]": "9e95307d17f2a6d4008c51ba425b5d3733f892a9e7bd58aa17bb81ed73246249",
"T2T1_en_webauthn-test_msg_webauthn.py::test_add_remove": "3e750190e9608a1ea76f00e5ec220576cc7842567c1f01c61a1d5b11ed3ed7c2",
"T2T1_en_webauthn-test_u2f_counter.py::test_u2f_counter": "f740248e1b4e4289052807569a0a1defdd88d8fc0532a47850da0ea26277276d",
"T2T1_en_zcash-test_sign_tx.py::test_external_presigned": "2492bd16ea82738cec9778d3afed746d21da8181d7e2782b701fa240dffbb42a",
@@ -15181,6 +15191,16 @@
"T3B1_en_tezos-test_sign_tx.py::test_tezos_smart_contract_delegation": "cc50720f6ffef257e64d9752d1959d4dfcb1f29a6227719434b030d7de40077d",
"T3B1_en_tezos-test_sign_tx.py::test_tezos_smart_contract_transfer": "0b352a3f187ef10ac9057194508facbf726c9a720c51b0e36fb7ba991d3e2de2",
"T3B1_en_tezos-test_sign_tx.py::test_tezos_smart_contract_transfer_to_contract": "8849dd6d70cc9109c84e2716396f96c390c39857361b63c5f494a96af91cf5fa",
+"T3B1_en_tron-test_get_address.py::test_get_address[parameters0-result0]": "55e02edf6022c8cf402a3a6fbfbb845326280b6ca168781989184f8493a61776",
+"T3B1_en_tron-test_get_address.py::test_get_address[parameters1-result1]": "ecb1c74313d53bd1ecfe6560e090515fb7efd35421c6b5702866b52087df7192",
+"T3B1_en_tron-test_get_address.py::test_get_address[parameters2-result2]": "2b4268f6feb8323a788ed836e3b9cc56de733ec005fb10ccff015c05bca1d41f",
+"T3B1_en_tron-test_get_address.py::test_get_address[parameters3-result3]": "0a88400447bebe78a49731adef743f59ad9cacf026adcf6634ea7ad27a2a7d8b",
+"T3B1_en_tron-test_get_address.py::test_get_address[parameters4-result4]": "dedeffe9573db86b1626a83e4c10e0a0d679f82e4b6db3d9fdbec6845a76eb0d",
+"T3B1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters0-result0]": "6b69576e0b00a1475832496363c0a1c9ec43821f65234217dce7fba009ff3f46",
+"T3B1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters1-result1]": "2f6c9534bfb311a67c24a4bc30d4b5cb57cac994268c8aba89513e21ea529ade",
+"T3B1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters2-result2]": "11a436458eb83fc2f7123e2cc35efa4ec6ba25461d781afe1bfda1a4a9299292",
+"T3B1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters3-result3]": "f7959b4955aacde49001e6bc5a78249409e541d7a4eef6b8f8fa0e4b228e3c57",
+"T3B1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters4-result4]": "69336c030fa424d7d59076429f68af919ec1eb31361848147a8b58bcf562ddcd",
"T3B1_en_webauthn-test_msg_webauthn.py::test_add_remove": "540214b367b638082b9beb67e492b59b5ac523b5dedb972ace9b4caca974ef6e",
"T3B1_en_webauthn-test_u2f_counter.py::test_u2f_counter": "49f01fce798fe9d5a22cea12d7f276fb91cd77c04087b1dd2c3e37a6106cc350",
"T3B1_en_zcash-test_sign_tx.py::test_external_presigned": "6bc1f0b265163f105b4b084e518a23e6a248849f3141d82dbe25538a43d69883",
@@ -24518,6 +24538,16 @@
"T3T1_en_tezos-test_sign_tx.py::test_tezos_smart_contract_delegation": "f5677d6f97040c38ff905e98592b081159f48eeb3ef7c88679fd9d5ca188e3b6",
"T3T1_en_tezos-test_sign_tx.py::test_tezos_smart_contract_transfer": "e851fb3fc4ccdf02279f78d073426dd542efa19eee98a542bfdd710f03adac47",
"T3T1_en_tezos-test_sign_tx.py::test_tezos_smart_contract_transfer_to_contract": "b44acbfa6842550050a469f673d8b95709eb2cf6c6994c19bd85ddc52f284fa2",
+"T3T1_en_tron-test_get_address.py::test_get_address[parameters0-result0]": "3ab3b0d2260cc26cad72db0f605386e7bf3748309ffed11d4ce6c5239fc8c1c5",
+"T3T1_en_tron-test_get_address.py::test_get_address[parameters1-result1]": "da21e176bb32edad8eb3b1f33519583565feaa1c085d5aee4d69937b0ff04622",
+"T3T1_en_tron-test_get_address.py::test_get_address[parameters2-result2]": "94ed3b42b3d7e047ea09b199039d104f20768ca47c08d3433f9fd2d3ccb46bd1",
+"T3T1_en_tron-test_get_address.py::test_get_address[parameters3-result3]": "41ef39efce3994f2833718c3cd22e29ea39799bece5a6c8846cb0e243b7f4961",
+"T3T1_en_tron-test_get_address.py::test_get_address[parameters4-result4]": "12b67255b4ca83ecefbdd84ca03af1435b55e1d9f0c0c52cb3f0738ef0cd710f",
+"T3T1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters0-result0]": "62da1521d5672c09eca0e4da1671af6178dced03d3d9817216c8477dffc43179",
+"T3T1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters1-result1]": "61c62fdf8aa02d61a055cde175a6ee6422d4e9fbd836d9cb425fe97061d0b424",
+"T3T1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters2-result2]": "dda6ab26cdc8b87513cb103ea59fb4bfedc1a7eab5b3315387b80e6966aeb0ef",
+"T3T1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters3-result3]": "ad33d464f3c232d23b0c39a99285644e6c04da6273e8f1baa9dd402d26aa81f9",
+"T3T1_en_tron-test_get_address.py::test_get_address_chunkify_details[parameters4-result4]": "d37c7fd865110a5aef5e447fb091fb1e945603bb8c85b29c542aa62f8d3a1a8f",
"T3T1_en_webauthn-test_msg_webauthn.py::test_add_remove": "95351793ff4ed12276b36d9223bff9456adce515a4ec26e72c966b351c32e179",
"T3T1_en_webauthn-test_u2f_counter.py::test_u2f_counter": "b81ea8c63aa65f04c3f42b6da5b8c4fda384013d468ca7b24a446863984cc788",
"T3T1_en_zcash-test_sign_tx.py::test_external_presigned": "085efb36e91998d277faa56ba28564d2233b7bde8517c2f810270e40dc3ca8bf",
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.