Merge pull request #183 from LedgerHQ/bigger_chainid
Improve display for big chainIDs
6
.github/workflows/ci-workflow.yml
vendored
@@ -124,13 +124,17 @@ jobs:
|
||||
- name: Build/Install build js deps
|
||||
run: |
|
||||
cd tests && yarn install
|
||||
- name: Create tmp folder for artifacts
|
||||
run: |
|
||||
mkdir tests/elfs
|
||||
- name: Download app binaries
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: tests/elfs
|
||||
- name: Gather elfs
|
||||
run: |
|
||||
cp `find . -name "*.elf"` ./tests/elfs
|
||||
cd tests/elfs
|
||||
cp `find . -name "*.elf"` .
|
||||
- name: Run zemu tests
|
||||
run: |
|
||||
cd tests && yarn test
|
||||
|
||||
3
.gitignore
vendored
@@ -14,6 +14,7 @@ obj/
|
||||
tests/node_modules
|
||||
tests/lib
|
||||
tests/yarn-error.log
|
||||
|
||||
tests/elfs/*
|
||||
tests/snapshots/tmp/*
|
||||
|
||||
.vscode
|
||||
|
||||
15
CHANGELOG.md
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [1.9.3](https://github.com/ledgerhq/app-ethereum/compare/1.9.2...1.9.3) - 2021-9-03
|
||||
|
||||
### Added
|
||||
|
||||
- Added better display for bigger chainIDs.
|
||||
- Added support for Songbird.
|
||||
- Added support for Celo.
|
||||
|
||||
### Changed
|
||||
|
||||
- Small refactor of `getEthDisplayableAddress` helper
|
||||
- Improve Zemu tests to get parallelization
|
||||
- Increased plugin interface to version 2
|
||||
- Remove support for Theta and Flare
|
||||
|
||||
## [1.9.2](https://github.com/ledgerhq/app-ethereum/compare/1.9.0...1.9.2) - 2021-8-11
|
||||
|
||||
### Added
|
||||
|
||||
14
Makefile
@@ -30,7 +30,7 @@ APP_LOAD_PARAMS += --path "1517992542'/1101353413'"
|
||||
|
||||
APPVERSION_M=1
|
||||
APPVERSION_N=9
|
||||
APPVERSION_P=2
|
||||
APPVERSION_P=3
|
||||
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
|
||||
APP_LOAD_FLAGS= --appFlags 0x240 --dep Ethereum:$(APPVERSION)
|
||||
|
||||
@@ -203,17 +203,17 @@ else ifeq ($(CHAIN),flare_coston)
|
||||
APP_LOAD_PARAMS += --path "44'/554'" --path "44'/60'"
|
||||
DEFINES += CHAINID_UPCASE=\"FLARE\" CHAINID_COINNAME=\"FLR\" CHAIN_KIND=CHAIN_KIND_FLARE CHAIN_ID=16
|
||||
APPNAME = "Flare Coston"
|
||||
else ifeq ($(CHAIN),theta)
|
||||
APP_LOAD_PARAMS += --path "44'/500'"
|
||||
DEFINES += CHAINID_UPCASE=\"THETA\" CHAINID_COINNAME=\"THETA\" CHAIN_KIND=CHAIN_KIND_THETA CHAIN_ID=500
|
||||
APPNAME = "Theta"
|
||||
else ifeq ($(CHAIN),bsc)
|
||||
APP_LOAD_PARAMS += --path "44'/60'"
|
||||
DEFINES += CHAINID_UPCASE=\"BSC\" CHAINID_COINNAME=\"BNB\" CHAIN_KIND=CHAIN_KIND_BSC CHAIN_ID=56
|
||||
APPNAME = "Binance Smart Chain"
|
||||
else ifeq ($(CHAIN),songbird)
|
||||
APP_LOAD_PARAMS += --path "44'/554'" --path "44'/60'"
|
||||
DEFINES += CHAINID_UPCASE=\"SONGBIRD\" CHAINID_COINNAME=\"SGB\" CHAIN_KIND=CHAIN_KIND_SONGBIRD CHAIN_ID=19
|
||||
APPNAME = "Songbird"
|
||||
else
|
||||
ifeq ($(filter clean,$(MAKECMDGOALS)),)
|
||||
$(error Unsupported CHAIN - use ethereum, ropsten, ethereum_classic, expanse, poa, artis_sigma1, artis_tau1, rsk, rsk_testnet, ubiq, wanchain, kusd, musicoin, pirl, akroma, atheios, callisto, ethersocial, ellaism, ether1, ethergem, gochain, mix, reosc, hpb, tomochain, tobalaba, dexon, volta, ewc, webchain, thundercore, flare, flare_coston, theta)
|
||||
$(error Unsupported CHAIN - use ethereum, ropsten, ethereum_classic, expanse, poa, artis_sigma1, artis_tau1, rsk, rsk_testnet, ubiq, wanchain, kusd, musicoin, pirl, akroma, atheios, callisto, ethersocial, ellaism, ether1, ethergem, gochain, mix, reosc, hpb, tomochain, tobalaba, dexon, volta, ewc, webchain, thundercore, bsc, songbird)
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -384,4 +384,4 @@ include $(BOLOS_SDK)/Makefile.rules
|
||||
dep/%.d: %.c Makefile
|
||||
|
||||
listvariants:
|
||||
@echo VARIANTS CHAIN ethereum ropsten ethereum_classic expanse poa rsk rsk_testnet ubiq wanchain pirl akroma atheios callisto ethersocial ether1 gochain musicoin ethergem mix ellaism reosc hpb tomochain dexon volta ewc thundercore flare flare_coston theta bsc
|
||||
@echo VARIANTS CHAIN ethereum ropsten ethereum_classic expanse poa rsk rsk_testnet ubiq wanchain pirl akroma atheios callisto ethersocial ether1 gochain musicoin ethergem mix ellaism reosc hpb tomochain dexon volta ewc thundercore bsc songbird
|
||||
|
||||
@@ -17,8 +17,15 @@ Testing is done via the open-source framework [zemu](https://github.com/Zondax/z
|
||||
## Running tests
|
||||
|
||||
First [install yarn](https://classic.yarnpkg.com/en/docs/install/#debian-stable).
|
||||
Open `tests/build_local_test_elfs.sh` and add your BOLOS SDKs path to `NANOS_SDK` and `NANOX_SDK`.
|
||||
This helper script will build the applications required by the test suite and move them at the right place.
|
||||
```
|
||||
cd test
|
||||
./build_local_test_elfs.sh
|
||||
```
|
||||
Then you can install the project by simply running:
|
||||
```
|
||||
cd ..
|
||||
make test
|
||||
```
|
||||
This will run `make install_tests` and `make run_tests`
|
||||
|
||||
@@ -520,7 +520,7 @@ The following standard Status Words are returned for all APDUs - some specific S
|
||||
|===============================================================================================
|
||||
| *SW* | *Description*
|
||||
| 6501 | TransactionType not supported
|
||||
| 6502 | Output buffer too small for snprintf input
|
||||
| 6502 | Output buffer too small for chainId conversion
|
||||
| 6503 | Plugin error
|
||||
| 6504 | Failed to convert from int256
|
||||
| 6700 | Incorrect length
|
||||
|
||||
BIN
icons/nanos_app_songbird.gif
Normal file
|
After Width: | Height: | Size: 73 B |
BIN
icons/nanox_app_songbird.gif
Normal file
|
After Width: | Height: | Size: 57 B |
BIN
icons/songbird.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
@@ -54,13 +54,13 @@ typedef enum chain_kind_e {
|
||||
CHAIN_KIND_WEBCHAIN,
|
||||
CHAIN_KIND_THUNDERCORE,
|
||||
CHAIN_KIND_FLARE,
|
||||
CHAIN_KIND_THETA,
|
||||
CHAIN_KIND_BSC
|
||||
CHAIN_KIND_BSC,
|
||||
CHAIN_KIND_SONGBIRD
|
||||
} chain_kind_t;
|
||||
|
||||
typedef struct chain_config_s {
|
||||
char coinName[10]; // ticker
|
||||
uint32_t chainId;
|
||||
uint64_t chainId;
|
||||
chain_kind_t kind;
|
||||
} chain_config_t;
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ eth_plugin_result_t eth_plugin_call(int method, void *parameter) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT:
|
||||
PRINTF("-- PLUGIN INIT CONTRACT --\n");
|
||||
((ethPluginInitContract_t *) parameter)->interfaceVersion =
|
||||
ETH_PLUGIN_INTERFACE_VERSION_1;
|
||||
ETH_PLUGIN_INTERFACE_VERSION_LATEST;
|
||||
((ethPluginInitContract_t *) parameter)->result = ETH_PLUGIN_RESULT_UNAVAILABLE;
|
||||
((ethPluginInitContract_t *) parameter)->pluginSharedRW = &pluginRW;
|
||||
((ethPluginInitContract_t *) parameter)->pluginSharedRO = &pluginRO;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// Interface version. To be updated everytime we introduce breaking changes to the plugin interface.
|
||||
typedef enum {
|
||||
ETH_PLUGIN_INTERFACE_VERSION_1 = 1, // Version 1
|
||||
ETH_PLUGIN_INTERFACE_VERSION_LATEST = 2,
|
||||
} eth_plugin_interface_version_t;
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -61,7 +61,7 @@ int handle_check_address(check_address_parameters_t* params, chain_config_t* cha
|
||||
getEthAddressStringFromKey(&locals_union2.publicKey,
|
||||
locals_union1.address,
|
||||
&local_sha3,
|
||||
chain_config);
|
||||
chain_config->chainId);
|
||||
ZERO(locals_union2);
|
||||
|
||||
uint8_t offset_0x = 0;
|
||||
|
||||
20
src/main.c
@@ -250,12 +250,12 @@ tokenDefinition_t *getKnownToken(uint8_t *contractAddress) {
|
||||
case CHAIN_KIND_FLARE:
|
||||
numTokens = NUM_TOKENS_FLARE;
|
||||
break;
|
||||
case CHAIN_KIND_THETA:
|
||||
numTokens = NUM_TOKENS_THETA;
|
||||
break;
|
||||
case CHAIN_KIND_BSC:
|
||||
numTokens = NUM_TOKENS_BSC;
|
||||
break;
|
||||
case CHAIN_KIND_SONGBIRD:
|
||||
numTokens = NUM_TOKENS_SONGBIRD;
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < numTokens; i++) {
|
||||
switch (chainConfig->kind) {
|
||||
@@ -352,12 +352,12 @@ tokenDefinition_t *getKnownToken(uint8_t *contractAddress) {
|
||||
case CHAIN_KIND_FLARE:
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_FLARE[i]);
|
||||
break;
|
||||
case CHAIN_KIND_THETA:
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_THETA[i]);
|
||||
break;
|
||||
case CHAIN_KIND_BSC:
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_BSC[i]);
|
||||
break;
|
||||
case CHAIN_KIND_SONGBIRD:
|
||||
currentToken = (tokenDefinition_t *) PIC(&TOKENS_SONGBIRD[i]);
|
||||
break;
|
||||
}
|
||||
if (memcmp(currentToken->address, tmpContent.txContent.destination, ADDRESS_LENGTH) == 0) {
|
||||
return currentToken;
|
||||
@@ -876,22 +876,22 @@ __attribute__((section(".boot"))) int main(int arg0) {
|
||||
PRINTF("Hello from Eth-clone\n");
|
||||
check_api_level(CX_COMPAT_APILEVEL);
|
||||
// delegate to Ethereum app/lib
|
||||
libcall_params[0] = "Ethereum";
|
||||
libcall_params[0] = (unsigned int) "Ethereum";
|
||||
libcall_params[1] = 0x100;
|
||||
libcall_params[2] = RUN_APPLICATION;
|
||||
libcall_params[3] = &local_chainConfig;
|
||||
libcall_params[3] = (unsigned int) &local_chainConfig;
|
||||
libcall_params[4] = 0;
|
||||
if (arg0) {
|
||||
// call as a library
|
||||
libcall_params[2] = ((unsigned int *) arg0)[1];
|
||||
libcall_params[4] = ((unsigned int *) arg0)[3]; // library arguments
|
||||
os_lib_call(&libcall_params);
|
||||
os_lib_call((unsigned int *) &libcall_params);
|
||||
((unsigned int *) arg0)[0] = libcall_params[1];
|
||||
os_lib_end();
|
||||
} else {
|
||||
// launch coin application
|
||||
libcall_params[1] = 0x100; // use the Init call, as we won't exit
|
||||
os_lib_call(&libcall_params);
|
||||
os_lib_call((unsigned int *) &libcall_params);
|
||||
}
|
||||
}
|
||||
FINALLY {
|
||||
|
||||
@@ -162,14 +162,14 @@ typedef enum {
|
||||
#endif
|
||||
} contract_call_t;
|
||||
|
||||
#define NETWORK_NAME_MAX_SIZE 12
|
||||
#define NETWORK_STRING_MAX_SIZE 16
|
||||
|
||||
typedef struct txStringProperties_t {
|
||||
char fullAddress[43];
|
||||
char fullAmount[50];
|
||||
char maxFee[50];
|
||||
char nonce[8]; // 10M tx per account ought to be enough for everybody
|
||||
char network_name[NETWORK_NAME_MAX_SIZE];
|
||||
char network_name[NETWORK_STRING_MAX_SIZE];
|
||||
} txStringProperties_t;
|
||||
|
||||
#define SHARED_CTX_FIELD_1_SIZE 100
|
||||
|
||||
@@ -3853,10 +3853,6 @@ const tokenDefinition_t const TOKENS_ETHEREUM[NUM_TOKENS_ETHEREUM] = {
|
||||
0x91, 0x9a, 0xbc, 0x23, 0x5c, 0xa4, 0xfd, 0x7f, 0x72, 0xc1},
|
||||
"TGT ",
|
||||
1},
|
||||
{{0x38, 0x83, 0xf5, 0xe1, 0x81, 0xfc, 0xca, 0xf8, 0x41, 0x0f,
|
||||
0xa6, 0x1e, 0x12, 0xb5, 0x9b, 0xad, 0x96, 0x3f, 0xb6, 0x45},
|
||||
"THETA ",
|
||||
18},
|
||||
{{0x1c, 0xb3, 0x20, 0x9d, 0x45, 0xb2, 0xa6, 0x0b, 0x7f, 0xbc,
|
||||
0xa1, 0xcc, 0xdb, 0xf8, 0x7f, 0x67, 0x42, 0x37, 0xa4, 0xaa},
|
||||
"THR ",
|
||||
@@ -4564,8 +4560,8 @@ const tokenDefinition_t const TOKENS_THUNDERCORE[NUM_TOKENS_THUNDERCORE] = {};
|
||||
|
||||
const tokenDefinition_t const TOKENS_FLARE[NUM_TOKENS_FLARE] = {};
|
||||
|
||||
const tokenDefinition_t const TOKENS_THETA[NUM_TOKENS_THETA] = {};
|
||||
|
||||
const tokenDefinition_t const TOKENS_BSC[NUM_TOKENS_BSC] = {};
|
||||
|
||||
const tokenDefinition_t const TOKENS_SONGBIRD[NUM_TOKENS_SONGBIRD] = {};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -95,8 +95,8 @@ static const uint8_t LEDGER_SIGNATURE_PUBLIC_KEY[] = {
|
||||
#define NUM_TOKENS_WEBCHAIN 0
|
||||
#define NUM_TOKENS_THUNDERCORE 0
|
||||
#define NUM_TOKENS_FLARE 0
|
||||
#define NUM_TOKENS_THETA 0
|
||||
#define NUM_TOKENS_BSC 0
|
||||
#define NUM_TOKENS_SONGBIRD 0
|
||||
|
||||
extern tokenDefinition_t const TOKENS_AKROMA[NUM_TOKENS_AKROMA];
|
||||
extern tokenDefinition_t const TOKENS_ELLAISM[NUM_TOKENS_ELLAISM];
|
||||
@@ -129,8 +129,8 @@ extern tokenDefinition_t const TOKENS_ARTIS_TAU1[NUM_TOKENS_ARTIS_TAU1];
|
||||
extern tokenDefinition_t const TOKENS_WEBCHAIN[NUM_TOKENS_WEBCHAIN];
|
||||
extern tokenDefinition_t const TOKENS_THUNDERCORE[NUM_TOKENS_THUNDERCORE];
|
||||
extern tokenDefinition_t const TOKENS_FLARE[NUM_TOKENS_FLARE];
|
||||
extern tokenDefinition_t const TOKENS_THETA[NUM_TOKENS_THETA];
|
||||
extern tokenDefinition_t const TOKENS_BSC[NUM_TOKENS_BSC];
|
||||
extern tokenDefinition_t const TOKENS_SONGBIRD[NUM_TOKENS_SONGBIRD];
|
||||
|
||||
#endif /* HAVE_TOKENS_LIST */
|
||||
|
||||
|
||||
22
src/utils.c
@@ -54,19 +54,17 @@ int local_strchr(char *string, char ch) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t u32_from_BE(uint8_t *in, uint8_t size) {
|
||||
switch (size) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return in[0];
|
||||
case 2:
|
||||
return (in[0] << 8) | in[1];
|
||||
case 3:
|
||||
return (in[0] << 16) | (in[1] << 8) | in[2];
|
||||
default:
|
||||
return (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3];
|
||||
uint64_t u64_from_BE(uint8_t *in, uint8_t size) {
|
||||
uint8_t i = 0;
|
||||
uint64_t res = 0;
|
||||
|
||||
while (i < size && i < sizeof(res)) {
|
||||
res <<= 8;
|
||||
res |= in[i];
|
||||
i++;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool uint256_to_decimal(const uint8_t *value, size_t value_len, char *out, size_t out_len) {
|
||||
|
||||
@@ -28,7 +28,7 @@ void convertUint256BE(uint8_t* data, uint32_t length, uint256_t* target);
|
||||
|
||||
int local_strchr(char* string, char ch);
|
||||
|
||||
uint32_t u32_from_BE(uint8_t* in, uint8_t size);
|
||||
uint64_t u64_from_BE(uint8_t* in, uint8_t size);
|
||||
|
||||
bool uint256_to_decimal(const uint8_t* value, size_t value_len, char* out, size_t out_len);
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ typedef struct txContent_t {
|
||||
txInt256_t chainID;
|
||||
uint8_t destination[ADDRESS_LENGTH];
|
||||
uint8_t destinationLength;
|
||||
uint8_t v[4];
|
||||
uint8_t v[8];
|
||||
uint8_t vLength;
|
||||
bool dataPresent;
|
||||
} txContent_t;
|
||||
|
||||
@@ -126,17 +126,45 @@ void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey,
|
||||
char *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t *chain_config) {
|
||||
uint64_t chainId) {
|
||||
uint8_t hashAddress[INT256_LENGTH];
|
||||
cx_keccak_init(sha3Context, 256);
|
||||
cx_hash((cx_hash_t *) sha3Context, CX_LAST, publicKey->W + 1, 64, hashAddress, 32);
|
||||
getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context, chain_config);
|
||||
getEthAddressStringFromBinary(hashAddress + 12, out, sha3Context, chainId);
|
||||
}
|
||||
|
||||
void u64_to_string(uint64_t src, char *dst, uint8_t dst_size) {
|
||||
// Copy the numbers in ASCII format.
|
||||
uint8_t i = 0;
|
||||
do {
|
||||
// Checking `i + 1` to make sure we have enough space for '\0'.
|
||||
if (i + 1 >= dst_size) {
|
||||
THROW(0x6502);
|
||||
}
|
||||
dst[i] = src % 10 + '0';
|
||||
src /= 10;
|
||||
i++;
|
||||
} while (src);
|
||||
|
||||
// Null terminate string
|
||||
dst[i] = '\0';
|
||||
|
||||
// Revert the string
|
||||
i--;
|
||||
uint8_t j = 0;
|
||||
while (j < i) {
|
||||
char tmp = dst[i];
|
||||
dst[i] = dst[j];
|
||||
dst[j] = tmp;
|
||||
i--;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
void getEthAddressStringFromBinary(uint8_t *address,
|
||||
char *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t *chain_config) {
|
||||
uint64_t chainId) {
|
||||
// save some precious stack space
|
||||
union locals_union {
|
||||
uint8_t hashChecksum[INT256_LENGTH];
|
||||
@@ -146,18 +174,17 @@ void getEthAddressStringFromBinary(uint8_t *address,
|
||||
uint8_t i;
|
||||
bool eip1191 = false;
|
||||
uint32_t offset = 0;
|
||||
switch (chain_config->chainId) {
|
||||
switch (chainId) {
|
||||
case 30:
|
||||
case 31:
|
||||
eip1191 = true;
|
||||
break;
|
||||
}
|
||||
if (eip1191) {
|
||||
snprintf((char *) locals_union.tmp,
|
||||
sizeof(locals_union.tmp),
|
||||
"%d0x",
|
||||
chain_config->chainId);
|
||||
offset = strlen((char *) locals_union.tmp);
|
||||
u64_to_string(chainId, (char *) locals_union.tmp, sizeof(locals_union.tmp));
|
||||
offset = strnlen((char *) locals_union.tmp, sizeof(locals_union.tmp));
|
||||
strlcat((char *) locals_union.tmp + offset, "0x", sizeof(locals_union.tmp) - offset);
|
||||
offset = strnlen((char *) locals_union.tmp, sizeof(locals_union.tmp));
|
||||
}
|
||||
for (i = 0; i < 20; i++) {
|
||||
uint8_t digit = address[i];
|
||||
@@ -192,6 +219,24 @@ void getEthAddressStringFromBinary(uint8_t *address,
|
||||
out[40] = '\0';
|
||||
}
|
||||
|
||||
/* Fills the `out` buffer with the lowercase string representation of the pubkey passed in as binary
|
||||
format by `in`. (eg: uint8_t*:0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB ->
|
||||
char*:"0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB\0" )
|
||||
`sha3` context doesn't have have to be initialized prior to call.*/
|
||||
void getEthDisplayableAddress(uint8_t *in,
|
||||
char *out,
|
||||
size_t out_len,
|
||||
cx_sha3_t *sha3,
|
||||
uint64_t chainId) {
|
||||
if (out_len < 43) {
|
||||
strlcpy(out, "ERROR", out_len);
|
||||
return;
|
||||
}
|
||||
out[0] = '0';
|
||||
out[1] = 'x';
|
||||
getEthAddressStringFromBinary(in, out + 2, sha3, chainId);
|
||||
}
|
||||
|
||||
bool adjustDecimals(char *src,
|
||||
uint32_t srcLength,
|
||||
char *target,
|
||||
|
||||
@@ -42,12 +42,20 @@ void getEthAddressFromKey(cx_ecfp_public_key_t *publicKey, uint8_t *out, cx_sha3
|
||||
void getEthAddressStringFromKey(cx_ecfp_public_key_t *publicKey,
|
||||
char *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t *chain_config);
|
||||
uint64_t chainId);
|
||||
|
||||
void u64_to_string(uint64_t src, char *dst, uint8_t dst_size);
|
||||
|
||||
void getEthAddressStringFromBinary(uint8_t *address,
|
||||
char *out,
|
||||
cx_sha3_t *sha3Context,
|
||||
chain_config_t *chain_config);
|
||||
uint64_t chainId);
|
||||
|
||||
void getEthDisplayableAddress(uint8_t *in,
|
||||
char *out,
|
||||
size_t out_len,
|
||||
cx_sha3_t *sha3,
|
||||
uint64_t chainId);
|
||||
|
||||
bool adjustDecimals(char *src,
|
||||
uint32_t srcLength,
|
||||
|
||||
@@ -19,30 +19,33 @@ const network_info_t NETWORK_MAPPING[] = {
|
||||
{.chain_id = 100, .name = "xDai", .ticker = "xDAI "},
|
||||
{.chain_id = 137, .name = "Polygon", .ticker = "MATIC "},
|
||||
{.chain_id = 250, .name = "Fantom", .ticker = "FTM "},
|
||||
{.chain_id = 43114, .name = "Avalanche", .ticker = "AVAX "}};
|
||||
{.chain_id = 42220, .name = "Celo", .ticker = "CELO "},
|
||||
{.chain_id = 43114, .name = "Avalanche", .ticker = "AVAX "},
|
||||
{.chain_id = 44787, .name = "Celo Alfajores", .ticker = "aCELO "},
|
||||
{.chain_id = 62320, .name = "Celo Baklava", .ticker = "bCELO "},
|
||||
{.chain_id = 11297108109, .name = "Palm Network", .ticker = "PALM "}};
|
||||
|
||||
uint32_t get_chain_id(void) {
|
||||
uint32_t chain_id = 0;
|
||||
uint64_t get_chain_id(void) {
|
||||
uint64_t chain_id = 0;
|
||||
|
||||
switch (txContext.txType) {
|
||||
case LEGACY:
|
||||
chain_id = u32_from_BE(txContext.content->v, txContext.content->vLength);
|
||||
chain_id = u64_from_BE(txContext.content->v, txContext.content->vLength);
|
||||
break;
|
||||
case EIP2930:
|
||||
case EIP1559:
|
||||
chain_id = u32_from_BE(tmpContent.txContent.chainID.value,
|
||||
chain_id = u64_from_BE(tmpContent.txContent.chainID.value,
|
||||
tmpContent.txContent.chainID.length);
|
||||
break;
|
||||
default:
|
||||
PRINTF("Txtype `%d` not supported while generating chainID\n", txContext.txType);
|
||||
break;
|
||||
}
|
||||
PRINTF("ChainID: %d\n", chain_id);
|
||||
return chain_id;
|
||||
}
|
||||
|
||||
network_info_t *get_network(void) {
|
||||
uint32_t chain_id = get_chain_id();
|
||||
uint64_t chain_id = get_chain_id();
|
||||
for (uint8_t i = 0; i < sizeof(NETWORK_MAPPING) / sizeof(*NETWORK_MAPPING); i++) {
|
||||
if (NETWORK_MAPPING[i].chain_id == chain_id) {
|
||||
return (network_info_t *) PIC(&NETWORK_MAPPING[i]);
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
#include <stdint.h>
|
||||
#include "tokens.h"
|
||||
|
||||
#define NETWORK_STRING_MAX_SIZE 12
|
||||
#include "shared_context.h"
|
||||
|
||||
typedef struct network_info_s {
|
||||
const char name[NETWORK_STRING_MAX_SIZE];
|
||||
const char ticker[MAX_TICKER_LEN];
|
||||
uint32_t chain_id;
|
||||
uint64_t chain_id;
|
||||
} network_info_t;
|
||||
|
||||
// Returns the current chain id. Defaults to 0 if txType was not found.
|
||||
uint32_t get_chain_id(void);
|
||||
uint64_t get_chain_id(void);
|
||||
// Returns a pointer to the network struct, or NULL if there is none.
|
||||
network_info_t *get_network(void);
|
||||
// Returns a pointer to the network name, or NULL if there is none.
|
||||
|
||||
@@ -50,7 +50,7 @@ void handleGetPublicKey(uint8_t p1,
|
||||
getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey,
|
||||
tmpCtx.publicKeyContext.address,
|
||||
&global_sha3,
|
||||
chainConfig);
|
||||
chainConfig->chainId);
|
||||
#ifndef NO_CONSENT
|
||||
if (p1 == P1_NON_CONFIRM)
|
||||
#endif // NO_CONSENT
|
||||
|
||||
@@ -59,7 +59,7 @@ void handleSign(uint8_t p1,
|
||||
} else {
|
||||
txContext.txType = LEGACY;
|
||||
}
|
||||
PRINTF("TxType: %d\n", txContext.txType);
|
||||
PRINTF("TxType: %x\n", txContext.txType);
|
||||
} else if (p1 != P1_MORE) {
|
||||
THROW(0x6B00);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#endif
|
||||
#include "eth_plugin_handler.h"
|
||||
#include "network.h"
|
||||
#include "ethUtils.h"
|
||||
|
||||
#define ERR_SILENT_MODE_CHECK_FAILED 0x6001
|
||||
|
||||
@@ -261,16 +262,8 @@ void prepareNetworkDisplay() {
|
||||
char *name = get_network_name();
|
||||
if (name == NULL) {
|
||||
// No network name found so simply copy the chain ID as the network name.
|
||||
uint32_t chain_id = get_chain_id();
|
||||
uint8_t res = snprintf(strings.common.network_name,
|
||||
sizeof(strings.common.network_name),
|
||||
"%d",
|
||||
chain_id);
|
||||
if (res >= sizeof(strings.common.network_name)) {
|
||||
// If the return value is higher or equal to the size passed in as parameter, then
|
||||
// the output was truncated. Return the appropriate error code.
|
||||
THROW(0x6502);
|
||||
}
|
||||
uint64_t chain_id = get_chain_id();
|
||||
u64_to_string(chain_id, strings.common.network_name, sizeof(strings.common.network_name));
|
||||
} else {
|
||||
// Network name found, simply copy it.
|
||||
strlcpy(strings.common.network_name, name, sizeof(strings.common.network_name));
|
||||
@@ -308,7 +301,7 @@ void finalizeParsing(bool direct) {
|
||||
// Verify the chain
|
||||
if (chainConfig->chainId != ETHEREUM_MAINNET_CHAINID) {
|
||||
// TODO: Could we remove above check?
|
||||
uint32_t id = get_chain_id();
|
||||
uint64_t id = get_chain_id();
|
||||
|
||||
if (chainConfig->chainId != id) {
|
||||
PRINTF("Invalid chainID %u expected %u\n", id, chainConfig->chainId);
|
||||
@@ -422,12 +415,11 @@ void finalizeParsing(bool direct) {
|
||||
// Prepare destination address to display
|
||||
if (genericUI) {
|
||||
if (tmpContent.txContent.destinationLength != 0) {
|
||||
displayBuffer[0] = '0';
|
||||
displayBuffer[1] = 'x';
|
||||
getEthAddressStringFromBinary(tmpContent.txContent.destination,
|
||||
displayBuffer + 2,
|
||||
&global_sha3,
|
||||
chainConfig);
|
||||
getEthDisplayableAddress(tmpContent.txContent.destination,
|
||||
displayBuffer,
|
||||
sizeof(displayBuffer),
|
||||
&global_sha3,
|
||||
chainConfig->chainId);
|
||||
compareOrCopy(strings.common.fullAddress,
|
||||
sizeof(strings.common.fullAddress),
|
||||
displayBuffer,
|
||||
@@ -459,9 +451,11 @@ void finalizeParsing(bool direct) {
|
||||
|
||||
// Compute maximum fee
|
||||
prepareFeeDisplay();
|
||||
PRINTF("Fees displayed: %s\n", strings.common.maxFee);
|
||||
|
||||
// Prepare chainID field
|
||||
prepareNetworkDisplay();
|
||||
PRINTF("Network: %s\n", strings.common.network_name);
|
||||
|
||||
bool no_consent;
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ unsigned int io_seproxyhal_touch_tx_ok(__attribute__((unused)) const bagl_elemen
|
||||
uint8_t signature[100];
|
||||
cx_ecfp_private_key_t privateKey;
|
||||
uint32_t tx = 0;
|
||||
uint32_t v = u32_from_BE(tmpContent.txContent.v, tmpContent.txContent.vLength);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
os_perso_derive_node_bip32(CX_CURVE_256K1,
|
||||
tmpCtx.transactionContext.bip32Path,
|
||||
@@ -40,7 +39,12 @@ unsigned int io_seproxyhal_touch_tx_ok(__attribute__((unused)) const bagl_elemen
|
||||
G_io_apdu_buffer[0] = 27;
|
||||
} else {
|
||||
// New API
|
||||
// Note that this is wrong for a large v, but the client can always recover
|
||||
// Note that this is wrong for a large v, but ledgerjs will recover.
|
||||
|
||||
// Taking only the 4 highest bytes to not introduce breaking changes. In the future,
|
||||
// this should be updated.
|
||||
uint32_t v = (uint32_t) u64_from_BE(tmpContent.txContent.v,
|
||||
MIN(4, tmpContent.txContent.vLength));
|
||||
G_io_apdu_buffer[0] = (v * 2) + 35;
|
||||
}
|
||||
if (info & CX_ECCINFO_PARITY_ODD) {
|
||||
|
||||
@@ -222,9 +222,8 @@ void ux_approve_tx(bool fromPlugin) {
|
||||
ux_approval_tx_flow[step++] = &ux_approval_nonce_step;
|
||||
}
|
||||
|
||||
uint32_t chain_id = get_chain_id();
|
||||
uint64_t chain_id = get_chain_id();
|
||||
if (chainConfig->chainId == ETHEREUM_MAINNET_CHAINID && chain_id != chainConfig->chainId) {
|
||||
// TODO: do we need the `&&` above?
|
||||
ux_approval_tx_flow[step++] = &ux_approval_network_step;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,16 +13,6 @@ void stark_sign_display_master_account() {
|
||||
dataContext.starkContext.transferDestination);
|
||||
}
|
||||
|
||||
void stark_sign_display_condition_address() {
|
||||
strings.tmp.tmp[0] = '0';
|
||||
strings.tmp.tmp[1] = 'x';
|
||||
getEthAddressStringFromBinary(dataContext.starkContext.conditionAddress,
|
||||
strings.tmp.tmp + 2,
|
||||
&global_sha3,
|
||||
chainConfig);
|
||||
strings.tmp.tmp[42] = '\0';
|
||||
}
|
||||
|
||||
void stark_sign_display_condition_fact() {
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.fact);
|
||||
}
|
||||
@@ -189,7 +179,11 @@ UX_STEP_NOCB_INIT(
|
||||
UX_STEP_NOCB_INIT(
|
||||
ux_stark_conditional_transfer_8_step,
|
||||
bnnn_paging,
|
||||
stark_sign_display_condition_address(),
|
||||
getEthDisplayableAddress(dataContext.starkContext.conditionAddress,
|
||||
strings.tmp.tmp,
|
||||
sizeof(strings.tmp.tmp),
|
||||
&global_sha3,
|
||||
chainConfig->chainId),
|
||||
{
|
||||
.title = "Cond. Address",
|
||||
.text = strings.tmp.tmp
|
||||
|
||||
@@ -212,12 +212,11 @@ void erc20_plugin_call(int message, void *parameters) {
|
||||
strlcpy(msg->msg, context->contract_name, msg->msgLength);
|
||||
} else {
|
||||
strlcpy(msg->title, "Address", msg->titleLength);
|
||||
msg->msg[0] = '0';
|
||||
msg->msg[1] = 'x';
|
||||
getEthAddressStringFromBinary(context->destinationAddress,
|
||||
msg->msg + 2,
|
||||
msg->pluginSharedRW->sha3,
|
||||
chainConfig);
|
||||
getEthDisplayableAddress(context->destinationAddress,
|
||||
msg->msg,
|
||||
msg->msgLength,
|
||||
msg->pluginSharedRW->sha3,
|
||||
chainConfig->chainId);
|
||||
}
|
||||
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
#include "ethUtils.h"
|
||||
#include "utils.h"
|
||||
|
||||
void starkware_print_stark_key(uint8_t *starkKey, char *destination);
|
||||
void starkware_print_eth_address(uint8_t *address, char *destination);
|
||||
|
||||
typedef struct erc721_parameters_t {
|
||||
uint8_t selectorIndex;
|
||||
uint8_t address[ADDRESS_LENGTH];
|
||||
@@ -119,19 +116,27 @@ void erc721_plugin_call(int message, void *parameters) {
|
||||
switch (msg->screenIndex) {
|
||||
case 0:
|
||||
strlcpy(msg->title, "Contract Name", msg->titleLength);
|
||||
starkware_print_eth_address(tmpContent.txContent.destination, msg->msg);
|
||||
getEthDisplayableAddress(tmpContent.txContent.destination,
|
||||
msg->msg,
|
||||
msg->msgLength,
|
||||
&global_sha3,
|
||||
chainConfig->chainId);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
strlcpy(msg->title, "NFT Contract", msg->titleLength);
|
||||
starkware_print_eth_address(context->address, msg->msg);
|
||||
getEthDisplayableAddress(context->address,
|
||||
msg->msg,
|
||||
msg->msgLength,
|
||||
&global_sha3,
|
||||
chainConfig->chainId);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
strlcpy(msg->title, "TokenID", msg->titleLength);
|
||||
starkware_print_stark_key(context->tokenId, msg->msg);
|
||||
snprintf(msg->msg, 70, "0x%.*H", 32, context->tokenId);
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
|
||||
|
||||
@@ -32,19 +32,6 @@ typedef struct eth2_deposit_parameters_t {
|
||||
char deposit_address[ETH2_DEPOSIT_PUBKEY_LENGTH];
|
||||
} eth2_deposit_parameters_t;
|
||||
|
||||
// Fills the `out` buffer with the lowercase string representation of the pubkey passed in as binary
|
||||
// format by `in`. Does not check the size, so expects `out` to be big enough to hold the string
|
||||
// representation. Returns the length of string (counting the null terminating character).
|
||||
static int getEthDisplayableAddress(char *out, uint8_t *in, cx_sha3_t *sha3) {
|
||||
out[0] = '0';
|
||||
out[1] = 'x';
|
||||
getEthAddressStringFromBinary(in, out + 2, sha3, chainConfig);
|
||||
|
||||
uint8_t destinationLen = strlen(out) + 1; // Adding one to account for \0.
|
||||
|
||||
return destinationLen;
|
||||
}
|
||||
|
||||
void eth2_plugin_call(int message, void *parameters) {
|
||||
switch (message) {
|
||||
case ETH_PLUGIN_INIT_CONTRACT: {
|
||||
@@ -130,9 +117,11 @@ void eth2_plugin_call(int message, void *parameters) {
|
||||
|
||||
// Use a temporary buffer to store the string representation.
|
||||
char tmp[ETH2_DEPOSIT_PUBKEY_LENGTH];
|
||||
getEthDisplayableAddress(tmp,
|
||||
(uint8_t *) context->deposit_address,
|
||||
msg->pluginSharedRW->sha3);
|
||||
getEthDisplayableAddress((uint8_t *) context->deposit_address,
|
||||
tmp,
|
||||
sizeof(tmp),
|
||||
msg->pluginSharedRW->sha3,
|
||||
chainConfig->chainId);
|
||||
|
||||
// Copy back the string to the global variable.
|
||||
strlcpy(context->deposit_address, tmp, ETH2_DEPOSIT_PUBKEY_LENGTH);
|
||||
|
||||
@@ -279,18 +279,6 @@ void starkware_print_stark_key(uint8_t *starkKey, char *destination) {
|
||||
snprintf(destination, 70, "0x%.*H", 32, starkKey);
|
||||
}
|
||||
|
||||
// TODO : rewrite as independant code
|
||||
void starkware_print_eth_address(uint8_t *address, char *destination, size_t destinationLength) {
|
||||
if (destinationLength < 43) {
|
||||
strlcpy(destination, "ERROR", destinationLength);
|
||||
return;
|
||||
}
|
||||
destination[0] = '0';
|
||||
destination[1] = 'x';
|
||||
getEthAddressStringFromBinary(address, destination + 2, &global_sha3, chainConfig);
|
||||
destination[42] = '\0';
|
||||
}
|
||||
|
||||
// TODO : rewrite as independant code
|
||||
void starkware_print_amount(uint8_t *amountData,
|
||||
char *destination,
|
||||
@@ -348,7 +336,11 @@ void starkware_print_asset_contract(char *destination, size_t destinationLength)
|
||||
if (dataContext.tokenContext.quantumIndex != MAX_TOKEN) {
|
||||
tokenDefinition_t *token =
|
||||
&tmpCtx.transactionContext.tokens[dataContext.tokenContext.quantumIndex];
|
||||
starkware_print_eth_address(token->address, destination, destinationLength);
|
||||
getEthDisplayableAddress(token->address,
|
||||
destination,
|
||||
destinationLength,
|
||||
&global_sha3,
|
||||
chainConfig->chainId);
|
||||
} else {
|
||||
strlcpy(destination, "UNKNOWN", destinationLength);
|
||||
}
|
||||
@@ -372,7 +364,7 @@ void starkware_get_source_address(char *destination) {
|
||||
io_seproxyhal_io_heartbeat();
|
||||
destination[0] = '0';
|
||||
destination[1] = 'x';
|
||||
getEthAddressStringFromKey(&publicKey, destination + 2, &global_sha3, chainConfig);
|
||||
getEthAddressStringFromKey(&publicKey, destination + 2, &global_sha3, chainConfig->chainId);
|
||||
destination[42] = '\0';
|
||||
}
|
||||
|
||||
@@ -708,9 +700,11 @@ void starkware_plugin_call(int message, void *parameters) {
|
||||
if (is_deversify_contract(tmpContent.txContent.destination)) {
|
||||
strlcpy(msg->msg, "DeversiFi", msg->msgLength);
|
||||
} else {
|
||||
starkware_print_eth_address(tmpContent.txContent.destination,
|
||||
msg->msg,
|
||||
msg->msgLength);
|
||||
getEthDisplayableAddress(tmpContent.txContent.destination,
|
||||
msg->msg,
|
||||
msg->msgLength,
|
||||
&global_sha3,
|
||||
chainConfig->chainId);
|
||||
}
|
||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||
break;
|
||||
@@ -720,7 +714,11 @@ void starkware_plugin_call(int message, void *parameters) {
|
||||
case STARKWARE_REGISTER_AND_DEPOSIT_TOKEN:
|
||||
case STARKWARE_REGISTER_AND_DEPOSIT_ETH:
|
||||
strlcpy(msg->title, "From ETH Address", msg->titleLength);
|
||||
starkware_print_eth_address(context->amount, msg->msg, msg->msgLength);
|
||||
getEthDisplayableAddress(context->amount,
|
||||
msg->msg,
|
||||
msg->msgLength,
|
||||
&global_sha3,
|
||||
chainConfig->chainId);
|
||||
break;
|
||||
case STARKWARE_ESCAPE:
|
||||
strlcpy(msg->title, "Amount", msg->titleLength);
|
||||
@@ -784,7 +782,11 @@ void starkware_plugin_call(int message, void *parameters) {
|
||||
case STARKWARE_WITHDRAW_TO:
|
||||
case STARKWARE_WITHDRAW_NFT_TO:
|
||||
strlcpy(msg->title, "To ETH Address", msg->titleLength);
|
||||
starkware_print_eth_address(context->amount, msg->msg, msg->msgLength);
|
||||
getEthDisplayableAddress(context->amount,
|
||||
msg->msg,
|
||||
msg->msgLength,
|
||||
&global_sha3,
|
||||
chainConfig->chainId);
|
||||
break;
|
||||
case STARKWARE_WITHDRAW_AND_MINT:
|
||||
strlcpy(msg->title, "Asset Contract", msg->titleLength);
|
||||
|
||||
34
tests/build_local_test_elfs.sh
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
# FILL THESE WITH YOUR OWN SDKs PATHS
|
||||
NANOS_SDK=$TWO
|
||||
NANOX_SDK=$X
|
||||
|
||||
# list of apps required by tests that we want to build here
|
||||
appnames=("ethereum" "ethereum_classic")
|
||||
|
||||
# create elfs folder if it doesn't exist
|
||||
mkdir -p elfs
|
||||
|
||||
# move to repo's root to build apps
|
||||
cd ..
|
||||
|
||||
echo "*Building elfs for Nano S..."
|
||||
for app in "${appnames[@]}"
|
||||
do
|
||||
echo "**Building $app for Nano S..."
|
||||
make clean BOLOS_SDK=$NANOS_SDK
|
||||
make -j DEBUG=1 ALLOW_DATA=1 BOLOS_SDK=$NANOS_SDK CHAIN=$app
|
||||
cp bin/app.elf "tests/elfs/${app}_nanos.elf"
|
||||
done
|
||||
|
||||
echo "*Building elfs for Nano X..."
|
||||
for app in "${appnames[@]}"
|
||||
do
|
||||
echo "**Building $app for Nano X..."
|
||||
make clean BOLOS_SDK=$NANOX_SDK
|
||||
make -j DEBUG=1 ALLOW_DATA=1 BOLOS_SDK=$NANOX_SDK CHAIN=$app
|
||||
cp bin/app.elf "tests/elfs/${app}_nanox.elf"
|
||||
done
|
||||
|
||||
echo "done"
|
||||
@@ -1,4 +1,5 @@
|
||||
import Zemu from "@zondax/zemu";
|
||||
import fsExtra from "fs-extra";
|
||||
|
||||
const catchExit = async () => {
|
||||
process.on("SIGINT", () => {
|
||||
@@ -12,4 +13,5 @@ module.exports = async () => {
|
||||
await catchExit();
|
||||
await Zemu.checkAndPullImage();
|
||||
await Zemu.stopAllEmuContainers();
|
||||
fsExtra.emptyDirSync("snapshots/tmp")
|
||||
};
|
||||
@@ -30,4 +30,10 @@ module.exports = {
|
||||
"**/?(*.)+(spec|test).[tj]s?(x)",
|
||||
"**/?(*.)+(ispec|test).[tj]s?(x)",
|
||||
],
|
||||
|
||||
// Path of the file where tests can be """decorated"""
|
||||
setupFilesAfterEnv: ['<rootDir>/setupTests.js'],
|
||||
|
||||
// Stop immediatly when a test fail
|
||||
bail: true,
|
||||
};
|
||||
|
||||
@@ -12,14 +12,15 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
||||
"@ledgerhq/hw-app-eth": "^5.52.1",
|
||||
"@ledgerhq/hw-app-eth": "^6.5.0",
|
||||
"@ledgerhq/hw-transport-http": "^4.74.2",
|
||||
"@ledgerhq/logs": "^5.50.0",
|
||||
"@zondax/zemu": "0.13.0",
|
||||
"@zondax/zemu": "0.16.5",
|
||||
"bignumber.js": "^9.0.0",
|
||||
"bip32-path": "^0.4.2",
|
||||
"core-js": "^3.7.0",
|
||||
"ethereum-tx-decoder": "^3.0.0",
|
||||
"fs-extra": "^10.0.0",
|
||||
"google-protobuf": "^3.11.0",
|
||||
"jest-serial-runner": "^1.1.0",
|
||||
"js-sha256": "^0.9.0",
|
||||
|
||||
19
tests/setupTests.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import expect from 'expect'
|
||||
|
||||
expect.extend({
|
||||
toMatchSnapshot(received, original) {
|
||||
|
||||
if(received.data.equals(original.data)){
|
||||
return {
|
||||
message: () => `snapshots are equal`,
|
||||
pass: true
|
||||
}
|
||||
} else {
|
||||
console.log("snapshots are not equal")
|
||||
return {
|
||||
message: () => `snapshots are not equal`,
|
||||
pass: false
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 674 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 612 B After Width: | Height: | Size: 619 B |
|
Before Width: | Height: | Size: 730 B After Width: | Height: | Size: 737 B |
|
Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 559 B After Width: | Height: | Size: 566 B |
BIN
tests/snapshots/chainid/nanos/accept.png
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
tests/snapshots/chainid/nanos/address_1.png
Normal file
|
After Width: | Height: | Size: 809 B |
BIN
tests/snapshots/chainid/nanos/address_2.png
Normal file
|
After Width: | Height: | Size: 837 B |
BIN
tests/snapshots/chainid/nanos/address_3.png
Normal file
|
After Width: | Height: | Size: 567 B |
BIN
tests/snapshots/chainid/nanos/amount_1.png
Normal file
|
After Width: | Height: | Size: 474 B |
BIN
tests/snapshots/chainid/nanos/amount_1_palm.png
Normal file
|
After Width: | Height: | Size: 507 B |
BIN
tests/snapshots/chainid/nanos/amount_2.png
Normal file
|
After Width: | Height: | Size: 759 B |
BIN
tests/snapshots/chainid/nanos/amount_3.png
Normal file
|
After Width: | Height: | Size: 479 B |
BIN
tests/snapshots/chainid/nanos/fees.png
Normal file
|
After Width: | Height: | Size: 561 B |
BIN
tests/snapshots/chainid/nanos/fees_palm.png
Normal file
|
After Width: | Height: | Size: 594 B |
BIN
tests/snapshots/chainid/nanos/network.png
Normal file
|
After Width: | Height: | Size: 628 B |
BIN
tests/snapshots/chainid/nanos/palm.png
Normal file
|
After Width: | Height: | Size: 572 B |
BIN
tests/snapshots/chainid/nanos/review.png
Normal file
|
After Width: | Height: | Size: 541 B |
BIN
tests/snapshots/chainid/nanox/accept.png
Normal file
|
After Width: | Height: | Size: 674 B |
BIN
tests/snapshots/chainid/nanox/address.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
tests/snapshots/chainid/nanox/amount.png
Normal file
|
After Width: | Height: | Size: 866 B |
BIN
tests/snapshots/chainid/nanox/amount_palm.png
Normal file
|
After Width: | Height: | Size: 897 B |
BIN
tests/snapshots/chainid/nanox/fees.png
Normal file
|
After Width: | Height: | Size: 692 B |
BIN
tests/snapshots/chainid/nanox/fees_palm.png
Normal file
|
After Width: | Height: | Size: 721 B |
BIN
tests/snapshots/chainid/nanox/network.png
Normal file
|
After Width: | Height: | Size: 737 B |
BIN
tests/snapshots/chainid/nanox/palm.png
Normal file
|
After Width: | Height: | Size: 680 B |
BIN
tests/snapshots/chainid/nanox/review.png
Normal file
|
After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 674 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 530 B After Width: | Height: | Size: 537 B |
|
Before Width: | Height: | Size: 593 B After Width: | Height: | Size: 600 B |
|
Before Width: | Height: | Size: 745 B After Width: | Height: | Size: 752 B |
|
Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 674 B |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 514 B After Width: | Height: | Size: 521 B |
|
Before Width: | Height: | Size: 659 B After Width: | Height: | Size: 666 B |
|
Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 674 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 860 B After Width: | Height: | Size: 866 B |
|
Before Width: | Height: | Size: 685 B After Width: | Height: | Size: 692 B |
|
Before Width: | Height: | Size: 585 B After Width: | Height: | Size: 592 B |
|
Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 674 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 884 B After Width: | Height: | Size: 891 B |
|
Before Width: | Height: | Size: 692 B After Width: | Height: | Size: 699 B |
|
Before Width: | Height: | Size: 555 B After Width: | Height: | Size: 561 B |
|
Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 636 B |
|
Before Width: | Height: | Size: 667 B After Width: | Height: | Size: 674 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 869 B After Width: | Height: | Size: 875 B |
|
Before Width: | Height: | Size: 688 B After Width: | Height: | Size: 695 B |
|
Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 636 B |
1
tests/snapshots/tmp/nanos/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
*.png
|
||||
1
tests/snapshots/tmp/nanox/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
*.png
|
||||
@@ -6,22 +6,19 @@ import Zemu from "@zondax/zemu";
|
||||
import { TransportStatusError } from "@ledgerhq/errors";
|
||||
import { expect } from "../jest";
|
||||
|
||||
const {NANOS_ELF_PATH, NANOX_ELF_PATH, sim_options_nanos, sim_options_nanox, TIMEOUT} = require("generic.js");
|
||||
const {NANOS_ELF_PATH, NANOX_ELF_PATH, sim_options_nanos, sim_options_nanox, TIMEOUT, getTmpPath} = require("generic.js");
|
||||
|
||||
const ORIGINAL_SNAPSHOT_PATH_PREFIX = "snapshots/approve/";
|
||||
const SNAPSHOT_PATH_PREFIX = "snapshots/tmp/";
|
||||
|
||||
const ORIGINAL_SNAPSHOT_PATH_NANOS = ORIGINAL_SNAPSHOT_PATH_PREFIX + "nanos/";
|
||||
const ORIGINAL_SNAPSHOT_PATH_NANOX = ORIGINAL_SNAPSHOT_PATH_PREFIX + "nanox/";
|
||||
|
||||
const SNAPSHOT_PATH_NANOS = SNAPSHOT_PATH_PREFIX + "nanos/";
|
||||
const SNAPSHOT_PATH_NANOX = SNAPSHOT_PATH_PREFIX + "nanox/";
|
||||
|
||||
|
||||
test("Approve DAI tokens nanos", async () => {
|
||||
jest.setTimeout(TIMEOUT);
|
||||
const sim = new Zemu(NANOS_ELF_PATH);
|
||||
|
||||
let tmpPath = getTmpPath(expect.getState().currentTestName);
|
||||
|
||||
try {
|
||||
await sim.start(sim_options_nanos);
|
||||
|
||||
@@ -40,59 +37,59 @@ test("Approve DAI tokens nanos", async () => {
|
||||
|
||||
// Review tx
|
||||
filename = "review.png";
|
||||
await sim.snapshot(SNAPSHOT_PATH_NANOS + filename);
|
||||
const review = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||
await sim.snapshot(tmpPath + filename);
|
||||
const review = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(review).toEqual(expected_review);
|
||||
expect(review).toMatchSnapshot(expected_review);
|
||||
|
||||
// Type
|
||||
filename = "type.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||
const type = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const type = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_type = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(type).toEqual(expected_type);
|
||||
expect(type).toMatchSnapshot(expected_type);
|
||||
|
||||
// Amount
|
||||
filename = "amount.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||
const amount = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const amount = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_amount = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(amount).toEqual(expected_amount);
|
||||
expect(amount).toMatchSnapshot(expected_amount);
|
||||
|
||||
// Address 1/3
|
||||
filename = "address_1.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||
const address_1 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address_1 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(address_1).toEqual(expected_address_1);
|
||||
expect(address_1).toMatchSnapshot(expected_address_1);
|
||||
|
||||
// Address 2/3
|
||||
filename = "address_2.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||
const address_2 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address_2 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(address_2).toEqual(expected_address_2);
|
||||
expect(address_2).toMatchSnapshot(expected_address_2);
|
||||
|
||||
// Address 3/3
|
||||
filename = "address_3.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||
const address_3 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address_3 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(address_3).toEqual(expected_address_3);
|
||||
expect(address_3).toMatchSnapshot(expected_address_3);
|
||||
|
||||
// Max Fees
|
||||
filename = "fees.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||
const fees = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const fees = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(fees).toEqual(expected_fees);
|
||||
expect(fees).toMatchSnapshot(expected_fees);
|
||||
|
||||
// Accept
|
||||
filename = "accept.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||
const accept = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const accept = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(accept).toEqual(expected_accept);
|
||||
expect(accept).toMatchSnapshot(expected_accept);
|
||||
|
||||
await sim.clickBoth();
|
||||
|
||||
@@ -108,6 +105,8 @@ test("Approve DAI token nanox", async () => {
|
||||
jest.setTimeout(TIMEOUT);
|
||||
const sim = new Zemu(NANOX_ELF_PATH);
|
||||
|
||||
let tmpPath = getTmpPath(expect.getState().currentTestName);
|
||||
|
||||
try {
|
||||
await sim.start(sim_options_nanox);
|
||||
|
||||
@@ -125,45 +124,45 @@ test("Approve DAI token nanox", async () => {
|
||||
await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot());
|
||||
// Review tx
|
||||
filename = "review.png";
|
||||
await sim.snapshot(SNAPSHOT_PATH_NANOX + filename);
|
||||
const review = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||
await sim.snapshot(tmpPath + filename);
|
||||
const review = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(review).toEqual(expected_review);
|
||||
expect(review).toMatchSnapshot(expected_review);
|
||||
|
||||
// Type
|
||||
filename = "type.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||
const type = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const type = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_type = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(type).toEqual(expected_type);
|
||||
expect(type).toMatchSnapshot(expected_type);
|
||||
|
||||
// Amount
|
||||
filename = "amount.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||
const amount = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const amount = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_amount = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(amount).toEqual(expected_amount);
|
||||
expect(amount).toMatchSnapshot(expected_amount);
|
||||
|
||||
// Address
|
||||
filename = "address.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||
const address = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(address).toEqual(expected_address);
|
||||
expect(address).toMatchSnapshot(expected_address);
|
||||
|
||||
// Max Fees
|
||||
filename = "fees.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||
const fees = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const fees = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(fees).toEqual(expected_fees);
|
||||
expect(fees).toMatchSnapshot(expected_fees);
|
||||
|
||||
// Accept
|
||||
filename = "accept.png";
|
||||
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||
const accept = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const accept = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(accept).toEqual(expected_accept);
|
||||
expect(accept).toMatchSnapshot(expected_accept);
|
||||
|
||||
await sim.clickBoth();
|
||||
|
||||
|
||||
370
tests/src/chainid.test.js
Normal file
@@ -0,0 +1,370 @@
|
||||
import "core-js/stable";
|
||||
import "regenerator-runtime/runtime";
|
||||
import Eth from "@ledgerhq/hw-app-eth";
|
||||
import { byContractAddress } from "@ledgerhq/hw-app-eth/erc20";
|
||||
import Zemu from "@zondax/zemu";
|
||||
import { TransportStatusError } from "@ledgerhq/errors";
|
||||
import { expect } from "../jest";
|
||||
|
||||
const {NANOS_ELF_PATH, NANOX_ELF_PATH, sim_options_nanos, sim_options_nanox, TIMEOUT, getTmpPath} = require("generic.js");
|
||||
|
||||
const ORIGINAL_SNAPSHOT_PATH_PREFIX = "snapshots/chainid/";
|
||||
|
||||
const ORIGINAL_SNAPSHOT_PATH_NANOS = ORIGINAL_SNAPSHOT_PATH_PREFIX + "nanos/";
|
||||
const ORIGINAL_SNAPSHOT_PATH_NANOX = ORIGINAL_SNAPSHOT_PATH_PREFIX + "nanox/";
|
||||
|
||||
test("Transfer on network 112233445566 on Ethereum nanos", async () => {
|
||||
jest.setTimeout(TIMEOUT);
|
||||
const sim = new Zemu(NANOS_ELF_PATH);
|
||||
let tmpPath = getTmpPath(expect.getState().currentTestName);
|
||||
|
||||
try {
|
||||
await sim.start(sim_options_nanos);
|
||||
|
||||
let transport = await sim.getTransport();
|
||||
let eth = new Eth(transport);
|
||||
|
||||
// Send transaction
|
||||
let tx = eth.signTransaction(
|
||||
"44'/60'/0'/0/0",
|
||||
"f044850306dc4200825208945a321744667052affa8386ed49e00ef223cbffc3876f9c9e7bf6181880851a21a278be8080"
|
||||
)
|
||||
let filename;
|
||||
|
||||
await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot());
|
||||
// Review tx
|
||||
filename = "review.png";
|
||||
await sim.snapshot(tmpPath + filename);
|
||||
const review = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(review).toMatchSnapshot(expected_review);
|
||||
|
||||
// Amount 1/3
|
||||
filename = "amount_1.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const amount_1 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_amount_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(amount_1).toMatchSnapshot(expected_amount_1);
|
||||
|
||||
// Amount 2/3
|
||||
filename = "amount_2.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const amount_2 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_amount_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(amount_2).toMatchSnapshot(expected_amount_2);
|
||||
|
||||
// Amount 3/3
|
||||
filename = "amount_3.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const amount_3 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_amount_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(amount_3).toMatchSnapshot(expected_amount_3);
|
||||
|
||||
// Address 1/3
|
||||
filename = "address_1.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address_1 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(address_1).toMatchSnapshot(expected_address_1);
|
||||
|
||||
// Address 2/3
|
||||
filename = "address_2.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address_2 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(address_2).toMatchSnapshot(expected_address_2);
|
||||
|
||||
// Address 3/3
|
||||
filename = "address_3.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address_3 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(address_3).toMatchSnapshot(expected_address_3);
|
||||
|
||||
// Network
|
||||
filename = "network.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const network = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_network = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(network).toMatchSnapshot(expected_network);
|
||||
|
||||
// Max Fees
|
||||
filename = "fees.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const fees = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(fees).toMatchSnapshot(expected_fees);
|
||||
|
||||
// Accept
|
||||
filename = "accept.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const accept = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(accept).toMatchSnapshot(expected_accept);
|
||||
|
||||
await sim.clickBoth();
|
||||
|
||||
await expect(tx).resolves.toEqual(
|
||||
{
|
||||
"r": "31fca443b3cad62f3ce18e287f3cf4892ac2669379cc21b5cf198561f0511d1e",
|
||||
"s": "3cf21485cd8b86e1acddbcc641e16a3efad18aaeb5ae96a650f1a8b291078494",
|
||||
"v": "344344f1a0",
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
await sim.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("Transfer on palm network on Ethereum nanos", async () => {
|
||||
jest.setTimeout(TIMEOUT);
|
||||
const sim = new Zemu(NANOS_ELF_PATH);
|
||||
let tmpPath = getTmpPath(expect.getState().currentTestName);
|
||||
|
||||
try {
|
||||
await sim.start(sim_options_nanos);
|
||||
|
||||
let transport = await sim.getTransport();
|
||||
let eth = new Eth(transport);
|
||||
|
||||
// Send transaction
|
||||
let tx = eth.signTransaction(
|
||||
"44'/60'/0'/0/0",
|
||||
"f044850306dc4200825208945a321744667052affa8386ed49e00ef223cbffc3876f9c9e7bf61818808502a15c308d8080"
|
||||
);
|
||||
let filename;
|
||||
|
||||
await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot());
|
||||
// Review tx
|
||||
filename = "review.png";
|
||||
await sim.snapshot(tmpPath + filename);
|
||||
const review = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(review).toMatchSnapshot(expected_review);
|
||||
|
||||
// Amount 1/3
|
||||
filename = "amount_1_palm.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const amount_1 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_amount_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(amount_1).toMatchSnapshot(expected_amount_1);
|
||||
|
||||
// Amount 2/3
|
||||
filename = "amount_2.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const amount_2 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_amount_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(amount_2).toMatchSnapshot(expected_amount_2);
|
||||
|
||||
// Amount 3/3
|
||||
filename = "amount_3.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const amount_3 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_amount_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(amount_3).toMatchSnapshot(expected_amount_3);
|
||||
|
||||
// Address 1/3
|
||||
filename = "address_1.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address_1 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(address_1).toMatchSnapshot(expected_address_1);
|
||||
|
||||
// Address 2/3
|
||||
filename = "address_2.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address_2 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(address_2).toMatchSnapshot(expected_address_2);
|
||||
|
||||
// Address 3/3
|
||||
filename = "address_3.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address_3 = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(address_3).toMatchSnapshot(expected_address_3);
|
||||
|
||||
// Network
|
||||
filename = "palm.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const network = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_network = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(network).toMatchSnapshot(expected_network);
|
||||
|
||||
// Max Fees
|
||||
filename = "fees_palm.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const fees = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(fees).toMatchSnapshot(expected_fees);
|
||||
|
||||
// Accept
|
||||
filename = "accept.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const accept = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||
expect(accept).toMatchSnapshot(expected_accept);
|
||||
|
||||
await sim.clickBoth();
|
||||
|
||||
await expect(tx).resolves.toEqual(
|
||||
{
|
||||
"r": "f9b5d903c47c34027156e869bda5aa002233d6cca583ad53d125612fc0795f3b",
|
||||
"s": "00da038129414e5ae6f7c1529c6067e82484e3694c84c16d575e77162f631c27",
|
||||
"v": "0542b8613d",
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
await sim.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("Transfer on network 112233445566 on Ethereum nanox", async () => {
|
||||
jest.setTimeout(TIMEOUT);
|
||||
const sim = new Zemu(NANOX_ELF_PATH);
|
||||
let tmpPath = getTmpPath(expect.getState().currentTestName);
|
||||
|
||||
try {
|
||||
await sim.start(sim_options_nanox);
|
||||
|
||||
let transport = await sim.getTransport();
|
||||
let eth = new Eth(transport);
|
||||
|
||||
// Send transaction
|
||||
let tx = eth.signTransaction(
|
||||
"44'/60'/0'/0/0",
|
||||
"f044850306dc4200825208945a321744667052affa8386ed49e00ef223cbffc3876f9c9e7bf6181880851a21a278be8080"
|
||||
)
|
||||
let filename;
|
||||
|
||||
await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot());
|
||||
// Review tx
|
||||
filename = "review.png";
|
||||
await sim.snapshot(tmpPath + filename);
|
||||
const review = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(review).toMatchSnapshot(expected_review);
|
||||
|
||||
// Amount
|
||||
filename = "amount.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const amount = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_amount = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(amount).toMatchSnapshot(expected_amount);
|
||||
|
||||
// Address
|
||||
filename = "address.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(address).toMatchSnapshot(expected_address);
|
||||
|
||||
// Network
|
||||
filename = "network.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const network = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_network = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(network).toMatchSnapshot(expected_network);
|
||||
|
||||
// Max Fees
|
||||
filename = "fees.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const fees = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(fees).toMatchSnapshot(expected_fees);
|
||||
|
||||
// Accept
|
||||
filename = "accept.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const accept = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(accept).toMatchSnapshot(expected_accept);
|
||||
|
||||
await sim.clickBoth();
|
||||
|
||||
await expect(tx).resolves.toEqual(
|
||||
{
|
||||
"r": "31fca443b3cad62f3ce18e287f3cf4892ac2669379cc21b5cf198561f0511d1e",
|
||||
"s": "3cf21485cd8b86e1acddbcc641e16a3efad18aaeb5ae96a650f1a8b291078494",
|
||||
"v": "344344f1a0",
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
await sim.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("Transfer on palm network on Ethereum nanox", async () => {
|
||||
jest.setTimeout(TIMEOUT);
|
||||
const sim = new Zemu(NANOX_ELF_PATH);
|
||||
let tmpPath = getTmpPath(expect.getState().currentTestName);
|
||||
|
||||
try {
|
||||
await sim.start(sim_options_nanox);
|
||||
|
||||
let transport = await sim.getTransport();
|
||||
let eth = new Eth(transport);
|
||||
|
||||
// Send transaction
|
||||
let tx = eth.signTransaction(
|
||||
"44'/60'/0'/0/0",
|
||||
"f044850306dc4200825208945a321744667052affa8386ed49e00ef223cbffc3876f9c9e7bf61818808502a15c308d8080"
|
||||
);
|
||||
let filename;
|
||||
|
||||
await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot());
|
||||
// Review tx
|
||||
filename = "review.png";
|
||||
await sim.snapshot(tmpPath + filename);
|
||||
const review = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(review).toMatchSnapshot(expected_review);
|
||||
|
||||
// Amount
|
||||
filename = "amount_palm.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const amount = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_amount = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(amount).toMatchSnapshot(expected_amount);
|
||||
|
||||
// Address
|
||||
filename = "address.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const address = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_address = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(address).toMatchSnapshot(expected_address);
|
||||
|
||||
// Network
|
||||
filename = "palm.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const network = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_network = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(network).toMatchSnapshot(expected_network);
|
||||
|
||||
// Max Fees
|
||||
filename = "fees_palm.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const fees = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(fees).toMatchSnapshot(expected_fees);
|
||||
|
||||
// Accept
|
||||
filename = "accept.png";
|
||||
await sim.clickRight(tmpPath + filename);
|
||||
const accept = Zemu.LoadPng2RGB(tmpPath + filename);
|
||||
const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||
expect(accept).toMatchSnapshot(expected_accept);
|
||||
|
||||
await sim.clickBoth();
|
||||
|
||||
await expect(tx).resolves.toEqual(
|
||||
{
|
||||
"r": "f9b5d903c47c34027156e869bda5aa002233d6cca583ad53d125612fc0795f3b",
|
||||
"s": "00da038129414e5ae6f7c1529c6067e82484e3694c84c16d575e77162f631c27",
|
||||
"v": "0542b8613d",
|
||||
}
|
||||
);
|
||||
} finally {
|
||||
await sim.close();
|
||||
}
|
||||
});
|
||||