Skip to content

Commit 4f33166

Browse files
committed
feat(tron): Add support for VoteWitnessContract - core
- Main logic. Scaffolding in previous commit. - Supports up to 9 candidates. - Each layout needs some variation - Figma design available. [no changelog]
1 parent 8e11074 commit 4f33166

9 files changed

Lines changed: 92 additions & 8 deletions

File tree

core/src/apps/tron/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Therefore, we do not show any fees to the user on the device. The host applicati
3232
- [X] `FreezeBalanceV2`: Stake `TRX` to get more `Bandwidth` or `Energy`
3333
- [X] `UnfreezeBalanceV2`: Unstake frozen `TRX`
3434
- [X] `WithdrawExpireUnfreeze`: Claim Unstaked `TRX` past their lock-up period
35-
- [ ] `VoteWitnessAccount`: Vote using earned TRON Power. **Coming soon**
35+
- [X] `VoteWitnessAccount`: Vote using earned TRON Power.
3636

3737
### Notes
3838

core/src/apps/tron/consts.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,11 @@
66
from buffer_types import AnyBytes
77
from typing import Iterator, Tuple
88

9-
from trezor.messages import TronTransferContract
10-
11-
TronMessageType = TronTransferContract
12-
139
TYPE_URL_TEMPLATE = "type.googleapis.com/protocol."
1410

15-
# TODO: Use TypeVar like ethereum/keychain.py:MsgInSignTx
1611
CONTRACT_TYPES = (
1712
MessageType.TronTransferContract,
13+
MessageType.TronVoteWitnessContract,
1814
MessageType.TronTriggerSmartContract,
1915
MessageType.TronFreezeBalanceV2Contract,
2016
MessageType.TronUnfreezeBalanceV2Contract,

core/src/apps/tron/layout.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
if TYPE_CHECKING:
1010
from buffer_types import AnyBytes
1111

12-
from trezor.messages import TronTransferContract, TronTriggerSmartContract
12+
from trezor.messages import (
13+
TronTransferContract,
14+
TronTriggerSmartContract,
15+
TronVoteWitnessContract,
16+
)
1317

1418

1519
def format_trx_amount(amount: int) -> str:
@@ -154,3 +158,13 @@ async def confirm_withdraw_unfreeze(owner_address: AnyBytes) -> None:
154158
br_name="tron/claim",
155159
cancel=True,
156160
)
161+
162+
163+
async def confirm_votes(contract: TronVoteWitnessContract) -> None:
164+
from trezor.ui.layouts import confirm_tron_voting
165+
166+
voting_list: list[tuple[int, str]] = [
167+
(vote.count, get_encoded_address(vote.address))
168+
for vote in contract.votes
169+
]
170+
await confirm_tron_voting(voting_list)

core/src/apps/tron/sign_tx.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ async def sign_tx(msg: TronSignTx, keychain: Keychain) -> TronSignature:
5656
if fee_limit > _MAX_FEE_LIMIT:
5757
raise DataError("Tron: fees too high")
5858

59+
# TODO: CONTRACT_TYPES are all the Tron message types. Can we do better than manually writing them again in consts.py?
5960
contract = await call_any(messages.TronContractRequest(), *consts.CONTRACT_TYPES)
6061
raw_contract = await process_contract(contract, fee_limit)
6162

@@ -89,11 +90,12 @@ async def process_contract(
8990
# But it causes type error in messages.TronRawContract.type.
9091
from trezor import TR
9192
from trezor.enums import TronRawContractType
92-
from trezor.ui.layouts import confirm_tron_send
9393

9494
_INT64_MAX = const(9_223_372_036_854_775_807)
9595

9696
if messages.TronTransferContract.is_type_of(contract):
97+
from trezor.ui.layouts import confirm_tron_send
98+
9799
contract_type = TronRawContractType.TransferContract
98100
await layout.confirm_transfer_contract(contract)
99101
if contract.amount > _INT64_MAX:
@@ -148,6 +150,9 @@ async def process_contract(
148150
contract_type = TronRawContractType.WithdrawExpireUnfreezeContract
149151
await layout.confirm_withdraw_unfreeze(contract.owner_address)
150152

153+
elif messages.TronVoteWitnessContract.is_type_of(contract):
154+
contract_type = TronRawContractType.VoteWitnessContract
155+
await layout.confirm_votes(contract)
151156
else:
152157
raise DataError("Tron: contract type unknown")
153158

core/src/trezor/ui/layouts/bolt/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,17 @@ async def confirm_tron_transfer(
16091609
None,
16101610
)
16111611

1612+
async def confirm_tron_voting(voting_list: list[tuple[int, str]]) -> None:
1613+
await raise_if_not_confirmed(
1614+
trezorui_api.confirm_properties(
1615+
title=TR.words__review,
1616+
items=[(f"{TR.words__votes}: {vote[0]}", f"{vote[1]}\n", True) for vote in voting_list],
1617+
hold=True,
1618+
),
1619+
br_name="tron/vote",
1620+
br_code=ButtonRequestType.SignTx,
1621+
)
1622+
16121623

16131624
def confirm_joint_total(spending_amount: str, total_amount: str) -> Awaitable[None]:
16141625
return raise_if_not_confirmed(

core/src/trezor/ui/layouts/caesar/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,6 +1672,18 @@ async def confirm_tron_transfer(
16721672
br_name=br_name,
16731673
)
16741674

1675+
async def confirm_tron_voting(voting_list: list[tuple[int, str]]) -> None:
1676+
await raise_if_not_confirmed(
1677+
trezorui_api.confirm_properties(
1678+
title=TR.words__review,
1679+
subtitle=TR.words__voting,
1680+
items=[(f"{TR.words__votes}: {vote[0]}", vote[1], True) for vote in voting_list],
1681+
hold=True,
1682+
),
1683+
br_name="tron/vote",
1684+
br_code=ButtonRequestType.SignTx,
1685+
)
1686+
16751687

16761688
def confirm_joint_total(spending_amount: str, total_amount: str) -> Awaitable[None]:
16771689
return confirm_properties(

core/src/trezor/ui/layouts/delizia/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,24 @@ async def confirm_tron_approve(
15651565
None,
15661566
)
15671567

1568+
async def confirm_tron_voting(voting_list: list[tuple[int, str]]) -> None:
1569+
1570+
item_list : list[StrPropertyType] = []
1571+
for vote_count, address in voting_list:
1572+
item_list.append((TR.words__address, address, True))
1573+
item_list.append((f"\n{TR.words__votes}", f"{vote_count}", False))
1574+
1575+
await raise_if_not_confirmed(
1576+
trezorui_api.confirm_properties(
1577+
title=TR.words__review,
1578+
subtitle=TR.words__voting,
1579+
items=item_list,
1580+
hold=True,
1581+
),
1582+
br_name="tron/vote",
1583+
br_code=ButtonRequestType.SignTx,
1584+
)
1585+
15681586

15691587
def confirm_joint_total(spending_amount: str, total_amount: str) -> Awaitable[None]:
15701588
return _confirm_summary(

core/src/trezor/ui/layouts/eckhart/__init__.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,24 @@ async def confirm_tron_approve(
16621662
None,
16631663
)
16641664

1665+
async def confirm_tron_voting(voting_list: list[tuple[int, str]]) -> None:
1666+
1667+
item_list : list[StrPropertyType] = []
1668+
for vote_count, address in voting_list:
1669+
item_list.append((TR.words__address, address, True))
1670+
item_list.append((f"\n{TR.words__votes}", f"{vote_count}", False))
1671+
1672+
await raise_if_not_confirmed(
1673+
trezorui_api.confirm_properties(
1674+
title=TR.words__review,
1675+
subtitle=TR.words__voting,
1676+
items=item_list,
1677+
hold=True,
1678+
),
1679+
br_name="tron/vote",
1680+
br_code=ButtonRequestType.SignTx,
1681+
)
1682+
16651683

16661684
def confirm_joint_total(spending_amount: str, total_amount: str) -> Awaitable[None]:
16671685
return _confirm_summary(

python/src/trezorlib/tron.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
messages.TronFreezeBalanceV2Contract,
1515
messages.TronUnfreezeBalanceV2Contract,
1616
messages.TronWithdrawUnfreeze,
17+
messages.TronVoteWitnessContract,
1718
]
1819

1920
DEFAULT_BIP32_PATH = "m/44h/195h/0h/0/0"
@@ -86,6 +87,15 @@ def from_raw_data(
8687
contract = messages.TronWithdrawUnfreeze(
8788
owner_address=raw_contract.owner_address,
8889
)
90+
elif contract_type == messages.TronRawContractType.VoteWitnessContract:
91+
raw_contract = load_message(
92+
io.BytesIO(parameter_value),
93+
messages.TronVoteWitnessContract,
94+
)
95+
contract = messages.TronVoteWitnessContract(
96+
owner_address=raw_contract.owner_address,
97+
votes=raw_contract.votes
98+
)
8999
else:
90100
raise ValueError(f"Unsupported contract type: {contract_type}")
91101

0 commit comments

Comments
 (0)