mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 07:28:10 +00:00
refactor(core): make ethereum summary reusable for more coins
- and use it for Solana
This commit is contained in:
parent
0dff9390db
commit
a8096652e0
@ -24,10 +24,12 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_address_label;
|
MP_QSTR_address_label;
|
||||||
MP_QSTR_address_title;
|
MP_QSTR_address_title;
|
||||||
MP_QSTR_allow_cancel;
|
MP_QSTR_allow_cancel;
|
||||||
|
MP_QSTR_altcoin_tx_summary;
|
||||||
MP_QSTR_amount;
|
MP_QSTR_amount;
|
||||||
MP_QSTR_amount_change;
|
MP_QSTR_amount_change;
|
||||||
MP_QSTR_amount_new;
|
MP_QSTR_amount_new;
|
||||||
MP_QSTR_amount_title;
|
MP_QSTR_amount_title;
|
||||||
|
MP_QSTR_amount_value;
|
||||||
MP_QSTR_app_name;
|
MP_QSTR_app_name;
|
||||||
MP_QSTR_attach_timer_fn;
|
MP_QSTR_attach_timer_fn;
|
||||||
MP_QSTR_bootscreen;
|
MP_QSTR_bootscreen;
|
||||||
@ -35,6 +37,7 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_button;
|
MP_QSTR_button;
|
||||||
MP_QSTR_button_event;
|
MP_QSTR_button_event;
|
||||||
MP_QSTR_cancel_arrow;
|
MP_QSTR_cancel_arrow;
|
||||||
|
MP_QSTR_cancel_cross;
|
||||||
MP_QSTR_case_sensitive;
|
MP_QSTR_case_sensitive;
|
||||||
MP_QSTR_check_homescreen_format;
|
MP_QSTR_check_homescreen_format;
|
||||||
MP_QSTR_chunkify;
|
MP_QSTR_chunkify;
|
||||||
@ -69,11 +72,12 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_dry_run;
|
MP_QSTR_dry_run;
|
||||||
MP_QSTR_encode;
|
MP_QSTR_encode;
|
||||||
MP_QSTR_encoded_length;
|
MP_QSTR_encoded_length;
|
||||||
MP_QSTR_ethereum_tx_summary;
|
|
||||||
MP_QSTR_extra;
|
MP_QSTR_extra;
|
||||||
MP_QSTR_fee_amount;
|
MP_QSTR_fee_amount;
|
||||||
MP_QSTR_fee_label;
|
MP_QSTR_fee_label;
|
||||||
MP_QSTR_fee_rate_amount;
|
MP_QSTR_fee_rate_amount;
|
||||||
|
MP_QSTR_fee_title;
|
||||||
|
MP_QSTR_fee_value;
|
||||||
MP_QSTR_fingerprint;
|
MP_QSTR_fingerprint;
|
||||||
MP_QSTR_hold;
|
MP_QSTR_hold;
|
||||||
MP_QSTR_hold_danger;
|
MP_QSTR_hold_danger;
|
||||||
@ -90,7 +94,6 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_max_feerate;
|
MP_QSTR_max_feerate;
|
||||||
MP_QSTR_max_len;
|
MP_QSTR_max_len;
|
||||||
MP_QSTR_max_rounds;
|
MP_QSTR_max_rounds;
|
||||||
MP_QSTR_maximum_fee;
|
|
||||||
MP_QSTR_min_count;
|
MP_QSTR_min_count;
|
||||||
MP_QSTR_multiple_pages_texts;
|
MP_QSTR_multiple_pages_texts;
|
||||||
MP_QSTR_notification;
|
MP_QSTR_notification;
|
||||||
|
@ -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) }
|
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 block = |_args: &[Obj], kwargs: &Map| {
|
||||||
let total_amount: StrBuffer = kwargs.get(Qstr::MP_QSTR_total_amount)?.try_into()?;
|
let amount_title: StrBuffer = kwargs.get(Qstr::MP_QSTR_amount_title)?.try_into()?;
|
||||||
let maximum_fee: StrBuffer = kwargs.get(Qstr::MP_QSTR_maximum_fee)?.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 items: Obj = kwargs.get(Qstr::MP_QSTR_items)?;
|
||||||
|
|
||||||
let get_page = move |page_index| {
|
let get_page = move |page_index| {
|
||||||
match page_index {
|
match page_index {
|
||||||
0 => {
|
0 => {
|
||||||
// Total amount + fee
|
// Amount + fee
|
||||||
let btn_layout = ButtonLayout::up_arrow_armed_info("CONFIRM".into());
|
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 btn_actions = ButtonActions::cancel_confirm_next();
|
||||||
|
|
||||||
let ops = OpTextLayout::new(theme::TEXT_MONO)
|
let ops = OpTextLayout::new(theme::TEXT_MONO)
|
||||||
.text_mono(total_amount.clone())
|
.text_mono(amount_value.clone())
|
||||||
.newline()
|
.newline()
|
||||||
.newline_half()
|
.newline_half()
|
||||||
.text_bold("Maximum fee:".into())
|
.text_bold(fee_title.clone())
|
||||||
.newline()
|
.newline()
|
||||||
.text_mono(maximum_fee.clone());
|
.text_mono(fee_value.clone());
|
||||||
|
|
||||||
let formatted = FormattedText::new(ops);
|
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 => {
|
1 => {
|
||||||
// Fee information
|
// Other information
|
||||||
let btn_layout = ButtonLayout::arrow_none_none();
|
let btn_layout = ButtonLayout::arrow_none_none();
|
||||||
let btn_actions = ButtonActions::prev_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."""
|
/// """Confirm summary of a transaction."""
|
||||||
Qstr::MP_QSTR_confirm_total => obj_fn_kw!(0, new_confirm_total).as_obj(),
|
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,
|
/// amount_title: str,
|
||||||
/// maximum_fee: str,
|
/// amount_value: str,
|
||||||
|
/// fee_title: str,
|
||||||
|
/// fee_value: str,
|
||||||
/// items: Iterable[Tuple[str, str]],
|
/// items: Iterable[Tuple[str, str]],
|
||||||
|
/// cancel_cross: bool = False,
|
||||||
/// ) -> object:
|
/// ) -> object:
|
||||||
/// """Confirm details about Ethereum transaction."""
|
/// """Confirm details about altcoin transaction."""
|
||||||
Qstr::MP_QSTR_ethereum_tx_summary => obj_fn_kw!(0, new_ethereum_tx_summary).as_obj(),
|
Qstr::MP_QSTR_altcoin_tx_summary => obj_fn_kw!(0, new_altcoin_tx_summary).as_obj(),
|
||||||
|
|
||||||
/// def tutorial() -> object:
|
/// def tutorial() -> object:
|
||||||
/// """Show user how to interact with the device."""
|
/// """Show user how to interact with the device."""
|
||||||
|
@ -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, value]: [Obj; 2] = iter_into_array(para)?;
|
||||||
let key: StrBuffer = key.try_into()?;
|
let key: StrBuffer = key.try_into()?;
|
||||||
let value: StrBuffer = value.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));
|
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)? {
|
for pair in IterBuf::new().try_iterate(items)? {
|
||||||
let [label, value]: [StrBuffer; 2] = iter_into_array(pair)?;
|
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));
|
paragraphs.add(Paragraph::new(&theme::TEXT_MONO, value));
|
||||||
}
|
}
|
||||||
let mut page: ButtonPage<_, StrBuffer> =
|
let mut page: ButtonPage<_, StrBuffer> =
|
||||||
@ -1757,7 +1757,7 @@ pub static mp_module_trezorui2: Module = obj_module! {
|
|||||||
/// def confirm_total(
|
/// def confirm_total(
|
||||||
/// *,
|
/// *,
|
||||||
/// title: str,
|
/// title: str,
|
||||||
/// items: list[tuple[str, str]],
|
/// items: Iterable[tuple[str, str]],
|
||||||
/// info_button: bool = False,
|
/// info_button: bool = False,
|
||||||
/// cancel_arrow: bool = False,
|
/// cancel_arrow: bool = False,
|
||||||
/// ) -> object:
|
/// ) -> object:
|
||||||
|
@ -169,13 +169,16 @@ def confirm_total(
|
|||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_tr/layout.rs
|
# rust/src/ui/model_tr/layout.rs
|
||||||
def ethereum_tx_summary(
|
def altcoin_tx_summary(
|
||||||
*,
|
*,
|
||||||
total_amount: str,
|
amount_title: str,
|
||||||
maximum_fee: str,
|
amount_value: str,
|
||||||
|
fee_title: str,
|
||||||
|
fee_value: str,
|
||||||
items: Iterable[Tuple[str, str]],
|
items: Iterable[Tuple[str, str]],
|
||||||
|
cancel_cross: bool = False,
|
||||||
) -> object:
|
) -> object:
|
||||||
"""Confirm details about Ethereum transaction."""
|
"""Confirm details about altcoin transaction."""
|
||||||
|
|
||||||
|
|
||||||
# rust/src/ui/model_tr/layout.rs
|
# rust/src/ui/model_tr/layout.rs
|
||||||
@ -586,7 +589,7 @@ def confirm_value(
|
|||||||
def confirm_total(
|
def confirm_total(
|
||||||
*,
|
*,
|
||||||
title: str,
|
title: str,
|
||||||
items: list[tuple[str, str]],
|
items: Iterable[tuple[str, str]],
|
||||||
info_button: bool = False,
|
info_button: bool = False,
|
||||||
cancel_arrow: bool = False,
|
cancel_arrow: bool = False,
|
||||||
) -> object:
|
) -> object:
|
||||||
|
@ -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(
|
async def confirm_ethereum_tx(
|
||||||
recipient: str,
|
recipient: str,
|
||||||
total_amount: str,
|
total_amount: str,
|
||||||
@ -1001,9 +1028,11 @@ async def confirm_ethereum_tx(
|
|||||||
chunkify: bool = False,
|
chunkify: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
summary_layout = RustLayout(
|
summary_layout = RustLayout(
|
||||||
trezorui2.ethereum_tx_summary(
|
trezorui2.altcoin_tx_summary(
|
||||||
total_amount=total_amount,
|
amount_title="Amount:",
|
||||||
maximum_fee=maximum_fee,
|
amount_value=total_amount,
|
||||||
|
fee_title="Maximum fee:",
|
||||||
|
fee_value=maximum_fee,
|
||||||
items=items,
|
items=items,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -901,33 +901,48 @@ async def confirm_properties(
|
|||||||
async def confirm_total(
|
async def confirm_total(
|
||||||
total_amount: str,
|
total_amount: str,
|
||||||
fee_amount: str,
|
fee_amount: str,
|
||||||
fee_rate_amount: str | None = None,
|
|
||||||
title: str = "SUMMARY",
|
title: str = "SUMMARY",
|
||||||
total_label: str = "Total amount:",
|
total_label: str = "Total amount:",
|
||||||
fee_label: str = "Including fee:",
|
fee_label: str = "Including fee:",
|
||||||
account_label: str | None = None,
|
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_type: str = "confirm_total",
|
||||||
br_code: ButtonRequestType = ButtonRequestType.SignTx,
|
br_code: ButtonRequestType = ButtonRequestType.SignTx,
|
||||||
) -> None:
|
) -> None:
|
||||||
total_layout = RustLayout(
|
total_layout = RustLayout(
|
||||||
trezorui2.confirm_total(
|
trezorui2.confirm_total(
|
||||||
title=title,
|
title=title.upper(),
|
||||||
items=[
|
items=items,
|
||||||
(total_label, total_amount),
|
info_button=bool(info_items),
|
||||||
(fee_label, fee_amount),
|
|
||||||
],
|
|
||||||
info_button=bool(account_label or fee_rate_amount),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
items: list[tuple[str, str]] = []
|
info_items = info_items or []
|
||||||
if account_label:
|
|
||||||
items.append(("Sending from account:", account_label))
|
|
||||||
if fee_rate_amount:
|
|
||||||
items.append(("Fee rate:", fee_rate_amount))
|
|
||||||
info_layout = RustLayout(
|
info_layout = RustLayout(
|
||||||
trezorui2.show_info_with_cancel(
|
trezorui2.show_info_with_cancel(
|
||||||
title="INFORMATION",
|
title="INFORMATION",
|
||||||
items=items,
|
items=info_items,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
await raise_if_not_confirmed(with_info(total_layout, info_layout, br_type, br_code))
|
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
|
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:
|
async def confirm_joint_total(spending_amount: str, total_amount: str) -> None:
|
||||||
await raise_if_not_confirmed(
|
await raise_if_not_confirmed(
|
||||||
interact(
|
interact(
|
||||||
|
@ -6,7 +6,7 @@ EXCEPTIONS+=( "decred" ) # "decred" figures in field names used by the bitcoin
|
|||||||
EXCEPTIONS+=( "omni" ) # OMNI is part of the bitcoin app
|
EXCEPTIONS+=( "omni" ) # OMNI is part of the bitcoin app
|
||||||
# BIP39 or SLIP39 words that have "dash" in them
|
# BIP39 or SLIP39 words that have "dash" in them
|
||||||
EXCEPTIONS+=( "dash" )
|
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=()
|
GREP_ARGS=()
|
||||||
for exception in "${EXCEPTIONS[@]}"; do
|
for exception in "${EXCEPTIONS[@]}"; do
|
||||||
|
Loading…
Reference in New Issue
Block a user