feat: unit-test with cmocka

- Test only 1 function which is in utils2.c
    - Because is not inlude nano sdk
- Move zemu's into functional folder
    - Change path of zemu's test in CI and Makefile
This commit is contained in:
Alexandre Paillier
2022-06-28 14:38:19 +02:00
committed by Coline
parent 4eb7109b86
commit ad8334e54c
356 changed files with 573 additions and 11 deletions

18
tests/functional/.babelrc Normal file
View File

@@ -0,0 +1,18 @@
{
"plugins": [
[
"@babel/plugin-proposal-class-properties"
]
],
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
],
"@babel/preset-flow"
],
}

View File

@@ -0,0 +1,13 @@
[ignore]
<PROJECT_ROOT>/lib
[include]
[libs]
flow-typed
[lints]
[options]
[strict]

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -e
TESTS_FULL_PATH=$(dirname "$(realpath "$0")")
# FILL THESE WITH YOUR OWN SDKs PATHS
# NANOS_SDK=
# NANOX_SDK=
# list of apps required by tests that we want to build here
APPS=("ethereum" "ethereum_classic")
# list of SDKS
NANO_SDKS=("$NANOS_SDK" "$NANOX_SDK")
# list of target elf file name suffix
FILE_SUFFIXES=("nanos" "nanox")
# move to the tests directory
cd "$TESTS_FULL_PATH" || exit 1
# Do it only now since before the cd command, we might not have been inside the repository
GIT_REPO_ROOT=$(git rev-parse --show-toplevel)
TESTS_REL_PATH=$(realpath --relative-to="$GIT_REPO_ROOT" "$TESTS_FULL_PATH")
# create elfs directory if it doesn't exist
mkdir -p elfs
# move to repo's root to build apps
cd "$GIT_REPO_ROOT" || exit 1
for ((sdk_idx=0; sdk_idx < "${#NANO_SDKS[@]}"; sdk_idx++))
do
nano_sdk="${NANO_SDKS[$sdk_idx]}"
elf_suffix="${FILE_SUFFIXES[$sdk_idx]}"
echo "* Building elfs for $(basename "$nano_sdk")..."
for appname in "${APPS[@]}"
do
echo "** Building app $appname..."
make clean BOLOS_SDK="$nano_sdk"
make -j DEBUG=1 NFT_TESTING_KEY=1 BOLOS_SDK="$nano_sdk" CHAIN="$appname"
cp bin/app.elf "$TESTS_REL_PATH/elfs/${appname}_${elf_suffix}.elf"
done
done
echo "done"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,17 @@
import Zemu from "@zondax/zemu";
import fsExtra from "fs-extra";
const catchExit = async () => {
process.on("SIGINT", () => {
Zemu.stopAllEmuContainers(function () {
process.exit();
});
});
};
module.exports = async () => {
await catchExit();
await Zemu.checkAndPullImage();
await Zemu.stopAllEmuContainers();
fsExtra.emptyDirSync("snapshots/tmp")
};

View File

@@ -0,0 +1,39 @@
// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html
module.exports = {
modulePaths: ["<rootDir>/src", "<rootDir>/tests"],
moduleNameMapper: {
"^jest$": "<rootDir>/jest.js",
},
// Automatically clear mock calls and instances between every test
clearMocks: true,
// The directory where Jest should output its coverage files
coverageDirectory: "coverage",
globalSetup: "<rootDir>/globalsetup.js",
// A list of paths to directories that Jest should use to search for files in
roots: ["<rootDir>"],
runner: "jest-serial-runner",
// The test environment that will be used for testing
testEnvironment: "node",
// The glob patterns Jest uses to detect test files
testMatch: [
"**/__tests__/**/*.[jt]s?(x)",
"**/?(*.)+(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,
};

22
tests/functional/jest.js Normal file
View File

@@ -0,0 +1,22 @@
export default jest;
export const { expect, test } = global;
export const sim_options_s = {
model: "nanos",
logging: true,
start_delay: 2000,
X11: true,
custom: "",
};
export const sim_options_x = {
model: "nanox",
logging: true,
start_delay: 2000,
X11: true,
custom: "",
};
export const Resolve = require("path").resolve;
export const NANOS_ELF_PATH = Resolve("elfs/ethereum_nanos.elf");
export const NANOX_ELF_PATH = Resolve("elfs/ethereum_nanox.elf");

View File

@@ -0,0 +1,22 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _test = require("./test.fixture");
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Approve DAI tokens', (0, _test.zemu)(model, async (sim, eth) => {
const tx = eth.signTransaction("44'/60'/1'/0/0", 'F869468506A8B15E0082EBEB946B175474E89094C44DA98B954EEDEAC495271D0F80B844095EA7B30000000000000000000000007D2768DE32B0B80B7A3454C06BDAC94A69DDC7A9FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF018080');
let clicks;
if (model.letter === 'S') clicks = 8;else clicks = 6;
await (0, _test.waitForAppScreen)(sim);
await sim.navigateAndCompareSnapshots('.', model.name + '_approve_dai_tokens', [clicks, -1, 0]);
await expect(tx).resolves.toEqual({
"r": "92243511396b65a4faa735a5472ea99b3ce0f7f2338eab426206730bc0ddc57f",
"s": "161bc0f861064d840de4f4304cfd19a571017e62df7d8f70cf605c0f025593b6",
"v": "25"
});
}));
});

View File

@@ -0,0 +1,24 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _test = require("./test.fixture");
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Deposit ETH on compound, blind sign', (0, _test.zemu)(model, async (sim, eth) => {
// Enable blind-signing
await sim.navigateAndCompareSnapshots('.', model.name + '_enable_blind_signing', [-2, 0, 0, 3, 0]);
const tx = eth.signTransaction("44'/60'/1'/0/0", 'f8924685028fa6ae008306599594cc9a0b7c43dc2a5f023bb9b738e45b0ef6b06e0488016345785d8a0000b864474cf53d0000000000000000000000007d2768de32b0b80b7a3454c06bdac94a69ddc7a900000000000000000000000070bc641723fad48be2df6cf63dc6270ee2f897430000000000000000000000000000000000000000000000000000000000000000018080');
await (0, _test.waitForAppScreen)(sim);
let clicks;
if (model.letter === 'S') clicks = 8;else clicks = 6;
await sim.navigateAndCompareSnapshots('.', model.name + '_deposit_eth_compound_blind', [clicks, -1, 0]);
await expect(tx).resolves.toEqual({
"r": "b5ae3a011eb50e7d1fe9f5e6f6d91ca9f4dfca5f73805fc4866d49e72ead2f5c",
"s": "3c6e55db5925586bb58e434b58b2c04756f662131597f98c1aa2418b16992b81",
"v": "26"
});
}));
});

View File

@@ -0,0 +1,37 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _test = require("./test.fixture");
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Transfer on network 112233445566 on Ethereum', (0, _test.zemu)(model, async (sim, eth) => {
const tx = eth.signTransaction("44'/60'/1'/0/0", 'f044850306dc4200825208945a321744667052affa8386ed49e00ef223cbffc3876f9c9e7bf6181880851a21a278be8080');
await (0, _test.waitForAppScreen)(sim);
let clicks;
if (model.letter === 'S') clicks = 10;else clicks = 6;
await sim.navigateAndCompareSnapshots('.', model.name + '_transfer_112233445566_network', [clicks, -1, 0]);
await expect(tx).resolves.toEqual({
"r": "509981d8dfb66757e25ff47c009b9b5bc5db0f169473e4735f5212b144f1c069",
"s": "5db989d81025de3c846e41a9ce01a3f9fd0982e2d827f1b88ffc95d73a48d04c",
"v": "344344f19f"
});
}));
});
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Transfer on palm network on Ethereum', (0, _test.zemu)(model, async (sim, eth) => {
const tx = eth.signTransaction("44'/60'/1'/0/0", 'f044850306dc4200825208945a321744667052affa8386ed49e00ef223cbffc3876f9c9e7bf61818808502a15c308d8080');
await (0, _test.waitForAppScreen)(sim);
let clicks;
if (model.letter === 'S') clicks = 10;else clicks = 6;
await sim.navigateAndCompareSnapshots('.', model.name + '_transfer_palm_network', [clicks, -1, 0]);
await expect(tx).resolves.toEqual({
"r": "946700c4972b3da24ddaa95e590ad25a8f905da62e2bd053285a4cc17f93f490",
"s": "3698e84564e58477a49f7a9cea572ef5d672a5538db08f3ee42df5eb75a1b907",
"v": "0542b8613d"
});
}));
});

View File

@@ -0,0 +1,30 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _jest = require("../jest");
var _errors = require("@ledgerhq/errors");
var _test = require("./test.fixture");
var _zemu = _interopRequireDefault(require("@zondax/zemu"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Try to blind sign with setting disabled', (0, _test.zemu)(model, async (sim, eth) => {
// we can't use eth.signTransaction because it detects that contract data is disabled and fails early
let transport = await sim.getTransport();
let buffer = Buffer.from("058000002c8000003c800000010000000000000000f849208506fc23ac008303dc3194f650c3d88d12db855b8bf7d11be6c55a4e07dcc980a4a1712d6800000000000000000000000000000000000000000000000000000000000acbc7018080", "hex");
let tx = transport.send(0xe0, 0x04, 0x00, 0x00, buffer);
await (0, _jest.expect)(tx).rejects.toEqual(new _errors.TransportStatusError(0x6a80));
await _zemu.default.sleep(1000);
await (0, _test.waitForAppScreen)(sim);
let clicks;
if (model.letter === 'S') clicks = [1, 0];else clicks = [0];
await sim.navigateAndCompareSnapshots('.', model.name + '_try_to_blind_sign_with_setting_disabled', clicks);
}));
});

View File

@@ -0,0 +1,22 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _test = require("./test.fixture");
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Transfer eip1559', (0, _test.zemu)(model, async (sim, eth) => {
const tx = eth.signTransaction("44'/60'/0'/0/0", '02f87001018502540be4008502540be40086246139ca800094cccccccccccccccccccccccccccccccccccccccc8000c001a0e07fb8a64ea3786c9a6649e54429e2786af3ea31c6d06165346678cf8ce44f9ba00e4a0526db1e905b7164a858fd5ebd2f1759e22e6955499448bd276a6aa62830');
await (0, _test.waitForAppScreen)(sim);
let clicks;
if (model.letter === 'S') clicks = 7;else clicks = 5;
await sim.navigateAndCompareSnapshots('.', model.name + '_transfer_eip1559', [clicks, -1, 0]);
await expect(tx).resolves.toEqual({
"r": "3d6dfabc6c52374bfa34cb2c433856a0bcd9484870dd1b50249f7164a5fce052",
"s": "0548a774dd0b63930d83cb2e1a836fe3ef24444e8b758b00585d9a076c0e98a8",
"v": "01"
});
}));
});

View File

@@ -0,0 +1,65 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _zemu = _interopRequireDefault(require("@zondax/zemu"));
var _errors = require("@ledgerhq/errors");
var _test = require("./test.fixture");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Only LNX
const model = _test.nano_models[1];
{
const set_plugin = (0, _test.apdu_as_string)('e01600007401010745524331313535495f947276749ce646f68ac8c248420045cb7b5ef242432a00000000000000010001473045022100ec4377d17e8d98d424bf16b29c691bc1a010825fb5b8a35de0268a9dc22eab2402206701b016fe6718bf519d18cc12e9838e9ef898cc4c143017839023c3260b2d74');
const provide_nft_info = (0, _test.apdu_as_string)('e01400007b0101124f70656e53656120436f6c6c656374696f6e495f947276749ce646f68ac8c248420045cb7b5e0000000000000001000147304502210083e357a828f13d574b1296214a3749c194ab1df1f8a243655c053b1c72f91e0c02201ed93cfac7e87759445c4da2e4bfd6e1cf0405ea37c7293bc965948f51bef5cc');
const sign_first = (0, _test.apdu_as_string)('e004000096058000002c8000003c800000000000000000000000f901090b8520b673dd0082bcb394495f947276749ce646f68ac8c248420045cb7b5e80b8e4f242432a0000000000000000000000006cbcd73cd8e8a42844662f0a0e76d7f79afd933d000000000000000000000000c2907efcce4011c491bbeda8a0fa63ba7aab596cabf06640f8ca8fc5e0ed471b10befcdf65a33e4300000000');
const sign_more = (0, _test.apdu_as_string)('e00480008b00006a0000000064000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000043078303000000000000000000000000000000000000000000000000000000000018080');
test('[Nano ' + model.letter + '] Transfer ERC-1155', (0, _test.zemu)(model, async (sim, eth) => {
const current_screen = sim.getMainMenuSnapshot();
await (0, _test.send_apdu)(eth.transport, set_plugin);
await (0, _test.send_apdu)(eth.transport, provide_nft_info);
await (0, _test.send_apdu)(eth.transport, sign_first);
let sign_promise = (0, _test.send_apdu)(eth.transport, sign_more);
await (0, _test.waitForAppScreen)(sim, current_screen);
await sim.navigateAndCompareSnapshots('.', model.name + '_erc1155_transfer', [10, -1, 0]);
await sign_promise;
}));
test('[Nano ' + model.letter + '] Transfer ERC-1155 w/o PROVIDE_NFT_INFORMATION', (0, _test.zemu)(model, async (sim, eth) => {
const current_screen = sim.getMainMenuSnapshot();
await (0, _test.send_apdu)(eth.transport, set_plugin);
await (0, _test.send_apdu)(eth.transport, sign_first);
let sign_promise = (0, _test.send_apdu)(eth.transport, sign_more);
await (0, _test.waitForAppScreen)(sim, current_screen);
await sim.navigateAndCompareSnapshots('.', model.name + '_erc1155_transfer_wo_info', [10, -1, 0]);
await sign_promise;
}));
test('[Nano ' + model.letter + '] Transfer ERC-1155 w/o SET_PLUGIN', (0, _test.zemu)(model, async (sim, eth) => {
const current_screen = sim.getMainMenuSnapshot();
await (0, _test.send_apdu)(eth.transport, provide_nft_info);
let sign_tx = (0, _test.send_apdu)(eth.transport, sign_first);
await expect(sign_tx).rejects.toEqual(new _errors.TransportStatusError(0x6a80));
}));
}
test('[Nano ' + model.letter + '] Batch transfer ERC-1155', (0, _test.zemu)(model, async (sim, eth) => {
const set_plugin = (0, _test.apdu_as_string)('e01600007401010745524331313535495f947276749ce646f68ac8c248420045cb7b5e2eb2c2d60000000000000001000147304502210087b35cefc53fd94e25404933eb0d5ff08f20ba655d181de3b24ff0099dc3317f02204a216aa9e0b84bef6e20fcb036bd49647bf0cab66732b99b49ec277ffb682aa1');
const provide_nft_info = (0, _test.apdu_as_string)('e0140000820101194f70656e536561205368617265642053746f726566726f6e74495f947276749ce646f68ac8c248420045cb7b5e00000000000000010001473045022100c74cd613a27a9f4887210f5a3a0e12745e1ba0ab3a0d284cb6485d89c3cce4e602205a13e62a91164985cf58a838f8f531c0b91b980d206a5ba8df28270023ef93a3');
const sign_first = (0, _test.apdu_as_string)('e004000096058000002c8000003c800000000000000000000000f9020b0e850d8cfd86008301617d94495f947276749ce646f68ac8c248420045cb7b5e80b901e42eb2c2d60000000000000000000000006cbcd73cd8e8a42844662f0a0e76d7f79afd933d000000000000000000000000c2907efcce4011c491bbeda8a0fa63ba7aab596c00000000000000000000000000000000000000000000');
const sign_more_1 = (0, _test.apdu_as_string)('e004800096000000000000000000a0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001a00000000000000000000000000000000000000000000000000000000000000003abf06640f8ca8fc5e0ed471b10befcdf65a33e430000000000006a0000000064def9d99ff495856496c028c0');
const sign_more_2 = (0, _test.apdu_as_string)('e00480009689732473fcd0bbbe000000000000a30000000001abf06640f8ca8fc5e0ed471b10befcdf65a33e430000000000006a00000000640000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000010000');
const sign_more_3 = (0, _test.apdu_as_string)('e00480006100000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000043078303000000000000000000000000000000000000000000000000000000000018080');
const current_screen = sim.getMainMenuSnapshot();
await (0, _test.send_apdu)(eth.transport, set_plugin);
await (0, _test.send_apdu)(eth.transport, provide_nft_info);
await (0, _test.send_apdu)(eth.transport, sign_first);
await (0, _test.send_apdu)(eth.transport, sign_more_1);
await (0, _test.send_apdu)(eth.transport, sign_more_2);
let sign_promise = (0, _test.send_apdu)(eth.transport, sign_more_3);
await (0, _test.waitForAppScreen)(sim, current_screen);
await sim.navigateAndCompareSnapshots('.', model.name + '_erc1155_batch_transfer', [8, -1, 0]);
await sign_promise;
}));

View File

@@ -0,0 +1,45 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _zemu = _interopRequireDefault(require("@zondax/zemu"));
var _errors = require("@ledgerhq/errors");
var _test = require("./test.fixture");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// Only LNX
const model = _test.nano_models[1];
const set_plugin = (0, _test.apdu_as_string)('e01600007301010645524337323160f80121c31a0d46b5279700f9df786054aa5ee542842e0e0000000000000001000147304502202e2282d7d3ea714da283010f517af469e1d59654aaee0fc438f017aa557eaea50221008b369679381065bbe01135723a4f9adb229295017d37c4d30138b90a51cf6ab6');
const provide_nft_info = (0, _test.apdu_as_string)('e01400007001010752617269626c6560f80121c31a0d46b5279700f9df786054aa5ee500000000000000010001473045022025696986ef5f0ee2f72d9c6e41d7e2bf2e4f06373ab26d73ebe326c7fd4c7a6602210084f6b064d8750ae68ed5dd012296f37030390ec06ff534c5da6f0f4a4460af33');
const sign_first = (0, _test.apdu_as_string)('e004000096058000002c8000003c800000000000000000000000f88a0a852c3ce1ec008301f5679460f80121c31a0d46b5279700f9df786054aa5ee580b86442842e0e0000000000000000000000006cbcd73cd8e8a42844662f0a0e76d7f79afd933d000000000000000000000000c2907efcce4011c491bbeda8a0fa63ba7aab596c000000000000000000000000000000000000000000000000');
const sign_more = (0, _test.apdu_as_string)('e00480000b0000000000112999018080');
test('[Nano ' + model.letter + '] Transfer ERC-721', (0, _test.zemu)(model, async (sim, eth) => {
const current_screen = sim.getMainMenuSnapshot();
await (0, _test.send_apdu)(eth.transport, set_plugin);
await (0, _test.send_apdu)(eth.transport, provide_nft_info);
await (0, _test.send_apdu)(eth.transport, sign_first);
let sign_promise = (0, _test.send_apdu)(eth.transport, sign_more);
await (0, _test.waitForAppScreen)(sim, current_screen);
await sim.navigateAndCompareSnapshots('.', model.name + '_erc721_transfer', [8, -1, 0]);
await sign_promise;
}));
test('[Nano ' + model.letter + '] Transfer ERC-721 w/o NFT_PROVIDE_INFORMATION', (0, _test.zemu)(model, async (sim, eth) => {
const current_screen = sim.getMainMenuSnapshot();
await (0, _test.send_apdu)(eth.transport, set_plugin);
await (0, _test.send_apdu)(eth.transport, sign_first);
let sign_promise = (0, _test.send_apdu)(eth.transport, sign_more);
await (0, _test.waitForAppScreen)(sim, current_screen);
await sim.navigateAndCompareSnapshots('.', model.name + '_erc721_transfer_wo_info', [8, -1, 0]);
await sign_promise;
}));
test('[Nano ' + model.letter + '] Transfer ERC-721 w/o SET_PLUGIN', (0, _test.zemu)(model, async (sim, eth) => {
const current_screen = sim.getMainMenuSnapshot();
await (0, _test.send_apdu)(eth.transport, provide_nft_info);
let sign_tx = (0, _test.send_apdu)(eth.transport, sign_first);
await expect(sign_tx).rejects.toEqual(new _errors.TransportStatusError(0x6a80));
}));

View File

@@ -0,0 +1,46 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _test = require("./test.fixture");
var _errors = require("@ledgerhq/errors");
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Transfer Ether on Ethereum app', (0, _test.zemu)(model, async (sim, eth) => {
const tx = eth.signTransaction("44'/60'/1'/0/0", 'EB44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF6181880018080');
await (0, _test.waitForAppScreen)(sim);
let clicks;
if (model.letter === 'S') clicks = 9;else clicks = 5;
await sim.navigateAndCompareSnapshots('.', model.name + '_transfer_ethereum', [clicks, -1, 0]);
await expect(tx).resolves.toEqual({
"r": "6f389d15320f0501383526ed03de917c14212716f09a262dbc98431086a5db49",
"s": "0dc994b7b97230bb35fdf6fec2f4d8ff4cfb8bfeb2a652c364c738ff033c05dd",
"v": "26"
});
}));
});
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Transfer amount >= 2^87 Eth on Ethereum app should fail', (0, _test.zemu)(model, async (sim, eth) => {
const tx = eth.signTransaction("44'/60'/1'/0/0", 'f83f268e02cc9be5c53ea44bd43c289dcddc82520894dac17f958d2ee523a2206206994597c13d831ec7928db8b0861b8f7fe5df83cd553a829878000080018080');
await expect(tx).rejects.toEqual(new _errors.TransportStatusError(0x6807));
}));
});
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Transfer Ether on network 5234 on Ethereum app', (0, _test.zemu)(model, async (sim, eth) => {
const tx = eth.signTransaction("44'/60'/1'/0/0", 'ED44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF61818808214728080');
await (0, _test.waitForAppScreen)(sim);
let clicks;
if (model.letter === 'S') clicks = 10;else clicks = 6;
await sim.navigateAndCompareSnapshots('.', model.name + '_transfer_ethereum_5234_network', [clicks, -1, 0]);
await expect(tx).resolves.toEqual({
"r": "07a7982dfd16360c96a03467877d0cf9c36f799deff4dace250cdb18e28a3b90",
"s": "773318a93da2e32c1cf308ddd6add1e8c0d285973e541520a05fb4dc720e4fb1",
"v": "2908"
});
}));
});

View File

@@ -0,0 +1,22 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _test = require("./test.fixture");
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Transfer bsc', (0, _test.zemu)(model, async (sim, eth) => {
const tx = eth.signTransaction("44'/60'/1'/0/0", 'EB0185012A05F200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF6181880388080');
await (0, _test.waitForAppScreen)(sim);
let clicks;
if (model.letter === 'S') clicks = 10;else clicks = 6;
await sim.navigateAndCompareSnapshots('.', model.name + '_transfer_bsc', [clicks, -1, 0]);
await expect(tx).resolves.toEqual({
"r": "f667cc34e9815df4f052fb3463cdbe355fff5c1acf4e919b3539806521a059ad",
"s": "6b35492b7108d9d9e1cc7aede536ed6b3173197b56dd873cbc3b43e041d6f407",
"v": "93"
});
}));
});

View File

@@ -0,0 +1,31 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _errors = require("@ledgerhq/errors");
var _test = require("./test.fixture");
_test.nano_models.forEach(function (model) {
test("[Nano " + model.letter + "] Transfer on Ethereum clone app", (0, _test.zemu)(model, async (sim, eth) => {
const tx = eth.signTransaction("44'/60'/0'/0/0", 'EB44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF61818803D8080');
await (0, _test.waitForAppScreen)(sim);
let clicks;
if (model.letter === 'S') clicks = 9;else clicks = 5;
await sim.navigateAndCompareSnapshots('.', model.name + '_transfer_ethereum_clone', [clicks, -1, 0]);
await expect(tx).resolves.toEqual({
"r": "60df850d297e355596f87dc313a742032de4b59c5579186b3d59bdf31402fec0",
"s": "23c3a2beacabc1943d487a2e1d545e4c46c718b1e70e9d1c11a98828c9338927",
"v": "9e"
});
}, true));
});
_test.nano_models.forEach(function (model) {
test("[Nano " + model.letter + "] Transfer on network 5234 on Ethereum clone", (0, _test.zemu)(model, async (sim, eth) => {
const tx = eth.signTransaction("44'/60'/0'/0/0", 'ED44850306DC4200825208945A321744667052AFFA8386ED49E00EF223CBFFC3876F9C9E7BF61818808214728080');
await expect(tx).rejects.toEqual(new _errors.EthAppPleaseEnableContractData("Please enable Contract data on the Ethereum app Settings"));
}, true));
});

View File

@@ -0,0 +1,32 @@
"use strict";
require("core-js/stable");
require("regenerator-runtime/runtime");
var _test = require("./test.fixture");
var _erc = require("@ledgerhq/hw-app-eth/erc20");
var _bignumber = require("bignumber.js");
_test.nano_models.forEach(function (model) {
test('[Nano ' + model.letter + '] Transfer Ether on Ethereum app', (0, _test.zemu)(model, async (sim, eth) => {
// Provide USDT token info to the app
const usdt_info = (0, _erc.byContractAddressAndChainId)("0xdac17f958d2ee523a2206206994597c13d831ec7", 1);
await eth.provideERC20TokenInformation(usdt_info); // Provide Stark quantum
const quantization = new _bignumber.BigNumber(1);
await eth.starkProvideQuantum_v2("0xdac17f958d2ee523a2206206994597c13d831ec7", "erc20", quantization, null);
const tx = eth.signTransaction("44'/60'/1'/0/0", 'f8b5018a0472698b413b43200000825208940102030405060708090a0b0c0d0e0f1011121314872bd72a24874000b8842505c3d9010101010101010102020202020202020303030303030303040404040404040402ce625e94458d39dd0bf3b45a843544dd4a14b8169045a3a3d15aa564b936c500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000030d40808080');
await (0, _test.waitForAppScreen)(sim);
let clicks;
if (model.letter === 'S') clicks = 14;else clicks = 10;
await sim.navigateAndCompareSnapshots('.', model.name + '_starkware_usdt_deposit', [clicks, -1, 0]);
await expect(tx).resolves.toEqual({
"r": "14c368c0d32e399470d6113cf796c5f4cd70300766337d8b0ba71ecad21b3d52",
"s": "4207c027959e84fc2242a1f4fd955603f137ba28f67268ffc91fef5d65071b0a",
"v": "1c"
});
}));
});

View File

@@ -0,0 +1,138 @@
"use strict";
var _zemu = _interopRequireWildcard(require("@zondax/zemu"));
var _hwAppEth = _interopRequireDefault(require("@ledgerhq/hw-app-eth"));
var _utils = require("ethers/lib/utils");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const transactionUploadDelay = 60000;
async function waitForAppScreen(sim, current_screen = null) {
if (current_screen === null) current_screen = sim.getMainMenuSnapshot();
await sim.waitUntilScreenIsNot(current_screen, transactionUploadDelay);
}
const sim_options_nano = { ..._zemu.DEFAULT_START_OPTIONS,
logging: true,
X11: true,
startText: 'is ready'
};
const Resolve = require('path').resolve;
const NANOS_ELF_PATH = Resolve('elfs/ethereum_nanos.elf');
const NANOX_ELF_PATH = Resolve('elfs/ethereum_nanox.elf');
const NANOS_CLONE_ELF_PATH = Resolve("elfs/ethereum_classic_nanos.elf");
const NANOX_CLONE_ELF_PATH = Resolve("elfs/ethereum_classic_nanox.elf");
const nano_models = [{
name: 'nanos',
letter: 'S',
path: NANOS_ELF_PATH,
clone_path: NANOS_CLONE_ELF_PATH
}, {
name: 'nanox',
letter: 'X',
path: NANOX_ELF_PATH,
clone_path: NANOX_CLONE_ELF_PATH
}];
const TIMEOUT = 1000000; // useful to take an apdu as a hex string and convert its JS representation
function apdu_as_string(str) {
let buffer = [];
for (let i = 0; i < str.length; i += 2) {
const str_extract = str.substring(i, i + 2);
buffer[i / 2] = parseInt(str_extract, 16);
}
return {
cla: buffer[0],
ins: buffer[1],
p1: buffer[2],
p2: buffer[3],
data: Buffer.from(buffer.slice(5))
};
}
async function send_apdu(ts, apdu) {
return ts.send(apdu.cla, apdu.ins, apdu.p1, apdu.p2, apdu.data);
} // Generates a serializedTransaction from a rawHexTransaction copy pasted from etherscan.
function txFromEtherscan(rawTx) {
// Remove 0x prefix
rawTx = rawTx.slice(2);
let txType = rawTx.slice(0, 2);
if (txType == "02" || txType == "01") {
// Remove "02" prefix
rawTx = rawTx.slice(2);
} else {
txType = "";
}
let decoded = _utils.RLP.decode("0x" + rawTx);
if (txType != "") {
decoded = decoded.slice(0, decoded.length - 3); // remove v, r, s
} else {
decoded[decoded.length - 1] = "0x"; // empty
decoded[decoded.length - 2] = "0x"; // empty
decoded[decoded.length - 3] = "0x01"; // chainID 1
} // Encode back the data, drop the '0x' prefix
let encoded = _utils.RLP.encode(decoded).slice(2); // Don't forget to prepend the txtype
return txType + encoded;
}
function zemu(device, func, start_clone = false) {
return async () => {
jest.setTimeout(TIMEOUT);
let elf_path;
let lib_elf;
if (start_clone) {
elf_path = device.clone_path;
lib_elf = {
'Ethereum': device.path
};
} else {
elf_path = device.path;
}
const sim = new _zemu.default(elf_path, lib_elf);
try {
await sim.start({ ...sim_options_nano,
model: device.name
});
const transport = await sim.getTransport();
await func(sim, new _hwAppEth.default(transport));
} finally {
await sim.close();
}
};
}
module.exports = {
zemu,
waitForAppScreen,
sim_options_nano,
nano_models,
TIMEOUT,
txFromEtherscan,
apdu_as_string,
send_apdu
};

View File

@@ -0,0 +1,41 @@
{
"name": "swap-test",
"version": "1.0.0",
"description": "",
"main": "test.js",
"scripts": {
"build": "babel src/ -d lib/",
"prepublish": "yarn run build",
"test": "jest src --verbose --runInBand --detectOpenHandles"
},
"author": "",
"license": "ISC",
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@ledgerhq/hw-app-eth": "^6.5.0",
"@ledgerhq/hw-transport-http": "^4.74.2",
"@ledgerhq/logs": "^5.50.0",
"@zondax/zemu": "^0.27.4",
"bignumber.js": "^9.0.0",
"bip32-path": "^0.4.2",
"core-js": "^3.7.0",
"ethereum-tx-decoder": "^3.0.0",
"ethers": "^5.5.1",
"fs-extra": "^10.0.0",
"google-protobuf": "^3.11.0",
"jest-serial-runner": "^1.1.0",
"js-sha256": "^0.9.0",
"regenerator-runtime": "^0.13.7",
"secp256k1": "^3.7.1"
},
"devDependencies": {
"@babel/cli": "^7.7.0",
"@babel/core": "^7.7.2",
"@babel/preset-env": "^7.7.1",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-stage-0": "^7.0.0",
"@babel/register": "^7.7.0",
"flow-bin": "^0.112.0",
"jest": "^26.6.3"
}
}

View 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
}
}
},
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

View File

@@ -0,0 +1 @@
00007.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

View File

@@ -0,0 +1 @@
00007.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 359 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 391 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

View File

@@ -0,0 +1 @@
00013.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

View File

@@ -0,0 +1 @@
00009.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

Some files were not shown because too many files have changed in this diff Show More