Correctly error handle getTransaction and set 404 status when not found.
This commit is contained in:
		
							parent
							
								
									fb41f58f7c
								
							
						
					
					
						commit
						5b268794af
					
				| @ -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<IBitcoinApi.MempoolEntry> { | ||||
|     return this.bitcoindClient.getMempoolEntry(txid); | ||||
|   } | ||||
| 
 | ||||
|   private $getRawMempoolVerbose(): Promise<IBitcoinApi.RawMempool> { | ||||
|     return this.bitcoindClient.getRawMemPool(true); | ||||
|   } | ||||
| 
 | ||||
|   private async $calculateFeeFromInputs(transaction: IEsploraApi.Transaction, addPrevout: boolean): Promise<IEsploraApi.Transaction> { | ||||
|     if (transaction.vin[0].is_coinbase) { | ||||
|       transaction.fee = 0; | ||||
|  | ||||
| @ -40,19 +40,6 @@ class BitcoinBaseApi { | ||||
|     } | ||||
|     return this.bitcoindClient.getMempoolInfo(); | ||||
|   } | ||||
| 
 | ||||
|   $getRawTransaction(txId: string): Promise<IBitcoinApi.Transaction> { | ||||
|     return this.bitcoindClient.getRawTransaction(txId, true); | ||||
|   } | ||||
| 
 | ||||
|   $getMempoolEntry(txid: string): Promise<IBitcoinApi.MempoolEntry> { | ||||
|     return this.bitcoindClient.getMempoolEntry(txid); | ||||
|   } | ||||
| 
 | ||||
|   $getRawMempoolVerbose(): Promise<IBitcoinApi.RawMempool> { | ||||
|     return this.bitcoindClient.getRawMemPool(true); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| export default new BitcoinBaseApi(); | ||||
|  | ||||
| @ -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); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
| @ -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); | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|  | ||||
| @ -20,20 +20,14 @@ class TransactionUtils { | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   public async $getTransactionExtended(txId: string, forceBitcoind = false, addPrevouts = false): Promise<TransactionExtended | null> { | ||||
|     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<TransactionExtended> { | ||||
|     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 { | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user