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