Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature - Adding support to Flex device #22

Merged
merged 20 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ include $(BOLOS_SDK)/Makefile.defines
APP_LOAD_PARAMS= --curve secp256k1 $(COMMON_LOAD_PARAMS)

APPVERSION_M=1
APPVERSION_N=2
APPVERSION_P=3
APPVERSION_N=3
APPVERSION_P=1
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)

# Celo
Expand All @@ -34,16 +34,18 @@ APP_LOAD_PARAMS += --path "44'/60'/0'/0/0" --path "44'/60'/0'" --path "44'/60'/0

APPNAME = "Celo"
APP_LOAD_FLAGS=--appFlags 0
ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX))
ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX TARGET_FLEX))
APP_LOAD_FLAGS=--appFlags 0x200 # APPLICATION_FLAG_BOLOS_SETTINGS
endif
APP_LOAD_PARAMS += $(APP_LOAD_FLAGS)

#prepare hsm generation
ifeq ($(TARGET_NAME), TARGET_NANOS)
ICONNAME=nanos_app_celo.gif
else ifeq ($(TARGET_NAME),TARGET_STAX)
else ifeq ($(TARGET_NAME), TARGET_STAX)
ICONNAME=stax_app_celo.gif
else ifeq ($(TARGET_NAME), TARGET_FLEX)
ICONNAME=flex_app_celo.gif
else
ICONNAME=nanox_app_celo.gif
endif
Expand Down Expand Up @@ -75,7 +77,7 @@ DEFINES += APPVERSION=\"$(APPVERSION)\"

DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL=""

ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX))
ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX TARGET_FLEX))
DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000
DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE
endif
Expand All @@ -86,7 +88,7 @@ else
DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300
endif

ifeq ($(TARGET_NAME),TARGET_STAX)
ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_FLEX TARGET_STAX))
DEFINES += NBGL_QRCODE
SDK_SOURCE_PATH += qrcode
else
Expand Down Expand Up @@ -152,11 +154,11 @@ include $(BOLOS_SDK)/Makefile.glyphs
APP_SOURCE_PATH += src_common src
SDK_SOURCE_PATH += lib_stusb lib_stusb_impl lib_u2f

ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX))
ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX TARGET_FLEX))
SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl
endif

ifneq ($(TARGET_NAME),TARGET_STAX)
ifneq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_FLEX TARGET_STAX))
SDK_SOURCE_PATH += lib_ux
endif

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Celo app for Ledger Wallet

This app adds support for the Celo native token for the Ledger Nano S/X/SP and Stax.
This app adds support for the Celo native token for the Ledger Nano S/X/SP/Stax and Flex.

## Quick start guide

Expand Down Expand Up @@ -80,6 +80,7 @@ You can choose which device to compile and load for by setting the `BOLOS_SDK` e
- `BOLOS_SDK=$NANOX_SDK`
- `BOLOS_SDK=$NANOSP_SDK`
- `BOLOS_SDK=$STAX_SDK`
- `BOLOS_SDK=$FLEX_SDK`

By default this variable is set to build/load for Nano S.

Expand Down Expand Up @@ -206,3 +207,4 @@ It outputs 3 artifacts:
- `compiled_app_binaries` within binary files of the build process for each device
- `code-coverage` within HTML details of code coverage
- `documentation` within HTML auto-generated documentation

Binary file added flex_app_celo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified glyphs/celo_64px.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion ledger_app.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[app]
build_directory = "./"
sdk = "C"
devices = ["nanos", "nanox", "nanos+", "stax"]
devices = ["nanos", "nanox", "nanos+", "stax", "flex"]

[tests]
unit_directory = "./tests/unit"
Expand Down
2 changes: 1 addition & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -849,7 +849,7 @@ __attribute__((section(".boot"))) int main(void) {

if (N_storage.initialized != 0x01) {
internalStorage_t storage;
storage.dataAllowed = 0x01;
storage.dataAllowed = 0x00;
storage.contractDetails = 0x00;
storage.initialized = 0x01;
nvm_write(&N_storage, (void*)&storage, sizeof(internalStorage_t));
Expand Down
25 changes: 8 additions & 17 deletions src/ui_confirm_selector_nbgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,44 +14,35 @@ static void approveCallback(void) {

static void confirmationCallback(bool confirm) {
if (confirm) {
nbgl_useCaseStatus("SELECTOR\nAPPROVED", true, ui_idle);
nbgl_useCaseReviewStatus(STATUS_TYPE_OPERATION_SIGNED, ui_idle);
approveCallback();
}
else {
nbgl_useCaseStatus("Selector rejected", false, ui_idle);
nbgl_useCaseReviewStatus(STATUS_TYPE_OPERATION_REJECTED, ui_idle);
rejectCallback();
}
}

static void continueCallback(void) {
tagValueList.pairs = tagValuePair;
tagValueList.smallCaseForValue = false;

infoLongPress.text = "Approve selector";
infoLongPress.icon = &C_celo_64px;
infoLongPress.longPressText = "Hold to sign";
infoLongPress.longPressToken = 0;
infoLongPress.tuneId = TUNE_TAP_CASUAL;

nbgl_useCaseStaticReview(&tagValueList, &infoLongPress, "Cancel", confirmationCallback);
}

void ui_confirm_selector_flow(void) {
tagValuePair[0].item = "Selector";
tagValuePair[0].value = (char*)strings.tmp.tmp;

tagValueList.nbMaxLinesForValue = 0;
tagValueList.nbPairs = 1;
tagValueList.pairs = tagValuePair;

nbgl_useCaseReviewStart(&C_celo_64px, "Verify selector", "", "Cancel", continueCallback, rejectCallback);
nbgl_useCaseReview(TYPE_TRANSACTION, &tagValueList, &C_celo_64px, "Verify selector", NULL, "Confirm selector", confirmationCallback);
}

void ui_confirm_parameter_flow(void) {
tagValuePair[0].item = "Parameter";
tagValuePair[0].value = (char*)strings.tmp.tmp;

tagValueList.nbMaxLinesForValue = 0;
tagValueList.nbPairs = 1;
tagValueList.pairs = tagValuePair;

nbgl_useCaseReviewStart(&C_celo_64px, "Verify", strings.tmp.tmp2, "Cancel", continueCallback, rejectCallback);
nbgl_useCaseReview(TYPE_TRANSACTION, &tagValueList, &C_celo_64px, "Verify", NULL, "Confirm", confirmationCallback);
}

#endif // HAVE_NBGL
20 changes: 8 additions & 12 deletions src/ui_display_public_nbgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,27 @@
#include "bolos_target.h"

static void address_cancel(void) {
nbgl_useCaseStatus("Address rejected", false, ui_idle);
nbgl_useCaseReviewStatus(STATUS_TYPE_ADDRESS_REJECTED, ui_idle);
io_seproxyhal_touch_address_cancel();
}

static void address_confirmation(bool confirm) {
if (confirm) {
nbgl_useCaseStatus("ADDRESS\nAPPROVED", true, ui_idle);
nbgl_useCaseReviewStatus(STATUS_TYPE_ADDRESS_VERIFIED, ui_idle);
io_seproxyhal_touch_address_ok();
}
else {
address_cancel();
}
}

static void address_display(void) {
nbgl_useCaseAddressConfirmation(strings.common.fullAddress, address_confirmation);
}

void ui_display_public_flow(void) {
nbgl_useCaseReviewStart(&C_celo_64px,
"Verify Celo\naddress",
"",
"Cancel",
address_display,
address_cancel);
nbgl_useCaseAddressReview(tmpCtx.publicKeyContext.address,
NULL,
&C_celo_64px,
"Verify Celo\naddress",
NULL,
address_confirmation);
}

#endif // HAVE_NBGL
92 changes: 46 additions & 46 deletions src/ui_settings_nbgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,54 +10,42 @@
#define IS_TOUCHABLE false

// Forward declaration
static void displaySettingsMenu(void);
static void settingsControlsCallback(int token, uint8_t index);
static bool settingsNavCallback(uint8_t page, nbgl_pageContent_t *content);
static uint8_t initSettingPage;
static void controls_callback(int token, uint8_t index, int page);

enum {
SWITCH_CONTRACT_DATA_SET_TOKEN = FIRST_USER_TOKEN,
SWITCH_DEBUG_DATA_SET_TOKEN,
NB_SETTINGS_SWITCHES,
};

static nbgl_layoutSwitch_t switches[NB_SETTINGS_SWITCHES - FIRST_USER_TOKEN];
static nbgl_contentSwitch_t switches[NB_SETTINGS_SWITCHES - FIRST_USER_TOKEN];

static const char* const infoTypes[] = {"Version", "Celo App"};
static const char* const infoContents[] = {APPVERSION, "(c) 2022 Ledger"};
static const char* const infoTypes[NB_INFO_FIELDS] = {"Version", "Celo App"};
static const char* const infoContents[NB_INFO_FIELDS] = {APPVERSION, "(c) 2022 Ledger"};

static void onQuitCallback(void) {
os_sched_exit(-1);
}

static bool settingsNavCallback(uint8_t page, nbgl_pageContent_t *content) {
if (page == 0) {
content->type = INFOS_LIST;
content->infosList.nbInfos = NB_INFO_FIELDS;
content->infosList.infoTypes = (const char**) infoTypes;
content->infosList.infoContents = (const char**) infoContents;
}
else if (page == 1) {
switches[0].text = "Contract data";
switches[0].subText = "Allow contract data\nin transactions";
switches[0].token = SWITCH_CONTRACT_DATA_SET_TOKEN;
switches[0].tuneId = TUNE_TAP_CASUAL;
switches[0].initState = N_storage.dataAllowed;
static const nbgl_contentInfoList_t infoList = {
.nbInfos = NB_INFO_FIELDS,
.infoTypes = (const char**) infoTypes,
.infoContents = (const char**) infoContents,
};

switches[1].text = "Debug data";
switches[1].subText = "Display contract data details";
switches[1].token = SWITCH_DEBUG_DATA_SET_TOKEN;
switches[1].tuneId = TUNE_TAP_CASUAL;
switches[1].initState = N_storage.contractDetails;

content->type = SWITCHES_LIST;
content->switchesList.nbSwitches = NB_SETTINGS_SWITCHES - FIRST_USER_TOKEN,
content->switchesList.switches = (nbgl_layoutSwitch_t*) switches;
}
else {
return false;
}
return true;
}
// settings menu definition
#define SETTING_CONTENTS_NB 1
static const nbgl_content_t contents[SETTING_CONTENTS_NB] = {
{.type = SWITCHES_LIST,
.content.switchesList.nbSwitches = NB_SETTINGS_SWITCHES - FIRST_USER_TOKEN,
.content.switchesList.switches = (nbgl_layoutSwitch_t*) switches,
.contentActionCallback = controls_callback}};

static const nbgl_genericContents_t settingContents = {.callbackCallNeeded = false,
.contentsList = contents,
.nbContents = SETTING_CONTENTS_NB};

static void switch_settings_contract_data() {
uint8_t value = (N_storage.dataAllowed ? 0 : 1);
Expand All @@ -68,14 +56,14 @@ static void switch_settings_display_data() {
uint8_t value = (N_storage.contractDetails ? 0 : 1);
nvm_write(&N_storage.contractDetails, (void*)&value, sizeof(uint8_t));
}

static void settingsControlsCallback(int token, uint8_t index) {
static void controls_callback(int token, uint8_t index, int page) {
UNUSED(index);
initSettingPage = page;
switch(token)
{
case SWITCH_CONTRACT_DATA_SET_TOKEN:
switch_settings_contract_data();
break;
break;

case SWITCH_DEBUG_DATA_SET_TOKEN:
switch_settings_display_data();
Expand All @@ -88,19 +76,31 @@ static void settingsControlsCallback(int token, uint8_t index) {

switches[0].initState = N_storage.dataAllowed;
switches[1].initState = N_storage.contractDetails;

displaySettingsMenu();
}

static void displaySettingsMenu(void) {
nbgl_useCaseSettings("Celo settings", PAGE_START, NB_PAGE_SETTING, IS_TOUCHABLE, ui_idle,
settingsNavCallback, settingsControlsCallback);
}

void ui_idle(void) {
nbgl_useCaseHome("Celo", &C_celo_64px,
NULL, true,
displaySettingsMenu, onQuitCallback);
switches[0].initState = N_storage.dataAllowed;
switches[0].text = "Contract data";
switches[0].subText = "Allow contract data\nin transactions";
switches[0].token = SWITCH_CONTRACT_DATA_SET_TOKEN;
switches[0].tuneId = TUNE_TAP_CASUAL;

switches[1].initState = N_storage.contractDetails;
switches[1].text = "Debug data";
switches[1].subText = "Display contract data details";
switches[1].token = SWITCH_DEBUG_DATA_SET_TOKEN;
switches[1].tuneId = TUNE_TAP_CASUAL;

nbgl_useCaseHomeAndSettings(
"Celo",
&C_celo_64px,
NULL,
INIT_HOME_PAGE,
&settingContents,
&infoList,
NULL,
onQuitCallback
);
}

#endif // HAVE_NBGL
23 changes: 4 additions & 19 deletions src/ui_sign_nbgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,28 @@
#include "bolos_target.h"

static void sign_cancel(void) {
nbgl_useCaseStatus("Message rejected", false, ui_idle);
nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_REJECTED, ui_idle);
io_seproxyhal_touch_signMessage_cancel();
}

static void sign_confirmation(bool confirm) {
if (confirm) {
nbgl_useCaseStatus("MESSAGE\nAPPROVED", true, ui_idle);
nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_SIGNED, ui_idle);
io_seproxyhal_touch_signMessage_ok();
}
else {
sign_cancel();
}
}

static void sign_display(void) {
void ui_display_sign_flow(void) {
tagValuePair[0].item = "Message hash";
tagValuePair[0].value = (char*)strings.common.fullAddress;

tagValueList.nbPairs = 1;
tagValueList.pairs = tagValuePair;
tagValueList.smallCaseForValue = false;

infoLongPress.text = "Sign message";
infoLongPress.icon = &C_celo_64px;
infoLongPress.longPressText = "Hold to sign";
infoLongPress.longPressToken = 0;
infoLongPress.tuneId = TUNE_TAP_CASUAL;

nbgl_useCaseStaticReview(&tagValueList, &infoLongPress, "Cancel", sign_confirmation);
}

void ui_display_sign_flow(void) {
nbgl_useCaseReviewStart(&C_celo_64px,
"Review message",
"",
"Cancel",
sign_display,
sign_cancel);
nbgl_useCaseReview(TYPE_MESSAGE, &tagValueList, &C_celo_64px, "Review message", NULL, "Sign message", sign_confirmation);
}
#endif // HAVE_NBGL
Loading
Loading