|
1 |
| -extern crate alloc; |
2 |
| -use alloc::{vec, vec::Vec}; |
| 1 | +use crate::error_code::ErrorCode; |
| 2 | +use crate::ledger_sdk_stub::nbgl_review::NbglStreamingReview; |
| 3 | +use include_gif::include_gif; |
| 4 | +use ledger_device_sdk::nbgl::{Field, NbglChoice, NbglGlyph, NbglReviewStatus, TransactionType}; |
3 | 5 |
|
4 |
| -#[cfg(any(target_os = "stax", target_os = "flex"))] |
5 |
| -use alloc::ffi::CString; |
6 |
| -use core::ffi::c_char; |
7 |
| -use ledger_device_sdk::nbgl::*; |
8 |
| -use ledger_secure_sdk_sys::*; |
| 6 | +pub static APP_ICON: NbglGlyph = NbglGlyph::from_include(include_gif!("alph_64x64.gif", NBGL)); |
9 | 7 |
|
10 |
| -pub enum ReviewType { |
11 |
| - Transaction, |
12 |
| - Hash, |
| 8 | +fn new_nbgl_review(tx_type: TransactionType, blind: bool) -> NbglStreamingReview { |
| 9 | + let reviewer = NbglStreamingReview::new().tx_type(tx_type).glyph(&APP_ICON); |
| 10 | + if blind { |
| 11 | + reviewer.blind() |
| 12 | + } else { |
| 13 | + reviewer |
| 14 | + } |
13 | 15 | }
|
14 | 16 |
|
15 |
| -pub fn nbgl_review_fields(title: &str, subtitle: &str, fields: &TagValueList) -> bool { |
16 |
| - unsafe { |
17 |
| - let title = CString::new(title).unwrap(); |
18 |
| - let subtitle = CString::new(subtitle).unwrap(); |
19 |
| - let finish = CString::new("Click to continue").unwrap(); |
20 |
| - let icon = nbgl_icon_details_t::default(); |
21 |
| - let sync_ret = ux_sync_reviewLight( |
22 |
| - TYPE_TRANSACTION.into(), |
23 |
| - &fields.into() as *const nbgl_contentTagValueList_t, |
24 |
| - &icon as *const nbgl_icon_details_t, |
25 |
| - title.as_ptr() as *const c_char, |
26 |
| - subtitle.as_ptr() as *const c_char, |
27 |
| - finish.as_ptr() as *const c_char, |
28 |
| - ); |
29 |
| - matches!(sync_ret, UX_SYNC_RET_APPROVED) |
30 |
| - } |
| 17 | +pub struct NbglReviewer { |
| 18 | + pub review_started: bool, |
| 19 | + reviewer: Option<NbglStreamingReview>, |
31 | 20 | }
|
32 | 21 |
|
33 |
| -pub fn nbgl_sync_review_status(tpe: ReviewType) { |
34 |
| - unsafe { |
35 |
| - let status_type = match tpe { |
36 |
| - ReviewType::Transaction => STATUS_TYPE_TRANSACTION_SIGNED, |
37 |
| - ReviewType::Hash => STATUS_TYPE_OPERATION_SIGNED, // there is no `STATUS_TYPE_HASH` in ledger sdk |
38 |
| - }; |
39 |
| - let _ = ux_sync_reviewStatus(status_type); |
| 22 | +impl NbglReviewer { |
| 23 | + pub fn new() -> NbglReviewer { |
| 24 | + NbglReviewer { |
| 25 | + review_started: false, |
| 26 | + reviewer: None, |
| 27 | + } |
40 | 28 | }
|
41 |
| -} |
42 | 29 |
|
43 |
| -fn nbgl_generic_review(content: &NbglPageContent, button_str: &str) -> bool { |
44 |
| - unsafe { |
45 |
| - let (c_struct, content_type, action_callback) = content.into(); |
46 |
| - let c_content_list: Vec<nbgl_content_t> = vec![nbgl_content_t { |
47 |
| - content: c_struct, |
48 |
| - contentActionCallback: action_callback, |
49 |
| - type_: content_type, |
50 |
| - }]; |
| 30 | + pub fn reset(&mut self) { |
| 31 | + self.review_started = false; |
| 32 | + self.reviewer = None; |
| 33 | + } |
51 | 34 |
|
52 |
| - let content_struct = nbgl_genericContents_t { |
53 |
| - callbackCallNeeded: false, |
54 |
| - __bindgen_anon_1: nbgl_genericContents_t__bindgen_ty_1 { |
55 |
| - contentsList: c_content_list.as_ptr(), |
56 |
| - }, |
57 |
| - nbContents: 1, |
58 |
| - }; |
| 35 | + #[inline] |
| 36 | + fn get_reviewer(&self) -> &NbglStreamingReview { |
| 37 | + assert!(self.reviewer.is_some()); |
| 38 | + self.reviewer.as_ref().unwrap() |
| 39 | + } |
59 | 40 |
|
60 |
| - let button_cstring = CString::new(button_str).unwrap(); |
| 41 | + pub fn set_reviewer(&mut self, blind: bool) { |
| 42 | + assert!(self.reviewer.is_none()); |
| 43 | + self.reviewer = Some(new_nbgl_review(TransactionType::Transaction, blind)); |
| 44 | + } |
61 | 45 |
|
62 |
| - let sync_ret = ux_sync_genericReview( |
63 |
| - &content_struct as *const nbgl_genericContents_t, |
64 |
| - button_cstring.as_ptr() as *const c_char, |
65 |
| - ); |
| 46 | + pub fn start_review(&mut self, message: &str) -> Result<(), ErrorCode> { |
| 47 | + if self.get_reviewer().start(message, "") { |
| 48 | + self.review_started = true; |
| 49 | + Ok(()) |
| 50 | + } else { |
| 51 | + NbglReviewStatus::new().show(false); |
| 52 | + Err(ErrorCode::UserCancelled) |
| 53 | + } |
| 54 | + } |
| 55 | + |
| 56 | + pub fn continue_review<'a>(&self, fields: &'a [Field<'a>]) -> Result<(), ErrorCode> { |
| 57 | + if self.get_reviewer().continue_review(fields) { |
| 58 | + Ok(()) |
| 59 | + } else { |
| 60 | + NbglReviewStatus::new().show(false); |
| 61 | + Err(ErrorCode::UserCancelled) |
| 62 | + } |
| 63 | + } |
66 | 64 |
|
67 |
| - // Return true if the user approved the transaction, false otherwise. |
68 |
| - matches!(sync_ret, ledger_secure_sdk_sys::UX_SYNC_RET_APPROVED) |
| 65 | + pub fn finish_review(&self, message: &str) -> Result<(), ErrorCode> { |
| 66 | + if self.get_reviewer().finish(message) { |
| 67 | + NbglReviewStatus::new().show(true); |
| 68 | + Ok(()) |
| 69 | + } else { |
| 70 | + NbglReviewStatus::new().show(false); |
| 71 | + Err(ErrorCode::UserCancelled) |
| 72 | + } |
69 | 73 | }
|
70 | 74 | }
|
71 | 75 |
|
72 |
| -pub fn nbgl_review_warning(message: &str) -> bool { |
73 |
| - let content = NbglPageContent::InfoButton(InfoButton::new( |
74 |
| - message, |
75 |
| - None, |
76 |
| - "Continue", |
77 |
| - TuneIndex::TapCasual, |
78 |
| - )); |
79 |
| - nbgl_generic_review(&content, "Reject") |
| 76 | +pub fn nbgl_review_hash(hash: &str) -> bool { |
| 77 | + let reviewer = new_nbgl_review(TransactionType::Operation, false); |
| 78 | + if !reviewer.start("Review Hash", "") { |
| 79 | + return false; |
| 80 | + } |
| 81 | + let fields = [Field { |
| 82 | + name: "Hash", |
| 83 | + value: hash, |
| 84 | + }]; |
| 85 | + if !reviewer.continue_review(&fields) { |
| 86 | + return false; |
| 87 | + } |
| 88 | + reviewer.finish("Sign Hash") |
80 | 89 | }
|
81 | 90 |
|
82 |
| -pub fn nbgl_review_info(message: &str) { |
83 |
| - let content = NbglPageContent::CenteredInfo(CenteredInfo::new( |
84 |
| - message, |
85 |
| - "", |
86 |
| - "", |
87 |
| - None, |
88 |
| - false, |
89 |
| - CenteredInfoStyle::NormalInfo, |
90 |
| - 0, |
91 |
| - )); |
92 |
| - let _ = nbgl_generic_review(&content, "Tap to continue"); |
| 91 | +pub fn nbgl_review_warning( |
| 92 | + message: &str, |
| 93 | + sub_message: &str, |
| 94 | + confirm_text: &str, |
| 95 | + cancel_text: &str, |
| 96 | +) -> bool { |
| 97 | + const WARNING: NbglGlyph = NbglGlyph::from_include(include_gif!("Warning_64px.gif", NBGL)); |
| 98 | + NbglChoice::new() |
| 99 | + .glyph(&WARNING) |
| 100 | + .show(message, sub_message, confirm_text, cancel_text) |
93 | 101 | }
|
0 commit comments