"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable no-console */
const LiveConfig_1 = require("@ledgerhq/live-config/LiveConfig");
const bignumber_js_1 = __importDefault(require("bignumber.js"));
const child_process_1 = __importDefault(require("child_process"));
const fs_1 = require("fs");
const util_1 = require("util");
const yargs_1 = require("yargs");
const rxjs_1 = require("rxjs");
const account_1 = require("../../account");
const impl_1 = require("../../bridge/impl");
const sharedConfig_1 = require("../../config/sharedConfig");
const currencies_1 = require("../../currencies");
const addresses_1 = require("./addresses");
// mandatory to run the script
(0, currencies_1.setSupportedCurrencies)([
    "bitcoin",
    "ethereum",
    "bsc",
    "polkadot",
    "ripple",
    "litecoin",
    "polygon",
    "bitcoin_cash",
    "stellar",
    "dogecoin",
    "cosmos",
    "dash",
    "tron",
    "tezos",
    "elrond",
    "ethereum_classic",
    "zcash",
    "decred",
    "digibyte",
    "algorand",
    "avalanche_c_chain",
    "qtum",
    "bitcoin_gold",
    "komodo",
    "zencash",
    "crypto_org",
    "crypto_org_croeseid",
    "celo",
    "hedera",
    "cardano",
    "solana",
    "osmosis",
    "fantom",
    "moonbeam",
    "cronos",
    "songbird",
    "flare",
    "near",
    "optimism",
    "arbitrum",
    "rsk",
    "bittorrent",
    "energy_web",
    "astar",
    "metis",
    "boba",
    "moonriver",
    "velas_evm",
    "syscoin",
    "axelar",
    "stargaze",
    "secret_network",
    "umee",
    "desmos",
    "dydx",
    "onomy",
    "sei_network",
    "persistence",
    "quicksilver",
    "vechain",
    "internet_computer",
    "klaytn",
    "polygon_zk_evm",
    "base",
    "base_sepolia",
    "stacks",
    "telos_evm",
    "coreum",
    "injective",
    "casper",
    "neon_evm",
    "lukso",
    "filecoin",
    "linea",
    "ton",
    "mina",
]);
LiveConfig_1.LiveConfig.setConfig(sharedConfig_1.liveConfig);
LiveConfig_1.LiveConfig.setAppinfo({
    environment: "ci",
    platform: "headless-linux",
});
const args = yargs_1.argv;
const { currencies, inputFile, noEmit, outputFolderPath } = args;
const getMockAccount = (currencyId, address) => {
    const currency = (0, currencies_1.getCryptoCurrencyById)(currencyId);
    return {
        type: "Account",
        id: (0, account_1.encodeAccountId)({
            type: "js",
            version: "",
            currencyId: currencyId,
            xpubOrAddress: address,
            derivationMode: "",
        }),
        freshAddress: address,
        xpub: address,
        derivationMode: "",
        operations: [],
        currency,
        creationDate: new Date(0),
        balance: new bignumber_js_1.default(0),
        spendableBalance: new bignumber_js_1.default(0),
        blockHeight: 0,
        freshAddressPath: "",
        seedIdentifier: "",
        index: 0,
        used: true,
        operationsCount: 0,
        pendingOperations: [],
        lastSyncDate: new Date(0),
        balanceHistoryCache: {
            HOUR: { latestDate: 0, balances: [] },
            DAY: { latestDate: 0, balances: [] },
            WEEK: { latestDate: 0, balances: [] },
        },
        swapHistory: [],
    };
};
const testSync = async (currencyId, xpubOrAddress) => {
    console.log("starting sync on", currencyId, xpubOrAddress);
    const mockAccount = getMockAccount(currencyId, xpubOrAddress);
    const currency = (0, currencies_1.getCryptoCurrencyById)(currencyId);
    const currencyBrige = (0, impl_1.getCurrencyBridge)(currency);
    const data = await currencyBrige.preload(currency);
    currencyBrige.hydrate(data, currency);
    const accountBrige = (0, impl_1.getAccountBridgeByFamily)(mockAccount.currency.family, mockAccount.id);
    const syncedAccount = await (0, rxjs_1.firstValueFrom)(accountBrige
        .sync(mockAccount, { paginationConfig: {}, blacklistedTokenIds: [] })
        .pipe((0, rxjs_1.reduce)((acc, f) => f(acc), mockAccount)));
    const accountRaw = (0, account_1.toAccountRaw)(syncedAccount);
    console.log("finishing sync on", currencyId, xpubOrAddress);
    return accountRaw;
};
const testSyncAccount = async (account) => {
    console.log("starting sync on", account.currency.id, account.xpub ?? account.freshAddress);
    const currency = (0, currencies_1.getCryptoCurrencyById)(account.currency.id);
    const currencyBrige = (0, impl_1.getCurrencyBridge)(currency);
    const data = await currencyBrige.preload(currency);
    currencyBrige.hydrate(data, currency);
    const accountBrige = (0, impl_1.getAccountBridgeByFamily)(account.currency.family, account.id);
    const syncedAccount = await (0, rxjs_1.firstValueFrom)(accountBrige
        .sync(account, { paginationConfig: {}, blacklistedTokenIds: [] })
        .pipe((0, rxjs_1.reduce)((acc, f) => f(acc), account)));
    const accountRaw = (0, account_1.toAccountRaw)(syncedAccount);
    console.log("finishing sync on", account.currency.id, account.xpub ?? account.freshAddress);
    return accountRaw;
};
(async () => {
    // list of accounts from input file
    const inputAccounts = [];
    if (inputFile) {
        if (!(0, fs_1.existsSync)(inputFile)) {
            console.warn(`Incorrect file path: ${inputFile} does not exist`, "Will use default addresses instead");
        }
        else {
            // if there's a input file we parse it
            inputAccounts.push(JSON.parse((0, fs_1.readFileSync)(inputFile, "utf8")));
        }
    }
    const currencyIds = currencies?.split(",");
    for (const currencyId of currencyIds || []) {
        if (!(0, currencies_1.findCryptoCurrencyById)(currencyId)) {
            continue;
        }
    }
    // Basically the inputAccounts only exist after the second run
    // So we first try to sync the default addresses
    // And in the 2nd run we use the input file (which is the ouput of the first sync run)
    const migrationAddresses = inputAccounts.length ? inputAccounts : addresses_1.migrationAddresses;
    const filteredAddresses = migrationAddresses.filter(({ currencyId }) => {
        if (currencyIds) {
            return currencyIds.includes(currencyId);
        }
        return true;
    });
    let syncedAccounts = [];
    // if --inputFile we use the addresses from the input file otherwise from addresses.ts
    if (inputAccounts.length) {
        syncedAccounts = await Promise.allSettled(filteredAddresses.map(rawAccount => {
            const account = (0, account_1.fromAccountRaw)(rawAccount);
            return testSyncAccount(account);
        }));
    }
    else {
        syncedAccounts = await Promise.allSettled(filteredAddresses.map(migrationAddress => {
            return testSync(migrationAddress.currencyId, migrationAddress.xpub ?? migrationAddress.address);
        }));
    }
    const errors = [];
    const response = syncedAccounts.map((account, i) => {
        if (account.status === "fulfilled") {
            return account.value;
        }
        else {
            // Promise.allSettled preserve order so it's safe to use filteredAddresses[i]
            errors.push(`${filteredAddresses[i].currencyId} ${account.reason.stack}`);
        }
    });
    if (errors.length) {
        throw new Error(errors.map(err => `${err}`).join("\n\n"));
    }
    const exec = (0, util_1.promisify)(child_process_1.default.exec);
    const outputContent = JSON.stringify(response, null, 3);
    if (!noEmit) {
        // also used in account-migration.yml to know which input file to use
        const { stdout } = await exec("git rev-parse --short HEAD");
        const outputFilePath = outputFolderPath
            ? `${outputFolderPath}/${stdout.trim()}.json`
            : `${stdout.trim()}.json`;
        console.log("Writing output....");
        (0, fs_1.writeFileSync)(outputFilePath, outputContent);
        console.log(`File created: ${outputFilePath}`);
    }
    console.log("Done");
    return response;
})();
//# sourceMappingURL=account-migration.js.map