18#include "os_helpers.h"
25#define PAGE_NB_ELEMENTS_BITS 3
26#define GET_PAGE_NB_ELEMENTS(pageData) ((pageData) &0x07)
27#define SET_PAGE_NB_ELEMENTS(nbElements) ((nbElements) &0x07)
29#define PAGE_FLAG_BITS 1
30#define GET_PAGE_FLAG(pageData) (((pageData) &0x08) >> 3)
31#define SET_PAGE_FLAG(flag) (((flag) &0x01) << 3)
33#define PAGE_DATA_BITS (PAGE_NB_ELEMENTS_BITS + PAGE_FLAG_BITS)
34#define PAGES_PER_UINT8 (8 / PAGE_DATA_BITS)
35#define SET_PAGE_DATA(pageIdx, pageData) \
36 (pagesData[pageIdx / PAGES_PER_UINT8] = pageData \
37 << ((pageIdx % PAGES_PER_UINT8) * PAGE_DATA_BITS))
39#define MAX_PAGE_NB 256
42#define STARTING_CONTENT localContentsList[0]
43#define FINISHING_CONTENT localContentsList[1]
46#define QRCODE_NB_MAX_LINES 3
48#define QRCODE_REDUCED_ADDR_LEN 128
51#define keypadContext sharedContext.keypad
52#define reviewWithWarnCtx sharedContext.reviewWithWarning
55#define W3C_DESCRIPTION_MAX_LEN 128
62#define RISKY_OPERATION (1 << 6)
74 ADDRESS_QRCODE_BUTTON_TOKEN,
87 DISMISS_WARNING_TOKEN,
99typedef struct DetailsContext_s {
105 const char *nextPageStart;
108typedef struct AddressConfirmationContext_s {
111} AddressConfirmationContext_t;
114typedef struct KeypadContext_s {
124typedef struct BlindSigningContext_s {
129 const char *reviewTitle;
130 const char *reviewSubTitle;
131 const char *finishTitle;
139} ReviewWithWarningContext_t;
145 KeypadContext_t keypad;
147 ReviewWithWarningContext_t reviewWithWarning;
151 USE_CASE_GENERIC = 0,
153} GenericContextType_t;
156 GenericContextType_t type;
160 uint8_t currentContentElementNb;
162 bool hasStartingContent;
163 bool hasFinishingContent;
164 const char *detailsItem;
165 const char *detailsvalue;
166 bool detailsWrapping;
183} nbgl_homeAndSettingsContext_t;
188} nbgl_reviewContext_t;
196} nbgl_reviewStreamingContext_t;
199 nbgl_homeAndSettingsContext_t homeAndSettings;
200 nbgl_reviewContext_t review;
201 nbgl_reviewStreamingContext_t reviewStreaming;
202} nbgl_BundleNavContext_t;
208} SecurityReportItem_t;
215static char tmpString[W3C_DESCRIPTION_MAX_LEN];
235static const char *pageTitle;
238static const char *tipBoxModalTitle;
243static bool forwardNavOnly;
244static NavType_t navType;
246static DetailsContext_t detailsContext;
249static SharedContext_t sharedContext;
252static AddressConfirmationContext_t addressConfirmationContext;
255static GenericContext_t genericContext;
257 localContentsList[3];
258static uint8_t genericContextPagesInfo[MAX_PAGE_NB / PAGES_PER_UINT8];
261static nbgl_BundleNavContext_t bundleNavContext;
264static const uint8_t nbMaxElementsPerContentType[] = {
280 .text =
"Blind signing",
281 .subText =
"This transaction cannot be fully decoded." },
283 .text =
"Web3 Checks issue",
284 .subText =
"Web3 Checks could not verify this transaction." },
286 .text =
"Risk detected",
287 .subText =
"This transaction was scanned as risky by Web3 Checks." },
289 = {.icon = &ROUND_WARN_ICON,
290 .text =
"Threat detected",
291 .subText =
"This transaction was scanned as malicious by Web3 Checks."}
299static char reducedAddress[QRCODE_REDUCED_ADDR_LEN];
305static void displayReviewPage(
uint8_t page,
bool forceFullRefresh);
306static void displayDetailsPage(
uint8_t page,
bool forceFullRefresh);
307static void displayFullValuePage(
const char *backText,
308 const char *aliasText,
310static void displayTipBoxModal(
void);
311static void displaySettingsPage(
uint8_t page,
bool forceFullRefresh);
312static void displayGenericContextPage(
uint8_t pageIdx,
bool forceFullRefresh);
313static void pageCallback(
int token,
uint8_t index);
315static void displayAddressQRCode(
void);
317static void modalLayoutTouchCallback(
int token,
uint8_t index);
318static void displaySkipWarning(
void);
320static void bundleNavStartHome(
void);
321static void bundleNavStartSettingsAtPage(
uint8_t initSettingPage);
322static void bundleNavStartSettings(
void);
324static void bundleNavReviewStreamingChoice(
bool confirm);
325static void displaySecurityReport(uint32_t set);
327static void displayInitialWarning(
void);
331 const char *reviewTitle,
332 const char *reviewSubTitle,
333 const char *finishTitle,
337 bool playNotifSound);
340 const char *reviewTitle,
341 const char *reviewSubTitle,
343 bool playNotifSound);
344static void useCaseHomeExt(
const char *appName,
351static void displayDetails(
const char *tag,
const char *value,
bool wrapping);
353static void reset_callbacks(
void)
360 onContentAction = NULL;
362 onModalConfirm = NULL;
364 onValidatePin = NULL;
369static void genericContextSetPageInfo(
uint8_t pageIdx,
uint8_t nbElements,
bool flag)
371 uint8_t pageData = SET_PAGE_NB_ELEMENTS(nbElements) + SET_PAGE_FLAG(flag);
373 genericContextPagesInfo[pageIdx / PAGES_PER_UINT8]
374 &= ~(0x0F << ((pageIdx % PAGES_PER_UINT8) * PAGE_DATA_BITS));
375 genericContextPagesInfo[pageIdx / PAGES_PER_UINT8]
376 |= pageData << ((pageIdx % PAGES_PER_UINT8) * PAGE_DATA_BITS);
380static void genericContextGetPageInfo(
uint8_t pageIdx,
uint8_t *nbElements,
bool *flag)
382 uint8_t pageData = genericContextPagesInfo[pageIdx / PAGES_PER_UINT8]
383 >> ((pageIdx % PAGES_PER_UINT8) * PAGE_DATA_BITS);
384 if (nbElements != NULL) {
385 *nbElements = GET_PAGE_NB_ELEMENTS(pageData);
388 *flag = GET_PAGE_FLAG(pageData);
395 switch (content->
type) {
417 if (contentIdx < 0 || contentIdx >= genericContents->
nbContents) {
434static void prepareNavInfo(
bool isReview,
uint8_t nbPages,
const char *rejectText)
436 memset(&navInfo, 0,
sizeof(navInfo));
439 navInfo.
tuneId = TUNE_TAP_CASUAL;
443 if (isReview ==
false) {
452 = ((navType == STREAMING_NAV) && (nbPages < 2)) ?
false : true;
459 const char *reviewTitle,
460 const char *reviewSubTitle)
462 contentCenter->
icon = icon;
463 contentCenter->
title = reviewTitle;
465 contentCenter->
subText =
"Swipe to review";
468 contentCenter->
padding =
false;
474 const char *finishTitle)
476 infoLongPress->
text = finishTitle;
477 infoLongPress->
icon = icon;
484 const char *finishTitle)
486 infoButton->
text = finishTitle;
487 infoButton->
icon = icon;
494 UNUSED(operationType);
500static void pageModalCallback(
int token,
uint8_t index)
504 if (token == INFO_ALIAS_TOKEN) {
506 displayFullValuePage(tipBoxInfoList.
infoTypes[index],
512 modalPageContext = NULL;
513 if (token == NAV_TOKEN) {
520 displayDetailsPage(index,
false);
523 if (token == QUIT_TOKEN) {
528 else if (token == SKIP_TOKEN) {
539 else if (token == CHOICE_TOKEN) {
541 if (onModalConfirm != NULL) {
554static void pageCallback(
int token,
uint8_t index)
557 if (token == QUIT_TOKEN) {
558 if (onQuit != NULL) {
562 else if (token == CONTINUE_TOKEN) {
563 if (onContinue != NULL) {
567 else if (token == CHOICE_TOKEN) {
568 if (onChoice != NULL) {
569 onChoice((index == 0) ?
true : false);
572 else if (token == ACTION_BUTTON_TOKEN) {
573 if ((index == 0) && (onAction != NULL)) {
576 else if ((index == 1) && (onQuit != NULL)) {
581 else if (token == ADDRESS_QRCODE_BUTTON_TOKEN) {
582 displayAddressQRCode();
585 else if (token == CONFIRM_TOKEN) {
586 if (onChoice != NULL) {
590 else if (token == REJECT_TOKEN) {
591 if (onChoice != NULL) {
595 else if (token == DETAILS_BUTTON_TOKEN) {
596 displayDetails(genericContext.detailsItem,
597 genericContext.detailsvalue,
598 genericContext.detailsWrapping);
600 else if (token == NAV_TOKEN) {
602 if (onQuit != NULL) {
607 if (navType == GENERIC_NAV || navType == STREAMING_NAV) {
608 displayGenericContextPage(index,
false);
610 else if (navType == REVIEW_NAV) {
611 displayReviewPage(index,
false);
614 displaySettingsPage(index,
false);
618 else if (token == NEXT_TOKEN) {
620 displayReviewPage(navInfo.
activePage + 1,
false);
623 displayGenericContextPage(navInfo.
activePage + 1,
false);
626 else if (token == BACK_TOKEN) {
628 displayReviewPage(navInfo.
activePage - 1,
true);
631 displayGenericContextPage(navInfo.
activePage - 1,
false);
634 else if (token == SKIP_TOKEN) {
636 displaySkipWarning();
638 else if (token == VALUE_ALIAS_TOKEN) {
641 if (genericContext.currentPairs != NULL) {
642 pair = &genericContext.currentPairs[genericContext.currentElementIdx + index];
645 pair = genericContext.currentCallback(genericContext.currentElementIdx + index);
649 else if (token == BLIND_WARNING_TOKEN) {
650 reviewWithWarnCtx.isIntro =
false;
651 reviewWithWarnCtx.warning = NULL;
654 else if (token == WARNING_BUTTON_TOKEN) {
656 reviewWithWarnCtx.securityReportLevel = 1;
658 if (reviewWithWarnCtx.warning->predefinedSet) {
659 displaySecurityReport(reviewWithWarnCtx.warning->predefinedSet);
663 if (reviewWithWarnCtx.isIntro) {
664 displayCustomizedSecurityReport(reviewWithWarnCtx.warning->introDetails);
667 displayCustomizedSecurityReport(reviewWithWarnCtx.warning->reviewDetails);
671 else if (token == TIP_BOX_TOKEN) {
672 displayTipBoxModal();
675 if (onContentAction != NULL) {
676 onContentAction(token, index, navInfo.
activePage);
678 if (onControls != NULL) {
679 onControls(token, index);
685static void tickerCallback(
void)
688 if (onQuit != NULL) {
694static void displaySettingsPage(
uint8_t page,
bool forceFullRefresh)
698 if ((onNav == NULL) || (onNav(page, &content) ==
false)) {
703 content.
title = pageTitle;
706 content.
tuneId = TUNE_TAP_CASUAL;
711 if (forceFullRefresh) {
720static void displayReviewPage(
uint8_t page,
bool forceFullRefresh)
729 if ((onNav == NULL) || (onNav(navInfo.
activePage, &content) ==
false)) {
734 content.
title = NULL;
736 content.
tuneId = TUNE_TAP_CASUAL;
743 if (forwardNavOnly) {
767 if (forceFullRefresh) {
779 uint8_t *p_nbElementsInNextPage,
782 int8_t nextContentIdx = genericContext.currentContentIdx;
783 int16_t nextElementIdx = genericContext.currentElementIdx;
787 genericContextGetPageInfo(pageIdx, &nbElementsInNextPage, p_flag);
788 *p_nbElementsInNextPage = nbElementsInNextPage;
793 uint8_t nbElementsInCurrentPage;
795 genericContextGetPageInfo(navInfo.
activePage, &nbElementsInCurrentPage, NULL);
796 nextElementIdx += nbElementsInCurrentPage;
801 if ((nextElementIdx >= genericContext.currentContentElementNb)
802 && (genericContext.currentContentElementNb > 0)) {
812 nextElementIdx -= nbElementsInNextPage;
818 if (nextElementIdx < 0) {
820 nextElementIdx = -nbElementsInNextPage;
826 if ((nextContentIdx == -1) && (genericContext.hasStartingContent)) {
827 p_content = &STARTING_CONTENT;
829 else if ((nextContentIdx == genericContext.genericContents.nbContents)
830 && (genericContext.hasFinishingContent)) {
831 p_content = &FINISHING_CONTENT;
834 p_content = getContentAtIdx(&genericContext.genericContents, nextContentIdx, content);
836 if (p_content == NULL) {
851 if ((nextContentIdx != genericContext.currentContentIdx)
852 || (genericContext.currentContentElementNb == 0)) {
853 genericContext.currentContentIdx = nextContentIdx;
854 genericContext.currentContentElementNb = getContentNbElement(p_content);
856 if (nextElementIdx < 0) {
857 nextElementIdx = genericContext.currentContentElementNb + nextElementIdx;
862 if ((nextElementIdx < 0) || (nextElementIdx >= genericContext.currentContentElementNb)) {
864 "Invalid element index %d / %d\n",
866 genericContext.currentContentElementNb);
871 genericContext.currentElementIdx = nextElementIdx;
879static bool genericContextPreparePageContent(
const nbgl_content_t *p_content,
884 uint8_t nextElementIdx = genericContext.currentElementIdx;
886 pageContent->
title = pageTitle;
889 pageContent->
tuneId = TUNE_TAP_CASUAL;
891 pageContent->
type = p_content->
type;
892 switch (pageContent->
type) {
944 p_tagValueList = NULL;
956 genericContext.detailsItem = pair->
item;
957 genericContext.detailsvalue = pair->
value;
962 if (p_tagValueList != NULL) {
963 p_tagValueList->
nbPairs = nbElementsInPage;
966 p_tagValueList->
pairs
969 for (
uint8_t i = 0; i < nbElementsInPage; i++) {
971 p_tagValueList->
token = VALUE_ALIAS_TOKEN;
977 p_tagValueList->
pairs = NULL;
981 for (
uint8_t i = 0; i < nbElementsInPage; i++) {
985 p_tagValueList->
token = VALUE_ALIAS_TOKEN;
1023 < nextElementIdx + nbElementsInPage)) {
1043 bool isFirstOrLastPage
1047 = (navType == STREAMING_NAV)
1048 ? bundleNavContext.reviewStreaming.operationType
1049 : ((navType == GENERIC_NAV) ? bundleNavContext.review.operationType : 0);
1052 if (isFirstOrLastPage && (operationType & (
BLIND_OPERATION | RISKY_OPERATION))) {
1054 if ((operationType & RISKY_OPERATION)
1055 && (reviewWithWarnCtx.warning->predefinedSet == (1 <<
W3C_ISSUE_WARN))) {
1063 = (operationType &
BLIND_OPERATION) ? BLIND_WARNING_TOKEN : WARNING_BUTTON_TOKEN;
1070static void displayGenericContextPage(
uint8_t pageIdx,
bool forceFullRefresh)
1078 if (navType == STREAMING_NAV) {
1080 if (bundleNavContext.reviewStreaming.skipCallback != NULL) {
1081 bundleNavContext.reviewStreaming.skipCallback();
1085 else if (pageIdx >= bundleNavContext.reviewStreaming.stepPageNb) {
1086 bundleNavReviewStreamingChoice(
true);
1093 = genericContextComputeNextPageParams(pageIdx, &content, &nbElementsInPage, &flag);
1098 for (
int i = navInfo.
activePage + 1; i <= pageIdx; i++) {
1099 p_content = genericContextComputeNextPageParams(i, &content, &nbElementsInPage, &flag);
1109 = genericContextComputeNextPageParams(pageIdx, &content, &nbElementsInPage, &flag);
1112 if (p_content == NULL) {
1118 if (!genericContextPreparePageContent(p_content, nbElementsInPage, flag, &pageContent)) {
1124 if (forceFullRefresh) {
1133static const char *getDetailsPageAt(
uint8_t detailsPage)
1136 const char *currentChar = detailsContext.value;
1137 while (page < detailsPage) {
1140 if (nbLines > NB_MAX_LINES_IN_DETAILS) {
1145 NB_MAX_LINES_IN_DETAILS,
1147 detailsContext.wrapping);
1149 currentChar = currentChar + len;
1157static void displayDetailsPage(
uint8_t detailsPage,
bool forceFullRefresh)
1161 .nbPages = detailsContext.nbPages,
1163 .quitToken = QUIT_TOKEN,
1164 .navWithButtons.navToken = NAV_TOKEN,
1165 .navWithButtons.quitButton =
true,
1166 .navWithButtons.backButton =
true,
1167 .navWithButtons.quitText = NULL,
1168 .progressIndicator =
false,
1169 .tuneId = TUNE_TAP_CASUAL};
1171 .topRightIcon = NULL,
1172 .tagValueList.nbPairs = 1,
1173 .tagValueList.pairs = ¤tPair,
1174 .tagValueList.smallCaseForValue =
true,
1175 .tagValueList.wrapping = detailsContext.wrapping};
1177 if (modalPageContext != NULL) {
1180 currentPair.
item = detailsContext.tag;
1182 if (detailsPage <= detailsContext.currentPage) {
1184 currentPair.
value = getDetailsPageAt(detailsPage);
1185 forceFullRefresh =
true;
1189 currentPair.
value = detailsContext.nextPageStart;
1191 detailsContext.currentPage = detailsPage;
1195 if (nbLines > NB_MAX_LINES_IN_DETAILS) {
1200 NB_MAX_LINES_IN_DETAILS,
1202 detailsContext.wrapping);
1205 detailsContext.nextPageStart = currentPair.
value + len;
1211 detailsContext.nextPageStart = NULL;
1220 if (forceFullRefresh) {
1229static void displayFullValuePage(
const char *backText,
1230 const char *aliasText,
1234 .withLeftBorder =
true,
1235 .onActionCallback = &modalLayoutTouchCallback,
1236 .tapActionText = NULL};
1238 .separationLine =
false,
1239 .backAndText.token = 0,
1240 .backAndText.tuneId = TUNE_TAP_CASUAL,
1241 .backAndText.text = PIC(backText)};
1250 .text1 = (extension->
title != NULL) ? extension->
title : extension->fullValue,
1251 .text2 = extension->explanation,
1262 info =
"ENS names are resolved by Ledger backend.";
1265 info =
"This account label comes from your Address Book in Ledger Live.";
1271 genericContext.modalLayout, aliasText, extension->
fullValue, info);
1279static void displayTipBoxModal(
void)
1284 .quitToken = QUIT_TOKEN,
1285 .navWithButtons.navToken = NAV_TOKEN,
1286 .navWithButtons.quitButton =
false,
1287 .navWithButtons.backButton =
true,
1288 .navWithButtons.quitText = NULL,
1289 .progressIndicator =
false,
1290 .tuneId = TUNE_TAP_CASUAL};
1292 .topRightIcon = NULL,
1293 .infosList.nbInfos = tipBoxInfoList.
nbInfos,
1295 .infosList.infoTypes = tipBoxInfoList.
infoTypes,
1298 .infosList.token = INFO_ALIAS_TOKEN,
1299 .
title = tipBoxModalTitle,
1300 .titleToken = QUIT_TOKEN,
1301 .tuneId = TUNE_TAP_CASUAL};
1303 if (modalPageContext != NULL) {
1312static void displayAddressQRCode(
void)
1316 .withLeftBorder =
true,
1317 .onActionCallback = &modalLayoutTouchCallback,
1318 .tapActionText = NULL};
1320 .
type =
HEADER_EMPTY, .separationLine =
false, .emptySpace.height = SMALL_CENTERING_HEADER};
1326 addressConfirmationContext.modalLayout =
nbgl_layoutGet(&layoutDescription);
1331 SMALL_REGULAR_FONT, addressConfirmationContext.tagValuePair.value,
AVAILABLE_WIDTH,
false);
1333 if (nbLines <= QRCODE_NB_MAX_LINES) {
1334 qrCode.
text2 = addressConfirmationContext.tagValuePair.value;
1339 addressConfirmationContext.tagValuePair.value,
1341 QRCODE_NB_MAX_LINES,
1343 QRCODE_REDUCED_ADDR_LEN);
1344 qrCode.
text2 = reducedAddress;
1350 addressConfirmationContext.modalLayout,
"Close", DISMISS_QR_TOKEN, TUNE_TAP_CASUAL);
1358static void modalLayoutTouchCallback(
int token,
uint8_t index)
1361 if (token == DISMISS_QR_TOKEN) {
1364 addressConfirmationContext.modalLayout = NULL;
1367 else if (token == DISMISS_WARNING_TOKEN) {
1371 if (reviewWithWarnCtx.securityReportLevel <= 1) {
1372 reviewWithWarnCtx.modalLayout = NULL;
1377 reviewWithWarnCtx.securityReportLevel = 1;
1379 if (reviewWithWarnCtx.warning->predefinedSet) {
1380 displaySecurityReport(reviewWithWarnCtx.warning->predefinedSet);
1385 = (reviewWithWarnCtx.isIntro) ? reviewWithWarnCtx.warning->introDetails
1386 : reviewWithWarnCtx.warning->reviewDetails;
1387 displayCustomizedSecurityReport(details);
1392 else if ((token >= FIRST_WARN_BAR_TOKEN) && (token <= LAST_WARN_BAR_TOKEN)) {
1395 reviewWithWarnCtx.securityReportLevel = 2;
1397 if (reviewWithWarnCtx.warning->predefinedSet) {
1398 displaySecurityReport(1 << (token - FIRST_WARN_BAR_TOKEN));
1403 ? reviewWithWarnCtx.warning->introDetails
1404 : reviewWithWarnCtx.warning->reviewDetails;
1406 displayCustomizedSecurityReport(
1415 genericContext.modalLayout = NULL;
1422static void layoutTouchCallback(
int token,
uint8_t index)
1425 if (token == WARNING_CHOICE_TOKEN) {
1427 reviewWithWarnCtx.choiceCallback(
false);
1430 reviewWithWarnCtx.isIntro =
false;
1431 if (reviewWithWarnCtx.isStreaming) {
1432 useCaseReviewStreamingStart(reviewWithWarnCtx.operationType,
1433 reviewWithWarnCtx.icon,
1434 reviewWithWarnCtx.reviewTitle,
1435 reviewWithWarnCtx.reviewSubTitle,
1436 reviewWithWarnCtx.choiceCallback,
1440 useCaseReview(reviewWithWarnCtx.operationType,
1441 reviewWithWarnCtx.tagValueList,
1442 reviewWithWarnCtx.icon,
1443 reviewWithWarnCtx.reviewTitle,
1444 reviewWithWarnCtx.reviewSubTitle,
1445 reviewWithWarnCtx.finishTitle,
1446 reviewWithWarnCtx.tipBox,
1447 reviewWithWarnCtx.choiceCallback,
1454 else if (token == WARNING_BUTTON_TOKEN) {
1456 reviewWithWarnCtx.securityReportLevel = 1;
1458 if (reviewWithWarnCtx.warning->predefinedSet) {
1459 displaySecurityReport(reviewWithWarnCtx.warning->predefinedSet);
1464 ? reviewWithWarnCtx.warning->introDetails
1465 : reviewWithWarnCtx.warning->reviewDetails;
1466 displayCustomizedSecurityReport(details);
1472static void displaySkipWarning(
void)
1475 .cancelText =
"Go back to review",
1476 .centeredInfo.text1 =
"Skip review?",
1478 =
"If you're sure you don't need to review all fields, you can skip straight to signing.",
1479 .centeredInfo.text3 = NULL,
1481 .centeredInfo.icon = &C_Important_Circle_64px,
1482 .centeredInfo.offsetY = 0,
1483 .confirmationText =
"Yes, skip",
1484 .confirmationToken = SKIP_TOKEN,
1485 .
tuneId = TUNE_TAP_CASUAL,
1487 if (modalPageContext != NULL) {
1499static void updateKeyPad(
bool add)
1501 bool enableValidate, enableBackspace, enableDigits;
1502 bool redrawKeypad =
false;
1505 enableDigits = (keypadContext.pinLen < keypadContext.pinMaxDigits);
1506 enableValidate = (keypadContext.pinLen >= keypadContext.pinMinDigits);
1507 enableBackspace = (keypadContext.pinLen > 0);
1509 if ((keypadContext.pinLen == keypadContext.pinMinDigits)
1511 (keypadContext.pinLen == keypadContext.pinMaxDigits)
1513 (keypadContext.pinLen == 1)) {
1514 redrawKeypad =
true;
1518 if ((keypadContext.pinLen == 0) ||
1519 (keypadContext.pinLen == (keypadContext.pinMinDigits - 1))
1521 (keypadContext.pinLen
1522 == (keypadContext.pinMaxDigits - 1))) {
1523 redrawKeypad =
true;
1526 if (keypadContext.hidden ==
true) {
1531 keypadContext.layoutCtx,
false, 0, (
const char *) keypadContext.pinEntry);
1535 keypadContext.layoutCtx, 0, enableValidate, enableBackspace, enableDigits);
1538 if ((!add) && (keypadContext.pinLen == 0)) {
1546static void keypadCallback(
char touchedKey)
1548 switch (touchedKey) {
1550 if (keypadContext.pinLen > 0) {
1551 keypadContext.pinLen--;
1552 keypadContext.pinEntry[keypadContext.pinLen] = 0;
1554 updateKeyPad(
false);
1563 onValidatePin(keypadContext.pinEntry, keypadContext.pinLen);
1567 if ((touchedKey >= 0x30) && (touchedKey < 0x40)) {
1568 if (keypadContext.pinLen < keypadContext.pinMaxDigits) {
1569 keypadContext.pinEntry[keypadContext.pinLen] = touchedKey;
1570 keypadContext.pinLen++;
1579static void keypadGenericUseCase(
const char *title,
1585 tune_index_e tuneId,
1591 .separationLine =
true,
1592 .backAndText.token = backToken,
1593 .backAndText.tuneId = tuneId,
1594 .backAndText.text = NULL};
1603 memset(&keypadContext, 0,
sizeof(KeypadContext_t));
1607 layoutDescription.
modal =
false;
1610 keypadContext.hidden = hidden;
1622 keypadContext.layoutCtx, title, keypadContext.hidden, maxDigits,
"");
1629 onValidatePin = validatePinCallback;
1631 keypadContext.pinMinDigits = minDigits;
1632 keypadContext.pinMaxDigits = maxDigits;
1650 nbElements = getContentNbElement(content);
1652 while (nbElements > 0) {
1655 bool hasNav = !isLast || (pageIdxStart > 0) || (elemIdx > 0);
1677 nbElementsInPage =
MIN(nbMaxElementsPerContentType[content->
type], nbElements);
1680 elemIdx += nbElementsInPage;
1681 genericContextSetPageInfo(pageIdxStart + nbPages, nbElementsInPage, flag);
1682 nbElements -= nbElementsInPage;
1697 for (
int i = 0; i < genericContents->
nbContents; i++) {
1698 p_content = getContentAtIdx(genericContents, i, &content);
1699 if (p_content == NULL) {
1702 nbPages += nbgl_useCaseGetNbPagesForContent(p_content,
1703 pageIdxStart + nbPages,
1711static void prepareAddressConfirmationPages(
const char *address,
1718 addressConfirmationContext.tagValuePair.item =
"Address";
1719 addressConfirmationContext.tagValuePair.value = address;
1728 if (tagValueList != NULL) {
1739 tagValueConfirm->tuneId = TUNE_TAP_CASUAL;
1747 if (tagValueList != NULL) {
1757 if (tagValueList != NULL) {
1765 tagValueConfirm->tuneId = TUNE_TAP_CASUAL;
1770static void bundleNavStartHome(
void)
1772 nbgl_homeAndSettingsContext_t *context = &bundleNavContext.homeAndSettings;
1774 useCaseHomeExt(context->appName,
1777 context->settingContents != NULL ?
true : false,
1778 &context->homeAction,
1779 bundleNavStartSettings,
1780 context->quitCallback);
1783static void bundleNavStartSettingsAtPage(
uint8_t initSettingPage)
1785 nbgl_homeAndSettingsContext_t *context = &bundleNavContext.homeAndSettings;
1789 context->settingContents,
1791 bundleNavStartHome);
1794static void bundleNavStartSettings(
void)
1796 bundleNavStartSettingsAtPage(0);
1799static void bundleNavReviewConfirmRejection(
void)
1801 bundleNavContext.review.choiceCallback(
false);
1808 const char *confirmText;
1812 title =
"Reject transaction?";
1813 confirmText =
"Go back to transaction";
1816 title =
"Reject message?";
1817 confirmText =
"Go back to message";
1820 title =
"Reject operation?";
1821 confirmText =
"Go back to operation";
1828static void bundleNavReviewChoice(
bool confirm)
1831 bundleNavContext.review.choiceCallback(
true);
1834 bundleNavReviewAskRejectionConfirmation(bundleNavContext.review.operationType,
1835 bundleNavReviewConfirmRejection);
1839static void bundleNavReviewStreamingConfirmRejection(
void)
1841 bundleNavContext.reviewStreaming.choiceCallback(
false);
1844static void bundleNavReviewStreamingChoice(
bool confirm)
1851 bundleNavContext.reviewStreaming.choiceCallback(
true);
1854 bundleNavReviewAskRejectionConfirmation(bundleNavContext.reviewStreaming.operationType,
1855 bundleNavReviewStreamingConfirmRejection);
1862static void displaySecurityReport(uint32_t set)
1865 .withLeftBorder =
true,
1866 .onActionCallback = modalLayoutTouchCallback,
1867 .tapActionText = NULL};
1869 .separationLine =
true,
1870 .backAndText.icon = NULL,
1871 .backAndText.tuneId = TUNE_TAP_CASUAL,
1872 .backAndText.token = DISMISS_WARNING_TOKEN};
1877 const char *provider;
1879 reviewWithWarnCtx.modalLayout =
nbgl_layoutGet(&layoutDescription);
1883 if (set & (1 << i)) {
1888 if ((nbWarnings > 1) && (reviewWithWarnCtx.securityReportLevel == 1)) {
1891 if (reviewWithWarnCtx.warning->predefinedSet & (1 << i)) {
1894 || (reviewWithWarnCtx.warning->providerMessage == NULL)) {
1895 bar.
subText = securityReportItems[i].subText;
1899 W3C_DESCRIPTION_MAX_LEN,
1900 "Web3 Checks found a risk:\n%s.",
1901 reviewWithWarnCtx.warning->providerMessage);
1904 bar.
text = securityReportItems[i].text;
1906 bar.
iconLeft = securityReportItems[i].icon;
1907 bar.
token = FIRST_WARN_BAR_TOKEN + i;
1908 bar.tuneId = TUNE_TAP_CASUAL;
1921 if (reviewWithWarnCtx.warning && reviewWithWarnCtx.warning->reportProvider) {
1922 provider = reviewWithWarnCtx.warning->reportProvider;
1925 provider =
"[unknown]";
1928 if (reviewWithWarnCtx.isIntro) {
1932 = {.
url =
"ledger.com/e8",
1933 .text1 =
"ledger.com/e8",
1934 .text2 =
"Scan to learn about the risks of blind signing.",
1945 info.
icon = &C_Warning_64px;
1946 info.
title =
"Blind Signing";
1948 =
"This transaction's details are not fully verifiable. If you sign it, you could "
1949 "lose all your assets.\n\n"
1950 "Learn about blind signing:\nledger.com/e8";
1959 info.
icon = &C_Important_Circle_64px;
1960 info.
title =
"Web3 Checks could not verify this message";
1961 info.
description =
"An issue prevented Web3 Checks from running.\nGet help: ledger.com/e11";
1967 if (reviewWithWarnCtx.isIntro) {
1971 .text1 = reviewWithWarnCtx.warning->reportUrl,
1976 W3C_DESCRIPTION_MAX_LEN,
1977 "Scan to view the threat report from %s.",
1987 info.
icon = &C_Warning_64px;
1988 info.
title =
"Threat detected";
1990 if (reviewWithWarnCtx.warning->providerMessage != NULL) {
1991 info.
smallTitle = reviewWithWarnCtx.warning->providerMessage;
1997 W3C_DESCRIPTION_MAX_LEN,
1998 "This transaction was scanned as malicious by Web3 Checks.\n\n"
1999 "View full %s report:\n%s",
2001 reviewWithWarnCtx.warning->reportUrl);
2008 if (reviewWithWarnCtx.isIntro) {
2012 .text1 = reviewWithWarnCtx.warning->reportUrl,
2017 W3C_DESCRIPTION_MAX_LEN,
2018 "Scan to view the risk report from %s.",
2028 info.
icon = &C_Warning_64px;
2029 info.
title =
"Risk detected";
2031 if (reviewWithWarnCtx.warning->providerMessage != NULL) {
2032 info.
smallTitle = reviewWithWarnCtx.warning->providerMessage;
2038 W3C_DESCRIPTION_MAX_LEN,
2039 "This transaction was scanned as risky by Web3 Checks.\n\n"
2040 "View full %s report:\n%s",
2042 reviewWithWarnCtx.warning->reportUrl);
2062 .withLeftBorder =
true,
2063 .onActionCallback = modalLayoutTouchCallback,
2064 .tapActionText = NULL};
2066 .separationLine =
true,
2067 .backAndText.icon = NULL,
2068 .backAndText.tuneId = TUNE_TAP_CASUAL,
2069 .backAndText.token = DISMISS_WARNING_TOKEN};
2072 reviewWithWarnCtx.modalLayout =
nbgl_layoutGet(&layoutDescription);
2083 bar.
token = FIRST_WARN_BAR_TOKEN + i;
2084 bar.tuneId = TUNE_TAP_CASUAL;
2108static void displayInitialWarning(
void)
2111#ifdef HAVE_PIEZO_SOUND
2112 io_seproxyhal_play_tune(TUNE_LOOK_AT_ME);
2116 .token = WARNING_CHOICE_TOKEN,
2117 .topText =
"Back to safety",
2119 .tuneId = TUNE_TAP_CASUAL};
2121 .separationLine =
false,
2122 .emptySpace.height = MEDIUM_CENTERING_HEADER};
2124 reviewWithWarnCtx.isIntro =
true;
2126 layoutDescription.
modal =
false;
2132 layoutDescription.
ticker.tickerCallback = NULL;
2133 reviewWithWarnCtx.layoutCtx =
nbgl_layoutGet(&layoutDescription);
2137 if (reviewWithWarnCtx.warning->predefinedSet != (1 <<
W3C_ISSUE_WARN)) {
2138 if (reviewWithWarnCtx.warning->predefinedSet != 0) {
2140 reviewWithWarnCtx.layoutCtx, &PRIVACY_ICON, WARNING_BUTTON_TOKEN, TUNE_TAP_CASUAL);
2142 else if (reviewWithWarnCtx.warning->introTopRightIcon != NULL) {
2144 reviewWithWarnCtx.warning->introTopRightIcon,
2145 WARNING_BUTTON_TOKEN,
2153 if (reviewWithWarnCtx.warning->predefinedSet != 0) {
2155 info.
icon = &C_Warning_64px;
2157 info.
title =
"Blind signing ahead";
2159 =
"The details of this transaction or message are not fully verifiable. If "
2160 "you sign it, you could lose all "
2163 else if (reviewWithWarnCtx.warning->predefinedSet == (1 <<
W3C_ISSUE_WARN)) {
2164 info.
icon = &C_Important_Circle_64px;
2165 info.
title =
"Web3 Checks could not verify this message";
2167 =
"An issue prevented Web3 Checks from running.\nGet help: ledger.com/e11";
2170 info.
title =
"Risk detected";
2171 info.
description =
"This transaction was scanned as ricky by Web3 Checks.";
2172 if (reviewWithWarnCtx.warning->providerMessage != NULL) {
2173 info.
smallTitle = reviewWithWarnCtx.warning->providerMessage;
2180 info.
title =
"Threat detected";
2181 info.
description =
"This transaction was scanned as malicious by Web3 Checks.";
2182 if (reviewWithWarnCtx.warning->providerMessage != NULL) {
2183 info.
smallTitle = reviewWithWarnCtx.warning->providerMessage;
2191 info.
title =
"Dangerous transaction";
2192 if (reviewWithWarnCtx.warning->predefinedSet & (1 <<
W3C_ISSUE_WARN)) {
2194 =
"This transaction cannot be fully decoded, and was not verified by Web3 "
2199 =
"This transaction cannot be fully decoded, and was marked as risky by Web3 "
2205 else if (reviewWithWarnCtx.warning->info != NULL) {
2218 const char *reviewTitle,
2219 const char *reviewSubTitle,
2220 const char *finishTitle,
2224 bool playNotifSound)
2227 memset(&genericContext, 0,
sizeof(genericContext));
2229 bundleNavContext.review.operationType = operationType;
2230 bundleNavContext.review.choiceCallback = choiceCallback;
2233 onChoice = bundleNavReviewChoice;
2234 navType = GENERIC_NAV;
2237 genericContext.genericContents.contentsList = localContentsList;
2238 genericContext.genericContents.nbContents = 3;
2243 prepareReviewFirstPage(
2244 &STARTING_CONTENT.content.extendedCenter.contentCenter, icon, reviewTitle, reviewSubTitle);
2245 if (tipBox != NULL) {
2247 STARTING_CONTENT.content.extendedCenter.contentCenter.subText = NULL;
2249 STARTING_CONTENT.content.extendedCenter.tipBox.icon = tipBox->
icon;
2250 STARTING_CONTENT.content.extendedCenter.tipBox.text = tipBox->
text;
2251 STARTING_CONTENT.content.extendedCenter.tipBox.token = TIP_BOX_TOKEN;
2252 STARTING_CONTENT.content.extendedCenter.tipBox.tuneId = TUNE_TAP_CASUAL;
2266 memcpy(&localContentsList[1].content.tagValueList,
2274 prepareReviewLightLastPage(&localContentsList[2].content.infoButton, icon, finishTitle);
2278 prepareReviewLastPage(&localContentsList[2].content.infoLongPress, icon, finishTitle);
2282 uint8_t nbPages = getNbPagesForGenericContents(
2284 prepareNavInfo(
true, nbPages, getRejectReviewText(operationType));
2287 if (playNotifSound) {
2288#ifdef HAVE_PIEZO_SOUND
2289 io_seproxyhal_play_tune(TUNE_LOOK_AT_ME);
2293 displayGenericContextPage(0,
true);
2299 const char *reviewTitle,
2300 const char *reviewSubTitle,
2302 bool playNotifSound)
2305 memset(&genericContext, 0,
sizeof(genericContext));
2307 bundleNavContext.reviewStreaming.operationType = operationType;
2308 bundleNavContext.reviewStreaming.choiceCallback = choiceCallback;
2309 bundleNavContext.reviewStreaming.icon = icon;
2312 onChoice = bundleNavReviewStreamingChoice;
2313 navType = STREAMING_NAV;
2316 genericContext.genericContents.contentsList = localContentsList;
2317 genericContext.genericContents.nbContents = 1;
2322 prepareReviewFirstPage(
2323 &STARTING_CONTENT.content.extendedCenter.contentCenter, icon, reviewTitle, reviewSubTitle);
2326 bundleNavContext.reviewStreaming.stepPageNb = getNbPagesForGenericContents(
2333 if (playNotifSound) {
2334#ifdef HAVE_PIEZO_SOUND
2335 io_seproxyhal_play_tune(TUNE_LOOK_AT_ME);
2339 displayGenericContextPage(0,
true);
2358static void useCaseHomeExt(
const char *appName,
2360 const char *tagline,
2369 .centeredInfo.text1 = appName,
2370 .centeredInfo.text3 = NULL,
2372 .centeredInfo.offsetY = 0,
2375 .tapActionText = NULL,
2377 .topRightToken = CONTINUE_TOKEN,
2378 .tuneId = TUNE_TAP_CASUAL};
2379 if ((homeAction->
text != NULL) || (homeAction->
icon != NULL)) {
2394 if (tagline == NULL) {
2398 "This app enables signing\ntransactions on its network.");
2425 onContinue = topRightCallback;
2426 onQuit = quitCallback;
2440static void displayDetails(
const char *tag,
const char *value,
bool wrapping)
2442 memset(&detailsContext, 0,
sizeof(detailsContext));
2448 detailsContext.tag = tag;
2449 detailsContext.value = value;
2450 detailsContext.nbPages = (nbLines + NB_MAX_LINES_IN_DETAILS - 1) / NB_MAX_LINES_IN_DETAILS;
2451 detailsContext.currentPage = 0;
2452 detailsContext.wrapping = wrapping;
2454 if (detailsContext.nbPages > 1) {
2455 uint16_t nbLostChars = (detailsContext.nbPages - 1) * 3;
2459 = nbLines - ((detailsContext.nbPages - 1) * NB_MAX_LINES_IN_DETAILS);
2461 detailsContext.nbPages += nbLostLines / NB_MAX_LINES_IN_DETAILS;
2462 if ((nbLinesInLastPage + (nbLostLines % NB_MAX_LINES_IN_DETAILS))
2463 > NB_MAX_LINES_IN_DETAILS) {
2464 detailsContext.nbPages++;
2468 displayDetailsPage(0,
true);
2490 bool *requireSpecificDisplay)
2493 nbPairs, tagValueList, startIndex,
false, requireSpecificDisplay);
2513 bool *requireSpecificDisplay)
2516 uint16_t currentHeight = PRE_TAG_VALUE_MARGIN;
2522 maxUsableHeight -= TOUCHABLE_HEADER_BAR_HEIGHT - SMALL_CENTERING_HEADER;
2525 *requireSpecificDisplay =
false;
2526 while (nbPairsInPage < nbPairs) {
2533 if (nbPairsInPage > 0) {
2534 currentHeight += INTER_TAG_VALUE_MARGIN;
2537 if (tagValueList->
pairs != NULL) {
2538 pair = PIC(&tagValueList->
pairs[startIndex + nbPairsInPage]);
2541 pair = PIC(tagValueList->
callback(startIndex + nbPairsInPage));
2550 if (nbPairsInPage > 0) {
2557 *requireSpecificDisplay =
true;
2569 value_font = SMALL_REGULAR_FONT;
2572 value_font = LARGE_MEDIUM_FONT;
2580 if ((currentHeight >= maxUsableHeight) || (nbLines > NB_MAX_LINES_IN_REVIEW)) {
2581 if (nbPairsInPage == 0) {
2585 *requireSpecificDisplay =
true;
2591 return nbPairsInPage;
2611 uint16_t navHeight = withNav ? SIMPLE_FOOTER_HEIGHT : 0;
2612 const char *
const *infoTypes = PIC(infosList->
infoTypes);
2613 const char *
const *infoContents = PIC(infosList->
infoContents);
2615 while (nbInfosInPage < nbInfos) {
2617 currentHeight += PRE_TEXT_MARGIN;
2621 SMALL_BOLD_FONT, PIC(infoTypes[startIndex + nbInfosInPage]),
AVAILABLE_WIDTH,
true);
2623 currentHeight += TEXT_SUBTEXT_MARGIN;
2627 PIC(infoContents[startIndex + nbInfosInPage]),
2630 currentHeight += POST_SUBTEXT_MARGIN;
2635 if (!withNav && (previousHeight >= (
INFOS_AREA_HEIGHT - SIMPLE_FOOTER_HEIGHT))) {
2640 previousHeight = currentHeight;
2643 return nbInfosInPage;
2663 uint16_t navHeight = withNav ? SIMPLE_FOOTER_HEIGHT : 0;
2666 while (nbSwitchesInPage < nbSwitches) {
2668 currentHeight += PRE_TEXT_MARGIN;
2672 switchArray[startIndex + nbSwitchesInPage].text,
2676 currentHeight += TEXT_SUBTEXT_MARGIN;
2681 switchArray[startIndex + nbSwitchesInPage].subText,
2684 currentHeight += POST_SUBTEXT_MARGIN;
2689 if (!withNav && (previousHeight >= (
INFOS_AREA_HEIGHT - SIMPLE_FOOTER_HEIGHT))) {
2694 previousHeight = currentHeight;
2697 return nbSwitchesInPage;
2717 uint16_t navHeight = withNav ? SIMPLE_FOOTER_HEIGHT : 0;
2722 while (nbBarsInPage < nbBars) {
2723 currentHeight += TOUCHABLE_BAR_HEIGHT;
2728 previousHeight = currentHeight;
2733 if (!withNav && (previousHeight >= (
INFOS_AREA_HEIGHT - SIMPLE_FOOTER_HEIGHT))) {
2736 return nbBarsInPage;
2756 uint16_t navHeight = withNav ? SIMPLE_FOOTER_HEIGHT : 0;
2758 UNUSED(choicesList);
2761 while (nbChoicesInPage < nbChoices) {
2762 currentHeight += TOUCHABLE_BAR_HEIGHT;
2767 if (!withNav && (previousHeight >= (
INFOS_AREA_HEIGHT - SIMPLE_FOOTER_HEIGHT))) {
2772 previousHeight = currentHeight;
2775 return nbChoicesInPage;
2792 while (i < tagValueList->nbPairs) {
2796 nbPairs -= nbPairsInPage;
2808 const char *tagline,
2815 appName, appIcon, tagline, withSettings, &homeAction, topRightCallback, quitCallback);
2824 const char *tagline,
2826 const char *actionButtonText,
2834 .text = actionButtonText};
2837 appName, appIcon, tagline, withSettings, &homeAction, topRightCallback, quitCallback);
2863 onQuit = quitCallback;
2864 onNav = navCallback;
2865 onControls = controlsCallback;
2867 navType = SETTINGS_NAV;
2870 prepareNavInfo(
false, nbPages, NULL);
2872 displaySettingsPage(initPage,
true);
2890 title, initPage, nbPages, quitCallback, navCallback, controlsCallback);
2912 memset(&genericContext, 0,
sizeof(genericContext));
2915 onQuit = quitCallback;
2916 pageTitle = appName;
2917 navType = GENERIC_NAV;
2919 if (settingContents != NULL) {
2922 if (infosList != NULL) {
2923 genericContext.hasFinishingContent =
true;
2926 memcpy(&FINISHING_CONTENT.content, infosList,
sizeof(
nbgl_content_u));
2930 uint8_t nbPages = getNbPagesForGenericContents(&genericContext.genericContents, 0,
false);
2931 if (infosList != NULL) {
2932 nbPages += nbgl_useCaseGetNbPagesForContent(&FINISHING_CONTENT, nbPages,
true,
false);
2935 prepareNavInfo(
false, nbPages, NULL);
2937 displayGenericContextPage(initPage,
true);
2976 const char *appName,
2978 const char *tagline,
2986 nbgl_homeAndSettingsContext_t *context = &bundleNavContext.homeAndSettings;
2988 context->appName = appName;
2989 context->appIcon = appIcon;
2990 context->tagline = tagline;
2991 context->settingContents = settingContents;
2992 context->infosList = infosList;
2993 if (action != NULL) {
2999 context->quitCallback = quitCallback;
3002 bundleNavStartSettingsAtPage(initSettingPage);
3005 bundleNavStartHome();
3021 .tickerCallback = &tickerCallback,
3022 .tickerIntervale = 0,
3025 onQuit = quitCallback;
3027#ifdef HAVE_PIEZO_SOUND
3028 io_seproxyhal_play_tune(TUNE_LEDGER_MOMENT);
3036 .centeredInfo.icon = &C_Denied_Circle_64px,
3037 .centeredInfo.offsetY = SMALL_FOOTER_HEIGHT / 2,
3038 .centeredInfo.onTop =
false,
3040 .centeredInfo.text1 = message,
3041 .centeredInfo.text2 = NULL,
3042 .centeredInfo.text3 = NULL,
3043 .tapActionText =
"",
3044 .isSwipeable =
false,
3045 .tapActionToken = QUIT_TOKEN,
3047 .actionButtonText = NULL,
3048 .tuneId = TUNE_TAP_CASUAL};
3065 switch (reviewStatusType) {
3067 msg =
"Operation signed";
3071 msg =
"Operation rejected";
3075 msg =
"Transaction signed";
3079 msg =
"Transaction rejected";
3083 msg =
"Message signed";
3087 msg =
"Message rejected";
3091 msg =
"Address verified";
3095 msg =
"Address verification\ncancelled";
3117 const char *message,
3118 const char *subMessage,
3119 const char *confirmText,
3120 const char *cancelText,
3127 .centeredInfo.text2 = subMessage,
3128 .centeredInfo.text3 = NULL,
3130 .centeredInfo.icon = icon,
3131 .centeredInfo.offsetY = 0,
3132 .confirmationText = confirmText,
3133 .confirmationToken = CHOICE_TOKEN,
3134 .tuneId = TUNE_TAP_CASUAL,
3137 if ((confirmText == NULL) || (cancelText == NULL)) {
3140 onChoice = callback;
3159 const char *subMessage,
3160 const char *confirmText,
3161 const char *cancelText,
3167 .centeredInfo.text1 = message,
3168 .centeredInfo.text2 = subMessage,
3169 .centeredInfo.text3 = NULL,
3171 .centeredInfo.icon = &C_Important_Circle_64px,
3172 .centeredInfo.offsetY = 0,
3173 .confirmationText = confirmText,
3174 .confirmationToken = CHOICE_TOKEN,
3175 .tuneId = TUNE_TAP_CASUAL,
3177 onModalConfirm = callback;
3178 if (modalPageContext != NULL) {
3197 const char *reviewTitle,
3198 const char *reviewSubTitle,
3199 const char *rejectText,
3206 .footerToken = QUIT_TOKEN,
3207 .tapActionText = NULL,
3208 .isSwipeable =
true,
3209 .tapActionToken = CONTINUE_TOKEN,
3211 .actionButtonText = NULL,
3212 .
tuneId = TUNE_TAP_CASUAL};
3219 onQuit = rejectCallback;
3220 onContinue = continueCallback;
3222#ifdef HAVE_PIEZO_SOUND
3224 io_seproxyhal_play_tune(TUNE_LOOK_AT_ME);
3237 const char *rejectText,
3245 onChoice = choiceCallback;
3246 onNav = navCallback;
3247 onControls = buttonCallback;
3248 forwardNavOnly =
false;
3249 navType = REVIEW_NAV;
3253 prepareNavInfo(
true, nbPages, getRejectReviewText(
TYPE_OPERATION));
3255 displayReviewPage(initPage,
true);
3272 const char *rejectText,
3278 memset(&genericContext, 0,
sizeof(genericContext));
3281 onChoice = callback;
3282 navType = GENERIC_NAV;
3286 genericContext.genericContents.contentsList = localContentsList;
3289 if (tagValueList != NULL && tagValueList->
nbPairs != 0) {
3291 memcpy(&localContentsList[offset].content.tagValueList,
3298 memcpy(&localContentsList[offset].content.infoLongPress,
3304 genericContext.genericContents.nbContents = offset;
3307 uint8_t nbPages = getNbPagesForGenericContents(&genericContext.genericContents, 0,
false);
3309 prepareNavInfo(
true, nbPages, getRejectReviewText(
TYPE_OPERATION));
3311 displayGenericContextPage(0,
true);
3329 const char *rejectText,
3335 memset(&genericContext, 0,
sizeof(genericContext));
3338 onChoice = callback;
3339 navType = GENERIC_NAV;
3342 genericContext.genericContents.contentsList = localContentsList;
3345 if (tagValueList != NULL && tagValueList->
nbPairs != 0) {
3347 memcpy(&localContentsList[offset].content.tagValueList,
3361 genericContext.genericContents.nbContents = offset;
3364 uint8_t nbPages = getNbPagesForGenericContents(&genericContext.genericContents, 0,
false);
3366 prepareNavInfo(
true, nbPages, getRejectReviewText(
TYPE_OPERATION));
3368 displayGenericContextPage(0,
true);
3390 const char *reviewTitle,
3391 const char *reviewSubTitle,
3392 const char *finishTitle,
3395 useCaseReview(operationType,
3427 const char *reviewTitle,
3428 const char *reviewSubTitle,
3429 const char *finishTitle,
3433 useCaseReview(operationType,
3467 const char *reviewTitle,
3468 const char *reviewSubTitle,
3469 const char *finishTitle,
3480 &blindSigningWarning,
3509 const char *reviewTitle,
3510 const char *reviewSubTitle,
3511 const char *finishTitle,
3516 memset(&reviewWithWarnCtx, 0,
sizeof(reviewWithWarnCtx));
3517 reviewWithWarnCtx.isStreaming =
false;
3518 reviewWithWarnCtx.operationType = operationType | RISKY_OPERATION;
3519 reviewWithWarnCtx.tagValueList = tagValueList;
3520 reviewWithWarnCtx.icon = icon;
3521 reviewWithWarnCtx.reviewTitle = reviewTitle;
3522 reviewWithWarnCtx.reviewSubTitle = reviewSubTitle;
3523 reviewWithWarnCtx.finishTitle = finishTitle;
3524 reviewWithWarnCtx.tipBox = tipBox;
3525 reviewWithWarnCtx.warning = warning;
3526 reviewWithWarnCtx.choiceCallback = choiceCallback;
3528 displayInitialWarning();
3550 const char *reviewTitle,
3551 const char *reviewSubTitle,
3552 const char *finishTitle,
3555 useCaseReview(operationType,
3576 const char *rejectText,
3580 memset(&genericContext, 0,
sizeof(genericContext));
3583 onQuit = rejectCallback;
3584 navType = GENERIC_NAV;
3591 uint8_t nbPages = getNbPagesForGenericContents(&genericContext.genericContents, 0,
false);
3592 prepareNavInfo(
true, nbPages, rejectText);
3595#ifdef HAVE_PIEZO_SOUND
3597 io_seproxyhal_play_tune(TUNE_LOOK_AT_ME);
3600 displayGenericContextPage(0,
true);
3617 const char *reviewTitle,
3618 const char *reviewSubTitle,
3621 useCaseReviewStreamingStart(
3622 operationType, icon, reviewTitle, reviewSubTitle, choiceCallback,
true);
3640 const char *reviewTitle,
3641 const char *reviewSubTitle,
3645 operationType, icon, reviewTitle, reviewSubTitle, &blindSigningWarning, choiceCallback);
3665 const char *reviewTitle,
3666 const char *reviewSubTitle,
3670 memset(&reviewWithWarnCtx, 0,
sizeof(reviewWithWarnCtx));
3672 reviewWithWarnCtx.isStreaming =
true;
3673 reviewWithWarnCtx.operationType = operationType | RISKY_OPERATION;
3674 reviewWithWarnCtx.icon = icon;
3675 reviewWithWarnCtx.reviewTitle = reviewTitle;
3676 reviewWithWarnCtx.reviewSubTitle = reviewSubTitle;
3677 reviewWithWarnCtx.choiceCallback = choiceCallback;
3678 reviewWithWarnCtx.warning = warning;
3680 displayInitialWarning();
3701 memset(&genericContext, 0,
sizeof(genericContext));
3703 bundleNavContext.reviewStreaming.choiceCallback = choiceCallback;
3704 bundleNavContext.reviewStreaming.skipCallback = skipCallback;
3707 onChoice = bundleNavReviewStreamingChoice;
3708 navType = STREAMING_NAV;
3711 genericContext.genericContents.contentsList = localContentsList;
3712 genericContext.genericContents.nbContents = 1;
3721 bundleNavContext.reviewStreaming.stepPageNb = getNbPagesForGenericContents(
3722 &genericContext.genericContents,
3725 prepareNavInfo(
true,
3727 getRejectReviewText(bundleNavContext.reviewStreaming.operationType));
3735 displayGenericContextPage(0,
true);
3766 memset(&genericContext, 0,
sizeof(genericContext));
3768 bundleNavContext.reviewStreaming.choiceCallback = choiceCallback;
3771 onChoice = bundleNavReviewStreamingChoice;
3772 navType = STREAMING_NAV;
3775 genericContext.genericContents.contentsList = localContentsList;
3776 genericContext.genericContents.nbContents = 1;
3781 prepareReviewLastPage(&STARTING_CONTENT.content.infoLongPress,
3782 bundleNavContext.reviewStreaming.icon,
3786 bundleNavContext.reviewStreaming.stepPageNb = getNbPagesForGenericContents(
3787 &genericContext.genericContents,
3790 prepareNavInfo(
true, 1, getRejectReviewText(bundleNavContext.reviewStreaming.operationType));
3792 displayGenericContextPage(0,
true);
3804 memset(&genericContext, 0,
sizeof(genericContext));
3805 memset(&addressConfirmationContext, 0,
sizeof(addressConfirmationContext));
3808 onChoice = callback;
3809 navType = GENERIC_NAV;
3812 genericContext.genericContents.contentsList = localContentsList;
3813 genericContext.genericContents.nbContents = (tagValueList == NULL) ? 1 : 2;
3815 prepareAddressConfirmationPages(
3816 address, tagValueList, &STARTING_CONTENT, &localContentsList[1]);
3819 uint8_t nbPages = getNbPagesForGenericContents(&genericContext.genericContents, 0,
false);
3821 prepareNavInfo(
true, nbPages,
"Cancel");
3823#ifdef HAVE_PIEZO_SOUND
3825 io_seproxyhal_play_tune(TUNE_LOOK_AT_ME);
3828 displayGenericContextPage(0,
true);
3850 const char *reviewTitle,
3851 const char *reviewSubTitle,
3855 memset(&genericContext, 0,
sizeof(genericContext));
3857 if (addressConfirmationContext.modalLayout) {
3860 memset(&addressConfirmationContext, 0,
sizeof(addressConfirmationContext));
3863 onChoice = choiceCallback;
3864 navType = GENERIC_NAV;
3868 genericContext.genericContents.contentsList = localContentsList;
3869 genericContext.genericContents.nbContents = (additionalTagValueList == NULL) ? 2 : 3;
3874 prepareReviewFirstPage(
3875 &STARTING_CONTENT.content.extendedCenter.contentCenter, icon, reviewTitle, reviewSubTitle);
3876 STARTING_CONTENT.content.extendedCenter.contentCenter.subText =
"Swipe to continue";
3879 prepareAddressConfirmationPages(
3880 address, additionalTagValueList, &localContentsList[1], &localContentsList[2]);
3883 uint8_t nbPages = getNbPagesForGenericContents(&genericContext.genericContents, 0,
false);
3885 prepareNavInfo(
true, nbPages,
"Cancel");
3887#ifdef HAVE_PIEZO_SOUND
3889 io_seproxyhal_play_tune(TUNE_LOOK_AT_ME);
3892 displayGenericContextPage(0,
true);
3906 if (genericContext.type != USE_CASE_SPINNER) {
3907 memset(&genericContext, 0,
sizeof(genericContext));
3908 genericContext.type = USE_CASE_SPINNER;
3913 genericContext.backgroundLayout =
nbgl_layoutGet(&layoutDescription);
3916 genericContext.backgroundLayout, text, NULL, genericContext.spinnerPosition);
3923 genericContext.spinnerPosition++;
3926 genericContext.spinnerPosition = 0;
3929 genericContext.backgroundLayout, text, NULL, genericContext.spinnerPosition);
3933 else if (ret == 2) {
3964 tune_index_e tuneId,
3968 keypadGenericUseCase(title,
3975 validatePinCallback,
4002 tune_index_e tuneId,
4006 keypadGenericUseCase(title,
4013 validatePinCallback,
nbgl_contentTagValue_t *(* nbgl_contentTagValueCallback_t)(uint8_t pairIndex)
prototype of tag/value pair retrieval callback
@ ICON_ILLUSTRATION
simple icon
@ LARGE_CASE_INFO
text in BLACK and large case (INTER 32px), subText in black in Inter24px
@ INFO_LONG_PRESS
a centered info and a long press button
@ EXTENDED_CENTER
a centered content and a possible tip-box
@ CHOICES_LIST
list of choices through radio buttons
@ CENTERED_INFO
a centered info
@ SWITCHES_LIST
list of switches with descriptions
@ TAG_VALUE_DETAILS
a tag/value pair and a small button to get details.
@ INFOS_LIST
list of infos with titles
@ TAG_VALUE_CONFIRM
tag/value pairs and a black button/footer to confirm/cancel.
@ TAG_VALUE_LIST
list of tag/value pairs
@ BARS_LIST
list of touchable bars (with > on the right to go to sub-pages)
@ INFO_BUTTON
a centered info and a simple black button
@ ENS_ALIAS
alias comes from ENS
@ ADDRESS_BOOK_ALIAS
alias comes from Address Book
@ QR_CODE_ALIAS
alias is an address to be displayed as a QR Code
void(* nbgl_contentActionCallback_t)(int token, uint8_t index, int page)
prototype of function to be called when an action on a content object occurs
#define LOG_DEBUG(__logger,...)
bool nbgl_getTextMaxLenInNbLines(nbgl_font_id_e fontId, const char *text, uint16_t maxWidth, uint16_t maxNbLines, uint16_t *len, bool wrapping)
compute the len of the given text (in bytes) fitting in the given maximum nb lines,...
void nbgl_textReduceOnNbLines(nbgl_font_id_e fontId, const char *origText, uint16_t maxWidth, uint8_t nbLines, char *reducedText, uint16_t reducedTextLen)
Create a reduced version of given ASCII text to wrap it on the given max width (in pixels),...
uint16_t nbgl_getTextHeightInWidth(nbgl_font_id_e fontId, const char *text, uint16_t maxWidth, bool wrapping)
return the height of the given multiline text, with the given font.
uint16_t nbgl_getTextNbLinesInWidth(nbgl_font_id_e fontId, const char *text, uint16_t maxWidth, bool wrapping)
compute the number of lines of the given text fitting in the given maxWidth
void(* nbgl_layoutTouchCallback_t)(int token, uint8_t index)
prototype of function to be called when an object is touched
int nbgl_layoutAddContentCenter(nbgl_layout_t *layout, const nbgl_contentCenter_t *info)
Creates an area on the center of the main panel, with a possible icon, and possible texts under it.
int nbgl_layoutAddTextContent(nbgl_layout_t *layout, const char *title, const char *description, const char *info)
Creates in the main container three text areas:
int nbgl_layoutUpdateKeypad(nbgl_layout_t *layout, uint8_t index, bool enableValidate, bool enableBackspace, bool enableDigits)
Updates an existing keypad on bottom of the screen, with the given configuration.
int nbgl_layoutAddSeparationLine(nbgl_layout_t *layout)
adds a separation line on bottom of the last added item
int nbgl_layoutAddQRCode(nbgl_layout_t *layout, const nbgl_layoutQRCode_t *info)
Creates an area on the center of the main panel, with a QRCode, a possible text in black (bold) under...
int nbgl_layoutDraw(nbgl_layout_t *layout)
Applies given layout. The screen will be redrawn.
int nbgl_layoutAddTouchableBar(nbgl_layout_t *layout, const nbgl_layoutBar_t *barLayout)
Creates a touchable bar in main panel.
@ WHITE_BACKGROUND
rounded bordered button, with text/icon in black, on white background
@ BLACK_BACKGROUND
rounded bordered button, with text/icon in white, on black background
int nbgl_layoutAddTopRightButton(nbgl_layout_t *layout, const nbgl_icon_details_t *icon, uint8_t token, tune_index_e tuneId)
Creates a Top-right button in the top right corner of the top panel.
void * nbgl_layout_t
type shared externally
@ HEADER_EMPTY
empty space, to have a better vertical centering of centered info
@ HEADER_BACK_AND_TEXT
back key and optional text
int nbgl_layoutAddKeypadContent(nbgl_layout_t *layout, const char *title, bool hidden, uint8_t nbDigits, const char *text)
Adds an area with a title and a placeholder for hidden digits on top of a keypad, to represent the en...
int nbgl_layoutUpdateKeypadContent(nbgl_layout_t *layout, bool hidden, uint8_t nbActiveDigits, const char *text)
Updates an existing set of hidden digits, with the given configuration.
nbgl_layout_t * nbgl_layoutGet(const nbgl_layoutDescription_t *description)
returns a layout of the given type. The layout is reset
int nbgl_layoutAddExtendedFooter(nbgl_layout_t *layout, const nbgl_layoutFooter_t *footerDesc)
Creates a touchable area at the footer of the screen, containing various controls,...
@ ROUNDED_AND_FOOTER_STYLE
A black background button on top of a footer.
int nbgl_layoutAddChoiceButtons(nbgl_layout_t *layout, const nbgl_layoutChoiceButtons_t *info)
Creates two buttons to make a choice. Both buttons are mandatory. Both buttons are full width,...
int nbgl_layoutAddSpinner(nbgl_layout_t *layout, const char *text, const char *subText, uint8_t initPosition)
Creates a centered (vertically & horizontally) spinner with a text under it.
int nbgl_layoutUpdateSpinner(nbgl_layout_t *layout, const char *text, const char *subText, uint8_t position)
Update an existing spinner (must be the only object of the layout)
#define NBGL_NO_PROGRESS_INDICATOR
To be used when a control token shall not be used.
int nbgl_layoutAddHeader(nbgl_layout_t *layout, const nbgl_layoutHeader_t *headerDesc)
Creates a touchable (or not) area at the header of the screen, containing various controls,...
@ FOOTER_EMPTY
empty space, to have a better vertical centering of centered info
int nbgl_layoutRelease(nbgl_layout_t *layout)
Release the layout obtained with nbgl_layoutGet()
int nbgl_layoutAddFooter(nbgl_layout_t *layout, const char *text, uint8_t token, tune_index_e tuneId)
Creates a touchable text at the footer of the screen, separated with a thin line from the rest of the...
int nbgl_layoutAddKeypad(nbgl_layout_t *layout, keyboardCallback_t callback, bool shuffled)
Adds a keypad on bottom of the screen, with the associated callback.
#define NB_SPINNER_POSITIONS
void nbgl_refresh(void)
This functions refreshes the actual screen on display with what has changed since the last refresh.
#define KEYPAD_MAX_DIGITS
void nbgl_refreshSpecial(nbgl_refresh_mode_t mode)
This functions refreshes the actual screen on display with what has changed since the last refresh,...
void nbgl_refreshSpecialWithPostRefresh(nbgl_refresh_mode_t mode, nbgl_post_refresh_t post_refresh)
nbgl_page_t * nbgl_pageDrawGenericContent(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_pageNavigationInfo_t *nav, nbgl_pageContent_t *content)
draw a generic content page, with the given content, and if nav parameter is not NULL,...
nbgl_page_t * nbgl_pageDrawInfo(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_screenTickerConfiguration_t *ticker, const nbgl_pageInfoDescription_t *info)
draw a page with a centered info (icon and/or texts) with a touchable footer, in a potential "tapable...
void * nbgl_page_t
type shared externally
@ NAV_WITH_BUTTONS
move forward and backward with buttons in bottom nav bar
nbgl_page_t * nbgl_pageDrawLedgerInfo(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_screenTickerConfiguration_t *ticker, const char *text, int tapActionToken)
draw a page with a centered text in large case, with a round check icon
nbgl_page_t * nbgl_pageDrawConfirmation(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_pageConfirmationDescription_t *info)
draw a confirmation page, with a centered info (icon and/or text), a button to confirm and a footer t...
int nbgl_pageRelease(nbgl_page_t *)
Release the page obtained with any of the nbgl_pageDrawXXX() functions.
nbgl_page_t * nbgl_pageDrawGenericContentExt(nbgl_layoutTouchCallback_t onActionCallback, const nbgl_pageNavigationInfo_t *nav, nbgl_pageContent_t *content, bool modal)
draw a generic content page, with the given content, and if nav parameter is not NULL,...
@ QUIT_APP_TEXT
A full width button with "Quit app" text (only for bottom button)
@ INFO_ICON
info (i) icon in the button.
@ NO_BUTTON_STYLE
no button.
@ SETTINGS_ICON
settings (wheel) icon in the button.
struct PACKED__ nbgl_screenTickerConfiguration_s nbgl_screenTickerConfiguration_t
struct to configure a screen layer
void nbgl_screenRedraw(void)
This function redraws the whole screen on top of stack and its children.
@ POST_REFRESH_FORCE_POWER_ON
Force screen power on after refresh.
struct PACKED__ nbgl_icon_details_s nbgl_icon_details_t
Represents all information about an icon.
nbgl_refresh_mode_t
different modes of refresh for nbgl_refreshSpecial()
@ FULL_COLOR_CLEAN_REFRESH
to be used for lock screen display (cleaner but longer refresh)
@ BLACK_AND_WHITE_FAST_REFRESH
to be used for pure B&W area, when contrast is not priority
@ FULL_COLOR_PARTIAL_REFRESH
to be used for small partial refresh (radio buttons, switches)
@ FULL_COLOR_REFRESH
to be used for normal refresh
API of the Advanced BOLOS Graphical Library, for typical application use-cases.
DEPRECATED void nbgl_useCaseHome(const char *appName, const nbgl_icon_details_t *appIcon, const char *tagline, bool withSettings, nbgl_callback_t topRightCallback, nbgl_callback_t quitCallback)
DEPRECATED void nbgl_useCaseSettings(const char *settingsTitle, uint8_t initPage, uint8_t nbPages, bool touchableTitle, nbgl_callback_t quitCallback, nbgl_navCallback_t navCallback, nbgl_layoutTouchCallback_t controlsCallback)
uint8_t nbgl_useCaseGetNbTagValuesInPageExt(uint8_t nbPairs, const nbgl_contentTagValueList_t *tagValueList, uint8_t startIndex, bool isSkippable, bool *requireSpecificDisplay)
void(* nbgl_callback_t)(void)
prototype of generic callback function
#define SKIPPABLE_OPERATION
This is to use in nbgl_operationType_t when the operation is skippable. This is used.
void nbgl_useCaseGenericSettings(const char *appName, uint8_t initPage, const nbgl_genericContents_t *settingContents, const nbgl_contentInfoList_t *infosList, nbgl_callback_t quitCallback)
void nbgl_useCaseKeypadPIN(const char *title, uint8_t minDigits, uint8_t maxDigits, uint8_t backToken, bool shuffled, tune_index_e tuneId, nbgl_pinValidCallback_t validatePinCallback, nbgl_layoutTouchCallback_t actionCallback)
uint32_t nbgl_operationType_t
This mask is used to describe the type of operation to review with additional options It is a mask of...
void nbgl_useCaseReviewStreamingWithWarningStart(nbgl_operationType_t operationType, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const nbgl_warning_t *warning, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseReview(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, nbgl_choiceCallback_t choiceCallback)
uint8_t nbgl_useCaseGetNbTagValuesInPage(uint8_t nbPairs, const nbgl_contentTagValueList_t *tagValueList, uint8_t startIndex, bool *requireSpecificDisplay)
uint8_t nbgl_useCaseGetNbPagesForTagValueList(const nbgl_contentTagValueList_t *tagValueList)
DEPRECATED void nbgl_useCaseRegularReview(uint8_t initPage, uint8_t nbPages, const char *rejectText, nbgl_layoutTouchCallback_t buttonCallback, nbgl_navCallback_t navCallback, nbgl_choiceCallback_t choiceCallback)
void(* nbgl_pinValidCallback_t)(const uint8_t *pin, uint8_t pinLen)
prototype of pin validation callback function
void nbgl_useCaseReviewStreamingStart(nbgl_operationType_t operationType, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseHomeAndSettings(const char *appName, const nbgl_icon_details_t *appIcon, const char *tagline, const uint8_t initSettingPage, const nbgl_genericContents_t *settingContents, const nbgl_contentInfoList_t *infosList, const nbgl_homeAction_t *action, nbgl_callback_t quitCallback)
void nbgl_useCaseStaticReviewLight(const nbgl_contentTagValueList_t *tagValueList, const nbgl_pageInfoLongPress_t *infoLongPress, const char *rejectText, nbgl_choiceCallback_t callback)
uint8_t nbgl_useCaseGetNbInfosInPage(uint8_t nbInfos, const nbgl_contentInfoList_t *infosList, uint8_t startIndex, bool withNav)
void(* nbgl_choiceCallback_t)(bool confirm)
prototype of choice callback function
uint8_t nbgl_useCaseGetNbBarsInPage(uint8_t nbBars, const nbgl_contentBarsList_t *barsList, uint8_t startIndex, bool withNav)
void nbgl_useCaseNavigableContent(const char *title, uint8_t initPage, uint8_t nbPages, nbgl_callback_t quitCallback, nbgl_navCallback_t navCallback, nbgl_layoutTouchCallback_t controlsCallback)
#define INFOS_AREA_HEIGHT
height available for infos pairs display
@ STRONG_HOME_ACTION
Black button, implicating the main action of the App.
void nbgl_useCaseReviewStreamingFinish(const char *finishTitle, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseReviewWithWarning(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, const nbgl_tipBox_t *tipBox, const nbgl_warning_t *warning, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseSpinner(const char *text)
void nbgl_useCaseConfirm(const char *message, const char *subMessage, const char *confirmText, const char *rejectText, nbgl_callback_t callback)
void nbgl_useCaseReviewStart(const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *rejectText, nbgl_callback_t continueCallback, nbgl_callback_t rejectCallback)
DEPRECATED void nbgl_useCaseHomeExt(const char *appName, const nbgl_icon_details_t *appIcon, const char *tagline, bool withSettings, const char *actionButtonText, nbgl_callback_t actionCallback, nbgl_callback_t topRightCallback, nbgl_callback_t quitCallback)
void nbgl_useCaseKeypadDigits(const char *title, uint8_t minDigits, uint8_t maxDigits, uint8_t backToken, bool shuffled, tune_index_e tuneId, nbgl_pinValidCallback_t validatePinCallback, nbgl_layoutTouchCallback_t actionCallback)
#define APP_DESCRIPTION_MAX_LEN
Length of buffer used for the default Home tagline.
void nbgl_useCaseStatus(const char *message, bool isSuccess, nbgl_callback_t quitCallback)
@ W3C_THREAT_DETECTED_WARN
Web3 Checks: Thread detexted, malicious (know drainer)
@ W3C_ISSUE_WARN
Web3 Checks issue.
@ BLIND_SIGNING_WARN
Blind signing.
@ W3C_LOSING_SWAP_WARN
Web3 Checks: Losing Swap risk.
DEPRECATED void nbgl_useCaseAddressConfirmationExt(const char *address, nbgl_choiceCallback_t callback, const nbgl_contentTagValueList_t *tagValueList)
void nbgl_useCaseGenericConfiguration(const char *title, uint8_t initPage, const nbgl_genericContents_t *contents, nbgl_callback_t quitCallback)
#define INIT_HOME_PAGE
Value to pass to nbgl_useCaseHomeAndSettings() initSettingPage parameter to initialize the use case o...
void nbgl_useCaseReviewStreamingContinueExt(const nbgl_contentTagValueList_t *tagValueList, nbgl_choiceCallback_t choiceCallback, nbgl_callback_t skipCallback)
void nbgl_useCaseReviewBlindSigning(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, const nbgl_tipBox_t *tipBox, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseChoice(const nbgl_icon_details_t *icon, const char *message, const char *subMessage, const char *confirmText, const char *rejectString, nbgl_choiceCallback_t callback)
#define TAG_VALUE_AREA_HEIGHT
height available for tag/value pairs display
#define BLIND_OPERATION
This is to use in nbgl_operationType_t when the operation is "blind" This is used to indicate a warni...
#define TAGLINE_PART1
Default strings used in the Home tagline.
void nbgl_useCaseGenericReview(const nbgl_genericContents_t *contents, const char *rejectText, nbgl_callback_t rejectCallback)
void nbgl_useCaseStaticReview(const nbgl_contentTagValueList_t *tagValueList, const nbgl_pageInfoLongPress_t *infoLongPress, const char *rejectText, nbgl_choiceCallback_t callback)
void nbgl_useCaseReviewStreamingBlindSigningStart(nbgl_operationType_t operationType, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseAdvancedReview(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, const nbgl_tipBox_t *tipBox, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseReviewStreamingContinue(const nbgl_contentTagValueList_t *tagValueList, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseReviewLight(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, nbgl_choiceCallback_t choiceCallback)
uint8_t nbgl_useCaseGetNbChoicesInPage(uint8_t nbChoices, const nbgl_contentRadioChoice_t *choicesList, uint8_t startIndex, bool withNav)
void nbgl_useCaseReviewStatus(nbgl_reviewStatusType_t reviewStatusType, nbgl_callback_t quitCallback)
#define LAST_PAGE_FOR_REVIEW
value of page parameter used with navigation callback when "skip" button is touched,...
@ CENTERED_INFO_WARNING
Centered info.
@ BAR_LIST_WARNING
list of touchable bars, to display sub-pages
nbgl_reviewStatusType_t
The different types of review status.
@ STATUS_TYPE_TRANSACTION_REJECTED
@ STATUS_TYPE_ADDRESS_REJECTED
@ STATUS_TYPE_TRANSACTION_SIGNED
@ STATUS_TYPE_OPERATION_REJECTED
@ STATUS_TYPE_OPERATION_SIGNED
@ STATUS_TYPE_ADDRESS_VERIFIED
@ STATUS_TYPE_MESSAGE_SIGNED
@ STATUS_TYPE_MESSAGE_REJECTED
bool(* nbgl_navCallback_t)(uint8_t page, nbgl_pageContent_t *content)
prototype of navigation callback function
#define MAX_APP_NAME_FOR_SDK_TAGLINE
Max supported length of appName used for the default Home tagline.
void nbgl_useCaseAddressReview(const char *address, const nbgl_contentTagValueList_t *additionalTagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, nbgl_choiceCallback_t choiceCallback)
@ TYPE_TRANSACTION
For operations transferring a coin or taken from an account to another.
@ TYPE_OPERATION
For other types of operation (generic type)
uint8_t nbgl_useCaseGetNbSwitchesInPage(uint8_t nbSwitches, const nbgl_contentSwitchesList_t *switchesList, uint8_t startIndex, bool withNav)
This structure contains data to build a BARS_LIST content.
const uint8_t * tokens
array of tokens, one for each bar (nbBars items)
const char *const * barTexts
array of texts for each bar (nbBars items, in black/bold)
uint8_t nbBars
number of elements in barTexts and tokens array
This structure contains info to build a centered (vertically and horizontally) area,...
uint16_t iconHug
vertical margin to apply on top and bottom of the icon
const nbgl_icon_details_t * icon
the icon (can be null)
const char * title
title in black large (can be null)
const char * description
description in black small regular case (can be null)
const char * subText
sub-text in dark gray regular small case
bool padding
if true, apply a padding of 40px at the bottom
const char * smallTitle
sub-title in black small bold case (can be null)
nbgl_contentIllustrationType_t illustrType
const char * text2
second text (can be null)
const char * text1
first text (can be null)
nbgl_contentCenteredInfoStyle_t style
style to apply to this info
int16_t offsetY
vertical shift to apply to this info (if >0, shift to bottom)
const char * text3
third text (can be null)
const nbgl_icon_details_t * icon
a buffer containing the 1BPP icon
nbgl_contentCenter_t contentCenter
centered content (icon + text(s))
This structure contains data to build a centered info + simple black button content.
const char * buttonText
text of the long press button
const nbgl_icon_details_t * icon
a buffer containing the 1BPP icon
const char * text
centered text in large case
This structure contains data to build a INFOS_LIST content.
uint8_t nbInfos
number of elements in infoTypes and infoContents array
const char *const * infoContents
array of contents of infos (in black)
const char *const * infoTypes
array of types of infos (in black/bold)
const nbgl_contentValueExt_t * infoExtensions
This structure contains data to build a centered info + long press button content.
const char * longPressText
text of the long press button
const nbgl_icon_details_t * icon
a buffer containing the 1BPP icon
const char * text
centered text in large case
This structure contains a list of names to build a list of radio buttons (on the right part of screen...
uint8_t initChoice
index of the current choice
const char *const * names
array of strings giving the choices (nbChoices)
uint8_t nbChoices
number of choices
This structure contains info to build a switch (on the right) with a description (on the left),...
This structure contains [item,value] pair(s) and info about a potential "details" button,...
const char * confirmationText
text of the confirmation button, if NULL "It matches" is used
uint8_t detailsButtonToken
uint8_t confirmationToken
the token used as argument of the onActionCallback
nbgl_contentTagValueList_t tagValueList
list of tag/value pairs
const char * detailsButtonText
this text is used for "details" button (if NULL, no button)
const nbgl_icon_details_t * detailsButtonIcon
icon to use in details button
const nbgl_icon_details_t * detailsButtonIcon
icon to use in details button
uint8_t detailsButtonToken
const char * detailsButtonText
this text is used for "details" button
nbgl_contentTagValueList_t tagValueList
list of tag/value pairs
This structure contains a list of [tag,value] pairs.
nbgl_contentActionCallback_t actionCallback
called when a valueIcon is touched on a given pair
const nbgl_contentTagValue_t * pairs
array of [tag,value] pairs (nbPairs items). If NULL, callback is used instead
bool wrapping
if set to true, value text will be wrapped on ' ' to avoid cutting words
uint8_t startIndex
index of the first pair to get with callback
nbgl_contentTagValueCallback_t callback
function to call to retrieve a given pair
uint8_t nbMaxLinesForValue
This structure contains a [tag,value] pair.
const nbgl_contentValueExt_t * extension
if not NULL, gives additional info on value field
const nbgl_icon_details_t * valueIcon
int8_t centeredInfo
if set to 1, the tag will be displayed as a centered info
const char * value
string giving the value name
const char * item
string giving the tag name
This structure contains additions to a tag/value pair, to be able to build a screen to display these ...
const char * fullValue
full string of the value when used as an alias
nbgl_contentValueAliasType_t aliasType
type of alias
This structure contains data to build a content.
nbgl_contentActionCallback_t contentActionCallback
callback to be called when an action on an object occurs
nbgl_contentType_t type
type of page content in the content union
uint8_t nbContents
number of contents
const nbgl_content_t * contentsList
array of nbgl_content_t (nbContents items).
nbgl_contentCallback_t contentGetterCallback
function to call to retrieve a given content
Structure describing the action button in Home Screen.
const nbgl_icon_details_t * icon
icon to use in action button in Home page
nbgl_callback_t callback
function to call when action button is touched in Home page
const char * text
text to use in action button in Home page
nbgl_homeActionStyle_t style
style of action button
This structure contains info to build a clickable "bar" with a text and an icon.
bool inactive
if set to true, the bar is grayed-out and cannot be touched
const char * text
text (can be NULL)
uint8_t token
the token that will be used as argument of the callback
bool large
set to true only for the main level of OS settings
const char * subText
sub text (can be NULL)
const nbgl_icon_details_t * iconLeft
a buffer containing the 1BPP icon for icon on left (can be NULL)
const nbgl_icon_details_t * iconRight
Structure containing all information when creating a layout. This structure must be passed as argumen...
nbgl_screenTickerConfiguration_t ticker
const char * tapActionText
Light gray text used when main container is "tapable".
nbgl_layoutTouchCallback_t onActionCallback
the callback to be called on any action on the layout
This structure contains info to build a centered (vertically and horizontally) area,...
const char * text2
second text (can be null)
const char * url
URL for QR code.
Structure containing all specific information when creating a confirmation page.
const char * cancelText
the text used for cancel action, if NULL a simple X button is used
tune_index_e tuneId
if not NBGL_NO_TUNE, a tune will be played when button is pressed
This structure contains data to build a page in multi-pages mode (nbgl_pageDrawGenericContent)
nbgl_contentTagValueDetails_t tagValueDetails
TAG_VALUE_DETAILS type
const char * title
text for the title of the page (if NULL, no title)
uint8_t topRightToken
token used when top-right button (if not NULL) is touched
nbgl_contentInfoLongPress_t infoLongPress
INFO_LONG_PRESS type
nbgl_contentRadioChoice_t choicesList
CHOICES_LIST type
nbgl_contentSwitchesList_t switchesList
SWITCHES_LIST type
tune_index_e tuneId
if not NBGL_NO_TUNE, a tune will be played when title is touched
nbgl_contentBarsList_t barsList
BARS_LIST type
nbgl_contentInfoButton_t infoButton
INFO_BUTTON type
nbgl_contentInfoList_t infosList
INFOS_LIST type
nbgl_contentTagValueList_t tagValueList
TAG_VALUE_LIST type
const nbgl_icon_details_t * topRightIcon
nbgl_contentType_t type
type of page content in the following union
nbgl_contentCenteredInfo_t centeredInfo
CENTERED_INFO type
nbgl_contentTagValueConfirm_t tagValueConfirm
TAG_VALUE_CONFIRM type
bool isTouchableTitle
if set to true, the title is preceded by <- arrow to go back
nbgl_contentExtendedCenter_t extendedCenter
EXTENDED_CENTER type
Structure containing all specific information when creating an information page.
nbgl_layoutButtonStyle_t actionButtonStyle
style of "action" button
const char * actionButtonText
if not NULL an "action" button is set under the centered info
uint8_t bottomButtonsToken
const nbgl_icon_details_t * actionButtonIcon
potential icon of "action" button
nbgl_pageButtonStyle_t bottomButtonStyle
style to apply to the Bottom button
nbgl_layoutCenteredInfo_t centeredInfo
description of the centered info to be used
Structure containing all specific information when creating a multi-screens page.
uint8_t nbPages
the number of pages to display (if <2, no navigation bar)
uint8_t quitToken
the token used as argument of the actionCallback when the footer is touched
uint8_t skipToken
if skipText is NULL the token used when right part of footer is touched
nbgl_pageNavigationType_t navType
uint8_t activePage
the index of the page to display at start-up
bool progressIndicator
if set to true, display a progress indicator on top of the page
nbgl_pageNavWithButtons_t navWithButtons
structure used when navigation with buttons
tune_index_e tuneId
if not NBGL_NO_TUNE, a tune will be played when next or back is pressed
bool visiblePageIndicator
if set to true, the page indicator will be visible in navigation
const char * quitText
the text displayed in footer (on the left), used to quit (only on Flex)
bool backButton
if set to true, a back button (<-) is displayed in the nav bar
This structure contains data to build a SWITCHES_LIST content.
uint8_t nbSwitches
number of elements in switches and tokens array
const nbgl_contentSwitch_t * switches
array of switches (nbSwitches items)
The necessary parameters to build a tip-box in first review page and the modal if this tip box is tou...
const char * modalTitle
title given to modal window displayed when tip-box is touched
nbgl_contentInfoList_t infos
infos pairs displayed in modal.
const char * text
text of the tip-box
nbgl_contentType_t type
type of page content in the following union
const nbgl_icon_details_t * icon
icon of the tip-box
const char *const * texts
array of texts for each bar (nbBars items, in black/bold)
const struct nbgl_warningDetails_s * details
array of nbBars structures giving what to display when each bar is touched.
const char *const * subTexts
array of texts for each bar (nbBars items, in black)
uint8_t nbBars
number of touchable bars
const nbgl_icon_details_t ** icons
array of icons for each bar (nbBars items)
The necessary parameters to build the page(s) displayed when the top-right button is touched in intro...
nbgl_warningDetailsType_t type
type of content in the page, determining what to use in the following union
nbgl_contentCenter_t centeredInfo
centered info, if type == CENTERED_INFO_WARNING
const char * title
text of the page (used to go back)
nbgl_layoutQRCode_t qrCode
QR code, if type == QRCODE_WARNING.
nbgl_warningBarList_t barList
touchable bars list, if type == BAR_LIST_WARNING
The necessary parameters to build a warning page preceding a review. One can either use predefinedSet...
Union of the different type of contents.
nbgl_contentInfoList_t infosList
INFOS_LIST type
nbgl_contentInfoLongPress_t infoLongPress
INFO_LONG_PRESS type
nbgl_contentTagValueConfirm_t tagValueConfirm
TAG_VALUE_CONFIRM type
nbgl_contentTagValueList_t tagValueList
TAG_VALUE_LIST type
nbgl_contentCenteredInfo_t centeredInfo
CENTERED_INFO type
nbgl_contentBarsList_t barsList
BARS_LIST type
nbgl_contentExtendedCenter_t extendedCenter
EXTENDED_CENTER type
nbgl_contentSwitchesList_t switchesList
SWITCHES_LIST type
nbgl_contentInfoButton_t infoButton
INFO_BUTTON type
nbgl_contentRadioChoice_t choicesList
CHOICES_LIST type