@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
241 lines • 8.22 kB
JavaScript
;
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",
"sei_network_evm",
"berachain",
"hyperevm",
"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