From 6e8007b771dbbcba3ddb62203dee53dc76d62fa7 Mon Sep 17 00:00:00 2001 From: Clement Bouvet Date: Tue, 21 Feb 2023 10:53:42 +0100 Subject: [PATCH 01/25] .gitignore: ignore build folder --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9443644..6779287 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ bin/ debug/ dep/ obj/ +build/ # Python *.pyc From 22c7254c9dfa30c087029aba4d4168a4c16695ab Mon Sep 17 00:00:00 2001 From: Clement Bouvet Date: Tue, 21 Feb 2023 10:53:54 +0100 Subject: [PATCH 02/25] Makefile: stax modifications --- Makefile | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index a32c240..025a00d 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,7 @@ include ./makefile_conf/chain/$(CHAIN).mk else $(error Unsupported CHAIN - use $(SUPPORTED_CHAINS)) endif +CFLAGS += -DAPPNAME=\"$(APPNAME)\" ######### # Other # @@ -65,6 +66,13 @@ DEFINES += $(DEFINES_LIB) #prepare hsm generation ifeq ($(TARGET_NAME),TARGET_NANOS) ICONNAME=icons/nanos_app_$(CHAIN).gif +else ifeq ($(TARGET_NAME),TARGET_STAX) +ICONNAME=icons/stax_app_$(CHAIN).gif +DEFINES += ICONGLYPH=C_stax_app_$(CHAIN)_64px +DEFINES += ICONBITMAP=C_stax_app_$(CHAIN)_64px_bitmap +DEFINES += ICONGLYPH_SMALL=C_stax_app_$(CHAIN) +GLYPH_FILES += icons/stax_app_$(CHAIN)_64px.gif +GLYPH_FILES += icons/stax_app_$(CHAIN).gif else ICONNAME=icons/nanox_app_$(CHAIN).gif endif @@ -79,7 +87,7 @@ all: default ############ DEFINES += OS_IO_SEPROXYHAL -DEFINES += HAVE_BAGL HAVE_SPRINTF HAVE_SNPRINTF_FORMAT_U +DEFINES += HAVE_SPRINTF HAVE_SNPRINTF_FORMAT_U DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=4 IO_HID_EP_LENGTH=64 HAVE_USB_APDU DEFINES += LEDGER_MAJOR_VERSION=$(APPVERSION_M) LEDGER_MINOR_VERSION=$(APPVERSION_N) LEDGER_PATCH_VERSION=$(APPVERSION_P) @@ -97,23 +105,34 @@ DEFINES += HAVE_UX_FLOW DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL="" -ifeq ($(TARGET_NAME),TARGET_NANOX) +ifneq (,$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX)) +DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE +SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl endif -ifeq ($(TARGET_NAME),TARGET_NANOS) +ifneq (,$(filter $(TARGET_NAME),TARGET_NANOS TARGET_NANOS2)) DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=72 -DEFINES += HAVE_WALLET_ID_SDK +endif + +ifeq ($(TARGET_NAME),TARGET_STAX) +DEFINES += HAVE_NBGL +DEFINES += NBGL_QRCODE +else +DEFINES += HAVE_BAGL +ifeq ($(TARGET_NAME),TARGET_NANOS) +DEFINES += HAVE_WALLET_ID_SDK +DEFINES += BAGL_WIDTH=128 BAGL_HEIGHT=32 else -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 DEFINES += HAVE_GLO096 -DEFINES += HAVE_BAGL BAGL_WIDTH=128 BAGL_HEIGHT=64 +DEFINES += BAGL_WIDTH=128 BAGL_HEIGHT=64 DEFINES += HAVE_BAGL_ELLIPSIS # long label truncation feature DEFINES += HAVE_BAGL_FONT_OPEN_SANS_REGULAR_11PX DEFINES += HAVE_BAGL_FONT_OPEN_SANS_EXTRABOLD_11PX DEFINES += HAVE_BAGL_FONT_OPEN_SANS_LIGHT_16PX endif +endif # Enables direct data signing without having to specify it in the settings. Useful when testing with speculos. ALLOW_DATA:=0 @@ -167,7 +186,7 @@ endif endif # Enabling debug PRINTF -DEBUG:=0 +DEBUG:=1 ifneq ($(DEBUG),0) DEFINES += HAVE_STACK_OVERFLOW_CHECK ifeq ($(TARGET_NAME),TARGET_NANOS) @@ -204,13 +223,13 @@ endif CC := $(CLANGPATH)clang -#CFLAGS += -O0 -CFLAGS += -Oz -Wno-format-invalid-specifier -Wno-format-extra-args +CFLAGS += -Og -g +# CFLAGS += -Oz -Wno-format-invalid-specifier -Wno-format-extra-args AS := $(GCCPATH)arm-none-eabi-gcc LD := $(GCCPATH)arm-none-eabi-gcc -LDFLAGS += -O3 -Os +LDFLAGS += -O0 LDLIBS += -lm -lgcc -lc # import rules to compile glyphs(/pone) @@ -219,11 +238,13 @@ include $(BOLOS_SDK)/Makefile.glyphs ### variables processed by the common makefile.rules of the SDK to grab source files and include dirs APP_SOURCE_PATH += src_common src src_features src_plugins SDK_SOURCE_PATH += lib_stusb lib_stusb_impl lib_u2f +ifeq ($(TARGET_NAME),TARGET_STAX) +SDK_SOURCE_PATH += lib_ux_stax +APP_SOURCE_PATH += src_nbgl +else SDK_SOURCE_PATH += lib_ux -ifeq ($(TARGET_NAME),TARGET_NANOX) -SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl -endif APP_SOURCE_PATH += src_bagl +endif ### initialize plugin SDK submodule if needed, rebuild it, and warn if a difference is noticed ifeq ($(CHAIN),ethereum) From b275067f4704553d8a6ea005481c83aa1f8aa882 Mon Sep 17 00:00:00 2001 From: Clement Bouvet Date: Tue, 21 Feb 2023 10:57:42 +0100 Subject: [PATCH 03/25] common_ui: remove non implemented function --- src/common_ui.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/common_ui.h b/src/common_ui.h index 9b2b0dc..e14f57b 100644 --- a/src/common_ui.h +++ b/src/common_ui.h @@ -9,7 +9,6 @@ void ui_display_public_eth2(void); void ui_display_privacy_public_key(void); void ui_display_privacy_shared_secret(void); void ui_display_public_key(void); -void ui_display_sign(void); void ui_sign_712_v0(void); void ui_display_stark_public(void); void ui_confirm_selector(void); From be029c642d42f41d70771995f796fe855ecf0dce Mon Sep 17 00:00:00 2001 From: Clement Bouvet Date: Tue, 21 Feb 2023 11:01:18 +0100 Subject: [PATCH 04/25] stax: add UI implementation --- src/handle_swap_sign_transaction.c | 6 + src/main.c | 25 ++- src/ui_callbacks.h | 4 + src_nbgl/ui_approve_tx.c | 235 ++++++++++++++++++++++++++++ src_nbgl/ui_confirm_parameter.c | 56 +++++++ src_nbgl/ui_confirm_selector.c | 56 +++++++ src_nbgl/ui_display_privacy.c | 68 ++++++++ src_nbgl/ui_get_eth2_public_key.c | 30 ++++ src_nbgl/ui_get_public_key.c | 28 ++++ src_nbgl/ui_get_stark_public_key.c | 29 ++++ src_nbgl/ui_idle.c | 61 ++++++++ src_nbgl/ui_nbgl.h | 19 +++ src_nbgl/ui_settings.c | 92 +++++++++++ src_nbgl/ui_sign_712.c | 80 ++++++++++ src_nbgl/ui_sign_712_v0.c | 66 ++++++++ src_nbgl/ui_sign_message.c | 166 ++++++++++++++++++++ src_nbgl/ui_stark_limit_order.c | 67 ++++++++ src_nbgl/ui_stark_transfer.c | 127 +++++++++++++++ src_nbgl/ui_stark_unsafe_sign.c | 70 +++++++++ src_nbgl/ui_warning_contract_data.c | 21 +++ 20 files changed, 1298 insertions(+), 8 deletions(-) create mode 100644 src_nbgl/ui_approve_tx.c create mode 100644 src_nbgl/ui_confirm_parameter.c create mode 100644 src_nbgl/ui_confirm_selector.c create mode 100644 src_nbgl/ui_display_privacy.c create mode 100644 src_nbgl/ui_get_eth2_public_key.c create mode 100644 src_nbgl/ui_get_public_key.c create mode 100644 src_nbgl/ui_get_stark_public_key.c create mode 100644 src_nbgl/ui_idle.c create mode 100644 src_nbgl/ui_nbgl.h create mode 100644 src_nbgl/ui_settings.c create mode 100644 src_nbgl/ui_sign_712.c create mode 100644 src_nbgl/ui_sign_712_v0.c create mode 100644 src_nbgl/ui_sign_message.c create mode 100644 src_nbgl/ui_stark_limit_order.c create mode 100644 src_nbgl/ui_stark_transfer.c create mode 100644 src_nbgl/ui_stark_unsafe_sign.c create mode 100644 src_nbgl/ui_warning_contract_data.c diff --git a/src/handle_swap_sign_transaction.c b/src/handle_swap_sign_transaction.c index 39268f5..7eb0e27 100644 --- a/src/handle_swap_sign_transaction.c +++ b/src/handle_swap_sign_transaction.c @@ -67,7 +67,13 @@ void handle_swap_sign_transaction(chain_config_t* config) { nvm_write((void*) &N_storage, (void*) &storage, sizeof(internalStorage_t)); } +#ifdef HAVE_BAGL UX_INIT(); +#endif // HAVE_BAGL +#ifdef HAVE_NBGL + nbgl_objInit(); +#endif // HAVE_NBGL + USB_power(0); USB_power(1); // ui_idle(); diff --git a/src/main.c b/src/main.c index d66dbb1..67442b0 100644 --- a/src/main.c +++ b/src/main.c @@ -877,9 +877,11 @@ void app_main(void) { } // override point, but nothing more to do +#ifdef HAVE_BAGL void io_seproxyhal_display(const bagl_element_t *element) { io_seproxyhal_display_default((bagl_element_t *) element); } +#endif unsigned char io_event(__attribute__((unused)) unsigned char channel) { // nothing done with the event, throw an error on the transport layer if @@ -890,10 +892,11 @@ unsigned char io_event(__attribute__((unused)) unsigned char channel) { case SEPROXYHAL_TAG_FINGER_EVENT: UX_FINGER_EVENT(G_io_seproxyhal_spi_buffer); break; - +#ifdef HAVE_BAGL case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT: UX_BUTTON_PUSH_EVENT(G_io_seproxyhal_spi_buffer); break; +#endif // HAVE_BAGL case SEPROXYHAL_TAG_STATUS_EVENT: if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID && @@ -907,16 +910,17 @@ unsigned char io_event(__attribute__((unused)) unsigned char channel) { break; case SEPROXYHAL_TAG_DISPLAY_PROCESSED_EVENT: +#ifdef HAVE_BAGL UX_DISPLAYED_EVENT({}); +#endif // HAVE_BAGL +#ifdef HAVE_NBGL + UX_DEFAULT_EVENT(); +#endif // HAVE_NBGL break; -#if 0 - case SEPROXYHAL_TAG_TICKER_EVENT: - UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, - { - }); - break; -#endif + case SEPROXYHAL_TAG_TICKER_EVENT: + UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, {}); + break; } // close the event if not done previously (by a display or whatever) @@ -958,7 +962,12 @@ void coin_main(chain_config_t *coin_config) { tmpCtx.transactionContext.currentItemIndex = 0; for (;;) { +#ifdef HAVE_BAGL UX_INIT(); +#endif // HAVE_BAGL +#ifdef HAVE_NBGL + nbgl_objInit(); +#endif // HAVE_NBGL BEGIN_TRY { TRY { diff --git a/src/ui_callbacks.h b/src/ui_callbacks.h index 2035c27..041f717 100644 --- a/src/ui_callbacks.h +++ b/src/ui_callbacks.h @@ -4,6 +4,10 @@ #include "shared_context.h" #include "ux.h" +#ifdef HAVE_NBGL +typedef int bagl_element_t; +#endif + unsigned int io_seproxyhal_touch_settings(const bagl_element_t *e); unsigned int io_seproxyhal_touch_exit(const bagl_element_t *e); unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e); diff --git a/src_nbgl/ui_approve_tx.c b/src_nbgl/ui_approve_tx.c new file mode 100644 index 0000000..e808cf2 --- /dev/null +++ b/src_nbgl/ui_approve_tx.c @@ -0,0 +1,235 @@ + +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" +#include "network.h" +#include "plugins.h" + +// 1 more than actually displayed on screen, because of calculations in StaticReview +#define MAX_PLUGIN_ITEMS_PER_SCREEN 4 +#define TAG_MAX_LEN 43 +#define VALUE_MAX_LEN 79 +enum { + REJECT_TOKEN, + START_REVIEW_TOKEN, +}; + +static nbgl_layoutTagValue_t tlv; +// these buffers are used as circular +static char title_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][TAG_MAX_LEN]; +static char msg_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][VALUE_MAX_LEN]; +static char transaction_type[100]; +static nbgl_layoutTagValueList_t useCaseTagValueList; +static nbgl_pageInfoLongPress_t infoLongPress; + +struct tx_approval_context_t { + bool fromPlugin; + bool blindSigning; + bool displayNetwork; +}; + +static struct tx_approval_context_t tx_approval_context; + +static void reviewContinueCommon(void); + +static void reviewReject(void) { + io_seproxyhal_touch_tx_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_tx_ok(NULL); +} + +static void onConfirmAbandon(void) { + nbgl_useCaseStatus("Transaction rejected", false, reviewReject); +} + +static void rejectTransactionQuestion(void) { + nbgl_useCaseConfirm("Reject transaction?", + NULL, + "Yes, reject", + "Go back to transaction", + onConfirmAbandon); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + nbgl_useCaseStatus("TRANSACTION\nSIGNED", true, confirmTransation); + } else { + rejectTransactionQuestion(); + } +} + +// called by NBGL to get the tag/value pair corresponding to pairIndex +static nbgl_layoutTagValue_t *getTagValuePair(uint8_t pairIndex) { + static int counter = 0; + + if (tx_approval_context.fromPlugin) { + if (pairIndex < dataContext.tokenContext.pluginUiMaxItems) { + // for the next dataContext.tokenContext.pluginUiMaxItems items, get tag/value from + // plugin_ui_get_item_internal() + dataContext.tokenContext.pluginUiCurrentItem = pairIndex; + plugin_ui_get_item_internal((uint8_t *) title_buffer[counter], + TAG_MAX_LEN, + (uint8_t *) msg_buffer[counter], + VALUE_MAX_LEN); + tlv.item = title_buffer[counter]; + tlv.value = msg_buffer[counter]; + } else { + pairIndex -= dataContext.tokenContext.pluginUiMaxItems; + // for the last 1 (or 2), tags are fixed + if (tx_approval_context.displayNetwork && (pairIndex == 0)) { + tlv.item = "Network"; + tlv.value = strings.common.network_name; + } else { + tlv.item = "Max fees"; + tlv.value = strings.common.maxFee; + } + } + } else { + // if displayNonce is false, we skip index 2 + if ((pairIndex > 1) && (!N_storage.displayNonce)) { + pairIndex++; + } + + switch (pairIndex) { + case 0: + tlv.item = "Amount"; + tlv.value = strings.common.fullAmount; + break; + case 1: + tlv.item = "Address"; + tlv.value = strings.common.fullAddress; + break; + case 2: + tlv.item = "Nonce"; + tlv.value = strings.common.nonce; + break; + case 3: + tlv.item = "Max fees"; + tlv.value = strings.common.maxFee; + break; + case 4: + tlv.item = "Network"; + tlv.value = strings.common.network_name; + break; + } + } + // counter is used as index to circular buffer + counter++; + if (counter == MAX_PLUGIN_ITEMS_PER_SCREEN) { + counter = 0; + } + return &tlv; +} + +static void pageCallback(int token, uint8_t index) { + (void) index; + nbgl_pageRelease(pageContext); + if (token == REJECT_TOKEN) { + reviewReject(); + } else if (token == START_REVIEW_TOKEN) { + reviewContinueCommon(); + } +} + +static void reviewContinue(void) { + if (tx_approval_context.blindSigning) { + nbgl_pageInfoDescription_t info = { + .centeredInfo.icon = &C_round_warning_64px, + .centeredInfo.text1 = "Blind Signing", + .centeredInfo.text2 = + "This transaction cannot be\nsecurely interpreted by Ledger\nStax. It might put " + "your assets\nat risk.", + .centeredInfo.text3 = NULL, + .centeredInfo.style = LARGE_CASE_INFO, + .centeredInfo.offsetY = -32, + .footerText = "Reject transaction", + .footerToken = REJECT_TOKEN, + .tapActionText = "Tap to continue", + .tapActionToken = START_REVIEW_TOKEN, + .topRightStyle = NO_BUTTON_STYLE, + .actionButtonText = NULL, + .tuneId = TUNE_TAP_CASUAL}; + + if (pageContext != NULL) { + nbgl_pageRelease(pageContext); + pageContext = NULL; + } + pageContext = nbgl_pageDrawInfo(&pageCallback, NULL, &info); + } else { + reviewContinueCommon(); + } +} + +static void reviewContinueCommon(void) { + uint8_t nbPairs = 0; + + if (tx_approval_context.fromPlugin) { + // plugin id + max items + fees + nbPairs += dataContext.tokenContext.pluginUiMaxItems + 1; + if (tx_approval_context.displayNetwork) { + nbPairs++; + } + } else { + nbPairs += 3; + if (N_storage.displayNonce) { + nbPairs++; + } + if (tx_approval_context.displayNetwork) { + nbPairs++; + } + } + + useCaseTagValueList.pairs = NULL; + useCaseTagValueList.callback = getTagValuePair; + useCaseTagValueList.startIndex = 0; + useCaseTagValueList.nbPairs = nbPairs; ///< number of pairs in pairs array + useCaseTagValueList.smallCaseForValue = false; + useCaseTagValueList.wrapping = false; + infoLongPress.icon = get_app_chain_icon(); + infoLongPress.text = tx_approval_context.fromPlugin ? transaction_type : "Review transaction"; + infoLongPress.longPressText = "Hold to sign"; + nbgl_useCaseStaticReview(&useCaseTagValueList, + &infoLongPress, + "Reject transaction", + reviewChoice); +} + +static void buildFirstPage(void) { + if (tx_approval_context.fromPlugin) { + plugin_ui_get_id(); + SPRINTF(transaction_type, + "Review %s\ntransaction:\n%s", + strings.common.fullAddress, + strings.common.fullAmount); + nbgl_useCaseReviewStart(get_app_chain_icon(), + transaction_type, + NULL, + "Reject transaction", + reviewContinue, + rejectTransactionQuestion); + } else { + nbgl_useCaseReviewStart(get_app_chain_icon(), + "Review transaction", + NULL, + "Reject transaction", + reviewContinue, + rejectTransactionQuestion); + } +} + +void ux_approve_tx(bool fromPlugin) { + tx_approval_context.blindSigning = + !fromPlugin && tmpContent.txContent.dataPresent && !N_storage.contractDetails; + tx_approval_context.fromPlugin = fromPlugin; + tx_approval_context.displayNetwork = false; + + uint64_t chain_id = get_tx_chain_id(); + if (chainConfig->chainId == ETHEREUM_MAINNET_CHAINID && chain_id != chainConfig->chainId) { + tx_approval_context.displayNetwork = true; + } + + buildFirstPage(); +} diff --git a/src_nbgl/ui_confirm_parameter.c b/src_nbgl/ui_confirm_parameter.c new file mode 100644 index 0000000..81d2a8a --- /dev/null +++ b/src_nbgl/ui_confirm_parameter.c @@ -0,0 +1,56 @@ +#include "common_ui.h" +#include "ui_nbgl.h" +#include "network.h" + +static nbgl_layoutTagValue_t tlv; + +static void reviewReject(void) { + io_seproxyhal_touch_data_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_data_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + if (page == 0) { + tlv.item = "Parameter"; + tlv.value = strings.tmp.tmp; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 1; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) &tlv; + } else if (page == 1) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->infoLongPress.text = "Confirm parameter"; + content->infoLongPress.longPressText = "Hold to confirm"; + } else { + return false; + } + // valid page so return true + return true; +} + +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, 2, "Reject parameter", NULL, displayTransactionPage, reviewChoice); +} + +static void buildScreen(void) { + nbgl_useCaseReviewStart(get_app_chain_icon(), + "Verify parameter", + NULL, + "Reject", + reviewContinue, + reviewReject); +} + +void ui_confirm_parameter(void) { + buildScreen(); +} diff --git a/src_nbgl/ui_confirm_selector.c b/src_nbgl/ui_confirm_selector.c new file mode 100644 index 0000000..3bf5a11 --- /dev/null +++ b/src_nbgl/ui_confirm_selector.c @@ -0,0 +1,56 @@ +#include "common_ui.h" +#include "ui_nbgl.h" +#include "network.h" + +static nbgl_layoutTagValue_t tlv; + +static void reviewReject(void) { + io_seproxyhal_touch_data_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_data_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + if (page == 0) { + tlv.item = "Parameter"; + tlv.value = strings.tmp.tmp; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 1; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) &tlv; + } else if (page == 1) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->infoLongPress.text = "Confirm selector"; + content->infoLongPress.longPressText = "Hold to confirm"; + } else { + return false; + } + // valid page so return true + return true; +} + +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, 2, "Reject selector", NULL, displayTransactionPage, reviewChoice); +} + +static void buildScreen(void) { + nbgl_useCaseReviewStart(get_app_chain_icon(), + "Verify selector", + NULL, + "Reject", + reviewContinue, + reviewReject); +} + +void ui_confirm_selector(void) { + buildScreen(); +} diff --git a/src_nbgl/ui_display_privacy.c b/src_nbgl/ui_display_privacy.c new file mode 100644 index 0000000..b4a9d1c --- /dev/null +++ b/src_nbgl/ui_display_privacy.c @@ -0,0 +1,68 @@ +#include "common_ui.h" +#include "ui_nbgl.h" +#include "ui_callbacks.h" +#include "nbgl_use_case.h" +#include "network.h" + +static nbgl_layoutTagValue_t tlv[2]; +static char *review_string; + +static void reviewReject(void) { + io_seproxyhal_touch_privacy_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_privacy_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + if (page == 0) { + tlv[0].item = "Address"; + tlv[0].value = strings.common.fullAddress; + tlv[1].item = "Key"; + tlv[1].value = strings.common.fullAmount; + + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 2; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + } else if (page == 1) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->infoLongPress.text = review_string; + content->infoLongPress.longPressText = "Hold to approve"; + } else { + return false; + } + // valid page so return true + return true; +} + +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, 2, "Reject", NULL, displayTransactionPage, reviewChoice); +} + +static void buildFirstPage(void) { + nbgl_useCaseReviewStart(get_app_chain_icon(), + review_string, + NULL, + "Reject", + reviewContinue, + reviewReject); +} + +void ui_display_privacy_public_key(void) { + review_string = "Provide public\nprivacy key"; + buildFirstPage(); +} + +void ui_display_privacy_shared_secret(void) { + review_string = "Provide public\nsecret key"; + buildFirstPage(); +} diff --git a/src_nbgl/ui_get_eth2_public_key.c b/src_nbgl/ui_get_eth2_public_key.c new file mode 100644 index 0000000..9f388df --- /dev/null +++ b/src_nbgl/ui_get_eth2_public_key.c @@ -0,0 +1,30 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" + +static void reviewReject(void) { + io_seproxyhal_touch_address_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_address_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + // display a status page and go back to main + nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, confirmTransation); + } else { + nbgl_useCaseStatus("Address verification\ncancelled", false, reviewReject); + } +} + +static void buildScreen(void) { + snprintf(strings.tmp.tmp, 100, "0x%.*H", 48, tmpCtx.publicKeyContext.publicKey.W); + nbgl_useCaseAddressConfirmation(strings.tmp.tmp, reviewChoice); +} + +void ui_display_public_eth2(void) { + buildScreen(); +} \ No newline at end of file diff --git a/src_nbgl/ui_get_public_key.c b/src_nbgl/ui_get_public_key.c new file mode 100644 index 0000000..5966737 --- /dev/null +++ b/src_nbgl/ui_get_public_key.c @@ -0,0 +1,28 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" + +static void reviewReject(void) { + io_seproxyhal_touch_address_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_address_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + // display a status page and go back to main + nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, confirmTransation); + } else { + nbgl_useCaseStatus("Address verification\ncancelled", false, reviewReject); + } +} + +static void buildScreen(void) { + nbgl_useCaseAddressConfirmation(strings.common.fullAddress, reviewChoice); +} +void ui_display_public_key(void) { + buildScreen(); +} \ No newline at end of file diff --git a/src_nbgl/ui_get_stark_public_key.c b/src_nbgl/ui_get_stark_public_key.c new file mode 100644 index 0000000..ce57787 --- /dev/null +++ b/src_nbgl/ui_get_stark_public_key.c @@ -0,0 +1,29 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" + +static void reviewReject(void) { + io_seproxyhal_touch_address_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_stark_pubkey_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + // display a status page and go back to main + nbgl_useCaseStatus("ADDRESS\nVERIFIED", true, confirmTransation); + } else { + nbgl_useCaseStatus("Address verification\ncancelled", false, reviewReject); + } +} + +static void buildScreen(void) { + nbgl_useCaseAddressConfirmation(strings.tmp.tmp, reviewChoice); +} + +void ui_display_stark_public(void) { + buildScreen(); +} \ No newline at end of file diff --git a/src_nbgl/ui_idle.c b/src_nbgl/ui_idle.c new file mode 100644 index 0000000..7e02101 --- /dev/null +++ b/src_nbgl/ui_idle.c @@ -0,0 +1,61 @@ +#include "common_ui.h" +#include "shared_context.h" +#include "ui_nbgl.h" +#include "nbgl_use_case.h" +#include "glyphs.h" +#include "network.h" + +uint8_t staxSharedBuffer[SHARED_BUFFER_SIZE] = {0}; + +nbgl_page_t* pageContext; + +void releaseContext(void) { + if (pageContext != NULL) { + nbgl_pageRelease(pageContext); + pageContext = NULL; + } +} +enum { BACK_TOKEN = 0, INFO_TOKEN, NEXT_TOKEN, CANCEL_TOKEN, QUIT_INFO_TOKEN, QUIT_APP_TOKEN }; + +void app_quit(void) { + // exit app here + os_sched_exit(-1); +} + +void ui_idle(void) { + if (plugin_name != NULL) { // plugin + nbgl_useCasePlugInHome((char*) plugin_name, + APPNAME, + &ICONGLYPH_SMALL, + NULL, + NULL, + true, + ui_menu_settings, + app_quit); + } else { + char* app_name = (char*) get_app_network_name(); + + switch (get_app_chain_id()) { + // Standalone apps + case 1: // Mainnet + case 3: // Ropsten + case 5: // Goerli + nbgl_useCaseHome(app_name, + get_app_chain_icon(), + NULL, + true, + ui_menu_settings, + app_quit); + break; + // Clones + default: + nbgl_useCaseHome(app_name, + get_app_chain_icon(), + NULL, + true, + ui_menu_settings, + app_quit); + break; + } + } +} diff --git a/src_nbgl/ui_nbgl.h b/src_nbgl/ui_nbgl.h new file mode 100644 index 0000000..66ffd4f --- /dev/null +++ b/src_nbgl/ui_nbgl.h @@ -0,0 +1,19 @@ +#ifndef _UI_NBGL_H_ +#define _UI_NBGL_H_ + +#include +#include +#include + +#define SHARED_BUFFER_SIZE SHARED_CTX_FIELD_1_SIZE +extern uint8_t staxSharedBuffer[SHARED_BUFFER_SIZE]; + +extern nbgl_page_t* pageContext; + +void releaseContext(void); + +void ui_idle(void); +void ui_menu_settings(void); +void ui_menu_about(void); + +#endif // _UI_NBGL_H_ \ No newline at end of file diff --git a/src_nbgl/ui_settings.c b/src_nbgl/ui_settings.c new file mode 100644 index 0000000..482d220 --- /dev/null +++ b/src_nbgl/ui_settings.c @@ -0,0 +1,92 @@ +#include "common_ui.h" +#include "ui_nbgl.h" +#include "nbgl_use_case.h" + +static const char* const infoTypes[] = {"Version", APPNAME " App"}; +static const char* const infoContents[] = {APPVERSION, "(c) 2022 Ledger"}; + +enum { BLIND_SIGNING_TOKEN = FIRST_USER_TOKEN, DEBUG_TOKEN, NONCE_TOKEN, EIP712_VERBOSE_TOKEN }; + +static nbgl_layoutSwitch_t switches[4]; + +static bool navCallback(uint8_t page, nbgl_pageContent_t* content) { + switch (page) { + case 0: + switches[0] = + (nbgl_layoutSwitch_t){.initState = N_storage.dataAllowed ? ON_STATE : OFF_STATE, + .text = "Blind signing", + .subText = "Enable transaction blind signing", + .token = BLIND_SIGNING_TOKEN, + .tuneId = TUNE_TAP_CASUAL}; + switches[1] = + (nbgl_layoutSwitch_t){.initState = N_storage.contractDetails ? ON_STATE : OFF_STATE, + .text = "Debug", + .subText = "Display contract data details", + .token = DEBUG_TOKEN, + .tuneId = TUNE_TAP_CASUAL}; + switches[2] = + (nbgl_layoutSwitch_t){.initState = N_storage.displayNonce ? ON_STATE : OFF_STATE, + .text = "Nonce", + .subText = "Display account nonce\nin transaction", + .token = NONCE_TOKEN, + .tuneId = TUNE_TAP_CASUAL}; + + content->type = SWITCHES_LIST; + content->switchesList.nbSwitches = 3; + content->switchesList.switches = (nbgl_layoutSwitch_t*) switches; + break; + + case 1: + switches[0] = + (nbgl_layoutSwitch_t){.initState = N_storage.verbose_eip712 ? ON_STATE : OFF_STATE, + .text = "Verbose EIP712", + .subText = "Ignore filtering and\ndisplay raw content", + .token = EIP712_VERBOSE_TOKEN, + .tuneId = TUNE_TAP_CASUAL}; + + content->type = SWITCHES_LIST; + content->switchesList.nbSwitches = 1; + content->switchesList.switches = (nbgl_layoutSwitch_t*) switches; + break; + + case 2: + content->type = INFOS_LIST; + content->infosList.nbInfos = 2; + content->infosList.infoTypes = (const char**) infoTypes; + content->infosList.infoContents = (const char**) infoContents; + break; + + default: + return false; + break; + } + + return true; +} + +static void controlsCallback(int token, uint8_t index) { + (void) index; + uint8_t value; + switch (token) { + case BLIND_SIGNING_TOKEN: + value = (N_storage.dataAllowed ? 0 : 1); + nvm_write((void*) &N_storage.dataAllowed, (void*) &value, sizeof(uint8_t)); + break; + case DEBUG_TOKEN: + value = (N_storage.contractDetails ? 0 : 1); + nvm_write((void*) &N_storage.contractDetails, (void*) &value, sizeof(uint8_t)); + break; + case NONCE_TOKEN: + value = (N_storage.displayNonce ? 0 : 1); + nvm_write((void*) &N_storage.displayNonce, (void*) &value, sizeof(uint8_t)); + break; + case EIP712_VERBOSE_TOKEN: + value = (N_storage.verbose_eip712 ? 0 : 1); + nvm_write((void*) &N_storage.verbose_eip712, (void*) &value, sizeof(uint8_t)); + break; + } +} + +void ui_menu_settings(void) { + nbgl_useCaseSettings(APPNAME " settings", 0, 3, true, ui_idle, navCallback, controlsCallback); +} diff --git a/src_nbgl/ui_sign_712.c b/src_nbgl/ui_sign_712.c new file mode 100644 index 0000000..c13a78a --- /dev/null +++ b/src_nbgl/ui_sign_712.c @@ -0,0 +1,80 @@ +#include "common_ui.h" +#include "ui_nbgl.h" +#include "ui_logic.h" +#include "common_712.h" +#include "nbgl_use_case.h" +#include "network.h" + +// 4 pairs of tag/value to display +static nbgl_layoutTagValue_t tlv; + +static void reject_message(void) { + ui_712_reject(NULL); +} + +static void sign_message() { + ui_712_approve(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + sign_message(); + } else { + reject_message(); + } +} +static bool displaySignPage(uint8_t page, nbgl_pageContent_t *content) { + (void) page; + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->infoLongPress.text = "Sign typed message"; + content->infoLongPress.longPressText = "Hold to sign"; + return true; +} + +static uint32_t stringsIdx = 0; + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + uint16_t len = 0; + if (stringsIdx < strlen(strings.tmp.tmp)) { + bool reached = nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_32px, + strings.tmp.tmp + stringsIdx, + SCREEN_WIDTH - (2 * BORDER_MARGIN), + 9, + &len); + memset(staxSharedBuffer, 0, sizeof(staxSharedBuffer)); + memcpy(staxSharedBuffer, strings.tmp.tmp + stringsIdx, len); + stringsIdx += len; + tlv.item = strings.tmp.tmp2; + tlv.value = staxSharedBuffer; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 1; + content->tagValueList.pairs = &tlv; + return true; + } else { + stringsIdx = 0; + switch (ui_712_next_field()) { + case EIP712_NO_MORE_FIELD: + return displaySignPage(page, content); + break; + case EIP712_FIELD_INCOMING: + case EIP712_FIELD_LATER: + default: + break; + } + return false; + } +} + +void ui_712_switch_to_sign(void) { + nbgl_useCaseRegularReview(0, 0, "Reject", NULL, displaySignPage, reviewChoice); +} + +void ui_712_start(void) { + stringsIdx = 0; + nbgl_useCaseRegularReview(0, 0, "Reject", NULL, displayTransactionPage, reviewChoice); +} + +void ui_712_switch_to_message(void) { + stringsIdx = 0; + nbgl_useCaseRegularReview(0, 0, "Reject", NULL, displayTransactionPage, reviewChoice); +} diff --git a/src_nbgl/ui_sign_712_v0.c b/src_nbgl/ui_sign_712_v0.c new file mode 100644 index 0000000..34b529c --- /dev/null +++ b/src_nbgl/ui_sign_712_v0.c @@ -0,0 +1,66 @@ +#include "common_ui.h" +#include "ui_nbgl.h" +#include "common_712.h" +#include "network.h" + +static nbgl_layoutTagValue_t tlv[2]; + +static char domain_hash[70]; +static char message_hash[70]; + +static void reviewReject(void) { + ui_712_approve_cb(NULL); +} + +static void confirmTransation(void) { + ui_712_reject_cb(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + // display a status page and go back to main + nbgl_useCaseStatus("MESSAGE\nSIGNED", true, confirmTransation); + } else { + nbgl_useCaseStatus("Message signing\ncancelled", false, reviewReject); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + snprintf(domain_hash, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.domainHash); + snprintf(message_hash, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.messageHash); + + if (page == 0) { + tlv[0].item = "Domain hash"; + tlv[0].value = domain_hash; + tlv[1].item = "Message hash"; + tlv[1].value = message_hash; + + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 2; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + } else if (page == 1) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->infoLongPress.text = "Sign typed message"; + content->infoLongPress.longPressText = "Hold to sign"; + } else { + return false; + } + // valid page so return true + return true; +} +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, 2, "Reject", NULL, displayTransactionPage, reviewChoice); +} + +static void buildFirstPage(void) { + nbgl_useCaseReviewStart(get_app_chain_icon(), + "Sign typed message", + NULL, + "Reject", + reviewContinue, + reviewReject); +} + +void ui_sign_712_v0(void) { + buildFirstPage(); +} diff --git a/src_nbgl/ui_sign_message.c b/src_nbgl/ui_sign_message.c new file mode 100644 index 0000000..7bcf541 --- /dev/null +++ b/src_nbgl/ui_sign_message.c @@ -0,0 +1,166 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" +#include "sign_message.h" +#include "glyphs.h" +#include "nbgl_use_case.h" +#include "common_ui.h" + +typedef enum { + UI_191_NBGL_START_REVIEW_DISPLAYED = 0, + UI_191_NBGL_GO_TO_NEXT_CONTENT, + UI_191_NBGL_BACK_FROM_REJECT_CANCEL, + UI_191_NBGL_GO_TO_SIGN, + UI_191_NBGL_SIGN_DISPLAYED, +} e_ui_nbgl_191_state; + +static e_ui_nbgl_191_state state; +static e_ui_nbgl_191_state state_before_reject_cancel; + +static nbgl_layoutTagValue_t pair; + +// +static uint32_t eip191MessageIdx = 0; +static uint32_t stringsTmpTmpIdx = 0; + +static void reject_message(void) { + io_seproxyhal_touch_signMessage_cancel(); +} + +static void sign_message() { + io_seproxyhal_touch_signMessage_ok(); +} + +static bool nav_callback(uint8_t page, nbgl_pageContent_t *content) { + UNUSED(page); + + if ((state != UI_191_NBGL_GO_TO_SIGN) && (state != UI_191_NBGL_SIGN_DISPLAYED)) { + if (state != UI_191_NBGL_BACK_FROM_REJECT_CANCEL) { + memset(staxSharedBuffer + eip191MessageIdx, 0, SHARED_BUFFER_SIZE - eip191MessageIdx); + memcpy( + staxSharedBuffer + eip191MessageIdx, + strings.tmp.tmp + stringsTmpTmpIdx, + MIN(SHARED_BUFFER_SIZE - eip191MessageIdx, SHARED_BUFFER_SIZE - stringsTmpTmpIdx)); + uint16_t len = 0; + bool reached = nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_32px, + staxSharedBuffer, + SCREEN_WIDTH - (2 * BORDER_MARGIN), + 9, + &len); + + stringsTmpTmpIdx = len - eip191MessageIdx; + eip191MessageIdx = len; + staxSharedBuffer[eip191MessageIdx] = '\0'; + + if (!reached && eip191MessageIdx < SHARED_BUFFER_SIZE) { + stringsTmpTmpIdx = 0; + question_switcher(); + + if (state != UI_191_NBGL_GO_TO_SIGN) { + return false; + } + } else if (reached || eip191MessageIdx == SHARED_BUFFER_SIZE) { + eip191MessageIdx = 0; + } + } + + pair.value = staxSharedBuffer; + pair.item = "Message"; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 1; + content->tagValueList.pairs = &pair; + content->tagValueList.smallCaseForValue = false; + content->tagValueList.nbMaxLinesForValue = 9; + content->tagValueList.wrapping = false; + + if (state == UI_191_NBGL_BACK_FROM_REJECT_CANCEL) { + // We come back from Reject screen. + // The previously displayed content must be redisplayed. + // Do not call question_switcher() to avoid replacing + // string.tmp.tmp content. + state = state_before_reject_cancel; + } else if (stringsTmpTmpIdx >= strlen(strings.tmp.tmp)) { + // Fetch the next content to display into strings.tmp.tmp buffer. + stringsTmpTmpIdx = 0; + question_switcher(); + return true; + } + } else { + // the last page must contain a long press button + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = &C_Message_64px; + content->infoLongPress.text = "Sign Message?"; + content->infoLongPress.longPressText = "Hold to sign"; + state = UI_191_NBGL_SIGN_DISPLAYED; + } + return true; +} + +static void choice_callback(bool confirm) { + if (confirm) { + nbgl_useCaseStatus("MESSAGE\nSIGNED", true, sign_message); + sign_message(); + } +} + +static void continue_review(void) { + nbgl_useCaseForwardOnlyReview("Reject", NULL, nav_callback, choice_callback); +} + +static void confirm_transaction_rejection_choice(bool confirm) { + if (confirm) { + reject_message(); + } else { + // Go to previous screen accordingly + if (state == UI_191_NBGL_START_REVIEW_DISPLAYED) { + ui_191_start(); + } else { + if (state != UI_191_NBGL_SIGN_DISPLAYED) { + state_before_reject_cancel = state; + state = UI_191_NBGL_BACK_FROM_REJECT_CANCEL; + } + continue_review(); + } + } +} + +static void confirm_transaction_rejection() { + nbgl_useCaseChoice(&C_warning64px, + "Reject message?", + NULL, + "Yes, Reject", + "Go back to message", + confirm_transaction_rejection_choice); +} + +void ui_191_start(void) { + state = UI_191_NBGL_START_REVIEW_DISPLAYED; + eip191MessageIdx = 0; + stringsTmpTmpIdx = 0; + + nbgl_useCaseReviewStart(&C_Message_64px, + "Review message", + NULL, + "Reject", + continue_review, + confirm_transaction_rejection); +} + +void ui_191_switch_to_message(void) { + // No question mechanism on Stax: + // Message is already displayed + state = UI_191_NBGL_GO_TO_NEXT_CONTENT; + continue_review(); +} + +void ui_191_switch_to_sign(void) { + // Next nav_callback callback must display + // the hold to approve screen + state = UI_191_NBGL_GO_TO_SIGN; +} + +void ui_191_switch_to_question(void) { + // No question mechanism on Stax: + // Always display the next message chunk. + continue_displaying_message(); +} \ No newline at end of file diff --git a/src_nbgl/ui_stark_limit_order.c b/src_nbgl/ui_stark_limit_order.c new file mode 100644 index 0000000..20277be --- /dev/null +++ b/src_nbgl/ui_stark_limit_order.c @@ -0,0 +1,67 @@ +#include "common_ui.h" +#include "ui_nbgl.h" +#include "ui_callbacks.h" +#include "nbgl_use_case.h" +#include "network.h" + +#ifdef HAVE_STARKWARE + +static nbgl_layoutTagValue_t tlv[3]; + +static void reviewReject(void) { + io_seproxyhal_touch_tx_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_stark_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + if (page == 0) { + tlv[0].item = "Sell"; + tlv[0].value = strings.common.fullAmount; + tlv[1].item = "Buy"; + tlv[1].value = strings.common.maxFee; + tlv[2].item = "Token amount"; + tlv[2].value = strings.common.fullAddress; + + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 3; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + } else if (page == 1) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->infoLongPress.text = "Review stark limit order"; + content->infoLongPress.longPressText = "Hold to sign"; + } else { + return false; + } + // valid page so return true + return true; +} + +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, 2, "Reject", NULL, displayTransactionPage, reviewChoice); +} + +static void buildFirstPage(void) { + nbgl_useCaseReviewStart(get_app_chain_icon(), + "Review stark limit order", + NULL, + "Reject", + reviewContinue, + reviewReject); +} + +void ui_stark_limit_order(void) { + buildFirstPage(); +} + +#endif \ No newline at end of file diff --git a/src_nbgl/ui_stark_transfer.c b/src_nbgl/ui_stark_transfer.c new file mode 100644 index 0000000..3532c17 --- /dev/null +++ b/src_nbgl/ui_stark_transfer.c @@ -0,0 +1,127 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" +#include "starkDisplayUtils.h" +#include "ethUtils.h" +#include "network.h" + +#ifdef HAVE_STARKWARE + +static nbgl_layoutTagValue_t tlv[3]; +static char condAddressBuffer[43]; +struct stark_transfer_context { + bool selfTransfer; + bool conditional; +}; + +static struct stark_transfer_context context; + +static void reviewReject(void) { + io_seproxyhal_touch_tx_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_stark_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + uint8_t count = 0; + if (page == 0) { + tlv[count].item = "Amount"; + tlv[count].value = tmpContent.tmp; + count++; + + if (context.selfTransfer == false && context.conditional == false) { + tlv[count].item = "Master Account"; + tlv[count].value = strings.tmp.tmp; + count++; + } + if (context.conditional) { + stark_sign_display_master_account(); + tlv[count].item = "Master Account"; + tlv[count].value = strings.tmp.tmp; + count++; + } + tlv[count].item = "Token Account"; + tlv[count].value = strings.tmp.tmp2; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = count; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + + return true; + } + if (page == 1) { + if (context.conditional) { + getEthDisplayableAddress(dataContext.starkContext.conditionAddress, + condAddressBuffer, + sizeof(condAddressBuffer), + &global_sha3, + chainConfig->chainId), + tlv[0].item = "Cond. Address"; + tlv[0].value = condAddressBuffer; + + stark_sign_display_condition_fact(); + tlv[1].item = "Cond. Address"; + tlv[1].value = strings.tmp.tmp; + + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 2; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + + } else { + page++; + } + } + if (page == 2) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->infoLongPress.text = "Review transaction"; + content->infoLongPress.longPressText = "Hold to sign"; + } + + return false; +} + +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, + context.conditional ? 3 : 2, + "Reject", + NULL, + displayTransactionPage, + reviewChoice); +} + +void ui_stark_transfer(bool selfTransfer, bool conditional) { + context.selfTransfer = selfTransfer; + context.conditional = conditional; + char *subTitle; + if (conditional) { + if (selfTransfer) { + subTitle = "Conditionnal self transfer"; + } else { + subTitle = "Conditionnal transfer"; + } + } else { + if (selfTransfer) { + subTitle = "self transfer"; + } else { + subTitle = "Transfer"; + } + } + nbgl_useCaseReviewStart(get_app_chain_icon(), + "Review stark transaction", + subTitle, + "Reject", + reviewContinue, + reviewReject); +} + +#endif // #ifdef HAVE_STARKWARE diff --git a/src_nbgl/ui_stark_unsafe_sign.c b/src_nbgl/ui_stark_unsafe_sign.c new file mode 100644 index 0000000..59a6eac --- /dev/null +++ b/src_nbgl/ui_stark_unsafe_sign.c @@ -0,0 +1,70 @@ + +#include "common_ui.h" +#include "ui_nbgl.h" +#include "ui_callbacks.h" +#include "nbgl_use_case.h" +#include "network.h" + +#ifdef HAVE_STARKWARE + +static nbgl_layoutTagValue_t tlv[2]; +static char from_account[64]; +static char message_hash[64]; + +static void reviewReject(void) { + io_seproxyhal_touch_tx_cancel(NULL); +} + +static void confirmTransation(void) { + io_seproxyhal_touch_stark_unsafe_sign_ok(NULL); +} + +static void reviewChoice(bool confirm) { + if (confirm) { + confirmTransation(); + } else { + reviewReject(); + } +} + +static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { + snprintf(from_account, sizeof(from_account), "0x%.*H", 32, dataContext.starkContext.w1); + snprintf(message_hash, sizeof(message_hash), "0x%.*H", 32, dataContext.starkContext.w2); + + if (page == 0) { + tlv[0].item = "From Account"; + tlv[0].value = from_account; + tlv[1].item = "Hash"; + tlv[1].value = message_hash; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 2; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + } else if (page == 1) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->infoLongPress.text = "Unsafe Stark Sign"; + content->infoLongPress.longPressText = "Hold to sign"; + } else { + return false; + } + // valid page so return true + return true; +} + +static void reviewContinue(void) { + nbgl_useCaseRegularReview(0, 2, "Reject", NULL, displayTransactionPage, reviewChoice); +} + +static void buildFirstPage(void) { + nbgl_useCaseReviewStart(get_app_chain_icon(), + "Unsafe Stark Sign", + NULL, + "Reject", + reviewContinue, + reviewReject); +} + +void ui_stark_unsafe_sign(void) { + buildFirstPage(); +} + +#endif // HAVE_STARKWARE \ No newline at end of file diff --git a/src_nbgl/ui_warning_contract_data.c b/src_nbgl/ui_warning_contract_data.c new file mode 100644 index 0000000..2619dce --- /dev/null +++ b/src_nbgl/ui_warning_contract_data.c @@ -0,0 +1,21 @@ +#include +#include "shared_context.h" +#include "ui_callbacks.h" +#include "ui_nbgl.h" + +static void ui_warning_contract_data_choice(bool confirm) { + if (confirm) { + ui_idle(); + } else { + ui_menu_settings(); + } +} + +void ui_warning_contract_data(void) { + nbgl_useCaseChoice(&C_warning64px, + "This message cannot\nbe clear-signed", + "Enable blind-signing in\nthe settings to sign\nthis transaction.", + "Exit", + "Go to settings", + ui_warning_contract_data_choice); +} From b5c58b59cf59b0d7561bd6220cd481c5654e0698 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Thu, 4 May 2023 11:52:16 +0200 Subject: [PATCH 05/25] network: cleanup --- src/eth_plugin_handler.c | 2 +- src_bagl/ui_flow_signTx.c | 4 +-- src_common/network.c | 40 ++++++++++++++++++++++++------ src_common/network.h | 17 ++++++++----- src_features/signTx/logic_signTx.c | 10 ++++---- 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/eth_plugin_handler.c b/src/eth_plugin_handler.c index 3aa6883..29e965f 100644 --- a/src/eth_plugin_handler.c +++ b/src/eth_plugin_handler.c @@ -64,7 +64,7 @@ void eth_plugin_prepare_query_contract_UI(ethQueryContractUI_t *queryContractUI, } queryContractUI->screenIndex = screenIndex; - strlcpy(queryContractUI->network_ticker, get_network_ticker(), MAX_TICKER_LEN); + strlcpy(queryContractUI->network_ticker, get_tx_network_ticker(), MAX_TICKER_LEN); queryContractUI->title = title; queryContractUI->titleLength = titleLength; queryContractUI->msg = msg; diff --git a/src_bagl/ui_flow_signTx.c b/src_bagl/ui_flow_signTx.c index 2b55922..c60f46d 100644 --- a/src_bagl/ui_flow_signTx.c +++ b/src_bagl/ui_flow_signTx.c @@ -220,7 +220,7 @@ void ux_approve_tx(bool fromPlugin) { // We're in a regular transaction, just show the amount and the address ux_approval_tx_flow[step++] = &ux_approval_amount_step; #ifdef HAVE_DOMAIN_NAME - uint64_t chain_id = get_chain_id(); + uint64_t chain_id = get_tx_chain_id(); if (has_domain_name(&chain_id, tmpContent.txContent.destination)) { ux_approval_tx_flow[step++] = &ux_domain_name_step; if (N_storage.verbose_domain_name) { @@ -238,7 +238,7 @@ void ux_approve_tx(bool fromPlugin) { ux_approval_tx_flow[step++] = &ux_approval_nonce_step; } - uint64_t chain_id = get_chain_id(); + uint64_t chain_id = get_tx_chain_id(); if (chainConfig->chainId == ETHEREUM_MAINNET_CHAINID && chain_id != chainConfig->chainId) { ux_approval_tx_flow[step++] = &ux_approval_network_step; } diff --git a/src_common/network.c b/src_common/network.c index f0dc4d1..1111134 100644 --- a/src_common/network.c +++ b/src_common/network.c @@ -7,6 +7,8 @@ #include "shared_context.h" #include "utils.h" +typedef enum { APP, TX } e_net_type; + // Mappping of chain ids to networks. static const network_info_t NETWORK_MAPPING[] = { {.chain_id = 1, .name = "Ethereum", .ticker = "ETH"}, @@ -64,7 +66,7 @@ static const network_info_t NETWORK_MAPPING[] = { {.chain_id = 39797, .name = "Energi", .ticker = "NRG"}, {.chain_id = 248, .name = "Oasys", .ticker = "OAS"}}; -uint64_t get_chain_id(void) { +uint64_t get_tx_chain_id(void) { uint64_t chain_id = 0; switch (txContext.txType) { @@ -83,8 +85,16 @@ uint64_t get_chain_id(void) { return chain_id; } -const network_info_t *get_network(void) { - uint64_t chain_id = get_chain_id(); +uint64_t get_app_chain_id(void) { + return chainConfig->chainId; +} + +static uint64_t get_chain_id(e_net_type type) { + return (type == APP) ? get_app_chain_id() : get_tx_chain_id(); +} + +static const network_info_t *get_network(e_net_type type) { + uint64_t chain_id = get_chain_id(type); for (size_t i = 0; i < sizeof(NETWORK_MAPPING) / sizeof(*NETWORK_MAPPING); i++) { if (NETWORK_MAPPING[i].chain_id == chain_id) { return (const network_info_t *) PIC(&NETWORK_MAPPING[i]); @@ -93,8 +103,8 @@ const network_info_t *get_network(void) { return NULL; } -const char *get_network_name(void) { - const network_info_t *network = get_network(); +static const char *get_network_name(e_net_type type) { + const network_info_t *network = get_network(type); if (network == NULL) { return NULL; } else { @@ -102,11 +112,27 @@ const char *get_network_name(void) { } } -const char *get_network_ticker(void) { - const network_info_t *network = get_network(); +const char *get_app_network_name(void) { + return get_network_name(APP); +} + +const char *get_tx_network_name(void) { + return get_network_name(TX); +} + +static const char *get_network_ticker(e_net_type type) { + const network_info_t *network = get_network(type); if (network == NULL) { return chainConfig->coinName; } else { return (char *) PIC(network->ticker); } } + +const char *get_app_network_ticker(void) { + return get_network_ticker(APP); +} + +const char *get_tx_network_ticker(void) { + return get_network_ticker(TX); +} \ No newline at end of file diff --git a/src_common/network.h b/src_common/network.h index b9ce7f3..e9069f5 100644 --- a/src_common/network.h +++ b/src_common/network.h @@ -11,13 +11,18 @@ typedef struct network_info_s { uint64_t chain_id; } network_info_t; -// Returns the current chain id. Defaults to 0 if txType was not found. -uint64_t get_chain_id(void); -// Returns a pointer to the network struct, or NULL if there is none. -const network_info_t *get_network(void); +// Returns the chain ID. Defaults to 0 if txType was not found (For TX). +uint64_t get_tx_chain_id(void); +uint64_t get_app_chain_id(void); +#ifdef HAVE_NBGL +const nbgl_icon_details_t *get_app_chain_icon(void); +#endif // HAVE_NBGL // Returns a pointer to the network name, or NULL if there is none. -const char *get_network_name(void); +const char *get_tx_network_name(void); +const char *get_app_network_name(void); + // Returns a pointer to the network ticker, or chainConfig->coinName if there is none. -const char *get_network_ticker(void); +const char *get_tx_network_ticker(void); +const char *get_app_network_ticker(void); #endif // _NETWORK_H_ diff --git a/src_features/signTx/logic_signTx.c b/src_features/signTx/logic_signTx.c index 199ccbb..c3074db 100644 --- a/src_features/signTx/logic_signTx.c +++ b/src_features/signTx/logic_signTx.c @@ -195,7 +195,7 @@ static void address_to_string(uint8_t *in, } static void raw_fee_to_string(uint256_t *rawFee, char *displayBuffer, uint32_t displayBufferSize) { - const char *feeTicker = get_network_ticker(); + const char *feeTicker = get_tx_network_ticker(); uint8_t tickerOffset = 0; uint32_t i; @@ -262,10 +262,10 @@ static void nonce_to_string(const txInt256_t *nonce, char *out, size_t out_size) } static void get_network_as_string(char *out, size_t out_size) { - const char *name = get_network_name(); + const char *name = get_tx_network_name(); if (name == NULL) { // No network name found so simply copy the chain ID as the network name. - uint64_t chain_id = get_chain_id(); + uint64_t chain_id = get_tx_chain_id(); u64_to_string(chain_id, out, out_size); } else { // Network name found, simply copy it. @@ -312,13 +312,13 @@ static int strcasecmp_workaround(const char *str1, const char *str2) { void finalizeParsing(bool direct) { char displayBuffer[50]; uint8_t decimals = WEI_TO_ETHER; - const char *ticker = get_network_ticker(); + const char *ticker = get_tx_network_ticker(); ethPluginFinalize_t pluginFinalize; bool use_standard_UI = true; // Verify the chain if (chainConfig->chainId != ETHEREUM_MAINNET_CHAINID) { - uint64_t id = get_chain_id(); + uint64_t id = get_tx_chain_id(); if (chainConfig->chainId != id) { PRINTF("Invalid chainID %u expected %u\n", id, chainConfig->chainId); From 0414a043c8e3f338528ffa897cd9b441d5e6cbde Mon Sep 17 00:00:00 2001 From: Clement Bouvet Date: Tue, 21 Feb 2023 11:15:20 +0100 Subject: [PATCH 06/25] rework plugin start so name and icon can be passed to eth --- src/chainConfig.h | 7 +++++++ src/main.c | 43 +++++++++++++++++++++++-------------------- src/shared_context.h | 2 ++ src/swap_lib_calls.h | 13 +++++++++++++ src_common/network.c | 13 ++++++++++++- 5 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/chainConfig.h b/src/chainConfig.h index 070de49..63a4324 100644 --- a/src/chainConfig.h +++ b/src/chainConfig.h @@ -77,10 +77,17 @@ typedef enum chain_kind_e { CHAIN_KIND_OASYS } chain_kind_t; +#ifdef HAVE_NBGL +#include "nbgl_types.h" +#endif // HAVE_NBGL + typedef struct chain_config_s { char coinName[10]; // ticker uint64_t chainId; chain_kind_t kind; +#ifdef HAVE_NBGL + nbgl_icon_details_t coinIconDetails; +#endif // HAVE_NBGL } chain_config_t; #define ETHEREUM_MAINNET_CHAINID 1 diff --git a/src/main.c b/src/main.c index 67442b0..7032183 100644 --- a/src/main.c +++ b/src/main.c @@ -69,7 +69,8 @@ bolos_ux_params_t G_ux_params; const internalStorage_t N_storage_real; -chain_config_t *chainConfig; +const char *plugin_name = NULL; +chain_config_t *chainConfig = NULL; void reset_app_context() { // PRINTF("!!RESET_APP_CONTEXT\n"); @@ -950,14 +951,19 @@ void init_coin_config(chain_config_t *coin_config) { coin_config->kind = CHAIN_KIND; } -void coin_main(chain_config_t *coin_config) { +void coin_main(libargs_t *args) { chain_config_t config; - if (coin_config == NULL) { + if (args) { + if (args->chain_config != NULL) { + chainConfig = args->chain_config; + } + plugin_name = args->plugin_name; + } + if (chainConfig == NULL) { init_coin_config(&config); chainConfig = &config; - } else { - chainConfig = coin_config; } + reset_app_context(); tmpCtx.transactionContext.currentItemIndex = 0; @@ -1031,18 +1037,7 @@ void coin_main(chain_config_t *coin_config) { app_exit(); } -struct libargs_s { - unsigned int id; - unsigned int command; - chain_config_t *chain_config; - union { - check_address_parameters_t *check_address; - create_transaction_parameters_t *create_transaction; - get_printable_amount_parameters_t *get_printable_amount; - }; -}; - -static void library_main_helper(struct libargs_s *args) { +static void library_main_helper(libargs_t *args) { check_api_level(CX_COMPAT_APILEVEL); PRINTF("Inside a library \n"); switch (args->command) { @@ -1070,7 +1065,7 @@ static void library_main_helper(struct libargs_s *args) { } } -void library_main(struct libargs_s *args) { +void library_main(libargs_t *args) { chain_config_t coin_config; if (args->chain_config == NULL) { init_coin_config(&coin_config); @@ -1102,6 +1097,13 @@ __attribute__((section(".boot"))) int main(int arg0) { unsigned int libcall_params[5]; chain_config_t local_chainConfig; init_coin_config(&local_chainConfig); +#ifdef HAVE_NBGL + uint8_t coinIcon[sizeof(ICONBITMAP)]; + memcpy(coinIcon, &ICONBITMAP, sizeof(ICONBITMAP)); + memcpy(&local_chainConfig.coinIconDetails, &ICONGLYPH, sizeof(ICONGLYPH)); + local_chainConfig.coinIconDetails.bitmap = coinIcon; +#endif // HAVE_NBGL + PRINTF("Hello from Eth-clone\n"); check_api_level(CX_COMPAT_APILEVEL); // delegate to Ethereum app/lib @@ -1110,6 +1112,7 @@ __attribute__((section(".boot"))) int main(int arg0) { libcall_params[2] = RUN_APPLICATION; libcall_params[3] = (unsigned int) &local_chainConfig; libcall_params[4] = 0; + if (arg0) { // call as a library libcall_params[2] = ((unsigned int *) arg0)[1]; @@ -1141,7 +1144,7 @@ __attribute__((section(".boot"))) int main(int arg0) { return 0; } - struct libargs_s *args = (struct libargs_s *) arg0; + libargs_t *args = (libargs_t *) arg0; if (args->id != 0x100) { app_exit(); return 0; @@ -1149,7 +1152,7 @@ __attribute__((section(".boot"))) int main(int arg0) { switch (args->command) { case RUN_APPLICATION: // called as ethereum from altcoin or plugin - coin_main(args->chain_config); + coin_main(args); break; default: // called as ethereum or altcoin library diff --git a/src/shared_context.h b/src/shared_context.h index ce907dd..e4d3c4d 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -229,6 +229,8 @@ extern bool quantumSet; extern uint32_t eth2WithdrawalIndex; #endif +extern const char *plugin_name; + void reset_app_context(void); const uint8_t *parseBip32(const uint8_t *dataBuffer, uint8_t *dataLength, bip32_path_t *bip32); diff --git a/src/swap_lib_calls.h b/src/swap_lib_calls.h index 9bdb115..1bca6c2 100644 --- a/src/swap_lib_calls.h +++ b/src/swap_lib_calls.h @@ -2,6 +2,7 @@ #define _SWAP_LIB_CALLS_H_ #include "stdbool.h" +#include "chainConfig.h" #define RUN_APPLICATION 1 @@ -52,4 +53,16 @@ typedef struct create_transaction_parameters_s { const char* const destination_address_extra_id; } create_transaction_parameters_t; +typedef struct libargs_s { + unsigned int id; + unsigned int command; + chain_config_t* chain_config; + union { + check_address_parameters_t* check_address; + create_transaction_parameters_t* create_transaction; + get_printable_amount_parameters_t* get_printable_amount; + char* plugin_name; + }; +} libargs_t; + #endif // _SWAP_LIB_CALLS_H_ diff --git a/src_common/network.c b/src_common/network.c index 1111134..7366179 100644 --- a/src_common/network.c +++ b/src_common/network.c @@ -135,4 +135,15 @@ const char *get_app_network_ticker(void) { const char *get_tx_network_ticker(void) { return get_network_ticker(TX); -} \ No newline at end of file +} + +#ifdef HAVE_NBGL +#include "glyphs.h" +const nbgl_icon_details_t *get_app_chain_icon(void) { + if (chainConfig->coinIconDetails.bitmap) { + return &chainConfig->coinIconDetails; // if called from a clone, the bitmap is correct + } else { + return &ICONGLYPH; // else, jsu return the ETH icon + } +} +#endif // HAVE_NBGL \ No newline at end of file From 8361e349b754e6296dd739ea1fa8ed8f0b4a81c7 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Mon, 20 Mar 2023 10:27:19 +0100 Subject: [PATCH 07/25] Now has a separate struct for caller app name & icon - New home screen wording - Removed duplicate RUN_APPLICATION macro --- src/chainConfig.h | 7 ---- src/eth_plugin_internal.h | 1 - src/main.c | 32 ++++++++++----- src/shared_context.h | 15 ++++++- src/swap_lib_calls.h | 3 +- src_common/network.c | 11 ------ src_common/network.h | 3 -- src_nbgl/ui_approve_tx.c | 6 +-- src_nbgl/ui_confirm_parameter.c | 4 +- src_nbgl/ui_confirm_selector.c | 4 +- src_nbgl/ui_display_privacy.c | 4 +- src_nbgl/ui_idle.c | 70 ++++++++++++++++----------------- src_nbgl/ui_nbgl.h | 6 ++- src_nbgl/ui_sign_712.c | 2 +- src_nbgl/ui_sign_712_v0.c | 2 +- src_nbgl/ui_stark_limit_order.c | 6 +-- src_nbgl/ui_stark_transfer.c | 4 +- src_nbgl/ui_stark_unsafe_sign.c | 6 +-- tools/build_sdk.py | 10 +++-- 19 files changed, 103 insertions(+), 93 deletions(-) diff --git a/src/chainConfig.h b/src/chainConfig.h index 63a4324..070de49 100644 --- a/src/chainConfig.h +++ b/src/chainConfig.h @@ -77,17 +77,10 @@ typedef enum chain_kind_e { CHAIN_KIND_OASYS } chain_kind_t; -#ifdef HAVE_NBGL -#include "nbgl_types.h" -#endif // HAVE_NBGL - typedef struct chain_config_s { char coinName[10]; // ticker uint64_t chainId; chain_kind_t kind; -#ifdef HAVE_NBGL - nbgl_icon_details_t coinIconDetails; -#endif // HAVE_NBGL } chain_config_t; #define ETHEREUM_MAINNET_CHAINID 1 diff --git a/src/eth_plugin_internal.h b/src/eth_plugin_internal.h index 692c9b6..2d2ca03 100644 --- a/src/eth_plugin_internal.h +++ b/src/eth_plugin_internal.h @@ -7,7 +7,6 @@ #define SELECTOR_SIZE 4 #define PARAMETER_LENGTH 32 -#define RUN_APPLICATION 1 void copy_address(uint8_t* dst, const uint8_t* parameter, uint8_t dst_size); diff --git a/src/main.c b/src/main.c index 7032183..36dbdf6 100644 --- a/src/main.c +++ b/src/main.c @@ -69,7 +69,7 @@ bolos_ux_params_t G_ux_params; const internalStorage_t N_storage_real; -const char *plugin_name = NULL; +caller_app_t *caller_app = NULL; chain_config_t *chainConfig = NULL; void reset_app_context() { @@ -957,7 +957,13 @@ void coin_main(libargs_t *args) { if (args->chain_config != NULL) { chainConfig = args->chain_config; } - plugin_name = args->plugin_name; + if ((caller_app = args->caller_app) != NULL) { + if (chainConfig != NULL) { + caller_app->type = CALLER_TYPE_CLONE; + } else { + caller_app->type = CALLER_TYPE_PLUGIN; + } + } } if (chainConfig == NULL) { init_coin_config(&config); @@ -1097,12 +1103,6 @@ __attribute__((section(".boot"))) int main(int arg0) { unsigned int libcall_params[5]; chain_config_t local_chainConfig; init_coin_config(&local_chainConfig); -#ifdef HAVE_NBGL - uint8_t coinIcon[sizeof(ICONBITMAP)]; - memcpy(coinIcon, &ICONBITMAP, sizeof(ICONBITMAP)); - memcpy(&local_chainConfig.coinIconDetails, &ICONGLYPH, sizeof(ICONGLYPH)); - local_chainConfig.coinIconDetails.bitmap = coinIcon; -#endif // HAVE_NBGL PRINTF("Hello from Eth-clone\n"); check_api_level(CX_COMPAT_APILEVEL); @@ -1111,7 +1111,21 @@ __attribute__((section(".boot"))) int main(int arg0) { libcall_params[1] = 0x100; libcall_params[2] = RUN_APPLICATION; libcall_params[3] = (unsigned int) &local_chainConfig; - libcall_params[4] = 0; +#ifdef HAVE_NBGL + const char app_name[] = APPNAME; + caller_app_t capp; + nbgl_icon_details_t icon_details; + uint8_t bitmap[sizeof(ICONBITMAP)]; + + memcpy(&icon_details, &ICONGLYPH, sizeof(ICONGLYPH)); + memcpy(&bitmap, &ICONBITMAP, sizeof(bitmap)); + icon_details.bitmap = (const uint8_t *) bitmap; + capp.name = app_name; + capp.icon = &icon_details; + libcall_params[4] = (unsigned int) &capp; +#else + libcall_params[4] = NULL; +#endif // HAVE_NBGL if (arg0) { // call as a library diff --git a/src/shared_context.h b/src/shared_context.h index e4d3c4d..c2fc66a 100644 --- a/src/shared_context.h +++ b/src/shared_context.h @@ -7,6 +7,9 @@ #include "tokens.h" #include "chainConfig.h" #include "nft.h" +#ifdef HAVE_NBGL +#include "nbgl_types.h" +#endif #define MAX_BIP32_PATH 10 @@ -221,6 +224,16 @@ typedef enum { extern pluginType_t pluginType; +typedef enum { CALLER_TYPE_CLONE, CALLER_TYPE_PLUGIN } e_caller_type; + +typedef struct caller_app_t { + const char *name; +#ifdef HAVE_NBGL + const nbgl_icon_details_t *icon; +#endif + char type; // does not have to be set by the caller app +} caller_app_t; + extern uint8_t appState; #ifdef HAVE_STARKWARE extern bool quantumSet; @@ -229,7 +242,7 @@ extern bool quantumSet; extern uint32_t eth2WithdrawalIndex; #endif -extern const char *plugin_name; +extern caller_app_t *caller_app; void reset_app_context(void); const uint8_t *parseBip32(const uint8_t *dataBuffer, uint8_t *dataLength, bip32_path_t *bip32); diff --git a/src/swap_lib_calls.h b/src/swap_lib_calls.h index 1bca6c2..4fd0284 100644 --- a/src/swap_lib_calls.h +++ b/src/swap_lib_calls.h @@ -3,6 +3,7 @@ #include "stdbool.h" #include "chainConfig.h" +#include "shared_context.h" #define RUN_APPLICATION 1 @@ -61,7 +62,7 @@ typedef struct libargs_s { check_address_parameters_t* check_address; create_transaction_parameters_t* create_transaction; get_printable_amount_parameters_t* get_printable_amount; - char* plugin_name; + caller_app_t* caller_app; }; } libargs_t; diff --git a/src_common/network.c b/src_common/network.c index 7366179..dbb8f6b 100644 --- a/src_common/network.c +++ b/src_common/network.c @@ -136,14 +136,3 @@ const char *get_app_network_ticker(void) { const char *get_tx_network_ticker(void) { return get_network_ticker(TX); } - -#ifdef HAVE_NBGL -#include "glyphs.h" -const nbgl_icon_details_t *get_app_chain_icon(void) { - if (chainConfig->coinIconDetails.bitmap) { - return &chainConfig->coinIconDetails; // if called from a clone, the bitmap is correct - } else { - return &ICONGLYPH; // else, jsu return the ETH icon - } -} -#endif // HAVE_NBGL \ No newline at end of file diff --git a/src_common/network.h b/src_common/network.h index e9069f5..a2ce262 100644 --- a/src_common/network.h +++ b/src_common/network.h @@ -14,9 +14,6 @@ typedef struct network_info_s { // Returns the chain ID. Defaults to 0 if txType was not found (For TX). uint64_t get_tx_chain_id(void); uint64_t get_app_chain_id(void); -#ifdef HAVE_NBGL -const nbgl_icon_details_t *get_app_chain_icon(void); -#endif // HAVE_NBGL // Returns a pointer to the network name, or NULL if there is none. const char *get_tx_network_name(void); const char *get_app_network_name(void); diff --git a/src_nbgl/ui_approve_tx.c b/src_nbgl/ui_approve_tx.c index e808cf2..eb872ac 100644 --- a/src_nbgl/ui_approve_tx.c +++ b/src_nbgl/ui_approve_tx.c @@ -188,7 +188,7 @@ static void reviewContinueCommon(void) { useCaseTagValueList.nbPairs = nbPairs; ///< number of pairs in pairs array useCaseTagValueList.smallCaseForValue = false; useCaseTagValueList.wrapping = false; - infoLongPress.icon = get_app_chain_icon(); + infoLongPress.icon = get_app_icon(true); infoLongPress.text = tx_approval_context.fromPlugin ? transaction_type : "Review transaction"; infoLongPress.longPressText = "Hold to sign"; nbgl_useCaseStaticReview(&useCaseTagValueList, @@ -204,14 +204,14 @@ static void buildFirstPage(void) { "Review %s\ntransaction:\n%s", strings.common.fullAddress, strings.common.fullAmount); - nbgl_useCaseReviewStart(get_app_chain_icon(), + nbgl_useCaseReviewStart(get_app_icon(true), transaction_type, NULL, "Reject transaction", reviewContinue, rejectTransactionQuestion); } else { - nbgl_useCaseReviewStart(get_app_chain_icon(), + nbgl_useCaseReviewStart(get_app_icon(true), "Review transaction", NULL, "Reject transaction", diff --git a/src_nbgl/ui_confirm_parameter.c b/src_nbgl/ui_confirm_parameter.c index 81d2a8a..bebe5ae 100644 --- a/src_nbgl/ui_confirm_parameter.c +++ b/src_nbgl/ui_confirm_parameter.c @@ -28,7 +28,7 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { content->tagValueList.nbPairs = 1; content->tagValueList.pairs = (nbgl_layoutTagValue_t *) &tlv; } else if (page == 1) { - content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); content->infoLongPress.text = "Confirm parameter"; content->infoLongPress.longPressText = "Hold to confirm"; } else { @@ -43,7 +43,7 @@ static void reviewContinue(void) { } static void buildScreen(void) { - nbgl_useCaseReviewStart(get_app_chain_icon(), + nbgl_useCaseReviewStart(get_app_icon(true), "Verify parameter", NULL, "Reject", diff --git a/src_nbgl/ui_confirm_selector.c b/src_nbgl/ui_confirm_selector.c index 3bf5a11..c268d28 100644 --- a/src_nbgl/ui_confirm_selector.c +++ b/src_nbgl/ui_confirm_selector.c @@ -28,7 +28,7 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { content->tagValueList.nbPairs = 1; content->tagValueList.pairs = (nbgl_layoutTagValue_t *) &tlv; } else if (page == 1) { - content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); content->infoLongPress.text = "Confirm selector"; content->infoLongPress.longPressText = "Hold to confirm"; } else { @@ -43,7 +43,7 @@ static void reviewContinue(void) { } static void buildScreen(void) { - nbgl_useCaseReviewStart(get_app_chain_icon(), + nbgl_useCaseReviewStart(get_app_icon(true), "Verify selector", NULL, "Reject", diff --git a/src_nbgl/ui_display_privacy.c b/src_nbgl/ui_display_privacy.c index b4a9d1c..d2b2841 100644 --- a/src_nbgl/ui_display_privacy.c +++ b/src_nbgl/ui_display_privacy.c @@ -34,7 +34,7 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { content->tagValueList.nbPairs = 2; content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; } else if (page == 1) { - content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); content->infoLongPress.text = review_string; content->infoLongPress.longPressText = "Hold to approve"; } else { @@ -49,7 +49,7 @@ static void reviewContinue(void) { } static void buildFirstPage(void) { - nbgl_useCaseReviewStart(get_app_chain_icon(), + nbgl_useCaseReviewStart(get_app_icon(true), review_string, NULL, "Reject", diff --git a/src_nbgl/ui_idle.c b/src_nbgl/ui_idle.c index 7e02101..b14ca9b 100644 --- a/src_nbgl/ui_idle.c +++ b/src_nbgl/ui_idle.c @@ -5,9 +5,10 @@ #include "glyphs.h" #include "network.h" -uint8_t staxSharedBuffer[SHARED_BUFFER_SIZE] = {0}; +char staxSharedBuffer[SHARED_BUFFER_SIZE] = {0}; +nbgl_page_t *pageContext; -nbgl_page_t* pageContext; +#define FORMAT_PLUGIN "This app enables clear\nsigning transactions for\nthe %s dApp." void releaseContext(void) { if (pageContext != NULL) { @@ -15,47 +16,44 @@ void releaseContext(void) { pageContext = NULL; } } -enum { BACK_TOKEN = 0, INFO_TOKEN, NEXT_TOKEN, CANCEL_TOKEN, QUIT_INFO_TOKEN, QUIT_APP_TOKEN }; void app_quit(void) { // exit app here os_sched_exit(-1); } -void ui_idle(void) { - if (plugin_name != NULL) { // plugin - nbgl_useCasePlugInHome((char*) plugin_name, - APPNAME, - &ICONGLYPH_SMALL, - NULL, - NULL, - true, - ui_menu_settings, - app_quit); - } else { - char* app_name = (char*) get_app_network_name(); +const nbgl_icon_details_t *get_app_icon(bool caller_icon) { + const nbgl_icon_details_t *icon = NULL; - switch (get_app_chain_id()) { - // Standalone apps - case 1: // Mainnet - case 3: // Ropsten - case 5: // Goerli - nbgl_useCaseHome(app_name, - get_app_chain_icon(), - NULL, - true, - ui_menu_settings, - app_quit); - break; - // Clones - default: - nbgl_useCaseHome(app_name, - get_app_chain_icon(), - NULL, - true, - ui_menu_settings, - app_quit); - break; + if (caller_icon && caller_app) { + if (caller_app->icon) { + icon = caller_app->icon; } + } else { + icon = &ICONGLYPH; } + return icon; +} + +void ui_idle(void) { + const char *app_name = NULL; + const char *tagline = NULL; + + if (caller_app) { + app_name = caller_app->name; + + if (caller_app->type == CALLER_TYPE_PLUGIN) { + snprintf(staxSharedBuffer, sizeof(staxSharedBuffer), FORMAT_PLUGIN, app_name); + tagline = staxSharedBuffer; + } + } else { // Ethereum app + app_name = get_app_network_name(); + } + + nbgl_useCaseHome((char *) app_name, + get_app_icon(true), + tagline, + true, + ui_menu_settings, + app_quit); } diff --git a/src_nbgl/ui_nbgl.h b/src_nbgl/ui_nbgl.h index 66ffd4f..d7db175 100644 --- a/src_nbgl/ui_nbgl.h +++ b/src_nbgl/ui_nbgl.h @@ -6,14 +6,16 @@ #include #define SHARED_BUFFER_SIZE SHARED_CTX_FIELD_1_SIZE -extern uint8_t staxSharedBuffer[SHARED_BUFFER_SIZE]; +extern char staxSharedBuffer[SHARED_BUFFER_SIZE]; extern nbgl_page_t* pageContext; void releaseContext(void); +const nbgl_icon_details_t* get_app_icon(bool caller_icon); + void ui_idle(void); void ui_menu_settings(void); void ui_menu_about(void); -#endif // _UI_NBGL_H_ \ No newline at end of file +#endif // _UI_NBGL_H_ diff --git a/src_nbgl/ui_sign_712.c b/src_nbgl/ui_sign_712.c index c13a78a..ab40a9e 100644 --- a/src_nbgl/ui_sign_712.c +++ b/src_nbgl/ui_sign_712.c @@ -25,7 +25,7 @@ static void reviewChoice(bool confirm) { } static bool displaySignPage(uint8_t page, nbgl_pageContent_t *content) { (void) page; - content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); content->infoLongPress.text = "Sign typed message"; content->infoLongPress.longPressText = "Hold to sign"; return true; diff --git a/src_nbgl/ui_sign_712_v0.c b/src_nbgl/ui_sign_712_v0.c index 34b529c..df9a547 100644 --- a/src_nbgl/ui_sign_712_v0.c +++ b/src_nbgl/ui_sign_712_v0.c @@ -39,7 +39,7 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { content->tagValueList.nbPairs = 2; content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; } else if (page == 1) { - content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); content->infoLongPress.text = "Sign typed message"; content->infoLongPress.longPressText = "Hold to sign"; } else { diff --git a/src_nbgl/ui_stark_limit_order.c b/src_nbgl/ui_stark_limit_order.c index 20277be..1270706 100644 --- a/src_nbgl/ui_stark_limit_order.c +++ b/src_nbgl/ui_stark_limit_order.c @@ -37,7 +37,7 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { content->tagValueList.nbPairs = 3; content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; } else if (page == 1) { - content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(false); content->infoLongPress.text = "Review stark limit order"; content->infoLongPress.longPressText = "Hold to sign"; } else { @@ -52,7 +52,7 @@ static void reviewContinue(void) { } static void buildFirstPage(void) { - nbgl_useCaseReviewStart(get_app_chain_icon(), + nbgl_useCaseReviewStart(get_app_icon(false), "Review stark limit order", NULL, "Reject", @@ -64,4 +64,4 @@ void ui_stark_limit_order(void) { buildFirstPage(); } -#endif \ No newline at end of file +#endif diff --git a/src_nbgl/ui_stark_transfer.c b/src_nbgl/ui_stark_transfer.c index 3532c17..463b835 100644 --- a/src_nbgl/ui_stark_transfer.c +++ b/src_nbgl/ui_stark_transfer.c @@ -82,7 +82,7 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { } } if (page == 2) { - content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(false); content->infoLongPress.text = "Review transaction"; content->infoLongPress.longPressText = "Hold to sign"; } @@ -116,7 +116,7 @@ void ui_stark_transfer(bool selfTransfer, bool conditional) { subTitle = "Transfer"; } } - nbgl_useCaseReviewStart(get_app_chain_icon(), + nbgl_useCaseReviewStart(get_app_icon(false), "Review stark transaction", subTitle, "Reject", diff --git a/src_nbgl/ui_stark_unsafe_sign.c b/src_nbgl/ui_stark_unsafe_sign.c index 59a6eac..05bf256 100644 --- a/src_nbgl/ui_stark_unsafe_sign.c +++ b/src_nbgl/ui_stark_unsafe_sign.c @@ -40,7 +40,7 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { content->tagValueList.nbPairs = 2; content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; } else if (page == 1) { - content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_chain_icon(); + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(false); content->infoLongPress.text = "Unsafe Stark Sign"; content->infoLongPress.longPressText = "Hold to sign"; } else { @@ -55,7 +55,7 @@ static void reviewContinue(void) { } static void buildFirstPage(void) { - nbgl_useCaseReviewStart(get_app_chain_icon(), + nbgl_useCaseReviewStart(get_app_icon(false), "Unsafe Stark Sign", NULL, "Reject", @@ -67,4 +67,4 @@ void ui_stark_unsafe_sign(void) { buildFirstPage(); } -#endif // HAVE_STARKWARE \ No newline at end of file +#endif // HAVE_STARKWARE diff --git a/tools/build_sdk.py b/tools/build_sdk.py index a808e4a..552bb25 100755 --- a/tools/build_sdk.py +++ b/tools/build_sdk.py @@ -82,10 +82,13 @@ def extract_from_c_files(sources, nodes_to_extract): def merge_headers(sources, nodes_to_extract): includes = [ + '#include ', + '#include ', '#include "os.h"', '#include "cx.h"', - '#include ', - '#include ' + '#ifdef HAVE_NBGL', + '#include "nbgl_types.h"', + '#endif' ] body = extract_from_headers(sources, nodes_to_extract) @@ -156,11 +159,12 @@ if __name__ == "__main__": "src/shared_context.h", "src/eth_plugin_internal.h", "src/nft.h", + "src/swap_lib_calls.h" ] nodes_to_extract = { "#define": ["MAX_TICKER_LEN", "ADDRESS_LENGTH", "INT256_LENGTH", "WEI_TO_ETHER", "SELECTOR_SIZE", "PARAMETER_LENGTH", "RUN_APPLICATION", "COLLECTION_NAME_MAX_LEN"], "typedef enum": [], - "typedef struct": ["tokenDefinition_t", "txInt256_t", "txContent_t", "nftInfo_t"], + "typedef struct": ["tokenDefinition_t", "txInt256_t", "txContent_t", "nftInfo_t", "caller_app_t"], "typedef union": ["extraInfo_t"], "__attribute__((no_instrument_function)) inline": ["int allzeroes"], "const": ["HEXDIGITS"], From 6326a4a9f205a35d41c4ff7ad40f940fb3a94014 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Tue, 14 Mar 2023 18:47:50 +0100 Subject: [PATCH 08/25] EIP-191 fixes Skip button did not work --- src_nbgl/ui_sign_message.c | 130 ++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 54 deletions(-) diff --git a/src_nbgl/ui_sign_message.c b/src_nbgl/ui_sign_message.c index 7bcf541..587bb68 100644 --- a/src_nbgl/ui_sign_message.c +++ b/src_nbgl/ui_sign_message.c @@ -17,6 +17,7 @@ typedef enum { static e_ui_nbgl_191_state state; static e_ui_nbgl_191_state state_before_reject_cancel; +static bool skip_message; static nbgl_layoutTagValue_t pair; @@ -28,72 +29,89 @@ static void reject_message(void) { io_seproxyhal_touch_signMessage_cancel(); } -static void sign_message() { +static void sign_message(void) { io_seproxyhal_touch_signMessage_ok(); } -static bool nav_callback(uint8_t page, nbgl_pageContent_t *content) { - UNUSED(page); +static bool display_message(nbgl_pageContent_t *content) { + uint16_t len = 0; + bool reached; - if ((state != UI_191_NBGL_GO_TO_SIGN) && (state != UI_191_NBGL_SIGN_DISPLAYED)) { - if (state != UI_191_NBGL_BACK_FROM_REJECT_CANCEL) { - memset(staxSharedBuffer + eip191MessageIdx, 0, SHARED_BUFFER_SIZE - eip191MessageIdx); - memcpy( - staxSharedBuffer + eip191MessageIdx, + if (state != UI_191_NBGL_BACK_FROM_REJECT_CANCEL) { + strncpy(staxSharedBuffer + eip191MessageIdx, strings.tmp.tmp + stringsTmpTmpIdx, - MIN(SHARED_BUFFER_SIZE - eip191MessageIdx, SHARED_BUFFER_SIZE - stringsTmpTmpIdx)); - uint16_t len = 0; - bool reached = nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_32px, - staxSharedBuffer, - SCREEN_WIDTH - (2 * BORDER_MARGIN), - 9, - &len); + SHARED_BUFFER_SIZE - eip191MessageIdx); + reached = nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_32px, + (char *) staxSharedBuffer, + SCREEN_WIDTH - (2 * BORDER_MARGIN), + 9, + &len); - stringsTmpTmpIdx = len - eip191MessageIdx; - eip191MessageIdx = len; - staxSharedBuffer[eip191MessageIdx] = '\0'; + stringsTmpTmpIdx = len - eip191MessageIdx; + eip191MessageIdx = len; + staxSharedBuffer[eip191MessageIdx] = '\0'; - if (!reached && eip191MessageIdx < SHARED_BUFFER_SIZE) { - stringsTmpTmpIdx = 0; - question_switcher(); - - if (state != UI_191_NBGL_GO_TO_SIGN) { - return false; - } - } else if (reached || eip191MessageIdx == SHARED_BUFFER_SIZE) { - eip191MessageIdx = 0; - } - } - - pair.value = staxSharedBuffer; - pair.item = "Message"; - content->type = TAG_VALUE_LIST; - content->tagValueList.nbPairs = 1; - content->tagValueList.pairs = &pair; - content->tagValueList.smallCaseForValue = false; - content->tagValueList.nbMaxLinesForValue = 9; - content->tagValueList.wrapping = false; - - if (state == UI_191_NBGL_BACK_FROM_REJECT_CANCEL) { - // We come back from Reject screen. - // The previously displayed content must be redisplayed. - // Do not call question_switcher() to avoid replacing - // string.tmp.tmp content. - state = state_before_reject_cancel; - } else if (stringsTmpTmpIdx >= strlen(strings.tmp.tmp)) { - // Fetch the next content to display into strings.tmp.tmp buffer. + if (!reached && eip191MessageIdx < SHARED_BUFFER_SIZE) { stringsTmpTmpIdx = 0; question_switcher(); - return true; + + if (state != UI_191_NBGL_GO_TO_SIGN) { + return false; + } + } else if (reached || eip191MessageIdx == SHARED_BUFFER_SIZE) { + eip191MessageIdx = 0; + } + } + + pair.value = staxSharedBuffer; + pair.item = "Message"; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 1; + content->tagValueList.pairs = &pair; + content->tagValueList.smallCaseForValue = false; + content->tagValueList.nbMaxLinesForValue = 9; + content->tagValueList.wrapping = false; + + if (state == UI_191_NBGL_BACK_FROM_REJECT_CANCEL) { + // We come back from Reject screen. + // The previously displayed content must be redisplayed. + // Do not call question_switcher() to avoid replacing + // string.tmp.tmp content. + state = state_before_reject_cancel; + } else if (stringsTmpTmpIdx >= strlen(strings.tmp.tmp)) { + // Fetch the next content to display into strings.tmp.tmp buffer. + stringsTmpTmpIdx = 0; + question_switcher(); + } + return true; +} + +static void display_sign(nbgl_pageContent_t *content) { + content->type = INFO_LONG_PRESS, content->infoLongPress.icon = &C_Message_64px; + content->infoLongPress.text = "Sign Message?"; + content->infoLongPress.longPressText = "Hold to sign"; + state = UI_191_NBGL_SIGN_DISPLAYED; +} + +static bool nav_callback(uint8_t page, nbgl_pageContent_t *content) { + bool ret = true; + + if (page == LAST_PAGE_FOR_REVIEW) { // was skipped + skip_message = true; + skip_rest_of_message(); + } + if ((state != UI_191_NBGL_GO_TO_SIGN) && (state != UI_191_NBGL_SIGN_DISPLAYED)) { + if (skip_message) { + // do not refresh when this callback triggers after user validation + ret = false; + } else { + ret = display_message(content); } } else { // the last page must contain a long press button - content->type = INFO_LONG_PRESS, content->infoLongPress.icon = &C_Message_64px; - content->infoLongPress.text = "Sign Message?"; - content->infoLongPress.longPressText = "Hold to sign"; - state = UI_191_NBGL_SIGN_DISPLAYED; + display_sign(content); } - return true; + return ret; } static void choice_callback(bool confirm) { @@ -135,6 +153,7 @@ static void confirm_transaction_rejection() { void ui_191_start(void) { state = UI_191_NBGL_START_REVIEW_DISPLAYED; + skip_message = false; eip191MessageIdx = 0; stringsTmpTmpIdx = 0; @@ -157,10 +176,13 @@ void ui_191_switch_to_sign(void) { // Next nav_callback callback must display // the hold to approve screen state = UI_191_NBGL_GO_TO_SIGN; + if (skip_message) { + continue_review(); // to force screen refresh + } } void ui_191_switch_to_question(void) { // No question mechanism on Stax: // Always display the next message chunk. continue_displaying_message(); -} \ No newline at end of file +} From 8881471a8e567cf1d76182826d757965c9a48278 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Thu, 16 Mar 2023 18:16:35 +0100 Subject: [PATCH 09/25] EIP-712 fixes - Now displays a Review page before showing the fields - Now asks for confirmation before rejecting - Now does not refresh the screen twice after a signature approval/rejection - Both EIP-712 implementations on par UX-wise - Fixed v0 approve/reject status word mismatch - Unified NBGL UI of both implementations --- src_features/signMessageEIP712/context_712.c | 1 - src_nbgl/ui_712_common.c | 48 +++++++++ src_nbgl/ui_712_common.h | 13 +++ src_nbgl/ui_sign_712.c | 108 +++++++++---------- src_nbgl/ui_sign_712_v0.c | 53 ++++----- 5 files changed, 134 insertions(+), 89 deletions(-) create mode 100644 src_nbgl/ui_712_common.c create mode 100644 src_nbgl/ui_712_common.h diff --git a/src_features/signMessageEIP712/context_712.c b/src_features/signMessageEIP712/context_712.c index 82abd09..57d5be6 100644 --- a/src_features/signMessageEIP712/context_712.c +++ b/src_features/signMessageEIP712/context_712.c @@ -72,7 +72,6 @@ void eip712_context_deinit(void) { mem_reset(); eip712_context = NULL; reset_app_context(); - ui_idle(); } #endif diff --git a/src_nbgl/ui_712_common.c b/src_nbgl/ui_712_common.c new file mode 100644 index 0000000..a1b13e3 --- /dev/null +++ b/src_nbgl/ui_712_common.c @@ -0,0 +1,48 @@ +#include "ui_nbgl.h" +#include "ui_712_common.h" +#include "common_712.h" + +static void (*g_resume_func)(void) = NULL; + +void nbgl_712_review_approve(void) { + ui_712_approve_cb(NULL); +} + +void nbgl_712_review_reject(void) { + ui_712_reject_cb(NULL); +} + +void nbgl_712_confirm_rejection_cb(bool confirm) { + if (confirm) { + nbgl_useCaseStatus("Message signing\ncancelled", false, nbgl_712_review_reject); + } else { + (*g_resume_func)(); + } +} + +void nbgl_712_confirm_rejection(void) { + nbgl_useCaseChoice(&C_warning64px, + "Reject message?", + NULL, + "Yes, reject", + "Go back to message", + nbgl_712_confirm_rejection_cb); +} + +void nbgl_712_review_choice(bool confirm) { + if (confirm) { + nbgl_useCaseStatus("MESSAGE\nSIGNED", true, nbgl_712_review_approve); + } else { + nbgl_712_confirm_rejection(); + } +} + +void nbgl_712_start(void (*resume_func)(void), const char *title) { + g_resume_func = resume_func; + nbgl_useCaseReviewStart(&C_Message_64px, + title, + NULL, + "Reject", + resume_func, + nbgl_712_confirm_rejection); +} diff --git a/src_nbgl/ui_712_common.h b/src_nbgl/ui_712_common.h new file mode 100644 index 0000000..ab8bd4f --- /dev/null +++ b/src_nbgl/ui_712_common.h @@ -0,0 +1,13 @@ +#ifndef UI_712_COMMON_H_ +#define UI_712_COMMON_H_ + +#include + +void nbgl_712_approve(void); +void nbgl_712_reject(void); +void nbgl_712_confirm_rejection_cb(bool confirm); +void nbgl_712_confirm_rejection(void); +void nbgl_712_review_choice(bool confirm); +void nbgl_712_start(void (*resume_func)(void), const char *title); + +#endif // UI_712_COMMON_H_ diff --git a/src_nbgl/ui_sign_712.c b/src_nbgl/ui_sign_712.c index ab40a9e..094fdb6 100644 --- a/src_nbgl/ui_sign_712.c +++ b/src_nbgl/ui_sign_712.c @@ -1,29 +1,16 @@ +#ifdef HAVE_EIP712_FULL_SUPPORT + #include "common_ui.h" #include "ui_nbgl.h" #include "ui_logic.h" #include "common_712.h" #include "nbgl_use_case.h" #include "network.h" +#include "ui_712_common.h" -// 4 pairs of tag/value to display -static nbgl_layoutTagValue_t tlv; +static nbgl_layoutTagValue_t pair; -static void reject_message(void) { - ui_712_reject(NULL); -} - -static void sign_message() { - ui_712_approve(NULL); -} - -static void reviewChoice(bool confirm) { - if (confirm) { - sign_message(); - } else { - reject_message(); - } -} -static bool displaySignPage(uint8_t page, nbgl_pageContent_t *content) { +static bool display_sign_page(uint8_t page, nbgl_pageContent_t *content) { (void) page; content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); content->infoLongPress.text = "Sign typed message"; @@ -31,50 +18,63 @@ static bool displaySignPage(uint8_t page, nbgl_pageContent_t *content) { return true; } -static uint32_t stringsIdx = 0; +static bool display_review_page(uint8_t page, nbgl_pageContent_t *content) { + bool ret; + uint16_t len; -static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { - uint16_t len = 0; - if (stringsIdx < strlen(strings.tmp.tmp)) { - bool reached = nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_32px, - strings.tmp.tmp + stringsIdx, - SCREEN_WIDTH - (2 * BORDER_MARGIN), - 9, - &len); - memset(staxSharedBuffer, 0, sizeof(staxSharedBuffer)); - memcpy(staxSharedBuffer, strings.tmp.tmp + stringsIdx, len); - stringsIdx += len; - tlv.item = strings.tmp.tmp2; - tlv.value = staxSharedBuffer; - content->type = TAG_VALUE_LIST; - content->tagValueList.nbPairs = 1; - content->tagValueList.pairs = &tlv; - return true; - } else { - stringsIdx = 0; - switch (ui_712_next_field()) { - case EIP712_NO_MORE_FIELD: - return displaySignPage(page, content); - break; - case EIP712_FIELD_INCOMING: - case EIP712_FIELD_LATER: - default: - break; - } - return false; + switch (page) { + case 0: + // limit the value to one page + nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_32px, + strings.tmp.tmp, + SCREEN_WIDTH - (2 * BORDER_MARGIN), + 9, + &len); + strings.tmp.tmp[len] = '\0'; + + pair.item = strings.tmp.tmp2; + pair.value = strings.tmp.tmp; + content->type = TAG_VALUE_LIST; + content->tagValueList.nbPairs = 1; + content->tagValueList.pairs = &pair; + content->tagValueList.wrapping = false; + content->tagValueList.nbMaxLinesForValue = 0; + ret = true; + break; + + case 1: + switch (ui_712_next_field()) { + case EIP712_NO_MORE_FIELD: + return display_sign_page(page, content); + break; + case EIP712_FIELD_INCOMING: + case EIP712_FIELD_LATER: + default: + break; + } + __attribute__((fallthrough)); + + default: + ret = false; + break; } + return ret; } -void ui_712_switch_to_sign(void) { - nbgl_useCaseRegularReview(0, 0, "Reject", NULL, displaySignPage, reviewChoice); +static void handle_display(nbgl_navCallback_t cb) { + nbgl_useCaseRegularReview(0, 0, "Reject", NULL, cb, nbgl_712_review_choice); } void ui_712_start(void) { - stringsIdx = 0; - nbgl_useCaseRegularReview(0, 0, "Reject", NULL, displayTransactionPage, reviewChoice); + nbgl_712_start(&ui_712_switch_to_message, "Review typed message"); } void ui_712_switch_to_message(void) { - stringsIdx = 0; - nbgl_useCaseRegularReview(0, 0, "Reject", NULL, displayTransactionPage, reviewChoice); + handle_display(display_review_page); } + +void ui_712_switch_to_sign(void) { + handle_display(display_sign_page); +} + +#endif // HAVE_EIP712_FULL_SUPPORT diff --git a/src_nbgl/ui_sign_712_v0.c b/src_nbgl/ui_sign_712_v0.c index df9a547..feca3bf 100644 --- a/src_nbgl/ui_sign_712_v0.c +++ b/src_nbgl/ui_sign_712_v0.c @@ -2,41 +2,34 @@ #include "ui_nbgl.h" #include "common_712.h" #include "network.h" +#include "ethUtils.h" +#include "ui_712_common.h" static nbgl_layoutTagValue_t tlv[2]; -static char domain_hash[70]; -static char message_hash[70]; +static void start_review(void); // forward declaration -static void reviewReject(void) { - ui_712_approve_cb(NULL); +static char *format_hash(const uint8_t *hash, char *buffer, size_t buffer_size, size_t offset) { + snprintf(buffer + offset, buffer_size - offset, "0x%.*H", KECCAK256_HASH_BYTESIZE, hash); + return buffer + offset; } -static void confirmTransation(void) { - ui_712_reject_cb(NULL); -} - -static void reviewChoice(bool confirm) { - if (confirm) { - // display a status page and go back to main - nbgl_useCaseStatus("MESSAGE\nSIGNED", true, confirmTransation); - } else { - nbgl_useCaseStatus("Message signing\ncancelled", false, reviewReject); - } -} - -static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { - snprintf(domain_hash, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.domainHash); - snprintf(message_hash, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.messageHash); - +static bool display_review_page(uint8_t page, nbgl_pageContent_t *content) { if (page == 0) { tlv[0].item = "Domain hash"; - tlv[0].value = domain_hash; + tlv[0].value = format_hash(tmpCtx.messageSigningContext712.domainHash, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + 0); tlv[1].item = "Message hash"; - tlv[1].value = message_hash; + tlv[1].value = format_hash(tmpCtx.messageSigningContext712.messageHash, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + 70); content->type = TAG_VALUE_LIST; content->tagValueList.nbPairs = 2; + content->tagValueList.nbMaxLinesForValue = 0; content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; } else if (page == 1) { content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); @@ -48,19 +41,11 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { // valid page so return true return true; } -static void reviewContinue(void) { - nbgl_useCaseRegularReview(0, 2, "Reject", NULL, displayTransactionPage, reviewChoice); -} -static void buildFirstPage(void) { - nbgl_useCaseReviewStart(get_app_chain_icon(), - "Sign typed message", - NULL, - "Reject", - reviewContinue, - reviewReject); +static void start_review(void) { + nbgl_useCaseRegularReview(0, 2, "Reject", NULL, display_review_page, nbgl_712_review_choice); } void ui_sign_712_v0(void) { - buildFirstPage(); + nbgl_712_start(&start_review, "Sign typed message"); } From 3810cbd852f301a511eb08e3d253b00dcd413295 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Tue, 21 Mar 2023 11:55:51 +0100 Subject: [PATCH 10/25] Fix Makefile configuration - Removed DEBUG enabled by default - Removed optimization & debug levels and use ones from SDK - Disable PRINTF formatting warnings again (for the custom %.*H format) --- Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 025a00d..2ed9286 100644 --- a/Makefile +++ b/Makefile @@ -186,7 +186,6 @@ endif endif # Enabling debug PRINTF -DEBUG:=1 ifneq ($(DEBUG),0) DEFINES += HAVE_STACK_OVERFLOW_CHECK ifeq ($(TARGET_NAME),TARGET_NANOS) @@ -223,13 +222,11 @@ endif CC := $(CLANGPATH)clang -CFLAGS += -Og -g -# CFLAGS += -Oz -Wno-format-invalid-specifier -Wno-format-extra-args +CFLAGS += -Wno-format-invalid-specifier -Wno-format-extra-args AS := $(GCCPATH)arm-none-eabi-gcc LD := $(GCCPATH)arm-none-eabi-gcc -LDFLAGS += -O0 LDLIBS += -lm -lgcc -lc # import rules to compile glyphs(/pone) From 4cce06ca2cc76a1e75116ed8ff78b3166f33e6e2 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Tue, 4 Apr 2023 17:12:58 +0200 Subject: [PATCH 11/25] Fix compilation warnings --- src/main.c | 2 +- src_nbgl/ui_display_privacy.c | 4 ++-- src_nbgl/ui_stark_transfer.c | 8 ++++---- src_plugins/eth2/eth2_plugin.c | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main.c b/src/main.c index 36dbdf6..08113ae 100644 --- a/src/main.c +++ b/src/main.c @@ -905,7 +905,7 @@ unsigned char io_event(__attribute__((unused)) unsigned char channel) { SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) { THROW(EXCEPTION_IO_RESET); } - // no break is intentional + __attribute__((fallthrough)); default: UX_DEFAULT_EVENT(); break; diff --git a/src_nbgl/ui_display_privacy.c b/src_nbgl/ui_display_privacy.c index d2b2841..3e52d5f 100644 --- a/src_nbgl/ui_display_privacy.c +++ b/src_nbgl/ui_display_privacy.c @@ -58,11 +58,11 @@ static void buildFirstPage(void) { } void ui_display_privacy_public_key(void) { - review_string = "Provide public\nprivacy key"; + review_string = (char *) "Provide public\nprivacy key"; buildFirstPage(); } void ui_display_privacy_shared_secret(void) { - review_string = "Provide public\nsecret key"; + review_string = (char *) "Provide public\nsecret key"; buildFirstPage(); } diff --git a/src_nbgl/ui_stark_transfer.c b/src_nbgl/ui_stark_transfer.c index 463b835..99726f3 100644 --- a/src_nbgl/ui_stark_transfer.c +++ b/src_nbgl/ui_stark_transfer.c @@ -105,15 +105,15 @@ void ui_stark_transfer(bool selfTransfer, bool conditional) { char *subTitle; if (conditional) { if (selfTransfer) { - subTitle = "Conditionnal self transfer"; + subTitle = (char *) "Conditionnal self transfer"; } else { - subTitle = "Conditionnal transfer"; + subTitle = (char *) "Conditionnal transfer"; } } else { if (selfTransfer) { - subTitle = "self transfer"; + subTitle = (char *) "self transfer"; } else { - subTitle = "Transfer"; + subTitle = (char *) "Transfer"; } } nbgl_useCaseReviewStart(get_app_icon(false), diff --git a/src_plugins/eth2/eth2_plugin.c b/src_plugins/eth2/eth2_plugin.c index 29ea299..c93c82e 100644 --- a/src_plugins/eth2/eth2_plugin.c +++ b/src_plugins/eth2/eth2_plugin.c @@ -212,7 +212,7 @@ void eth2_plugin_call(int message, void *parameters) { strlcpy(msg->title, "Validator", msg->titleLength); strlcpy(msg->msg, context->deposit_address, msg->msgLength); msg->result = ETH_PLUGIN_RESULT_OK; - } + } break; default: break; } From cb7334ceede9e1f098cc9d6bb03ea46cdde5e8f5 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Tue, 4 Apr 2023 17:50:40 +0200 Subject: [PATCH 12/25] Fix settings word split --- src_nbgl/ui_settings.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src_nbgl/ui_settings.c b/src_nbgl/ui_settings.c index 482d220..4ca3f3e 100644 --- a/src_nbgl/ui_settings.c +++ b/src_nbgl/ui_settings.c @@ -15,13 +15,13 @@ static bool navCallback(uint8_t page, nbgl_pageContent_t* content) { switches[0] = (nbgl_layoutSwitch_t){.initState = N_storage.dataAllowed ? ON_STATE : OFF_STATE, .text = "Blind signing", - .subText = "Enable transaction blind signing", + .subText = "Enable transaction blind\nsigning", .token = BLIND_SIGNING_TOKEN, .tuneId = TUNE_TAP_CASUAL}; switches[1] = (nbgl_layoutSwitch_t){.initState = N_storage.contractDetails ? ON_STATE : OFF_STATE, .text = "Debug", - .subText = "Display contract data details", + .subText = "Display contract data\ndetails", .token = DEBUG_TOKEN, .tuneId = TUNE_TAP_CASUAL}; switches[2] = From e0bb1225fe67fc2bc8b2e22b3b21692eb40a8f2d Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Fri, 7 Apr 2023 11:29:27 +0200 Subject: [PATCH 13/25] Unified nbgl layoutTagValue variable naming --- src_nbgl/ui_approve_tx.c | 36 ++++++++++++++++----------------- src_nbgl/ui_display_privacy.c | 12 +++++------ src_nbgl/ui_settings.c | 2 +- src_nbgl/ui_sign_712_v0.c | 24 +++++++++++----------- src_nbgl/ui_stark_limit_order.c | 16 +++++++-------- src_nbgl/ui_stark_transfer.c | 30 +++++++++++++-------------- src_nbgl/ui_stark_unsafe_sign.c | 12 +++++------ 7 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src_nbgl/ui_approve_tx.c b/src_nbgl/ui_approve_tx.c index eb872ac..78c9d81 100644 --- a/src_nbgl/ui_approve_tx.c +++ b/src_nbgl/ui_approve_tx.c @@ -15,7 +15,7 @@ enum { START_REVIEW_TOKEN, }; -static nbgl_layoutTagValue_t tlv; +static nbgl_layoutTagValue_t pair; // these buffers are used as circular static char title_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][TAG_MAX_LEN]; static char msg_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][VALUE_MAX_LEN]; @@ -74,17 +74,17 @@ static nbgl_layoutTagValue_t *getTagValuePair(uint8_t pairIndex) { TAG_MAX_LEN, (uint8_t *) msg_buffer[counter], VALUE_MAX_LEN); - tlv.item = title_buffer[counter]; - tlv.value = msg_buffer[counter]; + pair.item = title_buffer[counter]; + pair.value = msg_buffer[counter]; } else { pairIndex -= dataContext.tokenContext.pluginUiMaxItems; // for the last 1 (or 2), tags are fixed if (tx_approval_context.displayNetwork && (pairIndex == 0)) { - tlv.item = "Network"; - tlv.value = strings.common.network_name; + pair.item = "Network"; + pair.value = strings.common.network_name; } else { - tlv.item = "Max fees"; - tlv.value = strings.common.maxFee; + pair.item = "Max fees"; + pair.value = strings.common.maxFee; } } } else { @@ -95,24 +95,24 @@ static nbgl_layoutTagValue_t *getTagValuePair(uint8_t pairIndex) { switch (pairIndex) { case 0: - tlv.item = "Amount"; - tlv.value = strings.common.fullAmount; + pair.item = "Amount"; + pair.value = strings.common.fullAmount; break; case 1: - tlv.item = "Address"; - tlv.value = strings.common.fullAddress; + pair.item = "Address"; + pair.value = strings.common.fullAddress; break; case 2: - tlv.item = "Nonce"; - tlv.value = strings.common.nonce; + pair.item = "Nonce"; + pair.value = strings.common.nonce; break; case 3: - tlv.item = "Max fees"; - tlv.value = strings.common.maxFee; + pair.item = "Max fees"; + pair.value = strings.common.maxFee; break; case 4: - tlv.item = "Network"; - tlv.value = strings.common.network_name; + pair.item = "Network"; + pair.value = strings.common.network_name; break; } } @@ -121,7 +121,7 @@ static nbgl_layoutTagValue_t *getTagValuePair(uint8_t pairIndex) { if (counter == MAX_PLUGIN_ITEMS_PER_SCREEN) { counter = 0; } - return &tlv; + return &pair; } static void pageCallback(int token, uint8_t index) { diff --git a/src_nbgl/ui_display_privacy.c b/src_nbgl/ui_display_privacy.c index 3e52d5f..fb014ba 100644 --- a/src_nbgl/ui_display_privacy.c +++ b/src_nbgl/ui_display_privacy.c @@ -4,7 +4,7 @@ #include "nbgl_use_case.h" #include "network.h" -static nbgl_layoutTagValue_t tlv[2]; +static nbgl_layoutTagValue_t pairs[2]; static char *review_string; static void reviewReject(void) { @@ -25,14 +25,14 @@ static void reviewChoice(bool confirm) { static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { if (page == 0) { - tlv[0].item = "Address"; - tlv[0].value = strings.common.fullAddress; - tlv[1].item = "Key"; - tlv[1].value = strings.common.fullAmount; + pairs[0].item = "Address"; + pairs[0].value = strings.common.fullAddress; + pairs[1].item = "Key"; + pairs[1].value = strings.common.fullAmount; content->type = TAG_VALUE_LIST; content->tagValueList.nbPairs = 2; - content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; } else if (page == 1) { content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); content->infoLongPress.text = review_string; diff --git a/src_nbgl/ui_settings.c b/src_nbgl/ui_settings.c index 4ca3f3e..b55d323 100644 --- a/src_nbgl/ui_settings.c +++ b/src_nbgl/ui_settings.c @@ -7,7 +7,7 @@ static const char* const infoContents[] = {APPVERSION, "(c) 2022 Ledger"}; enum { BLIND_SIGNING_TOKEN = FIRST_USER_TOKEN, DEBUG_TOKEN, NONCE_TOKEN, EIP712_VERBOSE_TOKEN }; -static nbgl_layoutSwitch_t switches[4]; +static nbgl_layoutSwitch_t switches[3]; static bool navCallback(uint8_t page, nbgl_pageContent_t* content) { switch (page) { diff --git a/src_nbgl/ui_sign_712_v0.c b/src_nbgl/ui_sign_712_v0.c index feca3bf..e5dc92e 100644 --- a/src_nbgl/ui_sign_712_v0.c +++ b/src_nbgl/ui_sign_712_v0.c @@ -5,7 +5,7 @@ #include "ethUtils.h" #include "ui_712_common.h" -static nbgl_layoutTagValue_t tlv[2]; +static nbgl_layoutTagValue_t pairs[2]; static void start_review(void); // forward declaration @@ -16,21 +16,21 @@ static char *format_hash(const uint8_t *hash, char *buffer, size_t buffer_size, static bool display_review_page(uint8_t page, nbgl_pageContent_t *content) { if (page == 0) { - tlv[0].item = "Domain hash"; - tlv[0].value = format_hash(tmpCtx.messageSigningContext712.domainHash, - strings.tmp.tmp, - sizeof(strings.tmp.tmp), - 0); - tlv[1].item = "Message hash"; - tlv[1].value = format_hash(tmpCtx.messageSigningContext712.messageHash, - strings.tmp.tmp, - sizeof(strings.tmp.tmp), - 70); + pairs[0].item = "Domain hash"; + pairs[0].value = format_hash(tmpCtx.messageSigningContext712.domainHash, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + 0); + pairs[1].item = "Message hash"; + pairs[1].value = format_hash(tmpCtx.messageSigningContext712.messageHash, + strings.tmp.tmp, + sizeof(strings.tmp.tmp), + 70); content->type = TAG_VALUE_LIST; content->tagValueList.nbPairs = 2; content->tagValueList.nbMaxLinesForValue = 0; - content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; } else if (page == 1) { content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); content->infoLongPress.text = "Sign typed message"; diff --git a/src_nbgl/ui_stark_limit_order.c b/src_nbgl/ui_stark_limit_order.c index 1270706..4c164c5 100644 --- a/src_nbgl/ui_stark_limit_order.c +++ b/src_nbgl/ui_stark_limit_order.c @@ -6,7 +6,7 @@ #ifdef HAVE_STARKWARE -static nbgl_layoutTagValue_t tlv[3]; +static nbgl_layoutTagValue_t pairs[3]; static void reviewReject(void) { io_seproxyhal_touch_tx_cancel(NULL); @@ -26,16 +26,16 @@ static void reviewChoice(bool confirm) { static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { if (page == 0) { - tlv[0].item = "Sell"; - tlv[0].value = strings.common.fullAmount; - tlv[1].item = "Buy"; - tlv[1].value = strings.common.maxFee; - tlv[2].item = "Token amount"; - tlv[2].value = strings.common.fullAddress; + pairs[0].item = "Sell"; + pairs[0].value = strings.common.fullAmount; + pairs[1].item = "Buy"; + pairs[1].value = strings.common.maxFee; + pairs[2].item = "Token amount"; + pairs[2].value = strings.common.fullAddress; content->type = TAG_VALUE_LIST; content->tagValueList.nbPairs = 3; - content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; } else if (page == 1) { content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(false); content->infoLongPress.text = "Review stark limit order"; diff --git a/src_nbgl/ui_stark_transfer.c b/src_nbgl/ui_stark_transfer.c index 99726f3..0b752eb 100644 --- a/src_nbgl/ui_stark_transfer.c +++ b/src_nbgl/ui_stark_transfer.c @@ -8,7 +8,7 @@ #ifdef HAVE_STARKWARE -static nbgl_layoutTagValue_t tlv[3]; +static nbgl_layoutTagValue_t pairs[3]; static char condAddressBuffer[43]; struct stark_transfer_context { bool selfTransfer; @@ -36,26 +36,26 @@ static void reviewChoice(bool confirm) { static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { uint8_t count = 0; if (page == 0) { - tlv[count].item = "Amount"; - tlv[count].value = tmpContent.tmp; + pairs[count].item = "Amount"; + pairs[count].value = tmpContent.tmp; count++; if (context.selfTransfer == false && context.conditional == false) { - tlv[count].item = "Master Account"; - tlv[count].value = strings.tmp.tmp; + pairs[count].item = "Master Account"; + pairs[count].value = strings.tmp.tmp; count++; } if (context.conditional) { stark_sign_display_master_account(); - tlv[count].item = "Master Account"; - tlv[count].value = strings.tmp.tmp; + pairs[count].item = "Master Account"; + pairs[count].value = strings.tmp.tmp; count++; } - tlv[count].item = "Token Account"; - tlv[count].value = strings.tmp.tmp2; + pairs[count].item = "Token Account"; + pairs[count].value = strings.tmp.tmp2; content->type = TAG_VALUE_LIST; content->tagValueList.nbPairs = count; - content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; return true; } @@ -66,16 +66,16 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { sizeof(condAddressBuffer), &global_sha3, chainConfig->chainId), - tlv[0].item = "Cond. Address"; - tlv[0].value = condAddressBuffer; + pairs[0].item = "Cond. Address"; + pairs[0].value = condAddressBuffer; stark_sign_display_condition_fact(); - tlv[1].item = "Cond. Address"; - tlv[1].value = strings.tmp.tmp; + pairs[1].item = "Cond. Address"; + pairs[1].value = strings.tmp.tmp; content->type = TAG_VALUE_LIST; content->tagValueList.nbPairs = 2; - content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; } else { page++; diff --git a/src_nbgl/ui_stark_unsafe_sign.c b/src_nbgl/ui_stark_unsafe_sign.c index 05bf256..70579bb 100644 --- a/src_nbgl/ui_stark_unsafe_sign.c +++ b/src_nbgl/ui_stark_unsafe_sign.c @@ -7,7 +7,7 @@ #ifdef HAVE_STARKWARE -static nbgl_layoutTagValue_t tlv[2]; +static nbgl_layoutTagValue_t pairs[2]; static char from_account[64]; static char message_hash[64]; @@ -32,13 +32,13 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { snprintf(message_hash, sizeof(message_hash), "0x%.*H", 32, dataContext.starkContext.w2); if (page == 0) { - tlv[0].item = "From Account"; - tlv[0].value = from_account; - tlv[1].item = "Hash"; - tlv[1].value = message_hash; + pairs[0].item = "From Account"; + pairs[0].value = from_account; + pairs[1].item = "Hash"; + pairs[1].value = message_hash; content->type = TAG_VALUE_LIST; content->tagValueList.nbPairs = 2; - content->tagValueList.pairs = (nbgl_layoutTagValue_t *) tlv; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) pairs; } else if (page == 1) { content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(false); content->infoLongPress.text = "Unsafe Stark Sign"; From 12fb8c6a3ae7721d9d610aa2f6bf334d8ee7b818 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Fri, 7 Apr 2023 11:30:40 +0200 Subject: [PATCH 14/25] Merged confirm_parameter & confirm_selector UI code --- ...eter.c => ui_confirm_parameter_selector.c} | 35 +++++++++--- src_nbgl/ui_confirm_selector.c | 56 ------------------- 2 files changed, 28 insertions(+), 63 deletions(-) rename src_nbgl/{ui_confirm_parameter.c => ui_confirm_parameter_selector.c} (50%) delete mode 100644 src_nbgl/ui_confirm_selector.c diff --git a/src_nbgl/ui_confirm_parameter.c b/src_nbgl/ui_confirm_parameter_selector.c similarity index 50% rename from src_nbgl/ui_confirm_parameter.c rename to src_nbgl/ui_confirm_parameter_selector.c index bebe5ae..43f93fc 100644 --- a/src_nbgl/ui_confirm_parameter.c +++ b/src_nbgl/ui_confirm_parameter_selector.c @@ -2,7 +2,10 @@ #include "ui_nbgl.h" #include "network.h" -static nbgl_layoutTagValue_t tlv; +typedef enum { PARAMETER_CONFIRMATION, SELECTOR_CONFIRMATION } e_confirmation_type; + +static nbgl_layoutTagValue_t pair; +static e_confirmation_type confirm_type; static void reviewReject(void) { io_seproxyhal_touch_data_cancel(NULL); @@ -22,14 +25,18 @@ static void reviewChoice(bool confirm) { static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { if (page == 0) { - tlv.item = "Parameter"; - tlv.value = strings.tmp.tmp; + pair.item = (confirm_type == PARAMETER_CONFIRMATION) ? "Parameter" : "Selector"; + pair.value = strings.tmp.tmp; content->type = TAG_VALUE_LIST; content->tagValueList.nbPairs = 1; - content->tagValueList.pairs = (nbgl_layoutTagValue_t *) &tlv; + content->tagValueList.pairs = (nbgl_layoutTagValue_t *) &pair; } else if (page == 1) { + snprintf(staxSharedBuffer, + sizeof(staxSharedBuffer), + "Confirm %s", + (confirm_type == PARAMETER_CONFIRMATION) ? "parameter" : "selector"); content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); - content->infoLongPress.text = "Confirm parameter"; + content->infoLongPress.text = staxSharedBuffer; content->infoLongPress.longPressText = "Hold to confirm"; } else { return false; @@ -39,12 +46,20 @@ static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { } static void reviewContinue(void) { - nbgl_useCaseRegularReview(0, 2, "Reject parameter", NULL, displayTransactionPage, reviewChoice); + snprintf(staxSharedBuffer, + sizeof(staxSharedBuffer), + "Reject %s", + (confirm_type == PARAMETER_CONFIRMATION) ? "parameter" : "selector"); + nbgl_useCaseRegularReview(0, 2, staxSharedBuffer, NULL, displayTransactionPage, reviewChoice); } static void buildScreen(void) { + snprintf(staxSharedBuffer, + sizeof(staxSharedBuffer), + "Verify %s", + (confirm_type == PARAMETER_CONFIRMATION) ? "parameter" : "selector"); nbgl_useCaseReviewStart(get_app_icon(true), - "Verify parameter", + staxSharedBuffer, NULL, "Reject", reviewContinue, @@ -52,5 +67,11 @@ static void buildScreen(void) { } void ui_confirm_parameter(void) { + confirm_type = PARAMETER_CONFIRMATION; + buildScreen(); +} + +void ui_confirm_selector(void) { + confirm_type = SELECTOR_CONFIRMATION; buildScreen(); } diff --git a/src_nbgl/ui_confirm_selector.c b/src_nbgl/ui_confirm_selector.c deleted file mode 100644 index c268d28..0000000 --- a/src_nbgl/ui_confirm_selector.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "common_ui.h" -#include "ui_nbgl.h" -#include "network.h" - -static nbgl_layoutTagValue_t tlv; - -static void reviewReject(void) { - io_seproxyhal_touch_data_cancel(NULL); -} - -static void confirmTransation(void) { - io_seproxyhal_touch_data_ok(NULL); -} - -static void reviewChoice(bool confirm) { - if (confirm) { - confirmTransation(); - } else { - reviewReject(); - } -} - -static bool displayTransactionPage(uint8_t page, nbgl_pageContent_t *content) { - if (page == 0) { - tlv.item = "Parameter"; - tlv.value = strings.tmp.tmp; - content->type = TAG_VALUE_LIST; - content->tagValueList.nbPairs = 1; - content->tagValueList.pairs = (nbgl_layoutTagValue_t *) &tlv; - } else if (page == 1) { - content->type = INFO_LONG_PRESS, content->infoLongPress.icon = get_app_icon(true); - content->infoLongPress.text = "Confirm selector"; - content->infoLongPress.longPressText = "Hold to confirm"; - } else { - return false; - } - // valid page so return true - return true; -} - -static void reviewContinue(void) { - nbgl_useCaseRegularReview(0, 2, "Reject selector", NULL, displayTransactionPage, reviewChoice); -} - -static void buildScreen(void) { - nbgl_useCaseReviewStart(get_app_icon(true), - "Verify selector", - NULL, - "Reject", - reviewContinue, - reviewReject); -} - -void ui_confirm_selector(void) { - buildScreen(); -} From a5e1d2960d650e0f18e73298db3e16e8092a9466 Mon Sep 17 00:00:00 2001 From: abonnaudet-ledger Date: Wed, 26 Apr 2023 09:23:29 +0200 Subject: [PATCH 15/25] Fat: INTER_REGULAR_32 is now INTER_MEDIUM_32 Replace BAGL_FONT_INTER_REGULAR_32px by BAGL_FONT_INTER_MEDIUM_32px. This change is valid starting from API_LEVEL_9 --- src_nbgl/ui_sign_712.c | 2 +- src_nbgl/ui_sign_message.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src_nbgl/ui_sign_712.c b/src_nbgl/ui_sign_712.c index 094fdb6..bfe53fd 100644 --- a/src_nbgl/ui_sign_712.c +++ b/src_nbgl/ui_sign_712.c @@ -25,7 +25,7 @@ static bool display_review_page(uint8_t page, nbgl_pageContent_t *content) { switch (page) { case 0: // limit the value to one page - nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_32px, + nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_MEDIUM_32px, strings.tmp.tmp, SCREEN_WIDTH - (2 * BORDER_MARGIN), 9, diff --git a/src_nbgl/ui_sign_message.c b/src_nbgl/ui_sign_message.c index 587bb68..5ea2c89 100644 --- a/src_nbgl/ui_sign_message.c +++ b/src_nbgl/ui_sign_message.c @@ -41,7 +41,7 @@ static bool display_message(nbgl_pageContent_t *content) { strncpy(staxSharedBuffer + eip191MessageIdx, strings.tmp.tmp + stringsTmpTmpIdx, SHARED_BUFFER_SIZE - eip191MessageIdx); - reached = nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_REGULAR_32px, + reached = nbgl_getTextMaxLenInNbLines(BAGL_FONT_INTER_MEDIUM_32px, (char *) staxSharedBuffer, SCREEN_WIDTH - (2 * BORDER_MARGIN), 9, From ee8c8e357cc0959c410e94e7fdd04b4d1aee32f0 Mon Sep 17 00:00:00 2001 From: Clement Bouvet Date: Tue, 21 Feb 2023 10:54:38 +0100 Subject: [PATCH 16/25] New stax icons --- Makefile | 9 ++++----- glyphs/stax_akroma_64px.gif | Bin 0 -> 886 bytes glyphs/stax_apothemnetwork_64px.gif | Bin 0 -> 815 bytes glyphs/stax_artis_sigma1_64px.gif | Bin 0 -> 997 bytes glyphs/stax_artis_tau1_64px.gif | Bin 0 -> 985 bytes glyphs/stax_astar_64px.gif | Bin 0 -> 1019 bytes glyphs/stax_atheios_64px.gif | Bin 0 -> 584 bytes glyphs/stax_bsc_64px.gif | Bin 0 -> 885 bytes glyphs/stax_bttc_64px.gif | Bin 0 -> 1070 bytes glyphs/stax_callisto_64px.gif | Bin 0 -> 773 bytes glyphs/stax_conflux_espace_64px.gif | Bin 0 -> 641 bytes glyphs/stax_cube_64px.gif | Bin 0 -> 966 bytes glyphs/stax_dexon_64px.gif | Bin 0 -> 914 bytes glyphs/stax_ellaism_64px.gif | Bin 0 -> 639 bytes glyphs/stax_energywebchain_64px.gif | Bin 0 -> 836 bytes glyphs/stax_ether1_64px.gif | Bin 0 -> 622 bytes glyphs/stax_ethereum_64px.gif | Bin 0 -> 556 bytes glyphs/stax_ethereum_classic_64px.gif | Bin 0 -> 618 bytes glyphs/stax_ethergem_64px.gif | Bin 0 -> 649 bytes glyphs/stax_ethersocial_64px.gif | Bin 0 -> 265 bytes glyphs/stax_expanse_64px.gif | Bin 0 -> 384 bytes glyphs/stax_flare_64px.gif | Bin 0 -> 199 bytes glyphs/stax_flare_coston_64px.gif | Bin 0 -> 210 bytes glyphs/stax_gochain_64px.gif | Bin 0 -> 314 bytes glyphs/stax_goerli_64px.gif | Bin 0 -> 339 bytes glyphs/stax_hpb_64px.gif | Bin 0 -> 354 bytes glyphs/stax_id4good_64px.gif | Bin 0 -> 339 bytes glyphs/stax_kardiachain_64px.gif | Bin 0 -> 310 bytes glyphs/stax_kusd_64px.gif | Bin 0 -> 283 bytes glyphs/stax_meter_64px.gif | Bin 0 -> 311 bytes glyphs/stax_mix_64px.gif | Bin 0 -> 246 bytes glyphs/stax_moonbeam_64px.gif | Bin 0 -> 212 bytes glyphs/stax_moonriver_64px.gif | Bin 0 -> 294 bytes glyphs/stax_multivac_64px.gif | Bin 0 -> 349 bytes glyphs/stax_musicoin_64px.gif | Bin 0 -> 300 bytes glyphs/stax_oasys_64px.gif | Bin 0 -> 340 bytes glyphs/stax_okc_64px.gif | Bin 0 -> 247 bytes glyphs/stax_pirl_64px.gif | Bin 0 -> 293 bytes glyphs/stax_poa_64px.gif | Bin 0 -> 299 bytes glyphs/stax_polygon_64px.gif | Bin 0 -> 681 bytes glyphs/stax_reosc_64px.gif | Bin 0 -> 314 bytes glyphs/stax_ropsten_64px.gif | Bin 0 -> 248 bytes glyphs/stax_rsk_64px.gif | Bin 0 -> 295 bytes glyphs/stax_rsk_testnet_64px.gif | Bin 0 -> 295 bytes glyphs/stax_shiden_64px.gif | Bin 0 -> 342 bytes glyphs/stax_shyft_64px.gif | Bin 0 -> 339 bytes glyphs/stax_songbird_64px.gif | Bin 0 -> 251 bytes glyphs/stax_tecracoin_64px.gif | Bin 0 -> 389 bytes glyphs/stax_tecratestnet_64px.gif | Bin 0 -> 389 bytes glyphs/stax_thundercore_64px.gif | Bin 0 -> 287 bytes glyphs/stax_tobalaba_64px.gif | Bin 0 -> 228 bytes glyphs/stax_tomochain_64px.gif | Bin 0 -> 227 bytes glyphs/stax_ubiq_64px.gif | Bin 0 -> 295 bytes glyphs/stax_volta_64px.gif | Bin 0 -> 339 bytes glyphs/stax_wanchain_64px.gif | Bin 0 -> 313 bytes glyphs/stax_webchain_64px.gif | Bin 0 -> 217 bytes glyphs/stax_wethio_64px.gif | Bin 0 -> 305 bytes glyphs/stax_xdcnetwork_64px.gif | Bin 0 -> 287 bytes icons/stax_app_akroma.gif | Bin 0 -> 467 bytes icons/stax_app_apothemnetwork.gif | Bin 0 -> 410 bytes icons/stax_app_artis_sigma1.gif | Bin 0 -> 476 bytes icons/stax_app_artis_tau1.gif | Bin 0 -> 481 bytes icons/stax_app_astar.gif | Bin 0 -> 506 bytes icons/stax_app_atheios.gif | Bin 0 -> 340 bytes icons/stax_app_bsc.gif | Bin 0 -> 473 bytes icons/stax_app_bttc.gif | Bin 0 -> 471 bytes icons/stax_app_callisto.gif | Bin 0 -> 404 bytes icons/stax_app_conflux_espace.gif | Bin 0 -> 347 bytes icons/stax_app_cube.gif | Bin 0 -> 438 bytes icons/stax_app_dexon.gif | Bin 0 -> 469 bytes icons/stax_app_ellaism.gif | Bin 0 -> 381 bytes icons/stax_app_energywebchain.gif | Bin 0 -> 446 bytes icons/stax_app_ether1.gif | Bin 0 -> 337 bytes icons/stax_app_ethereum.gif | Bin 0 -> 309 bytes icons/stax_app_ethereum_classic.gif | Bin 0 -> 328 bytes icons/stax_app_ethergem.gif | Bin 0 -> 328 bytes icons/stax_app_ethersocial.gif | Bin 0 -> 136 bytes icons/stax_app_expanse.gif | Bin 0 -> 165 bytes icons/stax_app_flare.gif | Bin 0 -> 110 bytes icons/stax_app_flare_coston.gif | Bin 0 -> 116 bytes icons/stax_app_gochain.gif | Bin 0 -> 150 bytes icons/stax_app_goerli.gif | Bin 0 -> 157 bytes icons/stax_app_hpb.gif | Bin 0 -> 161 bytes icons/stax_app_id4good.gif | Bin 0 -> 151 bytes icons/stax_app_kardiachain.gif | Bin 0 -> 153 bytes icons/stax_app_kusd.gif | Bin 0 -> 133 bytes icons/stax_app_meter.gif | Bin 0 -> 148 bytes icons/stax_app_mix.gif | Bin 0 -> 126 bytes icons/stax_app_moonbeam.gif | Bin 0 -> 107 bytes icons/stax_app_moonriver.gif | Bin 0 -> 142 bytes icons/stax_app_multivac.gif | Bin 0 -> 161 bytes icons/stax_app_musicoin.gif | Bin 0 -> 146 bytes icons/stax_app_oasys.gif | Bin 0 -> 149 bytes icons/stax_app_okc.gif | Bin 0 -> 131 bytes icons/stax_app_pirl.gif | Bin 0 -> 145 bytes icons/stax_app_poa.gif | Bin 0 -> 147 bytes icons/stax_app_polygon.gif | Bin 0 -> 362 bytes icons/stax_app_reosc.gif | Bin 0 -> 148 bytes icons/stax_app_ropsten.gif | Bin 0 -> 127 bytes icons/stax_app_rsk.gif | Bin 0 -> 144 bytes icons/stax_app_rsk_testnet.gif | Bin 0 -> 144 bytes icons/stax_app_shiden.gif | Bin 0 -> 156 bytes icons/stax_app_shyft.gif | Bin 0 -> 150 bytes icons/stax_app_songbird.gif | Bin 0 -> 132 bytes icons/stax_app_tecracoin.gif | Bin 0 -> 174 bytes icons/stax_app_tecratestnet.gif | Bin 0 -> 174 bytes icons/stax_app_thundercore.gif | Bin 0 -> 141 bytes icons/stax_app_tobalaba.gif | Bin 0 -> 116 bytes icons/stax_app_tomochain.gif | Bin 0 -> 126 bytes icons/stax_app_ubiq.gif | Bin 0 -> 143 bytes icons/stax_app_volta.gif | Bin 0 -> 158 bytes icons/stax_app_wanchain.gif | Bin 0 -> 153 bytes icons/stax_app_webchain.gif | Bin 0 -> 116 bytes icons/stax_app_wethio.gif | Bin 0 -> 149 bytes icons/stax_app_xdcnetwork.gif | Bin 0 -> 146 bytes 115 files changed, 4 insertions(+), 5 deletions(-) create mode 100644 glyphs/stax_akroma_64px.gif create mode 100644 glyphs/stax_apothemnetwork_64px.gif create mode 100644 glyphs/stax_artis_sigma1_64px.gif create mode 100644 glyphs/stax_artis_tau1_64px.gif create mode 100644 glyphs/stax_astar_64px.gif create mode 100644 glyphs/stax_atheios_64px.gif create mode 100644 glyphs/stax_bsc_64px.gif create mode 100644 glyphs/stax_bttc_64px.gif create mode 100644 glyphs/stax_callisto_64px.gif create mode 100644 glyphs/stax_conflux_espace_64px.gif create mode 100644 glyphs/stax_cube_64px.gif create mode 100644 glyphs/stax_dexon_64px.gif create mode 100644 glyphs/stax_ellaism_64px.gif create mode 100644 glyphs/stax_energywebchain_64px.gif create mode 100644 glyphs/stax_ether1_64px.gif create mode 100644 glyphs/stax_ethereum_64px.gif create mode 100644 glyphs/stax_ethereum_classic_64px.gif create mode 100644 glyphs/stax_ethergem_64px.gif create mode 100644 glyphs/stax_ethersocial_64px.gif create mode 100644 glyphs/stax_expanse_64px.gif create mode 100644 glyphs/stax_flare_64px.gif create mode 100644 glyphs/stax_flare_coston_64px.gif create mode 100644 glyphs/stax_gochain_64px.gif create mode 100644 glyphs/stax_goerli_64px.gif create mode 100644 glyphs/stax_hpb_64px.gif create mode 100644 glyphs/stax_id4good_64px.gif create mode 100644 glyphs/stax_kardiachain_64px.gif create mode 100644 glyphs/stax_kusd_64px.gif create mode 100644 glyphs/stax_meter_64px.gif create mode 100644 glyphs/stax_mix_64px.gif create mode 100644 glyphs/stax_moonbeam_64px.gif create mode 100644 glyphs/stax_moonriver_64px.gif create mode 100644 glyphs/stax_multivac_64px.gif create mode 100644 glyphs/stax_musicoin_64px.gif create mode 100644 glyphs/stax_oasys_64px.gif create mode 100644 glyphs/stax_okc_64px.gif create mode 100644 glyphs/stax_pirl_64px.gif create mode 100644 glyphs/stax_poa_64px.gif create mode 100644 glyphs/stax_polygon_64px.gif create mode 100644 glyphs/stax_reosc_64px.gif create mode 100644 glyphs/stax_ropsten_64px.gif create mode 100644 glyphs/stax_rsk_64px.gif create mode 100644 glyphs/stax_rsk_testnet_64px.gif create mode 100644 glyphs/stax_shiden_64px.gif create mode 100644 glyphs/stax_shyft_64px.gif create mode 100644 glyphs/stax_songbird_64px.gif create mode 100644 glyphs/stax_tecracoin_64px.gif create mode 100644 glyphs/stax_tecratestnet_64px.gif create mode 100644 glyphs/stax_thundercore_64px.gif create mode 100644 glyphs/stax_tobalaba_64px.gif create mode 100644 glyphs/stax_tomochain_64px.gif create mode 100644 glyphs/stax_ubiq_64px.gif create mode 100644 glyphs/stax_volta_64px.gif create mode 100644 glyphs/stax_wanchain_64px.gif create mode 100644 glyphs/stax_webchain_64px.gif create mode 100644 glyphs/stax_wethio_64px.gif create mode 100644 glyphs/stax_xdcnetwork_64px.gif create mode 100644 icons/stax_app_akroma.gif create mode 100644 icons/stax_app_apothemnetwork.gif create mode 100644 icons/stax_app_artis_sigma1.gif create mode 100644 icons/stax_app_artis_tau1.gif create mode 100644 icons/stax_app_astar.gif create mode 100644 icons/stax_app_atheios.gif create mode 100644 icons/stax_app_bsc.gif create mode 100644 icons/stax_app_bttc.gif create mode 100644 icons/stax_app_callisto.gif create mode 100644 icons/stax_app_conflux_espace.gif create mode 100644 icons/stax_app_cube.gif create mode 100644 icons/stax_app_dexon.gif create mode 100644 icons/stax_app_ellaism.gif create mode 100644 icons/stax_app_energywebchain.gif create mode 100644 icons/stax_app_ether1.gif create mode 100644 icons/stax_app_ethereum.gif create mode 100644 icons/stax_app_ethereum_classic.gif create mode 100644 icons/stax_app_ethergem.gif create mode 100644 icons/stax_app_ethersocial.gif create mode 100644 icons/stax_app_expanse.gif create mode 100644 icons/stax_app_flare.gif create mode 100644 icons/stax_app_flare_coston.gif create mode 100644 icons/stax_app_gochain.gif create mode 100644 icons/stax_app_goerli.gif create mode 100644 icons/stax_app_hpb.gif create mode 100644 icons/stax_app_id4good.gif create mode 100644 icons/stax_app_kardiachain.gif create mode 100644 icons/stax_app_kusd.gif create mode 100644 icons/stax_app_meter.gif create mode 100644 icons/stax_app_mix.gif create mode 100644 icons/stax_app_moonbeam.gif create mode 100644 icons/stax_app_moonriver.gif create mode 100644 icons/stax_app_multivac.gif create mode 100644 icons/stax_app_musicoin.gif create mode 100644 icons/stax_app_oasys.gif create mode 100644 icons/stax_app_okc.gif create mode 100644 icons/stax_app_pirl.gif create mode 100644 icons/stax_app_poa.gif create mode 100644 icons/stax_app_polygon.gif create mode 100644 icons/stax_app_reosc.gif create mode 100644 icons/stax_app_ropsten.gif create mode 100644 icons/stax_app_rsk.gif create mode 100644 icons/stax_app_rsk_testnet.gif create mode 100644 icons/stax_app_shiden.gif create mode 100644 icons/stax_app_shyft.gif create mode 100644 icons/stax_app_songbird.gif create mode 100644 icons/stax_app_tecracoin.gif create mode 100644 icons/stax_app_tecratestnet.gif create mode 100644 icons/stax_app_thundercore.gif create mode 100644 icons/stax_app_tobalaba.gif create mode 100644 icons/stax_app_tomochain.gif create mode 100644 icons/stax_app_ubiq.gif create mode 100644 icons/stax_app_volta.gif create mode 100644 icons/stax_app_wanchain.gif create mode 100644 icons/stax_app_webchain.gif create mode 100644 icons/stax_app_wethio.gif create mode 100644 icons/stax_app_xdcnetwork.gif diff --git a/Makefile b/Makefile index 2ed9286..d037261 100644 --- a/Makefile +++ b/Makefile @@ -68,11 +68,10 @@ ifeq ($(TARGET_NAME),TARGET_NANOS) ICONNAME=icons/nanos_app_$(CHAIN).gif else ifeq ($(TARGET_NAME),TARGET_STAX) ICONNAME=icons/stax_app_$(CHAIN).gif -DEFINES += ICONGLYPH=C_stax_app_$(CHAIN)_64px -DEFINES += ICONBITMAP=C_stax_app_$(CHAIN)_64px_bitmap -DEFINES += ICONGLYPH_SMALL=C_stax_app_$(CHAIN) -GLYPH_FILES += icons/stax_app_$(CHAIN)_64px.gif -GLYPH_FILES += icons/stax_app_$(CHAIN).gif +DEFINES += ICONGLYPH=C_stax_$(CHAIN)_64px +DEFINES += ICONBITMAP=C_stax_$(CHAIN)_64px_bitmap +DEFINES += ICONGLYPH_SMALL=C_stax_$(CHAIN) +GLYPH_FILES += $(ICONNAME) else ICONNAME=icons/nanox_app_$(CHAIN).gif endif diff --git a/glyphs/stax_akroma_64px.gif b/glyphs/stax_akroma_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..d092851dfbc8c87dc78769abb970463a2fbd45ed GIT binary patch literal 886 zcmV-+1Bv`cNk%w1VL$*t0P_F<000051qBNW3l|p`FfcG*Utgi2q0!ON=jZ41^Yi)n z`Tzg_000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1paWzNvpj$>&?6WU?`53F%(BauHhj7FoCLUoe^*@41|%|z{wz& z3&2i3MX-h=IspMBLb((bo=_t(ATuDUAk(%$7zDIi+2IS`9EL>i!9aLD0|GUzZ9x#w z00k2X2Ul1yTs{bUdV`Y%GLuIR&)~27m)>$CZ_OETBXL#S3p+1`~dE06YR`TLOYB z3a;VVjzlLEn^AKG$egMq>H*#GW5v6Ost_2U7l*~a9Q!7?iZVq4f_mo`uxbS<6Np>9 zDquvEupJ}|{@cRc6Y(&Oq>=?E9PCsfU9uG(IkBt5iv}TZ01~Q%lr2O)oeK&$Q^o30 zpgwT)tvCn+XtOONU14h}^wrWz5ha8~sLP#!Oa{h@B(XIHBb3Q%mF0or2QY-oK3JR8 zQ{7aDM%@*Fg(%Vpm)t6-6L6r`LT5XQj0B-Br^ZTORRR*0QUueZ6v|?DIIs*JM8fX2 zcp`ei+!#F<5bA6OXAz(t&>k6?Zm5Pytc{?_`XS~KoeD0)&M@x}Y7v0rFroygN8#R8 z9fwG8xmV_ToVxtj@HCJ`4&5t$Y8*;?25T%^U{9~`5Rn&Av}f8he1mK#PTd!<1F zo*^Xu$JKR+fQHHwtz9C0j3J4S@ihlZ)*1<-zaj+U4 zAA%UzMc66jfiD7eHsK)`+Lu>O-*NB@YfxCSn0<{6U;rio+T@`u^<{8bcBHJa$_R6y zsD*VOEO|$NUc{wi0s`sqV+O~l7)pO@@wuy)u_{L_NWZt6y z75}*Cfs_^A2?cy)E}{(_?|h&DA@f9tMxb}dvO^b5aM6$ldrG8QheJk)6QphGRv8eS z?&Vn)g3<`aq7t1*22H8D^JN=cM(Js)X*M#*0gawo;Q)M0$7yGOIFn?sv3V$DoX7|^ M>+G}8Y7hYcJ0ZDeWB>pF literal 0 HcmV?d00001 diff --git a/glyphs/stax_apothemnetwork_64px.gif b/glyphs/stax_apothemnetwork_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..974f8bb31c28bc7acb2565fb186c128e0edb70b7 GIT binary patch literal 815 zcmV+~1JL|ONk%w1VL$*t0P_j}0RaIE3kw$)7cMR?U|?XLo}SUs(dXyq^z`)l`uhL> z{{R30000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1pZLTNvpj$>&?6WU?`4cg%|}f3<2N*!b%iIa+Kw%3UB-NfxwD} zz=2S#UTjuqHVHdGP%tYRHHQMv6@VIU3PfUJRiIR_+4yQIBmo10L6l8)=j?>eHz!nr5c#691t4K3N;K^LaZ%=KE%~D*8(@CiCzVQk*(9%A5p=f z4HCHmfgnOcYdGO!%Th^i@JfY2_@mN3N<)%FX~Ae^44%sR(g<_J%Y;rt(99Oj+iwgk zEf^5;yuwN!$~58|5nY$v#urxAB-6|p9TuTYseaY0c)+;Zk5CT}r@91<>C4K#Y5u~o z0F^AjlL8cOSrCf~oh_zYLj8e&R06{w_8MG5fLD(t>S@50M;BfL2Y9vMV_z{)J$G7y z9ZFM?g6nC605?HcIKd~qq$t4&2aTw}Ju+fqlvaT$)MFv<3`s#rHIl=PUGC8#OKq-{ z)CG_pl;li+SJZI|l^-lA1d30kAc!xy&;%Bj7EH6*9olGl3JnjX=}!tiRCuAAQpmuB t6Hr9-16VdHz?5D;6j~=0Gz3b44QE8;gA_|NVSpHlR%+>`m{Je{06VElLgWAd literal 0 HcmV?d00001 diff --git a/glyphs/stax_artis_sigma1_64px.gif b/glyphs/stax_artis_sigma1_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..05c4f221cd8eb02251f821b7ef454598713e7309 GIT binary patch literal 997 zcmV z{{R30000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1pZLTNvpj$>&?6WU?`4cX`X0WCR}nH#=)v0n@_av|(4zQX+~T zjs*zV$X^IX{`aczyF^442v*Z7KB4DRre+^a`qL&JTjG5Vzjl=hugQywhnO0 zaAn*J_5dg<*MyUWk@0dW7&SrM#9{>RR+zV=%Mii_KM?>5dBQ+hi>Ge8caWvoE(JA| zT3O(c=|fsGUjmI01Gj!qCk2ibABOmY%3lX0-!GWJ1Mjv9}B;8JoL{KwKfg0V*%CJMsS8gTTP0aa{;Q3r(p z6k2eGGarHoph0$3m5y+vnWq4CkJ!XRQ=?c&MqPS!@SrrWk)}%(v!&5QYTAX!mjE_e z5DgusIC9@sX?SHEfVhRW!5MSJFl0ZNxbW7QXA-uceIK|0j||4-2iui|W!EHt+-ziE z3)I|0j4^F^fs36QcrwvWEpG78EI3pts6Hm`gPwrn^~R_RL$-lS3}RKa(>NtuCJjbc z94F`_lVn)Ie^OW%f-QQk3RM^bJkpelP>^_FSQJE)2tLRlQmZnN`qWR9AmphPKO1-H zazz%$1v>1l#_AdZZ{O52Oa%z+kVP0m@Nf#UufFM$t}YleW0qc`Fd@$=m~i#sVNYB>=;QI8Hkf`j*uKM)F=W|oP)*` Thb;2QB$sUR$tb7%K?DFhiBOzZ literal 0 HcmV?d00001 diff --git a/glyphs/stax_artis_tau1_64px.gif b/glyphs/stax_artis_tau1_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..87b527dae34f16890d7365a5c34a2374cada11e8 GIT binary patch literal 985 zcmV;~119`ONk%w1VL$*t0P_F<0RaIE3kwz&7A`I>U|?XLo}SRq(C6pp^Yioh`T76< z{{R30000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1pZLTNvpj$>&?6WU?`4cX`X0WCR}nH#=)v0nA0(LYBX>J66F$gn~5(ou^js^${jZZ@~2AEF-GYX}q2?YaR1e!Mr1z-e} zD2+j0iWLb4t8N1YrwXB91)C=agaHM%#uEmEU5RBD2!{Z@i72txyUD;Tf}#Rs!4!=? zo(qR00Y~R*=W@+>KYJ8@KV4wUeW`7)ouUY#}HVJ!?c}7B#Awheo_B3>)yM`7%tr zZ5vhD&Uj`g1B|D_j@zxM$S~Ux21#hZDKw)%cfmM5!^#cI;|}|3p(+5L?TNNCat~fJ zlw)B2Aj&UCQRk3bfDjZ^c2@AEiD};@7Tz_gz|$R43`*b{Y?X=8N`4f)g@|h8U1N+v zPRV7PNMwMZ6D|s3cT_*^@v@#2#e8tZBL)n$oFsFBg$Z+C5V%w&*0Chxb{2ZDjWQKx z0^&;Gp%aJ(( zR6HRd&l>RHH>EJ;xi$hLPB?YL6_~v7iz{vJQQ8O%-DQQBA~9FYCLB_LloThlG+l_0 ziJ|F(*F}*WNAy$>%NxtAV&6fUS{D*#CRpM{ilXjgNfvn&`UeZX-KPS2*YwDVjH_$y zK-wI?T!s)RG$qu;st5wxn6X6!H3no^nvw$`e*D1L9BlFfs27hclSL4GZ7UI+RiG5b zxxX>i#1=sK@JM$mh#1DcKrq)XBrlvYXqZ9t+XoM66=+5XIUJDW#29C+@x~l??D5AR HM*sjjv>us8 literal 0 HcmV?d00001 diff --git a/glyphs/stax_astar_64px.gif b/glyphs/stax_astar_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..60fb1e8fc4a3bd527e96ab21e917f4d67b930681 GIT binary patch literal 1019 zcmVNk%w1VL$*t0P_F<000061_lcY3mF+1EiElhPEK!cZ=9T*(b3W9=;-zJ z_4@ky|Ns900000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1pbi8Nvpj$>&?6WU?`5Hg&amf3;_TH0#O(TQr^;846N(BEugH1 z3n2`HpK_@j6cCG|W`QUKnb>8(X_HnI3S@Si9n_*;MwQIYKBbGrA&I??1!FV1q&VQQ zJXta{DRfK%2MQ$#27gKc1P60W1qTUHaSI6t1X%_oa*jU(1_=rUT0~SSGd7!sKLH0L zew1AYb^wT(lR#z+3TsRUaUTe^ns7i>6616`B2@?g< zE(Bd+0=Wg{9R^y;5(@@)0@?}9!xNk6pEw*_63`#A0^k_zbF(MRl586mSW)t>0xl)9 zD0E{2(ceZN{spE)^QLXWfhHvx^wNSr!JdIX@?~&{agRBQ373gml99qmB?fF#IA({O z1#UnUno7Vln2KCICm`VGqN9bMK4e{3_+y3&0xM+9Sm`3FNuC!@q1=j$%r&z)r~(LS zLTMrDAW51*F@5FWpI|~oL~T_>jPTDPiFC^WBZ63Bu9-t|at#cdW-CG{W$enS zA{wILsV>FgKo*rwRB~)-d6>tXb>w%{b?*^Ue_f06Wn|oR|Or literal 0 HcmV?d00001 diff --git a/glyphs/stax_atheios_64px.gif b/glyphs/stax_atheios_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..051e9c37e73fcb24e8ff820bf4c7b8a7b54e6c46 GIT binary patch literal 584 zcmZ?wbhEHbbYO5`_{_}!1gxyAJUl#-l9GCQdJz#3vuDq~aN)x9=g+@<`SSDU&;S4b zgA~Dl;!hSZQ}I8yXKrG8s&8U?W^y)PdSY&FqOF0Ri75y&=z!FKY+zvdS8&pE^H8~1CQQ$hB5wamCO(bBY zn8Vg2p60jH3OB3ZLbDjB1upV672PS~zqNOFh4`$b zx%pC&C9DUIiL$dCS*63V{tDY^(Z-}cJyxb7rmTD0CEKU#o?GB?F@E2+#TpYkZc9H6 zVtlQ}o*m*NGrxJGmxjYu*PHAqIe%t&6e!HK;%An=Bxs=UfTJmD%GcKo8!vX|+=$j{ zOW5J*Z75hdFZ1?_?ohtzY$0NMo;?hg(=*u(YMv$Q*u=di%sr>dLR=yppA{3{A-XjrtX{Ozr^ z-aZT4>Q`Fv_)KUoNIV?CxLI)J!%mf1s#a1HgB7&Q+TGp=q%Gw99Ke&Y&?6WU?`3xR}6!JAW7+R1`*5xp}x3v6awJ?gTf(~ zOPqd4Um%Dek`l3`^k-{1KL^=V(392-R}SLnwMD1QFy<7HE(h_!;+YihoIaK0Rtz&(bwuisyGy&Y>Ow)pbv3? zs97pTuG1%d{s*c7pm+favVSoW1z40JB@&hr4m=8wFx?(;RzlVhAWKuAa07J$@Yi9E zoqHC;IWt;kXiz%IJnXPH!N9vIX7)5iI3WwW4=WHHSe3M?BC|heP7s^GTL`OY<60XC z5v(`3a`TQn)xs@>7&Y@9(`z_) zCBRKwmQT%;2y?Ec%nHhFq=R^pHTRM(8P>wK56=hvAkvxdcMe3(HKuS4?JvexG@pE0 z=Kpp6HPHt79i^IkRr$wXRgd5%6g=xC2n0$52vXlZS1l+V9hW5Z;7Acl_Z=&+pa5PS z=*jd^1rO5Xmjd7%MA;4}PJ!MSV~N%rIpz?h0dj+G{1L;wIgm1|}B literal 0 HcmV?d00001 diff --git a/glyphs/stax_bttc_64px.gif b/glyphs/stax_bttc_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..99e51ff0174ef78b77c3ce9994e90e9246209375 GIT binary patch literal 1070 zcmV+}1kw9PNk%w1VL$*t0P_F<0RaIE3kw(+7%VI-US3|Eot@Co(CFys^z`)n{QUp_ z{{R30000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1pZLTNvpj$>&?6WU?`4cg%|}v3hp-rx>iq&!>m_k0v|Qd=r@i|Pv1$d@FtDdX z2}y4Ne@6)kZZCx;T5kdccqIsl00RY8R+D`I0hc9hOH&AuYFeCxB?UhOMu&M4Y+IZK zfC>enuNGJc1TVCt8VP(Z1ehKOMj!{hU2=2GtQ{vQD~r!A1I8N615_I*EN24AAj1H( z9K)R%dn-Uo0?r;-x6K@~#lRD7g8>3EU%ZLnMeJLPco>oZv1EXpzIg@?8gO+1+Cv5A zDizUlfQ$+v{xr00=!Hhlg#$ehUMR2$jgchb;P~)oiK0P!x>OM|wkskWbd9*Y^EdGr zGjtY?Uf|>7kpxO`WDrp?AcjZ{^@>>-rji1|F6d-o3t6F~ybeCcS;)F_NmwBpJAMJ# z@ajlTXKisJU;)7qPzC3S&xLOq1_Tw-Kq*iK^(Y%BB$aP~melAf{E zfco!a%)NHE3br88tAVC9WW}5G22GJe2&N6vn(m;5rsN0{L-vNRxktfGDr9_d0-Mdh zy9EDAOD95R>ohDw%^@^^-~NK5#QU|_YsMU63Ebd4`heiCV}#jEi(B$F&2^0rz#8XM z!6(4}ra)CgOrd=(l1M?;%Hk_#Ix47Qkr5y`h-eZvizS%^DH z5E^F#`rzOT9+D7f4aPJAMi(P8VE;G6^} zyn$mvf3>32akS9(4nP4JAgiojAhwKP_hsM{DhfPG%cRk0QPnADz|aE>Ft9=pQ6a$8 z6Xh_LOvcG!H%zj^u|aUcLq4)d2!c+6=I9SC%M1%@uVIi;Ypt@zGSej}o&;_hTHJU; zy~xH<7bdykVM-TT#fyQnmgL4#40RPIj#M8_L60M+T3TBg*2*A<4p4AGgc0@rCJAgR8lmGw# literal 0 HcmV?d00001 diff --git a/glyphs/stax_callisto_64px.gif b/glyphs/stax_callisto_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..44a6b888aef10eff738ac64add7d5c5e2a80c659 GIT binary patch literal 773 zcmV+g1N!_&Nk%w1VL$*t0P_F<000061_lic4Hgy_EiElzU|^k{ozKtD>FMe8^z`}p z`Tzg_000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1paWzNvpj$>&?6WU?`4RVhjOcB&x>~^2aLM zcNIthds|E^ffjjVgoImeUWtNwR0ReG1O${@1(FksN}Uo42?qxSK2rvtXmN7@s})2& zN(2WIr8t3e1GgBdG_eW>0ztlDpfm-56epAfIS0TheqeL47Q|H81yfB}YrPi=-9H6R zr30H>c1N4%76}ODGvW&g^n5})gUYQG2h5Gq#wLjhW+0LQD09jZ8hkSdRO_*BOqCa} z^aQ}RK$?mP{stV)u#}IAF%b&AotYqSg0vqJOO)g;D&}o2`}l`V$mVx z6nGb8m_rkkQKSwK1tbX|fGX88|5zF*z_p#rir$WGKwzq@SyM#EZ7>10R@Mt|!OWau zZ$lAMag@>#AXY8evuES7yn^sVAp(MN&68S#5M!wvE10-+shZ0Hh3aZJfSJy@w;`9h z1ZL5z2BS(=AzYw0;*|uN*w_S-)2HPHWG}&?6WU?`5{mLx@ilq`rCf>0!Ft-S#N$h7TG34;z0 z2=IQk6KpsP6p*zSb1H+Da8v5c8VY8!#x0kVcnQ8==h);$r>kpB+l@ZPDdu`AmlnsB zd{a3F3J3*(T6cv)dOe12PCZ;$U;+k`g#~VQP;*%_D;0)_Iz^mGd0%iBk7#N>O0Jfn z7^8ZyjA(utt*W~sWlO4;9=2dkv?7#WPcE8`Bc4>mA;yBIWI<<@%@#BVgtgDU2$&iP z2c$!@wFd(O;jH6X0|y`m>N>v^?mFNQURYHhLcu9ug>#14SL!_+`{ZlB2+s96|;dnZdwJX5}^*+j%dC zC5IChf>BZI*+3BKVk#)3Gz-%YqlkJ4GN9Xqs#C5y6L6rW9B@b__;jNptiQ8rQ+Ln&l3Co b=|j{K_a6t3?1bKch_!{_f($lzM+5*n$ngyo literal 0 HcmV?d00001 diff --git a/glyphs/stax_cube_64px.gif b/glyphs/stax_cube_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..81867228589bc0447a852e77d9fcc253c17543fc GIT binary patch literal 966 zcmV;%13COhNk%w1VL$*t0P_F<000061_lWU2^AF;E-o%!US5!pkgu<=&CSi{=jZeD z^ZNSw|Ns900000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1pbi8Nvpj$>&?6WU?`4cX`X1RuH1qga11NdlE`>ISFcWY2mv54 zED~-DiGm;qIEO@M^m#-~mc?h_m}nIM;4naNKoAZRgLusz!_JJwmpv#GteS&x9VjTi z1ug__gj;d|fd>O^1qp)%8d!8NV19Fid;>2+mTj7f0Gb(Uj7tHZdzfpD1g9@VY<`24 z2}wM&Ye%Gkm#Sg9M67Lh2B`rDwiE>d%wR+U24(<92Sd!w0YcB$(9*ix*ur8*7B2|r z=m>vc1}^Aj>FMxRbC3z|=?tV|eHI4>00RO{u#3Szfd~^CAjrv}!iB}2gn?9{mzZcw z>g@9cMu4zS{)EK+>QccGEHS7MC9vqLjvkeBvcV#QV9`Vj#Tcy|0>dW9A%1$ei-BOy zkxS$*m|{bd+0m06{T%#v5W#|V0Wh-DP?OCT1O~P!==$@{OJ~-~lv#9i+7Aqe+F(48 zfFM*t&>ZP3aFo*@1019kai$5uN|Bh_GCj9QtAKNFxf-A)T1~ifKwSdnsStZEEe14j5 z5wZdPpcNZc+&7VXd}Ie-D|8@t7b0dPmlA=IiLk%{4xfJD<9|CQ1S5hnB zw#GsR>H?aKVko$RcVTD}R+rJ-*Uf!?upq&OAvv;#A2+~YAA8Ti0*9GO$o7~XrOG}m8i@e~)LQEz9olB9tlBY?O)9di$0)Cv;wah+u~bNGrVm(o z>eZ#oT5wN1kg0c3v=>OD1rd`HND{Uc5GkN{Wb7I(k|Ays2)Gzvs1t*CunU*5y@9f> oycfLqouswkivf?uFcS^5{+46w!Il=R@WKo??C`@7V;TVfJApTrr~m)} literal 0 HcmV?d00001 diff --git a/glyphs/stax_dexon_64px.gif b/glyphs/stax_dexon_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..d37f6b26b2329c277f146a93b9f89539ad142f8c GIT binary patch literal 914 zcmV;D18w|ANk%w1VL$*t0P_F<000061_lcY3m6y}FfcG+U|^u2pwZFM=jZ42^z{1r z`uzO-|Ns900000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1pbi8Nvpj$>&?6WU?`4cX_m;brQ3m=T~TbZk|i?S27!?ogMklY z;Hh*M8~{K-D4rFvpm|Ng zIa@OXo`MMy9!m}=#a&|1lOd`DE35sBqY)s6U9B#0YgAx>PmN`LVsw@8qK1cAoKQeE zgQi6#>M9HbWI>;#OMX@KZ1f`NT9m}H6_lY2Tm?pS}x! zEg3xi5!7%!@h1RQ_0P;Yk5rH~Y!V`a60mYwC z9C$$)NNjl$oqcQIfJ-Yj(GvhbA^BlkgW|0*U&K z)DA!^br^yowv;m#G@^BcVL6*A=oJY0E%6SCU%Yb)I?rVWLSS1q^Ts##;PGP#E(P<< zKL4F_g)IiyhJrGa`Q%*y=;;znLL->~S0k!m7)zw59LPn5FcImA4cth|ln#Rdz+kAQ z4JM`&?6WU?`4cXB1^B9zkHJFozHTKpb&?6+sOY3Y~Ca z==lJK;1Grw9BTsHGNmXyeT2lcWVjw*+m*oU6M(~>8TmLspgrC75%u20$G2!&n*G-L&dZwd!)nO>izSDy+9feV5{2}P=? zKA#e5bEE`j2wFo2oj;_Shzbc>xWcQ%QZWjQjeqibGcgP43K+gj(L$mCGOLs5OD-6&KA*v^5Rxmkc zx?xC$C!wEf{tDOJfXGjxn*<>}>3W3k;Q}6yCZeSD1KCA60q78-WNRi*Oewt(yin55 zM24oOag>8E!$E{fgD#YMB)~`wjEvwpN)@D`j2%P`&|@NtAJPHnz!H+_q6pFdi#J5pD0-~^)no=wL3qq ZHu-H35FUO3>c@yq1tzHAf*wQw06WyX2f+XU literal 0 HcmV?d00001 diff --git a/glyphs/stax_energywebchain_64px.gif b/glyphs/stax_energywebchain_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..5cd4c4da1eed3dcb278b2727ab1204f666919094 GIT binary patch literal 836 zcmV-K1H1f3Nk%w1VL$*t0P_F<000051qBNW3l|p`EG#TsTwI@@pV86L=jZ42^z{1r z`v3p`000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1paWzNvpj$>&?6WU?`5Hg&amf5JEewg>fKBX)j1h1VG>OK0rV~ zh#_tvgbEmJIsrr(l5;2wp4e>hFumli%&a&_FdVy*Y9Ksr`wHBy;p(nC%hS1i-xL@W zB?$&>e0zQgfFTM7g^fXeBL)JFlu!mC2LzRr0R(X!N}HPnXB>>8o0n9Rs96CqbWa1H z7zzcgS$=?eSOpsgvA9mY5~s4X7PrD!0tJAfPp=ukgv&jU3xik$2#FQO)=vdB37XM= z7PgyfLpSI z&PkX!EEy|D{;KA9sv)n*r5sqKRmj+g8;%{Xjs)zbU{SSB7Csg_n2nVHE)Tb*={F#! zm`*w$5z}UAK?08Rb|v*8z=D`E7_&HAa0F2?`Pi?VF*@jKWjp z*5583Lx8fJSFB&v3S)a1&{xt2ff@%U1(@|xYq2avS32&ArJ(`@bPg*>oQ1BIWLg2u zbn+9CvccJi9)TtfbY-A*0fdCoHZ;I@K~zyFs4<%s#4lFw?Hbar?g?3YAxciVtxMj0 zT(Z6s5iGoXHfg>jRTmrQUKkklqxTfzt^u*h*X41X0=1N?s`NU-b$+qHod#Bj4ZxEG zB}oz0L5v{ppm&BnlVLF06D~QW0}Lo&1CRkLY>|k3kVQm+bLkSB~-%% z2&VLp1`9H1hBqkQ@`{Fnu&_`=9Te6?Co+hLf(k*P*W(EkF62Xd83ZMU06YxfB$G}I zLBs%o4Wl26xP`-DJ|IA+r7VBInB$ksprgoIWOk*?2#H8yBq{@#X#+3I08z$?NMQKp z9z1x61`cynSxB6CqES;7S@MA%c7K|%L?KaV*eC@#sKCk^q_t3l8IyiMqzdl10K<@- OmTKy$sHW;c1OPky#8K1$ literal 0 HcmV?d00001 diff --git a/glyphs/stax_ether1_64px.gif b/glyphs/stax_ether1_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..ec41146ed8950fcac0dd976223540fd69d4a454f GIT binary patch literal 622 zcmV-!0+IbkNk%w1VL$*t0P_j}0000B3kw$)7cMR?UteFMqN3H+)#&Kx^Yioh`T76< z{{R30000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1pZLTNvpj$>&?6WU?`4cXB1^R8pNT#o*@u$t;vF6@0A=72%b;| z2%v;JB4FS`)|5ZzQxE_EazSZIX>Dn@0;|>d^&k?xuz0B}ZwdzV#J2_j-I>B5PT`7k zcozo)0c~??Yd=|m3JC}WR!4_*Vv>wXmI`!~OpFQ$1XXrvlw&l32nGS7r<0{chGm0m ztrC8mi(imy18JhAWM#LVuCHug2?UgY#l{43P6fYWg?)&|%t(XNW0sr70mM9y#@^Sj ztC>^f*2Z;vLdxvT?om6^?zP|Uusia`0~X!lSL?-r0#twnq(@2AfC9OmglZ_DiKcTD z3B;~8hFJ^ zBLf5OBoQ#9O#-A5#T^iV1gSIVq+8~0A5isx3gpKt3V zE<-NSk;@GsM*L!yS^=8}X45I5h*g^z;lF~|@XKLgV8^_d6G&%eL_ I4-o(WJEu(u&Hw-a literal 0 HcmV?d00001 diff --git a/glyphs/stax_ethereum_64px.gif b/glyphs/stax_ethereum_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..48fa1ac7ea659bc6b4e0b2b6076f5e561a7a2e1f GIT binary patch literal 556 zcmZ?wbhEHbbYO5`_{_}!1gxyAJUl$&;^O-H`f+h_3l=Q6aN)wsmoGnm{`~jv-~a#r zgA~Dl;!hSZQ}I8yXKrG8s&8U?W^y)PdSY&FqOF0Ri75y&=z!FKY+zvdS8&pE^1q! zF;iBNjZwGv!|SfLq(v8byq0w`>s3#7*x!A1=P`kOmzm6}Bz5b8^trj3#8|yrUAa2D zI=HR->Y3~&371ZbV&$CJ#WpvpaFPy7ab+fqM2hja6;=|z4m z2j;B}TYNO>kOO<*si+k9PS)BBK^rZ(*jHT-V%lag=iUa6g@*f|6tGts-e$RWkMWW_ zXWqTSx9;pcrs|3?aT7o33j#XgcmZW^!_K$SDuc;Qx1Wj`I6#S&_D< ztMjs%oQ1EKvyf;EbHT|itp$(fPCm!)d)TXTpC(u3BIUTL>HFMe7^Yi`v z{r~^}000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1paWzNvpj$>&?6WU?`4cXBbJTh6yno$|`dO02IiqU&deqhMiE- z`T+=s;jR!c-juUL(>Vx2O9+C~7C>G{2}5AIEqq12t?_mKWXWm)A=lOURG1SJ+JX&@B{6hsW{t)7wE@Z-{vf?%$co^nxC=a09%7p#puqV-D+Y~Ro> zNcy7+qbyDYG>-g`OX5k+wv@UBNDhLjy+n!PJBeG(J(J*G9Yr}fg*2n)7`ISha~zAy z{XT-eyj-#}LaXCZg9P_-BA;Eq{+@v!nX%+K#Fm?WLpRgyH@u-9A1)5>_4DiBzaatu EJ3|fq{r~^~ literal 0 HcmV?d00001 diff --git a/glyphs/stax_ethergem_64px.gif b/glyphs/stax_ethergem_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..8bdb8e5f1ec0b86a9428a51c65c313be0066a58d GIT binary patch literal 649 zcmV;40(SjJNk%w1VL$*t0P_m~000051qBNW3l|p`FE1}$U0tD}q0rFK=;-M4^Yi-p z`v3p`000000000000000A^8LV00000A^!_WZDD6+O<`wgV`~m)VQp<;JuogbH8eFe zH2^FC0000$06+i$1paWzNvpj$>&?6WU?`4cXB1^BA_Re`uo(nKY-33=yLUew0RVvJ z>mdq4VIiR?#twrdKyXMnVMr;U(7cwQTEO7oE$PAmR5_$L5W>Ro8k8^yg7Dhh!-6LX zWP2P2eo}gZ83}KNLp+EWc8o(rj~7{zTQ8Lqk(gqKn+lgw1W{p2U5{<1QdERtV^*6w zctU9k2&}egn+srC0(zsi1DcO#S_HDWaB7HdwYD`0R>MMoh;?v01_pHkd5C>sHMu;< zq{eHnTEza9tcmI9L*|kNXO<|+w}2VQA}I~^j6&&^ zJDGB7{=?Z&!nl4$w?Ud zdIQKM*%zEMp>!J>K}pi2H?vkk(}_tbX{=NQ)Mhr>+E-G};Dwn$Ict~qR2Ay0hA1t+ zD>=q}=p(7Ad!{ED;JiRZ?!6>vkJF7I`0x(rF~Y9u8>3*J!z(b2W&jt#;rn?<;|x88 jCJSjAag%=-fF>G&861(%T?kgd0&fjQDB*-7L;wIgPPPkV literal 0 HcmV?d00001 diff --git a/glyphs/stax_ethersocial_64px.gif b/glyphs/stax_ethersocial_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..530fe5540540b088b73693cb7c31e7551050b6dd GIT binary patch literal 265 zcmV+k0rvh!Nk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0^p2~smtvT zqnxzbi}M5==pS{W2bRj%nW}+`tJ$V67;|&bQZ)(hc9<*qVh`eH=qt*O$mH$R+&!VS zMR0nkLY7#Zv0KrCb=UEx3=^Ve+zVR$%dB5>OuaXf=h=6%i@#^lr!oi>NLQ%z_mt?+ z2-jv9x$?+R$+UQu2{@_PiTBy?1{x}QNO`KcNy-y;>6WTmDi|x<%8GdlIjhLYyXE_9 zmNhzT`DN@`3n;ma80!QUB{eoJrm>n}{ia2&Hd@jCDtnO~r9?vpQ PUmtg`zt7))Pyhfs4>Nv* literal 0 HcmV?d00001 diff --git a/glyphs/stax_expanse_64px.gif b/glyphs/stax_expanse_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..61698c8d992cc6ab048bd744e5c12d6c7c4d0d5b GIT binary patch literal 384 zcmV-`0e}8SNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbi?iMh0ON7u;)Ox^jUsBYsd~As3|I0@*U(*p{Hsg+dZ!^!XCx*~u%*&@)If1g z&h&Z3Tv5Jl)Zyh8!(WEiyp6o3JLsY8LnIX}p-~PW19^7-`-aCvQuim;b$2M}0+yp! z=r_m&*fANGNErB`SQ*LrX!vtJkYb<-Km#2&6*;kqSPz>3O>8!S#9gS=qOf?JcJZ<`j3u^9)K32P)OkF)q zDE%%!T>hLQ34DxOqIR0-2{gFRpCElFXuVp9aLv4jhAQ&Qvo=MNZ)`BNFre ec2Nngt4fm`G_2GPagCwytJtw*%bG1)0029>D6{ea literal 0 HcmV?d00001 diff --git a/glyphs/stax_flare_64px.gif b/glyphs/stax_flare_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..c834fcb363058f7c76e13e79df68f7a72d437211 GIT binary patch literal 199 zcmZ?wbhEHbbYO5`XkY+=|Ns9h{$v3&bwDIYhJk5bPyfo(Z}}I`*>bCU^RflM`P&|O zR0Vb})B3UIowd~mAM-DNjee}t`{RF!v0YyNqlOJr?y31}c4j+fPsq$`KAW}u&bsg1 zeBH;Nd^*N;W0CKT(vNS_(jVpX?9JPGTL0I%J?j}IDz3Xt7hRr~y6wb`7e6>8H7z}V yZVB%cXsK-2Bzd8k)9YoBr`4{Yt|~37lecC)y7}^_r19y_^x3O-M+Y)6SOWl7=3KD= literal 0 HcmV?d00001 diff --git a/glyphs/stax_flare_coston_64px.gif b/glyphs/stax_flare_coston_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..28822f300826df7ad0299283f7dbf5f6c4783baa GIT binary patch literal 210 zcmZ?wbhEHbbYO5`XkY+=|Ns9h{$v3&bwDIYhJk5iPyfo(Z}}I`*>cOe@!p=_{B6-H z)1KY5eQ~PEkNdc<&t{+A`QGQ+%lV(YX*wdm(cJn|oY$OHn#~TmGgf`=I-9lq&bsg1 zeBHQJ}l`VFQdnO~#g2)`6 IKn4bD09!>|hX4Qo literal 0 HcmV?d00001 diff --git a/glyphs/stax_gochain_64px.gif b/glyphs/stax_gochain_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..aec56d0059144ada416edb971a963784ba33596d GIT binary patch literal 314 zcmV-A0mc4DNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbiy_#2=dX352bRZ(0_M~y>AN~(^4777BK3ZsxxRz-Qn=tRMhqE;qRR5tvOIeq zo|Hp1*eJ8?Hj<=%AK^wXc$96#(%*KKJAW6Dw*pugcVU zlHu4`6{%>ZhgauxDAO<|8y27s>~Ex>^c}${KogI4T#*WxH5wE3pek`MB5V zO8G}C>u70woR}=E2CQ4yoa+fqDqXA`Of5P%%^huhofQVy?er8o6%8t4CD+SZ{LY#|8-JSD1x(QX<#( zH;6NL^x}4P#$tI%;Uxsnm6@pXiPt#_SxN``7}w`h`PRr9I+V9Wcq+77HHquW>su>} z8Y_A$n|j5X(&(xkE+DN))Yxf13zm%vy`t5-3@E=@dp`t(@<06Quoo{Ing literal 0 HcmV?d00001 diff --git a/glyphs/stax_hpb_64px.gif b/glyphs/stax_hpb_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..392151ae65ae6ccac05e8b2f7a1a7b7fb1af18d8 GIT binary patch literal 354 zcmV-o0iFIwNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbizV2((+zUoxP+!ij^~x;G%Ov@Er+ZP_{86WcnUJTv=)B*xZIg?9?RKSkT z9kfa%4q2b;DKRx@Bi^xCYkri?;jntm=H?vAHwx`;;AYWnb*`6o)`t-D<;O*rIM`EE z_?K6Nl|@L_2q;;J7-V@D$rQB6CxV#?c4%?=$#goIN-F61h-yXYsv-Kyc-winv}3D@ zi~5_o+jxWbL_11cY{mSnD9735S}oNk+*`TbN{wxY%m^_zKCH?6?R#E+%M1!mC_Q@~ zyAC;C&AW=Piq$Sqzk2MPg*$eSV7^Ik5-N<6r=hxd|Ds7e=&x9$i#f>(ifV|#AiPaL zmcd$8Cq*A46ul)WDdZK*nCPz16bI$zw3Iq=I_&u{AkdvIhfXt!G^x_15()qSJG1em AXaE2J literal 0 HcmV?d00001 diff --git a/glyphs/stax_id4good_64px.gif b/glyphs/stax_id4good_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..6d04b228f32bf20aec3c73f805907ced6b68b4c2 GIT binary patch literal 339 zcmV-Z0j&NqLtnW%1dKeZ1i&?@1mf&%@@ly8HKqS7+xDc;`cSXsDM5 zrq~Dxz_&0r*+wblc)8csw^q0js=*@3>6jU+*=bq18J4<;BTGsNH;9}?H!KJ{F$!aZA`xYylLJ( z-&<`z4Xujp&-Q8`y?pWn;_G)U;UH%LVTTX}-dP+z<3PCy&4h`R-k$OSSv={bwj z=kh0|0jpNuqsh#MyG90h>?M+iT(SE4UYFzUL)|WChKAP`1mDY_M|qdbgR!d!-BXeivKNMih~b!KCuT^f@89 zT65YM!gSIFP4?ZQt_m^P)!bTF=`%X2L0ZScu^NLE&tv-e!Tcq0=hs&U80dvarN*Uq zsCeRraOL=TxPxeCS$OkkxG9Hewg-y!M*|v4RFx{3gxYHAC-iA4o1nRQ`$t>rxr>_$ z94tIcYHNJ_Yuws(8=I^Q7;WeaIovZy4XeGK>zo|s8qQTm&DIMZ{c@gF)lQr~j@@_) hKdagfdtbK1->>dooPQYzt}y5Yp~8g>8wMx<06TLhgWLcB literal 0 HcmV?d00001 diff --git a/glyphs/stax_meter_64px.gif b/glyphs/stax_meter_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..ee0804bc30603bd4c996b7d13b0f72b1cbcd0840 GIT binary patch literal 311 zcmV-70m%MGNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbi?iOm`wxcV1C(YtYUjG96brYm6W8*L*!u12j6bqTgrFG4=s_M~9cGiYaVDV| zYLQp5hO`sz78?PJ#H150;H8nRK2i79nJ=u0{X zIZ75RjQe=ZD%yv9`ApNid|Y~VMnq}wTo>Sj>HClQrIX%7B2di)47q{xvZ JOGYRF06Wl0kI4W4 literal 0 HcmV?d00001 diff --git a/glyphs/stax_mix_64px.gif b/glyphs/stax_mix_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..e3a3e570ad3c921a664050a521a2523d3e2d32d1 GIT binary patch literal 246 zcmVe`O48GG|q+c%eIJKwwff|w!kV?0iNK&2+>BtfH( zDb;biQeIjlt_u!}$K*1Z$)uv!&D>5p>%E`xSh{NU0onY0TS(*5S7!jzK{!Z5sE5dR zFn5@T2g#V#CrDW|ba@x~#woeA>DXBr2bu}^NgBE|%7&RGGItrPg3<_E$i;H|==d9m w`xU&FLTsl{i||LZ9QF(r-8D^ZY=&l5%&Wc2-R&(59y`8(T#lZuo?ZX|J779*+W-In literal 0 HcmV?d00001 diff --git a/glyphs/stax_moonbeam_64px.gif b/glyphs/stax_moonbeam_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..e8485ee55ffc61d4337921b524d9f77985dd4c17 GIT binary patch literal 212 zcmZ?wbhEHbbYO5`XkY+=|Ns9h{$v3&bwDIYhJk5yPyfo(Z}}I`*>bCU^SwR4`P-CO zr=(eCJ>RuVg?s)x;p=bL+}PEr{G0y;YlDN#LU8gx$t8`Bajh32i?Guwz L)6)~fz+epk(Cc4E literal 0 HcmV?d00001 diff --git a/glyphs/stax_moonriver_64px.gif b/glyphs/stax_moonriver_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..1809857093c45d6200884392edab68983cc8e68f GIT binary patch literal 294 zcmV+>0ondXNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{x7SsmtvT zqnxzbi?iMe_zwcyXoMz6X6K5g6AQO)6W8*L*t&=3``!!uhPa_|W+bMPM-o%Xc{Vpv zsH$qcV6&F(Pvhmj!axkUtUcSVH^!DN8b8?ymXCS8!w&N(S}4{PvS6aO=l2mYXqf2K zD91CF7ReU}NZ97~NU>RBNm;ju+38nlTKQG#d3qUIv-BCu+Hq1OyNcTyq{&L@Yv}+= zb*uY3>jT?MY@90$whXO&{4AXtT0O#C42;~&P3=7$Zas|cJidz_Oq_lVq21p703T1z sYaf43E8ec}u3Hb^K7r}{$qP6TVIGAG8K!Y)<{QL`6f0W1NTC1#JBk#CcmMzZ literal 0 HcmV?d00001 diff --git a/glyphs/stax_multivac_64px.gif b/glyphs/stax_multivac_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..e3ea7165790776989fd95665d64493c43d73c7f7 GIT binary patch literal 349 zcmV-j0iym#Nk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbi?iN*1JH%Xr+lEunWcH67Tb=nTfwnmlk}6{L9g2-fIgy+W?UtA#-OZu%s`#E zY4l}PPE*$6>_@~bZCdA2at5=?-d-eKT@Sx=w*wwm)%9%ZKG#6@cctcs5OzoR#K&N` z2*{(D=lF&QA$TY`VOc4c>A4An1v*LC$4G(sX!;3xp<3GMDy9j0N+}abT1bgE7+9;x zYkRw3ODw8u_seW7+&bI58hM!vyi1&ForwJ`o9*1ai?&@Yj{5C=jSe0j9eR!n-LC9M zKddf)td5Tk&CSl6uT_rrjT=bNpTU6T8Z}&KhLgEv!`PJKw+<4-CNx~K43a3t`LGQ)~HI}qCCm2@+ZpD& zi#tqw3w(?mY+Nc_%lz!z3q38Z!+Tvfach;dsgn1ytlHx6)%tT y{cC^UoR5yrAGq%yxoQFdMk{Dd4#I?&76$O=5aPmO4h{OLh%uwajRO%10028+i;Q&u literal 0 HcmV?d00001 diff --git a/glyphs/stax_oasys_64px.gif b/glyphs/stax_oasys_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..81c0e5fe8f52314723512828491bd32eb99c4c8e GIT binary patch literal 340 zcmV-a0jvH;Nk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbi?iOm`wxcVNS5Y_rs~SJt_8&MJiiEy=W(m|{i&k_Lpa7zQS2lazQz(mbNF`7 z+9fKTQme9xl?e!FYg=Sj@=ct_>+f1^ z%T;TOAFqFXUSbCU^SwRI{B24Z zy~|$A(F$0X_Np&e=8#F`-O|O6L;i1kndU4vp+Z=#*gcuwGuUmWfBMJkDGZTUUMF$) zdLF&I)XbVO`fTPFr{1;mp5|Jy-{aiy*&Dj vmP}30%oxu(**|!4c+T#bv!iM4qUpJ-CBl8H-`-uDS=Tpj-M)Qs3=Gx)K^Sn< literal 0 HcmV?d00001 diff --git a/glyphs/stax_pirl_64px.gif b/glyphs/stax_pirl_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..7c97331644305038bf18cf5fa28cd0b08bdf2ab9 GIT binary patch literal 293 zcmV+=0owjYNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{o1RsmtvT zqnxzbiyzoK`^kmh*n}pD9_E^o>)U$o9AEQYQ}>=n``>c_fk6c^a4aHuh-A-cfVQMj zW{s+{rm#)zh?@X|yxC3{_o1@RG#T0mW5+RX_`F)Lkn#6re*EXxRyL@&=Oo4;g}BES zcIbt*M%c&Kw|EJe2eqkLC^$)ZA{Qz;YHCJ$YFWy<3d*s-7&sfN80ndrdfQ3c2vJ)J z`wIAp8R&!iiMngp+sf?rEFz0stZQqxY*EX*ZS$)woROI5{LS3F^=nR-3mp>-e`VF~ r!efu}6JE4Gu9WT{z<|^SYS?E`LcW345_-$#@LI%)6f0U(Pyhfs8=H;3 literal 0 HcmV?d00001 diff --git a/glyphs/stax_poa_64px.gif b/glyphs/stax_poa_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..d857c17816569a9a3505ceb20012d250b68834f1 GIT binary patch literal 299 zcmV+`0o49SNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbn}FV2zYYRl$SGv$oZG0Hs+hj)>9(=myfC8Aq#vr$Zo`}`b2Q=@J>+uHR2C0W zX43i$RH0XHb}Rf5#k_7fI7VZ<)3w{#e#^mfH@%Lz<1P9SI;uuRdg?KW3d*^v+3IQu8@s7WD{I>Ul!&OCiy}pa z^=bBdIV@}dxGY+X8E2gOoIERyT&nDBniajX4Lyxr?VZgX&KoSwZ2nEX4&JV=T?fXP x*UV0j53m0&?6WU?`4cX`X1Rt}MA6MS-*}QV0Mr6bX$cg+Xoz zAQ%?D(ZWC=Is=3QGTB)m2mz-SAdpct*5G!mGxWZa1u|g}YO~~=QGsS84$ZNkTZjh= zQd2ZGeo;tFaXV)%33+346hMw!1wIEjTZ$Mqm|K=`L|rprcy3OgPEm9nY?C=9f))p$ z009Rg23oMO6thIOB7LVKFEM5ev6sKMA-TgIYMeO&hP|D&%plH09}7UHL!xR7zC*yx zx~zD#P6N#4Ip^KmLmb7|W0mBz^3e3J8l=S;Vn6~sY#`M91AxI>n}M|S9qd={IA@YqfpKjR6ofUnwziOh0ES!4&%Os-Bmf&eRFn~ViLGluf= zH0{m}EaQbGvg1Y^uXTwW3Bi`ZKX$2(VZf*MD^^w)Hg&43gfDqzv7=jJqiD=@9 PD5j|5iY&HRLIeOitdJaz literal 0 HcmV?d00001 diff --git a/glyphs/stax_reosc_64px.gif b/glyphs/stax_reosc_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..fa727e3705f59ab67f1e38145f2453dd9c3e4ee0 GIT binary patch literal 314 zcmV-A0mc4DNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbi?iPRfDZ!Qh=k@xcITRE>)T%M99J`3OE;ZEJ8t<2hbJ5HNTeW_!U^+v(?O?2 zU)8mghE!SWc7)WTNZ|$5_@N266;B9(Hru@-!(J+R$~>2eYTLMt#=+gZ`5I=Yv+_DT|33297b6H5SjZtK_%>$- z2Q&oMr4X5uh!93uX?b}drMW4xB{_&GW@1?C8Mnt8km}kRTQw^?N_(rQm*C^LOPUMW y`#St}_O+Uc46L+l`sw^^6wT{IT`hDC`m4>{*_~XgZ3rG-?htyezRn&{0028G)^Pd& literal 0 HcmV?d00001 diff --git a/glyphs/stax_rsk_64px.gif b/glyphs/stax_rsk_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..5e25ff6b25ebf143f3cbb079044138eae930e619 GIT binary patch literal 295 zcmV+?0oeXWNk%w1VL$*t0Du4h0|Nv9|NkNR1ONa4001li0000$06+i$0{)DTsmtvT zqnxzbiy_z``^kmfM=IhumL!U*D=WGl+{zby+BY8R7T@zxfE?i=xFBvC$O?-=gw`ZH z6VOVFL=#o+^|8gql3%9Myp)E?>)#n&-nG5+;aeSd*N=C3UW@|=7YNp8@I?2=ro_l- z*9ZxN(ZmP2Xmn_ZIY_u!xaW!B80s)eiq~aCnV2Q$x0;#CS_IN5YFjC(p%{P&s9VY# zo3hx-X)JaOT#V}#4BD%C`z#y{orcAro@?k{ tiw(Xkj%j+DZ|`rNxq#=s5iF>UAT)mq874ePj~2vT_$FGsh*3xZ06WCphI9Y` literal 0 HcmV?d00001 diff --git a/glyphs/stax_rsk_testnet_64px.gif b/glyphs/stax_rsk_testnet_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..5e25ff6b25ebf143f3cbb079044138eae930e619 GIT binary patch literal 295 zcmV+?0oeXWNk%w1VL$*t0Du4h0|Nv9|NkNR1ONa4001li0000$06+i$0{)DTsmtvT zqnxzbiy_z``^kmfM=IhumL!U*D=WGl+{zby+BY8R7T@zxfE?i=xFBvC$O?-=gw`ZH z6VOVFL=#o+^|8gql3%9Myp)E?>)#n&-nG5+;aeSd*N=C3UW@|=7YNp8@I?2=ro_l- z*9ZxN(ZmP2Xmn_ZIY_u!xaW!B80s)eiq~aCnV2Q$x0;#CS_IN5YFjC(p%{P&s9VY# zo3hx-X)JaOT#V}#4BD%C`z#y{orcAro@?k{ tiw(Xkj%j+DZ|`rNxq#=s5iF>UAT)mq874ePj~2vT_$FGsh*3xZ06WCphI9Y` literal 0 HcmV?d00001 diff --git a/glyphs/stax_shiden_64px.gif b/glyphs/stax_shiden_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..6bbe136ca827218571a37244bd76013119183912 GIT binary patch literal 342 zcmV-c0jd5+Nk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbi}L}T>;H732bRGonkq_eqe`&~+rkZ+(6)rTGSb=QUcS`OC_E9BOJ*;*d>VAg zVzKtC0)tbe6ENfMjLqg3EF_D+TPaM9?ylWwk~nIva_@YvR?g&e7568oWXM(+2G+9Y zr|8lpDMtu7bcpF>dBfO=IJ4=2W>>RNsU?cJb_3bidCID2HwiH+Yg_6t3OmM_S-a61 z%;TF|H#L#^tA`vhyUa}NN&ClpBsnb`LW*o0ZR&dH9mVMEs-3_mDz*Yg|m`Z2Nue?XFAnDFV8r`FNb@7(zAi*X06eoIr-C`@3wD!*{;XeC+PP_2zV$+6sDFo zNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0@93+smtvT zqnxzbTLIo2XbxsxNJidQrpk$`F59{(EWdPJ!Xr-VJHPS$fEMA9NHHFf5ap8Da6X|6 zX^dL6Vjb4&79llwzfSR(Yz&;DnzJgcUME;;rqC?MuibB5oaSR@cN6%xH)SK2=9fpL z2uJq^wG$Q@H>n3XgecS1cEva2DfY#-SenUTi5iBQ)#duBqng#dV5S=nEf3MEFSLM?QLDWoz33v{@zdk06Qvq BaxDM= literal 0 HcmV?d00001 diff --git a/glyphs/stax_tecracoin_64px.gif b/glyphs/stax_tecracoin_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..4fa9b491c6378acf04dc51ad07d02685718cf33f GIT binary patch literal 389 zcmV;00eb#NNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbiyzp$=Z|noM{b~1nqf+wRhqD^JF4q!$T(fr-l6-sWIkIUD53#-HzU%hgf*Kw zWsI3iW|0@^Re02fxs+fLFkOz24GgZjEzTVLdr5qoUS4{R?C8Ee zT#W6V-`y@v4sY*KKW5GLakDm%ptDW!5E^tNN+u_UOZl=U#a$D0vU>=U+Qpba^Q;tk@xxG$JB)f^iOq_} jpW~WF!2%VUR6tY-Z7tc=>Q@Qz#+p5gHmzC*1poj$^j)-} literal 0 HcmV?d00001 diff --git a/glyphs/stax_tecratestnet_64px.gif b/glyphs/stax_tecratestnet_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..4fa9b491c6378acf04dc51ad07d02685718cf33f GIT binary patch literal 389 zcmV;00eb#NNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbiyzp$=Z|noM{b~1nqf+wRhqD^JF4q!$T(fr-l6-sWIkIUD53#-HzU%hgf*Kw zWsI3iW|0@^Re02fxs+fLFkOz24GgZjEzTVLdr5qoUS4{R?C8Ee zT#W6V-`y@v4sY*KKW5GLakDm%ptDW!5E^tNN+u_UOZl=U#a$D0vU>=U+Qpba^Q;tk@xxG$JB)f^iOq_} jpW~WF!2%VUR6tY-Z7tc=>Q@Qz#+p5gHmzC*1poj$^j)-} literal 0 HcmV?d00001 diff --git a/glyphs/stax_thundercore_64px.gif b/glyphs/stax_thundercore_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..76134be81064b2c2a45fdcc2d6e9c78f10d5c796 GIT binary patch literal 287 zcmV+)0pR{eNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0``oLsmtvT zqnxzbix=2@=kIhP0G7yznkAa58OypDJkBm%U*3v$GY9I4en6s-q{~%~zNAvZ+*xpw zsB}qo|J3%-LMlaF%Qg$`*Y33mwZmjos<2;f+fEEe-*gE*p*h<{K{ER}C9q lZKCbP{b6mkFH=q)z<5svwu5KTP{JSx7dm_hF`~o*06PM)gmnM_ literal 0 HcmV?d00001 diff --git a/glyphs/stax_tobalaba_64px.gif b/glyphs/stax_tobalaba_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..0125e6b45ca7127e161ad0fb4534a92b15b2e45a GIT binary patch literal 228 zcmVg}tsmtvTqnxxZ0Ic2# z^KW4uNJ3&(rp&3f$T_+yjLIo(-*laGJKqcag1#S+C@~(959N~Ca6X|5Db-}XI;1ge zl{@2#$Kx;gjD}s(Y;v>>S7PJzskzRs;PaZjyXYrJ5@^&ysOEBL2SP~X2USNE2|4MA z$Fzr;85C%_+0&SF2r3p(CJJV7nwa&H$||@PYd9-gNPF8bC!|HPlByR8@5 zyPi2sdoHy^OM938nUltEZ&sw&S6}=5w`i|oVEP)Ce9z;XJS&}4FKI5xDrMVzT{nC; zPj~RfjgryUt7DgMo!wcvIU`c6%i+XJUziWQ#I4o zGL^G6^TpJ#5*6V^D-UwINTvSbT&1!~Anl=47pJuM%yc8RW3#MpCzXq@_{HthX6$2> aGKXc(PV=AJD%xf&(2mWmog2WwU=09wjbhdS literal 0 HcmV?d00001 diff --git a/glyphs/stax_ubiq_64px.gif b/glyphs/stax_ubiq_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..740b7e99c57956e11ed210ecb6266fcf7e96a535 GIT binary patch literal 295 zcmV+?0oeXWNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{)DTsmtvT zqnxzbizmq3g5QPEM~bFGrstZrtJuab7uWMu=Qox2d(;d59KqsnQA{R4x1@7fIyt9M z6>O?R=sMW!L73?pwPTOiNA_yY+b@>Kwx!>|xNNQ-*`coX27HexKSlX82E6= z&=zoK$VSAsDA`DvSs3ZJNvGF`SxJTSRF}6_Itj^13i^p@_1Y!TYKdfLiwh|#w#zvv z2)OGzd+AuQicG9}I^4|q%)IwE-Fb*;EsULP#+~h|?AaY1rbw-ObzEL8#n`Sn<7$4C tzHASTpRZrWkFxKdF?Iq0k}H@C9l{0*7cwO1@S(PdKqy+gi1A1P06RW-j8Xsq literal 0 HcmV?d00001 diff --git a/glyphs/stax_volta_64px.gif b/glyphs/stax_volta_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..83cfb91c4d5a5b4af72863717e74e00a8edb5940 GIT binary patch literal 339 zcmV-Z0j&NwB2lwg;fgjB9=m{c`%3fmFjJ2dj zTdfquR!1P}&ew%q!C@T5{4_npCv*c4;=2fWp zhIk0LNEqN($s^(B=afmg$qAte`3M>}N?CUldODh_YU*f!>MAsulvvbQ8VN_*t9xUc zOFJAG3>$mds<6xKIqNG4{3~mzY&cC_y}T_gTucn!Z5^#Wev8X(oE)yxE{@C|&WnC# zUH|Srf&E9XHU@2qx^MCX;+sQmojH5_3=UKnFx$gxjP||Cm(bagB`N?nLizH~4p!(d54~t5mLJ*-7M!j+jEEuwpZ(&Ye7a`qWtf06P!Bo_PQO literal 0 HcmV?d00001 diff --git a/glyphs/stax_wanchain_64px.gif b/glyphs/stax_wanchain_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..27a5582dae3ffb94e94341e876fbd341a86e610e GIT binary patch literal 313 zcmV-90mlAENk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbiy_z``^kmfM=IhumL!U*9t)?g6xZ_1*hY;veDdq-U_w`t`rgtegDJep^$$94kquJ?Mswjne3cBZLlj*t|mH0|q`Sv;V=T$iSNd$bW zdx{j)D_V!ebF5k$8S9McJ5_L literal 0 HcmV?d00001 diff --git a/glyphs/stax_webchain_64px.gif b/glyphs/stax_webchain_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..585832f1d5300bdbc6f36ad321190d23f89788da GIT binary patch literal 217 zcmZ?wbhEHbbYO5`XkY+=|Ns9h{$v3&bwDIYhJk5APyfo(Z}}I`*>bCU^SwR4`P&|O zOncV3?A57l@3>bV@VVZQ`P?V(vCZ8djP8eKF0N1(llKUmypzXvq0@yazc#xmhx>}3 z{#Sv~YR}jsznzen z`R(G184~KDGc{MbO3r$6MRVs$l~^XBsCXj)_8URV^V>|!= literal 0 HcmV?d00001 diff --git a/glyphs/stax_wethio_64px.gif b/glyphs/stax_wethio_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..8a66b1209e177a7510e58c8cff09142b28b5e4c1 GIT binary patch literal 305 zcmV-10nYwMNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0{@JUsmtvT zqnxzbi?iOm`_BR5NS5XaF6YXcDbmLAYsfbG-g=queu~2cL$1wGbG#&#MIsN`>?|i! zVYE`sWF1?sNYPbYDNooK5*CxdXKxvM_^Q{EH1zGJ)8g%f-Pp&6w->PW=cLCrhz7V= z7%0}5C^(4*AT@RE)61w|V#Z=&0ys>6q3z=lV+O3ES}5GAkQmdu%af{FYnSb{$n7A>N!`s%_2uuD*1* z4ez7PS)Q*x|Lsi2o_;n65xiya;0i+C6apOR@Y#om{(2~6h%uwajR+h&di)47LjeFg DCiRrF literal 0 HcmV?d00001 diff --git a/glyphs/stax_xdcnetwork_64px.gif b/glyphs/stax_xdcnetwork_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..b990ab31e5b34b9611909f8753f1b916761b45b4 GIT binary patch literal 287 zcmV+)0pR{eNk%w1VL$*t0Du4h00030|NkNR1ONa4001li0000$06+i$0``oLsmtvT zqnxzbi?iOmgAay4w}@tArXv}sXX(CLEGx7)-{7O~SO19sF+)j_ay0gkOH0!6oJ1K@ zr4CY+HmTd(753#+v(B#JxY{JqX?2s`_TJ80p9fgC-|?{nj@81a;`hfQI7k-)n0Oe( zsAt%ihPW6gNSIRj2v@Vnhe=uaxmoCW2wDo*h^i;eoyaQJb3;Rywh}0lfs1z8#;UlF(QKk06Tm8g$w`y literal 0 HcmV?d00001 diff --git a/icons/stax_app_akroma.gif b/icons/stax_app_akroma.gif new file mode 100644 index 0000000000000000000000000000000000000000..79768660eeaa88b42abb02d4fa9b6ba07c1dad4c GIT binary patch literal 467 zcmZ?wbhEHbRA5kG_{;zT+}zv}5)wK(IspLzMMXsm7A!b_{`~Xj&%b>6^6S^H|NsAk zRY3{GpDbXO;(u<>+{E-$-^BFH{!Rhob@vDbJZq>^hXbLg|@KSi#w@=rz^8^ap*GJab@?) z=lcn@uo#<7;bONc5v#V2;m)6!&lJc{VCUjGk;>_6naDg(a$#(xr%3f#hNq&NJA~d;G8<|L&t_oJ z6zwkK{^kDRlZ#bsfWlH=RoQ?n4h2D*Vngx{rZa+FTQy3;`8UvzkdDt|NlP& zDp35%0v1sG&+VC;n4apJn4X!O&6l2-o118Bpl4zVf($w!H6R-pSpEf^^jy97hLlpn z_eKW^&oI>tMHWRz5d*^w&5bjJig+9xWM(vGVSvP*FQxA4(Wmqv!_uN}Wg?$QM*LFr3na1!jF}boavs7d=1~j&daN1PcusSkM z;Y;se@S8&OAZL|$o@;Y2esQB4N=4b4B zs~fntEi9mhaq)o$(UL`T4;BUAY!_g)irON<$Y2csy#$Tp literal 0 HcmV?d00001 diff --git a/icons/stax_app_artis_sigma1.gif b/icons/stax_app_artis_sigma1.gif new file mode 100644 index 0000000000000000000000000000000000000000..8d769dba2e03f9d7b93357880d350be36a7087db GIT binary patch literal 476 zcmZ?wbhEHbRA5kG_{_k-&dx3-CT3`8=_*ib9On$M@Br)?r5& z;k1gSak6@MWlQ5>Cp#NwHkC;MXQho(h3^D92Piz_oMW}@>dFFzV>4whvza(IEa{oZ z8_n`SAtgaVm`VNAnuizK7#7TV-e%A_^KqAiuwKH47mWVQPI)m6b4<)dRxK4&%zAd? L^!E2{91PX~1*WFZ literal 0 HcmV?d00001 diff --git a/icons/stax_app_artis_tau1.gif b/icons/stax_app_artis_tau1.gif new file mode 100644 index 0000000000000000000000000000000000000000..555be4a6d6e3344f9acff781dca0e1278889b014 GIT binary patch literal 481 zcmZ?wbhEHbRA5kG_{_k-&dx3-CT3)0C3pPxT*;=~ObHe9%H;pNMhU%q_#_3PLF z|Nj|~fZ|UUFi-J6w`Xo*da7??dS-GqUwUG0ZlbM$o{1?4GU$NRfNWr3`B!k#bM;<} z;H6vEdo?K>PZT-&F|eah?1%w}Bg35o4Qsj+@0&IzI0)RyU^wJu$iNcB?&4G^!NS7I zaxn6T%(@1>=MF0b1?DmZEY*}=bFpcrt|QADCe3Ho5g#&{**G~xIGu}Fg2nT=Ioz1o zth*Vb{Kfm2xj1~&CAsV-hOvniMf$R~2+1g}tYh?IcghfMV+!@}N-^5Kn7fU+#m-9D z&UKn_s!2F=tWc^3o151@U(>z9YMjQ+B3XX-8HMcpu8Z!Mz3Z=*Rm<%=LGrmM8^hkz z9J9`k&dMTR7MI=9y)kKVOl!)vj;qlNp3O2-U=CSu*v$EUlmFKziOeC&-K@Ta(*G`I zKYM>}w)P5}KeH8AHqCOm$hB>g!~2^@oX$&~+&MXEnT7fky@CRf2Hw3=Hp-ci4I}^R#MGVufFf1xPswU&nDxer};3(rJNj?Yd Qi~bt@`x}^(I~W+O0pgLa*8l(j literal 0 HcmV?d00001 diff --git a/icons/stax_app_astar.gif b/icons/stax_app_astar.gif new file mode 100644 index 0000000000000000000000000000000000000000..458e51910ca56b5b16ccce377e11bd4e9e4ac815 GIT binary patch literal 506 zcmZ?wbhEHbRA5kG_{;zTtgNg&JUn7zV!FDzp`oD#1qF*1ExLH|;`8UvzkK=f|Nnom zDk!1&lLgFD{Lk%~o0y*Jo0y)NoXwY>n46nuYoKRh3W5weAT=Nx7+C%lob+71_r|i| z4u%E?5%x)`9gZvsx7nO4gHCPSr7uv!P^huFrIGbfV*<;e2dN$@Lag%+Bs@4O(7q;- zQ%j{m^r*lSZ-EmW3ljnkR5`I3Jatf+@nVoCCnAMtX)r8p; z429AZ>}%Z^8oAkHW^hkqEEMAKW>V#d2%Ik5#=z`1*OeoI!-bidDLa4mHfEhUZHz2j z$2itoSok_jV_+4kXX7@F(cL}EDpzQdt&mOQT|JdmG8Sc<6@?fN&U1~4bKqL<)=@2_ zxMIEamkAs;ArU>hwll;Sh17FNR3FWd<7Q-)bK`bwVqav)uwu)DCnu5=qq<~xW)vLr ziH4vHT>;l1w<#+aXX!5UEof<$HRO|L zStQh+*C#0G>0z-l&_Ud%yi%v*VCjSIh|s*g36}&mdPrLeizwVadhYaOE&Y^NHVY2j o5{Z<|`g3t&e+RdGfqw#H*pwM3B*nwN3M~}f^z^i_5(9%Z00D8V?f?J) literal 0 HcmV?d00001 diff --git a/icons/stax_app_atheios.gif b/icons/stax_app_atheios.gif new file mode 100644 index 0000000000000000000000000000000000000000..10a3e3b3b8440791a06fc8684357b1e5595df8a8 GIT binary patch literal 340 zcmZ?wbhEHbRA5kG_{;zTY;0^iJUn7zVtRUd2?+^v=FGWx@#6F6&%b>6^6S^H|NsAk zRY3{GpDbXO;(u<>+{E-$-^BFH^>V!Duz4t0#G2=>3Wv%DpV2NiglWq^}7G}$4 zV5yP{v6`aOYuzvI5zjbRs4;%>RM85@(5Y=|de%mg#a0VN+6|c}C9oF?`8&64i(Bet zD>iY1$+nJ3OiL5<_lNG~XijB0P%&XrqU`3J?%6qcvRs^O2dZA2RC=_P+knY)k<7$T ZOe{jGzw66?t1j;0knz~Cpo4?K8URuvc7p%_ literal 0 HcmV?d00001 diff --git a/icons/stax_app_bsc.gif b/icons/stax_app_bsc.gif new file mode 100644 index 0000000000000000000000000000000000000000..311d31a04c812cb467a1f537081efdbd1b6ef334 GIT binary patch literal 473 zcmZ?wbhEHbRA5kG_{_k-$jHda$tfu*X<}j$7#NtDnK^gv+{>3Qzk2oR%a<>|e*OCY z|33o~Q2faP<|+Q?_RLL8PxVbq&rHtdOHa(rO|&)8Gcg501|5(ZkPQqh{|ZieuHI|0 z-uRefmztluB11!f%;Gi)Ck6Hu2@1JOC0Mw4*bX0H_j#gX;BcTVdXJy?VULL%suioV z7Om0{3t>p}?++3_Cnrxwdo?g?q7qp1#2XQ&u**h|?)L@BrY!wNs z*lDy=gE>l^gMIq)y(e~RmC1{6Xw9;@w9|Dm3v=s~CD+&41ttqEV45U7by;uh9+z2p z8y8M*d&0?_`)cP>voEVRt&=q?+FmE2xov&>rU>sNdz*gql;nlsfSFbn)sEKIj>#lQ0i&n zlw|&tn<%>CSeKxeeAMj&P4gM*E!Vw>WXKCYIr(K@jh7>{@*HLHl4}!~%$+y$t$y|D JssJN{H2`lGtO)=B literal 0 HcmV?d00001 diff --git a/icons/stax_app_bttc.gif b/icons/stax_app_bttc.gif new file mode 100644 index 0000000000000000000000000000000000000000..cc8a3f986bfc9d18f5119c5f62e07c38ea8862f2 GIT binary patch literal 471 zcmZ?wbhEHbRA5kG_{_k-%gd{!rRDGMUtC-~Wy+NG>(`$q>Nz3`gr;P1tYCN$P&%pMwUoXN`_Y`BhGW4ii_<^a+|3Ai z8#p&)kK4r+?uCn4OqhfAR4wW`+7P#;>gdg;!Y&~l8?FO8TtXxyje|0#{hG@1d=0bg zrj!RtJ{pV>)ATNWFniC|6zC|p*3u=rV?&3y)f$bjO2>Fgb!KxgPHS(`t*`j(#=u|= E0L#6tLjV8( literal 0 HcmV?d00001 diff --git a/icons/stax_app_callisto.gif b/icons/stax_app_callisto.gif new file mode 100644 index 0000000000000000000000000000000000000000..890dd9f34687b84bd31d913c3d421193ad5b0335 GIT binary patch literal 404 zcmZ?wbhEHbRA5kG_{;zTJUl#7Qd0W*`tkAcix)4xbm`KQCr>_q{`~9LumAu5gOwl% z#h)x-j^clA&)mfHRNut(%;apo^u*lUL|X$r6H^dm&;h9d*}%Z^FW{u->b=`p0tLJx zDrA`%SXvmn)|7B8(-dgmv`txNzH@u>`U85?oc?HZUN2~0b+gV>c9nw!M+-yK@gKoV zY{yuflC@NL*z&wB7mFk`GjpaM&}42sY3tunm}M^J$i&9(#-SR;W@TubB^t=c$jofQ z#m20~GAY!sq_L_e)l81fs7Q6*G*NaIruFMtggMwkqoyy4uN2K-Z_N~I%=bxHv+sDn zWJIr@5XbBdxx!mnSWUZ~Wjx{xcgwRmwWwGdpS^6g&5d;?SFOfMbyrL2R@097^dL3c zXKM@?OH~pMUp{w!l|WpIZ-w#6>kL+9>uM}Z5+oY<*lMFHToTH4&)ym8~kt5>hSdiCn-*RMZ* z{P_R>KLZRX{$v3&75{U4<|d}6`X;7lCTH`dC+6lR+8XGYn1UdK4oD5i1_qW_6Ha=r z-fOWr^wgyVTO}9+T3)y@IXqZ;Gh)+Q?r5$>NF;#H#0Ie9Zo#)NHYB3;iQc@ zR?Y_;CI#h+86MAlYOwmN-b3bH(ag?UUvV-WOl4aq!Xhj=U4f06!#1RvsYI01xuBBS zu{}7JiBqhqrpJmc*|}|sQ!P)u73*Y?mN}yJ^B0;dPLF96<7}_%jhmd#B^+4%oRMg+!zhT3M%a<=dd-m+hmoGnm z{`~*{KLZRX{$v3&75{U4<|d}6`X;7lCTH`dC+6lR+8XGYn1UdK4oD5i1_qXY6Ha=r z-fQvttkAEMhji|x*L8&`CARW3Do7k}I$>caqthtfek8?_L4uv_;KGa?DPET5g_gHF zCE6W?y)-Q5UUb+L`GK#chbb}EL+;A!AGZuLP9JY*S`uR>!opEk)6CA~P!klzz*6m- z#GD=P8_43#Y>>ss$gagaId9%1>!2VGRu3i?O`+Bl)@73z0#bt7){Ag8<#Gn@sttDY zS{bA(7Q<|ulcB%PZH~mw*xWdOXua=CAemXVx-T4Poofm0%$-Ac9}3SSOWm}bD)a= literal 0 HcmV?d00001 diff --git a/icons/stax_app_dexon.gif b/icons/stax_app_dexon.gif new file mode 100644 index 0000000000000000000000000000000000000000..692537fdd863a5a2ff1d86e050039affd7435c73 GIT binary patch literal 469 zcmZ?wbhEHbRA5kG_{_k-$jHde%`GY_s-vS56&2Op-Mw++#?z-yKY#xG^XJdMe*OCY z|33o~Q2faP<|+Q?_RLL8PxVbq&rHtdOHa(rO|&)8Gcg501|5(ZkPQqh{|ZieuHL&t zZLj938IC1EfdO2J8VXYd4r(bL`Y`q24ZW@;7KZ441_ptM4o8J;(JGCW^B0`Z3COj6 z{nbH7ia+>0XNd#@%Lau42c8+d!HR0EIx6>`H!HsJ%jg%k%a*ryWf3y)*7i(i6XVi% z?c+*tO^#w>w{2|@Wowhxj5F(L6Pn1FEX38r)W_ZGz`zeQgA z8k6|tT!n;}uqd*y2CNk=XWEhU@kO#*ctXm}AI_fxSL=E8e0k-1fM=7~mro^zA)Q^T zc>Hx-xs5NMTA+5fjiKX_%8S)v6FPj7R2>fVmP*Z5c@y&JW%qjDh{6jOg4f3K2r@8O F0{|$Ou0j9+ literal 0 HcmV?d00001 diff --git a/icons/stax_app_ellaism.gif b/icons/stax_app_ellaism.gif new file mode 100644 index 0000000000000000000000000000000000000000..ac5ef850033f80d99d5b3311859c5d2919b80236 GIT binary patch literal 381 zcmZ?wbhEHbRA5kG_{;zTtgNg&JUrs!;-;pio}QkirKO7&ExLaF`pcIuzkK=f^XJe1 z|Nny(f(XT*EMT_ce{Rp*#Pn3(#PrPMY`*lw+}uQ413eQ{5Mi9&XS{I;FzOAkwKNw=R2uQ5lP=fy_?trVGV_0*`(ceQ-CN4Xdlbx9*AurUe zK#VJ`-!!1h#-2;pmMNF3kfUuHN7q#QELV5oE?*W-j;W?_c^fA*MP8n5p`G%NBQl*Xc)#vK^nD!>i=GpAc zx{-fgiJPm_=EUNJq6Z6-QhBE-{GJh!sqE^c8`>=8H}R{p604MHN92?VT*ut3cvS^D RZth6n6v&k?c41(!1^|n^fL8zj literal 0 HcmV?d00001 diff --git a/icons/stax_app_energywebchain.gif b/icons/stax_app_energywebchain.gif new file mode 100644 index 0000000000000000000000000000000000000000..3f8a57438ec4a73847e43d9ab6cda1feb4dbc090 GIT binary patch literal 446 zcmZ?wbhEHbRA5kG_{_rq1gxyATwGitA|iTvdI13eIXO9V=gvKM?%cCy&pv6~F(sT9R z8EbVf8y->MU`~|b+Pe1Yu8J0hGhcKB+>Lg=Efd(9Ah7-M3X!&k0#9LyARVqro^x5} zUF=+VidA9}_c6ztOWF92iEp@LB9g^2*QGGwIvdB4s7~SyrbD z<#%W#wHveYOfY5>>hhk&uECnZP*`fhBE)RE$b_APxnijqN1F+=kTcs9#?6dOm5cUq zEMnYllD^KgQh9Uv9@7=3mMhn+TT&obKHGHGj5r>aX?L5Vm-S!YxVVIkv#aN}(3Uk^ zGng#dcA7LL`_}SsUN(O8M^L~ap{If4M(pecK8HpYjyrQA#5X$hvD{_&GWmnLK$D0c z&liy&Cma}?0ty6H+$d+ixa*^U%l4isj!b+LUd;-gdhQF@a` U^2b#rzdo+x+;H=^AR~h{03Nw=Z2$lO literal 0 HcmV?d00001 diff --git a/icons/stax_app_ethereum.gif b/icons/stax_app_ethereum.gif new file mode 100644 index 0000000000000000000000000000000000000000..81db45cbdbc404688cff27427264219b0cd58961 GIT binary patch literal 309 zcmZ?wbhEHbRA5kG_{_}!1Z-?vbuzxE0kMXJ9z|G0iLJOmSg4J0risi$7WmALf)Sk(go}7F?v@Fn!yz zcek|vHr=^-;D=Mr;l`%dsT?hpmx4c?RbFGCZl&<|~V7JthzHN+D>C*jg;r~U&z50#?U#1Ri}LM+SO^SDr`ng=EW?Lq23(6^^DA{ uYpaukxsOh=J5lUhb|S>c#`L1Fzm4uSp)}k5w=bElzb(W4_<_D4gEatp_-&B@ literal 0 HcmV?d00001 diff --git a/icons/stax_app_ethereum_classic.gif b/icons/stax_app_ethereum_classic.gif new file mode 100644 index 0000000000000000000000000000000000000000..10a661d878d4eadbfcc9c5049ef176a8cf7e0151 GIT binary patch literal 328 zcmZ?wbhEHbRA5kG_{;zTJUl$&;^GDd21!Xtix)4xeEIT=7cahi`SR=6umAu5gOwl% z#h)x-j^clA&)mfHRNut(%;apo^u*lUL|X$r6H^dm&;h9d*}%YZJ>aD0>b(}LL%ROm zFyvs%@MB>RIKe5_C{>Zy#N=!T6y-4}= J-C2;q8UTU8aD)H= literal 0 HcmV?d00001 diff --git a/icons/stax_app_ethergem.gif b/icons/stax_app_ethergem.gif new file mode 100644 index 0000000000000000000000000000000000000000..0ed7b1cf96d69405c44059280c71f4321df214bb GIT binary patch literal 328 zcmZ?wbhEHbRA5kG_{_k-$jHde%`GM-rlX^il$5k^;lc|SF1&pC^2?VmzkdDt|NlP& zDp35%0v1sG&+VC;n4apJn4X!O&6l2-o118Bpl4zVf($w!H6R-pSgr@0^jy8y;&jlK z;~a(x@s^?t7iOwX6jE6&>7*smIcKM)!xJm+wd^}sb#0U$dPoW}GBYztxGZJcdgWDx z#1f{~Cl3y6apLzY@M-&y#mnaOU{~7A#Vk#c8&Xxd*%-||y^UCl85j$r+HGs)I9u45 zl`3ov)EeX2G-R}TJK5AGF)?%H2IkqRX3o=YpBKJJZnD{&8fh&y+dx&;JeE0uCJlLe z)mS4BPGyNLX6~0isjqn2?Bc!-`-#_mIC~i@`+S5rPIkDmrrhIX_q5|E^-4AuZ?{A)b` literal 0 HcmV?d00001 diff --git a/icons/stax_app_ethersocial.gif b/icons/stax_app_ethersocial.gif new file mode 100644 index 0000000000000000000000000000000000000000..e8fc4dd4a5006898ca76cc7088bae47e6494f57a GIT binary patch literal 136 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)*r+?+?x9mz4BA$`2dn?aB3A~q@ zdrrbBqIuR#uW9;w&h=>9?Krp5^nUakKSS5R&)TdLy`L_hyyR@(IrR-MTau>UTDvrR jYh&99!>Kp9X0LsjG4-y{#NbbxZ#e8<|FtHXk--`O9IZN1 literal 0 HcmV?d00001 diff --git a/icons/stax_app_expanse.gif b/icons/stax_app_expanse.gif new file mode 100644 index 0000000000000000000000000000000000000000..9dfd8705fe7c68068ba1374085300673ea99d10f GIT binary patch literal 165 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJmT3r+?+?xBQJ0H#AunrfyH)uPAGg z745lb%Hn0Ymv`we*V_Dd=Ho!WZ>w&qmT1eJ@DO}f=N0Vm?2PJsA5CKpZ>@<3A6>8# zk*mD&JZzP&(D}6G7N^wWjNM|Yc||ScsEqig}n&oo|-d{FUyZ3 zPbGbB_~C8uxQ~DGS^i|TUEaFQHWz-qE!q+Mw!=qDa_Z9+D`Q-3FP{vG617}-Zr$`i H1_o;YvHL1C literal 0 HcmV?d00001 diff --git a/icons/stax_app_flare_coston.gif b/icons/stax_app_flare_coston.gif new file mode 100644 index 0000000000000000000000000000000000000000..2f77deea1b355a1db0b99b06c4c069d0a23e4b27 GIT binary patch literal 116 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJneur+?*XHvYwP3@>&oo|-d{FUyZ3 zPbGbB_~C8uxQ~DG>GwbDQ?cs(wkN+sn^q?*NVn;lbY_|GGObUGJQPcR?5y&MQrKP{ N+;I53(IN&0YXH13EkFPO literal 0 HcmV?d00001 diff --git a/icons/stax_app_gochain.gif b/icons/stax_app_gochain.gif new file mode 100644 index 0000000000000000000000000000000000000000..04bb08df626b4c6425b4f305e0aa494e6218e99a GIT binary patch literal 150 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)!r+?+?T!w|SHKQD+*Ia-0xbW_@ zR-uc({9bBFX)w@ld&tmU7p}KO$e!T5qA>J^x#& wd9|MFduEF!FLp}Z!lhb&SM%$iHL}GA^Y@j1cN7Zye%(Eze8!3y5ey900J3X5M*si- literal 0 HcmV?d00001 diff --git a/icons/stax_app_goerli.gif b/icons/stax_app_goerli.gif new file mode 100644 index 0000000000000000000000000000000000000000..95c819d26d253ae627a6465dc2cb63c22149cd0b GIT binary patch literal 157 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJmT1r+?*XM*hUvYPURY-i>^FUshhi zYI??0wYDWoZ*LM6I39HTl)=>duRkwZnB#CYCH>2ZNvCeF&{W}?Z+s~~OV%|uBv-I< zty}%0!bl$*^&PIWqoQ)Boz3~2weQ{5lh?m>_M2UQ+WP3Jd*}*P)@$3R9Al9@8Nk3` F4FCe8_q=+@A1vns}#tn zId9(fNNk4K=Cq|c+8eWHcBC(_+*^GxP4I4~>YJ?%>Pp=~DbwaCYUx;-uoVlxEc@K@ ztIFP8_iJz2g&R-#bMh9~yjVQv+pfyH7x&chvWZ;2I(>=j3Fo4%i#*D1oDgS|G>P09 Iz`$S)08dmwW&i*H literal 0 HcmV?d00001 diff --git a/icons/stax_app_id4good.gif b/icons/stax_app_id4good.gif new file mode 100644 index 0000000000000000000000000000000000000000..ae3fae4a7c3ae895b23c172c40159f7f26d18d8a GIT binary patch literal 151 zcmZ?wbhEHbRA5kGXkcLY|NlP&1B2pE79h#MpaUX6G7L<4E&VHJKa}U2V`8SYdRyhU z-r9Z+CzbH5=T%m2N4Mp39GD({*(~Y3_3OoqrH3T-Iv%%9SQb6mvdC?rUgp$Ol4|wG z)D2hWK09#tWw=aV-^Hh|Bj>JL_ptbL*pAG_LHU;Z_kULp7ypqSI^)oS9Xlcz7_0#R C&p$!{ literal 0 HcmV?d00001 diff --git a/icons/stax_app_kardiachain.gif b/icons/stax_app_kardiachain.gif new file mode 100644 index 0000000000000000000000000000000000000000..0c092ffa257fc342a773f4f3ff577898f5b010ad GIT binary patch literal 153 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJmS|r+?+?xBD3yOnj7|p6-2Iqq<;O z!*Piyjm{bKe=mAeaY%d3t++kcO5W_ASha7#g%e3n`%Z*-bVO@KUl7UnQk_<}ilcnl z;W{g$IMv;|=bpZPx9xPxhO60gwlV#`Hu+*P-`nk9Rm4t+dz2O3Sa{;bjR*z?YXBHP BMIQhF literal 0 HcmV?d00001 diff --git a/icons/stax_app_kusd.gif b/icons/stax_app_kusd.gif new file mode 100644 index 0000000000000000000000000000000000000000..18b1a1c5ea722b40213b15f6c76033354a5ab79c GIT binary patch literal 133 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)jr+?+@1N?#o8`ouSUSjp=WGRo> zgh!uSmosj9ni}jmryVl0EMhmIl}@Tz_dw)?TOSXN1LP g>oy%W`;hl$^P=Y0D>lsyU4Q?B_@$Whi@6!B0oFn~7XSbN literal 0 HcmV?d00001 diff --git a/icons/stax_app_meter.gif b/icons/stax_app_meter.gif new file mode 100644 index 0000000000000000000000000000000000000000..d07813d1a32156348c2d5d1078cf23b52f3f720e GIT binary patch literal 148 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)&r+?+?xBnaF2%Pg?eaI&JOvAM6 zF@i5=EL|e0@u|<@#J0S-M~eLp|M=*1;#-E?FqE?k& w{9Cejo90ySX%{c4Z@VeBdDrAyzBSg^*pZrx08!CzwLfdw(sVJjH=Qu&uc>B3R?5+S6*h`8pnHKg+|h= Xs_;h_OzgT=hwg0dt&o%G zP|D~Ft8!bzwO7{jdRgSD4`;v6w|mLi-Y0M1;d7~H^Bg};QKRyUt4@1v&D!3^#9$2o D+|wpI literal 0 HcmV?d00001 diff --git a/icons/stax_app_moonriver.gif b/icons/stax_app_moonriver.gif new file mode 100644 index 0000000000000000000000000000000000000000..69466a7a5c8aed3f47b2fb85e1ae5730f6f72baf GIT binary patch literal 142 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)yr+?+?x9=O~2)T8w_TAZBTOp^> z6&C5VqH=BW<4rz)&PhFT%iVk5ZTTnPf+_9(g*>%A_D?>2pJU2=I>XI$ZIf73R+-eL o%Hwx8-RSv!=!(Y&vsrTaPi4$Kz4jMBFSWaNo<-wD00V&QOo0dPn8oKa% zq_TNZu+}E6$J>h7=P&EIQMu#s?n#R(G6Z7zzX}OCI#0TE^2^r+YN|zEPh~q!M;q

-`HJ#)$GcgCyki7N}f5DiaZ4r7`Y=G1=ZhQSvOMbF5Y I0SpY*0Q7D_WB>pF literal 0 HcmV?d00001 diff --git a/icons/stax_app_musicoin.gif b/icons/stax_app_musicoin.gif new file mode 100644 index 0000000000000000000000000000000000000000..eced2ed72d7d44bd7d416d5e8c53ec9af6f64d7f GIT binary patch literal 146 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)wr+?*X-v6_FHZ)nTJ?a;}uR^+` zL%wo`da>p!sla#A>=R-xea+h5_U`hM8rxe1#lIQ*=L;MB2zoU`Y30Tho6@$1zPWar twR%NzQKZcyq2$Xlh9XB(A8DAb|F?E=_OIIeXO@e9Q~#1)5x~G;4FFFWJ+S}) literal 0 HcmV?d00001 diff --git a/icons/stax_app_oasys.gif b/icons/stax_app_oasys.gif new file mode 100644 index 0000000000000000000000000000000000000000..83995c6979282f87779ba5dbeea40cb916694226 GIT binary patch literal 149 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)kr+?+?xBQFeY`N84%(Un8n^wiA zmQOEhs!uYy&nU6z%&}Fv#~*!vCVlVL&8WtCA1zKZwx5o=#9k{o)ltIu)S0x67Z$Di x{yS=Sknm2=u-@I7uUGB(cQwW$zxhS&Geu|P8l@%Sic11BDmrFVL@+Q|0{|#=K|}xm literal 0 HcmV?d00001 diff --git a/icons/stax_app_okc.gif b/icons/stax_app_okc.gif new file mode 100644 index 0000000000000000000000000000000000000000..38cfa3cc3c79f9b8ffce4c16752d8190630f05cc GIT binary patch literal 131 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)nr+?+_2mCV|Mb7+6IZ#=wUAth# zM7i)faj8}6(>AFkpYwiusq%D|;hW!~O-@`B*=@9PPBCx(Ddi-1K5gs9=w0iy70k0( d+$UVpUsrxRZQ~}>(B5m?9=~~F62ZV=4FF>`GXekr literal 0 HcmV?d00001 diff --git a/icons/stax_app_pirl.gif b/icons/stax_app_pirl.gif new file mode 100644 index 0000000000000000000000000000000000000000..6ac7154d380daa14a7e881a6357054d9d17c9fdc GIT binary patch literal 145 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)gr+?+?T!uL*0_T3OI_j70S1I37 z5$QT_wp3%3}?AOEv3sdQ;t=fp7zo6XjF5|i?Z;) re7jGjdw3h0wHCTdxK8DpyVZbYEok`|BbSMiCtW3=Gx)*Y7+9 literal 0 HcmV?d00001 diff --git a/icons/stax_app_poa.gif b/icons/stax_app_poa.gif new file mode 100644 index 0000000000000000000000000000000000000000..afa1186ba1727250b79db238843cb8427922b1b9 GIT binary patch literal 147 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)or+?+_2kYf>gl1%|?D<+|t2kqO zBVTx5np#~}^dZIKJzsR^|L{9!ll$AS$!Q9Iho{!my-SU6)_9d(esv_PH)$s0qU&Ez uZp?ZhaZ|>3eb1E-KUe%(wEO8}y?6f}KL5UJ-H!Bj;UDTQAuYiS4Aua_s6kZ# literal 0 HcmV?d00001 diff --git a/icons/stax_app_polygon.gif b/icons/stax_app_polygon.gif new file mode 100644 index 0000000000000000000000000000000000000000..eba2eaad34abc2ab162386d65112a4ad71b71301 GIT binary patch literal 362 zcmZ?wbhEHbRA5kG_{_k-$jHde%`G7zVPIeo5)zV|o7>ylyL$EN^XJdMeEIUrmoGnm z{`~*{KLZRX{$v3&75{U4<|d}6`X;7lCTH`dC+6lR+8XGYn1UdK4oD5i1_qX&6Ha=r z-fQuCsdbq9qu$Go49$v@ZZwH7DlBe46xOMDrdU9rLz>y-0Wa6lnF}^ZNmei^C{Lfl z8=-z+y<6qclnBX%o{=^O#RC`*CZ=%CKYZqq(vfM4%H8^==?EFvFtFw&RTm3cS~oEi zR7un@2&o0Is@b>pN~TZZ=}vNVW@npOkSpxcVa#m0oJXdLjm?Z_x|dKq`#O;-bryEk z`O!kgOC+jTdo;9!cS@dUV)PL;WJj~kN!1@qq{pF$i>?)RE?aa63W1I zhNH~pnDWil2i;=Kzs9qiRW43uTq>8{vc%9Jfm^p#Tu4EI<73m#E(u*11_o;Yuo8Rz literal 0 HcmV?d00001 diff --git a/icons/stax_app_reosc.gif b/icons/stax_app_reosc.gif new file mode 100644 index 0000000000000000000000000000000000000000..50fe3fba62f5a63646f21893a4b1f1a7e28c7fab GIT binary patch literal 148 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)&r+?+?xBSvGjNQ7{9v`(k~DL_aESHM u&coUd!?qdM@852!Tp5-houIS#-MstnHNvFk literal 0 HcmV?d00001 diff --git a/icons/stax_app_ropsten.gif b/icons/stax_app_ropsten.gif new file mode 100644 index 0000000000000000000000000000000000000000..4c7a5a0e74cfacc0e63e5f78819f711ac0853ebc GIT binary patch literal 127 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)pr+?+?T!uL*0_Uo;js!=)tB~H& zA>TPebk-{6SLSO1_0`1GY|j( literal 0 HcmV?d00001 diff --git a/icons/stax_app_rsk.gif b/icons/stax_app_rsk.gif new file mode 100644 index 0000000000000000000000000000000000000000..a576134bc929f78e6d1c207372863cb595e54009 GIT binary patch literal 144 zcmZ?wbhEHbRA5kGXkcJqW@i5X|G(l-76uT|0TCb>2B!3${*|X?85(D6xpl2Q8XSMG zLSTpDqLjM!=^HYCcC5{svvtnHvUl@VJdXa^X07<~$7>eHZl&U9RZgZpH_lf1rn&3q uo_W<1S`eR=B@=sZ*)yY0H)>b+p0pJ6n0D#?r49GqehpXis0d(Sum%7f&przP literal 0 HcmV?d00001 diff --git a/icons/stax_app_rsk_testnet.gif b/icons/stax_app_rsk_testnet.gif new file mode 100644 index 0000000000000000000000000000000000000000..a576134bc929f78e6d1c207372863cb595e54009 GIT binary patch literal 144 zcmZ?wbhEHbRA5kGXkcJqW@i5X|G(l-76uT|0TCb>2B!3${*|X?85(D6xpl2Q8XSMG zLSTpDqLjM!=^HYCcC5{svvtnHvUl@VJdXa^X07<~$7>eHZl&U9RZgZpH_lf1rn&3q uo_W<1S`eR=B@=sZ*)yY0H)>b+p0pJ6n0D#?r49GqehpXis0d(Sum%7f&przP literal 0 HcmV?d00001 diff --git a/icons/stax_app_shiden.gif b/icons/stax_app_shiden.gif new file mode 100644 index 0000000000000000000000000000000000000000..13223094882ad0d6141da1132474e311578d5d1c GIT binary patch literal 156 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJmTLr+?+?vkY@XHk^xm%vhe9Qkoz! zVQECx%WtKt(z*<`Z!&Rn&)0c*?CjyWZ3nyc%bhp+$y^QKtjU|Q^%=j5@3Rh1@uxSx z>a9KZW}9T$!F8#RyXWR@2{Ya*_Otu@tIC@-%by!Eg={Imt~M?F#deNX57wIj3=Gx) D2%bXs literal 0 HcmV?d00001 diff --git a/icons/stax_app_shyft.gif b/icons/stax_app_shyft.gif new file mode 100644 index 0000000000000000000000000000000000000000..0741eddac35b5d095221e61f8539ed91f7aa0beb GIT binary patch literal 150 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)!r+?*XUjErW8;-qPx3VJhS4qdQ z+=UWzR+g@~!8(7w%I=L3+LhbizsTZZsy{rhn_b}8B#rxEPqY-uWAF(ZJ1!5RRo0zc6J literal 0 HcmV?d00001 diff --git a/icons/stax_app_songbird.gif b/icons/stax_app_songbird.gif new file mode 100644 index 0000000000000000000000000000000000000000..811d72ac167f5690dee827a915275a6705ae0e2e GIT binary patch literal 132 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)%r+?*XPTph&|0tK&TO;4!s117F z$rU+EV%5BiRr}UDOUc=!eG`7vYqyX^+pev^cuy|rd3}1!ml%RQl;7FVBh0yr?a=kom0QEl|5yPxyP2^649a^C$<`Fz53W8 XBci?J>xob8$9GQrrl}Rkz+epk|3pmB literal 0 HcmV?d00001 diff --git a/icons/stax_app_tecratestnet.gif b/icons/stax_app_tecratestnet.gif new file mode 100644 index 0000000000000000000000000000000000000000..a1ccb2d47410b7dc321415d881f514c21a0c2e18 GIT binary patch literal 174 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJmTIr+?*XUjErG4-Q1DSBtr?t!X@- z`Dn&MxfNx1x#HYBr*-~07ddy|qPeR)3$`d^e$srEa9S?l`ESFiE7bZX@wm-2SH98} znRGPt>cuy|rd3}1!ml%RQl;7FVBh0yr?a=kom0QEl|5yPxyP2^649a^C$<`Fz53W8 XBci?J>xob8$9GQrrl}Rkz+epk|3pmB literal 0 HcmV?d00001 diff --git a/icons/stax_app_thundercore.gif b/icons/stax_app_thundercore.gif new file mode 100644 index 0000000000000000000000000000000000000000..4d730a167775aa5f4f183ff38b164d6fa7192fc4 GIT binary patch literal 141 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)ir+?*X-usWLLZX~MPu;oewqu_~ z+r(onPp)iym8qu1aQt}8{_XS5eYvOg(7R7w?6&5<-Pcf00stY03Me=HUIzs literal 0 HcmV?d00001 diff --git a/icons/stax_app_tobalaba.gif b/icons/stax_app_tobalaba.gif new file mode 100644 index 0000000000000000000000000000000000000000..cd3e9464ef235e7a671b3f663e03249fe43c3f0e GIT binary patch literal 116 zcmZ?wbhEHbRA5kGXkY+=|NsB%fM}2i15KIUBc02Qn~N0|4sJF$(|y literal 0 HcmV?d00001 diff --git a/icons/stax_app_tomochain.gif b/icons/stax_app_tomochain.gif new file mode 100644 index 0000000000000000000000000000000000000000..eb8d01a1a9f2b5b4562c206108e17047ec5ae37f GIT binary patch literal 126 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)xr+?*XE?(t|jmtdO9*uOqSIMK{ z74viMixunqUMoHD@el32UGA6t=grT9WixK9&X~g6yX48jmpl&Q!D5$IdF%2zJo*}$ Y`{h95MuXSF>*_Yn*(~iU%D`X^0MY|8Qvd(} literal 0 HcmV?d00001 diff --git a/icons/stax_app_ubiq.gif b/icons/stax_app_ubiq.gif new file mode 100644 index 0000000000000000000000000000000000000000..afd0577ad5a08defd653ecd78ef84a1784e6c7eb GIT binary patch literal 143 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)qr+?+?T!uL@0_UW&j{0T$RmxX% zBz4YAlk|P{Gv}^#TAcIstQp(Q=DdhZGIiD0*en^ZcuipAWQMt(cesAmIL-9Xns(Zo pt2X+9#TwzL%f}JLHE(gZ-sWY=1KWgJ)bs7XKAi9 zX`6Uk^>e9fx2Ch{jc&W+Pc<{{)}^0+S^3T`_i6j5FcY&M*O|>9@#+Dl^0vH&q0eAgF AKL7v# literal 0 HcmV?d00001 diff --git a/icons/stax_app_webchain.gif b/icons/stax_app_webchain.gif new file mode 100644 index 0000000000000000000000000000000000000000..3deecb3fff53dfd8ac5dc942d76529cdaf6d6f49 GIT binary patch literal 116 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJneur+?+?xBQFeY`N9F*=<4f>srSf zjZYkzLQc&UzTGAy(=8A?oqyiy-Mbq&8y&9)JhSMU;JG;XyE9+<`K9`cTK28F)%%^B Nulx9uPfHmXtO5T`E?)ou literal 0 HcmV?d00001 diff --git a/icons/stax_app_wethio.gif b/icons/stax_app_wethio.gif new file mode 100644 index 0000000000000000000000000000000000000000..4b540302e789064699de2bb9f76e669740bfec63 GIT binary patch literal 149 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)kr+?+?xBDCBOgR)%yw~mb$;N(* zNxh*=3#Y6Smzv4Nnfylb&fLB$+WU(Os~m0`RDAfVpppEkJ%uCqU}jNPi)E?gB2(>> viz#*qCDA6`XF}hP9Wycl7#OSp845n` literal 0 HcmV?d00001 diff --git a/icons/stax_app_xdcnetwork.gif b/icons/stax_app_xdcnetwork.gif new file mode 100644 index 0000000000000000000000000000000000000000..2cd15b212819b239c8ea642865d0466187c9d069 GIT binary patch literal 146 zcmZ?wbhEHbRA5kGXkY+=|Ns9h{$v3&bwDIYhJh)wr+?+?xAF~hF8Fl4Yn7U>XQ{BE zr>C-s>(+*ezjowtFHW(!WYt{qqIkh>{L tCMbCB+GCe&>k~4c=NyfjelqKa&Bt>`CV$PDZ-4Drt4l Date: Fri, 5 May 2023 11:54:39 +0200 Subject: [PATCH 17/25] Stax ENS support --- src_nbgl/ui_approve_tx.c | 65 +++++++++++++++++++++++++++------------- src_nbgl/ui_settings.c | 42 +++++++++++++++++++++----- 2 files changed, 79 insertions(+), 28 deletions(-) diff --git a/src_nbgl/ui_approve_tx.c b/src_nbgl/ui_approve_tx.c index 78c9d81..b3aec12 100644 --- a/src_nbgl/ui_approve_tx.c +++ b/src_nbgl/ui_approve_tx.c @@ -5,6 +5,7 @@ #include "ui_nbgl.h" #include "network.h" #include "plugins.h" +#include "domain_name.h" // 1 more than actually displayed on screen, because of calculations in StaticReview #define MAX_PLUGIN_ITEMS_PER_SCREEN 4 @@ -27,6 +28,9 @@ struct tx_approval_context_t { bool fromPlugin; bool blindSigning; bool displayNetwork; +#ifdef HAVE_DOMAIN_NAME + bool domain_name_match; +#endif }; static struct tx_approval_context_t tx_approval_context; @@ -35,10 +39,12 @@ static void reviewContinueCommon(void); static void reviewReject(void) { io_seproxyhal_touch_tx_cancel(NULL); + memset(&tx_approval_context, 0, sizeof(tx_approval_context)); } static void confirmTransation(void) { io_seproxyhal_touch_tx_ok(NULL); + memset(&tx_approval_context, 0, sizeof(tx_approval_context)); } static void onConfirmAbandon(void) { @@ -88,32 +94,41 @@ static nbgl_layoutTagValue_t *getTagValuePair(uint8_t pairIndex) { } } } else { - // if displayNonce is false, we skip index 2 - if ((pairIndex > 1) && (!N_storage.displayNonce)) { - pairIndex++; - } + uint8_t target_index = 0; - switch (pairIndex) { - case 0: - pair.item = "Amount"; - pair.value = strings.common.fullAmount; - break; - case 1: + if (pairIndex == target_index++) { + pair.item = "Amount"; + pair.value = strings.common.fullAmount; + } +#ifdef HAVE_DOMAIN_NAME + if (tx_approval_context.domain_name_match) { + if (pairIndex == target_index++) { + pair.item = "Domain"; + pair.value = g_domain_name; + } + } + if (!tx_approval_context.domain_name_match || N_storage.verbose_domain_name) { +#endif // HAVE_DOMAIN_NAME + if (pairIndex == target_index++) { pair.item = "Address"; pair.value = strings.common.fullAddress; - break; - case 2: + } +#ifdef HAVE_DOMAIN_NAME + } +#endif // HAVE_DOMAIN_NAME + if (N_storage.displayNonce) { + if (pairIndex == target_index++) { pair.item = "Nonce"; pair.value = strings.common.nonce; - break; - case 3: - pair.item = "Max fees"; - pair.value = strings.common.maxFee; - break; - case 4: - pair.item = "Network"; - pair.value = strings.common.network_name; - break; + } + } + if (pairIndex == target_index++) { + pair.item = "Max fees"; + pair.value = strings.common.maxFee; + } + if (pairIndex == target_index++) { + pair.item = "Network"; + pair.value = strings.common.network_name; } } // counter is used as index to circular buffer @@ -177,6 +192,14 @@ static void reviewContinueCommon(void) { if (N_storage.displayNonce) { nbPairs++; } +#ifdef HAVE_DOMAIN_NAME + uint64_t chain_id = get_tx_chain_id(); + tx_approval_context.domain_name_match = + has_domain_name(&chain_id, tmpContent.txContent.destination); + if (tx_approval_context.domain_name_match && N_storage.verbose_domain_name) { + nbPairs += 1; + } +#endif // HAVE_DOMAIN_NAME if (tx_approval_context.displayNetwork) { nbPairs++; } diff --git a/src_nbgl/ui_settings.c b/src_nbgl/ui_settings.c index b55d323..c952140 100644 --- a/src_nbgl/ui_settings.c +++ b/src_nbgl/ui_settings.c @@ -5,26 +5,38 @@ static const char* const infoTypes[] = {"Version", APPNAME " App"}; static const char* const infoContents[] = {APPVERSION, "(c) 2022 Ledger"}; -enum { BLIND_SIGNING_TOKEN = FIRST_USER_TOKEN, DEBUG_TOKEN, NONCE_TOKEN, EIP712_VERBOSE_TOKEN }; +enum { + BLIND_SIGNING_TOKEN = FIRST_USER_TOKEN, + DEBUG_TOKEN, + NONCE_TOKEN, +#ifdef HAVE_EIP712_FULL_SUPPORT + EIP712_VERBOSE_TOKEN, +#endif // HAVE_EIP712_FULL_SUPPORT +#ifdef HAVE_DOMAIN_NAME + DOMAIN_NAME_VERBOSE_TOKEN +#endif // HAVE_DOMAIN_NAME +}; static nbgl_layoutSwitch_t switches[3]; static bool navCallback(uint8_t page, nbgl_pageContent_t* content) { + uint8_t index = 0; + switch (page) { case 0: - switches[0] = + switches[index++] = (nbgl_layoutSwitch_t){.initState = N_storage.dataAllowed ? ON_STATE : OFF_STATE, .text = "Blind signing", .subText = "Enable transaction blind\nsigning", .token = BLIND_SIGNING_TOKEN, .tuneId = TUNE_TAP_CASUAL}; - switches[1] = + switches[index++] = (nbgl_layoutSwitch_t){.initState = N_storage.contractDetails ? ON_STATE : OFF_STATE, .text = "Debug", .subText = "Display contract data\ndetails", .token = DEBUG_TOKEN, .tuneId = TUNE_TAP_CASUAL}; - switches[2] = + switches[index++] = (nbgl_layoutSwitch_t){.initState = N_storage.displayNonce ? ON_STATE : OFF_STATE, .text = "Nonce", .subText = "Display account nonce\nin transaction", @@ -32,20 +44,28 @@ static bool navCallback(uint8_t page, nbgl_pageContent_t* content) { .tuneId = TUNE_TAP_CASUAL}; content->type = SWITCHES_LIST; - content->switchesList.nbSwitches = 3; + content->switchesList.nbSwitches = index; content->switchesList.switches = (nbgl_layoutSwitch_t*) switches; break; case 1: - switches[0] = + switches[index++] = (nbgl_layoutSwitch_t){.initState = N_storage.verbose_eip712 ? ON_STATE : OFF_STATE, .text = "Verbose EIP712", .subText = "Ignore filtering and\ndisplay raw content", .token = EIP712_VERBOSE_TOKEN, .tuneId = TUNE_TAP_CASUAL}; +#ifdef HAVE_DOMAIN_NAME + switches[index++] = (nbgl_layoutSwitch_t){ + .initState = N_storage.verbose_domain_name ? ON_STATE : OFF_STATE, + .text = "Verbose domains", + .subText = "Show resolved address", + .token = DOMAIN_NAME_VERBOSE_TOKEN, + .tuneId = TUNE_TAP_CASUAL}; +#endif // HAVE_DOMAIN_NAME content->type = SWITCHES_LIST; - content->switchesList.nbSwitches = 1; + content->switchesList.nbSwitches = index; content->switchesList.switches = (nbgl_layoutSwitch_t*) switches; break; @@ -80,10 +100,18 @@ static void controlsCallback(int token, uint8_t index) { value = (N_storage.displayNonce ? 0 : 1); nvm_write((void*) &N_storage.displayNonce, (void*) &value, sizeof(uint8_t)); break; +#ifdef HAVE_EIP712_FULL_SUPPORT case EIP712_VERBOSE_TOKEN: value = (N_storage.verbose_eip712 ? 0 : 1); nvm_write((void*) &N_storage.verbose_eip712, (void*) &value, sizeof(uint8_t)); break; +#endif // HAVE_EIP712_FULL_SUPPORT +#ifdef HAVE_DOMAIN_NAME + case DOMAIN_NAME_VERBOSE_TOKEN: + value = (N_storage.verbose_domain_name ? 0 : 1); + nvm_write((void*) &N_storage.verbose_domain_name, (void*) &value, sizeof(uint8_t)); + break; +#endif // HAVE_DOMAIN_NAME } } From 7c07008335086b1c655beb6438eb629ecf6c5b03 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Fri, 5 May 2023 14:26:09 +0200 Subject: [PATCH 18/25] Dynamic year shown in settings --- Makefile | 1 + src_nbgl/ui_settings.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d037261..104d521 100644 --- a/Makefile +++ b/Makefile @@ -89,6 +89,7 @@ DEFINES += OS_IO_SEPROXYHAL DEFINES += HAVE_SPRINTF HAVE_SNPRINTF_FORMAT_U DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=4 IO_HID_EP_LENGTH=64 HAVE_USB_APDU DEFINES += LEDGER_MAJOR_VERSION=$(APPVERSION_M) LEDGER_MINOR_VERSION=$(APPVERSION_N) LEDGER_PATCH_VERSION=$(APPVERSION_P) +DEFINES += BUILD_YEAR=\"$(shell date +%Y)\" # U2F DEFINES += HAVE_U2F HAVE_IO_U2F diff --git a/src_nbgl/ui_settings.c b/src_nbgl/ui_settings.c index c952140..7981356 100644 --- a/src_nbgl/ui_settings.c +++ b/src_nbgl/ui_settings.c @@ -3,7 +3,7 @@ #include "nbgl_use_case.h" static const char* const infoTypes[] = {"Version", APPNAME " App"}; -static const char* const infoContents[] = {APPVERSION, "(c) 2022 Ledger"}; +static const char* const infoContents[] = {APPVERSION, "(c) " BUILD_YEAR " Ledger"}; enum { BLIND_SIGNING_TOKEN = FIRST_USER_TOKEN, From 1413547d3ec13e13a77344e689be486869305aa4 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Fri, 5 May 2023 14:57:58 +0200 Subject: [PATCH 19/25] Removed large global buffer from NBGL transaction signing UI code --- src_nbgl/ui_approve_tx.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src_nbgl/ui_approve_tx.c b/src_nbgl/ui_approve_tx.c index b3aec12..377166c 100644 --- a/src_nbgl/ui_approve_tx.c +++ b/src_nbgl/ui_approve_tx.c @@ -20,7 +20,6 @@ static nbgl_layoutTagValue_t pair; // these buffers are used as circular static char title_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][TAG_MAX_LEN]; static char msg_buffer[MAX_PLUGIN_ITEMS_PER_SCREEN][VALUE_MAX_LEN]; -static char transaction_type[100]; static nbgl_layoutTagValueList_t useCaseTagValueList; static nbgl_pageInfoLongPress_t infoLongPress; @@ -212,7 +211,7 @@ static void reviewContinueCommon(void) { useCaseTagValueList.smallCaseForValue = false; useCaseTagValueList.wrapping = false; infoLongPress.icon = get_app_icon(true); - infoLongPress.text = tx_approval_context.fromPlugin ? transaction_type : "Review transaction"; + infoLongPress.text = tx_approval_context.fromPlugin ? staxSharedBuffer : "Review transaction"; infoLongPress.longPressText = "Hold to sign"; nbgl_useCaseStaticReview(&useCaseTagValueList, &infoLongPress, @@ -223,12 +222,12 @@ static void reviewContinueCommon(void) { static void buildFirstPage(void) { if (tx_approval_context.fromPlugin) { plugin_ui_get_id(); - SPRINTF(transaction_type, + SPRINTF(staxSharedBuffer, "Review %s\ntransaction:\n%s", strings.common.fullAddress, strings.common.fullAmount); nbgl_useCaseReviewStart(get_app_icon(true), - transaction_type, + staxSharedBuffer, NULL, "Reject transaction", reviewContinue, From 683e410fee0c0ae63f51ce29651f2d15fca51030 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Fri, 5 May 2023 16:43:27 +0200 Subject: [PATCH 20/25] Fix Makefile configuration --- Makefile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 104d521..20e4d69 100644 --- a/Makefile +++ b/Makefile @@ -98,7 +98,6 @@ DEFINES += USB_SEGMENT_SIZE=64 DEFINES += BLE_SEGMENT_SIZE=32 #max MTU, min 20 DEFINES += UNUSED\(x\)=\(void\)x DEFINES += APPVERSION=\"$(APPVERSION)\" -DEFINES += HAVE_UX_FLOW #WEBUSB_URL = www.ledgerwallet.com #DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=$(shell echo -n $(WEBUSB_URL) | wc -c) WEBUSB_URL=$(shell echo -n $(WEBUSB_URL) | sed -e "s/./\\\'\0\\\',/g") @@ -106,21 +105,22 @@ DEFINES += HAVE_UX_FLOW DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL="" ifneq (,$(filter $(TARGET_NAME),TARGET_NANOX TARGET_STAX)) -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl endif -ifneq (,$(filter $(TARGET_NAME),TARGET_NANOS TARGET_NANOS2)) -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=72 +ifeq ($(TARGET_NAME),TARGET_NANOS) +DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 +else +DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 endif ifeq ($(TARGET_NAME),TARGET_STAX) -DEFINES += HAVE_NBGL DEFINES += NBGL_QRCODE else DEFINES += HAVE_BAGL +DEFINES += HAVE_UX_FLOW ifeq ($(TARGET_NAME),TARGET_NANOS) DEFINES += HAVE_WALLET_ID_SDK DEFINES += BAGL_WIDTH=128 BAGL_HEIGHT=32 @@ -236,7 +236,6 @@ include $(BOLOS_SDK)/Makefile.glyphs APP_SOURCE_PATH += src_common src src_features src_plugins SDK_SOURCE_PATH += lib_stusb lib_stusb_impl lib_u2f ifeq ($(TARGET_NAME),TARGET_STAX) -SDK_SOURCE_PATH += lib_ux_stax APP_SOURCE_PATH += src_nbgl else SDK_SOURCE_PATH += lib_ux From fec9a80d2787056150c028553ea941698549da4f Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Tue, 9 May 2023 15:16:03 +0200 Subject: [PATCH 21/25] Stax Ragger tests --- tests/ragger/app/client.py | 183 ++++++---------------------- tests/ragger/app/command_builder.py | 36 +++--- tests/ragger/app/response_parser.py | 26 ++-- tests/ragger/app/setting.py | 16 --- tests/ragger/app/settings.py | 62 ++++++++++ tests/ragger/conftest.py | 8 -- tests/ragger/eip712/InputData.py | 69 ++++++++--- tests/ragger/test_domain_name.py | 172 +++++++++++++++++++------- tests/ragger/test_eip712.py | 81 +++++++++--- 9 files changed, 376 insertions(+), 277 deletions(-) delete mode 100644 tests/ragger/app/setting.py create mode 100644 tests/ragger/app/settings.py diff --git a/tests/ragger/app/client.py b/tests/ragger/app/client.py index 9732c81..616670c 100644 --- a/tests/ragger/app/client.py +++ b/tests/ragger/app/client.py @@ -2,14 +2,9 @@ from enum import IntEnum, auto from typing import Optional from ragger.backend import BackendInterface from ragger.utils import RAPDU -from ragger.navigator import NavInsID, NavIns, NanoNavigator -from .command_builder import EthereumCmdBuilder -from .setting import SettingType, SettingImpl +from .command_builder import CommandBuilder from .eip712 import EIP712FieldType -from .response_parser import EthereumRespParser from .tlv import format_tlv -import signal -import time from pathlib import Path import keychain import rlp @@ -41,58 +36,19 @@ class DOMAIN_NAME_TAG(IntEnum): ADDRESS = 0x22 -class EthereumClient: - _settings: dict[SettingType, SettingImpl] = { - SettingType.BLIND_SIGNING: SettingImpl( - [ "nanos", "nanox", "nanosp" ] - ), - SettingType.DEBUG_DATA: SettingImpl( - [ "nanos", "nanox", "nanosp" ] - ), - SettingType.NONCE: SettingImpl( - [ "nanos", "nanox", "nanosp" ] - ), - SettingType.VERBOSE_EIP712: SettingImpl( - [ "nanox", "nanosp" ] - ), - SettingType.VERBOSE_ENS: SettingImpl( - [ "nanox", "nanosp" ] - ) - } - _click_delay = 1/4 - _eip712_filtering = False - - def __init__(self, client: BackendInterface, golden_run: bool): +class EthAppClient: + def __init__(self, client: BackendInterface): self._client = client - self._chain_id = 1 - self._cmd_builder = EthereumCmdBuilder() - self._resp_parser = EthereumRespParser() - self._nav = NanoNavigator(client, client.firmware, golden_run) - signal.signal(signal.SIGALRM, self._click_signal_timeout) - for setting in self._settings.values(): - setting.value = False + self._cmd_builder = CommandBuilder() def _send(self, payload: bytearray): return self._client.exchange_async_raw(payload) - def _recv(self) -> RAPDU: + def response(self) -> RAPDU: return self._client._last_async_response - def _click_signal_timeout(self, _signum: int, _frame): - self._client.right_click() - - def _enable_click_until_response(self): - signal.setitimer(signal.ITIMER_REAL, - self._click_delay, - self._click_delay) - - def _disable_click_until_response(self): - signal.setitimer(signal.ITIMER_REAL, 0, 0) - def eip712_send_struct_def_struct_name(self, name: str): - with self._send(self._cmd_builder.eip712_send_struct_def_struct_name(name)): - pass - return self._recv().status == 0x9000 + return self._send(self._cmd_builder.eip712_send_struct_def_struct_name(name)) def eip712_send_struct_def_struct_field(self, field_type: EIP712FieldType, @@ -100,98 +56,45 @@ class EthereumClient: type_size: int, array_levels: [], key_name: str): - with self._send(self._cmd_builder.eip712_send_struct_def_struct_field( - field_type, - type_name, - type_size, - array_levels, - key_name)): - pass - return self._recv() + return self._send(self._cmd_builder.eip712_send_struct_def_struct_field( + field_type, + type_name, + type_size, + array_levels, + key_name)) def eip712_send_struct_impl_root_struct(self, name: str): - with self._send(self._cmd_builder.eip712_send_struct_impl_root_struct(name)): - self._enable_click_until_response() - self._disable_click_until_response() - return self._recv() + return self._send(self._cmd_builder.eip712_send_struct_impl_root_struct(name)) def eip712_send_struct_impl_array(self, size: int): - with self._send(self._cmd_builder.eip712_send_struct_impl_array(size)): - pass - return self._recv() + return self._send(self._cmd_builder.eip712_send_struct_impl_array(size)) def eip712_send_struct_impl_struct_field(self, raw_value: bytes): - for apdu in self._cmd_builder.eip712_send_struct_impl_struct_field(raw_value): - with self._send(apdu): - self._enable_click_until_response() - self._disable_click_until_response() - assert self._recv().status == 0x9000 + chunks = self._cmd_builder.eip712_send_struct_impl_struct_field(raw_value) + for chunk in chunks[:-1]: + with self._send(chunk): + pass + return self._send(chunks[-1]) - def eip712_sign_new(self, bip32_path: str): - with self._send(self._cmd_builder.eip712_sign_new(bip32_path)): - time.sleep(0.5) # tight on timing, needed by the CI otherwise might fail sometimes - if not self._settings[SettingType.VERBOSE_EIP712].value and \ - not self._eip712_filtering: # need to skip the message hash - self._client.right_click() - self._client.right_click() - self._client.both_click() # approve signature - resp = self._recv() - assert resp.status == 0x9000 - return self._resp_parser.sign(resp.data) + def eip712_sign_new(self, bip32_path: str, verbose: bool): + return self._send(self._cmd_builder.eip712_sign_new(bip32_path)) def eip712_sign_legacy(self, bip32_path: str, domain_hash: bytes, message_hash: bytes): - with self._send(self._cmd_builder.eip712_sign_legacy(bip32_path, - domain_hash, - message_hash)): - self._client.right_click() # sign typed message screen - for _ in range(2): # two hashes (domain + message) - if self._client.firmware.device == "nanos": - screens_per_hash = 4 - else: - screens_per_hash = 2 - for _ in range(screens_per_hash): - self._client.right_click() - self._client.both_click() # approve signature - - resp = self._recv() - - assert resp.status == 0x9000 - return self._resp_parser.sign(resp.data) - - def settings_set(self, new_values: dict[SettingType, bool]): - # Go to settings - for _ in range(2): - self._client.right_click() - self._client.both_click() - - for enum in self._settings.keys(): - if self._client.firmware.device in self._settings[enum].devices: - if enum in new_values.keys(): - if new_values[enum] != self._settings[enum].value: - self._client.both_click() - self._settings[enum].value = new_values[enum] - self._client.right_click() - self._client.both_click() + return self._send(self._cmd_builder.eip712_sign_legacy(bip32_path, + domain_hash, + message_hash)) def eip712_filtering_activate(self): - with self._send(self._cmd_builder.eip712_filtering_activate()): - pass - self._eip712_filtering = True - assert self._recv().status == 0x9000 + return self._send(self._cmd_builder.eip712_filtering_activate()) def eip712_filtering_message_info(self, name: str, filters_count: int, sig: bytes): - with self._send(self._cmd_builder.eip712_filtering_message_info(name, filters_count, sig)): - self._enable_click_until_response() - self._disable_click_until_response() - assert self._recv().status == 0x9000 + return self._send(self._cmd_builder.eip712_filtering_message_info(name, filters_count, sig)) def eip712_filtering_show_field(self, name: str, sig: bytes): - with self._send(self._cmd_builder.eip712_filtering_show_field(name, sig)): - pass - assert self._recv().status == 0x9000 + return self._send(self._cmd_builder.eip712_filtering_show_field(name, sig)) def send_fund(self, bip32_path: str, @@ -200,8 +103,7 @@ class EthereumClient: gas_limit: int, to: bytes, amount: float, - chain_id: int, - screenshot_collection: str = None): + chain_id: int): data = list() data.append(nonce) data.append(gas_price) @@ -213,27 +115,14 @@ class EthereumClient: data.append(bytes()) data.append(bytes()) - for chunk in self._cmd_builder.sign(bip32_path, rlp.encode(data)): + chunks = self._cmd_builder.sign(bip32_path, rlp.encode(data)) + for chunk in chunks[:-1]: with self._send(chunk): - nav_ins = NavIns(NavInsID.RIGHT_CLICK) - final_ins = [ NavIns(NavInsID.BOTH_CLICK) ] - target_text = "and send" - if screenshot_collection: - self._nav.navigate_until_text_and_compare(nav_ins, - final_ins, - target_text, - ROOT_SCREENSHOT_PATH, - screenshot_collection) - else: - self._nav.navigate_until_text(nav_ins, - final_ins, - target_text) + pass + return self._send(chunks[-1]) - def get_challenge(self) -> int: - with self._send(self._cmd_builder.get_challenge()): - pass - resp = self._recv() - return self._resp_parser.challenge(resp.data) + def get_challenge(self): + return self._send(self._cmd_builder.get_challenge()) def provide_domain_name(self, challenge: int, name: str, addr: bytes): payload = format_tlv(DOMAIN_NAME_TAG.STRUCTURE_TYPE, 3) # TrustedDomainName @@ -247,6 +136,8 @@ class EthereumClient: payload += format_tlv(DOMAIN_NAME_TAG.SIGNATURE, keychain.sign_data(keychain.Key.DOMAIN_NAME, payload)) - for chunk in self._cmd_builder.provide_domain_name(payload): + chunks = self._cmd_builder.provide_domain_name(payload) + for chunk in chunks[:-1]: with self._send(chunk): pass + return self._send(chunks[-1]) diff --git a/tests/ragger/app/command_builder.py b/tests/ragger/app/command_builder.py index aac10d0..ae3f730 100644 --- a/tests/ragger/app/command_builder.py +++ b/tests/ragger/app/command_builder.py @@ -29,7 +29,7 @@ class P2Type(IntEnum): FILTERING_CONTRACT_NAME = 0x0f FILTERING_FIELD_NAME = 0xff -class EthereumCmdBuilder: +class CommandBuilder: _CLA: int = 0xE0 def _serialize(self, @@ -103,6 +103,7 @@ class EthereumCmdBuilder: data) def eip712_send_struct_impl_struct_field(self, data: bytearray) -> Iterator[bytes]: + chunks = list() # Add a 16-bit integer with the data's byte length (network byte order) data_w_length = bytearray() data_w_length.append((len(data) & 0xff00) >> 8) @@ -110,11 +111,12 @@ class EthereumCmdBuilder: data_w_length += data while len(data_w_length) > 0: p1 = P1Type.PARTIAL_SEND if len(data_w_length) > 0xff else P1Type.COMPLETE_SEND - yield self._serialize(InsType.EIP712_SEND_STRUCT_IMPL, - p1, - P2Type.STRUCT_FIELD, - data_w_length[:0xff]) + chunks.append(self._serialize(InsType.EIP712_SEND_STRUCT_IMPL, + p1, + P2Type.STRUCT_FIELD, + data_w_length[:0xff])) data_w_length = data_w_length[0xff:] + return chunks def eip712_sign_new(self, bip32_path: str) -> bytes: data = pack_derivation_path(bip32_path) @@ -167,29 +169,33 @@ class EthereumCmdBuilder: P2Type.FILTERING_FIELD_NAME, self._eip712_filtering_send_name(name, sig)) - def sign(self, bip32_path: str, rlp_data: bytes) -> Iterator[bytes]: + def sign(self, bip32_path: str, rlp_data: bytes) -> list[bytes]: + apdus = list() payload = pack_derivation_path(bip32_path) payload += rlp_data p1 = P1Type.SIGN_FIRST_CHUNK while len(payload) > 0: - yield self._serialize(InsType.SIGN, - p1, - 0x00, - payload[:0xff]) + apdus.append(self._serialize(InsType.SIGN, + p1, + 0x00, + payload[:0xff])) payload = payload[0xff:] p1 = P1Type.SIGN_SUBSQT_CHUNK + return apdus def get_challenge(self) -> bytes: return self._serialize(InsType.GET_CHALLENGE, 0x00, 0x00) - def provide_domain_name(self, tlv_payload: bytes) -> bytes: + def provide_domain_name(self, tlv_payload: bytes) -> list[bytes]: + chunks = list() payload = struct.pack(">H", len(tlv_payload)) payload += tlv_payload p1 = 1 while len(payload) > 0: - yield self._serialize(InsType.PROVIDE_DOMAIN_NAME, - p1, - 0x00, - payload[:0xff]) + chunks.append(self._serialize(InsType.PROVIDE_DOMAIN_NAME, + p1, + 0x00, + payload[:0xff])) payload = payload[0xff:] p1 = 0 + return chunks diff --git a/tests/ragger/app/response_parser.py b/tests/ragger/app/response_parser.py index 242f4cf..5e73df4 100644 --- a/tests/ragger/app/response_parser.py +++ b/tests/ragger/app/response_parser.py @@ -1,18 +1,14 @@ -class EthereumRespParser: - def sign(self, data: bytes): - assert len(data) == (1 + 32 + 32) +def signature(data: bytes) -> tuple[bytes, bytes, bytes]: + assert len(data) == (1 + 32 + 32) - v = data[0:1] - data = data[1:] + v = data[0:1] + data = data[1:] + r = data[0:32] + data = data[32:] + s = data[0:32] - r = data[0:32] - data = data[32:] + return v, r, s - s = data[0:32] - data = data[32:] - - return v, r, s - - def challenge(self, data: bytes) -> int: - assert len(data) == 4 - return int.from_bytes(data, "big") +def challenge(data: bytes) -> int: + assert len(data) == 4 + return int.from_bytes(data, "big") diff --git a/tests/ragger/app/setting.py b/tests/ragger/app/setting.py deleted file mode 100644 index 7e79da7..0000000 --- a/tests/ragger/app/setting.py +++ /dev/null @@ -1,16 +0,0 @@ -from enum import IntEnum, auto -from typing import List - -class SettingType(IntEnum): - BLIND_SIGNING = 0, - DEBUG_DATA = auto() - NONCE = auto() - VERBOSE_EIP712 = auto() - VERBOSE_ENS = auto() - -class SettingImpl: - devices: List[str] - value: bool - - def __init__(self, devs: List[str]): - self.devices = devs diff --git a/tests/ragger/app/settings.py b/tests/ragger/app/settings.py new file mode 100644 index 0000000..435e21a --- /dev/null +++ b/tests/ragger/app/settings.py @@ -0,0 +1,62 @@ +from enum import Enum, auto +from typing import List +from ragger.firmware import Firmware +from ragger.navigator import Navigator, NavInsID, NavIns + +class SettingID(Enum): + BLIND_SIGNING = auto() + DEBUG_DATA = auto() + NONCE = auto() + VERBOSE_EIP712 = auto() + VERBOSE_ENS = auto() + +def get_device_settings(device: str) -> list[SettingID]: + if device == "nanos": + return [ + SettingID.BLIND_SIGNING, + SettingID.DEBUG_DATA, + SettingID.NONCE + ] + if (device == "nanox") or (device == "nanosp") or (device == "stax"): + return [ + SettingID.BLIND_SIGNING, + SettingID.DEBUG_DATA, + SettingID.NONCE, + SettingID.VERBOSE_EIP712, + SettingID.VERBOSE_ENS + ] + return [] + +settings_per_page = 3 + +def get_setting_position(device: str, setting: NavInsID) -> tuple[int, int]: + screen_height = 672 # px + header_height = 85 # px + footer_height = 124 # px + usable_height = screen_height - (header_height + footer_height) + setting_height = usable_height // settings_per_page + index_in_page = get_device_settings(device).index(setting) % settings_per_page + return 350, header_height + (setting_height * index_in_page) + (setting_height // 2) + +def settings_toggle(fw: Firmware, nav: Navigator, to_toggle: list[SettingID]): + moves = list() + settings = get_device_settings(fw.device) + # Assume the app is on the home page + if fw.device.startswith("nano"): + moves += [NavInsID.RIGHT_CLICK] * 2 + moves += [NavInsID.BOTH_CLICK] + for setting in settings: + if setting in to_toggle: + moves += [NavInsID.BOTH_CLICK] + moves += [NavInsID.RIGHT_CLICK] + moves += [NavInsID.BOTH_CLICK] # Back + else: + moves += [NavInsID.USE_CASE_HOME_SETTINGS] + for setting in settings: + setting_idx = settings.index(setting) + if (setting_idx > 0) and (setting_idx % settings_per_page) == 0: + moves += [NavInsID.USE_CASE_SETTINGS_NEXT] + if setting in to_toggle: + moves += [NavIns(NavInsID.TOUCH, get_setting_position(fw.device, setting))] + moves += [NavInsID.EXIT_HEADER_TAP] + nav.navigate(moves) diff --git a/tests/ragger/conftest.py b/tests/ragger/conftest.py index 68799b2..6dd6f4b 100644 --- a/tests/ragger/conftest.py +++ b/tests/ragger/conftest.py @@ -1,12 +1,4 @@ -import pytest from ragger.conftest import configuration -from ragger.backend import BackendInterface -from app.client import EthereumClient - -# This final fixture will return the properly configured app client, to be used in tests -@pytest.fixture -def app_client(backend: BackendInterface, golden_run: bool) -> EthereumClient: - return EthereumClient(backend, golden_run) # Pull all features from the base ragger conftest using the overridden configuration pytest_plugins = ("ragger.conftest.base_conftest", ) diff --git a/tests/ragger/eip712/InputData.py b/tests/ragger/eip712/InputData.py index 02a96eb..da382d8 100644 --- a/tests/ragger/eip712/InputData.py +++ b/tests/ragger/eip712/InputData.py @@ -4,15 +4,19 @@ import json import sys import re import hashlib -from app.client import EthereumClient, EIP712FieldType +from app.client import EthAppClient, EIP712FieldType import keychain +from typing import Callable +import signal # global variables -app_client: EthereumClient = None +app_client: EthAppClient = None filtering_paths = None current_path = list() sig_ctx = {} +autonext_handler: Callable = None + @@ -97,11 +101,12 @@ def send_struct_def_field(typename, keyname): type_enum = EIP712FieldType.CUSTOM typesize = None - app_client.eip712_send_struct_def_struct_field(type_enum, - typename, - typesize, - array_lvls, - keyname) + with app_client.eip712_send_struct_def_struct_field(type_enum, + typename, + typesize, + array_lvls, + keyname): + pass return (typename, type_enum, typesize, array_lvls) @@ -191,7 +196,9 @@ def send_struct_impl_field(value, field): if path in filtering_paths.keys(): send_filtering_show_field(filtering_paths[path]) - app_client.eip712_send_struct_impl_struct_field(data) + with app_client.eip712_send_struct_impl_struct_field(data): + enable_autonext() + disable_autonext() @@ -201,7 +208,8 @@ def evaluate_field(structs, data, field, lvls_left, new_level = True): if new_level: current_path.append(field["name"]) if len(array_lvls) > 0 and lvls_left > 0: - app_client.eip712_send_struct_impl_array(len(data)) + with app_client.eip712_send_struct_impl_array(len(data)): + pass idx = 0 for subdata in data: current_path.append("[]") @@ -252,7 +260,9 @@ def send_filtering_message_info(display_name: str, filters_count: int): to_sign.append(ord(char)) sig = keychain.sign_data(keychain.Key.CAL, to_sign) - app_client.eip712_filtering_message_info(display_name, filters_count, sig) + with app_client.eip712_filtering_message_info(display_name, filters_count, sig): + enable_autonext() + disable_autonext() # ledgerjs doesn't actually sign anything, and instead uses already pre-computed signatures def send_filtering_show_field(display_name): @@ -270,7 +280,8 @@ def send_filtering_show_field(display_name): for char in display_name: to_sign.append(ord(char)) sig = keychain.sign_data(keychain.Key.CAL, to_sign) - app_client.eip712_filtering_show_field(display_name, sig) + with app_client.eip712_filtering_show_field(display_name, sig): + pass def read_filtering_file(domain, message, filtering_file_path): data_json = None @@ -309,9 +320,25 @@ def init_signature_context(types, domain): schema_hash = hashlib.sha224(schema_str.encode()) sig_ctx["schema_hash"] = bytearray.fromhex(schema_hash.hexdigest()) -def process_file(aclient: EthereumClient, input_file_path: str, filtering_file_path = None) -> bool: + +def next_timeout(_signum: int, _frame): + autonext_handler() + +def enable_autonext(): + delay = 1/4 + signal.setitimer(signal.ITIMER_REAL, delay, delay) + +def disable_autonext(): + signal.setitimer(signal.ITIMER_REAL, 0, 0) + + +def process_file(aclient: EthAppClient, + input_file_path: str, + filtering_file_path = None, + autonext: Callable = None) -> bool: global sig_ctx global app_client + global autonext_handler app_client = aclient with open(input_file_path, "r") as data: @@ -322,23 +349,31 @@ def process_file(aclient: EthereumClient, input_file_path: str, filtering_file_p domain = data_json["domain"] message = data_json["message"] + if autonext: + autonext_handler = autonext + signal.signal(signal.SIGALRM, next_timeout) + if filtering_file_path: init_signature_context(types, domain) filtr = read_filtering_file(domain, message, filtering_file_path) # send types definition for key in types.keys(): - app_client.eip712_send_struct_def_struct_name(key) + with app_client.eip712_send_struct_def_struct_name(key): + pass for f in types[key]: (f["type"], f["enum"], f["typesize"], f["array_lvls"]) = \ send_struct_def_field(f["type"], f["name"]) if filtering_file_path: - app_client.eip712_filtering_activate() + with app_client.eip712_filtering_activate(): + pass prepare_filtering(filtr, message) # send domain implementation - app_client.eip712_send_struct_impl_root_struct(domain_typename) + with app_client.eip712_send_struct_impl_root_struct(domain_typename): + enable_autonext() + disable_autonext() if not send_struct_impl(types, domain, domain_typename): return False @@ -349,7 +384,9 @@ def process_file(aclient: EthereumClient, input_file_path: str, filtering_file_p send_filtering_message_info(domain["name"], len(filtering_paths)) # send message implementation - app_client.eip712_send_struct_impl_root_struct(message_typename) + with app_client.eip712_send_struct_impl_root_struct(message_typename): + enable_autonext() + disable_autonext() if not send_struct_impl(types, message, message_typename): return False diff --git a/tests/ragger/test_domain_name.py b/tests/ragger/test_domain_name.py index 317f72d..be08ebc 100644 --- a/tests/ragger/test_domain_name.py +++ b/tests/ragger/test_domain_name.py @@ -1,7 +1,11 @@ import pytest from ragger.error import ExceptionRAPDU -from app.client import EthereumClient, StatusWord -from app.setting import SettingType +from ragger.firmware import Firmware +from ragger.backend import BackendInterface +from ragger.navigator import Navigator, NavInsID +from app.client import EthAppClient, StatusWord, ROOT_SCREENSHOT_PATH +from app.settings import SettingID, settings_toggle +import app.response_parser as ResponseParser import struct # Values used across all tests @@ -20,108 +24,182 @@ AMOUNT = 1.22 def verbose(request) -> bool: return request.param -def common(app_client: EthereumClient) -> int: +def common(app_client: EthAppClient) -> int: if app_client._client.firmware.device == "nanos": pytest.skip("Not supported on LNS") - return app_client.get_challenge() + with app_client.get_challenge(): + pass + return ResponseParser.challenge(app_client.response().data) -def test_send_fund(app_client: EthereumClient, verbose: bool): +def test_send_fund(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: str, + verbose: bool): + app_client = EthAppClient(backend) challenge = common(app_client) if verbose: - app_client.settings_set({ - SettingType.VERBOSE_ENS: True - }) + settings_toggle(firmware, navigator, [SettingID.VERBOSE_ENS]) - app_client.provide_domain_name(challenge, NAME, ADDR) + with app_client.provide_domain_name(challenge, NAME, ADDR): + pass - app_client.send_fund(BIP32_PATH, - NONCE, - GAS_PRICE, - GAS_LIMIT, - ADDR, - AMOUNT, - CHAIN_ID, - "domain_name_verbose_" + str(verbose)) + with app_client.send_fund(BIP32_PATH, + NONCE, + GAS_PRICE, + GAS_LIMIT, + ADDR, + AMOUNT, + CHAIN_ID): + moves = list() + if firmware.device.startswith("nano"): + moves += [ NavInsID.RIGHT_CLICK ] * 4 + if verbose: + moves += [ NavInsID.RIGHT_CLICK ] + moves += [ NavInsID.BOTH_CLICK ] + else: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] * 2 + if verbose: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, + "domain_name_verbose_" + str(verbose), + moves) -def test_send_fund_wrong_challenge(app_client: EthereumClient): + +def test_send_fund_wrong_challenge(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) caught = False challenge = common(app_client) try: - app_client.provide_domain_name(~challenge & 0xffffffff, NAME, ADDR) + with app_client.provide_domain_name(~challenge & 0xffffffff, NAME, ADDR): + pass except ExceptionRAPDU as e: assert e.status == StatusWord.INVALID_DATA else: assert False # An exception should have been raised -def test_send_fund_wrong_addr(app_client: EthereumClient): + +def test_send_fund_wrong_addr(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: str): + app_client = EthAppClient(backend) challenge = common(app_client) - app_client.provide_domain_name(challenge, NAME, ADDR) + with app_client.provide_domain_name(challenge, NAME, ADDR): + pass addr = bytearray(ADDR) addr.reverse() - app_client.send_fund(BIP32_PATH, - NONCE, - GAS_PRICE, - GAS_LIMIT, - addr, - AMOUNT, - CHAIN_ID, - "domain_name_wrong_addr") + with app_client.send_fund(BIP32_PATH, + NONCE, + GAS_PRICE, + GAS_LIMIT, + addr, + AMOUNT, + CHAIN_ID): + moves = list() + if firmware.device.startswith("nano"): + moves += [ NavInsID.RIGHT_CLICK ] * 4 + moves += [ NavInsID.BOTH_CLICK ] + else: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] * 2 + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, + "domain_name_wrong_addr", + moves) -def test_send_fund_non_mainnet(app_client: EthereumClient): + +def test_send_fund_non_mainnet(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + test_name: str): + app_client = EthAppClient(backend) challenge = common(app_client) - app_client.provide_domain_name(challenge, NAME, ADDR) + with app_client.provide_domain_name(challenge, NAME, ADDR): + pass - app_client.send_fund(BIP32_PATH, - NONCE, - GAS_PRICE, - GAS_LIMIT, - ADDR, - AMOUNT, - 5, - "domain_name_non_mainnet") + with app_client.send_fund(BIP32_PATH, + NONCE, + GAS_PRICE, + GAS_LIMIT, + ADDR, + AMOUNT, + 5): + moves = list() + if firmware.device.startswith("nano"): + moves += [ NavInsID.RIGHT_CLICK ] * 5 + moves += [ NavInsID.BOTH_CLICK ] + else: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] * 3 + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate_and_compare(ROOT_SCREENSHOT_PATH, + "domain_name_non_mainnet", + moves) -def test_send_fund_domain_too_long(app_client: EthereumClient): + +def test_send_fund_domain_too_long(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) challenge = common(app_client) try: - app_client.provide_domain_name(challenge, "ledger" + "0"*25 + ".eth", ADDR) + with app_client.provide_domain_name(challenge, "ledger" + "0"*25 + ".eth", ADDR): + pass except ExceptionRAPDU as e: assert e.status == StatusWord.INVALID_DATA else: assert False # An exception should have been raised -def test_send_fund_domain_invalid_character(app_client: EthereumClient): + +def test_send_fund_domain_invalid_character(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) challenge = common(app_client) try: - app_client.provide_domain_name(challenge, "l\xe8dger.eth", ADDR) + with app_client.provide_domain_name(challenge, "l\xe8dger.eth", ADDR): + pass except ExceptionRAPDU as e: assert e.status == StatusWord.INVALID_DATA else: assert False # An exception should have been raised -def test_send_fund_uppercase(app_client: EthereumClient): + +def test_send_fund_uppercase(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) challenge = common(app_client) try: - app_client.provide_domain_name(challenge, NAME.upper(), ADDR) + with app_client.provide_domain_name(challenge, NAME.upper(), ADDR): + pass except ExceptionRAPDU as e: assert e.status == StatusWord.INVALID_DATA else: assert False # An exception should have been raised -def test_send_fund_domain_non_ens(app_client: EthereumClient): + +def test_send_fund_domain_non_ens(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) challenge = common(app_client) try: - app_client.provide_domain_name(challenge, "ledger.hte", ADDR) + with app_client.provide_domain_name(challenge, "ledger.hte", ADDR): + pass except ExceptionRAPDU as e: assert e.status == StatusWord.INVALID_DATA else: diff --git a/tests/ragger/test_eip712.py b/tests/ragger/test_eip712.py index 29cb843..729c4a6 100644 --- a/tests/ragger/test_eip712.py +++ b/tests/ragger/test_eip712.py @@ -2,10 +2,17 @@ import pytest import os import fnmatch from typing import List -from app.client import EthereumClient, SettingType +from ragger.firmware import Firmware +from ragger.backend import BackendInterface +from ragger.navigator import Navigator, NavInsID +from app.client import EthAppClient +from app.settings import SettingID, settings_toggle from eip712 import InputData from pathlib import Path from configparser import ConfigParser +import app.response_parser as ResponseParser +from functools import partial +import time BIP32_PATH = "m/44'/60'/0'/0/0" @@ -30,19 +37,52 @@ def filtering(request) -> bool: return request.param -def test_eip712_legacy(app_client: EthereumClient): - v, r, s = app_client.eip712_sign_legacy( - BIP32_PATH, - bytes.fromhex('6137beb405d9ff777172aa879e33edb34a1460e701802746c5ef96e741710e59'), - bytes.fromhex('eb4221181ff3f1a83ea7313993ca9218496e424604ba9492bb4052c03d5c3df8') - ) +def test_eip712_legacy(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator): + app_client = EthAppClient(backend) + with app_client.eip712_sign_legacy( + BIP32_PATH, + bytes.fromhex('6137beb405d9ff777172aa879e33edb34a1460e701802746c5ef96e741710e59'), + bytes.fromhex('eb4221181ff3f1a83ea7313993ca9218496e424604ba9492bb4052c03d5c3df8')): + moves = list() + if firmware.device.startswith("nano"): + moves += [ NavInsID.RIGHT_CLICK ] + if firmware.device == "nanos": + screens_per_hash = 4 + else: + screens_per_hash = 2 + moves += [ NavInsID.RIGHT_CLICK ] * screens_per_hash * 2 + moves += [ NavInsID.BOTH_CLICK ] + else: + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] * 2 + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate(moves) + + v, r, s = ResponseParser.signature(app_client.response().data) assert v == bytes.fromhex("1c") assert r == bytes.fromhex("ea66f747173762715751c889fea8722acac3fc35db2c226d37a2e58815398f64") assert s == bytes.fromhex("52d8ba9153de9255da220ffd36762c0b027701a3b5110f0a765f94b16a9dfb55") -def test_eip712_new(app_client: EthereumClient, input_file: Path, verbose: bool, filtering: bool): - if app_client._client.firmware.device == "nanos": + +def autonext(fw: Firmware, nav: Navigator): + moves = list() + if fw.device.startswith("nano"): + moves = [ NavInsID.RIGHT_CLICK ] + else: + moves = [ NavInsID.USE_CASE_REVIEW_TAP ] + nav.navigate(moves) + + +def test_eip712_new(firmware: Firmware, + backend: BackendInterface, + navigator: Navigator, + input_file: Path, + verbose: bool, + filtering: bool): + app_client = EthAppClient(backend) + if firmware.device == "nanos": pytest.skip("Not supported on LNS") else: test_path = "%s/%s" % (input_file.parent, "-".join(input_file.stem.split("-")[:-1])) @@ -63,12 +103,25 @@ def test_eip712_new(app_client: EthereumClient, input_file: Path, verbose: bool, if not filtering or Path(filter_file).is_file(): if verbose: - app_client.settings_set({ - SettingType.VERBOSE_EIP712: True - }) + settings_toggle(firmware, navigator, [SettingID.VERBOSE_EIP712]) - assert InputData.process_file(app_client, input_file, filter_file) == True - v, r, s = app_client.eip712_sign_new(BIP32_PATH) + assert InputData.process_file(app_client, + input_file, + filter_file, + partial(autonext, firmware, navigator)) == True + with app_client.eip712_sign_new(BIP32_PATH, verbose): + time.sleep(0.5) # tight on timing, needed by the CI otherwise might fail sometimes + moves = list() + if firmware.device.startswith("nano"): + if not verbose and not filtering: # need to skip the message hash + moves = [ NavInsID.RIGHT_CLICK ] * 2 + moves += [ NavInsID.BOTH_CLICK ] + else: + if not verbose and not filtering: # need to skip the message hash + moves += [ NavInsID.USE_CASE_REVIEW_TAP ] + moves += [ NavInsID.USE_CASE_REVIEW_CONFIRM ] + navigator.navigate(moves) + v, r, s = ResponseParser.signature(app_client.response().data) #print("[signature]") #print("v = %s" % (v.hex())) #print("r = %s" % (r.hex())) From 510a935e26347e71a8211a2659bbe9fc3e9cb99c Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Mon, 15 May 2023 15:46:22 +0200 Subject: [PATCH 22/25] Fix EIP712 fast autonext timer disrupting speculos for Stax --- tests/ragger/eip712/InputData.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/ragger/eip712/InputData.py b/tests/ragger/eip712/InputData.py index da382d8..6dd6471 100644 --- a/tests/ragger/eip712/InputData.py +++ b/tests/ragger/eip712/InputData.py @@ -325,8 +325,12 @@ def next_timeout(_signum: int, _frame): autonext_handler() def enable_autonext(): - delay = 1/4 - signal.setitimer(signal.ITIMER_REAL, delay, delay) + seconds = 1/4 + if app_client._client.firmware.device == 'stax': # Stax Speculos is slow + interval = seconds * 3 + else: + interval = seconds + signal.setitimer(signal.ITIMER_REAL, seconds, interval) def disable_autonext(): signal.setitimer(signal.ITIMER_REAL, 0, 0) From 8f4fb59ec036aa84966e7572874267ef4af70606 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Mon, 15 May 2023 15:46:43 +0200 Subject: [PATCH 23/25] Updated Ragger --- tests/ragger/app/settings.py | 2 +- tests/ragger/requirements.txt | 2 +- tests/ragger/test_eip712.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ragger/app/settings.py b/tests/ragger/app/settings.py index 435e21a..48d78cc 100644 --- a/tests/ragger/app/settings.py +++ b/tests/ragger/app/settings.py @@ -59,4 +59,4 @@ def settings_toggle(fw: Firmware, nav: Navigator, to_toggle: list[SettingID]): if setting in to_toggle: moves += [NavIns(NavInsID.TOUCH, get_setting_position(fw.device, setting))] moves += [NavInsID.EXIT_HEADER_TAP] - nav.navigate(moves) + nav.navigate(moves, screen_change_before_first_instruction=False) diff --git a/tests/ragger/requirements.txt b/tests/ragger/requirements.txt index e408ead..818749b 100644 --- a/tests/ragger/requirements.txt +++ b/tests/ragger/requirements.txt @@ -1,4 +1,4 @@ -ragger[speculos]>=1.6.0,<1.7.0 +ragger[speculos]>=1.7.0,<1.8.0 pytest ecdsa simple-rlp diff --git a/tests/ragger/test_eip712.py b/tests/ragger/test_eip712.py index 729c4a6..6ff0bc7 100644 --- a/tests/ragger/test_eip712.py +++ b/tests/ragger/test_eip712.py @@ -72,7 +72,7 @@ def autonext(fw: Firmware, nav: Navigator): moves = [ NavInsID.RIGHT_CLICK ] else: moves = [ NavInsID.USE_CASE_REVIEW_TAP ] - nav.navigate(moves) + nav.navigate(moves, screen_change_before_first_instruction=False, screen_change_after_last_instruction=False) def test_eip712_new(firmware: Firmware, From cea6f2baa7149cb1563aec6bac18e35e2d944985 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Mon, 15 May 2023 17:33:08 +0200 Subject: [PATCH 24/25] Added golden snapshots for Stax Ragger tests --- .../stax/domain_name_non_mainnet/00000.png | Bin 0 -> 8435 bytes .../stax/domain_name_non_mainnet/00001.png | Bin 0 -> 15045 bytes .../stax/domain_name_non_mainnet/00002.png | Bin 0 -> 7485 bytes .../stax/domain_name_non_mainnet/00003.png | Bin 0 -> 9348 bytes .../stax/domain_name_non_mainnet/00004.png | Bin 0 -> 5086 bytes .../stax/domain_name_verbose_False/00000.png | Bin 0 -> 8435 bytes .../stax/domain_name_verbose_False/00001.png | Bin 0 -> 10942 bytes .../stax/domain_name_verbose_False/00002.png | Bin 0 -> 9348 bytes .../stax/domain_name_verbose_False/00003.png | Bin 0 -> 5086 bytes .../stax/domain_name_verbose_True/00000.png | Bin 0 -> 8435 bytes .../stax/domain_name_verbose_True/00001.png | Bin 0 -> 14741 bytes .../stax/domain_name_verbose_True/00002.png | Bin 0 -> 7822 bytes .../stax/domain_name_verbose_True/00003.png | Bin 0 -> 9348 bytes .../stax/domain_name_verbose_True/00004.png | Bin 0 -> 5086 bytes .../stax/domain_name_wrong_addr/00000.png | Bin 0 -> 8435 bytes .../stax/domain_name_wrong_addr/00001.png | Bin 0 -> 15550 bytes .../stax/domain_name_wrong_addr/00002.png | Bin 0 -> 9348 bytes .../stax/domain_name_wrong_addr/00003.png | Bin 0 -> 5086 bytes 18 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/ragger/snapshots/stax/domain_name_non_mainnet/00000.png create mode 100644 tests/ragger/snapshots/stax/domain_name_non_mainnet/00001.png create mode 100644 tests/ragger/snapshots/stax/domain_name_non_mainnet/00002.png create mode 100644 tests/ragger/snapshots/stax/domain_name_non_mainnet/00003.png create mode 100644 tests/ragger/snapshots/stax/domain_name_non_mainnet/00004.png create mode 100644 tests/ragger/snapshots/stax/domain_name_verbose_False/00000.png create mode 100644 tests/ragger/snapshots/stax/domain_name_verbose_False/00001.png create mode 100644 tests/ragger/snapshots/stax/domain_name_verbose_False/00002.png create mode 100644 tests/ragger/snapshots/stax/domain_name_verbose_False/00003.png create mode 100644 tests/ragger/snapshots/stax/domain_name_verbose_True/00000.png create mode 100644 tests/ragger/snapshots/stax/domain_name_verbose_True/00001.png create mode 100644 tests/ragger/snapshots/stax/domain_name_verbose_True/00002.png create mode 100644 tests/ragger/snapshots/stax/domain_name_verbose_True/00003.png create mode 100644 tests/ragger/snapshots/stax/domain_name_verbose_True/00004.png create mode 100644 tests/ragger/snapshots/stax/domain_name_wrong_addr/00000.png create mode 100644 tests/ragger/snapshots/stax/domain_name_wrong_addr/00001.png create mode 100644 tests/ragger/snapshots/stax/domain_name_wrong_addr/00002.png create mode 100644 tests/ragger/snapshots/stax/domain_name_wrong_addr/00003.png diff --git a/tests/ragger/snapshots/stax/domain_name_non_mainnet/00000.png b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..a23d9177c3caeaee251141b056d94ed980f4bb5a GIT binary patch literal 8435 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 OK5L6x=JnUSlm825`x|rs literal 0 HcmV?d00001 diff --git a/tests/ragger/snapshots/stax/domain_name_non_mainnet/00001.png b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..25278595239f5dad36d574d40b68a59e5512c75d GIT binary patch literal 15045 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 XxbCHaqOicrlekbaVUB30700{$f literal 0 HcmV?d00001 diff --git a/tests/ragger/snapshots/stax/domain_name_non_mainnet/00003.png b/tests/ragger/snapshots/stax/domain_name_non_mainnet/00003.png new file mode 100644 index 0000000000000000000000000000000000000000..50df3498127a21582b14f2b69375b5f885b7217f GIT binary patch literal 9348 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�lMY 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 literal 0 HcmV?d00001 diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_False/00000.png b/tests/ragger/snapshots/stax/domain_name_verbose_False/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..a23d9177c3caeaee251141b056d94ed980f4bb5a GIT binary patch literal 8435 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 OK5L6x=JnUSlm825`x|rs literal 0 HcmV?d00001 diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_False/00001.png b/tests/ragger/snapshots/stax/domain_name_verbose_False/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..5e0c0a941e4f5ae45c5b4363de7a1b62a585bf1d GIT binary patch literal 10942 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 literal 0 HcmV?d00001 diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_False/00002.png b/tests/ragger/snapshots/stax/domain_name_verbose_False/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..2d6b095b8b7856ce0c19502a1fbd21cfb09c22a7 GIT binary patch literal 9348 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 Hr&@6SYv%)Dpx*fk`X6sWp?+ zkR~;jsAyt{iiqTR%*Gok5h@}%WQvHSfCzFqZ)cuoX1<+y&WH1y54|7v`|P#%UTgh- zd#!yvD8R>LwZ&=!0|OJ^Zx06>7#Q9*Fj)5RlV!k&YhVk>z+n9o-^1U8Tr83B2STSu zf4&;$cKX0~+YYXZ$h}LpH$2+Ej%;LW=y!Wvz0pp?qi>?mXy9*gUm8Ix1!FAu#Nemp zo2B&kZyvy^_7$V9JmDoq6txe|~De`D(1;9-}qawnQ9U+qNwJlZ~Hx zef;&&8y|Dy|3wbB^qN=Jg3-}vs5`EGe3$r=eubzOy!Q{`&YfN&PtV|TrE^8x5$XaK zedY7Nqv6Fm);hIj^BI*%ZRDTE{z`$qCfX>HUXuzYuq@4*7!2#ePMJz06qd2f%h_kO z@3cNAy$758g@ML-ZDO$);mTkzYObO(GnE?6Xkv+(i2|-%EFub3D%#|+cQO?hhjJZZ zxm#aVVf&Kko$O))+AXjM0UK-FlUbsE2`nbU|Gy85^kV?CeZ7QJi-^=TuBlUX&}dkg5|C+~}IHcC1~u6`Yfk3ZOok->EIok}Yz_mZJcf$LRjg3{!S@BOREt;`qc4K5WXKOF(wJSM!$Yx!j zoAthR)vTtYWDu@Bwb71*!eY~+%UeR6ijQf<1(!lCPdxEJuY_D3`LPe!H)RD4Rsmfu zL0tCnO3Ic4_B>Ey?`ML#^Wgi+G;;PgmTl@=$ty^$RWE94g6ns!pYW7*#1AkU%4)?H zCxTmt8{Sb;7>Ek!;J||U>&9O!%$&6~`e1S&NYOtJ!>UCO^D|drBUITbIX}Q?(P5BL zfxvWSUhpL@mrF@@pv}lO2{6ps)~TTtF|9gvka7tf>C1C}&1A;Zf^mAYltv!q!`YzX zR!Jpo3NRO|B?sSl(Ky+)hN_0|-Y^AsJ3Jgz|zz)#Vix5eYEsV!E!~_dJjbPSd)xi zM2S_1oY|}HxRHxiFU$y_0DK(!2lO#jg2Dm@UPkx#pI*AvC7y(Z=3i}(qqC0_T~bKm-H^QRWFyzJ02}mKL=zEIBSZ{4bMDFb_Jo$ zb0nhJ%@LkZXDeW-g46IW8##*Mq3*{DKwpW~K3-SNcDHa>UWi5<3@a*p(YWcU8}P5a+ibc#)jcPZbErllQ>BsaKtjE zy6`Dx8S?`~p7}0{@Ah7vW%YABwcJE%q9^}ZR1JV0*9AjX0)?L%4taCa%R1jXG4M`K z2P2$^B}qN2`Zf(Lmg&4CH1`Nqo2liI_0>$0MCfe2rUY}N={Uai6zaSeZfR)=m~L$w zC0JPI zmb5t@Hiey>?}c-VRvt_BpT_&kqcx zHfCmKI?zhG*4iCkbyWK^k;qlJWgllgdpqpwgFk74Yww7!8$Jg}F{4m%mK$FOi^kFp zz82lK=nNvnoqFH&Dj|Z19ZE|}gPQx?%iDG(cEUEi*LB2V*YpKZOsGD#Xj@?IDwMNT z7%B8Lr0Z)S@<-#AZjGlIk%FV7yFKq5`^7D>HYqe0fC|saa(8fp5pc~4U&o`rBr2N( z(r)NdKxTF(#Aar?i?adjl%}E@*#!>k2QO^-Z9apylxZe{k2BMW(DAL%_(jT-ouZbb zU8;oKBH}p(qQw_d-XBhzIs?dQTY3;L(03!FkNAz4MzbW)0@^yn$UNkq9zrlwb z46u>GWC99!p*<>AGz(u2-rVOM#}qW8!`{iiCdi7~a%7)v$axT}y;re)cVS^6r-zioJl)F1 z_Clh)P7UXCkn;9S*QGWujAh$unOf~iU`@)hI@dxS@p2dWBjSr=eeBayU=K6&Tjf5I zaHk1oN84&jOzrQW8++XRn_rzSa;m_jN5?DmIeA6Uaw^P*7~An#_193d(9F$UCohL* z9s3b1`DwiZdm`NtA94ps#zo!oHC=reUfy*hJAdsE;#!kqfR)C_k-s+hzj**7d>bNn4&|L8Z!a+Z3+1%J&Xe!2%*#7$%@8 zz;8Xo2A)JLPNsF1P6InaHmOhyhqPj#Xd$^d<{a2D{OzmB4ks&6VZaJXRE_t3pB?W> z`l-3OIe7rR(V=@|n6_bpNZj$nh5tn|n9(Epbw%N;vXISd-am#_j?m2+;(*!=_$p1R@VE+nnrpP_5yY2f#0fRaYZ#X9-C}zvK_EU&v4$d ze1T2Aw_>mAPRI7Rsy}%3?z6H1m{YL?NoPl$>gewF%LryqZz7qHfGAF~2m`Q?g>vOw z@5wV|15-L3h8mUPWJ&GH01j}jXZdG6|FH*NtTXils`9(Frqn{kawa?NV(7m%%e*w~}u;Ks! literal 0 HcmV?d00001 diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_True/00000.png b/tests/ragger/snapshots/stax/domain_name_verbose_True/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..a23d9177c3caeaee251141b056d94ed980f4bb5a GIT binary patch literal 8435 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 OK5L6x=JnUSlm825`x|rs literal 0 HcmV?d00001 diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_True/00001.png b/tests/ragger/snapshots/stax/domain_name_verbose_True/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..ad8f077559185ed6d5ed737c4a342b719ca39a08 GIT binary patch literal 14741 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 literal 0 HcmV?d00001 diff --git a/tests/ragger/snapshots/stax/domain_name_verbose_True/00002.png b/tests/ragger/snapshots/stax/domain_name_verbose_True/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..e64dacc0fa17a23f11fcaf4746b5bfac9dc56b93 GIT binary patch literal 7822 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�lMY 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 literal 0 HcmV?d00001 diff --git a/tests/ragger/snapshots/stax/domain_name_wrong_addr/00000.png b/tests/ragger/snapshots/stax/domain_name_wrong_addr/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..a23d9177c3caeaee251141b056d94ed980f4bb5a GIT binary patch literal 8435 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 OK5L6x=JnUSlm825`x|rs literal 0 HcmV?d00001 diff --git a/tests/ragger/snapshots/stax/domain_name_wrong_addr/00001.png b/tests/ragger/snapshots/stax/domain_name_wrong_addr/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..3e505d39daec60dd7f66f7b9c7e3c7e8ce937f39 GIT binary patch literal 15550 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 Hr&@6SYv%)Dpx*fk`X6sWp?+ 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 literal 0 HcmV?d00001 From d1d5685198bd2f105f0c440081f74e821485feb7 Mon Sep 17 00:00:00 2001 From: Alexandre Paillier Date: Tue, 16 May 2023 11:24:58 +0200 Subject: [PATCH 25/25] Enabled CI for Stax --- .github/workflows/ci-workflow.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 3e15b79..4c9118a 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -171,7 +171,6 @@ jobs: with: upload_app_binaries_artifact: "ragger_elfs" flags: "DEBUG=1 CAL_CI_KEY=1 DOMAIN_NAME_TEST_KEY=1" - run_for_devices: '["nanos", "nanox", "nanosp"]' jobs-ragger-tests: name: Run Ragger tests @@ -180,4 +179,3 @@ jobs: with: download_app_binaries_artifact: "ragger_elfs" test_dir: tests/ragger - run_for_devices: '["nanos", "nanox", "nanosp"]'