Skip to content

Commit

Permalink
feat(core/ethereum): new ETH contract flow
Browse files Browse the repository at this point in the history
  • Loading branch information
ibz committed Oct 18, 2024
1 parent cb3e437 commit 2d720de
Show file tree
Hide file tree
Showing 30 changed files with 334 additions and 103 deletions.
10 changes: 9 additions & 1 deletion core/embed/rust/librust_qstr.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ static void _librust_qstrs(void) {
MP_QSTR_buttons__try_again;
MP_QSTR_buttons__turn_off;
MP_QSTR_buttons__turn_on;
MP_QSTR_buttons__view_all_data;
MP_QSTR_can_go_back;
MP_QSTR_cancel_arrow;
MP_QSTR_cancel_cross;
Expand Down Expand Up @@ -217,8 +218,10 @@ static void _librust_qstrs(void) {
MP_QSTR_debug__loading_seed;
MP_QSTR_debug__loading_seed_not_recommended;
MP_QSTR_decode;
MP_QSTR_default_cancel;
MP_QSTR_deinit;
MP_QSTR_description;
MP_QSTR_description_font_green;
MP_QSTR_details_title;
MP_QSTR_device_name__change_template;
MP_QSTR_device_name__title;
Expand Down Expand Up @@ -729,6 +732,7 @@ static void _librust_qstrs(void) {
MP_QSTR_value;
MP_QSTR_verb;
MP_QSTR_verb_cancel;
MP_QSTR_verb_info;
MP_QSTR_verify;
MP_QSTR_version;
MP_QSTR_warning;
Expand Down Expand Up @@ -801,6 +805,7 @@ static void _librust_qstrs(void) {
MP_QSTR_words__title_threshold;
MP_QSTR_words__try_again;
MP_QSTR_words__unknown;
MP_QSTR_words__view_all_data_from_menu;
MP_QSTR_words__warning;
MP_QSTR_words__writable;
MP_QSTR_words__yes;
Expand Down Expand Up @@ -979,6 +984,7 @@ static void _librust_qstrs(void) {
MP_QSTR_ethereum__data_size_template;
MP_QSTR_ethereum__gas_limit;
MP_QSTR_ethereum__gas_price;
MP_QSTR_ethereum__interaction_contract;
MP_QSTR_ethereum__max_gas_price;
MP_QSTR_ethereum__name_and_version;
MP_QSTR_ethereum__new_contract;
Expand All @@ -997,13 +1003,15 @@ static void _librust_qstrs(void) {
MP_QSTR_ethereum__staking_stake_intro;
MP_QSTR_ethereum__staking_unstake;
MP_QSTR_ethereum__staking_unstake_intro;
MP_QSTR_ethereum__title_confirm_data;
MP_QSTR_ethereum__title_confirm_domain;
MP_QSTR_ethereum__title_confirm_message;
MP_QSTR_ethereum__title_confirm_struct;
MP_QSTR_ethereum__title_confirm_typed_data;
MP_QSTR_ethereum__title_input_data;
MP_QSTR_ethereum__title_signing_address;
MP_QSTR_ethereum__token_contract;
MP_QSTR_ethereum__units_template;
MP_QSTR_ethereum__unknown_contract_address;
MP_QSTR_ethereum__unknown_token;
MP_QSTR_ethereum__valid_signature;
MP_QSTR_fido__already_registered;
Expand Down
33 changes: 30 additions & 3 deletions core/embed/rust/src/translations/generated/translated_string.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions core/embed/rust/src/ui/model_mercury/component/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ where
self.with_button(theme::ICON_MENU, FlowMsg::Info, true)
}

pub fn with_danger_menu_button(self) -> Self {
self.with_button(theme::ICON_MENU, FlowMsg::Info, true)
.button_styled(theme::button_warning_high())
}

pub fn with_warning_low_icon(self) -> Self {
self.with_button(theme::ICON_WARNING, FlowMsg::Info, false)
.button_styled(theme::button_warning_low())
Expand Down
130 changes: 109 additions & 21 deletions core/embed/rust/src/ui/model_mercury/flow/confirm_action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,40 @@ impl FlowController for ConfirmActionSimple {
}
}

/// Flow similar to ConfirmActionSimple, but having swipe up cancel the flow rather than confirm.
/// To confirm, the user needs to open the menu.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum ConfirmActionSimpleDefaultCancel {
Intro,
Menu,
}

impl FlowController for ConfirmActionSimpleDefaultCancel {
#[inline]
fn index(&'static self) -> usize {
*self as usize
}

fn handle_swipe(&'static self, direction: Direction) -> Decision {
match (self, direction) {
(Self::Intro, Direction::Left) => Self::Menu.swipe(direction),
(Self::Menu, Direction::Right) => Self::Intro.swipe(direction),
(Self::Intro, Direction::Up) => self.return_msg(FlowMsg::Cancelled),
_ => self.do_nothing(),
}
}

fn handle_event(&'static self, msg: FlowMsg) -> Decision {
match (self, msg) {
(Self::Intro, FlowMsg::Info) => Self::Menu.goto(),
(Self::Menu, FlowMsg::Cancelled) => Self::Intro.swipe_right(),
(Self::Menu, FlowMsg::Choice(0)) => self.return_msg(FlowMsg::Cancelled),
(Self::Menu, FlowMsg::Choice(1)) => self.return_msg(FlowMsg::Confirmed),
_ => self.do_nothing(),
}
}
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub extern "C" fn new_confirm_action(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj {
unsafe { util::try_with_args_and_kwargs(n_args, args, kwargs, new_confirm_action_obj) }
Expand Down Expand Up @@ -144,6 +178,7 @@ fn new_confirm_action_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Err
title,
subtitle,
verb_cancel,
None,
prompt_screen.then_some(prompt_title),
hold,
false,
Expand All @@ -152,24 +187,33 @@ fn new_confirm_action_obj(_args: &[Obj], kwargs: &Map) -> Result<Obj, error::Err
}

#[inline(never)]
pub fn new_confirm_action_uni<T: Component + MaybeTrace + 'static>(
fn new_confirm_action_uni<T: Component + MaybeTrace + 'static>(
content: T,
title: TString<'static>,
subtitle: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
verb_info: Option<TString<'static>>,
prompt_screen: Option<TString<'static>>,
hold: bool,
info: bool,
default_cancel: bool,
) -> Result<Obj, error::Error> {
let (prompt_screen, prompt_pages, flow, page) = create_flow(title, prompt_screen, hold);
let (prompt_screen, prompt_pages, flow, page) = create_flow(title, prompt_screen, hold, default_cancel);

let mut content_intro = Frame::left_aligned(title, content)
.with_menu_button()
.with_footer(TR::instructions__swipe_up.into(), None)
.with_swipe(Direction::Up, SwipeSettings::default())
.with_swipe(Direction::Left, SwipeSettings::default())
.with_vertical_pages();

if default_cancel {
content_intro = content_intro.title_styled(theme::TEXT_WARNING);
content_intro = content_intro.with_danger_menu_button();
content_intro = content_intro.with_footer(TR::instructions__swipe_up.into(), Some(TR::send__cancel_sign.into()));
} else {
content_intro = content_intro.with_menu_button();
content_intro = content_intro.with_footer(TR::instructions__swipe_up.into(), None);
}

if let Some(subtitle) = subtitle {
content_intro = content_intro.with_subtitle(subtitle);
}
Expand All @@ -183,13 +227,14 @@ pub fn new_confirm_action_uni<T: Component + MaybeTrace + 'static>(

let flow = flow?.with_page(page, content_intro)?;

create_menu_and_confirm(subtitle, verb_cancel, hold, info, prompt_screen, flow)
create_menu_and_confirm(subtitle, verb_cancel, verb_info, hold, info, prompt_screen, default_cancel, flow)
}

fn create_flow(
title: TString<'static>,
prompt_screen: Option<TString<'static>>,
hold: bool,
default_cancel: bool,
) -> (
Option<TString<'static>>,
usize,
Expand All @@ -199,16 +244,14 @@ fn create_flow(
let prompt_screen = prompt_screen.or_else(|| hold.then_some(title));
let prompt_pages: usize = prompt_screen.is_some().into();

let flow = if prompt_screen.is_some() {
SwipeFlow::new(&ConfirmAction::Intro)
let (flow, page): (Result<SwipeFlow, Error>, &dyn FlowController) = if prompt_screen.is_some() {
(SwipeFlow::new(&ConfirmAction::Intro), &ConfirmAction::Intro)
} else {
SwipeFlow::new(&ConfirmActionSimple::Intro)
};

let page: &dyn FlowController = if prompt_screen.is_some() {
&ConfirmAction::Intro
} else {
&ConfirmActionSimple::Intro
if default_cancel {
(SwipeFlow::new(&ConfirmActionSimpleDefaultCancel::Intro), &ConfirmActionSimpleDefaultCancel::Intro)
} else {
(SwipeFlow::new(&ConfirmActionSimple::Intro), &ConfirmActionSimple::Intro)
}
};

(prompt_screen, prompt_pages, flow, page)
Expand All @@ -217,12 +260,14 @@ fn create_flow(
fn create_menu_and_confirm(
subtitle: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
verb_info: Option<TString<'static>>,
hold: bool,
info: bool,
prompt_screen: Option<TString<'static>>,
default_cancel: bool,
flow: SwipeFlow,
) -> Result<Obj, Error> {
let flow = create_menu(flow, verb_cancel, info, prompt_screen)?;
let flow = create_menu(flow, verb_cancel, verb_info, info, default_cancel, prompt_screen)?;

let flow = create_confirm(flow, subtitle, hold, prompt_screen)?;

Expand All @@ -232,19 +277,34 @@ fn create_menu_and_confirm(
fn create_menu(
flow: SwipeFlow,
verb_cancel: Option<TString<'static>>,
verb_info: Option<TString<'static>>,
info: bool,
default_cancel: bool,
prompt_screen: Option<TString<'static>>,
) -> Result<SwipeFlow, Error> {
let mut menu_choices = VerticalMenu::empty().danger(
theme::ICON_CANCEL,
verb_cancel.unwrap_or(TR::buttons__cancel.into()),
);
if info {
let mut menu_choices = VerticalMenu::empty();
if default_cancel {
menu_choices = menu_choices.item(
theme::ICON_CANCEL,
verb_cancel.unwrap_or(TR::buttons__cancel.into()),
);
menu_choices = menu_choices.danger(
theme::ICON_CHEVRON_RIGHT,
TR::words__title_information.into(),
TR::words__continue_anyway.into(),
);
} else {
menu_choices = menu_choices.danger(
theme::ICON_CANCEL,
verb_cancel.unwrap_or(TR::buttons__cancel.into()),
);
if info {
menu_choices = menu_choices.item(
theme::ICON_CHEVRON_RIGHT,
verb_info.unwrap_or(TR::words__title_information.into()),
);
}
}

let content_menu = Frame::left_aligned("".into(), menu_choices)
.with_cancel_button()
.with_swipe(Direction::Right, SwipeSettings::immediate());
Expand Down Expand Up @@ -308,6 +368,32 @@ pub fn new_confirm_action_simple<T: Component + Paginate + MaybeTrace + 'static>
title: TString<'static>,
subtitle: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
verb_info: Option<TString<'static>>,
prompt_screen: Option<TString<'static>>,
hold: bool,
info: bool,
page_limit: Option<usize>,
) -> Result<Obj, error::Error> {
new_confirm_action_uni(
SwipeContent::new(SwipePage::vertical(content).with_limit(page_limit)),
title,
subtitle,
verb_cancel,
verb_info,
prompt_screen,
hold,
info,
false,
)
}

#[inline(never)]
pub fn new_confirm_action_simple_default_cancel<T: Component + Paginate + MaybeTrace + 'static>(
content: T,
title: TString<'static>,
subtitle: Option<TString<'static>>,
verb_cancel: Option<TString<'static>>,
verb_info: Option<TString<'static>>,
prompt_screen: Option<TString<'static>>,
hold: bool,
info: bool,
Expand All @@ -318,8 +404,10 @@ pub fn new_confirm_action_simple<T: Component + Paginate + MaybeTrace + 'static>
title,
subtitle,
verb_cancel,
verb_info,
prompt_screen,
hold,
info,
true,
)
}
2 changes: 1 addition & 1 deletion core/embed/rust/src/ui/model_mercury/flow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub mod warning_hi_prio;

mod util;

pub use confirm_action::{new_confirm_action, new_confirm_action_simple};
pub use confirm_action::{new_confirm_action, new_confirm_action_simple, new_confirm_action_simple_default_cancel};
#[cfg(feature = "universal_fw")]
pub use confirm_fido::new_confirm_fido;
pub use confirm_firmware_update::new_confirm_firmware_update;
Expand Down
Loading

0 comments on commit 2d720de

Please sign in to comment.