Add network display (#152)
* Add network name display instead of chainID * Add display of correct ticker along with network * Add FTM * Clang-format * Add comment in python script * Rename SIZE_MAX to MAX_SIZE * Change %u to %d in printf * Remove needless PIC * Update comment about get_chain_id() * Update example script to follow EIP155 * Remove unused PIC calls * Add whitespace between ticker and amount when using EIP155 * Remove decimal config per network, set back 18 everywhere * Adapt u32_from_BE to swith cases * Remove chainid from signTx.py * Switch to switch in stead of if in get_chain_id * Revert "Remove chainid from signTx.py" This reverts commit 454e09f280ec3e3ec1c7d7cc0027247ef4390088. * Change Ethereum chainid to 1 * Rename chainid_step to network_step * Adapt finalizeParsing to new chainid for Ethereum * Update snapshots * clang-format * Fix network display logic for clones * Fix tests * Add clone tests Co-authored-by: TamtamHero <10632523+TamtamHero@users.noreply.github.com>
15
.github/workflows/ci-workflow.yml
vendored
@@ -25,23 +25,25 @@ jobs:
|
|||||||
- name: Build an altcoin
|
- name: Build an altcoin
|
||||||
run: |
|
run: |
|
||||||
make DEBUG=1 ALLOW_DATA=1 CHAIN=ethereum_classic
|
make DEBUG=1 ALLOW_DATA=1 CHAIN=ethereum_classic
|
||||||
|
mv bin/app.elf ethereum_classic_nanos.elf
|
||||||
|
|
||||||
- name: Upload altcoin binary
|
- name: Upload altcoin binary
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ethereum_classic_nanos
|
name: ethereum_classic_nanos
|
||||||
path: bin
|
path: ./ethereum_classic_nanos.elf
|
||||||
|
|
||||||
- name: Build Ethereum
|
- name: Build Ethereum
|
||||||
run: |
|
run: |
|
||||||
make clean
|
make clean
|
||||||
make DEBUG=1 ALLOW_DATA=1
|
make DEBUG=1 ALLOW_DATA=1
|
||||||
|
mv bin/app.elf ethereum_nanos.elf
|
||||||
|
|
||||||
- name: Upload app binary
|
- name: Upload app binary
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ethereum_nanos
|
name: ethereum_nanos
|
||||||
path: bin
|
path: ./ethereum_nanos.elf
|
||||||
|
|
||||||
job_build_debug_nano_x:
|
job_build_debug_nano_x:
|
||||||
name: Build debug Nano X
|
name: Build debug Nano X
|
||||||
@@ -60,23 +62,25 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
make clean
|
make clean
|
||||||
make BOLOS_SDK=$NANOX_SDK DEBUG=1 ALLOW_DATA=1 CHAIN=ethereum_classic
|
make BOLOS_SDK=$NANOX_SDK DEBUG=1 ALLOW_DATA=1 CHAIN=ethereum_classic
|
||||||
|
mv bin/app.elf ethereum_classic_nanox.elf
|
||||||
|
|
||||||
- name: Upload altcoin binary
|
- name: Upload altcoin binary
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ethereum_classic_nanox
|
name: ethereum_classic_nanox
|
||||||
path: bin
|
path: ./ethereum_classic_nanox.elf
|
||||||
|
|
||||||
- name: Build Ethereum Nano X
|
- name: Build Ethereum Nano X
|
||||||
run: |
|
run: |
|
||||||
make clean
|
make clean
|
||||||
make BOLOS_SDK=$NANOX_SDK DEBUG=1 ALLOW_DATA=1
|
make BOLOS_SDK=$NANOX_SDK DEBUG=1 ALLOW_DATA=1
|
||||||
|
mv bin/app.elf ethereum_nanox.elf
|
||||||
|
|
||||||
- name: Upload app binary
|
- name: Upload app binary
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: ethereum_nanox
|
name: ethereum_nanox
|
||||||
path: bin
|
path: ./ethereum_nanox.elf
|
||||||
|
|
||||||
jobs-e2e-tests:
|
jobs-e2e-tests:
|
||||||
needs: [job_build_debug_nano_s, job_build_debug_nano_x]
|
needs: [job_build_debug_nano_s, job_build_debug_nano_x]
|
||||||
@@ -104,6 +108,9 @@ jobs:
|
|||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
with:
|
with:
|
||||||
path: tests/elfs
|
path: tests/elfs
|
||||||
|
- name: Gather elfs
|
||||||
|
run: |
|
||||||
|
cp `find . -name "*.elf"` ./tests/elfs
|
||||||
- name: Run zemu tests
|
- name: Run zemu tests
|
||||||
run: |
|
run: |
|
||||||
cd tests && yarn test
|
cd tests && yarn test
|
||||||
|
|||||||
2
Makefile
@@ -41,7 +41,7 @@ endif
|
|||||||
ifeq ($(CHAIN),ethereum)
|
ifeq ($(CHAIN),ethereum)
|
||||||
# Lock the application on its standard path for 1.5. Please complain if non compliant
|
# Lock the application on its standard path for 1.5. Please complain if non compliant
|
||||||
APP_LOAD_PARAMS += --path "44'/60'"
|
APP_LOAD_PARAMS += --path "44'/60'"
|
||||||
DEFINES += CHAINID_UPCASE=\"ETHEREUM\" CHAINID_COINNAME=\"ETH\" CHAIN_KIND=CHAIN_KIND_ETHEREUM CHAIN_ID=0
|
DEFINES += CHAINID_UPCASE=\"ETHEREUM\" CHAINID_COINNAME=\"ETH\" CHAIN_KIND=CHAIN_KIND_ETHEREUM CHAIN_ID=1
|
||||||
# Starkware integration
|
# Starkware integration
|
||||||
APP_LOAD_PARAMS += --path "2645'/579218131'"
|
APP_LOAD_PARAMS += --path "2645'/579218131'"
|
||||||
DEFINES += HAVE_STARKWARE
|
DEFINES += HAVE_STARKWARE
|
||||||
|
|||||||
@@ -59,6 +59,9 @@ class UnsignedTransaction(Serializable):
|
|||||||
('to', address),
|
('to', address),
|
||||||
('value', big_endian_int),
|
('value', big_endian_int),
|
||||||
('data', binary),
|
('data', binary),
|
||||||
|
('chainid', big_endian_int),
|
||||||
|
('dummy1', big_endian_int),
|
||||||
|
('dummy2', big_endian_int),
|
||||||
]
|
]
|
||||||
|
|
||||||
def unsigned_tx_from_tx(tx):
|
def unsigned_tx_from_tx(tx):
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ parser.add_argument('--amount', help="Amount to send in ether", required=True)
|
|||||||
parser.add_argument('--to', help="Destination address", type=str, required=True)
|
parser.add_argument('--to', help="Destination address", type=str, required=True)
|
||||||
parser.add_argument('--path', help="BIP 32 path to sign with")
|
parser.add_argument('--path', help="BIP 32 path to sign with")
|
||||||
parser.add_argument('--data', help="Data to add, hex encoded")
|
parser.add_argument('--data', help="Data to add, hex encoded")
|
||||||
|
parser.add_argument('--chainid', help="Chain ID (1 for Ethereum mainnet, 137 for Polygon, etc)", type=int)
|
||||||
parser.add_argument('--descriptor', help="Optional descriptor")
|
parser.add_argument('--descriptor', help="Optional descriptor")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -71,6 +72,10 @@ if args.data == None:
|
|||||||
else:
|
else:
|
||||||
args.data = decode_hex(args.data[2:])
|
args.data = decode_hex(args.data[2:])
|
||||||
|
|
||||||
|
# default to Ethereum mainnet
|
||||||
|
if args.chainid == None:
|
||||||
|
args.chainid = 1
|
||||||
|
|
||||||
amount = Decimal(args.amount) * 10**18
|
amount = Decimal(args.amount) * 10**18
|
||||||
|
|
||||||
tx = UnsignedTransaction(
|
tx = UnsignedTransaction(
|
||||||
@@ -80,10 +85,16 @@ tx = UnsignedTransaction(
|
|||||||
to=decode_hex(args.to[2:]),
|
to=decode_hex(args.to[2:]),
|
||||||
value=int(amount),
|
value=int(amount),
|
||||||
data=args.data,
|
data=args.data,
|
||||||
|
chainid=args.chainid,
|
||||||
|
dummy1=0,
|
||||||
|
dummy2=0
|
||||||
)
|
)
|
||||||
|
|
||||||
encodedTx = encode(tx, UnsignedTransaction)
|
encodedTx = encode(tx, UnsignedTransaction)
|
||||||
|
|
||||||
|
# To test an EIP-2930 transaction, uncomment this line
|
||||||
|
#encodedTx = bytearray.fromhex("01f8e60380018402625a0094cccccccccccccccccccccccccccccccccccccccc830186a0a4693c61390000000000000000000000000000000000000000000000000000000000000002f85bf859940000000000000000000000000000000000000102f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000060a780a09b8adcd2a4abd34b42d56fcd90b949f74ca9696dfe2b427bc39aa280bbf1924ca029af4a471bb2953b4e7933ea95880648552a9345424a1ac760189655ceb1832a")
|
||||||
|
|
||||||
dongle = getDongle(True)
|
dongle = getDongle(True)
|
||||||
|
|
||||||
if args.descriptor != None:
|
if args.descriptor != None:
|
||||||
|
|||||||
@@ -162,13 +162,14 @@ typedef enum {
|
|||||||
#endif
|
#endif
|
||||||
} contract_call_t;
|
} contract_call_t;
|
||||||
|
|
||||||
|
#define NETWORK_NAME_MAX_SIZE 12
|
||||||
|
|
||||||
typedef struct txStringProperties_t {
|
typedef struct txStringProperties_t {
|
||||||
char fullAddress[43];
|
char fullAddress[43];
|
||||||
char fullAmount[50];
|
char fullAmount[50];
|
||||||
char maxFee[50];
|
char maxFee[50];
|
||||||
char nonce[8]; // 10M tx per account ought to be enough for everybody
|
char nonce[8]; // 10M tx per account ought to be enough for everybody
|
||||||
char chainID[8]; // 10M different chainID ought to be enough for people to find a unique
|
char network_name[NETWORK_NAME_MAX_SIZE];
|
||||||
// chainID for their token / chain.
|
|
||||||
} txStringProperties_t;
|
} txStringProperties_t;
|
||||||
|
|
||||||
#define SHARED_CTX_FIELD_1_SIZE 100
|
#define SHARED_CTX_FIELD_1_SIZE 100
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ void stark_get_amount_string(uint8_t *contractAddress,
|
|||||||
char *target100) {
|
char *target100) {
|
||||||
uint256_t amountPre, quantum, amount;
|
uint256_t amountPre, quantum, amount;
|
||||||
uint8_t decimals;
|
uint8_t decimals;
|
||||||
char *ticker = (char *) PIC(chainConfig->coinName);
|
char *ticker = chainConfig->coinName;
|
||||||
|
|
||||||
PRINTF("stark_get_amount_string %.*H\n", 20, contractAddress);
|
PRINTF("stark_get_amount_string %.*H\n", 20, contractAddress);
|
||||||
|
|
||||||
|
|||||||
30
src/utils.c
@@ -57,20 +57,24 @@ int local_strchr(char *string, char ch) {
|
|||||||
// Almost like U4BE except that it takes `size` as a parameter.
|
// Almost like U4BE except that it takes `size` as a parameter.
|
||||||
// The `strict` parameter defines whether we should throw in case of a length > 4.
|
// The `strict` parameter defines whether we should throw in case of a length > 4.
|
||||||
uint32_t u32_from_BE(uint8_t *in, uint8_t size, bool strict) {
|
uint32_t u32_from_BE(uint8_t *in, uint8_t size, bool strict) {
|
||||||
uint32_t res = 0;
|
switch (size) {
|
||||||
if (size == 1) {
|
case 0:
|
||||||
res = in[0];
|
return 0;
|
||||||
} else if (size == 2) {
|
case 1:
|
||||||
res = (in[0] << 8) | in[1];
|
return in[0];
|
||||||
} else if (size == 3) {
|
case 2:
|
||||||
res = (in[0] << 16) | (in[1] << 8) | in[2];
|
return (in[0] << 8) | in[1];
|
||||||
} else if (size == 4) {
|
case 3:
|
||||||
res = (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3];
|
return (in[0] << 16) | (in[1] << 8) | in[2];
|
||||||
} else if (strict && size != 0) {
|
case 4:
|
||||||
PRINTF("Unexpected format\n");
|
return (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3];
|
||||||
THROW(EXCEPTION);
|
default:
|
||||||
|
if (strict) {
|
||||||
|
PRINTF("Unexpected format\n");
|
||||||
|
THROW(EXCEPTION);
|
||||||
|
}
|
||||||
|
return (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3];
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool uint256_to_decimal(const uint8_t *value, size_t value_len, char *out, size_t out_len) {
|
bool uint256_to_decimal(const uint8_t *value, size_t value_len, char *out, size_t out_len) {
|
||||||
|
|||||||
70
src_common/network.c
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "network.h"
|
||||||
|
#include "os.h"
|
||||||
|
#include "shared_context.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
// Mappping of chain ids to networks.
|
||||||
|
const network_info_t NETWORK_MAPPING[] = {
|
||||||
|
{.chain_id = 1, .name = "Ethereum", .ticker = "ETH "},
|
||||||
|
{.chain_id = 3, .name = "Ropsten", .ticker = "ETH "},
|
||||||
|
{.chain_id = 4, .name = "Rinkeby", .ticker = "ETH "},
|
||||||
|
{.chain_id = 5, .name = "Goerli", .ticker = "ETH "},
|
||||||
|
{.chain_id = 10, .name = "Optimism", .ticker = "ETH "},
|
||||||
|
{.chain_id = 42, .name = "Kovan", .ticker = "ETH "},
|
||||||
|
{.chain_id = 56, .name = "BSC", .ticker = "BNB "},
|
||||||
|
{.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 "}};
|
||||||
|
|
||||||
|
uint32_t get_chain_id(void) {
|
||||||
|
uint32_t chain_id = 0;
|
||||||
|
|
||||||
|
switch (txContext.txType) {
|
||||||
|
case LEGACY:
|
||||||
|
chain_id = u32_from_BE(txContext.content->v, txContext.content->vLength, true);
|
||||||
|
break;
|
||||||
|
case EIP2930:
|
||||||
|
chain_id = u32_from_BE(tmpContent.txContent.chainID.value,
|
||||||
|
tmpContent.txContent.chainID.length,
|
||||||
|
true);
|
||||||
|
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();
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *get_network_name(void) {
|
||||||
|
network_info_t *network = get_network();
|
||||||
|
if (network == NULL) {
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
return (char *) PIC(network->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *get_network_ticker(void) {
|
||||||
|
network_info_t *network = get_network();
|
||||||
|
if (network == NULL) {
|
||||||
|
return chainConfig->coinName;
|
||||||
|
} else {
|
||||||
|
return (char *) PIC(network->ticker);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src_common/network.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include "tokens.h"
|
||||||
|
|
||||||
|
#define NETWORK_STRING_MAX_SIZE 12
|
||||||
|
|
||||||
|
typedef struct network_info_s {
|
||||||
|
const char name[NETWORK_STRING_MAX_SIZE];
|
||||||
|
const char ticker[MAX_TICKER_LEN];
|
||||||
|
uint32_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);
|
||||||
|
// 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.
|
||||||
|
char *get_network_name(void);
|
||||||
|
// Returns a pointer to the network ticker, or chainConfig->coinName if there is none.
|
||||||
|
char *get_network_ticker(void);
|
||||||
@@ -2,3 +2,5 @@
|
|||||||
|
|
||||||
customStatus_e customProcessor(txContext_t *context);
|
customStatus_e customProcessor(txContext_t *context);
|
||||||
void finalizeParsing(bool direct);
|
void finalizeParsing(bool direct);
|
||||||
|
|
||||||
|
void ux_approve_tx(bool dataPresent);
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "stark_utils.h"
|
#include "stark_utils.h"
|
||||||
#endif
|
#endif
|
||||||
#include "eth_plugin_handler.h"
|
#include "eth_plugin_handler.h"
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
#define ERR_SILENT_MODE_CHECK_FAILED 0x6001
|
#define ERR_SILENT_MODE_CHECK_FAILED 0x6001
|
||||||
|
|
||||||
@@ -195,7 +196,7 @@ void reportFinalizeError(bool direct) {
|
|||||||
|
|
||||||
void computeFees(char *displayBuffer, uint32_t displayBufferSize) {
|
void computeFees(char *displayBuffer, uint32_t displayBufferSize) {
|
||||||
uint256_t gasPrice, startGas, uint256;
|
uint256_t gasPrice, startGas, uint256;
|
||||||
uint8_t *feeTicker = (uint8_t *) PIC(chainConfig->coinName);
|
char *feeTicker = get_network_ticker();
|
||||||
uint8_t tickerOffset = 0;
|
uint8_t tickerOffset = 0;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
@@ -240,25 +241,14 @@ void computeFees(char *displayBuffer, uint32_t displayBufferSize) {
|
|||||||
void finalizeParsing(bool direct) {
|
void finalizeParsing(bool direct) {
|
||||||
char displayBuffer[50];
|
char displayBuffer[50];
|
||||||
uint8_t decimals = WEI_TO_ETHER;
|
uint8_t decimals = WEI_TO_ETHER;
|
||||||
uint8_t *ticker = (uint8_t *) PIC(chainConfig->coinName);
|
char *ticker = get_network_ticker();
|
||||||
ethPluginFinalize_t pluginFinalize;
|
ethPluginFinalize_t pluginFinalize;
|
||||||
tokenDefinition_t *token1 = NULL, *token2 = NULL;
|
tokenDefinition_t *token1 = NULL, *token2 = NULL;
|
||||||
bool genericUI = true;
|
bool genericUI = true;
|
||||||
|
|
||||||
// Verify the chain
|
// Verify the chain
|
||||||
if (chainConfig->chainId != 0) {
|
if (chainConfig->chainId != ETHEREUM_MAINNET_CHAINID) {
|
||||||
uint32_t id = 0;
|
uint32_t id = get_chain_id();
|
||||||
|
|
||||||
if (txContext.txType == LEGACY) {
|
|
||||||
id = u32_from_BE(txContext.content->v, txContext.content->vLength, true);
|
|
||||||
} else if (txContext.txType == EIP2930) {
|
|
||||||
id = u32_from_BE(txContext.content->chainID.value,
|
|
||||||
txContext.content->chainID.length,
|
|
||||||
false);
|
|
||||||
} else {
|
|
||||||
PRINTF("TxType `%u` not supported while checking for chainID\n", txContext.txType);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chainConfig->chainId != id) {
|
if (chainConfig->chainId != id) {
|
||||||
PRINTF("Invalid chainID %u expected %u\n", id, chainConfig->chainId);
|
PRINTF("Invalid chainID %u expected %u\n", id, chainConfig->chainId);
|
||||||
@@ -342,7 +332,7 @@ void finalizeParsing(bool direct) {
|
|||||||
tmpContent.txContent.destinationLength = 20;
|
tmpContent.txContent.destinationLength = 20;
|
||||||
if (token1 != NULL) {
|
if (token1 != NULL) {
|
||||||
decimals = token1->decimals;
|
decimals = token1->decimals;
|
||||||
ticker = token1->ticker;
|
ticker = (char *) token1->ticker;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -404,26 +394,22 @@ void finalizeParsing(bool direct) {
|
|||||||
|
|
||||||
// Prepare chainID field
|
// Prepare chainID field
|
||||||
if (genericUI) {
|
if (genericUI) {
|
||||||
if (txContext.txType == LEGACY) {
|
char *name = get_network_name();
|
||||||
uint32_t id = u32_from_BE(txContext.content->v, txContext.content->vLength, true);
|
if (name == NULL) {
|
||||||
PRINTF("Chain ID: %u\n", id);
|
// No network name found so simply copy the chain ID as the network name.
|
||||||
uint8_t res =
|
uint32_t chain_id = get_chain_id();
|
||||||
snprintf(strings.common.chainID, sizeof(strings.common.chainID), "%d", id);
|
uint8_t res = snprintf(strings.common.network_name,
|
||||||
if (res >= sizeof(strings.common.chainID)) {
|
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
|
// 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.
|
// the output was truncated. Return the appropriate error code.
|
||||||
THROW(0x6502);
|
THROW(0x6502);
|
||||||
}
|
}
|
||||||
} else if (txContext.txType == EIP2930) {
|
|
||||||
uint256_t chainID;
|
|
||||||
convertUint256BE(tmpContent.txContent.chainID.value,
|
|
||||||
tmpContent.txContent.chainID.length,
|
|
||||||
&chainID);
|
|
||||||
tostring256(&chainID, 10, displayBuffer, sizeof(displayBuffer));
|
|
||||||
strncpy(strings.common.chainID, displayBuffer, sizeof(strings.common.chainID));
|
|
||||||
} else {
|
} else {
|
||||||
PRINTF("Txtype `%u` not supported while generating chainID\n", txContext.txType);
|
// Network name found, simply copy it.
|
||||||
return;
|
strncpy(strings.common.network_name, name, sizeof(strings.common.network_name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#include "ui_callbacks.h"
|
#include "ui_callbacks.h"
|
||||||
#include "chainConfig.h"
|
#include "chainConfig.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "feature_signTx.h"
|
||||||
|
#include "network.h"
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
UX_STEP_NOCB(
|
UX_STEP_NOCB(
|
||||||
@@ -116,11 +118,11 @@ UX_STEP_NOCB(
|
|||||||
.text = strings.common.maxFee,
|
.text = strings.common.maxFee,
|
||||||
});
|
});
|
||||||
UX_STEP_NOCB(
|
UX_STEP_NOCB(
|
||||||
ux_approval_chainid_step,
|
ux_approval_network_step,
|
||||||
bnnn_paging,
|
bnnn_paging,
|
||||||
{
|
{
|
||||||
.title = "Chain ID",
|
.title = "Network",
|
||||||
.text = strings.common.chainID,
|
.text = strings.common.network_name,
|
||||||
});
|
});
|
||||||
UX_STEP_CB(
|
UX_STEP_CB(
|
||||||
ux_approval_accept_step,
|
ux_approval_accept_step,
|
||||||
@@ -171,18 +173,9 @@ void ux_approve_tx(bool dataPresent) {
|
|||||||
ux_approval_tx_flow_[step++] = &ux_approval_nonce_step;
|
ux_approval_tx_flow_[step++] = &ux_approval_nonce_step;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t id;
|
uint32_t chain_id = get_chain_id();
|
||||||
if (txContext.txType == LEGACY) {
|
if (chainConfig->chainId == ETHEREUM_MAINNET_CHAINID && chain_id != chainConfig->chainId) {
|
||||||
id = u32_from_BE(txContext.content->v, txContext.content->vLength, true);
|
ux_approval_tx_flow_[step++] = &ux_approval_network_step;
|
||||||
} else if (txContext.txType == EIP2930) {
|
|
||||||
id =
|
|
||||||
u32_from_BE(txContext.content->chainID.value, txContext.content->chainID.length, false);
|
|
||||||
} else {
|
|
||||||
PRINTF("TxType `%u` not supported while preparing to approve tx\n", txContext.txType);
|
|
||||||
THROW(0x6501);
|
|
||||||
}
|
|
||||||
if (id != ETHEREUM_MAINNET_CHAINID) {
|
|
||||||
ux_approval_tx_flow_[step++] = &ux_approval_chainid_step;
|
|
||||||
}
|
}
|
||||||
ux_approval_tx_flow_[step++] = &ux_approval_fees_step;
|
ux_approval_tx_flow_[step++] = &ux_approval_fees_step;
|
||||||
ux_approval_tx_flow_[step++] = &ux_approval_accept_step;
|
ux_approval_tx_flow_[step++] = &ux_approval_accept_step;
|
||||||
|
|||||||
@@ -217,12 +217,12 @@ void eth2_plugin_call(int message, void *parameters) {
|
|||||||
switch (msg->screenIndex) {
|
switch (msg->screenIndex) {
|
||||||
case 0: { // Amount screen
|
case 0: { // Amount screen
|
||||||
uint8_t decimals = WEI_TO_ETHER;
|
uint8_t decimals = WEI_TO_ETHER;
|
||||||
uint8_t *ticker = (uint8_t *) PIC(chainConfig->coinName);
|
char *ticker = chainConfig->coinName;
|
||||||
strcpy(msg->title, "Amount");
|
strcpy(msg->title, "Amount");
|
||||||
amountToString(tmpContent.txContent.value.value,
|
amountToString(tmpContent.txContent.value.value,
|
||||||
tmpContent.txContent.value.length,
|
tmpContent.txContent.value.length,
|
||||||
decimals,
|
decimals,
|
||||||
(char *) ticker,
|
ticker,
|
||||||
msg->msg,
|
msg->msg,
|
||||||
100);
|
100);
|
||||||
msg->result = ETH_PLUGIN_RESULT_OK;
|
msg->result = ETH_PLUGIN_RESULT_OK;
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ void starkware_print_eth_address(uint8_t *address, char *destination) {
|
|||||||
void starkware_print_amount(uint8_t *amountData, char *destination, bool forEscape) {
|
void starkware_print_amount(uint8_t *amountData, char *destination, bool forEscape) {
|
||||||
uint256_t amount, amountPre, quantum;
|
uint256_t amount, amountPre, quantum;
|
||||||
uint8_t decimals;
|
uint8_t decimals;
|
||||||
char *ticker = (char *) PIC(chainConfig->coinName);
|
char *ticker = chainConfig->coinName;
|
||||||
|
|
||||||
if ((amountData == NULL) ||
|
if ((amountData == NULL) ||
|
||||||
(forEscape && (dataContext.tokenContext.quantumIndex == MAX_TOKEN))) {
|
(forEscape && (dataContext.tokenContext.quantumIndex == MAX_TOKEN))) {
|
||||||
@@ -328,7 +328,7 @@ void starkware_print_amount(uint8_t *amountData, char *destination, bool forEsca
|
|||||||
|
|
||||||
// TODO : rewrite as independant code
|
// TODO : rewrite as independant code
|
||||||
void starkware_print_ticker(char *destination) {
|
void starkware_print_ticker(char *destination) {
|
||||||
char *ticker = (char *) PIC(chainConfig->coinName);
|
char *ticker = chainConfig->coinName;
|
||||||
|
|
||||||
if (dataContext.tokenContext.quantumIndex != MAX_TOKEN) {
|
if (dataContext.tokenContext.quantumIndex != MAX_TOKEN) {
|
||||||
tokenDefinition_t *token =
|
tokenDefinition_t *token =
|
||||||
|
|||||||
BIN
tests/snapshots/send/nanos/network.png
Normal file
|
After Width: | Height: | Size: 477 B |
BIN
tests/snapshots/send/nanox/network.png
Normal file
|
After Width: | Height: | Size: 585 B |
|
Before Width: | Height: | Size: 474 B After Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 382 B |
|
Before Width: | Height: | Size: 545 B After Width: | Height: | Size: 569 B |
BIN
tests/snapshots/send_bsc/nanos/network.png
Normal file
|
After Width: | Height: | Size: 449 B |
|
Before Width: | Height: | Size: 860 B After Width: | Height: | Size: 884 B |
|
Before Width: | Height: | Size: 473 B |
|
Before Width: | Height: | Size: 669 B After Width: | Height: | Size: 692 B |
BIN
tests/snapshots/send_bsc/nanox/network.png
Normal file
|
After Width: | Height: | Size: 555 B |
BIN
tests/snapshots/send_etc/nanos/accept.png
Normal file
|
After Width: | Height: | Size: 582 B |
BIN
tests/snapshots/send_etc/nanos/address_1.png
Normal file
|
After Width: | Height: | Size: 809 B |
BIN
tests/snapshots/send_etc/nanos/address_2.png
Normal file
|
After Width: | Height: | Size: 837 B |
BIN
tests/snapshots/send_etc/nanos/address_3.png
Normal file
|
After Width: | Height: | Size: 567 B |
BIN
tests/snapshots/send_etc/nanos/amount_1.png
Normal file
|
After Width: | Height: | Size: 475 B |
BIN
tests/snapshots/send_etc/nanos/amount_2.png
Normal file
|
After Width: | Height: | Size: 759 B |
BIN
tests/snapshots/send_etc/nanos/amount_3.png
Normal file
|
After Width: | Height: | Size: 479 B |
BIN
tests/snapshots/send_etc/nanos/fees.png
Normal file
|
After Width: | Height: | Size: 557 B |
BIN
tests/snapshots/send_etc/nanos/review.png
Normal file
|
After Width: | Height: | Size: 541 B |
BIN
tests/snapshots/send_etc/nanox/accept.png
Normal file
|
After Width: | Height: | Size: 667 B |
BIN
tests/snapshots/send_etc/nanox/address.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
tests/snapshots/send_etc/nanox/amount.png
Normal file
|
After Width: | Height: | Size: 869 B |
BIN
tests/snapshots/send_etc/nanox/fees.png
Normal file
|
After Width: | Height: | Size: 688 B |
BIN
tests/snapshots/send_etc/nanox/review.png
Normal file
|
After Width: | Height: | Size: 633 B |
@@ -15,14 +15,24 @@ const sim_options_nanox = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Resolve = require("path").resolve;
|
const Resolve = require("path").resolve;
|
||||||
const NANOS_ELF_PATH = Resolve("elfs/ethereum_nanos/app.elf");
|
const NANOS_ELF_PATH = Resolve("elfs/ethereum_nanos.elf");
|
||||||
const NANOX_ELF_PATH = Resolve("elfs/ethereum_nanox/app.elf");
|
const NANOX_ELF_PATH = Resolve("elfs/ethereum_nanox.elf");
|
||||||
|
|
||||||
|
const NANOS_ETH_LIB = { "Ethereum": NANOS_ELF_PATH };
|
||||||
|
const NANOX_ETH_LIB = { "Ethereum": NANOX_ELF_PATH };
|
||||||
|
|
||||||
|
const NANOS_CLONE_ELF_PATH = Resolve("elfs/ethereum_classic_nanos.elf");
|
||||||
|
const NANOX_CLONE_ELF_PATH = Resolve("elfs/ethereum_classic_nanox.elf");
|
||||||
|
|
||||||
const TIMEOUT = 1000000;
|
const TIMEOUT = 1000000;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
NANOS_ELF_PATH,
|
NANOS_ELF_PATH,
|
||||||
NANOX_ELF_PATH,
|
NANOX_ELF_PATH,
|
||||||
|
NANOS_ETH_LIB,
|
||||||
|
NANOX_ETH_LIB,
|
||||||
|
NANOS_CLONE_ELF_PATH,
|
||||||
|
NANOX_CLONE_ELF_PATH,
|
||||||
sim_options_nanos,
|
sim_options_nanos,
|
||||||
sim_options_nanox,
|
sim_options_nanox,
|
||||||
TIMEOUT,
|
TIMEOUT,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const ORIGINAL_SNAPSHOT_PATH_NANOX = ORIGINAL_SNAPSHOT_PATH_PREFIX + "nanox/";
|
|||||||
const SNAPSHOT_PATH_NANOS = SNAPSHOT_PATH_PREFIX + "nanos/";
|
const SNAPSHOT_PATH_NANOS = SNAPSHOT_PATH_PREFIX + "nanos/";
|
||||||
const SNAPSHOT_PATH_NANOX = SNAPSHOT_PATH_PREFIX + "nanox/";
|
const SNAPSHOT_PATH_NANOX = SNAPSHOT_PATH_PREFIX + "nanox/";
|
||||||
|
|
||||||
test("Transfer nanos", async () => {
|
test("Transfer Ether on Ethereum app nanos", async () => {
|
||||||
jest.setTimeout(TIMEOUT);
|
jest.setTimeout(TIMEOUT);
|
||||||
const sim = new Zemu(NANOS_ELF_PATH);
|
const sim = new Zemu(NANOS_ELF_PATH);
|
||||||
|
|
||||||
@@ -106,7 +106,103 @@ test("Transfer nanos", async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Transfer nanox", async () => {
|
test("Transfer on network 5234 on Ethereum nanos", async () => {
|
||||||
|
jest.setTimeout(TIMEOUT);
|
||||||
|
const sim = new Zemu(NANOS_ELF_PATH);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sim.start(sim_options_nanos);
|
||||||
|
|
||||||
|
let transport = await sim.getTransport();
|
||||||
|
|
||||||
|
let buffer = Buffer.from("058000002C8000003C800000010000000000000000EB44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF61818808214728080", "hex");
|
||||||
|
|
||||||
|
// Send transaction
|
||||||
|
let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer);
|
||||||
|
let filename;
|
||||||
|
|
||||||
|
await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot());
|
||||||
|
// Review tx
|
||||||
|
filename = "review.png";
|
||||||
|
await sim.snapshot(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const review = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(review).toEqual(expected_review);
|
||||||
|
|
||||||
|
// Amount 1/3
|
||||||
|
filename = "amount_1.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const amount_1 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_amount_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(amount_1).toEqual(expected_amount_1);
|
||||||
|
|
||||||
|
// Amount 2/3
|
||||||
|
filename = "amount_2.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const amount_2 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_amount_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(amount_2).toEqual(expected_amount_2);
|
||||||
|
|
||||||
|
// Amount 3/3
|
||||||
|
filename = "amount_3.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const amount_3 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_amount_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(amount_3).toEqual(expected_amount_3);
|
||||||
|
|
||||||
|
// Address 1/3
|
||||||
|
filename = "address_1.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const address_1 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_address_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(address_1).toEqual(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);
|
||||||
|
const expected_address_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(address_2).toEqual(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);
|
||||||
|
const expected_address_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(address_3).toEqual(expected_address_3);
|
||||||
|
|
||||||
|
// Network
|
||||||
|
filename = "network.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const network = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_network = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(network).toEqual(expected_network);
|
||||||
|
|
||||||
|
// Max Fees
|
||||||
|
filename = "fees.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const fees = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(fees).toEqual(expected_fees);
|
||||||
|
|
||||||
|
// Accept
|
||||||
|
filename = "accept.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const accept = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(accept).toEqual(expected_accept);
|
||||||
|
|
||||||
|
await sim.clickBoth();
|
||||||
|
|
||||||
|
await expect(tx).resolves.toEqual(
|
||||||
|
Buffer.from("08f3449bbc245669e26dd076986e11aa3117e2405ffe2ddc7a7e220f81326fbd91150515605c78119367be311345e9ff40c4e4ddb9ec0fd81f37035c3828f4c8b29000", 'hex')
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
await sim.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Transfer Ether on Ethereum nanox", async () => {
|
||||||
jest.setTimeout(TIMEOUT);
|
jest.setTimeout(TIMEOUT);
|
||||||
const sim = new Zemu(NANOX_ELF_PATH);
|
const sim = new Zemu(NANOX_ELF_PATH);
|
||||||
|
|
||||||
@@ -164,4 +260,73 @@ test("Transfer nanox", async () => {
|
|||||||
} finally {
|
} finally {
|
||||||
await sim.close();
|
await sim.close();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test("Transfer on network 5234 on Ethereum nanox", async () => {
|
||||||
|
jest.setTimeout(TIMEOUT);
|
||||||
|
const sim = new Zemu(NANOX_ELF_PATH);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sim.start(sim_options_nanox);
|
||||||
|
|
||||||
|
let transport = await sim.getTransport();
|
||||||
|
|
||||||
|
let buffer = Buffer.from("058000002C8000003C800000010000000000000000EB44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF61818808214728080", "hex");
|
||||||
|
|
||||||
|
// Send transaction
|
||||||
|
let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer);
|
||||||
|
let filename;
|
||||||
|
|
||||||
|
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);
|
||||||
|
const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(review).toEqual(expected_review);
|
||||||
|
|
||||||
|
// Amount
|
||||||
|
filename = "amount.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const amount = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const expected_amount = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(amount).toEqual(expected_amount);
|
||||||
|
|
||||||
|
// Address
|
||||||
|
filename = "address.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const address = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const expected_address = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(address).toEqual(expected_address);
|
||||||
|
|
||||||
|
// Network
|
||||||
|
filename = "network.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const network = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const expected_network = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(network).toEqual(expected_network);
|
||||||
|
|
||||||
|
// Max Fees
|
||||||
|
filename = "fees.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const fees = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(fees).toEqual(expected_fees);
|
||||||
|
|
||||||
|
// Accept
|
||||||
|
filename = "accept.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const accept = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(accept).toEqual(expected_accept);
|
||||||
|
|
||||||
|
await sim.clickBoth();
|
||||||
|
|
||||||
|
await expect(tx).resolves.toEqual(
|
||||||
|
Buffer.from("08f3449bbc245669e26dd076986e11aa3117e2405ffe2ddc7a7e220f81326fbd91150515605c78119367be311345e9ff40c4e4ddb9ec0fd81f37035c3828f4c8b29000", 'hex')
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
await sim.close();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
@@ -83,8 +83,8 @@ test("Transfer bsc nanos", async () => {
|
|||||||
const expected_address_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
const expected_address_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
expect(address_3).toEqual(expected_address_3);
|
expect(address_3).toEqual(expected_address_3);
|
||||||
|
|
||||||
// Chain ID
|
// Network name
|
||||||
filename = "chainid.png";
|
filename = "network.png";
|
||||||
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
const chainid = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
const chainid = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
const expected_chainid = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
const expected_chainid = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
@@ -151,8 +151,8 @@ test("Transfer bsc nanox", async () => {
|
|||||||
const expected_address = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
const expected_address = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
expect(address).toEqual(expected_address);
|
expect(address).toEqual(expected_address);
|
||||||
|
|
||||||
// Chain ID
|
// Network name
|
||||||
filename = "chainid.png";
|
filename = "network.png";
|
||||||
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||||
const chainid = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
const chainid = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||||
const expected_chainid = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
const expected_chainid = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
|||||||
208
tests/src/send_etc.test.js
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
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_ETH_LIB, NANOX_ETH_LIB, NANOS_CLONE_ELF_PATH, NANOX_CLONE_ELF_PATH, sim_options_nanos, sim_options_nanox, TIMEOUT} = require("generic.js");
|
||||||
|
|
||||||
|
const ORIGINAL_SNAPSHOT_PATH_PREFIX = "snapshots/send_etc/";
|
||||||
|
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("Transfer on Ethereum clone app nanos", async () => {
|
||||||
|
jest.setTimeout(TIMEOUT);
|
||||||
|
const sim = new Zemu(NANOS_CLONE_ELF_PATH, NANOS_ETH_LIB);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sim.start(sim_options_nanos);
|
||||||
|
|
||||||
|
let transport = await sim.getTransport();
|
||||||
|
|
||||||
|
let buffer = Buffer.from("058000002C8000003C800000010000000000000000EB44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF61818803D8080", "hex");
|
||||||
|
|
||||||
|
// Send transaction
|
||||||
|
let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer);
|
||||||
|
let filename;
|
||||||
|
|
||||||
|
await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot());
|
||||||
|
// Review tx
|
||||||
|
filename = "review.png";
|
||||||
|
await sim.snapshot(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const review = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(review).toEqual(expected_review);
|
||||||
|
|
||||||
|
// Amount 1/3
|
||||||
|
filename = "amount_1.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const amount_1 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_amount_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(amount_1).toEqual(expected_amount_1);
|
||||||
|
|
||||||
|
// Amount 2/3
|
||||||
|
filename = "amount_2.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const amount_2 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_amount_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(amount_2).toEqual(expected_amount_2);
|
||||||
|
|
||||||
|
// Amount 3/3
|
||||||
|
filename = "amount_3.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const amount_3 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_amount_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(amount_3).toEqual(expected_amount_3);
|
||||||
|
|
||||||
|
// Address 1/3
|
||||||
|
filename = "address_1.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const address_1 = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_address_1 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(address_1).toEqual(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);
|
||||||
|
const expected_address_2 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(address_2).toEqual(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);
|
||||||
|
const expected_address_3 = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(address_3).toEqual(expected_address_3);
|
||||||
|
|
||||||
|
// Max Fees
|
||||||
|
filename = "fees.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const fees = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(fees).toEqual(expected_fees);
|
||||||
|
|
||||||
|
// Accept
|
||||||
|
filename = "accept.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const accept = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOS + filename);
|
||||||
|
expect(accept).toEqual(expected_accept);
|
||||||
|
|
||||||
|
await sim.clickBoth();
|
||||||
|
await expect(tx).resolves.toEqual(
|
||||||
|
Buffer.from("9e52b80e10cb82f3dc8345005e3da3f9cae1fb3f2b9a5df05b7cedba786c685fed381875af27d121beaa9efd8a7450975f9d45a26ba5aa331b7a8b26bcce95e6d09000", 'hex')
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
await sim.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Transfer on network 5234 on Ethereum clone nanos", async () => {
|
||||||
|
jest.setTimeout(TIMEOUT);
|
||||||
|
const sim = new Zemu(NANOS_CLONE_ELF_PATH, NANOS_ETH_LIB);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sim.start(sim_options_nanos);
|
||||||
|
|
||||||
|
let transport = await sim.getTransport();
|
||||||
|
|
||||||
|
let buffer = Buffer.from("058000002C8000003C800000010000000000000000EB44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF61818808214728080", "hex");
|
||||||
|
|
||||||
|
// Send transaction
|
||||||
|
let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer);
|
||||||
|
|
||||||
|
await expect(tx).rejects.toEqual(new TransportStatusError(0x6a80));
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
await sim.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Transfer on Ethereum clone nanox", async () => {
|
||||||
|
jest.setTimeout(TIMEOUT);
|
||||||
|
const sim = new Zemu(NANOX_CLONE_ELF_PATH, NANOX_ETH_LIB);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sim.start(sim_options_nanox);
|
||||||
|
|
||||||
|
let transport = await sim.getTransport();
|
||||||
|
let buffer = Buffer.from("058000002C8000003C800000010000000000000000EB44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF61818803D8080", "hex");
|
||||||
|
|
||||||
|
// Send transaction
|
||||||
|
let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer);
|
||||||
|
let filename;
|
||||||
|
|
||||||
|
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);
|
||||||
|
const expected_review = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(review).toEqual(expected_review);
|
||||||
|
|
||||||
|
// Amount
|
||||||
|
filename = "amount.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const amount = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const expected_amount = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(amount).toEqual(expected_amount);
|
||||||
|
|
||||||
|
// Address
|
||||||
|
filename = "address.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const address = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const expected_address = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(address).toEqual(expected_address);
|
||||||
|
|
||||||
|
// Max Fees
|
||||||
|
filename = "fees.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const fees = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const expected_fees = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(fees).toEqual(expected_fees);
|
||||||
|
|
||||||
|
// Accept
|
||||||
|
filename = "accept.png";
|
||||||
|
await sim.clickRight(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const accept = Zemu.LoadPng2RGB(SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
const expected_accept = Zemu.LoadPng2RGB(ORIGINAL_SNAPSHOT_PATH_NANOX + filename);
|
||||||
|
expect(accept).toEqual(expected_accept);
|
||||||
|
|
||||||
|
await sim.clickBoth();
|
||||||
|
|
||||||
|
await expect(tx).resolves.toEqual(
|
||||||
|
Buffer.from("9e52b80e10cb82f3dc8345005e3da3f9cae1fb3f2b9a5df05b7cedba786c685fed381875af27d121beaa9efd8a7450975f9d45a26ba5aa331b7a8b26bcce95e6d09000", 'hex')
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
await sim.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test("Transfer on network 5234 on Ethereum clone nanox", async () => {
|
||||||
|
jest.setTimeout(TIMEOUT);
|
||||||
|
const sim = new Zemu(NANOX_CLONE_ELF_PATH, NANOX_ETH_LIB);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sim.start(sim_options_nanox);
|
||||||
|
|
||||||
|
let transport = await sim.getTransport();
|
||||||
|
|
||||||
|
let buffer = Buffer.from("058000002C8000003C800000010000000000000000EB44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF61818808214728080", "hex");
|
||||||
|
|
||||||
|
// Send transaction
|
||||||
|
let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer);
|
||||||
|
|
||||||
|
await expect(tx).rejects.toEqual(new TransportStatusError(0x6a80));
|
||||||
|
} finally {
|
||||||
|
await sim.close();
|
||||||
|
}
|
||||||
|
});
|
||||||