UNPKG

@ledgerhq/live-common

Version:
874 lines • 37.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.shareViewKey = exports.exportUfvk = exports.verifyAmountsAndRejectSwap = exports.verifyAmountsAndAcceptSwapForDifferentSeed = exports.verifyAmountsAndAcceptSwap = exports.expectValidAddressDevice = exports.providePublicKey = exports.goToSettings = exports.activateContractData = exports.activateExpertMode = exports.activateLedgerSync = exports.removeMemberLedgerSync = exports.pressUntilTextFound = exports.specs = void 0; exports.setExchangeDependencies = setExchangeDependencies; exports.startSpeculos = startSpeculos; exports.stopSpeculos = stopSpeculos; exports.getSpeculosAddress = getSpeculosAddress; exports.retryAxiosRequest = retryAxiosRequest; exports.waitFor = waitFor; exports.fetchCurrentScreenTexts = fetchCurrentScreenTexts; exports.getDeviceLabelCoordinates = getDeviceLabelCoordinates; exports.fetchAllEvents = fetchAllEvents; exports.containsSubstringInEvent = containsSubstringInEvent; exports.takeScreenshot = takeScreenshot; exports.waitForTimeOut = waitForTimeOut; exports.getDeviceLabels = getDeviceLabels; exports.signSendTransaction = signSendTransaction; exports.getSendEvents = getSendEvents; exports.signDelegationTransaction = signDelegationTransaction; exports.getDelegateEvents = getDelegateEvents; const invariant_1 = __importDefault(require("invariant")); const logs_1 = require("@ledgerhq/logs"); const speculos_1 = require("../load/speculos"); const speculosCI_1 = require("./speculosCI"); const devices_1 = require("@ledgerhq/devices"); const axios_1 = __importDefault(require("axios")); const live_env_1 = require("@ledgerhq/live-env"); const currencies_1 = require("../currencies"); const DeviceLabels_1 = require("./enum/DeviceLabels"); const Account_1 = require("./enum/Account"); const Currency_1 = require("./enum/Currency"); const expect_1 = __importDefault(require("expect")); const bitcoin_1 = require("./families/bitcoin"); const evm_1 = require("./families/evm"); const polkadot_1 = require("./families/polkadot"); const algorand_1 = require("./families/algorand"); const tron_1 = require("./families/tron"); const stellar_1 = require("./families/stellar"); const cardano_1 = require("./families/cardano"); const xrp_1 = require("./families/xrp"); const aptos_1 = require("./families/aptos"); const hedera_1 = require("./families/hedera"); const near_1 = require("./families/near"); const cosmos_1 = require("./families/cosmos"); const kaspa_1 = require("./families/kaspa"); const solana_1 = require("./families/solana"); const tezos_1 = require("./families/tezos"); const celo_1 = require("./families/celo"); const multiversX_1 = require("./families/multiversX"); const osmosis_1 = require("./families/osmosis"); const deviceLabelsData_1 = require("./data/deviceLabelsData"); const sui_1 = require("./families/sui"); const speculosAppVersion_1 = require("./speculosAppVersion"); const TouchDeviceSimulator_1 = require("./deviceInteraction/TouchDeviceSimulator"); const DeviceController_1 = require("./deviceInteraction/DeviceController"); const _1 = require("."); const vechain_1 = require("./families/vechain"); const deviceCoordinates_1 = require("./deviceCoordinates"); const internet_computer_1 = require("./families/internet_computer"); const isSpeculosRemote = process.env.REMOTE_SPECULOS === "true"; function setExchangeDependencies(dependencies) { const map = new Map(); for (const dep of dependencies) { if (!map.has(dep.name)) { map.set(dep.name, dep); } } exports.specs["Exchange"].dependencies = Array.from(map.values()); } exports.specs = { Bitcoin: { currency: (0, currencies_1.getCryptoCurrencyById)("bitcoin"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Bitcoin", }, dependencies: [], }, Aptos: { currency: (0, currencies_1.getCryptoCurrencyById)("aptos"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Aptos", }, dependencies: [], }, Exchange: { appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Exchange", }, dependencies: [], }, LedgerSync: { appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Ledger Sync", }, dependencies: [], }, Dogecoin: { currency: (0, currencies_1.getCryptoCurrencyById)("dogecoin"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Dogecoin", }, dependencies: [], }, Ethereum: { currency: (0, currencies_1.getCryptoCurrencyById)("ethereum"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Ethereum", }, dependencies: [], }, Ethereum_Sepolia: { currency: (0, currencies_1.getCryptoCurrencyById)("ethereum_sepolia"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Ethereum", }, dependencies: [], }, Ethereum_Classic: { currency: (0, currencies_1.getCryptoCurrencyById)("ethereum_classic"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Ethereum Classic", }, dependencies: [{ name: "Ethereum" }], }, Bitcoin_Testnet: { currency: (0, currencies_1.getCryptoCurrencyById)("bitcoin_testnet"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Bitcoin Test", }, dependencies: [], }, Solana: { currency: (0, currencies_1.getCryptoCurrencyById)("solana"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Solana", }, dependencies: [], }, Cardano: { currency: (0, currencies_1.getCryptoCurrencyById)("cardano"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "CardanoADA", }, dependencies: [], }, Polkadot: { currency: (0, currencies_1.getCryptoCurrencyById)("polkadot"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Polkadot", }, dependencies: [], }, Tron: { currency: (0, currencies_1.getCryptoCurrencyById)("tron"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Tron", }, dependencies: [], }, XRP: { currency: (0, currencies_1.getCryptoCurrencyById)("ripple"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "XRP", }, dependencies: [], }, Stellar: { currency: (0, currencies_1.getCryptoCurrencyById)("stellar"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Stellar", }, dependencies: [], }, Bitcoin_Cash: { currency: (0, currencies_1.getCryptoCurrencyById)("bitcoin_cash"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Bitcoin Cash", }, dependencies: [], }, Algorand: { currency: (0, currencies_1.getCryptoCurrencyById)("algorand"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Algorand", }, dependencies: [], }, Cosmos: { currency: (0, currencies_1.getCryptoCurrencyById)("cosmos"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Cosmos", }, dependencies: [], }, Tezos: { currency: (0, currencies_1.getCryptoCurrencyById)("tezos"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "TezosWallet", }, dependencies: [], }, Polygon: { currency: (0, currencies_1.getCryptoCurrencyById)("polygon"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Ethereum", }, dependencies: [], }, BNB_Chain: { currency: (0, currencies_1.getCryptoCurrencyById)("bsc"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Ethereum", }, dependencies: [], }, Ton: { currency: (0, currencies_1.getCryptoCurrencyById)("ton"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "TON", }, dependencies: [], }, Near: { currency: (0, currencies_1.getCryptoCurrencyById)("near"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "NEAR", }, dependencies: [], }, Multivers_X: { currency: (0, currencies_1.getCryptoCurrencyById)("elrond"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "MultiversX", }, dependencies: [], }, Osmosis: { currency: (0, currencies_1.getCryptoCurrencyById)("osmo"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Cosmos", }, dependencies: [], }, Injective: { currency: (0, currencies_1.getCryptoCurrencyById)("injective"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Cosmos", }, dependencies: [], }, Celo: { currency: (0, currencies_1.getCryptoCurrencyById)("celo"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Celo", }, dependencies: [], }, Litecoin: { currency: (0, currencies_1.getCryptoCurrencyById)("litecoin"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Litecoin", }, dependencies: [], }, Kaspa: { currency: (0, currencies_1.getCryptoCurrencyById)("kaspa"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Kaspa", }, dependencies: [], }, Hedera: { currency: (0, currencies_1.getCryptoCurrencyById)("hedera"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Hedera", }, dependencies: [], }, Sui: { currency: (0, currencies_1.getCryptoCurrencyById)("sui"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Sui", }, dependencies: [], }, Base: { currency: (0, currencies_1.getCryptoCurrencyById)("base"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Ethereum", }, dependencies: [], }, Vechain: { currency: (0, currencies_1.getCryptoCurrencyById)("vechain"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Vechain", }, dependencies: [], }, Zcash: { currency: (0, currencies_1.getCryptoCurrencyById)("zcash"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Zcash", }, dependencies: [], }, Aleo: { currency: (0, currencies_1.getCryptoCurrencyById)("aleo"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "Aleo", }, dependencies: [], }, Internet_Computer: { currency: (0, currencies_1.getCryptoCurrencyById)("internet_computer"), appQuery: { model: (0, speculosAppVersion_1.getSpeculosModel)(), appName: "InternetComputer", }, dependencies: [], }, }; async function startSpeculos(testName, spec) { (0, logs_1.log)("engine", `test ${testName}`); const { SEED, COINAPPS } = process.env; const seed = SEED; (0, invariant_1.default)(seed, "SEED is not set"); const coinapps = COINAPPS; (0, invariant_1.default)(coinapps, "COINAPPS is not set"); const appCandidates = await (0, speculos_1.listAppCandidates)(coinapps); const nanoAppCatalogPath = (0, live_env_1.getEnv)("E2E_NANO_APP_VERSION_PATH"); const { appQuery, onSpeculosDeviceCreated } = spec; try { const displayName = spec.currency?.managerAppName || appQuery.appName; const catalogVersion = await (0, speculosAppVersion_1.getAppVersionFromCatalog)(displayName, nanoAppCatalogPath); if (catalogVersion) { appQuery.appVersion = catalogVersion; } } catch (e) { console.warn("[speculos] Unable to fetch app version from catalog", e); } const appCandidate = (0, speculos_1.findLatestAppCandidate)(appCandidates, appQuery); const { model } = appQuery; const { dependencies } = spec; const newAppQuery = dependencies?.map(dep => { return (0, speculos_1.findLatestAppCandidate)(appCandidates, { model, appName: dep.name, firmware: appCandidate?.firmware, }); }); const appVersionMap = new Map(newAppQuery?.map(app => [app?.appName, app?.appVersion])); dependencies?.forEach(dependency => { dependency.appVersion = appVersionMap.get(dependency.name) || "1.0.0"; }); if (!appCandidate) { console.warn("no app found for " + testName); console.warn(appQuery); } (0, invariant_1.default)(appCandidate, "%s: no app found. Are you sure your COINAPPS is up to date?", testName, coinapps); (0, logs_1.log)("engine", `test ${testName} will use ${appCandidate.appName} ${appCandidate.appVersion} on ${appCandidate.model} ${appCandidate.firmware}`); const deviceParams = { ...appCandidate, appName: spec.currency ? spec.currency.managerAppName : spec.appQuery.appName, seed, dependencies, coinapps, onSpeculosDeviceCreated, }; try { return isSpeculosRemote ? await (0, speculosCI_1.createSpeculosDeviceCI)(deviceParams) : await (0, speculos_1.createSpeculosDevice)(deviceParams).then(device => { (0, invariant_1.default)(device.ports.apiPort, "[E2E] Speculos apiPort is not defined"); return { id: device.id, port: device.ports.apiPort, appName: deviceParams.appName, appVersion: deviceParams.appVersion, dependencies: deviceParams.dependencies, }; }); } catch (e) { console.error((0, _1.sanitizeError)(e)); (0, logs_1.log)("engine", `test ${testName} failed with ${String(e)}`); } } async function stopSpeculos(deviceId) { if (deviceId) { (0, logs_1.log)("engine", `test ${deviceId} finished`); isSpeculosRemote ? await (0, speculosCI_1.releaseSpeculosDeviceCI)(deviceId) : await (0, speculos_1.releaseSpeculosDevice)(deviceId); } } function getSpeculosAddress() { const speculosAddress = process.env.SPECULOS_ADDRESS; return speculosAddress || "http://127.0.0.1"; } async function retryAxiosRequest(requestFn, maxRetries = 5, baseDelay = 1000, retryableStatusCodes = [500, 502, 503, 504]) { let lastError; for (let attempt = 0; attempt <= maxRetries; attempt++) { try { return await requestFn(); } catch (error) { lastError = error; const isRetryable = axios_1.default.isAxiosError(error) && error.response && retryableStatusCodes.includes(error.response.status); const isNetworkError = axios_1.default.isAxiosError(error) && !error.response; if ((isRetryable || isNetworkError) && attempt < maxRetries) { const delay = baseDelay * (attempt + 1); console.warn(`Axios request failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms...`, { status: axios_1.default.isAxiosError(error) ? error.response?.status : "network error", message: error.message, }); await new Promise(resolve => setTimeout(resolve, delay)); continue; } throw lastError; } } throw lastError; } async function waitFor(text, maxAttempts = 60) { const port = (0, live_env_1.getEnv)("SPECULOS_API_PORT"); let texts = ""; for (let attempt = 0; attempt < maxAttempts; attempt++) { texts = await fetchCurrentScreenTexts(port); if (texts.toLowerCase().includes(text.toLowerCase())) { return texts; } await waitForTimeOut(500); } throw new Error(`Text "${text}" not found on device screen after ${maxAttempts} attempts. Last screen text: "${texts}"`); } async function fetchCurrentScreenTexts(speculosApiPort) { const speculosAddress = getSpeculosAddress(); const response = await retryAxiosRequest(() => axios_1.default.get(`${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=true`)); return response.data.events.map(event => event.text).join(" "); } async function getDeviceLabelCoordinates(label, speculosApiPort) { const speculosAddress = getSpeculosAddress(); const response = await retryAxiosRequest(() => axios_1.default.get(`${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=true`)); const event = response.data.events.find(e => e.text === label); if (!event) { throw new Error(`Label "${label}" not found in screen events`); } return { x: event.x, y: event.y }; } async function fetchAllEvents(speculosApiPort) { const speculosAddress = getSpeculosAddress(); const response = await retryAxiosRequest(() => axios_1.default.get(`${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=false`)); return response.data.events.map(event => event.text); } exports.pressUntilTextFound = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async (targetText, strictMatch = false) => { const maxAttempts = 18; const speculosApiPort = (0, live_env_1.getEnv)("SPECULOS_API_PORT"); const buttons = getButtonsController(); for (let attempts = 0; attempts < maxAttempts; attempts++) { const texts = await fetchCurrentScreenTexts(speculosApiPort); if (strictMatch ? texts === targetText : texts.toLowerCase().includes(targetText.toLowerCase())) { return await fetchAllEvents(speculosApiPort); } if ((0, speculosAppVersion_1.isTouchDevice)()) { await (0, TouchDeviceSimulator_1.swipeRight)(); } else { await buttons.right(); } await waitForTimeOut(200); } throw new Error(`ElementNotFoundException: Element with text "${targetText}" not found on speculos screen`); }); function containsSubstringInEvent(targetString, events) { const concatenatedEvents = events.join(""); let result = concatenatedEvents.includes(targetString); if (!result) { const regexPattern = targetString.split("").join(".*?"); const regex = new RegExp(regexPattern, "s"); result = regex.test(concatenatedEvents); } return result; } async function takeScreenshot(port) { const speculosAddress = getSpeculosAddress(); const speculosApiPort = port ?? (0, live_env_1.getEnv)("SPECULOS_API_PORT"); try { const response = await retryAxiosRequest(() => axios_1.default.get(`${speculosAddress}:${speculosApiPort}/screenshot`, { responseType: "arraybuffer", })); return response.data; } catch (error) { console.error("Error downloading speculos screenshot:", (0, _1.sanitizeError)(error)); } } async function waitForTimeOut(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } exports.removeMemberLedgerSync = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async () => { const buttons = getButtonsController(); await waitFor(DeviceLabels_1.DeviceLabels.CONNECT_TO); if ((0, speculosAppVersion_1.isTouchDevice)()) { await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.CONNECT); await waitFor(DeviceLabels_1.DeviceLabels.REMOVE_FROM_LEDGER_SYNC); await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.REMOVE); await waitFor(DeviceLabels_1.DeviceLabels.CONFIRM_CHANGE); await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.TAP_TO_CONTINUE); await waitFor(DeviceLabels_1.DeviceLabels.TURN_ON_SYNC); await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.LEDGER_WALLET_WILL_BE); await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.TURN_ON_SYNC); const turnOnSyncCoordinates = (0, deviceCoordinates_1.getDeviceCoordinates)("turnOnSync"); await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.TURN_ON_SYNC, turnOnSyncCoordinates.x, turnOnSyncCoordinates.y); } else { await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.CONNECT, true); await buttons.both(); await waitFor(DeviceLabels_1.DeviceLabels.REMOVE_FROM_LEDGER_SYNC); await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.REMOVE, true); await buttons.both(); await waitFor(DeviceLabels_1.DeviceLabels.TURN_ON_SYNC); await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.LEDGER_WALLET_WILL_BE); await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.TURN_ON_SYNC); await buttons.both(); } }); exports.activateLedgerSync = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async () => { const buttons = getButtonsController(); await waitFor(DeviceLabels_1.DeviceLabels.CONNECT_TO); if ((0, speculosAppVersion_1.isTouchDevice)()) { await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.CONNECT); } else { await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.CONNECT_TO_LEDGER_SYNC); await buttons.right(); await buttons.both(); } await waitFor(DeviceLabels_1.DeviceLabels.TURN_ON_SYNC); if ((0, speculosAppVersion_1.isTouchDevice)()) { const turnOnSyncCoordinates = (0, deviceCoordinates_1.getDeviceCoordinates)("turnOnSync"); await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.TURN_ON_SYNC, turnOnSyncCoordinates.x, turnOnSyncCoordinates.y); } else { await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.LEDGER_WALLET_WILL_BE); await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.TURN_ON_SYNC); await buttons.both(); } }); exports.activateExpertMode = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async () => { const buttons = getButtonsController(); if ((0, speculosAppVersion_1.isTouchDevice)()) { await (0, exports.goToSettings)(); const settingsToggle1Coords = (0, deviceCoordinates_1.getDeviceCoordinates)("settingsToggle1"); await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.SETTINGS_TOGGLE_1, settingsToggle1Coords.x, settingsToggle1Coords.y); } else { await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.EXPERT_MODE); await buttons.both(); } }); exports.activateContractData = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async () => { const buttons = getButtonsController(); await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.SETTINGS); await buttons.both(); await waitFor(DeviceLabels_1.DeviceLabels.CONTRACT_DATA); await buttons.both(); }); exports.goToSettings = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async () => { const buttons = getButtonsController(); if ((0, speculosAppVersion_1.isTouchDevice)()) { const settingsCogwheelCoords = (0, deviceCoordinates_1.getDeviceCoordinates)("settingsCogwheel"); await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.SETTINGS, settingsCogwheelCoords.x, settingsCogwheelCoords.y); } else { await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.SETTINGS); await buttons.both(); } }); exports.providePublicKey = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async () => { const buttons = getButtonsController(); await buttons.right(); }); function getDeviceLabels(appInfo) { const deviceModel = (0, speculosAppVersion_1.getSpeculosModel)(); const deviceConfig = deviceLabelsData_1.DEVICE_LABELS_CONFIG[deviceModel] ?? deviceLabelsData_1.DEVICE_LABELS_CONFIG.default; if (!deviceConfig) { throw new Error(`No device configuration found for ${deviceModel}`); } const receiveVerifyLabel = deviceConfig.receiveVerify[appInfo.name] ?? deviceConfig.receiveVerify.default; const receiveConfirmLabel = deviceConfig.receiveConfirm[appInfo.name] ?? deviceConfig.receiveConfirm.default; const delegateVerifyLabel = deviceConfig.delegateVerify[appInfo.name] ?? deviceConfig.delegateVerify.default; const delegateConfirmLabel = deviceConfig.delegateConfirm[appInfo.name] ?? deviceConfig.delegateConfirm.default; const sendVerifyLabel = deviceConfig.sendVerify[appInfo.name] ?? deviceConfig.sendVerify.default; const sendConfirmLabel = deviceConfig.sendConfirm[appInfo.name] ?? deviceConfig.sendConfirm.default; return { receiveVerifyLabel, receiveConfirmLabel, delegateVerifyLabel, delegateConfirmLabel, sendVerifyLabel, sendConfirmLabel, }; } exports.expectValidAddressDevice = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async (account, addressDisplayed) => { const buttons = getButtonsController(); if (account.currency === Currency_1.Currency.SUI_USDC) { await (0, exports.providePublicKey)(); } const { receiveVerifyLabel, receiveConfirmLabel } = getDeviceLabels(account.currency.speculosApp); await waitFor(receiveVerifyLabel); if ((0, speculosAppVersion_1.isTouchDevice)()) { const events = await (0, exports.pressUntilTextFound)(receiveConfirmLabel); const isAddressCorrect = containsSubstringInEvent(addressDisplayed, events); (0, expect_1.default)(isAddressCorrect).toBeTruthy(); await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.CONFIRM); } else { const events = await (0, exports.pressUntilTextFound)(receiveConfirmLabel); const isAddressCorrect = containsSubstringInEvent(addressDisplayed, events); (0, expect_1.default)(isAddressCorrect).toBeTruthy(); await buttons.both(); } }); async function signSendTransaction(tx) { const currencyId = tx.accountToDebit.currency.id; switch (currencyId) { case Currency_1.Currency.sepETH.id: case Currency_1.Currency.BASE.id: case Currency_1.Currency.POL.id: case Currency_1.Currency.ETH.id: case Currency_1.Currency.ETH_USDT.id: await (0, evm_1.sendEVM)(tx); break; case Currency_1.Currency.BTC.id: await (0, bitcoin_1.sendBTC)(tx); break; case Currency_1.Currency.DOGE.id: case Currency_1.Currency.BCH.id: case Currency_1.Currency.ZEC.id: await (0, bitcoin_1.sendBTCBasedCoin)(tx); break; case Currency_1.Currency.DOT.id: await (0, polkadot_1.sendPolkadot)(tx); break; case Currency_1.Currency.ALGO.id: await (0, algorand_1.sendAlgorand)(tx); break; case Currency_1.Currency.SOL.id: case Currency_1.Currency.SOL_GIGA.id: await (0, solana_1.sendSolana)(tx); break; case Currency_1.Currency.TRX.id: await (0, tron_1.sendTron)(tx); break; case Currency_1.Currency.XLM.id: await (0, stellar_1.sendStellar)(tx); break; case Currency_1.Currency.ATOM.id: await (0, cosmos_1.sendCosmos)(tx); break; case Currency_1.Currency.ADA.id: await (0, cardano_1.sendCardano)(tx); break; case Currency_1.Currency.XRP.id: await (0, xrp_1.sendXRP)(tx); break; case Currency_1.Currency.APT.id: await (0, aptos_1.sendAptos)(tx); break; case Currency_1.Currency.KAS.id: await (0, kaspa_1.sendKaspa)(tx); break; case Currency_1.Currency.HBAR.id: await (0, hedera_1.sendHedera)(); break; case Currency_1.Currency.SUI.id: case Currency_1.Currency.SUI_USDC.id: await (0, sui_1.sendSui)(tx); break; case Currency_1.Currency.VET.id: await (0, vechain_1.sendVechain)(tx); break; case Currency_1.Currency.ICP.id: await (0, internet_computer_1.sendInternetComputer)(tx); break; default: throw new Error(`Unsupported currency: ${tx.accountToDebit.currency.ticker}`); } } async function getSendEvents(tx) { const { sendVerifyLabel, sendConfirmLabel } = getDeviceLabels(tx.accountToDebit.currency.speculosApp); await waitFor(sendVerifyLabel); return await (0, exports.pressUntilTextFound)(sendConfirmLabel); } async function signDelegationTransaction(delegatingAccount) { const currencyName = delegatingAccount.account.currency.name; switch (currencyName) { case Account_1.Account.SOL_1.currency.name: await (0, solana_1.delegateSolana)(delegatingAccount); break; case Account_1.Account.NEAR_1.currency.name: await (0, near_1.delegateNear)(delegatingAccount); break; case Account_1.Account.ATOM_1.currency.name: case Account_1.Account.INJ_1.currency.name: await (0, cosmos_1.delegateCosmos)(delegatingAccount); break; case Account_1.Account.OSMO_1.currency.name: await (0, osmosis_1.delegateOsmosis)(delegatingAccount); break; case Account_1.Account.MULTIVERS_X_1.currency.name: await (0, multiversX_1.delegateMultiversX)(delegatingAccount); break; case Account_1.Account.ADA_1.currency.name: await (0, cardano_1.delegateCardano)(); break; case Account_1.Account.XTZ_1.currency.name: await (0, tezos_1.delegateTezos)(delegatingAccount); break; case Account_1.Account.CELO_1.currency.name: await (0, celo_1.delegateCelo)(delegatingAccount); break; case Account_1.Account.APTOS_1.currency.name: await (0, aptos_1.delegateAptos)(delegatingAccount); break; default: throw new Error(`Unsupported currency: ${currencyName}`); } } async function getDelegateEvents(delegatingAccount) { const { delegateVerifyLabel, delegateConfirmLabel } = getDeviceLabels(delegatingAccount.account.currency.speculosApp); await waitFor(delegateVerifyLabel); return await (0, exports.pressUntilTextFound)(delegateConfirmLabel); } exports.verifyAmountsAndAcceptSwap = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async (swap, amount) => { const buttons = getButtonsController(); await waitFor(DeviceLabels_1.DeviceLabels.REVIEW_TRANSACTION); const events = (0, speculosAppVersion_1.getSpeculosModel)() === devices_1.DeviceModelId.nanoS ? await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.ACCEPT_AND_SEND) : await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.SIGN_TRANSACTION); verifySwapData(swap, events, amount); if ((0, speculosAppVersion_1.isTouchDevice)()) { await (0, TouchDeviceSimulator_1.longPressAndRelease)(DeviceLabels_1.DeviceLabels.HOLD_TO_SIGN, 3); } else { await buttons.both(); } }); exports.verifyAmountsAndAcceptSwapForDifferentSeed = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async (swap, amount, errorMessage) => { const buttons = getButtonsController(); if (errorMessage === null) { if ((0, speculosAppVersion_1.isTouchDevice)()) { await waitFor(DeviceLabels_1.DeviceLabels.RECEIVE_ADDRESS_DOES_NOT_BELONG); await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.CONTINUE_ANYWAY); } else { await waitFor(DeviceLabels_1.DeviceLabels.REVIEW_TRANSACTION); await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.RECEIVE_ADDRESS_DOES_NOT_BELONG); await buttons.both(); } } else { await waitFor(DeviceLabels_1.DeviceLabels.REVIEW_TRANSACTION); } const events = await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.SIGN_TRANSACTION); verifySwapData(swap, events, amount); if ((0, speculosAppVersion_1.isTouchDevice)()) { await (0, TouchDeviceSimulator_1.longPressAndRelease)(DeviceLabels_1.DeviceLabels.HOLD_TO_SIGN, 3); } else { await buttons.both(); } }); exports.verifyAmountsAndRejectSwap = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async (swap, amount) => { const buttons = getButtonsController(); await waitFor(DeviceLabels_1.DeviceLabels.REVIEW_TRANSACTION); let events = []; if ((0, speculosAppVersion_1.isTouchDevice)()) { events = await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.HOLD_TO_SIGN); } else { events = await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.REJECT); } verifySwapData(swap, events, amount); if ((0, speculosAppVersion_1.isTouchDevice)()) { await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.REJECT); await waitFor(DeviceLabels_1.DeviceLabels.YES_REJECT); await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.YES_REJECT); } else { await buttons.both(); } }); function verifySwapData(swap, events, amount) { const swapPair = `swap ${swap.getAccountToDebit.currency.ticker} to ${swap.getAccountToCredit.currency.ticker}`; if ((0, speculosAppVersion_1.getSpeculosModel)() !== devices_1.DeviceModelId.nanoS) { expectDeviceScreenContains(swapPair, events, "Swap pair not found on the device screen"); } expectDeviceScreenContains(amount, events, `Amount ${amount} not found on the device screen`); } function expectDeviceScreenContains(substring, events, message) { const found = containsSubstringInEvent(substring, events); if (!found) { throw new Error(`${message}. Expected events to contain "${substring}". Got: ${JSON.stringify(events)}`); } } exports.exportUfvk = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async (account) => { const buttons = getButtonsController(); const { receiveVerifyLabel, receiveConfirmLabel } = getDeviceLabels(account.currency.speculosApp); await waitFor(receiveVerifyLabel); if ((0, speculosAppVersion_1.isTouchDevice)()) { await (0, exports.pressUntilTextFound)(receiveConfirmLabel); await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.CONFIRM); } else { await (0, exports.pressUntilTextFound)(receiveConfirmLabel); await buttons.both(); } }); exports.shareViewKey = (0, DeviceController_1.withDeviceController)(({ getButtonsController }) => async () => { const buttons = getButtonsController(); await (0, exports.pressUntilTextFound)(DeviceLabels_1.DeviceLabels.CONFIRM); if ((0, speculosAppVersion_1.isTouchDevice)()) { await (0, TouchDeviceSimulator_1.pressAndRelease)(DeviceLabels_1.DeviceLabels.CONFIRM); } else { await buttons.both(); } }); //# sourceMappingURL=speculos.js.map