Skip to content

Commit

Permalink
src: Use nbgl sync API step 1
Browse files Browse the repository at this point in the history
  • Loading branch information
Xavier Chapron committed Jan 29, 2024
1 parent 0c420da commit 572db73
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 108 deletions.
66 changes: 30 additions & 36 deletions src/ui/nbgl_display_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,53 +36,47 @@
#include "../transaction/types.h"
#include "../menu.h"

static char g_address[43];

static void confirm_address_rejection(void) {
// display a status page and go back to main
validate_pubkey(false);
nbgl_useCaseStatus("Address verification\ncancelled", false, ui_menu_main);
}

static void confirm_address_approval(void) {
// display a success status page and go back to main
validate_pubkey(true);
nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, ui_menu_main);
}

static void review_choice(bool confirm) {
if (confirm) {
confirm_address_approval();
} else {
confirm_address_rejection();
}
}

static void continue_review(void) {
nbgl_useCaseAddressConfirmation(g_address, review_choice);
}

int ui_display_address() {
if (G_context.req_type != CONFIRM_ADDRESS || G_context.state != STATE_NONE) {
G_context.state = STATE_NONE;
return io_send_sw(SW_BAD_STATE);
}
memset(g_address, 0, sizeof(g_address));
uint8_t address[ADDRESS_LEN] = {0};
if (!address_from_pubkey(G_context.pk_info.raw_public_key, address, sizeof(address))) {

char address_str[43] = {0};
uint8_t address_bin[ADDRESS_LEN] = {0};

if (!address_from_pubkey(G_context.pk_info.raw_public_key, address_bin, sizeof(address_bin))) {
return io_send_sw(SW_DISPLAY_ADDRESS_FAIL);
}

if (format_hex(address, sizeof(address), g_address, sizeof(g_address)) == -1) {
if (format_hex(address_bin, sizeof(address_bin), address_str, sizeof(address_str)) == -1) {
return io_send_sw(SW_DISPLAY_ADDRESS_FAIL);
}

nbgl_useCaseReviewStart(&C_app_boilerplate_64px,
"Verify BOL address",
NULL,
"Cancel",
continue_review,
confirm_address_rejection);
sync_nbgl_ret_t ret = sync_nbgl_useCaseAddressReview(address_str,
&C_app_boilerplate_64px,
"Verify BOL address",
NULL);

if (ret == NBGL_SYNC_RET_SUCCESS) {
// display a status page and go back to main
validate_pubkey(true);
nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, ui_menu_main);
} else if (ret == NBGL_SYNC_RET_REJECTED) {
// display a status page and go back to main
validate_pubkey(false);
nbgl_useCaseStatus("Address verification\ncancelled", false, ui_menu_main);
} else {
io_send_sw(SW_BAD_STATE);
nbgl_useCaseStatus("Address verification\nissue", false, ui_menu_main);
}

// Here we used async version of nbgl_useCaseStatus
// This means that upon end of timer or touch ui_menu_main will be called
// but in the meantime we return to app_main to process APDU.
// If an APDU is received before the timer ends, a new UX might be shown on
// the screen, and therefore the modal will be dismissed and its callback
// will never be called.
return 0;
}

Expand Down
124 changes: 52 additions & 72 deletions src/ui/nbgl_display_transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@

#include "os.h"
#include "glyphs.h"
#include "os_io_seproxyhal.h"
#include "nbgl_use_case.h"
#include "nbgl_sync.h"
#include "io.h"
#include "bip32.h"
#include "format.h"
Expand All @@ -37,95 +36,76 @@
#include "../transaction/types.h"
#include "../menu.h"

// Buffer where the transaction amount string is written
static char g_amount[30];
// Buffer where the transaction address string is written
static char g_address[43];

static nbgl_layoutTagValue_t pairs[2];
static nbgl_layoutTagValueList_t pairList;
static nbgl_pageInfoLongPress_t infoLongPress;

static void confirm_transaction_rejection(void) {
// display a status page and go back to main
validate_transaction(false);
nbgl_useCaseStatus("Transaction rejected", false, ui_menu_main);
}

static void ask_transaction_rejection_confirmation(void) {
// display a choice to confirm/cancel rejection
nbgl_useCaseConfirm("Reject transaction?",
NULL,
"Yes, Reject",
"Go back to transaction",
confirm_transaction_rejection);
}

// called when long press button on 3rd page is long-touched or when reject footer is touched
static void review_choice(bool confirm) {
if (confirm) {
// display a status page and go back to main
validate_transaction(true);
nbgl_useCaseStatus("TRANSACTION\nSIGNED", true, ui_menu_main);
} else {
ask_transaction_rejection_confirmation();
}
}

static void review_continue(void) {
// Setup data to display
pairs[0].item = "Amount";
pairs[0].value = g_amount;
pairs[1].item = "Address";
pairs[1].value = g_address;

// Setup list
pairList.nbMaxLinesForValue = 0;
pairList.nbPairs = 2;
pairList.pairs = pairs;

// Info long press
infoLongPress.icon = &C_app_boilerplate_64px;
infoLongPress.text = "Sign transaction\nto send BOL";
infoLongPress.longPressText = "Hold to sign";

nbgl_useCaseStaticReview(&pairList, &infoLongPress, "Reject transaction", review_choice);
}

// Public function to start the transaction review
// - Check if the app is in the right state for transaction review
// - Format the amount and address strings in g_amount and g_address buffers
// - Format the amount and address strings in amount_str and address_str buffers
// - Display the first screen of the transaction review
int ui_display_transaction() {
if (G_context.req_type != CONFIRM_TRANSACTION || G_context.state != STATE_PARSED) {
G_context.state = STATE_NONE;
return io_send_sw(SW_BAD_STATE);
}

// Format amount and address to g_amount and g_address buffers
memset(g_amount, 0, sizeof(g_amount));
char amount[30] = {0};
if (!format_fpu64(amount,
sizeof(amount),
// Buffer where the transaction amount string is written
char amount_str[30] = {0};
// Buffer where the transaction address string is written
char address_str[43] = {0};

// Format amount and address to amount_str and address_str buffers
char amount_bin[30] = {0};
if (!format_fpu64(amount_bin,
sizeof(amount_bin),
G_context.tx_info.transaction.value,
EXPONENT_SMALLEST_UNIT)) {
return io_send_sw(SW_DISPLAY_AMOUNT_FAIL);
}
snprintf(g_amount, sizeof(g_amount), "BOL %.*s", sizeof(amount), amount);
memset(g_address, 0, sizeof(g_address));
snprintf(amount_str, sizeof(amount_str), "BOL %.*s", sizeof(amount_bin), amount_bin);

if (format_hex(G_context.tx_info.transaction.to, ADDRESS_LEN, g_address, sizeof(g_address)) ==
if (format_hex(G_context.tx_info.transaction.to, ADDRESS_LEN, address_str, sizeof(address_str)) ==
-1) {
return io_send_sw(SW_DISPLAY_ADDRESS_FAIL);
}

nbgl_layoutTagValue_t pairs[2] = {0};
nbgl_layoutTagValueList_t pairList = {0};

// Setup data to display
pairs[0].item = "Amount";
pairs[0].value = amount_str;
pairs[1].item = "Address";
pairs[1].value = address_str;

// Setup list
pairList.nbMaxLinesForValue = 0;
pairList.nbPairs = 2;
pairList.pairs = pairs;

// Start review
nbgl_useCaseReviewStart(&C_app_boilerplate_64px,
"Review transaction\nto send BOL",
NULL,
"Reject transaction",
review_continue,
ask_transaction_rejection_confirmation);
sync_nbgl_ret_t ret = sync_nbgl_useCaseTransactionReview(
&pairList,
&C_app_boilerplate_64px,
"Review transaction\nto send BOL",
NULL,
"Sign transaction\nto send BOL");

if (ret == NBGL_SYNC_RET_SUCCESS) {
// display a status page and go back to main
validate_transaction(true);
sync_nbgl_useCaseStatus("TRANSACTION\nSIGNED", true);
} else if (ret == NBGL_SYNC_RET_REJECTED) {
// display a status page and go back to main
validate_transaction(false);
sync_nbgl_useCaseStatus("Transaction rejected", false);
} else {
io_send_sw(SW_BAD_STATE);
sync_nbgl_useCaseStatus("Transaction issue", false);
}

// Here we used sync version of nbgl_useCaseStatus
// This means that upon reception of any APDU during
// sync_nbgl_useCaseStatus, we will stop the status display even if the
// received APDU doesn't need an UX flow to be answered.
ui_menu_main();
return 0;
}

Expand Down

0 comments on commit 572db73

Please sign in to comment.