diff --git a/src/block-data-providers/esplora.provider.ts b/src/block-data-providers/esplora.provider.ts index 336308c..212ad65 100644 --- a/src/block-data-providers/esplora.provider.ts +++ b/src/block-data-providers/esplora.provider.ts @@ -12,6 +12,7 @@ import { IndexerService, TransactionInput } from '@/indexer/indexer.service'; type EsploraOperationState = { currentBlockHeight: number; indexedBlockHeight: number; + lastProcessedTxIndex: number; }; type EsploraTransactionInput = { @@ -110,6 +111,7 @@ export class EsploraProvider BitcoinNetwork.MAINNET ? TAPROOT_ACTIVATION_HEIGHT - 1 : 0, + lastProcessedTxIndex: 0, }; await this.setState(state); } @@ -162,33 +164,59 @@ export class EsploraProvider } private async processBlock(height: number, hash: string) { + const state = await this.getState(); const txids = await this.getTxidsForBlock(hash); - for (let i = 1; i < txids.length; i += this.batchSize) { + for ( + let i = state.lastProcessedTxIndex + 1; + i < txids.length; + i += this.batchSize + ) { const batch = txids.slice( i, Math.min(i + this.batchSize, txids.length), ); - await Promise.all( - batch.map(async (txid) => { - const tx = await this.getTx(txid); - const vin: TransactionInput[] = tx.vin.map((input) => ({ - txid: input.txid, - vout: input.vout, - scriptSig: input.scriptsig, - prevOutScript: input.prevout.scriptpubkey, - witness: input.witness, - })); - const vout = tx.vout.map((output) => ({ - scriptPubKey: output.scriptpubkey, - value: output.value, - })); + try { + await Promise.all( + batch.map(async (txid) => { + const tx = await this.getTx(txid); + const vin: TransactionInput[] = tx.vin.map((input) => ({ + txid: input.txid, + vout: input.vout, + scriptSig: input.scriptsig, + prevOutScript: input.prevout.scriptpubkey, + witness: input.witness, + })); + const vout = tx.vout.map((output) => ({ + scriptPubKey: output.scriptpubkey, + value: output.value, + })); - await this.indexTransaction(txid, vin, vout, height, hash); - }, this), - ); + await this.indexTransaction( + txid, + vin, + vout, + height, + hash, + ); + }, this), + ); + + state.lastProcessedTxIndex = i + this.batchSize - 1; + await this.setState(state); + } catch (error) { + this.logger.error( + `Error processing transactions in block at height ${height}, hash ${hash}: ${error.message}`, + ); + throw error; + } } + state.indexedBlockHeight = height; + state.lastProcessedTxIndex = 0; + await this.setState(state); + + this.isSyncing = false; } async request(config: AxiosRequestConfig): Promise {