"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable @typescript-eslint/consistent-type-assertions */
const index_1 = require("@ledgerhq/coin-solana/network/index");
const live_env_1 = require("@ledgerhq/live-env");
const bridge_1 = require("@ledgerhq/coin-solana/bridge/bridge");
const signer_1 = require("@ledgerhq/coin-solana/signer");
const web3_js_1 = require("@solana/web3.js");
const fp_1 = require("lodash/fp");
const mock_data_1 = require("./mock-data");
const mockHelpers_1 = require("../../../bridge/mockHelpers");
function mockChainAPI(config) {
    const mockedMethods = (0, mock_data_1.getMockedMethods)();
    const api = new Proxy({ config }, {
        get(_, propKey) {
            if (propKey in api) {
                return api[propKey];
            }
            if (propKey === "then") {
                return undefined;
            }
            const method = propKey.toString();
            const mocks = mockedMethods.filter(mock => mock.method === method);
            if (mocks.length === 0) {
                throw new Error(`no mock found for api method: ${method}`);
            }
            return function (...rawArgs) {
                const args = preprocessArgs(method, rawArgs);
                const mock = mocks.find(({ params: mockArgs }) => (0, fp_1.isEqual)(args)(mockArgs));
                if (mock === undefined) {
                    const argsJson = JSON.stringify(args);
                    throw new Error(`no mock found for api method ${method} with args ${argsJson}`);
                }
                return Promise.resolve(mock.answer);
            };
        },
    });
    return api;
}
function removeUndefineds(input) {
    return (0, fp_1.isObject)(input)
        ? (0, fp_1.isArray)(input)
            ? input.map(removeUndefineds)
            : (0, fp_1.flow)((0, fp_1.omitBy)(fp_1.isUndefined), (0, fp_1.mapValues)(removeUndefineds))(input)
        : input;
}
function preprocessArgs(method, args) {
    if (method === "getFeeForMessage") {
        // getFeeForMessage needs some args preprocessing
        if (args.length === 1 && (args[0] instanceof web3_js_1.Message || args[0] instanceof web3_js_1.MessageV0)) {
            return [Buffer.from(args[0].serialize()).toString("base64")];
        }
        else {
            throw new Error("unexpected getFeeForMessage function signature");
        }
    }
    if (method === "getSimulationComputeUnits") {
        // getSimulationComputeUnits needs args preprocessing
        // args[0] is instructions array, args[1] is payer PublicKey
        if (args.length === 2) {
            const instructions = args[0];
            const payer = args[1];
            // Serialize the payer PublicKey to string
            const serializedPayer = payer?.toString?.() ?? payer;
            // Serialize PublicKey objects in instruction keys to strings
            const serializedInstructions = instructions?.map?.(instruction => {
                const inst = instruction;
                return {
                    ...inst,
                    keys: inst.keys?.map?.(key => {
                        const k = key;
                        return {
                            ...k,
                            pubkey: k.pubkey?.toString?.() ?? k.pubkey,
                        };
                    }) || inst.keys,
                    programId: inst.programId?.toString?.() ?? inst.programId,
                };
            }) || instructions;
            return [serializedInstructions, serializedPayer];
        }
    }
    return removeUndefineds(args);
}
const APP_VERSION = "1.7.1";
const signature = "fakeSignatureTlaowosfpqwkpofqkpqwpoesHQv6xHyYwDsrPJvqcSKRJGBLrbE";
const signer = {
    getAppConfiguration: () => Promise.resolve({
        version: APP_VERSION,
        blindSigningEnabled: false,
        pubKeyDisplayMode: signer_1.PubKeyDisplayMode.LONG,
    }),
    getAddress: (_path, _display) => Promise.resolve({ address: Buffer.from("fakeAddress") }),
    signTransaction: (_path, _txBuffer) => Promise.resolve({ signature: Buffer.from(signature) }),
    signMessage: (_path, _messageHex) => Promise.resolve({ signature: Buffer.from(signature) }),
};
const signerContext = (_deviceId, fn) => fn(signer);
// Bridge with this api will log all api calls to a file.
// The calls data can be copied to mock-data.ts from the file.
// Uncomment fs module in logged.ts
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
function createMockDataForAPI() {
    const chainAPICache = new Map();
    return {
        getAPI: (config) => {
            const endpoint = config.endpoint;
            if (!chainAPICache.has(endpoint)) {
                chainAPICache.set(endpoint, (0, index_1.logged)((0, index_1.getChainAPI)(config), "/tmp/log"));
            }
            return chainAPICache.get(endpoint);
        },
        signerContext,
    };
}
function getMockedAPIs() {
    const mockedAPI = mockChainAPI({ cluster: "mock" });
    return {
        getAPI: (_) => mockedAPI,
        signerContext,
    };
}
// const bridges = makeBridges(createMockDataForAPI());
const bridges = (0, bridge_1.makeBridges)(getMockedAPIs());
exports.default = (0, live_env_1.getEnv)("PLAYWRIGHT_RUN") || (0, live_env_1.getEnv)("DETOX")
    ? {
        accountBridge: {
            ...bridges.accountBridge,
            sync: mockHelpers_1.sync,
        },
        currencyBridge: {
            ...bridges.currencyBridge,
            preload: () => Promise.resolve({}),
            hydrate: () => { },
            scanAccounts: mockHelpers_1.scanAccounts,
        },
    }
    : bridges;
//# sourceMappingURL=mock.js.map