javascriptweb3jsweb3-react

How to handle the error thrown by "_fireError" in web3.js?


I was trying to catch the error thrown by the web3.js during the calling of a function in my smart contract. This is the code I use for calling the function:

                contract.methods.mintBatch(quantity, data.nonce, data.hash, data.signature, data.nftIds, 1).send({ from: walletId, value: res * quantity }, (err: any, res: any) => {
                  if (err) {
                    console.error('mintBatch failed, error: ', err);
                    reject();
                  }
                  else {
                    console.log('mintBatch succeed, res: ', res);
                    resolve({
                      txHash: res,
                      nftIds: data.nftIds
                    });
                  }
                })

And this is the function I use to keep tracking the status of a transaction:

  function checkIfTransactionProceed(txHash: string) {
    return new Promise<void>(async (resolve, reject) => {
      var receipt = null;
      var counter = 0;
      try {
        while ((receipt = await web3.eth.getTransactionReceipt(txHash)) === null) {
          if (counter++ > 300) {
            break;
          }
          await new Promise<void>(resolve2 => {
              setTimeout(() => {
                  resolve2();
              }, 1000);
          });
        }
        if (receipt && (receipt.status === true)) {
          resolve();
        }
        else {
          reject();
        }
      }
      catch(err) {
        console.error('web3.eth.getTransactionReceipt failed, error: ', err);
        reject();
      }
    })
  }

The second one works perfectly, and it will throw an error when the transaction fails. But right after that error is thrown, this is given by my react frontend:

Unhandled Runtime Error
Error: Transaction has been reverted by the EVM:
{
  "blockHash": "0x2d7a0a4e5469e68250eaee0c52eb80559d6f9e2a8873ab4f7b2f47e5e9b973b3",
  "blockNumber": 11284056,
  "contractAddress": null,
  "cumulativeGasUsed": 368714,
  "effectiveGasPrice": 2500000009,
  "from": "somewhere",
  "gasUsed": 76047,
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "status": false,
  "to": "somewhere else",
  "transactionHash": "a random transaction hash",
  "transactionIndex": 2,
  "type": "0x2",
  "events": {}
}

By tracking the error, it seems the error comes from a function called _fireError inside the web3.js.

var _fireError = function (error, emitter, reject, callback, optionalData) {
    /*jshint maxcomplexity: 10 */
    // add data if given
    if (!!error && typeof error === 'object' && !(error instanceof Error) && error.data) {
        if (!!error.data && typeof error.data === 'object' || Array.isArray(error.data)) {
            error.data = JSON.stringify(error.data, null, 2);
        }
        error = error.message + "\n" + error.data;
    }
    if (typeof error === 'string') {
        error = new Error(error);
    }
    if (typeof callback === 'function') {
        callback(error, optionalData);
    }
    if (typeof reject === 'function') {
        // suppress uncatched error if an error listener is present
        // OR suppress uncatched error if an callback listener is present
        if (emitter &&
            (typeof emitter.listeners === 'function' &&
                emitter.listeners('error').length) || typeof callback === 'function') {
            emitter.catch(function () { });
        }
        // reject later, to be able to return emitter
        setTimeout(function () {
            reject(error);
        }, 1);
    }
    if (emitter && typeof emitter.emit === 'function') {
        // emit later, to be able to return emitter
        setTimeout(function () {
            emitter.emit('error', error, optionalData);
            emitter.removeAllListeners();
        }, 1);
    }
    return emitter;
};

Can anyone let me know how to catch that error? It doesn't trigger any catcher on my end, and that "mintBatch failed" isn't shown either.


Solution

  • Turns out the "err" inside the function call is not working. I have to use this way instead in order to catch that error.

            contract.methods.mintBatch(quantity, data.nonce, data.hash, data.signature, data.nftIds, 1).send({ from: walletId, value: res * quantity }, (err: any, res: any) => {
              if (err) {
                console.error('mintBatch failed, error: ', err);
                reject();
              }
              else {
                console.log('mintBatch succeed, res: ', res);
                resolve({
                  txHash: res,
                  nftIds: data.nftIds
                });
              }
            })
            .catch((err: any) => {
              // Handle the error here
              reject();
            })