From 5b268794afd6a3958c86122f30a013124d9dda17 Mon Sep 17 00:00:00 2001 From: softsimon Date: Sun, 24 Jan 2021 02:51:22 +0700 Subject: [PATCH] Correctly error handle getTransaction and set 404 status when not found. --- backend/src/api/bitcoin/bitcoin-api.ts | 13 ++++++++--- backend/src/api/bitcoin/bitcoin-base.api.ts | 13 ----------- backend/src/api/blocks.ts | 13 ++++++----- backend/src/api/mempool.ts | 8 +++---- backend/src/api/transaction-utils.ts | 20 ++++++----------- backend/src/api/websocket-handler.ts | 24 ++++++++++++++------- backend/src/routes.ts | 19 ++++++++-------- 7 files changed, 55 insertions(+), 55 deletions(-) diff --git a/backend/src/api/bitcoin/bitcoin-api.ts b/backend/src/api/bitcoin/bitcoin-api.ts index c40ab031c..b5e3843db 100644 --- a/backend/src/api/bitcoin/bitcoin-api.ts +++ b/backend/src/api/bitcoin/bitcoin-api.ts @@ -5,7 +5,6 @@ import { AbstractBitcoinApi } from './bitcoin-api-abstract-factory'; import { IBitcoinApi } from './bitcoin-api.interface'; import { IEsploraApi } from './esplora-api.interface'; import blocks from '../blocks'; -import bitcoinBaseApi from './bitcoin-base.api'; import mempool from '../mempool'; import { TransactionExtended } from '../../mempool.interfaces'; @@ -202,12 +201,12 @@ class BitcoinApi implements AbstractBitcoinApi { } let mempoolEntry: IBitcoinApi.MempoolEntry; if (!mempool.isInSync() && !this.rawMempoolCache) { - this.rawMempoolCache = await bitcoinBaseApi.$getRawMempoolVerbose(); + this.rawMempoolCache = await this.$getRawMempoolVerbose(); } if (this.rawMempoolCache && this.rawMempoolCache[transaction.txid]) { mempoolEntry = this.rawMempoolCache[transaction.txid]; } else { - mempoolEntry = await bitcoinBaseApi.$getMempoolEntry(transaction.txid); + mempoolEntry = await this.$getMempoolEntry(transaction.txid); } transaction.fee = mempoolEntry.fees.base * 100000000; return transaction; @@ -238,6 +237,14 @@ class BitcoinApi implements AbstractBitcoinApi { return this.bitcoindClient.validateAddress(address); } + private $getMempoolEntry(txid: string): Promise { + return this.bitcoindClient.getMempoolEntry(txid); + } + + private $getRawMempoolVerbose(): Promise { + return this.bitcoindClient.getRawMemPool(true); + } + private async $calculateFeeFromInputs(transaction: IEsploraApi.Transaction, addPrevout: boolean): Promise { if (transaction.vin[0].is_coinbase) { transaction.fee = 0; diff --git a/backend/src/api/bitcoin/bitcoin-base.api.ts b/backend/src/api/bitcoin/bitcoin-base.api.ts index 4be018211..2384c92e2 100644 --- a/backend/src/api/bitcoin/bitcoin-base.api.ts +++ b/backend/src/api/bitcoin/bitcoin-base.api.ts @@ -40,19 +40,6 @@ class BitcoinBaseApi { } return this.bitcoindClient.getMempoolInfo(); } - - $getRawTransaction(txId: string): Promise { - return this.bitcoindClient.getRawTransaction(txId, true); - } - - $getMempoolEntry(txid: string): Promise { - return this.bitcoindClient.getMempoolEntry(txid); - } - - $getRawMempoolVerbose(): Promise { - return this.bitcoindClient.getRawMemPool(true); - } - } export default new BitcoinBaseApi(); diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index bee53db9c..e567fb459 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -73,11 +73,12 @@ class Blocks { let findCoinbaseTxTries = 0; // It takes Electrum Server a few seconds to index the transaction after a block is found while (findCoinbaseTxTries < 5 && !txFound) { - const tx = await transactionUtils.$getTransactionExtended(txIds[i]); - if (tx) { + try { + const tx = await transactionUtils.$getTransactionExtended(txIds[i]); txFound = true; transactions.push(tx); - } else { + } catch (e) { + logger.debug('Coinbase transaction fetch error: ' + e.message || e); await Common.sleep(1000); findCoinbaseTxTries++; } @@ -88,9 +89,11 @@ class Blocks { transactionsFound++; } else if (config.MEMPOOL.BACKEND === 'esplora' || memPool.isInSync()) { logger.debug(`Fetching block tx ${i} of ${txIds.length}`); - const tx = await transactionUtils.$getTransactionExtended(txIds[i]); - if (tx) { + try { + const tx = await transactionUtils.$getTransactionExtended(txIds[i]); transactions.push(tx); + } catch (e) { + logger.debug('Error fetching block tx: ' + e.message || e); } } } diff --git a/backend/src/api/mempool.ts b/backend/src/api/mempool.ts index 7ec3a93a2..cccb532e2 100644 --- a/backend/src/api/mempool.ts +++ b/backend/src/api/mempool.ts @@ -103,8 +103,8 @@ class Mempool { for (const txid of transactions) { if (!this.mempoolCache[txid]) { - const transaction = await transactionUtils.$getTransactionExtended(txid, true); - if (transaction) { + try { + const transaction = await transactionUtils.$getTransactionExtended(txid, true); this.mempoolCache[txid] = transaction; txCount++; if (this.inSync) { @@ -121,8 +121,8 @@ class Mempool { logger.debug('Fetched transaction ' + txCount); } newTransactions.push(transaction); - } else { - logger.debug('Error finding transaction in mempool.'); + } catch (e) { + logger.debug('Error finding transaction in mempool: ' + e.message || e); } } diff --git a/backend/src/api/transaction-utils.ts b/backend/src/api/transaction-utils.ts index 1b7fda068..471d9304f 100644 --- a/backend/src/api/transaction-utils.ts +++ b/backend/src/api/transaction-utils.ts @@ -20,20 +20,14 @@ class TransactionUtils { }; } - public async $getTransactionExtended(txId: string, forceBitcoind = false, addPrevouts = false): Promise { - try { - let transaction: IEsploraApi.Transaction; - if (forceBitcoind) { - transaction = await bitcoinApi.$getRawTransactionBitcoind(txId, false, addPrevouts); - } else { - transaction = await bitcoinApi.$getRawTransaction(txId, false, addPrevouts); - } - return this.extendTransaction(transaction); - } catch (e) { - logger.debug('getTransactionExtended error: ' + (e.message || e)); - logger.debug(JSON.stringify(e)); - return null; + public async $getTransactionExtended(txId: string, forceBitcoind = false, addPrevouts = false): Promise { + let transaction: IEsploraApi.Transaction; + if (forceBitcoind) { + transaction = await bitcoinApi.$getRawTransactionBitcoind(txId, false, addPrevouts); + } else { + transaction = await bitcoinApi.$getRawTransaction(txId, false, addPrevouts); } + return this.extendTransaction(transaction); } private extendTransaction(transaction: IEsploraApi.Transaction): TransactionExtended { diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index 35d11c37c..9c75d8369 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -219,9 +219,11 @@ class WebsocketHandler { const tx = newTransactions.find((t) => t.txid === client['track-mempool-tx']); if (tx) { if (config.MEMPOOL.BACKEND !== 'esplora') { - const fullTx = await transactionUtils.$getTransactionExtended(tx.txid, false, true); - if (fullTx) { + try { + const fullTx = await transactionUtils.$getTransactionExtended(tx.txid, false, true); response['tx'] = fullTx; + } catch (e) { + logger.debug('Error finding transaction in mempool: ' + e.message || e); } } else { response['tx'] = tx; @@ -237,9 +239,11 @@ class WebsocketHandler { const someVin = tx.vin.some((vin) => !!vin.prevout && vin.prevout.scriptpubkey_address === client['track-address']); if (someVin) { if (config.MEMPOOL.BACKEND !== 'esplora') { - const fullTx = await transactionUtils.$getTransactionExtended(tx.txid, false, true); - if (fullTx) { + try { + const fullTx = await transactionUtils.$getTransactionExtended(tx.txid, false, true); foundTransactions.push(fullTx); + } catch (e) { + logger.debug('Error finding transaction in mempool: ' + e.message || e); } } else { foundTransactions.push(tx); @@ -249,9 +253,11 @@ class WebsocketHandler { const someVout = tx.vout.some((vout) => vout.scriptpubkey_address === client['track-address']); if (someVout) { if (config.MEMPOOL.BACKEND !== 'esplora') { - const fullTx = await transactionUtils.$getTransactionExtended(tx.txid, false, true); - if (fullTx) { + try { + const fullTx = await transactionUtils.$getTransactionExtended(tx.txid, false, true); foundTransactions.push(fullTx); + } catch (e) { + logger.debug('Error finding transaction in mempool: ' + e.message || e); } } else { foundTransactions.push(tx); @@ -298,9 +304,11 @@ class WebsocketHandler { if (client['track-tx'] === rbfTransaction) { const rbfTx = rbfTransactions[rbfTransaction]; if (config.MEMPOOL.BACKEND !== 'esplora') { - const fullTx = await transactionUtils.$getTransactionExtended(rbfTransaction, false, true); - if (fullTx) { + try { + const fullTx = await transactionUtils.$getTransactionExtended(rbfTransaction, false, true); response['rbfTransaction'] = fullTx; + } catch (e) { + logger.debug('Error finding transaction in mempool: ' + e.message || e); } } else { response['rbfTransaction'] = rbfTx; diff --git a/backend/src/routes.ts b/backend/src/routes.ts index e35164ab0..fc0357bb2 100644 --- a/backend/src/routes.ts +++ b/backend/src/routes.ts @@ -532,14 +532,13 @@ class Routes { public async getTransaction(req: Request, res: Response) { try { const transaction = await transactionUtils.$getTransactionExtended(req.params.txId, false, true); - - if (transaction) { - res.json(transaction); - } else { - res.status(500).send('Error fetching transaction.'); - } + res.json(transaction); } catch (e) { - res.status(500).send(e.message || e); + let statusCode = 500; + if (e.message && e.message.indexOf('No such mempool or blockchain transaction') > -1) { + statusCode = 404; + } + res.status(statusCode).send(e.message || e); } } @@ -599,10 +598,12 @@ class Routes { const endIndex = Math.min(startingIndex + 10, txIds.length); for (let i = startingIndex; i < endIndex; i++) { - const transaction = await transactionUtils.$getTransactionExtended(txIds[i], false, true); - if (transaction) { + try { + const transaction = await transactionUtils.$getTransactionExtended(txIds[i], false, true); transactions.push(transaction); loadingIndicators.setProgress('blocktxs-' + req.params.hash, (i + 1) / endIndex * 100); + } catch (e) { + logger.debug('getBlockTransactions error: ' + e.message || e); } } res.json(transactions);