"use strict";
import "../../__tests__/test-helpers/environment";
// import path from "path";
// import fs from "fs/promises";
import allSpecs from "../../generated/specs";
import { createSpeculosDevice, findAppCandidate, listAppCandidates, releaseSpeculosDevice, } from "../../load/speculos";
import { makeBridgeCacheSystem } from "../../bridge/cache";
import { getCurrencyBridge } from "../../bridge";
import { filter, map, reduce, timeout } from "rxjs/operators";
import { getEnv } from "@ledgerhq/live-env";
import { firstValueFrom, throwError } from "rxjs";
import { toAccountRaw } from "../../account";
import { Audit } from "./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 = allSpecs[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 listAppCandidates(COINAPPS);
    const { appQuery, currency, dependency, onSpeculosDeviceCreated } = spec;
    const appCandidate = 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 createSpeculosDevice(deviceParams);
    try {
        const audit = new Audit();
        // We scan and synchronize the accounts
        const localCache = {};
        const cache = makeBridgeCacheSystem({
            saveData(c, d) {
                localCache[c.id] = d;
                return Promise.resolve();
            },
            getData(c) {
                return Promise.resolve(localCache[c.id]);
            },
        });
        const bridge = getCurrencyBridge(currency);
        const syncConfig = {
            paginationConfig: {},
        };
        await cache.prepareCurrency(currency);
        const accounts = await firstValueFrom(bridge
            .scanAccounts({
            currency,
            deviceId: device.id,
            syncConfig,
        })
            .pipe(filter(e => e.type === "discovered"), map(e => e.account), reduce((all, a) => all.concat(a), []), timeout({
            each: getEnv("BOT_TIMEOUT_SCAN_ACCOUNTS"),
            with: () => throwError(() => new Error("scan accounts timeout for currency " + currency.name)),
        })));
        audit.end();
        const accountsRaw = JSON.stringify(accounts.map(a => 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 releaseSpeculosDevice(device.id);
    }
    return report;
}
//# sourceMappingURL=process-sync.js.map