1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 14:28:07 +00:00

feat(cardano): use nicer summary for send tx

Also show Recipient {i} for simple tx
This commit is contained in:
obrusvit 2024-10-04 17:17:14 +02:00 committed by Vít Obrusník
parent a3aacb7f13
commit 2c6a13064b
13 changed files with 147 additions and 33 deletions

View File

@ -0,0 +1 @@
Simplified UI of Cardano transactions initiated by Trezor Suite.

View File

@ -34,6 +34,7 @@ static void _librust_qstrs(void) {
MP_QSTR___name__;
MP_QSTR_account;
MP_QSTR_account_items;
MP_QSTR_account_items_title;
MP_QSTR_account_label;
MP_QSTR_account_path;
MP_QSTR_accounts;

View File

@ -86,6 +86,10 @@ impl ConfirmSummary {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
let account_items: Obj = kwargs.get(Qstr::MP_QSTR_account_items)?;
let account_items_title: Option<TString> = kwargs
.get(Qstr::MP_QSTR_account_items_title)
.unwrap_or(Obj::const_none())
.try_into_option()?;
let fee_items: Obj = kwargs.get(Qstr::MP_QSTR_fee_items)?;
let br_name: TString = kwargs.get(Qstr::MP_QSTR_br_name)?.try_into()?;
let br_code: u16 = kwargs.get(Qstr::MP_QSTR_br_code)?.try_into()?;
@ -134,7 +138,9 @@ impl ConfirmSummary {
// AccountInfo
let mut has_account_info = false;
let mut account = ShowInfoParams::new(TR::send__send_from.into()).with_cancel_button();
let mut account =
ShowInfoParams::new(account_items_title.unwrap_or(TR::send__send_from.into()))
.with_cancel_button();
for pair in IterBuf::new().try_iterate(account_items)? {
let [label, value]: [TString; 2] = util::iter_into_array(pair)?;
account = unwrap!(account.add(label, value));
@ -155,7 +161,7 @@ impl ConfirmSummary {
if has_account_info {
menu = menu.item(
theme::ICON_CHEVRON_RIGHT,
TR::address_details__account_info.into(),
account_items_title.unwrap_or(TR::address_details__account_info.into()),
);
unwrap!(menu_items.push(MENU_ITEM_ACCOUNT_INFO));
}

View File

@ -1702,6 +1702,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// title: str,
/// items: Iterable[tuple[str, str]],
/// account_items: Iterable[tuple[str, str]],
/// account_items_title: str | None,
/// fee_items: Iterable[tuple[str, str]],
/// br_code: ButtonRequestType,
/// br_name: str,

View File

@ -600,6 +600,7 @@ def flow_confirm_summary(
title: str,
items: Iterable[tuple[str, str]],
account_items: Iterable[tuple[str, str]],
account_items_title: str | None,
fee_items: Iterable[tuple[str, str]],
br_code: ButtonRequestType,
br_name: str,

View File

@ -218,11 +218,17 @@ async def confirm_sending(
ada_amount: int,
to: str,
output_type: Literal["address", "change", "collateral-return"],
output_index: int | None,
network_id: int,
chunkify: bool,
) -> None:
output_index_shown = None
if output_type == "address":
title = TR.cardano__sending
if output_index is None:
title = TR.cardano__sending
else:
title = None
output_index_shown = output_index
elif output_type == "change":
title = TR.cardano__change_output
elif output_type == "collateral-return":
@ -236,6 +242,7 @@ async def confirm_sending(
title,
br_code=ButtonRequestType.Other,
chunkify=chunkify,
output_index=output_index_shown,
)
@ -506,20 +513,49 @@ async def confirm_witness_request(
async def confirm_tx(
spending: int,
fee: int,
network_id: int,
protocol_magic: int,
ttl: int | None,
validity_interval_start: int | None,
) -> None:
total_amount = format_coin_amount(spending, network_id)
fee_amount = format_coin_amount(fee, network_id)
items = (
(TR.cardano__network, f"{protocol_magics.to_ui_string(protocol_magic)}"),
(TR.cardano__valid_since, f"{format_optional_int(validity_interval_start)}"),
(TR.cardano__ttl, f"{format_optional_int(ttl)}"),
)
await layouts.confirm_cardano_tx(
total_amount,
fee_amount,
items=items,
)
async def confirm_tx_details(
network_id: int,
protocol_magic: int,
ttl: int | None,
fee: int | None,
validity_interval_start: int | None,
total_collateral: int | None,
is_network_id_verifiable: bool,
tx_hash: bytes | None,
) -> None:
props: list[PropertyType] = [
(TR.cardano__transaction_fee, format_coin_amount(fee, network_id)),
]
props: list[PropertyType] = []
append = props.append # local_cache_attribute
if fee is not None:
append(
(
TR.cardano__transaction_fee,
format_coin_amount(fee, network_id),
)
)
if total_collateral is not None:
append(
(
@ -547,13 +583,14 @@ async def confirm_tx(
if tx_hash:
append((TR.cardano__transaction_id, tx_hash))
await confirm_properties(
"confirm_total",
TR.cardano__confirm_transaction,
props,
hold=True,
br_code=BRT_Other,
)
if props:
await confirm_properties(
"confirm_total",
TR.cardano__confirm_transaction,
props,
hold=True,
br_code=BRT_Other,
)
async def confirm_certificate(
@ -590,6 +627,7 @@ async def confirm_certificate(
"confirm_certificate",
TR.cardano__confirm_transaction,
props,
hold=False,
br_code=BRT_Other,
)

View File

@ -33,11 +33,11 @@ class MultisigSigner(Signer):
# super() omitted intentionally
is_network_id_verifiable = self._is_network_id_verifiable()
await layout.confirm_tx(
msg.fee,
await layout.confirm_tx_details(
msg.network_id,
msg.protocol_magic,
msg.ttl,
msg.fee,
msg.validity_interval_start,
msg.total_collateral,
is_network_id_verifiable,

View File

@ -92,8 +92,9 @@ class OrdinarySigner(Signer):
# super() omitted intentionally
msg = self.msg # local_cache_attribute
if self.suite_tx_type is SuiteTxType.SIMPLE_SEND:
spending = self.total_out + msg.fee - self.change_out
await layout.confirm_tx(
self.total_amount,
spending,
msg.fee,
msg.network_id,
msg.protocol_magic,

View File

@ -38,11 +38,11 @@ class PlutusSigner(Signer):
# computed by a trusted device (in case the tx contains many items which are
# tedious to check one by one on the Trezor screen).
is_network_id_verifiable = self._is_network_id_verifiable()
await layout.confirm_tx(
msg.fee,
await layout.confirm_tx_details(
msg.network_id,
msg.protocol_magic,
msg.ttl,
msg.fee,
msg.validity_interval_start,
msg.total_collateral,
is_network_id_verifiable,

View File

@ -109,6 +109,8 @@ class Signer:
self.msg = msg
self.keychain = keychain
self.total_out = 0 # sum of output amounts
self.change_out = 0 # sum of change amounts
self.account_path_checker = AccountPathChecker()
@ -257,7 +259,6 @@ class Signer:
raise ProcessError("Total collateral is out of range!")
validate_network_info(msg.network_id, msg.protocol_magic)
async def _show_tx_init(self) -> None:
self.should_show_details = await layout.show_tx_init(self.SIGNING_MODE_TITLE)
@ -292,25 +293,25 @@ class Signer:
# outputs
async def _process_outputs(self, outputs_list: HashBuilderList) -> None:
total_amount = 0
for _ in range(self.msg.outputs_count):
for output_index in range(self.msg.outputs_count):
output: CardanoTxOutput = await ctx_call(
CardanoTxItemAck(), CardanoTxOutput
)
await self._process_output(outputs_list, output)
await self._process_output(outputs_list, output, output_index)
self.total_out += output.amount
if self._is_change_output(output):
self.change_out += output.amount
total_amount += output.amount
if total_amount > LOVELACE_MAX_SUPPLY:
if self.total_out > LOVELACE_MAX_SUPPLY:
raise ProcessError("Total transaction amount is out of range!")
async def _process_output(
self, outputs_list: HashBuilderList, output: CardanoTxOutput
self, outputs_list: HashBuilderList, output: CardanoTxOutput, output_index: int
) -> None:
self._validate_output(output)
should_show = self._should_show_output(output)
if should_show:
await self._show_output_init(output)
await self._show_output_init(output, output_index)
output_items_count = 2 + sum(
(
@ -371,7 +372,9 @@ class Signer:
self.account_path_checker.add_output(output)
async def _show_output_init(self, output: CardanoTxOutput) -> None:
async def _show_output_init(
self, output: CardanoTxOutput, output_index: int
) -> None:
address_type = self._get_output_address_type(output)
if (
output.datum_hash is None
@ -395,14 +398,11 @@ class Signer:
assert output.address is not None # _validate_output
address = output.address
if self.suite_tx_type == SuiteTxType.SIMPLE_SEND:
output_type = n
else:
output_type = "change" if self._is_change_output(output) else "address"
await layout.confirm_sending(
output.amount,
address,
"change" if self._is_change_output(output) else "address",
output_index if self.suite_tx_type is SuiteTxType.SIMPLE_SEND else None,
self.msg.network_id,
chunkify=bool(self.msg.chunkify),
)
@ -1078,6 +1078,7 @@ class Signer:
output.amount,
address,
"collateral-return",
None,
self.msg.network_id,
chunkify=bool(self.msg.chunkify),
)

View File

@ -993,6 +993,7 @@ def confirm_total(
items=items,
fee_items=fee_items,
account_items=account_items,
account_items_title=None,
br_name=br_name,
br_code=br_code,
cancel_text=TR.send__cancel_sign,
@ -1011,7 +1012,6 @@ def _confirm_summary(
br_code: ButtonRequestType = ButtonRequestType.SignTx,
cancel_text: str | None = None,
) -> Awaitable[None]:
# TODO: info_title
title = title or TR.words__title_summary # def_arg
return raise_if_not_confirmed(
@ -1021,6 +1021,7 @@ def _confirm_summary(
items=items or (),
fee_items=fee_items or (),
account_items=info_items or (),
account_items_title=info_title,
br_name=br_name,
br_code=br_code,
cancel_text=cancel_text,
@ -1137,6 +1138,24 @@ if not utils.BITCOIN_ONLY:
br_code=br_code,
)
def confirm_cardano_tx(
amount: str,
fee: str,
items: Iterable[tuple[str, str]],
) -> Awaitable[None]:
amount_title = TR.send__total_amount
fee_title = TR.send__incl_transaction_fee
more_info_title = TR.buttons__more_info
return _confirm_summary(
items=((amount_title, amount), (fee_title, fee)),
info_items=items,
info_title=more_info_title,
fee_items=None,
br_name="confirm_cardano_tx",
br_code=ButtonRequestType.SignTx,
)
def confirm_joint_total(spending_amount: str, total_amount: str) -> Awaitable[None]:
return _confirm_summary(

View File

@ -1228,6 +1228,7 @@ if not utils.BITCOIN_ONLY:
amount_value=amount_value,
fee_title=f"{TR.send__maximum_fee}:",
fee_value=maximum_fee,
items_title=TR.confirm_total__title_fee,
items=[(f"{k}:", v) for (k, v) in info_items],
cancel_cross=True,
)
@ -1258,6 +1259,7 @@ if not utils.BITCOIN_ONLY:
amount_value=amount,
fee_title=fee_title,
fee_value=fee,
items_title=TR.confirm_total__title_fee,
items=items,
cancel_cross=True,
)
@ -1267,6 +1269,34 @@ if not utils.BITCOIN_ONLY:
)
)
def confirm_cardano_tx(
amount: str,
fee: str,
items: Iterable[tuple[str, str]],
amount_title: str | None = None,
fee_title: str | None = None,
) -> Awaitable[None]:
amount_title = f"{TR.send__total_amount}:"
fee_title = TR.send__including_fee
return raise_if_not_confirmed(
interact(
RustLayout(
trezorui2.altcoin_tx_summary(
amount_title=amount_title,
amount_value=amount,
fee_title=fee_title,
fee_value=fee,
items_title=TR.words__title_information,
items=items,
cancel_cross=True,
)
),
br_name="confirm_cardano_tx",
br_code=ButtonRequestType.SignTx,
)
)
async def confirm_ethereum_tx(
recipient: str,
total_amount: str,
@ -1284,6 +1314,7 @@ if not utils.BITCOIN_ONLY:
amount_value=total_amount,
fee_title=f"{TR.send__maximum_fee}:",
fee_value=maximum_fee,
items_title=TR.confirm_total__title_fee,
items=[(f"{k}:", v) for (k, v) in fee_info_items],
)
)

View File

@ -1208,6 +1208,20 @@ if not utils.BITCOIN_ONLY:
br_code=br_code,
)
def confirm_cardano_tx(
amount: str,
fee: str,
items: Iterable[tuple[str, str]],
) -> Awaitable[None]:
amount_title = f"{TR.send__total_amount}:"
fee_title = TR.send__including_fee
return _confirm_summary(
((amount_title, amount), (fee_title, fee)),
info_items=items,
br_name="confirm_cardano_tx",
br_code=ButtonRequestType.SignTx,
)
def confirm_joint_total(spending_amount: str, total_amount: str) -> Awaitable[None]:
return raise_if_not_confirmed(