"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
require("../../__tests__/test-helpers/environment");
// import path from "path";
// import fs from "fs/promises";
const specs_1 = __importDefault(require("../../generated/specs"));
const speculos_1 = require("../../load/speculos");
const cache_1 = require("../../bridge/cache");
const bridge_1 = require("../../bridge");
const operators_1 = require("rxjs/operators");
const live_env_1 = require("@ledgerhq/live-env");
const rxjs_1 = require("rxjs");
const account_1 = require("../../account");
const audits_1 = require("./audits");
main().then(r => {
    // eslint-disable-next-line no-console
    console.log(JSON.stringify(r));
    process.exit(0);
}, error => {
    // eslint-disable-next-line no-console
    console.log(JSON.stringify({ error: String(error) }));
    process.exit(0);
});
async function main() {
    const report = {};
    const [family, key] = process.argv.slice(2);
    const spec = specs_1.default[family][key];
    const { COINAPPS, SEED } = process.env;
    if (!COINAPPS) {
        throw new Error("COINAPPS env variable is required");
    }
    if (!SEED) {
        throw new Error("SEED env variable is required");
    }
    // Prepare speculos device simulator
    const appCandidates = await (0, speculos_1.listAppCandidates)(COINAPPS);
    const { appQuery, currency, dependency, onSpeculosDeviceCreated } = spec;
    const appCandidate = (0, speculos_1.findAppCandidate)(appCandidates, appQuery);
    if (!appCandidate) {
        console.warn("no app found for " + spec.name);
        console.warn(appQuery);
        console.warn(JSON.stringify(appCandidates, undefined, 2));
    }
    if (!appCandidate) {
        throw new Error(`no app found for ${spec.name}. Are you sure your COINAPPS is up to date?`);
    }
    const deviceParams = {
        ...appCandidate,
        appName: spec.currency.managerAppName,
        seed: SEED,
        dependency,
        coinapps: COINAPPS,
        onSpeculosDeviceCreated,
    };
    const device = await (0, speculos_1.createSpeculosDevice)(deviceParams);
    try {
        const audit = new audits_1.Audit();
        // We scan and synchronize the accounts
        const localCache = {};
        const cache = (0, cache_1.makeBridgeCacheSystem)({
            saveData(c, d) {
                localCache[c.id] = d;
                return Promise.resolve();
            },
            getData(c) {
                return Promise.resolve(localCache[c.id]);
            },
        });
        const bridge = (0, bridge_1.getCurrencyBridge)(currency);
        const syncConfig = {
            paginationConfig: {},
        };
        await cache.prepareCurrency(currency);
        const accounts = await (0, rxjs_1.firstValueFrom)(bridge
            .scanAccounts({
            currency,
            deviceId: device.id,
            syncConfig,
        })
            .pipe((0, operators_1.filter)(e => e.type === "discovered"), (0, operators_1.map)(e => e.account), (0, operators_1.reduce)((all, a) => all.concat(a), []), (0, operators_1.timeout)({
            each: (0, live_env_1.getEnv)("BOT_TIMEOUT_SCAN_ACCOUNTS"),
            with: () => (0, rxjs_1.throwError)(() => new Error("scan accounts timeout for currency " + currency.name)),
        })));
        audit.end();
        const accountsRaw = JSON.stringify(accounts.map(a => (0, account_1.toAccountRaw)(a)));
        const preloadJSON = JSON.stringify(localCache);
        audit.setAccountsJSONSize(accountsRaw.length);
        audit.setPreloadJSONSize(preloadJSON.length);
        /*
        // TODO big data
        if (REPORT_FOLDER) {
          const accountsFile = path.join(REPORT_FOLDER, "accounts.json");
          await fs.writeFile(accountsFile, accountsRaw);
        }
        */
        report.refillAddress = accounts[0]?.freshAddress;
        report.accountBalances = accounts.map(a => a.balance.toString());
        report.accountIds = accounts.map(a => a.id);
        report.accountOperationsLength = accounts.map(a => a.operations.length);
        report.auditResult = audit.result();
    }
    finally {
        await (0, speculos_1.releaseSpeculosDevice)(device.id);
    }
    return report;
}
//# sourceMappingURL=process-sync.js.map