Web3js

web3.js:N次確認後呼叫事件處理程序

  • May 8, 2020

web3.js 似乎在確認後直接呼叫事件的事件處理程序。我想知道是否可以僅在使用 web3.js 進行 5 次確認後呼叫事件處理程序。目前有可能嗎?

是的。

下面是我用來等待 N 次交易確認的 TypeScript 程式碼。

範例用法:


// Call a ERC-20 method
const promiEvent = return token.methods.approve(contractAddr, numberOfTokens).send({ from: userAddress });

promiEvent.on("txHash", (hash) => {
  // We get transaction hash from MetaMask right after the user presses Confirm
  const receipt = await waitTransaction(web3, hash, {blocksToWait: 5, internal: 5000})
  // Do something with transaction of 5 confirmations
});
/**
* Wait transactions to be mined.
*
* Based on https://raw.githubusercontent.com/Kaisle/await-transaction-mined/master/index.js
*/

import Web3 from "web3";

const DEFAULT_INTERVAL = 1500;

const DEFAULT_BLOCKS_TO_WAIT = 1;

interface Options {

 // Poll delay in milliseconds
 interval: number;

 // How many blocks to wait
 blocksToWait: number;
}

/**
* Wait for one or multiple transactions to confirm.
* 
* Usage:
* ```
* const promiEvent = return this.oldToken.methods.approve(this.tokenSwapSmartContractAddress, inputs.fullBalance).send({ from: this.walletState.selectedAddress });
* promiEvent.on("txHash", (hash) => {
*  // We get transaction hash from MetaMask right after the user presses Confirm
*  const receipt = await waitTransaction(web3, hash, {blocksToWait: 5, internal: 5000})
*  // Do something with transaction of 5 confirmations
* });
* 
* ```
*
* @param web3
* @param txnHash A transaction hash or list of those
* @param options Wait timers
* @return Transaction receipt
*/
export function waitTransaction(
 web3: Web3,
 txnHash: string | string[],
 options: Options = null
): Promise<any> {
 const interval =
   options && options.interval ? options.interval : DEFAULT_INTERVAL;
 const blocksToWait =
   options && options.blocksToWait
     ? options.blocksToWait
     : DEFAULT_BLOCKS_TO_WAIT;
 var transactionReceiptAsync = async function(txnHash, resolve, reject) {
   try {
     var receipt = web3.eth.getTransactionReceipt(txnHash);
     if (!receipt) {
       setTimeout(function() {
         transactionReceiptAsync(txnHash, resolve, reject);
       }, interval);
     } else {
       if (blocksToWait > 0) {
         var resolvedReceipt = await receipt;
         if (!resolvedReceipt || !resolvedReceipt.blockNumber)
           setTimeout(function() {
             // this.logger.debug("Polling");
             transactionReceiptAsync(txnHash, resolve, reject);
           }, interval);
         else {
           try {
             var block = await web3.eth.getBlock(resolvedReceipt.blockNumber);
             var current = await web3.eth.getBlock("latest");
             if (current.number - block.number >= blocksToWait) {
               var txn = await web3.eth.getTransaction(txnHash);
               if (txn.blockNumber != null) resolve(resolvedReceipt);
               else
                 reject(
                   new Error(
                     "Transaction with hash: " +
                       txnHash +
                       " ended up in an uncle block."
                   )
                 );
             } else
               setTimeout(function() {
                 transactionReceiptAsync(txnHash, resolve, reject);
               }, interval);
           } catch (e) {
             setTimeout(function() {
               transactionReceiptAsync(txnHash, resolve, reject);
             }, interval);
           }
         }
       } else resolve(receipt);
     }
   } catch (e) {
     reject(e);
   }
 };

 // Resolve multiple transactions once
 if (Array.isArray(txnHash)) {
   var promises = [];
   txnHash.forEach(function(oneTxHash) {
     promises.push(waitTransaction(web3, oneTxHash, options));
   });
   return Promise.all(promises);
 } else {
   return new Promise(function(resolve, reject) {
     transactionReceiptAsync(txnHash, resolve, reject);
   });
 }
}

/**
* Check if the transaction was success based on the receipt.
*
* https://ethereum.stackexchange.com/a/45967/620
*
* @param receipt Transaction receipt
*/
export function isSuccessfulTransaction(receipt: any): boolean {

 // TODO:
 // Hack fix for WalletModal reporting status=false even
 // though the transaction clearly went through.
 // Likely a web3.js bug.
 // Events are still set even if the status is set false.


 // blockHash: "0xc57dbdc96983d558cccadb591299e029c517e2ae548b4a683eb6968ede460411"
 // blockNumber: 10005547
 // contractAddress: null
 // cumulativeGasUsed: 2923750
 // events:
 // Approval: {address: "0xAf30D2a7E90d7DC361c8C4585e9BB7D2F6f15bc7", blockHash: "0xc57dbdc96983d558cccadb591299e029c517e2ae548b4a683eb6968ede460411", blockNumber: 10005547, logIndex: 18, removed: false, …}
 // from: "0x9b3979464c0d9c79fc34a4d4e9177891c4ef0ddb"
 // gasUsed: 24773
 // status: false
 // to: "0xaf30d2a7e90d7dc361c8c4585e9bb7d2f6f15bc7"
 // transactionHash: "0x60781cd7c97281acc97d163641c6c211c47740f07abc36d63ce32ac158e9f9d2"
 // transactionIndex: 19
 if(receipt.events) {
   if(receipt.events.Approval || receipt.events.Staked || receipt.events.Swapped) {
     return true;
   }
 }

 if (receipt.status == "0x1" || receipt.status == 1) {
   return true;
 } else {
   return false;
 }
}

引用自:https://ethereum.stackexchange.com/questions/82833