import invariant from "invariant";
import { log } from "@ledgerhq/logs";
import { createSpeculosDevice, findLatestAppCandidate, listAppCandidates, releaseSpeculosDevice, } from "../load/speculos";
import { createSpeculosDeviceCI, releaseSpeculosDeviceCI } from "./speculosCI";
import { DeviceModelId } from "@ledgerhq/devices";
import axios from "axios";
import { getEnv } from "@ledgerhq/live-env";
import { getCryptoCurrencyById } from "../currencies";
import { DeviceLabels } from "./enum/DeviceLabels";
import { Account } from "./enum/Account";
import { Currency } from "./enum/Currency";
import expect from "expect";
import { sendBTC, sendBTCBasedCoin } from "./families/bitcoin";
import { sendEVM } from "./families/evm";
import { sendPolkadot } from "./families/polkadot";
import { sendAlgorand } from "./families/algorand";
import { sendTron } from "./families/tron";
import { sendStellar } from "./families/stellar";
import { delegateCardano, sendCardano } from "./families/cardano";
import { sendXRP } from "./families/xrp";
import { delegateAptos, sendAptos } from "./families/aptos";
import { sendHedera } from "./families/hedera";
import { delegateNear } from "./families/near";
import { delegateCosmos, sendCosmos } from "./families/cosmos";
import { sendKaspa } from "./families/kaspa";
import { delegateSolana, sendSolana } from "./families/solana";
import { delegateTezos } from "./families/tezos";
import { delegateCelo } from "./families/celo";
import { delegateMultiversX } from "./families/multiversX";
import { delegateOsmosis } from "./families/osmosis";
import { DEVICE_LABELS_CONFIG } from "./data/deviceLabelsData";
import { sendSui } from "./families/sui";
import { getAppVersionFromCatalog, getSpeculosModel, isTouchDevice } from "./speculosAppVersion";
import { pressAndRelease, longPressAndRelease, swipeRight, } from "./deviceInteraction/TouchDeviceSimulator";
import { withDeviceController } from "./deviceInteraction/DeviceController";
import { sanitizeError } from ".";
const isSpeculosRemote = process.env.REMOTE_SPECULOS === "true";
export function setExchangeDependencies(dependencies) {
    const map = new Map();
    for (const dep of dependencies) {
        if (!map.has(dep.name)) {
            map.set(dep.name, dep);
        }
    }
    specs["Exchange"].dependencies = Array.from(map.values());
}
export const specs = {
    Bitcoin: {
        currency: getCryptoCurrencyById("bitcoin"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Bitcoin",
        },
        dependency: "",
    },
    Aptos: {
        currency: getCryptoCurrencyById("aptos"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Aptos",
        },
        dependency: "",
    },
    Exchange: {
        appQuery: {
            model: getSpeculosModel(),
            appName: "Exchange",
        },
        dependencies: [],
    },
    LedgerSync: {
        appQuery: {
            model: getSpeculosModel(),
            appName: "Ledger Sync",
        },
        dependency: "",
    },
    Dogecoin: {
        currency: getCryptoCurrencyById("dogecoin"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Dogecoin",
        },
        dependency: "",
    },
    Ethereum: {
        currency: getCryptoCurrencyById("ethereum"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Ethereum",
        },
        dependency: "",
    },
    Ethereum_Holesky: {
        currency: getCryptoCurrencyById("ethereum_holesky"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Ethereum",
        },
        dependency: "",
    },
    Ethereum_Sepolia: {
        currency: getCryptoCurrencyById("ethereum_sepolia"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Ethereum",
        },
        dependency: "",
    },
    Ethereum_Classic: {
        currency: getCryptoCurrencyById("ethereum_classic"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Ethereum Classic",
        },
        dependency: "Ethereum",
    },
    Bitcoin_Testnet: {
        currency: getCryptoCurrencyById("bitcoin_testnet"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Bitcoin Test",
        },
        dependency: "",
    },
    Solana: {
        currency: getCryptoCurrencyById("solana"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Solana",
        },
        dependency: "",
    },
    Cardano: {
        currency: getCryptoCurrencyById("cardano"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "CardanoADA",
        },
        dependency: "",
    },
    Polkadot: {
        currency: getCryptoCurrencyById("polkadot"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Polkadot",
        },
        dependency: "",
    },
    Tron: {
        currency: getCryptoCurrencyById("tron"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Tron",
        },
        dependency: "",
    },
    XRP: {
        currency: getCryptoCurrencyById("ripple"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "XRP",
        },
        dependency: "",
    },
    Stellar: {
        currency: getCryptoCurrencyById("stellar"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Stellar",
        },
        dependency: "",
    },
    Bitcoin_Cash: {
        currency: getCryptoCurrencyById("bitcoin_cash"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Bitcoin Cash",
        },
        dependency: "",
    },
    Algorand: {
        currency: getCryptoCurrencyById("algorand"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Algorand",
        },
        dependency: "",
    },
    Cosmos: {
        currency: getCryptoCurrencyById("cosmos"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Cosmos",
        },
        dependency: "",
    },
    Tezos: {
        currency: getCryptoCurrencyById("tezos"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "TezosWallet",
        },
        dependency: "",
    },
    Polygon: {
        currency: getCryptoCurrencyById("polygon"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Ethereum",
        },
        dependency: "",
    },
    BNB_Chain: {
        currency: getCryptoCurrencyById("bsc"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Ethereum",
        },
        dependency: "",
    },
    Ton: {
        currency: getCryptoCurrencyById("ton"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "TON",
        },
        dependency: "",
    },
    Near: {
        currency: getCryptoCurrencyById("near"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "NEAR",
        },
        dependency: "",
    },
    Multivers_X: {
        currency: getCryptoCurrencyById("elrond"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "MultiversX",
        },
        dependency: "",
    },
    Osmosis: {
        currency: getCryptoCurrencyById("osmo"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Cosmos",
        },
        dependency: "",
    },
    Injective: {
        currency: getCryptoCurrencyById("injective"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Cosmos",
        },
        dependency: "",
    },
    Celo: {
        currency: getCryptoCurrencyById("celo"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Celo",
        },
        dependency: "",
    },
    Litecoin: {
        currency: getCryptoCurrencyById("litecoin"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Litecoin",
        },
        dependency: "",
    },
    Kaspa: {
        currency: getCryptoCurrencyById("kaspa"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Kaspa",
        },
        dependency: "",
    },
    Hedera: {
        currency: getCryptoCurrencyById("hedera"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Hedera",
        },
        dependency: "",
    },
    Sui: {
        currency: getCryptoCurrencyById("sui"),
        appQuery: {
            model: getSpeculosModel(),
            appName: "Sui",
        },
        dependency: "",
    },
};
export async function startSpeculos(testName, spec) {
    log("engine", `test ${testName}`);
    const { SEED, COINAPPS } = process.env;
    const seed = SEED;
    invariant(seed, "SEED is not set");
    const coinapps = COINAPPS;
    invariant(coinapps, "COINAPPS is not set");
    const appCandidates = await listAppCandidates(coinapps);
    const nanoAppCatalogPath = getEnv("E2E_NANO_APP_VERSION_PATH");
    const { appQuery, dependency, onSpeculosDeviceCreated } = spec;
    try {
        const displayName = spec.currency?.managerAppName || appQuery.appName;
        const catalogVersion = await getAppVersionFromCatalog(displayName, nanoAppCatalogPath);
        if (catalogVersion) {
            appQuery.appVersion = catalogVersion;
        }
    }
    catch (e) {
        console.warn("[speculos] Unable to fetch app version from catalog", e);
    }
    const appCandidate = findLatestAppCandidate(appCandidates, appQuery);
    const { model } = appQuery;
    const { dependencies } = spec;
    const newAppQuery = dependencies?.map(dep => {
        return 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);
    }
    invariant(appCandidate, "%s: no app found. Are you sure your COINAPPS is up to date?", testName, coinapps);
    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,
        dependency,
        dependencies,
        coinapps,
        onSpeculosDeviceCreated,
    };
    try {
        return isSpeculosRemote
            ? await createSpeculosDeviceCI(deviceParams)
            : await createSpeculosDevice(deviceParams).then(device => {
                invariant(device.ports.apiPort, "[E2E] Speculos apiPort is not defined");
                return {
                    id: device.id,
                    port: device.ports.apiPort,
                    appName: appCandidate.appName,
                    appVersion: appCandidate.appVersion,
                };
            });
    }
    catch (e) {
        console.error(sanitizeError(e));
        log("engine", `test ${testName} failed with ${String(e)}`);
    }
}
export async function stopSpeculos(deviceId) {
    if (deviceId) {
        log("engine", `test ${deviceId} finished`);
        isSpeculosRemote
            ? await releaseSpeculosDeviceCI(deviceId)
            : await releaseSpeculosDevice(deviceId);
    }
}
export function getSpeculosAddress() {
    const speculosAddress = process.env.SPECULOS_ADDRESS;
    return speculosAddress || "http://127.0.0.1";
}
export 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.isAxiosError(error) &&
                error.response &&
                retryableStatusCodes.includes(error.response.status);
            const isNetworkError = axios.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.isAxiosError(error) ? error.response?.status : "network error",
                    message: error.message,
                });
                await new Promise(resolve => setTimeout(resolve, delay));
                continue;
            }
            throw lastError;
        }
    }
    throw lastError;
}
export async function waitFor(text, maxAttempts = 60) {
    const port = 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}"`);
}
export async function fetchCurrentScreenTexts(speculosApiPort) {
    const speculosAddress = getSpeculosAddress();
    const response = await retryAxiosRequest(() => axios.get(`${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=true`));
    return response.data.events.map(event => event.text).join(" ");
}
export async function getDeviceLabelCoordinates(label, speculosApiPort) {
    const speculosAddress = getSpeculosAddress();
    const response = await retryAxiosRequest(() => axios.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 };
}
export async function fetchAllEvents(speculosApiPort) {
    const speculosAddress = getSpeculosAddress();
    const response = await retryAxiosRequest(() => axios.get(`${speculosAddress}:${speculosApiPort}/events?stream=false&currentscreenonly=false`));
    return response.data.events.map(event => event.text);
}
export const pressUntilTextFound = withDeviceController(({ getButtonsController }) => async (targetText, strictMatch = false) => {
    const maxAttempts = 18;
    const speculosApiPort = 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 (isTouchDevice()) {
            await swipeRight();
        }
        else {
            await buttons.right();
        }
        await waitForTimeOut(200);
    }
    throw new Error(`ElementNotFoundException: Element with text "${targetText}" not found on speculos screen`);
});
export 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;
}
export async function takeScreenshot(port) {
    const speculosAddress = getSpeculosAddress();
    const speculosApiPort = port ?? getEnv("SPECULOS_API_PORT");
    try {
        const response = await retryAxiosRequest(() => axios.get(`${speculosAddress}:${speculosApiPort}/screenshot`, {
            responseType: "arraybuffer",
        }));
        return response.data;
    }
    catch (error) {
        console.error("Error downloading speculos screenshot:", sanitizeError(error));
    }
}
export async function waitForTimeOut(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
export const removeMemberLedgerSync = withDeviceController(({ getButtonsController }) => async () => {
    const buttons = getButtonsController();
    await waitFor(DeviceLabels.CONNECT_WITH);
    if (isTouchDevice()) {
        await pressAndRelease(DeviceLabels.CONNECT);
        await waitFor(DeviceLabels.REMOVE_FROM_LEDGER_SYNC);
        await pressAndRelease(DeviceLabels.REMOVE);
        await waitFor(DeviceLabels.CONFIRM_CHANGE);
        await pressAndRelease(DeviceLabels.TAP_TO_CONTINUE);
        await waitFor(DeviceLabels.TURN_ON_SYNC);
        await pressUntilTextFound(DeviceLabels.LEDGER_LIVE_WILL_BE);
        await pressUntilTextFound(DeviceLabels.TURN_ON_SYNC);
        await pressAndRelease(DeviceLabels.TURN_ON_SYNC);
    }
    else {
        await pressUntilTextFound(DeviceLabels.CONNECT_WITH_LEDGER_SYNC, true);
        await buttons.both();
        await waitFor(DeviceLabels.REMOVE_PHONE_OR_COMPUTER);
        await pressUntilTextFound(DeviceLabels.REMOVE_PHONE_OR_COMPUTER, true);
        await buttons.both();
        await waitFor(DeviceLabels.TURN_ON_SYNC);
        await pressUntilTextFound(DeviceLabels.LEDGER_LIVE_WILL_BE);
        await pressUntilTextFound(DeviceLabels.TURN_ON_SYNC);
        await buttons.both();
    }
});
export const activateLedgerSync = withDeviceController(({ getButtonsController }) => async () => {
    const buttons = getButtonsController();
    await waitFor(DeviceLabels.CONNECT_WITH);
    if (isTouchDevice()) {
        await pressAndRelease(DeviceLabels.CONNECT_WITH_LEDGER_SYNC);
    }
    else {
        await pressUntilTextFound(DeviceLabels.CONNECT_WITH_LEDGER_SYNC, true);
        await buttons.both();
    }
    await waitFor(DeviceLabels.TURN_ON_SYNC);
    if (isTouchDevice()) {
        await pressAndRelease(DeviceLabels.TURN_ON_SYNC);
    }
    else {
        await pressUntilTextFound(DeviceLabels.LEDGER_LIVE_WILL_BE);
        await pressUntilTextFound(DeviceLabels.TURN_ON_SYNC);
        await buttons.both();
    }
});
const getSettingsToggle1Coordinates = () => {
    const deviceModel = getSpeculosModel();
    switch (deviceModel) {
        case DeviceModelId.stax:
            return { x: 345, y: 136 };
        case DeviceModelId.europa:
            return { x: 420, y: 140 };
        case DeviceModelId.apex:
            return { x: 263, y: 100 };
        default:
            return { x: 420, y: 140 };
    }
};
const getSettingsCogwheelCoordinates = () => {
    const deviceModel = getSpeculosModel();
    switch (deviceModel) {
        case DeviceModelId.stax:
            return { x: 362, y: 43 };
        case DeviceModelId.europa:
            return { x: 400, y: 80 };
        case DeviceModelId.apex:
            return { x: 253, y: 58 };
        default:
            return { x: 400, y: 80 };
    }
};
export const activateExpertMode = withDeviceController(({ getButtonsController }) => async () => {
    const buttons = getButtonsController();
    if (isTouchDevice()) {
        await goToSettings();
        const SettingsToggle1Coordinates = getSettingsToggle1Coordinates();
        await pressAndRelease(DeviceLabels.SETTINGS_TOGGLE_1, SettingsToggle1Coordinates.x, SettingsToggle1Coordinates.y);
    }
    else {
        await pressUntilTextFound(DeviceLabels.EXPERT_MODE);
        await buttons.both();
    }
});
export const activateContractData = withDeviceController(({ getButtonsController }) => async () => {
    const buttons = getButtonsController();
    await pressUntilTextFound(DeviceLabels.SETTINGS);
    await buttons.both();
    await waitFor(DeviceLabels.CONTRACT_DATA);
    await buttons.both();
});
export const goToSettings = withDeviceController(({ getButtonsController }) => async () => {
    const buttons = getButtonsController();
    if (isTouchDevice()) {
        const SettingsCogwheelCoordinates = getSettingsCogwheelCoordinates();
        await pressAndRelease(DeviceLabels.SETTINGS, SettingsCogwheelCoordinates.x, SettingsCogwheelCoordinates.y);
    }
    else {
        await pressUntilTextFound(DeviceLabels.SETTINGS);
        await buttons.both();
    }
});
export const providePublicKey = withDeviceController(({ getButtonsController }) => async () => {
    const buttons = getButtonsController();
    await buttons.right();
});
export function getDeviceLabels(appInfo) {
    const deviceModel = getSpeculosModel();
    const deviceConfig = DEVICE_LABELS_CONFIG[deviceModel] ?? 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,
    };
}
export const expectValidAddressDevice = withDeviceController(({ getButtonsController }) => async (account, addressDisplayed) => {
    const buttons = getButtonsController();
    if (account.currency === Currency.SUI_USDC) {
        await providePublicKey();
    }
    const { receiveVerifyLabel, receiveConfirmLabel } = getDeviceLabels(account.currency.speculosApp);
    await waitFor(receiveVerifyLabel);
    if (isTouchDevice()) {
        const events = await pressUntilTextFound(receiveConfirmLabel);
        const isAddressCorrect = containsSubstringInEvent(addressDisplayed, events);
        expect(isAddressCorrect).toBeTruthy();
        await pressAndRelease(DeviceLabels.CONFIRM);
    }
    else {
        const events = await pressUntilTextFound(receiveConfirmLabel);
        const isAddressCorrect = containsSubstringInEvent(addressDisplayed, events);
        expect(isAddressCorrect).toBeTruthy();
        await buttons.both();
    }
});
export async function signSendTransaction(tx) {
    const currencyName = tx.accountToDebit.currency;
    switch (currencyName) {
        case Currency.sepETH:
        case Currency.POL:
        case Currency.ETH:
            await sendEVM(tx);
            break;
        case Currency.BTC:
            await sendBTC(tx);
            break;
        case Currency.ETH_USDT:
            await sendEVM(tx);
            break;
        case Currency.DOGE:
        case Currency.BCH:
            await sendBTCBasedCoin(tx);
            break;
        case Currency.DOT:
            await sendPolkadot(tx);
            break;
        case Currency.ALGO:
            await sendAlgorand(tx);
            break;
        case Currency.SOL:
        case Currency.SOL_GIGA:
            await sendSolana(tx);
            break;
        case Currency.TRX:
            await sendTron(tx);
            break;
        case Currency.XLM:
            await sendStellar(tx);
            break;
        case Currency.ATOM:
            await sendCosmos(tx);
            break;
        case Currency.ADA:
            await sendCardano(tx);
            break;
        case Currency.XRP:
            await sendXRP(tx);
            break;
        case Currency.APT:
            await sendAptos(tx);
            break;
        case Currency.KAS:
            await sendKaspa(tx);
            break;
        case Currency.HBAR:
            await sendHedera();
            break;
        case Currency.SUI:
        case Currency.SUI_USDC:
            await sendSui(tx);
            break;
        default:
            throw new Error(`Unsupported currency: ${currencyName.ticker}`);
    }
}
export async function getSendEvents(tx) {
    const { sendVerifyLabel, sendConfirmLabel } = getDeviceLabels(tx.accountToDebit.currency.speculosApp);
    await waitFor(sendVerifyLabel);
    return await pressUntilTextFound(sendConfirmLabel);
}
export async function signDelegationTransaction(delegatingAccount) {
    const currencyName = delegatingAccount.account.currency.name;
    switch (currencyName) {
        case Account.SOL_1.currency.name:
            await delegateSolana(delegatingAccount);
            break;
        case Account.NEAR_1.currency.name:
            await delegateNear(delegatingAccount);
            break;
        case Account.ATOM_1.currency.name:
        case Account.INJ_1.currency.name:
            await delegateCosmos(delegatingAccount);
            break;
        case Account.OSMO_1.currency.name:
            await delegateOsmosis(delegatingAccount);
            break;
        case Account.MULTIVERS_X_1.currency.name:
            await delegateMultiversX(delegatingAccount);
            break;
        case Account.ADA_1.currency.name:
            await delegateCardano();
            break;
        case Account.XTZ_1.currency.name:
            await delegateTezos(delegatingAccount);
            break;
        case Account.CELO_1.currency.name:
            await delegateCelo(delegatingAccount);
            break;
        case Account.APTOS_1.currency.name:
            await delegateAptos(delegatingAccount);
            break;
        default:
            throw new Error(`Unsupported currency: ${currencyName}`);
    }
}
export async function getDelegateEvents(delegatingAccount) {
    const { delegateVerifyLabel, delegateConfirmLabel } = getDeviceLabels(delegatingAccount.account.currency.speculosApp);
    await waitFor(delegateVerifyLabel);
    return await pressUntilTextFound(delegateConfirmLabel);
}
export const verifyAmountsAndAcceptSwap = withDeviceController(({ getButtonsController }) => async (swap, amount) => {
    const buttons = getButtonsController();
    await waitFor(DeviceLabels.REVIEW_TRANSACTION);
    const events = getSpeculosModel() === DeviceModelId.nanoS
        ? await pressUntilTextFound(DeviceLabels.ACCEPT_AND_SEND)
        : await pressUntilTextFound(DeviceLabels.SIGN_TRANSACTION);
    verifySwapData(swap, events, amount);
    if (isTouchDevice()) {
        await longPressAndRelease(DeviceLabels.HOLD_TO_SIGN, 3);
    }
    else {
        await buttons.both();
    }
});
export const verifyAmountsAndAcceptSwapForDifferentSeed = withDeviceController(({ getButtonsController }) => async (swap, amount, errorMessage) => {
    const buttons = getButtonsController();
    if (errorMessage === null) {
        if (isTouchDevice()) {
            await waitFor(DeviceLabels.RECEIVE_ADDRESS_DOES_NOT_BELONG);
            await pressAndRelease(DeviceLabels.CONTINUE_ANYWAY);
        }
        else {
            await waitFor(DeviceLabels.REVIEW_TRANSACTION);
            await pressUntilTextFound(DeviceLabels.RECEIVE_ADDRESS_DOES_NOT_BELONG);
            await buttons.both();
        }
    }
    else {
        await waitFor(DeviceLabels.REVIEW_TRANSACTION);
    }
    const events = await pressUntilTextFound(DeviceLabels.SIGN_TRANSACTION);
    verifySwapData(swap, events, amount);
    if (isTouchDevice()) {
        await longPressAndRelease(DeviceLabels.HOLD_TO_SIGN, 3);
    }
    else {
        await buttons.both();
    }
});
export const verifyAmountsAndRejectSwap = withDeviceController(({ getButtonsController }) => async (swap, amount) => {
    const buttons = getButtonsController();
    await waitFor(DeviceLabels.REVIEW_TRANSACTION);
    let events = [];
    if (isTouchDevice()) {
        events = await pressUntilTextFound(DeviceLabels.HOLD_TO_SIGN);
    }
    else {
        events = await pressUntilTextFound(DeviceLabels.REJECT);
    }
    verifySwapData(swap, events, amount);
    if (isTouchDevice()) {
        await pressAndRelease(DeviceLabels.REJECT);
        await waitFor(DeviceLabels.YES_REJECT);
        await pressAndRelease(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 (getSpeculosModel() !== 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)}`);
    }
}
//# sourceMappingURL=speculos.js.map