diff --git a/scripts/hyp-repair.ts b/scripts/hyp-repair.ts index fac52d6..ddcb73f 100644 --- a/scripts/hyp-repair.ts +++ b/scripts/hyp-repair.ts @@ -1,36 +1,47 @@ -import {Command} from 'commander'; -import {readFileSync} from "node:fs"; -import {Client, estypes} from "@elastic/elasticsearch"; +import { Command } from 'commander'; +import { readFileSync } from 'node:fs'; +import { Client, estypes } from '@elastic/elasticsearch'; // @ts-ignore -import cliProgress from "cli-progress"; -import {JsonRpc} from 'eosjs'; +import cliProgress from 'cli-progress'; +import { JsonRpc } from 'eosjs'; import fetch from 'cross-fetch'; -import {existsSync, mkdirSync, writeFileSync} from "fs"; -import {HyperionBlock} from "./repair-cli/interfaces.js"; +import { existsSync, mkdirSync, writeFileSync } from 'fs'; +import { HyperionBlock } from './repair-cli/interfaces.js'; import { getBlocks, getFirstIndexedBlock, getLastIndexedBlock, initESClient, readChainConfig, - readConnectionConfig -} from "./repair-cli/functions.js"; -import {SearchResponse} from "@elastic/elasticsearch/api/types"; + readConnectionConfig, +} from './repair-cli/functions.js'; +import { SearchResponse } from '@elastic/elasticsearch/api/types'; -import {WebSocket} from 'ws'; -import {block} from "../definitions/index-templates"; +import { WebSocket } from 'ws'; +import { block } from '../definitions/index-templates'; -const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic); +const progressBar = new cliProgress.SingleBar( + {}, + cliProgress.Presets.shades_classic +); const program = new Command(); const errorRanges: any[] = []; let pendingBlock: HyperionBlock | null = null; const missingBlocks: { - start: number, - end: number + start: number; + end: number; }[] = []; -async function run(client: Client, rpc: JsonRpc, indexName: string, blockInit: number, firstBlock: number, qtdTotal: any, loop: any = 1) { +async function run( + client: Client, + rpc: JsonRpc, + indexName: string, + blockInit: number, + firstBlock: number, + qtdTotal: any, + loop: any = 1 +) { let blockInitial = blockInit; let blockFinal = blockInitial - qtdTotal; const tRef = process.hrtime.bigint(); @@ -40,33 +51,44 @@ async function run(client: Client, rpc: JsonRpc, indexName: string, blockInit: n blockFinal = firstBlock; } try { - let {body} = await getBlocks(client, indexName, blockInitial, blockFinal, qtdTotal); - let {hits: {hits}} = body; + let { body } = await getBlocks( + client, + indexName, + blockInitial, + blockFinal, + qtdTotal + ); + let { + hits: { hits }, + } = body; const blocks = hits.map((obj: any) => obj._source); await findForksOnRange(blocks, rpc); blockInitial = blockFinal; blockFinal = blockInitial - qtdTotal; progressBar.update(i); } catch (e: any) { - console.log("Error: ", e); + console.log('Error: ', e); process.exit(1); } } progressBar.stop(); - console.log("=========== Forked Ranges ==========="); + console.log('=========== Forked Ranges ==========='); console.table(errorRanges); - console.log("=========== Missing Ranges =========="); + console.log('=========== Missing Ranges =========='); console.table(missingBlocks); const tDiff = Number(process.hrtime.bigint() - tRef) / 1000000; console.log(`Total time: ${Math.round(tDiff / 1000)}s`); } async function findForksOnRange(blocks: HyperionBlock[], rpc: JsonRpc) { - const removals: Set = new Set(); let start = null; let end = null; - if (blocks.length > 0 && pendingBlock && blocks[0].block_num !== pendingBlock.block_num) { + if ( + blocks.length > 0 && + pendingBlock && + blocks[0].block_num !== pendingBlock.block_num + ) { blocks.unshift(pendingBlock); } @@ -83,10 +105,14 @@ async function findForksOnRange(blocks: HyperionBlock[], rpc: JsonRpc) { i++; // console.log('previous -> ', previousBlock.block_num); if (previousBlock.block_num !== currentBlockNumber - 1) { - console.log(`\nBlock number mismatch, expected: ${currentBlockNumber - 1} got ${previousBlock.block_num}`); + console.log( + `\nBlock number mismatch, expected: ${ + currentBlockNumber - 1 + } got ${previousBlock.block_num}` + ); missingBlocks.push({ start: previousBlock.block_num + 1, - end: currentBlockNumber - 1 + end: currentBlockNumber - 1, }); continue; } @@ -107,7 +133,7 @@ async function findForksOnRange(blocks: HyperionBlock[], rpc: JsonRpc) { removals.add(currentBlock.block_id); } else { end = currentBlockNumber + 1; - const range = {start, end, ids: [...removals]}; + const range = { start, end, ids: [...removals] }; errorRanges.push(range); removals.clear(); // console.log(`\n ⚠️⚠️ Forked at ${range.start} to ${range.end}`); @@ -129,7 +155,7 @@ async function scanChain(chain: string, args: any) { const client = initESClient(config); - const jsonRpc = new JsonRpc(config.chains[chain].http, {fetch}); + const jsonRpc = new JsonRpc(config.chains[chain].http, { fetch }); const ping = await client.ping(); @@ -165,12 +191,20 @@ async function scanChain(chain: string, args: any) { const numberOfBatches = Math.ceil(totalBlocks / batchSize); - console.log("Range:", firstBlock, lastBlock); - console.log("Total Blocks:", totalBlocks); - console.log("Batch Size:", batchSize); - console.log("Number of Batches:", numberOfBatches); + console.log('Range:', firstBlock, lastBlock); + console.log('Total Blocks:', totalBlocks); + console.log('Batch Size:', batchSize); + console.log('Number of Batches:', numberOfBatches); - await run(client, jsonRpc, blockIndex, lastBlock, firstBlock, batchSize, numberOfBatches); + await run( + client, + jsonRpc, + blockIndex, + lastBlock, + firstBlock, + batchSize, + numberOfBatches + ); console.log(`Finished checking forked blocks!`); if (errorRanges.length > 0 || missingBlocks.length > 0) { @@ -180,7 +214,9 @@ async function scanChain(chain: string, args: any) { } if (errorRanges.length > 0) { - let path = `.repair/${chain}-${firstBlock + 2}-${lastBlock}-forked-blocks.json`; + let path = `.repair/${chain}-${ + firstBlock + 2 + }-${lastBlock}-forked-blocks.json`; if (args.outFile) { path = args.outFile + '-forked-blocks.json'; } @@ -188,7 +224,9 @@ async function scanChain(chain: string, args: any) { } if (missingBlocks.length > 0) { - let path = `.repair/${chain}-${firstBlock + 2}-${lastBlock}-missing-blocks.json`; + let path = `.repair/${chain}-${ + firstBlock + 2 + }-${lastBlock}-missing-blocks.json`; if (args.outFile) { path = args.outFile + '-missing-blocks.json'; } @@ -209,7 +247,6 @@ async function repairMissing(chain: string, file: string, args: any) { } async function repairChain(chain: string, file: string, args: any) { - const chainConfig = readChainConfig(chain); const config = readConnectionConfig(); const client = initESClient(config); @@ -243,7 +280,6 @@ async function repairChain(chain: string, file: string, args: any) { let deletePermissions = 0; for (const range of forkedBlocks) { - // ACTIONS const searchActions = { index: `${chain}-action-${chainConfig.settings.index_version}-*`, @@ -252,22 +288,52 @@ async function repairChain(chain: string, file: string, args: any) { body: { query: { bool: { - must: [{range: {block_num: {lte: range.start, gte: range.end}}}] - } - } - } + must: [ + { + range: { + block_num: { + lte: range.start, + gte: range.end, + }, + }, + }, + ], + }, + }, + }, }; if (args.dry) { const resultActions = await client.search(searchActions); - if ((resultActions.body.hits.total as estypes.SearchTotalHits)?.value > 0) { - deleteActions += (resultActions.body.hits.total as estypes.SearchTotalHits)?.value; + if ( + (resultActions.body.hits.total as estypes.SearchTotalHits) + ?.value > 0 + ) { + deleteActions += ( + resultActions.body.hits.total as estypes.SearchTotalHits + )?.value; } } else { - delete searchActions.size; - const deletedActionsResult = await client.deleteByQuery(searchActions); - if (deletedActionsResult && deletedActionsResult.body.deleted && deletedActionsResult.body.deleted > 0) { - deleteActions += deletedActionsResult.body.deleted; + const indexExists = await client.indices.exists({ + index: searchActions.index, + }); + + if (indexExists.body) { + delete searchActions.size; + const deletedActionsResult = await client.deleteByQuery( + searchActions + ); + if ( + deletedActionsResult && + deletedActionsResult.body.deleted && + deletedActionsResult.body.deleted > 0 + ) { + deleteActions += deletedActionsResult.body.deleted; + } + } else { + console.log( + `Index ${searchActions.index} doesn't exist. Unable to delete.` + ); } } @@ -279,22 +345,51 @@ async function repairChain(chain: string, file: string, args: any) { body: { query: { bool: { - must: [{range: {block_num: {lte: range.start, gte: range.end}}}] - } - } - } - } + must: [ + { + range: { + block_num: { + lte: range.start, + gte: range.end, + }, + }, + }, + ], + }, + }, + }, + }; if (args.dry) { const resultDeltas = await client.search(searchDeltas); - if ((resultDeltas.body.hits.total as estypes.SearchTotalHits)?.value > 0) { - deleteDeltas += (resultDeltas.body.hits.total as estypes.SearchTotalHits)?.value; + if ( + (resultDeltas.body.hits.total as estypes.SearchTotalHits) + ?.value > 0 + ) { + deleteDeltas += ( + resultDeltas.body.hits.total as estypes.SearchTotalHits + )?.value; } } else { - delete searchDeltas.size; - const deletedDeltasResult = await client.deleteByQuery(searchDeltas); - if (deletedDeltasResult && deletedDeltasResult.body.deleted && deletedDeltasResult.body.deleted > 0) { - deleteDeltas += deletedDeltasResult.body.deleted; + const indexExists = await client.indices.exists({ + index: searchDeltas.index, + }); + if (indexExists.body) { + delete searchDeltas.size; + const deletedDeltasResult = await client.deleteByQuery( + searchDeltas + ); + if ( + deletedDeltasResult && + deletedDeltasResult.body.deleted && + deletedDeltasResult.body.deleted > 0 + ) { + deleteDeltas += deletedDeltasResult.body.deleted; + } + } else { + console.log( + `Index ${searchDeltas.index} doesn't exist. Unable to delete.` + ); } } @@ -306,23 +401,49 @@ async function repairChain(chain: string, file: string, args: any) { body: { query: { bool: { - must: [{range: {block: {lte: range.start, gte: range.end}}}] - } - } - } - } + must: [ + { + range: { + block: { lte: range.start, gte: range.end }, + }, + }, + ], + }, + }, + }, + }; if (args.dry) { const resultAbis = await client.search(searchAbis); - if ((resultAbis.body.hits.total as estypes.SearchTotalHits)?.value > 0) { - deleteAbis += (resultAbis.body.hits.total as estypes.SearchTotalHits)?.value; - console.log('ABIs', {lte: range.start, gte: range.end}); + if ( + (resultAbis.body.hits.total as estypes.SearchTotalHits)?.value > + 0 + ) { + deleteAbis += ( + resultAbis.body.hits.total as estypes.SearchTotalHits + )?.value; + console.log('ABIs', { lte: range.start, gte: range.end }); } } else { - delete searchAbis.size; - const deletedAbisResult = await client.deleteByQuery(searchAbis); - if (deletedAbisResult && deletedAbisResult.body.deleted && deletedAbisResult.body.deleted > 0) { - deleteAbis += deletedAbisResult.body.deleted; + const indexExists = await client.indices.exists({ + index: searchAbis.index, + }); + if (indexExists.body) { + delete searchAbis.size; + const deletedAbisResult = await client.deleteByQuery( + searchAbis + ); + if ( + deletedAbisResult && + deletedAbisResult.body.deleted && + deletedAbisResult.body.deleted > 0 + ) { + deleteAbis += deletedAbisResult.body.deleted; + } + } else { + console.log( + `Index ${searchAbis.index} doesn't exist. Unable to delete.` + ); } } @@ -334,25 +455,61 @@ async function repairChain(chain: string, file: string, args: any) { body: { query: { bool: { - must: [{range: {block_num: {lte: range.start, gte: range.end}}}] - } - } - } - } + must: [ + { + range: { + block_num: { + lte: range.start, + gte: range.end, + }, + }, + }, + ], + }, + }, + }, + }; if (args.dry) { const resultAccounts = await client.search(searchAccounts); - if ((resultAccounts.body.hits.total as estypes.SearchTotalHits)?.value > 0) { - console.log('[WARNING]', (resultAccounts.body.hits.total as estypes.SearchTotalHits)?.value, 'accounts needs to be updated'); - deleteAccounts += (resultAccounts.body.hits.total as estypes.SearchTotalHits)?.value; + if ( + (resultAccounts.body.hits.total as estypes.SearchTotalHits) + ?.value > 0 + ) { + console.log( + '[WARNING]', + (resultAccounts.body.hits.total as estypes.SearchTotalHits) + ?.value, + 'accounts needs to be updated' + ); + deleteAccounts += ( + resultAccounts.body.hits.total as estypes.SearchTotalHits + )?.value; } } else { + + const indexExists = await client.indices.exists({ + index: searchAccounts.index, + }); + + if (indexExists.body) { delete searchAccounts.size; - const deletedAccountsResult = await client.deleteByQuery(searchAccounts); - if (deletedAccountsResult && deletedAccountsResult.body.deleted && deletedAccountsResult.body.deleted > 0) { + const deletedAccountsResult = await client.deleteByQuery( + searchAccounts + ); + if ( + deletedAccountsResult && + deletedAccountsResult.body.deleted && + deletedAccountsResult.body.deleted > 0 + ) { deleteAccounts += deletedAccountsResult.body.deleted; } + }else { + console.log( + `Index ${searchAccounts.index} doesn't exist. Unable to delete.` + ); } + } // VOTERS const searchVoters = { @@ -362,25 +519,61 @@ async function repairChain(chain: string, file: string, args: any) { body: { query: { bool: { - must: [{range: {block_num: {lte: range.start, gte: range.end}}}] - } - } - } - } + must: [ + { + range: { + block_num: { + lte: range.start, + gte: range.end, + }, + }, + }, + ], + }, + }, + }, + }; if (args.dry) { const resultVoters = await client.search(searchVoters); - if ((resultVoters.body.hits.total as estypes.SearchTotalHits)?.value > 0) { - console.log('[WARNING]', (resultVoters.body.hits.total as estypes.SearchTotalHits)?.value, 'voters needs to be updated'); - deleteVoters += (resultVoters.body.hits.total as estypes.SearchTotalHits)?.value; + if ( + (resultVoters.body.hits.total as estypes.SearchTotalHits) + ?.value > 0 + ) { + console.log( + '[WARNING]', + (resultVoters.body.hits.total as estypes.SearchTotalHits) + ?.value, + 'voters needs to be updated' + ); + deleteVoters += ( + resultVoters.body.hits.total as estypes.SearchTotalHits + )?.value; } } else { + const indexExists = await client.indices.exists({ + index: searchVoters.index, + }); + + if (indexExists.body) { + delete searchVoters.size; - const deletedVotersResult = await client.deleteByQuery(searchVoters); - if (deletedVotersResult && deletedVotersResult.body.deleted && deletedVotersResult.body.deleted > 0) { + const deletedVotersResult = await client.deleteByQuery( + searchVoters + ); + if ( + deletedVotersResult && + deletedVotersResult.body.deleted && + deletedVotersResult.body.deleted > 0 + ) { deleteVoters += deletedVotersResult.body.deleted; } + }else { + console.log( + `Index ${searchVoters.index} doesn't exist. Unable to delete.` + ); } + } // PROPOSALS const searchProposals = { @@ -390,25 +583,56 @@ async function repairChain(chain: string, file: string, args: any) { body: { query: { bool: { - must: [{range: {block_num: {lte: range.start, gte: range.end}}}] - } - } - } - } + must: [ + { + range: { + block_num: { + lte: range.start, + gte: range.end, + }, + }, + }, + ], + }, + }, + }, + }; if (args.dry) { const resultProposals = await client.search(searchProposals); - if ((resultProposals.body.hits.total as estypes.SearchTotalHits)?.value > 0) { - console.log('[WARNING]', (resultProposals.body.hits.total as estypes.SearchTotalHits)?.value, 'proposals needs to be updated'); - deleteProposals += (resultProposals.body.hits.total as estypes.SearchTotalHits)?.value; + if ( + (resultProposals.body.hits.total as estypes.SearchTotalHits) + ?.value > 0 + ) { + console.log( + '[WARNING]', + (resultProposals.body.hits.total as estypes.SearchTotalHits) + ?.value, + 'proposals needs to be updated' + ); + deleteProposals += ( + resultProposals.body.hits.total as estypes.SearchTotalHits + )?.value; } } else { + + + const indexExists = await client.indices.exists({index: searchProposals.index}); + + if (indexExists.body) { delete searchProposals.size; - const deletedProposalsResult = await client.deleteByQuery(searchProposals); - if (deletedProposalsResult && deletedProposalsResult.body.deleted && deletedProposalsResult.body.deleted > 0) { + const deletedProposalsResult = await client.deleteByQuery( + searchProposals + ); + if ( + deletedProposalsResult && + deletedProposalsResult.body.deleted && + deletedProposalsResult.body.deleted > 0 + ) { deleteProposals += deletedProposalsResult.body.deleted; } - } + }else { console.log(`Index ${searchProposals.index} doesn't exist. Unable to delete.`);} + } // LINKS const searchLinks = { @@ -418,25 +642,52 @@ async function repairChain(chain: string, file: string, args: any) { body: { query: { bool: { - must: [{range: {block_num: {lte: range.start, gte: range.end}}}] - } - } - } - } + must: [ + { + range: { + block_num: { + lte: range.start, + gte: range.end, + }, + }, + }, + ], + }, + }, + }, + }; if (args.dry) { const resultLinks = await client.search(searchLinks); - if ((resultLinks.body.hits.total as estypes.SearchTotalHits)?.value > 0) { - console.log('[WARNING]', (resultLinks.body.hits.total as estypes.SearchTotalHits)?.value, 'links needs to be updated'); - deleteLinks += (resultLinks.body.hits.total as estypes.SearchTotalHits)?.value; + if ( + (resultLinks.body.hits.total as estypes.SearchTotalHits) + ?.value > 0 + ) { + console.log( + '[WARNING]', + (resultLinks.body.hits.total as estypes.SearchTotalHits) + ?.value, + 'links needs to be updated' + ); + deleteLinks += ( + resultLinks.body.hits.total as estypes.SearchTotalHits + )?.value; } } else { + const indexExists = await client.indices.exists({index: searchLinks.index}); + + if (indexExists.body) { delete searchLinks.size; const deletedLinksResult = await client.deleteByQuery(searchLinks); - if (deletedLinksResult && deletedLinksResult.body.deleted && deletedLinksResult.body.deleted > 0) { + if ( + deletedLinksResult && + deletedLinksResult.body.deleted && + deletedLinksResult.body.deleted > 0 + ) { deleteLinks += deletedLinksResult.body.deleted; } - } + }else { console.log(`Index ${searchLinks.index} doesn't exist. Unable to delete.`);} + } // PERMISSIONS const searchPermissions = { @@ -446,38 +697,78 @@ async function repairChain(chain: string, file: string, args: any) { body: { query: { bool: { - must: [{range: {block_num: {lte: range.start, gte: range.end}}}] - } - } - } - } + must: [ + { + range: { + block_num: { + lte: range.start, + gte: range.end, + }, + }, + }, + ], + }, + }, + }, + }; if (args.dry) { - const resultPermissions = await client.search(searchPermissions); - if ((resultPermissions.body.hits.total as estypes.SearchTotalHits)?.value > 0) { - console.log('[WARNING]', (resultPermissions.body.hits.total as estypes.SearchTotalHits)?.value, 'permissions needs to be updated'); - console.log({lte: range.start, gte: range.end}); - deletePermissions += (resultPermissions.body.hits.total as estypes.SearchTotalHits)?.value; + const resultPermissions = await client.search( + searchPermissions + ); + if ( + (resultPermissions.body.hits.total as estypes.SearchTotalHits) + ?.value > 0 + ) { + console.log( + '[WARNING]', + ( + resultPermissions.body.hits + .total as estypes.SearchTotalHits + )?.value, + 'permissions needs to be updated' + ); + console.log({ lte: range.start, gte: range.end }); + deletePermissions += ( + resultPermissions.body.hits.total as estypes.SearchTotalHits + )?.value; } } else { + + const indexExists = await client.indices.exists({index: searchPermissions.index}); + if (indexExists.body) { delete searchPermissions.size; - const deletedPermissionsResult = await client.deleteByQuery(searchPermissions); - if (deletedPermissionsResult && deletedPermissionsResult.body.deleted && deletedPermissionsResult.body.deleted > 0) { + const deletedPermissionsResult = await client.deleteByQuery( + searchPermissions + ); + if ( + deletedPermissionsResult && + deletedPermissionsResult.body.deleted && + deletedPermissionsResult.body.deleted > 0 + ) { deletePermissions += deletedPermissionsResult.body.deleted; } - } + }else { console.log(`Index ${searchPermissions.index} doens't exist. Não foi possível realizar a exclusão.`);} + } for (const id of range.ids) { const searchBlocks = { index: blockIndex, body: { - query: {bool: {must: [{term: {block_id: {value: id}}}]}} - } + query: { + bool: { must: [{ term: { block_id: { value: id } } }] }, + }, + }, }; if (args.dry) { console.log(`Deleting block ${id}...`); - const resultBlocks = await client.search>(searchBlocks); - if (resultBlocks.body.hits.hits.length > 0 && resultBlocks.body.hits.hits[0]._source) { + const resultBlocks = await client.search< + SearchResponse + >(searchBlocks); + if ( + resultBlocks.body.hits.hits.length > 0 && + resultBlocks.body.hits.hits[0]._source + ) { deleteBlocks++; } } else { @@ -490,7 +781,9 @@ async function repairChain(chain: string, file: string, args: any) { } if (args.dry) { - console.log(`DRY-RUN: Would have deleted ${deleteBlocks} blocks, ${deleteActions} actions, ${deleteDeltas} deltas and ${deleteAbis} ABIs`); + console.log( + `DRY-RUN: Would have deleted ${deleteBlocks} blocks, ${deleteActions} actions, ${deleteDeltas} deltas and ${deleteAbis} ABIs` + ); console.dir({ blocks: deleteBlocks, actions: deleteActions, @@ -500,10 +793,12 @@ async function repairChain(chain: string, file: string, args: any) { voters: deleteVoters, proposals: deleteProposals, links: deleteLinks, - permissions: deletePermissions + permissions: deletePermissions, }); } else { - console.log(`Deleted ${deleteBlocks} blocks, ${deleteActions} actions, ${deleteDeltas} deltas and ${deleteAbis} ABIs`); + console.log( + `Deleted ${deleteBlocks} blocks, ${deleteActions} actions, ${deleteDeltas} deltas and ${deleteAbis} ABIs` + ); } await fillMissingBlocksFromFile(args.host, chain, file, args.dry); @@ -522,11 +817,11 @@ async function fillMissingBlocksFromFile(host, chain, file, dryRun) { async function sendChunk(chunk): Promise { return new Promise((resolve, reject) => { const payload = { - "event": "fill_missing_blocks", - "data": chunk + event: 'fill_missing_blocks', + data: chunk, }; controller.send(JSON.stringify(payload)); - + // Wait repair_completed confirmation controller.once('message', (data) => { const parsed = JSON.parse(data.toString()); @@ -543,21 +838,25 @@ async function fillMissingBlocksFromFile(host, chain, file, dryRun) { const parsedFile = JSON.parse(readFileSync(file).toString()); const chunkSize = 20; // Chunk size const totalLines = parsedFile.length; - + if (!dryRun) { let completedLines = 0; - + for (let i = 0; i < parsedFile.length; i += chunkSize) { const chunk = parsedFile.slice(i, i + chunkSize); await sendChunk(chunk); - + // Atualizar o progresso com base no número total de linhas completedLines += chunk.length; const progress = (completedLines / totalLines) * 100; - const progressBar = Array(Math.round(progress / 2)).fill('#').join(''); + const progressBar = Array(Math.round(progress / 2)) + .fill('#') + .join(''); process.stdout.clearLine(0); // Limpar a linha anterior process.stdout.cursorTo(0); // Mover o cursor para o início da linha - process.stdout.write(`Progress: [${progressBar}] ${progress.toFixed(2)}%`); + process.stdout.write( + `Progress: [${progressBar}] ${progress.toFixed(2)}%` + ); } console.log(); // Pule para a próxima linha após a conclusão controller.close(); @@ -576,7 +875,6 @@ async function fillMissingBlocksFromFile(host, chain, file, dryRun) { }); } - function viewFile(file: string) { const data = readFileSync(file, 'utf8'); const parsed = JSON.parse(data); @@ -590,8 +888,8 @@ program .description('CLI to find and repair forked and missing blocks on Hyperion') .version('0.2.2'); - -program.command('scan ') +program + .command('scan ') .description('scan for forked blocks') .option('-d, --dry', 'dry-run, do not delete or repair blocks') .option('-o, --out-file ', 'forked-blocks.json output file') @@ -600,24 +898,28 @@ program.command('scan ') .option('-b, --batch ', 'batch size to process') .action(scanChain); -program.command('repair ') +program + .command('repair ') .description('repair forked blocks') .option('-h, --host ', 'Hyperion local control api') .option('-d, --dry', 'dry-run, do not delete or repair blocks') .option('-t, --check-tasks', 'check for running tasks') .action(repairChain); -program.command('fill-missing ') +program + .command('fill-missing ') .description('write missing blocks') .option('-h, --host ', 'Hyperion local control api') .option('-d, --dry', 'dry-run, do not delete or repair blocks') .action(repairMissing); -program.command('view ') +program + .command('view ') .description('view forked blocks') .action(viewFile); -program.command('connect') +program + .command('connect') .option('-h, --host ', 'Hyperion local control api') .action(async (args) => { let hyperionIndexer = 'ws://localhost:4321'; @@ -633,12 +935,16 @@ program.command('connect') }); controller.on('close', () => { if (valid) { - console.log(`✅ Hyperion Indexer Online - ${hyperionIndexer}`); + console.log( + `✅ Hyperion Indexer Online - ${hyperionIndexer}` + ); } }); controller.on('error', (err) => { - console.log("Error:", err.message); - console.log(`Failed to connect on Hyperion Indexer at ${hyperionIndexer}, please use "--host ws://ADDRESS:PORT" to specify a remote indexer connection`); + console.log('Error:', err.message); + console.log( + `Failed to connect on Hyperion Indexer at ${hyperionIndexer}, please use "--host ws://ADDRESS:PORT" to specify a remote indexer connection` + ); }); } catch (e) { console.log(e); @@ -646,8 +952,3 @@ program.command('connect') }); program.parse(); - - - - -