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

refactor(core): make ethereum summary reusable for more coins

- and use it for Solana
This commit is contained in:
gabrielkerekes 2023-12-01 16:18:58 +01:00 committed by matejcik
parent 0dff9390db
commit a8096652e0
7 changed files with 119 additions and 42 deletions

View File

@ -24,10 +24,12 @@ static void _librust_qstrs(void) {
MP_QSTR_address_label;
MP_QSTR_address_title;
MP_QSTR_allow_cancel;
MP_QSTR_altcoin_tx_summary;
MP_QSTR_amount;
MP_QSTR_amount_change;
MP_QSTR_amount_new;
MP_QSTR_amount_title;
MP_QSTR_amount_value;
MP_QSTR_app_name;
MP_QSTR_attach_timer_fn;
MP_QSTR_bootscreen;
@ -35,6 +37,7 @@ static void _librust_qstrs(void) {
MP_QSTR_button;
MP_QSTR_button_event;
MP_QSTR_cancel_arrow;
MP_QSTR_cancel_cross;
MP_QSTR_case_sensitive;
MP_QSTR_check_homescreen_format;
MP_QSTR_chunkify;
@ -69,11 +72,12 @@ static void _librust_qstrs(void) {
MP_QSTR_dry_run;
MP_QSTR_encode;
MP_QSTR_encoded_length;
MP_QSTR_ethereum_tx_summary;
MP_QSTR_extra;
MP_QSTR_fee_amount;
MP_QSTR_fee_label;
MP_QSTR_fee_rate_amount;
MP_QSTR_fee_title;
MP_QSTR_fee_value;
MP_QSTR_fingerprint;
MP_QSTR_hold;
MP_QSTR_hold_danger;
@ -90,7 +94,6 @@ static void _librust_qstrs(void) {
MP_QSTR_max_feerate;
MP_QSTR_max_len;
MP_QSTR_max_rounds;
MP_QSTR_maximum_fee;
MP_QSTR_min_count;
MP_QSTR_multiple_pages_texts;
MP_QSTR_notification;

View File

@ -751,32 +751,39 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, block) }
}
extern "C" fn new_ethereum_tx_summary(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
extern "C" fn new_altcoin_tx_summary(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = |_args: &[Obj], kwargs: &Map| {
let total_amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_total_amount)?.try_into()?;
let maximum_fee: StrBuffer = kwargs.get(Qstr::MP_QSTR_maximum_fee)?.try_into()?;
let amount_title: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount_title)?.try_into()?;
let amount_value: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount_value)?.try_into()?;
let fee_title: StrBuffer = kwargs.get(Qstr::MP_QSTR_fee_title)?.try_into()?;
let fee_value: StrBuffer = kwargs.get(Qstr::MP_QSTR_fee_value)?.try_into()?;
let cancel_cross: bool = kwargs.get_or(Qstr::MP_QSTR_cancel_cross, false)?;
let items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
let get_page = move |page_index| {
match page_index {
0 => {
// Total amount + fee
let btn_layout = ButtonLayout::up_arrow_armed_info("CONFIRM".into());
// Amount + fee
let btn_layout = if cancel_cross {
ButtonLayout::cancel_armed_info("CONFIRM".into())
} else {
ButtonLayout::up_arrow_armed_info("CONFIRM".into())
};
let btn_actions = ButtonActions::cancel_confirm_next();
let ops = OpTextLayout::new(theme::TEXT_MONO)
.text_mono(total_amount.clone())
.text_mono(amount_value.clone())
.newline()
.newline_half()
.text_bold("Maximum fee:".into())
.text_bold(fee_title.clone())
.newline()
.text_mono(maximum_fee.clone());
.text_mono(fee_value.clone());
let formatted = FormattedText::new(ops);
Page::new(btn_layout, btn_actions, formatted).with_title("Amount:".into())
Page::new(btn_layout, btn_actions, formatted).with_title(amount_title.clone())
}
1 => {
// Fee information
// Other information
let btn_layout = ButtonLayout::arrow_none_none();
let btn_actions = ButtonActions::prev_none_none();
@ -1793,14 +1800,17 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// """Confirm summary of a transaction."""
Qstr::MP_QSTR_confirm_total => obj_fn_kw!(0, new_confirm_total).as_obj(),
/// def ethereum_tx_summary(
/// def altcoin_tx_summary(
/// *,
/// total_amount: str,
/// maximum_fee: str,
/// amount_title: str,
/// amount_value: str,
/// fee_title: str,
/// fee_value: str,
/// items: Iterable[Tuple[str, str]],
/// cancel_cross: bool = False,
/// ) -> object:
/// """Confirm details about Ethereum transaction."""
Qstr::MP_QSTR_ethereum_tx_summary => obj_fn_kw!(0, new_ethereum_tx_summary).as_obj(),
/// """Confirm details about altcoin transaction."""
Qstr::MP_QSTR_altcoin_tx_summary => obj_fn_kw!(0, new_altcoin_tx_summary).as_obj(),
/// def tutorial() -> object:
/// """Show user how to interact with the device."""

View File

@ -749,7 +749,7 @@ extern "C" fn new_show_info_with_cancel(n_args: usize, args: *const Obj, kwargs:
let [key, value]: [Obj; 2] = iter_into_array(para)?;
let key: StrBuffer = key.try_into()?;
let value: StrBuffer = value.try_into()?;
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, key));
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, key).no_break());
paragraphs.add(Paragraph::new(&theme::TEXT_MONO, value));
}
@ -812,7 +812,7 @@ extern "C" fn new_confirm_total(n_args: usize, args: *const Obj, kwargs: *mut Ma
for pair in IterBuf::new().try_iterate(items)? {
let [label, value]: [StrBuffer; 2] = iter_into_array(pair)?;
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, label));
paragraphs.add(Paragraph::new(&theme::TEXT_NORMAL, label).no_break());
paragraphs.add(Paragraph::new(&theme::TEXT_MONO, value));
}
let mut page: ButtonPage<_, StrBuffer> =
@ -1757,7 +1757,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
/// def confirm_total(
/// *,
/// title: str,
/// items: list[tuple[str, str]],
/// items: Iterable[tuple[str, str]],
/// info_button: bool = False,
/// cancel_arrow: bool = False,
/// ) -> object:

View File

@ -169,13 +169,16 @@ def confirm_total(
# rust/src/ui/model_tr/layout.rs
def ethereum_tx_summary(
def altcoin_tx_summary(
*,
total_amount: str,
maximum_fee: str,
amount_title: str,
amount_value: str,
fee_title: str,
fee_value: str,
items: Iterable[Tuple[str, str]],
cancel_cross: bool = False,
) -> object:
"""Confirm details about Ethereum transaction."""
"""Confirm details about altcoin transaction."""
# rust/src/ui/model_tr/layout.rs
@ -586,7 +589,7 @@ def confirm_value(
def confirm_total(
*,
title: str,
items: list[tuple[str, str]],
items: Iterable[tuple[str, str]],
info_button: bool = False,
cancel_arrow: bool = False,
) -> object:

View File

@ -991,6 +991,33 @@ async def confirm_total(
)
async def confirm_solana_tx(
amount: str,
fee: str,
items: Iterable[tuple[str, str]],
amount_title="Amount:",
fee_title="Fee",
br_type: str = "confirm_solana_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
):
await 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=items,
cancel_cross=True,
)
),
br_type=br_type,
br_code=br_code,
)
)
async def confirm_ethereum_tx(
recipient: str,
total_amount: str,
@ -1001,9 +1028,11 @@ async def confirm_ethereum_tx(
chunkify: bool = False,
) -> None:
summary_layout = RustLayout(
trezorui2.ethereum_tx_summary(
total_amount=total_amount,
maximum_fee=maximum_fee,
trezorui2.altcoin_tx_summary(
amount_title="Amount:",
amount_value=total_amount,
fee_title="Maximum fee:",
fee_value=maximum_fee,
items=items,
)
)

View File

@ -901,33 +901,48 @@ async def confirm_properties(
async def confirm_total(
total_amount: str,
fee_amount: str,
fee_rate_amount: str | None = None,
title: str = "SUMMARY",
total_label: str = "Total amount:",
fee_label: str = "Including fee:",
account_label: str | None = None,
fee_rate_amount: str | None = None,
br_type: str = "confirm_total",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
items = [
(total_label, total_amount),
(fee_label, fee_amount),
]
info_items = []
if account_label:
info_items.append(("Sending from account:", account_label))
if fee_rate_amount:
info_items.append(("Fee rate:", fee_rate_amount))
await confirm_summary(
items, "SUMMARY", info_items, br_type=br_type, br_code=br_code
)
async def confirm_summary(
items: Iterable[tuple[str, str]],
title: str = "SUMMARY",
info_items: Iterable[tuple[str, str]] | None = None,
br_type: str = "confirm_total",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
) -> None:
total_layout = RustLayout(
trezorui2.confirm_total(
title=title,
items=[
(total_label, total_amount),
(fee_label, fee_amount),
],
info_button=bool(account_label or fee_rate_amount),
title=title.upper(),
items=items,
info_button=bool(info_items),
)
)
items: list[tuple[str, str]] = []
if account_label:
items.append(("Sending from account:", account_label))
if fee_rate_amount:
items.append(("Fee rate:", fee_rate_amount))
info_items = info_items or []
info_layout = RustLayout(
trezorui2.show_info_with_cancel(
title="INFORMATION",
items=items,
items=info_items,
)
)
await raise_if_not_confirmed(with_info(total_layout, info_layout, br_type, br_code))
@ -980,6 +995,23 @@ async def confirm_ethereum_tx(
continue
async def confirm_solana_tx(
amount: str,
fee: str,
items: Iterable[tuple[str, str]],
amount_title="Amount:",
fee_title="Fee",
br_type: str = "confirm_solana_tx",
br_code: ButtonRequestType = ButtonRequestType.SignTx,
):
await confirm_summary(
((amount_title, amount), (fee_title, fee)),
info_items=items,
br_type=br_type,
br_code=br_code,
)
async def confirm_joint_total(spending_amount: str, total_amount: str) -> None:
await raise_if_not_confirmed(
interact(

View File

@ -6,7 +6,7 @@ EXCEPTIONS+=( "decred" ) # "decred" figures in field names used by the bitcoin
EXCEPTIONS+=( "omni" ) # OMNI is part of the bitcoin app
# BIP39 or SLIP39 words that have "dash" in them
EXCEPTIONS+=( "dash" )
EXCEPTIONS+=( "confirm_ethereum_tx" "ethereum_tx_summary" ) # is model-specific, so is in layout/__init__.py instead of ethereum/layout.py
EXCEPTIONS+=( "confirm_ethereum_tx" ) # is model-specific, so is in layout/__init__.py instead of ethereum/layout.py
GREP_ARGS=()
for exception in "${EXCEPTIONS[@]}"; do