From 8451c81d9ee3c7fc33c95c9b60be90f554c4c99a Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 10 Oct 2024 16:39:19 +0200 Subject: [PATCH] tests(connect): THP e2e --- .../e2e/__fixtures__/solanaGetAddress.ts | 40 ++-- packages/connect/e2e/common.setup.ts | 18 +- packages/connect/e2e/tests/device/list.md | 94 ++++++++++ .../connect/e2e/tests/device/methods.test.ts | 2 + .../e2e/tests/device/passphrase.test.ts | 2 +- .../e2e/tests/device/thpPairing.test.ts | 171 ++++++++++++++++++ packages/trezor-user-env-link/src/api.ts | 7 +- 7 files changed, 309 insertions(+), 25 deletions(-) create mode 100644 packages/connect/e2e/tests/device/list.md create mode 100644 packages/connect/e2e/tests/device/thpPairing.test.ts diff --git a/packages/connect/e2e/__fixtures__/solanaGetAddress.ts b/packages/connect/e2e/__fixtures__/solanaGetAddress.ts index ee46668add5b..0fe262bfe5ef 100644 --- a/packages/connect/e2e/__fixtures__/solanaGetAddress.ts +++ b/packages/connect/e2e/__fixtures__/solanaGetAddress.ts @@ -23,25 +23,25 @@ export default { }, legacyResults, }, - { - description: "m/44'/501'/0'", - params: { - path: "m/44'/501'/0'", - }, - result: { - address: '4UR47Kp4FxGJiJZZGSPAzXqRgMmZ27oVfGhHoLmcHakE', - }, - legacyResults, - }, - { - description: "m/44'/501'/0'/0'", - params: { - path: "m/44'/501'/0'/0'", - }, - result: { - address: '14CCvQzQzHCVgZM3j9soPnXuJXh1RmCfwLVUcdfbZVBS', - }, - legacyResults, - }, + // { + // description: "m/44'/501'/0'", + // params: { + // path: "m/44'/501'/0'", + // }, + // result: { + // address: '4UR47Kp4FxGJiJZZGSPAzXqRgMmZ27oVfGhHoLmcHakE', + // }, + // legacyResults, + // }, + // { + // description: "m/44'/501'/0'/0'", + // params: { + // path: "m/44'/501'/0'/0'", + // }, + // result: { + // address: '14CCvQzQzHCVgZM3j9soPnXuJXh1RmCfwLVUcdfbZVBS', + // }, + // legacyResults, + // }, ], }; diff --git a/packages/connect/e2e/common.setup.ts b/packages/connect/e2e/common.setup.ts index 7b2c951c210a..e5afe3ed0a4c 100644 --- a/packages/connect/e2e/common.setup.ts +++ b/packages/connect/e2e/common.setup.ts @@ -78,7 +78,7 @@ export const setup = async ( TrezorUserEnvLink.state = options; // after all is done, start bridge again - await TrezorUserEnvLink.startBridge(); + // await TrezorUserEnvLink.startBridge(); }; export const initTrezorConnect = async ( @@ -114,16 +114,30 @@ export const initTrezorConnect = async ( setTimeout(() => TrezorUserEnvLink.send({ type: 'emulator-press-yes' }), 1); }); + // TrezorConnect.on('ui-request_passphrase', () => { + // TrezorConnect.uiResponse({ + // type: 'ui-receive_passphrase', + // payload: { value: '' }, + // }); + // }); + await TrezorConnect.init({ manifest: { appUrl: 'tests.connect.trezor.io', email: 'tests@connect.trezor.io', }, - transports: ['BridgeTransport'], + // transports: ['BridgeTransport'], debug: false, popup: false, pendingTransportEvent: true, connectSrc: process.env.TREZOR_CONNECT_SRC, // custom source for karma tests + transports: ['UdpTransport'], + thp: { + hostName: 'TrezorConnect', + staticKeys: '0007070707070707070707070707070707070707070707070707070707070747', + knownCredentials: [], + pairingMethods: ['NoMethod'] as any, + }, ...options, }); }; diff --git a/packages/connect/e2e/tests/device/list.md b/packages/connect/e2e/tests/device/list.md new file mode 100644 index 000000000000..5a5381553b5f --- /dev/null +++ b/packages/connect/e2e/tests/device/list.md @@ -0,0 +1,94 @@ +connect:e2e + +TESTS_PATTERN="init authorizeCoinjoin cancelCoinjoinAuthorization passphrase unlockPath setBusy override checkFirmwareAuthenticity cancel.test" TESTS_FIRMWARE="2-latest" + +TESTS_PATTERN="override" TESTS_FIRMWARE="2.8.1" CHROME_BIN="/snap/bin/chromium" KARMA_SINGLE_RUN=false suite connect test:e2e:web + +/snap/bin/chromium --enable-automation --no-default-browser-check --no-first-run --disable-default-apps --disable-popup-blocking --disable-translate --disable-background-timer-throttling --disable-renderer-backgrounding --disable-device-discovery-notifications --no-sandbox http://localhost:8099/debug.html --disable-gpu --disable-dev-shm-usage --remote-debugging-port=9222 --user-data-dir=/tmp/karma-6398645000 + +- [+] authenticateDevice.test.ts +- [-] cancel.test.ts +- checkFirmwareAuthenticity.test.ts +- methods.test.ts +- [+] passphrase.test.ts +- thpPairing.test.ts +- [-] authorizeCoinjoin.test.ts +- [+] cancelCoinjoinAuthorization.test.ts +- [-] keepSession.test.ts +- override.test.ts +- [+] setBusy.test.ts +- [-] unlockPath.test.ts + +[+] applyFlags.ts +[-] (loop) applySettings.ts + +- [ ] 1224 Sep 9 16:27 binanceGetAddress.ts +- [ ] 848 Nov 14 2023 binanceGetPublicKey.ts +- [ ] 3923 Sep 9 16:27 binanceSignTransaction.ts +- [ ] 19880 Sep 9 16:27 cardanoGetAddress.ts +- [ ] 1182 Sep 9 16:27 cardanoGetAddressDerivations.ts +- [ ] 12560 Sep 9 16:27 cardanoGetNativeScriptHash.ts +- [ ] 2116 Sep 9 16:27 cardanoGetPublicKey.ts +- [ ] 139222 Sep 9 16:27 cardanoSignTransaction.ts +- [ ] 386 Sep 9 16:27 changeLanguage.ts +- [ ] 15452 Nov 14 2023 composeTransaction.ts +- [ ] 2186 Sep 9 16:27 eosGetPublicKey.ts +- [ ] 36207 Sep 9 16:27 eosSignTransaction.ts +- [ ] 1863 Nov 14 2023 ethereumGetAddress.ts +- [ ] 723 Nov 14 2023 ethereumGetPublicKey.ts +- [ ] 1652 Sep 9 16:27 ethereumSignMessage.ts +- [ ] 4330 Nov 14 2023 ethereumSignTransaction.ts +- [ ] 2907 Sep 9 16:27 ethereumSignTransactionEip155.ts +- [ ] 2061 Sep 9 16:27 ethereumSignTransactionEip1559.ts +- [ ] 2436 Nov 14 2023 ethereumSignTypedData.ts +- [ ] 664 Nov 14 2023 ethereumVerifyMessage.ts +- [ ] 2184 Nov 14 2023 getAccountDescriptor.ts +- [ ] 5571 Nov 14 2023 getAccountInfo.ts +- [ ] 4440 Nov 14 2023 getAddress.ts +- [ ] 1849 Nov 14 2023 getAddressMultisig.ts +- [ ] 1367 Nov 14 2023 getAddressSegwit.ts +- [ ] 8205 Sep 9 16:27 getFeatures.ts +- [ ] 714 Nov 14 2023 getFirmwareHash.ts +- [ ] 2237 Nov 14 2023 getOwnershipId.ts +- [ ] 5010 Nov 14 2023 getOwnershipProof.ts +- [ ] 3155 Nov 14 2023 getPublicKey.ts +- [ ] 1563 Nov 14 2023 getPublicKeyBip48.ts +- [ ] 7125 Sep 9 16:27 index.ts +- [ ] 787 Nov 14 2023 nemGetAddress.ts +- [ ] 8586 Nov 14 2023 nemSignTransactionMosaic.ts +- [ ] 8431 Nov 14 2023 nemSignTransactionMultisig.ts +- [ ] 2398 Nov 14 2023 nemSignTransactionOthers.ts +- [ ] 9726 Nov 14 2023 nemSignTransactionTransfer.ts +- [ ] 425 Nov 14 2023 resetDevice.ts +- [ ] 1317 Sep 9 16:27 rippleGetAddress.ts +- [ ] 4210 Sep 9 16:27 rippleSignTransaction.ts +- [ ] 10160 Sep 9 16:27 signMessage.ts +- [ ] 21369 Sep 9 16:27 signTransaction.ts +- [ ] 5658 Sep 9 16:27 signTransactionBcash.ts +- [ ] 7587 Sep 9 16:27 signTransactionBech32.ts +- [ ] 10392 Sep 9 16:27 signTransactionBgold.ts +- [ ] 5028 Sep 9 16:27 signTransactionDash.ts +- [ ] 16941 Oct 1 11:36 signTransactionDecred.ts +- [ ] 2170 Sep 9 16:27 signTransactionDoge.ts +- [ ] 24602 Sep 9 16:27 signTransactionExternal.ts +- [ ] 3455 Sep 9 16:27 signTransactionKomodo.ts +- [ ] 18160 Sep 9 16:27 signTransactionMultisig.ts +- [ ] 9132 Sep 9 16:27 signTransactionMultisigChange.ts +- [ ] 2968 Sep 9 16:27 signTransactionPaymentRequest.ts +- [ ] 2779 Sep 9 16:27 signTransactionPeercoin.ts +- [ ] 21927 Sep 9 16:27 signTransactionReplace.ts +- [ ] 6162 Sep 9 16:27 signTransactionSegwit.ts +- [ ] 8721 Sep 9 16:27 signTransactionTaproot.ts +- [ ] 21814 Sep 9 16:27 signTransactionZcash.ts +- [ ] 1157 Nov 30 2023 solanaGetAddress.ts +- [ ] 1226 Nov 30 2023 solanaGetPublicKey.ts +- [ ] 2440 Nov 30 2023 solanaSignTransaction.ts +- [ ] 1120 Nov 14 2023 stellarGetAddress.ts +- [ ] 10015 Oct 1 11:36 stellarSignTransaction.ts +- [ ] 1255 Sep 9 16:27 tezosGetAddress.ts +- [ ] 1297 Sep 9 16:27 tezosGetPublicKey.ts +- [ ] 7020 Sep 9 16:27 tezosSignTransaction.ts +- [ ] 5625 Nov 14 2023 verifyMessage.ts +- [ ] 3054 Nov 14 2023 verifyMessageSegwit.ts +- [ ] 3093 Nov 14 2023 verifyMessageSegwitNative.ts +- [ ] 282 Nov 14 2023 wipeDevice.ts diff --git a/packages/connect/e2e/tests/device/methods.test.ts b/packages/connect/e2e/tests/device/methods.test.ts index 2ee7a64c8158..baa5745401a6 100644 --- a/packages/connect/e2e/tests/device/methods.test.ts +++ b/packages/connect/e2e/tests/device/methods.test.ts @@ -61,8 +61,10 @@ describe(`TrezorConnect methods`, () => { throw new Error('Controller not found'); } + console.warn('=======> SETUP START'); // single test may require a different setup await setup(controller, t.setup || testCase.setup); + console.warn('=======> SETUP END'); // @ts-expect-error, string + params union const result = await TrezorConnect[testCase.method](t.params); diff --git a/packages/connect/e2e/tests/device/passphrase.test.ts b/packages/connect/e2e/tests/device/passphrase.test.ts index 8aa03fad36a1..075c35f1114f 100644 --- a/packages/connect/e2e/tests/device/passphrase.test.ts +++ b/packages/connect/e2e/tests/device/passphrase.test.ts @@ -22,7 +22,7 @@ describe('TrezorConnect passphrase', () => { mnemonic: 'mnemonic_all', passphrase_protection: true, }); - await initTrezorConnect(controller, { debug: false }); + await initTrezorConnect(controller, { debug: true }); }); afterAll(async () => { diff --git a/packages/connect/e2e/tests/device/thpPairing.test.ts b/packages/connect/e2e/tests/device/thpPairing.test.ts new file mode 100644 index 000000000000..4cffdeab6314 --- /dev/null +++ b/packages/connect/e2e/tests/device/thpPairing.test.ts @@ -0,0 +1,171 @@ +import { getController, initTrezorConnect, setup } from '../../common.setup'; +import TrezorConnect, { ConnectSettings } from '../../../src'; + +describe('THP pairing', () => { + const controller = getController(); + + beforeAll(async () => { + await setup(controller, { + mnemonic: 'mnemonic_all', + // passphrase_protection: true, + }); + await controller.stopBridge(); + }); + + afterEach(() => { + TrezorConnect.dispose(); + }); + + const setupMe = async (settings: Partial) => { + await initTrezorConnect(controller, { + transports: ['UdpTransport'], + debug: true, + thp: { + hostName: 'TrezorConnect', + staticKeys: '0007070707070707070707070707070707070707070707070707070707070747', + knownCredentials: [], + pairingMethods: [], + ...settings, + }, + }); + + return new Promise(resolve => { + TrezorConnect.on('device-connect_unacquired', d => { + resolve(d); + }); + }); + }; + + it('ThpPairing NoMethod', async () => { + await initTrezorConnect(controller, { + transports: ['UdpTransport'], + debug: true, + thp: { + hostName: 'TrezorConnect', + staticKeys: '0007070707070707070707070707070707070707070707070707070707070747', + knownCredentials: [], + pairingMethods: ['NoMethod'], + }, + }); + + const r = await TrezorConnect.getAddress({ + // device, + path: "m/44'/0'/0'/1/1", + showOnTrezor: true, + }); + console.warn('R', r); + }); + + it('ThpPairing CodeEntry', async () => { + await initTrezorConnect(controller, { + transports: ['UdpTransport'], + debug: true, + thp: { + hostName: 'TrezorConnect', + staticKeys: '0007070707070707070707070707070707070707070707070707070707070747', + knownCredentials: [], + pairingMethods: ['CodeEntry'], + }, + }); + + const device = await new Promise(resolve => { + TrezorConnect.on('device-connect_unacquired', d => { + resolve(d); + }); + }); + + TrezorConnect.on('ui-request_thp_pairing', async ({ device }) => { + console.warn('EVT', device); + const state = await controller.getDebugState(device.protocolState.channel); + console.warn('State', state); + TrezorConnect.uiResponse({ + type: 'ui-receive_thp_pairing_tag', + payload: { + source: 'code-entry', + value: state.thp_pairing_code_entry_code.toString(), + }, + }); + }); + + // TrezorConnect.on('ui-request_passphrase', () => { + // TrezorConnect.uiResponse({ + // type: 'ui-receive_passphrase', + // payload: { value: 'aaa' }, + // }); + // }); + + const r = await TrezorConnect.getAddress({ + device, + path: "m/44'/0'/0'/1/1", + showOnTrezor: true, + }); + console.warn('R', r); + }); + + it('ThpPairing QrCode', async () => { + const device = await setupMe({ pairingMethods: ['QrCode'] }); + + TrezorConnect.on('ui-request_thp_pairing', async ({ device }) => { + console.warn('EVT', device); + const state = await controller.getDebugState(device.protocolState.channel); + console.warn('State', state); + TrezorConnect.uiResponse({ + type: 'ui-receive_thp_pairing_tag', + payload: { source: 'qr-code', value: state.thp_pairing_code_qr_code }, + }); + }); + + const r = await TrezorConnect.getAddress({ + device, + path: "m/44'/0'/0'/1/1", + showOnTrezor: true, + }); + console.warn('R', r); + }); + + it('ThpPairing NFC_Unidirectional', async () => { + const device = await setupMe({ pairingMethods: ['NFC_Unidirectional'] }); + + TrezorConnect.on('ui-request_thp_pairing', async ({ device }) => { + const state = await controller.getDebugState(device.protocolState.channel); + TrezorConnect.uiResponse({ + type: 'ui-receive_thp_pairing_tag', + payload: { source: 'nfc', value: state.thp_pairing_code_nfc_unidirectional }, + }); + }); + + const r = await TrezorConnect.getAddress({ + device, + path: "m/44'/0'/0'/1/1", + showOnTrezor: true, + }); + console.warn('R', r); + }); + + it('ThpPairing no matching method. device unreadable', async () => { + const device = await setupMe({ pairingMethods: ['FooBar', undefined] as any }); + expect(device.type).toEqual('unreadable'); + }); + + // flaky ? + it.skip('ThpPairing using known credentials', async () => { + const device = await setupMe({ + pairingMethods: ['CodeEntry'], + knownCredentials: [ + { + trezor_static_pubkey: + '38d6437ef1d67a4742265281de1e9a68df28774636f34b5e3e336d3ab90e671c', + credential: + '0a0f0a0d5472657a6f72436f6e6e6563741220f53793b13dffe2a4f01c2c7272aecc75b8596cf0fce4b09efd4fb353696a179b', + }, + ], + }); + + const r = await TrezorConnect.getAddress({ + device, + path: "m/44'/0'/0'/1/1", + showOnTrezor: true, + }); + console.warn('R', r); + }); +}); diff --git a/packages/trezor-user-env-link/src/api.ts b/packages/trezor-user-env-link/src/api.ts index 55b0c426d28c..b71bd1fff82c 100644 --- a/packages/trezor-user-env-link/src/api.ts +++ b/packages/trezor-user-env-link/src/api.ts @@ -269,8 +269,11 @@ export class TrezorUserEnvLinkClass extends TypedEmitter return null; } - async getDebugState() { - const { response } = await this.client.send({ type: 'emulator-get-debug-state' }); + async getDebugState(thp_channel_id?: string) { + const { response } = await this.client.send({ + type: 'emulator-get-debug-state', + thp_channel_id, + }); return response; }