diff --git a/Makefile b/Makefile new file mode 100755 index 0000000..699afb8 --- /dev/null +++ b/Makefile @@ -0,0 +1,205 @@ +#******************************************************************************* +# Ledger Blue +# (c) 2016 Ledger +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +#******************************************************************************* + +#extract TARGET_ID from the SDK to allow for makefile choices +TARGET_ID := $(shell cat $(BOLOS_SDK)/include/bolos_target.h | grep 0x | cut -f3 -d' ') +$(info TARGET_ID=$(TARGET_ID)) +APPNAME = Ethereum +APP_LOAD_PARAMS=--appFlags 0x40 --path "44'/60'" --path "44'/61'" --curve secp256k1 + +APPVERSION_M=1 +APPVERSION_N=0 +APPVERSION_P=5 +APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) + +#prepare hsm generation +ifeq ($(TARGET_ID),0x31000002) +ICONNAME=app_ethereum.gif +LOADFLAGS = --params --appVersion $(APPVERSION) +else +ICONNAME=icon.gif +endif + + +################ +# Default rule # +################ + +all: default + +# consider every intermediate target as final to avoid deleting intermediate files +.SECONDARY: + +# disable builtin rules that overload the build process (and the debug log !!) +.SUFFIXES: +MAKEFLAGS += -r + +SHELL = /bin/bash +#.ONESHELL: + + +############ +# Platform # +############ +PROG := token-genericwallet + +CONFIG_PRODUCTIONS := bin/$(PROG) + +GLYPH_FILES := $(addprefix glyphs/,$(sort $(notdir $(shell find glyphs/)))) +GLYPH_DESTC := src_common/glyphs.c +GLYPH_DESTH := src_common/glyphs.h +$(GLYPH_DESTC) $(GLYPH_DESTH): $(GLYPH_FILES) $(BOLOS_SDK)/icon.py + -rm $@ + if [ ! -z "$(GLYPH_FILES)" ] ; then for gif in $(GLYPH_FILES) ; do python $(BOLOS_SDK)/icon.py $$gif glyphcheader ; done > $(GLYPH_DESTH) ; fi + if [ ! -z "$(GLYPH_FILES)" ] ; then for gif in $(GLYPH_FILES) ; do python $(BOLOS_SDK)/icon.py $$gif glyphcfile ; done > $(GLYPH_DESTC) ; fi + +SOURCE_PATH := src_genericwallet $(BOLOS_SDK)/src $(dir $(shell find $(BOLOS_SDK)/lib_stusb* | grep "\.c$$")) src_common +SOURCE_FILES := $(foreach path, $(SOURCE_PATH),$(shell find $(path) | grep "\.c$$") ) $(GLYPH_DESTC) +INCLUDES_PATH := $(dir $(shell find $(BOLOS_SDK)/lib_stusb* | grep "\.h$$")) include src_genericwallet $(BOLOS_SDK)/include $(BOLOS_SDK)/include/arm src_common + +### platform definitions +DEFINES := ST31 gcc __IO=volatile + +DEFINES += OS_IO_SEPROXYHAL IO_SEPROXYHAL_BUFFER_SIZE_B=128 +DEFINES += HAVE_BAGL HAVE_SPRINTF +#DEFINES += HAVE_PRINTF PRINTF=screen_printf +DEFINES += PRINTF\(...\)= +DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=6 IO_HID_EP_LENGTH=64 HAVE_USB_APDU +DEFINES += LEDGER_MAJOR_VERSION=$(APPVERSION_M) LEDGER_MINOR_VERSION=$(APPVERSION_N) LEDGER_PATCH_VERSION=$(APPVERSION_P) + + +# U2F +DEFINES += HAVE_U2F +DEFINES += USB_SEGMENT_SIZE=64 +DEFINES += BLE_SEGMENT_SIZE=32 #max MTU, min 20 +DEFINES += U2F_MAX_MESSAGE_SIZE=264 #257+5+2 +DEFINES += UNUSED\(x\)=\(void\)x + +############## +# Compiler # +############## +GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/ +CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin +CC := $(CLANGPATH)/clang + +CFLAGS := +CFLAGS += -gdwarf-2 -gstrict-dwarf +#CFLAGS += -O0 +#CFLAGS += -O0 -g3 +CFLAGS += -O3 -Os +CFLAGS += -mcpu=cortex-m0 -mthumb +CFLAGS += -fno-common -mtune=cortex-m0 -mlittle-endian +CFLAGS += -std=gnu99 -Werror=int-to-pointer-cast -Wall -Wextra #-save-temps +CFLAGS += -fdata-sections -ffunction-sections -funsigned-char -fshort-enums +CFLAGS += -mno-unaligned-access +CFLAGS += -Wno-unused-parameter -Wno-duplicate-decl-specifier + +CFLAGS += -fropi --target=armv6m-none-eabi +#CFLAGS += -finline-limit-0 -funsigned-bitfields + +AS := $(GCCPATH)/arm-none-eabi-gcc +AFLAGS += -ggdb2 -O3 -Os -mcpu=cortex-m0 -fno-common -mtune=cortex-m0 + +# NOT SUPPORTED BY STM3L152 CFLAGS += -fpack-struct +#-pg --coverage +LD := $(GCCPATH)/arm-none-eabi-gcc +LDFLAGS := +LDFLAGS += -gdwarf-2 -gstrict-dwarf +#LDFLAGS += -O0 -g3 +LDFLAGS += -O3 -Os +#LDFLAGS += -O0 +LDFLAGS += -Wall +LDFLAGS += -mcpu=cortex-m0 -mthumb +LDFLAGS += -fno-common -ffunction-sections -fdata-sections -fwhole-program -nostartfiles +LDFLAGS += -mno-unaligned-access +#LDFLAGS += -nodefaultlibs +#LDFLAGS += -nostdlib -nostdinc +LDFLAGS += -T$(BOLOS_SDK)/script.ld -Wl,--gc-sections -Wl,-Map,debug/$(PROG).map,--cref +LDLIBS += -Wl,--library-path -Wl,$(GCCPATH)/../lib/armv6-m/ +#LDLIBS += -Wl,--start-group +LDLIBS += -lm -lgcc -lc +#LDLIBS += -Wl,--end-group +# -mno-unaligned-access +#-pg --coverage + +### computed variables +VPATH := $(dir $(SOURCE_FILES)) +OBJECT_FILES := $(sort $(addprefix obj/, $(addsuffix .o, $(basename $(notdir $(SOURCE_FILES)))))) +DEPEND_FILES := $(sort $(addprefix dep/, $(addsuffix .d, $(basename $(notdir $(SOURCE_FILES)))))) + +ifeq ($(filter clean,$(MAKECMDGOALS)),) +-include $(DEPEND_FILES) +endif + +clean: + rm -fr obj bin debug dep $(GLYPH_DESTC) $(GLYPH_DESTH) + +prepare: $(GLYPH_DESTC) + @mkdir -p bin obj debug dep + +.SECONDEXPANSION: + +# default is not to display make commands +log = $(if $(strip $(VERBOSE)),$1,@$1) + +default: prepare bin/$(PROG) + + + +load: all + python -m ledgerblue.loadApp --targetId $(TARGET_ID) --fileName bin/$(PROG).hex --appName $(APPNAME) --icon `python $(BOLOS_SDK)/icon.py $(ICONNAME) hexbitmaponly` $(LOADFLAGS) $(APP_LOAD_PARAMS) + +delete: + python -m ledgerblue.deleteApp --targetId $(TARGET_ID) --appName $(APPNAME) + +bin/$(PROG): $(OBJECT_FILES) $(BOLOS_SDK)/script.ld + @echo "[LINK] $@" + $(call log,$(call link_cmdline,$(OBJECT_FILES) $(LDLIBS),$@)) + $(call log,$(GCCPATH)/arm-none-eabi-objcopy -O ihex -S bin/$(PROG) bin/$(PROG).hex) + $(call log,mv bin/$(PROG) bin/$(PROG).elf) + $(call log,cp bin/$(PROG).elf obj) + $(call log,$(GCCPATH)/arm-none-eabi-objdump -S -d bin/$(PROG).elf > debug/$(PROG).asm) + +dep/%.d: %.c Makefile.genericwallet + @echo "[DEP] $@" + @mkdir -p dep + $(call log,$(call dep_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@)) + +obj/%.o: %.c dep/%.d + @echo "[CC] $@" + $(call log,$(call cc_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@)) + +obj/%.o: %.s + @echo "[CC] $@" + $(call log,$(call as_cmdline,$(INCLUDES_PATH), $(DEFINES),$<,$@)) + + +### BEGIN GCC COMPILER RULES + +# link_cmdline(objects,dest) Macro that is used to format arguments for the linker +link_cmdline = $(LD) $(LDFLAGS) -o $(2) $(1) + +# dep_cmdline(include,defines,src($<),dest($@)) Macro that is used to format arguments for the dependency creator +dep_cmdline = $(CC) -M $(CFLAGS) $(addprefix -D,$(2)) $(addprefix -I,$(1)) $(3) | sed 's/\($*\)\.o[ :]*/obj\/\1.o: /g' | sed -e 's/[:\t ][^ ]\+\.c//g' > dep/$(basename $(notdir $(4))).d 2>/dev/null + +# cc_cmdline(include,defines,src,dest) Macro that is used to format arguments for the compiler +cc_cmdline = $(CC) -c $(CFLAGS) $(addprefix -D,$(2)) $(addprefix -I,$(1)) -o $(4) $(3) + +as_cmdline = $(AS) -c $(AFLAGS) $(addprefix -D,$(2)) $(addprefix -I,$(1)) -o $(4) $(3) + +### END GCC COMPILER RULES + diff --git a/Makefile.genericwallet b/Makefile.genericwallet index 8f4f47f..36ec2b7 100755 --- a/Makefile.genericwallet +++ b/Makefile.genericwallet @@ -23,7 +23,7 @@ APP_LOAD_PARAMS=--appFlags 0x40 --path "44'/60'" --path "44'/61'" --curve secp25 APPVERSION_M=1 APPVERSION_N=0 -APPVERSION_P=4 +APPVERSION_P=5 APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) #prepare hsm generation diff --git a/src_common/ethUtils.c b/src_common/ethUtils.c index 00c6639..5fadc96 100644 --- a/src_common/ethUtils.c +++ b/src_common/ethUtils.c @@ -250,7 +250,9 @@ bool adjustDecimals(char *src, uint32_t srcLength, char *target, while (offset < delta) { target[offset++] = src[sourceOffset++]; } - target[offset++] = '.'; + if (decimals != 0) { + target[offset++] = '.'; + } startOffset = offset; while (sourceOffset < srcLength) { target[offset++] = src[sourceOffset++]; diff --git a/src_genericwallet/main.c b/src_genericwallet/main.c index a6985a8..accbaaf 100644 --- a/src_genericwallet/main.c +++ b/src_genericwallet/main.c @@ -21,6 +21,7 @@ #include "ethUstream.h" #include "ethUtils.h" #include "uint256.h" +#include "tokens.h" #include "os_io_seproxyhal.h" #include "string.h" @@ -73,6 +74,14 @@ uint32_t set_result_get_publicKey(void); #define WEI_TO_ETHER 18 +static const uint8_t const TOKEN_TRANSFER_ID[] = {0xa9, 0x05, 0x9c, 0xbb}; +static const uint8_t const TICKER_ETH[] = "ETH "; +typedef struct tokenContext_t { + uint8_t data[4 + 32 + 32]; + uint32_t dataFieldPos; + bool provisioned; +} tokenContext_t; + typedef struct publicKeyContext_t { cx_ecfp_public_key_t publicKey; uint8_t address[41]; @@ -93,6 +102,7 @@ union { txContext_t txContext; txContent_t txContent; cx_sha3_t sha3; +tokenContext_t tokenContext; volatile uint8_t dataAllowed; volatile uint8_t fidoTransport; volatile char addressSummary[32]; @@ -663,7 +673,7 @@ const bagl_element_t ui_settings_nanos[] = { NULL}, //{{BAGL_ICON , 0x01, 3, 14, 7, 4, 0, 0, 0 //, 0xFFFFFF, 0x000000, 0, - //BAGL_GLYPH_ICON_UP }, NULL, 0, 0, 0, NULL, NULL, NULL }, + // BAGL_GLYPH_ICON_UP }, NULL, 0, 0, 0, NULL, NULL, NULL }, {{BAGL_ICON, 0x01, 118, 14, 7, 4, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_DOWN}, NULL, @@ -1033,10 +1043,10 @@ const bagl_element_t ui_address_blue[] = { NULL}, //{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0, - //BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, - //BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, - //0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF, - //io_seproxyhal_touch_exit, NULL, NULL}, + // BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, + // BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, + // 0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF, + // io_seproxyhal_touch_exit, NULL, NULL}, {{BAGL_LABELINE, 0x00, 30, 106, 320, 30, 0, 0, BAGL_FILL, 0x999999, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, @@ -1280,10 +1290,10 @@ const bagl_element_t ui_details_blue[] = { NULL, NULL}, //{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0, - //BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, - //BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, - //0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF, - //io_seproxyhal_touch_exit, NULL, NULL}, + // BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, + // BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, + // 0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF, + // io_seproxyhal_touch_exit, NULL, NULL}, {{BAGL_LABELINE, 0x00, 30, 106, 320, 30, 0, 0, BAGL_FILL, 0x999999, COLOR_BG_1, BAGL_FONT_OPEN_SANS_SEMIBOLD_8_11PX, 0}, @@ -1518,10 +1528,10 @@ const bagl_element_t ui_approval_blue[] = { NULL}, //{{BAGL_RECTANGLE | BAGL_FLAG_TOUCHABLE, 0x00, 264, 19, 56, 44, 0, 0, - //BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, - //BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, - //0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF, - //io_seproxyhal_touch_exit, NULL, NULL}, + // BAGL_FILL, COLOR_APP, COLOR_APP_LIGHT, + // BAGL_FONT_SYMBOLS_0|BAGL_FONT_ALIGNMENT_CENTER|BAGL_FONT_ALIGNMENT_MIDDLE, + // 0 }, " " /*BAGL_FONT_SYMBOLS_0_DASHBOARD*/, 0, COLOR_APP, 0xFFFFFF, + // io_seproxyhal_touch_exit, NULL, NULL}, // BADGE_TRANSACTION.GIF {{BAGL_ICON, 0x00, 30, 98, 50, 50, 0, 0, BAGL_FILL, 0, COLOR_BG_1, 0, 0}, @@ -1738,9 +1748,10 @@ const bagl_element_t ui_approval_blue[] = { NULL}, //{{BAGL_LABELINE , 0x05, 130, 343, 160, 30, 0, 0, - //BAGL_FILL, 0x666666, COLOR_BG_1, - //BAGL_FONT_OPEN_SANS_REGULAR_10_13PX|BAGL_FONT_ALIGNMENT_RIGHT, 0 }, "Not - //present", 0, 0, 0, NULL, NULL, NULL}, + // BAGL_FILL, 0x666666, COLOR_BG_1, + // BAGL_FONT_OPEN_SANS_REGULAR_10_13PX|BAGL_FONT_ALIGNMENT_RIGHT, 0 }, + // "Not + // present", 0, 0, 0, NULL, NULL, NULL}, {{BAGL_LABELINE, 0x06, 133, 343, 140, 30, 0, 0, BAGL_FILL, 0x666666, COLOR_BG_1, BAGL_FONT_OPEN_SANS_REGULAR_10_13PX | BAGL_FONT_ALIGNMENT_RIGHT, 0}, @@ -2380,6 +2391,29 @@ bool customProcessor(txContext_t *context) { THROW(EXCEPTION); } else { dataPresent = true; + if (context->currentFieldLength == sizeof(tokenContext.data)) { + if (context->currentFieldPos < context->currentFieldLength) { + uint32_t copySize = (context->commandLength < + ((context->currentFieldLength - + context->currentFieldPos)) + ? context->commandLength + : context->currentFieldLength - + context->currentFieldPos); + copyTxData(context, + tokenContext.data + context->currentFieldPos, + copySize); + } + if (context->currentFieldPos == context->currentFieldLength) { + context->currentField++; + context->processingField = false; + // Initial check to see if the token content can be + // processed + tokenContext.provisioned = + (os_memcmp(tokenContext.data, TOKEN_TRANSFER_ID, 4) == + 0); + } + return true; + } } } return false; @@ -2464,6 +2498,9 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint256_t gasPrice, startGas, uint256; uint32_t i; uint8_t address[41]; + uint8_t decimals = WEI_TO_ETHER; + uint8_t *ticker = TICKER_ETH; + uint8_t tickerOffset = 0; if (p1 == P1_FIRST) { tmpCtx.transactionContext.pathLength = workBuffer[0]; if ((tmpCtx.transactionContext.pathLength < 0x01) || @@ -2481,6 +2518,7 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, dataLength -= 4; } dataPresent = false; + tokenContext.provisioned = false; initTx(&txContext, &sha3, &txContent, customProcessor, NULL); } else if (p1 != P1_MORE) { THROW(0x6B00); @@ -2504,10 +2542,28 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, PRINTF("Unexpected parser status\n"); THROW(0x6A80); } - // Store the hash cx_hash((cx_hash_t *)&sha3, CX_LAST, tmpCtx.transactionContext.hash, 0, tmpCtx.transactionContext.hash); + // If there is a token to process, check if it is well known + if (tokenContext.provisioned) { + for (i = 0; i < NUM_TOKENS; i++) { + tokenDefinition_t *currentToken = PIC(&TOKENS[i]); + if (os_memcmp(currentToken->address, txContent.destination, 20) == + 0) { + dataPresent = false; + decimals = currentToken->decimals; + ticker = currentToken->ticker; + txContent.destinationLength = 20; + os_memmove(txContent.destination, tokenContext.data + 4 + 12, + 20); + os_memmove(txContent.value.value, tokenContext.data + 4 + 32, + 32); + txContent.value.length = 32; + break; + } + } + } // Add address if (txContent.destinationLength != 0) { getEthAddressStringFromBinary(txContent.destination, address, &sha3); @@ -2527,7 +2583,7 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, sizeof(CONTRACT_ADDRESS)); strcpy(fullAddress, "Contract"); } - // Add amount in ethers + // Add amount in ethers or tokens convertUint256BE(txContent.value.value, txContent.value.length, &uint256); tostring256(&uint256, 10, (char *)(G_io_apdu_buffer + 100), 100); i = 0; @@ -2535,17 +2591,18 @@ void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, i++; } adjustDecimals((char *)(G_io_apdu_buffer + 100), i, - (char *)G_io_apdu_buffer, 100, WEI_TO_ETHER); + (char *)G_io_apdu_buffer, 100, decimals); i = 0; - fullAmount[0] = 'E'; - fullAmount[1] = 'T'; - fullAmount[2] = 'H'; - fullAmount[3] = ' '; + tickerOffset = 0; + while (ticker[tickerOffset]) { + fullAmount[tickerOffset] = ticker[tickerOffset]; + tickerOffset++; + } while (G_io_apdu_buffer[i]) { - fullAmount[4 + i] = G_io_apdu_buffer[i]; + fullAmount[tickerOffset + i] = G_io_apdu_buffer[i]; i++; } - fullAmount[4 + i] = '\0'; + fullAmount[tickerOffset + i] = '\0'; // Compute maximum fee convertUint256BE(txContent.gasprice.value, txContent.gasprice.length, &gasPrice); @@ -2632,7 +2689,6 @@ void handleApdu(volatile unsigned int *flags, volatile unsigned int *tx) { G_io_apdu_buffer[OFFSET_LC], flags, tx); break; - default: THROW(0x6D00); break; diff --git a/src_genericwallet/tokens.c b/src_genericwallet/tokens.c new file mode 100644 index 0000000..31c0bb2 --- /dev/null +++ b/src_genericwallet/tokens.c @@ -0,0 +1,102 @@ +/******************************************************************************* +* Ledger Blue +* (c) 2016 Ledger +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +********************************************************************************/ + +#include "tokens.h" + +const tokenDefinition_t const TOKENS[NUM_TOKENS] = { + {{0xAf, 0x30, 0xD2, 0xa7, 0xE9, 0x0d, 0x7D, 0xC3, 0x61, 0xc8, + 0xC4, 0x58, 0x5e, 0x9B, 0xB7, 0xD2, 0xF6, 0xf1, 0x5b, 0xc7}, + "1ST ", + 18}, + {{0xAc, 0x70, 0x9F, 0xcB, 0x44, 0xa4, 0x3c, 0x35, 0xF0, 0xDA, + 0x4e, 0x31, 0x63, 0xb1, 0x17, 0xA1, 0x7F, 0x37, 0x70, 0xf5}, + "ARC ", + 18}, + {{0x74, 0xc1, 0xe4, 0xb8, 0xca, 0xe5, 0x92, 0x69, 0xec, 0x1d, + 0x85, 0xd3, 0xd4, 0xf3, 0x24, 0x39, 0x60, 0x48, 0xf4, 0xac}, + "(^) ", + 0}, + {{0x1e, 0x79, 0x7C, 0xe9, 0x86, 0xC3, 0xCF, 0xF4, 0x47, 0x2F, + 0x7D, 0x38, 0xd5, 0xC4, 0xab, 0xa5, 0x5D, 0xfE, 0xFE, 0x40}, + "BCDN ", + 15}, + {{0xe4, 0xc9, 0x4d, 0x45, 0xf7, 0xae, 0xf7, 0x01, 0x8a, 0x5d, + 0x66, 0xf4, 0x4a, 0xf7, 0x80, 0xec, 0x60, 0x23, 0x37, 0x8e}, + "CCRB ", + 6}, + {{0xbb, 0x9b, 0xc2, 0x44, 0xd7, 0x98, 0x12, 0x3f, 0xde, 0x78, + 0x3f, 0xcc, 0x1c, 0x72, 0xd3, 0xbb, 0x8c, 0x18, 0x94, 0x13}, + "DAO ", + 16}, + {{0x5c, 0x40, 0xeF, 0x6f, 0x52, 0x7f, 0x4F, 0xbA, 0x68, 0x36, + 0x87, 0x74, 0xE6, 0x13, 0x0c, 0xE6, 0x51, 0x51, 0x23, 0xf2}, + "DAOe ", + 0}, + {{0xe0, 0xb7, 0x92, 0x7c, 0x4a, 0xf2, 0x37, 0x65, 0xcb, 0x51, + 0x31, 0x4a, 0x0e, 0x05, 0x21, 0xa9, 0x64, 0x5f, 0x0e, 0x2a}, + "DGD ", + 9}, + {{0x55, 0xb9, 0xa1, 0x1c, 0x2e, 0x83, 0x51, 0xb4, 0xff, 0xc7, + 0xb1, 0x15, 0x61, 0x14, 0x8b, 0xfa, 0xc9, 0x97, 0x78, 0x55}, + "DGX1 ", + 9}, + {{0xa7, 0x44, 0x76, 0x44, 0x31, 0x19, 0xA9, 0x42, 0xdE, 0x49, + 0x85, 0x90, 0xFe, 0x1f, 0x24, 0x54, 0xd7, 0xD4, 0xaC, 0x0d}, + "GNT ", + 18}, + {{0x14, 0xF3, 0x7B, 0x57, 0x42, 0x42, 0xD3, 0x66, 0x55, 0x8d, + 0xB6, 0x1f, 0x33, 0x35, 0x28, 0x9a, 0x50, 0x35, 0xc5, 0x06}, + "HKG ", + 3}, + {{0x88, 0x86, 0x66, 0xCA, 0x69, 0xE0, 0xf1, 0x78, 0xDE, 0xD6, + 0xD7, 0x5b, 0x57, 0x26, 0xCe, 0xe9, 0x9A, 0x87, 0xD6, 0x98}, + "ICN ", + 18}, + {{0xc6, 0x6e, 0xa8, 0x02, 0x71, 0x7b, 0xfb, 0x98, 0x33, 0x40, + 0x02, 0x64, 0xdd, 0x12, 0xc2, 0xbc, 0xea, 0xa3, 0x4a, 0x6d}, + "MKR ", + 18}, + {{0x45, 0xe4, 0x2D, 0x65, 0x9D, 0x9f, 0x94, 0x66, 0xcD, 0x5D, + 0xF6, 0x22, 0x50, 0x60, 0x33, 0x14, 0x5a, 0x9b, 0x89, 0xBc}, + "NXM ", + 3}, + {{0xD8, 0x91, 0x2C, 0x10, 0x68, 0x1D, 0x8B, 0x21, 0xFd, 0x37, + 0x42, 0x24, 0x4f, 0x44, 0x65, 0x8d, 0xBA, 0x12, 0x26, 0x4E}, + "PLU ", + 18}, + {{0x48, 0xc8, 0x0F, 0x1f, 0x4D, 0x53, 0xD5, 0x95, 0x1e, 0x5D, + 0x54, 0x38, 0xB5, 0x4C, 0xba, 0x84, 0xf2, 0x9F, 0x32, 0xa5}, + "REP ", + 18}, + {{0xae, 0xc2, 0xe8, 0x7e, 0x0a, 0x23, 0x52, 0x66, 0xd9, 0xc5, + 0xad, 0xc9, 0xde, 0xb4, 0xb2, 0xe2, 0x9b, 0x54, 0xd0, 0x09}, + "SNGL ", + 0}, + {{0x89, 0x20, 0x5A, 0x3A, 0x3b, 0x2A, 0x69, 0xDe, 0x6D, 0xbf, + 0x7f, 0x01, 0xED, 0x13, 0xB2, 0x10, 0x8B, 0x2c, 0x43, 0xe7}, + "o> ", + 0}, + {{0x5c, 0x54, 0x3e, 0x7A, 0xE0, 0xA1, 0x10, 0x4f, 0x78, 0x40, + 0x6C, 0x34, 0x0E, 0x9C, 0x64, 0xFD, 0x9f, 0xCE, 0x51, 0x70}, + "VSL ", + 18}, + {{0x4D, 0xF8, 0x12, 0xF6, 0x06, 0x4d, 0xef, 0x1e, 0x5e, 0x02, + 0x9f, 0x1c, 0xa8, 0x58, 0x77, 0x7C, 0xC9, 0x8D, 0x2D, 0x81}, + "XAUR ", + 8}, + +}; diff --git a/src_genericwallet/tokens.h b/src_genericwallet/tokens.h new file mode 100644 index 0000000..f8df01c --- /dev/null +++ b/src_genericwallet/tokens.h @@ -0,0 +1,28 @@ +/******************************************************************************* +* Ledger Blue +* (c) 2016 Ledger +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +********************************************************************************/ + +#include "os.h" + +typedef struct tokenDefinition_t { + uint8_t address[20]; + uint8_t ticker[6]; + uint8_t decimals; +} tokenDefinition_t; + +#define NUM_TOKENS 20 + +extern tokenDefinition_t const TOKENS[NUM_TOKENS];