1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-24 07:28:34 +00:00

chore(core/eckhart): update show_address flow

This commit is contained in:
Lukas Bielesch 2025-06-04 09:19:04 +02:00 committed by Lukáš Bielesch
parent 0c5e71e973
commit aa74ab922d
34 changed files with 138 additions and 47 deletions

View File

@ -82,6 +82,7 @@ static void _librust_qstrs(void) {
MP_QSTR_address__title_cosigner;
MP_QSTR_address__title_receive_address;
MP_QSTR_address__title_yours;
MP_QSTR_address__xpub;
MP_QSTR_address_details__account_info;
MP_QSTR_address_details__derivation_path;
MP_QSTR_address_details__derivation_path_colon;

View File

@ -1445,6 +1445,7 @@ pub enum TranslatedString {
recovery__share_from_group_entered_template = 1044, // "Share #{0} from Group #{1} entered."
send__cancel_transaction = 1045, // "Cancel transaction"
send__multisig_different_paths = 1046, // "Using different paths for different XPUBs."
address__xpub = 1047, // {"Bolt": "XPUB", "Caesar": "XPUB", "Delizia": "XPUB", "Eckhart": "Public key (XPUB)"}
}
impl TranslatedString {
@ -3195,6 +3196,14 @@ impl TranslatedString {
(Self::recovery__share_from_group_entered_template, "Share #{0} from Group #{1} entered."),
(Self::send__cancel_transaction, "Cancel transaction"),
(Self::send__multisig_different_paths, "Using different paths for different XPUBs."),
#[cfg(feature = "layout_bolt")]
(Self::address__xpub, "XPUB"),
#[cfg(feature = "layout_caesar")]
(Self::address__xpub, "XPUB"),
#[cfg(feature = "layout_delizia")]
(Self::address__xpub, "XPUB"),
#[cfg(feature = "layout_eckhart")]
(Self::address__xpub, "Public key (XPUB)"),
];
#[cfg(feature = "micropython")]
@ -3215,6 +3224,7 @@ impl TranslatedString {
(Qstr::MP_QSTR_address__title_cosigner, Self::address__title_cosigner),
(Qstr::MP_QSTR_address__title_receive_address, Self::address__title_receive_address),
(Qstr::MP_QSTR_address__title_yours, Self::address__title_yours),
(Qstr::MP_QSTR_address__xpub, Self::address__xpub),
(Qstr::MP_QSTR_address_details__account_info, Self::address_details__account_info),
(Qstr::MP_QSTR_address_details__derivation_path, Self::address_details__derivation_path),
(Qstr::MP_QSTR_address_details__derivation_path_colon, Self::address_details__derivation_path_colon),

View File

@ -543,6 +543,7 @@ extern "C" fn new_flow_confirm_set_new_pin(
extern "C" fn new_flow_get_address(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
let block = move |_args: &[Obj], kwargs: &Map| {
let title: TString = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?;
let subtitle: Option<TString> = kwargs.get(Qstr::MP_QSTR_subtitle)?.try_into_option()?;
let description: Option<TString> =
kwargs.get(Qstr::MP_QSTR_description)?.try_into_option()?;
let extra: Option<TString> = kwargs.get(Qstr::MP_QSTR_extra)?.try_into_option()?;
@ -559,6 +560,7 @@ extern "C" fn new_flow_get_address(n_args: usize, args: *const Obj, kwargs: *mut
let layout = ModelUI::flow_get_address(
address,
title,
subtitle,
description,
extra,
chunkify,
@ -1515,6 +1517,7 @@ pub static mp_module_trezorui_api: Module = obj_module! {
/// *,
/// address: str | bytes,
/// title: str,
/// subtitle: str | None,
/// description: str | None,
/// extra: str | None,
/// chunkify: bool,

View File

@ -212,3 +212,7 @@ pub fn get_user_custom_image() -> Result<BinaryData<'static>, Error> {
load_avatar(unsafe { Gc::<[u8]>::as_mut(&mut data) })?;
Ok(data.into())
}
/// Maximum number of extended public keys (xpubs) that can be displayed in
/// a layout or flow.
pub const MAX_XPUBS: usize = 16;

View File

@ -11,14 +11,13 @@ use crate::{
Component, Event, EventCtx, Paginate, Qr,
},
geometry::Rect,
layout::util::MAX_XPUBS,
shape::Renderer,
},
};
use super::{theme, Frame, FrameMsg};
const MAX_XPUBS: usize = 16;
pub struct AddressDetails {
qr_code: Frame<Qr>,
details: Frame<Paragraphs<ParagraphVecShort<'static>>>,

View File

@ -591,6 +591,7 @@ impl FirmwareUI for UIBolt {
fn flow_get_address(
_address: Obj,
_title: TString<'static>,
_subtitle: Option<TString<'static>>,
_description: Option<TString<'static>>,
_extra: Option<TString<'static>>,
_chunkify: bool,

View File

@ -11,6 +11,7 @@ use crate::{
Child, Component, Event, EventCtx, Pad, Paginate, Qr,
},
geometry::Rect,
layout::util::MAX_XPUBS,
shape::Renderer,
},
};
@ -19,7 +20,6 @@ use super::{
theme, ButtonController, ButtonControllerMsg, ButtonDetails, ButtonLayout, ButtonPos, Frame,
};
const MAX_XPUBS: usize = 16;
const QR_BORDER: i16 = 3;
pub struct AddressDetails {

View File

@ -727,6 +727,7 @@ impl FirmwareUI for UICaesar {
fn flow_get_address(
_address: Obj,
_title: TString<'static>,
_subtitle: Option<TString<'static>>,
_description: Option<TString<'static>>,
_extra: Option<TString<'static>>,
_chunkify: bool,

View File

@ -14,6 +14,7 @@ use crate::{
event::SwipeEvent,
flow::Swipable,
geometry::{Direction, Rect},
layout::util::MAX_XPUBS,
shape::Renderer,
util::Pager,
},
@ -21,8 +22,6 @@ use crate::{
use super::{theme, Frame, FrameMsg};
const MAX_XPUBS: usize = 16;
pub struct AddressDetails {
details: Frame<Paragraphs<ParagraphVecShort<'static>>>,
xpub_view: Frame<Paragraphs<Paragraph<'static>>>,

View File

@ -15,7 +15,7 @@ use crate::{
FlowController, FlowMsg, SwipeFlow, SwipePage,
},
geometry::Direction,
layout::util::ConfirmValueParams,
layout::util::{ConfirmValueParams, MAX_XPUBS},
},
};

View File

@ -621,6 +621,7 @@ impl FirmwareUI for UIDelizia {
fn flow_get_address(
address: Obj,
title: TString<'static>,
_subtitle: Option<TString<'static>>,
description: Option<TString<'static>>,
extra: Option<TString<'static>>,
chunkify: bool,

View File

@ -6,7 +6,9 @@ use crate::{
ui::{
button_request::ButtonRequest,
component::{
text::paragraphs::{Paragraph, ParagraphSource, ParagraphVecLong, VecExt},
text::paragraphs::{
Paragraph, ParagraphSource, ParagraphVecLong, ParagraphVecShort, VecExt,
},
ButtonRequestExt, ComponentExt, Qr,
},
flow::{
@ -14,6 +16,7 @@ use crate::{
FlowController, FlowMsg, SwipeFlow,
},
geometry::{Direction, LinearPlacement},
layout::util::MAX_XPUBS,
},
};
use heapless::Vec;
@ -29,7 +32,6 @@ use super::super::{
const ITEM_PADDING: i16 = 16;
const GROUP_PADDING: i16 = 20;
const MAX_XPUBS: usize = 3;
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum GetAddress {
@ -70,8 +72,9 @@ impl FlowController for GetAddress {
#[allow(clippy::too_many_arguments)]
pub fn new_get_address(
title: TString<'static>,
_description: Option<TString<'static>>,
_extra: Option<TString<'static>>,
subtitle: Option<TString<'static>>,
description: Option<TString<'static>>,
extra: Option<TString<'static>>,
address: Obj, // TODO: get rid of Obj
chunkify: bool,
address_qr: TString<'static>,
@ -82,29 +85,42 @@ pub fn new_get_address(
br_code: u16,
br_name: TString<'static>,
) -> Result<SwipeFlow, error::Error> {
// Address
let flow_title: TString = TR::words__receive.into();
let test_style = if chunkify {
let text_style = if chunkify {
let address: TString = address.try_into()?;
theme::get_chunkified_text_style(address.len())
} else {
&theme::TEXT_MONO_ADDRESS
};
let paragraphs = Paragraph::new(test_style, address.try_into().unwrap_or(TString::empty()))
.into_paragraphs()
.with_placement(LinearPlacement::vertical());
let content_address = TextScreen::new(paragraphs)
.with_header(Header::new(flow_title).with_menu_button())
.with_subtitle(title)
.with_action_bar(ActionBar::new_single(
Button::with_text(TR::buttons__confirm.into()).styled(theme::button_confirm()),
))
.with_hint(Hint::new_instruction(
TR::address__check_with_source,
Some(theme::ICON_INFO),
))
let mut paragraphs = ParagraphVecShort::new();
if let Some(description) = description {
paragraphs.add(
Paragraph::new(&theme::TEXT_SMALL_LIGHT, description).with_bottom_padding(ITEM_PADDING),
);
}
paragraphs.add(Paragraph::new(
text_style,
address.try_into().unwrap_or(TString::empty()),
));
let button = if extra.is_some() {
Button::with_text(TR::buttons__confirm.into()).styled(theme::button_cancel_gradient())
} else {
Button::with_text(TR::buttons__confirm.into()).styled(theme::button_confirm())
};
let mut address_screen = TextScreen::new(
paragraphs
.into_paragraphs()
.with_placement(LinearPlacement::vertical()),
)
.with_header(Header::new(title).with_menu_button())
.with_subtitle(subtitle.unwrap_or(TString::empty()))
.with_action_bar(ActionBar::new_single(button));
if let Some(extra) = extra {
address_screen = address_screen.with_hint(Hint::new_warning_caution(extra));
}
let content_address = address_screen
.map(|msg| match msg {
TextScreenMsg::Cancelled => Some(FlowMsg::Cancelled),
TextScreenMsg::Confirmed => Some(FlowMsg::Confirmed),
@ -129,7 +145,7 @@ pub fn new_get_address(
)),
)
.with_header(
Header::new(flow_title)
Header::new(title)
.with_right_button(Button::with_icon(theme::ICON_CROSS), HeaderMsg::Cancelled),
)
.map(|msg| match msg {
@ -200,7 +216,7 @@ pub fn new_get_address(
.into_paragraphs()
.with_placement(LinearPlacement::vertical()),
)
.with_header(Header::new(flow_title))
.with_header(Header::new(title))
.with_action_bar(ActionBar::new_double(
Button::with_icon(theme::ICON_CHEVRON_LEFT),
Button::with_text(TR::buttons__cancel.into()).styled(theme::button_cancel()),

View File

@ -731,6 +731,7 @@ impl FirmwareUI for UIEckhart {
fn flow_get_address(
address: Obj,
title: TString<'static>,
subtitle: Option<TString<'static>>,
description: Option<TString<'static>>,
extra: Option<TString<'static>>,
chunkify: bool,
@ -744,6 +745,7 @@ impl FirmwareUI for UIEckhart {
) -> Result<impl LayoutMaybeTrace, Error> {
let flow = flow::get_address::new_get_address(
title,
subtitle,
description,
extra,
address,

View File

@ -197,6 +197,7 @@ pub trait FirmwareUI {
fn flow_get_address(
address: Obj, // TODO: replace Obj
title: TString<'static>,
subtitle: Option<TString<'static>>,
description: Option<TString<'static>>,
extra: Option<TString<'static>>,
chunkify: bool,

View File

@ -359,6 +359,7 @@ def flow_get_address(
*,
address: str | bytes,
title: str,
subtitle: str | None,
description: str | None,
extra: str | None,
chunkify: bool,

View File

@ -18,6 +18,7 @@ class TR:
address__title_cosigner: str = "Cosigner"
address__title_receive_address: str = "Receive address"
address__title_yours: str = "Yours"
address__xpub: str = "XPUB"
address_details__account_info: str = "Account info"
address_details__derivation_path: str = "Derivation path"
address_details__derivation_path_colon: str = "Derivation path:"

View File

@ -36,6 +36,7 @@ def _get_xpubs(
@with_keychain
async def get_address(msg: GetAddress, keychain: Keychain, coin: CoinInfo) -> Address:
from trezor import TR
from trezor.enums import InputScriptType
from trezor.messages import Address
from trezor.ui.layouts import (
@ -105,6 +106,7 @@ async def get_address(msg: GetAddress, keychain: Keychain, coin: CoinInfo) -> Ad
if msg.show_display:
path = address_n_to_str(address_n)
subtitle = TR.address__coin_address_template.format(coin.coin_shortcut)
if multisig:
if multisig.nodes:
pubnodes = multisig.nodes
@ -138,6 +140,7 @@ async def get_address(msg: GetAddress, keychain: Keychain, coin: CoinInfo) -> Ad
await show_address(
address_short,
subtitle=subtitle,
case_sensitive=address_case_sensitive,
path=path,
multisig_index=multisig_index,
@ -149,6 +152,7 @@ async def get_address(msg: GetAddress, keychain: Keychain, coin: CoinInfo) -> Ad
account = address_n_to_name_or_unknown(coin, address_n, script_type)
await show_address(
address_short,
subtitle=subtitle,
address_qr=address,
case_sensitive=address_case_sensitive,
path=path,

View File

@ -110,10 +110,13 @@ async def get_public_key(
show_xpub = descriptor
await show_pubkey(
show_xpub,
"XPUB",
TR.address__xpub,
account=account,
path=path,
mismatch_title=TR.addr_mismatch__xpub_mismatch,
warning=(
TR.addr_mismatch__wrong_derivation_path if account is None else None
),
br_name="show_xpub",
)

View File

@ -1111,6 +1111,7 @@ async def show_cardano_address(
await layouts.show_address(
address,
subtitle=TR.address__coin_address_template.format("ADA"),
path=path,
account=account,
network=network_name,

View File

@ -16,6 +16,7 @@ async def get_address(
keychain: Keychain,
defs: Definitions,
) -> EthereumAddress:
from trezor import TR
from trezor.messages import EthereumAddress
from trezor.ui.layouts import show_address
@ -33,11 +34,13 @@ async def get_address(
if msg.show_display:
slip44_id = address_n[1] # it depends on the network (ETH vs ETC...)
coin = "ETH"
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(
"ETH", address_n, PATTERNS_ADDRESS, slip44_id
coin, address_n, PATTERNS_ADDRESS, slip44_id
),
chunkify=bool(msg.chunkify),
)

View File

@ -10,7 +10,7 @@ if TYPE_CHECKING:
@auto_keychain(__name__)
async def get_address(msg: MoneroGetAddress, keychain: Keychain) -> MoneroAddress:
from trezor import wire
from trezor import TR, wire
from trezor.messages import MoneroAddress
from trezor.ui.layouts import show_address
@ -68,11 +68,13 @@ async def get_address(msg: MoneroGetAddress, keychain: Keychain) -> MoneroAddres
if msg.show_display:
from . import PATTERN, SLIP44_ID
coin = "XMR"
await show_address(
addr,
subtitle=TR.address__coin_address_template.format(coin),
address_qr="monero:" + addr,
path=paths.address_n_to_str(address_n),
account=paths.get_account_name("XMR", msg.address_n, PATTERN, SLIP44_ID),
account=paths.get_account_name(coin, msg.address_n, PATTERN, SLIP44_ID),
chunkify=bool(msg.chunkify),
)

View File

@ -12,6 +12,7 @@ if TYPE_CHECKING:
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
async def get_address(msg: NEMGetAddress, keychain: Keychain) -> NEMAddress:
from trezor import TR
from trezor.messages import NEMAddress
from trezor.ui.layouts import show_address
@ -32,11 +33,13 @@ async def get_address(msg: NEMGetAddress, keychain: Keychain) -> NEMAddress:
if msg.show_display:
from . import PATTERNS, SLIP44_ID
coin = "NEM"
await show_address(
address,
subtitle=TR.address__coin_address_template.format(coin),
case_sensitive=False,
path=paths.address_n_to_str(address_n),
account=paths.get_account_name("NEM", msg.address_n, PATTERNS, SLIP44_ID),
account=paths.get_account_name(coin, msg.address_n, PATTERNS, SLIP44_ID),
network=get_network_str(network),
chunkify=bool(msg.chunkify),
)

View File

@ -11,6 +11,7 @@ if TYPE_CHECKING:
@auto_keychain(__name__)
async def get_address(msg: RippleGetAddress, keychain: Keychain) -> RippleAddress:
# NOTE: local imports here saves 20 bytes
from trezor import TR
from trezor.messages import RippleAddress
from trezor.ui.layouts import show_address
@ -29,10 +30,12 @@ async def get_address(msg: RippleGetAddress, keychain: Keychain) -> RippleAddres
if msg.show_display:
from . import PATTERN, SLIP44_ID
coin = "XRP"
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("XRP", msg.address_n, PATTERN, SLIP44_ID),
account=paths.get_account_name(coin, msg.address_n, PATTERN, SLIP44_ID),
chunkify=bool(msg.chunkify),
)

View File

@ -17,6 +17,7 @@ async def get_address(
msg: SolanaGetAddress,
keychain: Keychain,
) -> SolanaAddress:
from trezor import TR
from trezor.messages import SolanaAddress
from trezor.ui.layouts import show_address
@ -30,6 +31,7 @@ async def get_address(
if msg.show_display:
await show_address(
address,
subtitle=TR.address__coin_address_template.format("SOL"),
path=paths.address_n_to_str(msg.address_n),
chunkify=bool(msg.chunkify),
)

View File

@ -10,6 +10,7 @@ if TYPE_CHECKING:
@auto_keychain(__name__)
async def get_address(msg: StellarGetAddress, keychain: Keychain) -> StellarAddress:
from trezor import TR
from trezor.messages import StellarAddress
from trezor.ui.layouts import show_address
@ -28,11 +29,13 @@ async def get_address(msg: StellarGetAddress, keychain: Keychain) -> StellarAddr
if msg.show_display:
from . import PATTERN, SLIP44_ID
coin = "XLM"
await show_address(
address,
subtitle=TR.address__coin_address_template.format(coin),
case_sensitive=False,
path=paths.address_n_to_str(address_n),
account=paths.get_account_name("XLM", msg.address_n, PATTERN, SLIP44_ID),
account=paths.get_account_name(coin, msg.address_n, PATTERN, SLIP44_ID),
chunkify=bool(msg.chunkify),
)

View File

@ -12,6 +12,7 @@ if TYPE_CHECKING:
@with_slip44_keychain(*PATTERNS, slip44_id=SLIP44_ID, curve=CURVE)
async def get_address(msg: TezosGetAddress, keychain: Keychain) -> TezosAddress:
from trezor import TR
from trezor.crypto import hashlib
from trezor.messages import TezosAddress
from trezor.ui.layouts import show_address
@ -33,10 +34,12 @@ async def get_address(msg: TezosGetAddress, keychain: Keychain) -> TezosAddress:
if msg.show_display:
from . import PATTERNS, SLIP44_ID
coin = "XTZ"
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("XTZ", address_n, PATTERNS, SLIP44_ID),
account=paths.get_account_name(coin, address_n, PATTERNS, SLIP44_ID),
chunkify=bool(msg.chunkify),
)

View File

@ -279,6 +279,7 @@ async def show_address(
address: str,
*,
title: str | None = None,
subtitle: str | None = None,
address_qr: str | None = None,
case_sensitive: bool = True,
path: str | None = None,
@ -288,6 +289,7 @@ async def show_address(
xpubs: Sequence[str] = (),
mismatch_title: str | None = None,
details_title: str | None = None,
warning: str | None = None,
br_name: str = "show_address",
br_code: ButtonRequestType = ButtonRequestType.Address,
chunkify: bool = False,
@ -369,6 +371,7 @@ def show_pubkey(
account: str | None = None,
path: str | None = None,
mismatch_title: str | None = None,
warning: str | None = None,
br_name: str = "show_pubkey",
) -> Awaitable[None]:
title = title or TR.address__public_key # def_arg

View File

@ -296,6 +296,7 @@ async def show_address(
address: str,
*,
title: str | None = None,
subtitle: str | None = None,
address_qr: str | None = None,
case_sensitive: bool = True,
path: str | None = None,
@ -304,6 +305,7 @@ async def show_address(
multisig_index: int | None = None,
xpubs: Sequence[str] = (),
mismatch_title: str | None = None,
warning: str | None = None,
br_name: str = "show_address",
br_code: ButtonRequestType = ButtonRequestType.Address,
chunkify: bool = False,
@ -384,6 +386,7 @@ def show_pubkey(
account: str | None = None,
path: str | None = None,
mismatch_title: str | None = None,
warning: str | None = None,
br_name: str = "show_pubkey",
) -> Awaitable[None]:
title = title or TR.address__public_key # def_arg

View File

@ -276,6 +276,7 @@ async def show_address(
address: str,
*,
title: str | None = None,
subtitle: str | None = None,
address_qr: str | None = None,
case_sensitive: bool = True,
path: str | None = None,
@ -285,6 +286,7 @@ async def show_address(
xpubs: Sequence[str] = (),
mismatch_title: str | None = None,
details_title: str | None = None,
warning: str | None = None,
br_name: str = "show_address",
br_code: ButtonRequestType = ButtonRequestType.Address,
chunkify: bool = False,
@ -302,6 +304,7 @@ async def show_address(
trezorui_api.flow_get_address(
address=address,
title=title or TR.address__title_receive_address,
subtitle=None,
description=network or "",
extra=None,
chunkify=chunkify,
@ -330,6 +333,7 @@ def show_pubkey(
account: str | None = None,
path: str | None = None,
mismatch_title: str | None = None,
warning: str | None = None,
br_name: str = "show_pubkey",
) -> Awaitable[None]:
title = title or TR.address__public_key # def_arg

View File

@ -274,6 +274,7 @@ async def show_address(
address: str,
*,
title: str | None = None,
subtitle: str | None = None,
address_qr: str | None = None,
case_sensitive: bool = True,
path: str | None = None,
@ -283,6 +284,7 @@ async def show_address(
xpubs: Sequence[str] = (),
mismatch_title: str | None = None,
details_title: str | None = None,
warning: str | None = None,
br_name: str = "show_address",
br_code: ButtonRequestType = ButtonRequestType.Address,
chunkify: bool = False,
@ -296,12 +298,15 @@ async def show_address(
)
return result
if warning is None and multisig_index is not None:
warning = TR.send__receiving_to_multisig
await raise_if_not_confirmed(
trezorui_api.flow_get_address(
address=address,
title=title or TR.address__title_receive_address,
title=title or TR.words__receive,
subtitle=subtitle,
description=network or "",
extra=None,
extra=warning,
chunkify=chunkify,
address_qr=address if address_qr is None else address_qr,
case_sensitive=case_sensitive,
@ -328,18 +333,20 @@ def show_pubkey(
account: str | None = None,
path: str | None = None,
mismatch_title: str | None = None,
warning: str | None = None,
br_name: str = "show_pubkey",
) -> Awaitable[None]:
title = title or TR.address__public_key # def_arg
mismatch_title = mismatch_title or TR.addr_mismatch__key_mismatch # def_arg
return show_address(
address=pubkey,
title=title,
title=title or TR.address__public_key,
subtitle=account,
account=account,
path=path,
br_name=br_name,
br_code=ButtonRequestType.PublicKey,
mismatch_title=mismatch_title,
warning=warning,
chunkify=False,
)

View File

@ -20,6 +20,12 @@
"address__check_with_source": "Check the address with source.",
"address__confirmed": "Receive address confirmed",
"address__public_key": "Public key",
"address__xpub": {
"Bolt": "XPUB",
"Caesar": "XPUB",
"Delizia": "XPUB",
"Eckhart": "Public key (XPUB)"
},
"address__public_key_confirmed": "Public key confirmed",
"address__qr_code": "QR code",
"address__title_cosigner": "Cosigner",

View File

@ -1045,5 +1045,6 @@
"1043": "reset__select_word_from_share_template",
"1044": "recovery__share_from_group_entered_template",
"1045": "send__cancel_transaction",
"1046": "send__multisig_different_paths"
"1046": "send__multisig_different_paths",
"1047": "address__xpub"
}

View File

@ -1,8 +1,8 @@
{
"current": {
"merkle_root": "fbe14244ebd30a0fe40a3c2b52d86a650543ac3fec026cb1130de666ff141728",
"datetime": "2025-06-25T14:18:09.981692+00:00",
"commit": "b1b4095ad0078a4f97ffd477f7716b27063adb79"
"merkle_root": "298ecf2b73797fb62a725f64a2bb6c2233e1280c60a433b9ec87560ccb9cf69a",
"datetime": "2025-06-26T11:56:11.247313+00:00",
"commit": "545997e8726deae49f23a2108bd14844741d6a3e"
},
"history": [
{

View File

@ -763,7 +763,7 @@ class InputFlowShowMultisigXPUBs(InputFlowBase):
yield # show address
layout = self.debug.read_layout()
assert TR.address__title_receive_address in layout.subtitle()
assert TR.regexp("address__coin_address_template").match(layout.subtitle())
assert layout.text_content().replace(" ", "").strip() == self.address
self.debug.click(self.debug.screen_buttons.menu())
@ -927,7 +927,7 @@ class InputFlowShowXpubQRCode(InputFlowBase):
for _ in range(br.pages - 1):
self.debug.click(self.debug.screen_buttons.ok())
assert layout.subtitle() in (TR.address__public_key, "XPUB")
assert TR.address__public_key in layout.title()
self.debug.click(self.debug.screen_buttons.menu())
assert "VerticalMenu" in self.all_components()