主页 > imtoken钱包官方网站 > 使用 web3.js

使用 web3.js

imtoken钱包官方网站 2023-01-18 10:56:44

跟踪区块链中的以太坊交易

web3 API 不允许您直接订阅钱包交易区块链交易查询,因此为了解决我们的特定问题,我们不得不使用不同的策略。首先,我们订阅所有待处理的交易,然后按发件人的钱包地址和其他一些条件过滤它们。程序员

web3.js 允许我们通过包括 HTTP 和 WebSockets 在内的多种协议直接与以太坊节点对话。例如,我使用了 Rinkeby 的测试网和 Infura 提供的节点。但是,您可以自由使用任何其他提供程序,包括本地节点。 github

在下面显示的函数中,使用提供的 WebSockets 建立一个新的 Web3 实例,并用于创建对区块链中新建立的交易的订阅。此实例称为待处理。网络

可以使用两种方法 subscribe() 和 unsubscribe() 创建订阅对象。它们都接受回调函数来处理错误和订阅的任何结果。对于未决交易的订阅,我们可以处理两个事件:数据和错误。当然,数据是我们需要查找交易的事件。

数据事件处理程序只有一个输入参数,即交易哈希,如果需要比哈希更详细的信息,它会检查每笔交易是否符合我们的搜索条件。这是一个不同的 web3.js 方法,getTransaction(),可以用来读取交易详情。由于这是一个异步调用,我只需将其包装在 try-catch 语句中并等待响应。您可以在 Web3 官方文档中找到响应对象格式。

区块链交易查询

一旦收到响应并且交易符合我们的过滤条件,我们需要启动交易确认过程并通过调用其 unsubscribe() 方法取消订阅。如果我们没有满足过滤器的事务,我们只需从函数返回到订阅。函数如下所示:

function watchEtherTransfers() {
  // Instantiate web3 with WebSocket provider
  const web3 = new Web3(new Web3.providers.WebsocketProvider('wss://rinkeby.infura.io/ws'))
  // Instantiate subscription object
  const subscription = web3.eth.subscribe('pendingTransactions')
  // Subscribe to pending transactions
  subscription.subscribe((error, result) => { if (error) console.log(error) }) .on('data', async (txHash) => { try { // Instantiate web3 with HttpProvider const web3Http = new Web3('https://rinkeby.infura.io/') // Get transaction details const trx = await web3Http.eth.getTransaction(txHash) const valid = validateTransaction(trx) // If transaction is not valid, simply return if (!valid) return console.log('Found incoming Ether transaction from ' + process.env.WALLET_FROM + ' to ' + process.env.WALLET_TO); console.log('Transaction value is: ' + process.env.AMOUNT) console.log('Transaction hash is: ' + txHash + '\n') // Initiate transaction confirmation confirmEtherTransaction(txHash) // Unsubscribe from pending transactions. subscription.unsubscribe() } catch (error) { console.log(error) } }) }

请注意区块链交易查询,上面的示例使用 HttpProvider 来获取交易详细信息,因为使用 WebSocket 链接错误的风险要高得多。在我三十分钟的观察中,WebSocketProvider 至少有两个错误,而 HttpProvider 没有。

以太坊交易确认

区块链交易查询

一旦我们确定了需要监控的交易,我们就可以开始监控确认,直到它们达到所需的数量。

有一种很简单的确认方式,就是根据一笔交易最初开采时区块号的方法,即以当前区块号与交易区块号之差作为确认计算价值。要获得它,我建议使用下面列出的辅助函数。

async function getConfirmations(txHash) {
  try {
    // Instantiate web3 with HttpProvider
    const web3 = new Web3('https://rinkeby.infura.io/')
    // Get transaction details
    const trx = await web3.eth.getTransaction(txHash)
    // Get current block number
    const currentBlock = await web3.eth.getBlockNumber()
    // When transaction is unconfirmed, its block number is null.
    // In this case we return 0 as number of confirmations
    return trx.blockNumber === null ? 0 : currentBlock - trx.blockNumber
  }
  catch (error) {
    console.log(error)
  }
}

作为调用这个函数的结果,我们得到一个表示确认计算值的整数值。有些项目需要 100 次确认,有些少于 10 次,这就是我们必须递归使用此函数的原因。

区块链交易查询

在下面的示例中,我通过 setTimeout() 函数调用 getConfirmations() 来实现,但您可以通过其他方式实现。

我选择了 10 作为默认确认次数,并设置了 30 秒的间隔,这比以太坊的出块时间(10 到 19 秒)略多。

function confirmEtherTransaction(txHash, confirmations = 10) {
  setTimeout(async () => { // Get current number of confirmations and compare it with sought-for value const trxConfirmations = await getConfirmations(txHash) console.log('Transaction with hash ' + txHash + ' has ' + trxConfirmations + ' confirmation(s)') if (trxConfirmations >= confirmations) { // Handle confirmation event according to your business logic console.log('Transaction with hash ' + txHash + ' has been successfully confirmed') return } // Recursive call return confirmEtherTransaction(txHash, confirmations) }, 30 * 1000) }

监控 ERC20 代币

区块链交易查询

我们都知道,ERC20 代币是在以太坊上创建的智能合约,乍一看,监控 Ether 似乎很容易。在钱包中找到一定数量的加密交易和以太币是不一样的,因为交易的接收地址永远是智能合约的地址。但是,对于每次代币转移,都会调用一个特定于代币的合约函数。该函数调用区块链上的转账事件,成功后所有事件都被区块链记录下来,可以随时访问。

我们的目标是捕获满足请求的事务,直到它被发布到区块链,所以我们将使用相同的 WebSocketProvider。但是,我们将实例化代币合约对象并监听转账事件,而不是订阅该对象。

订阅和解析交易数据需要代币合约,因为行数据是十六进制格式,我们无法读取。对于合约对象的实例化,我们需要代币的 JSON-ABI(见示例)和部署在以太坊上的合约地址。

web3.js API 允许我们通过设置过滤事件的参数来过滤事件。在传输事件的情况下,这些参数是_from、_to 和_value。在设置订阅事件的选项对象时,还可以设置开始查找事件块号。

区块链交易查询

当我们过滤交易事件时,一旦它们出现在区块链上,我们就会得到查询到的交易,然后我们就可以进入确认阶段了。

function watchTokenTransfers() {
  // Instantiate web3 with WebSocketProvider
  const web3 = new Web3(new Web3.providers.WebsocketProvider('wss://rinkeby.infura.io/ws'))
  // Instantiate token contract object with JSON ABI and address
  const tokenContract = new web3.eth.Contract(
    TOKEN_ABI, process.env.TOKEN_CONTRACT_ADDRESS,
    (error, result) => { if (error) console.log(error) }
  )
  // Generate filter options
  const options = {
    filter: {
      _from:  process.env.WALLET_FROM,
      _to:    process.env.WALLET_TO,
      _value: process.env.AMOUNT
    },
    fromBlock: 'latest'
  }
  // Subscribe to Transfer events matching filter criteria
  tokenContract.events.Transfer(options, async (error, event) => { if (error) { console.log(error) return } console.log('Found incoming Pluton transaction from ' + process.env.WALLET_FROM + ' to ' + process.env.WALLET_TO + '\n'); console.log('Transaction value is: ' + process.env.AMOUNT) console.log('Transaction hash is: ' + txHash + '\n') // Initiate transaction confirmation confirmEtherTransaction(event.transactionHash) return }) }

以太交易对象遵循与转账交易相同的规则,这意味着我们可以在上面的例子中使用相同的 confirmEtherTransaction() 函数来处理以太交易。

最后

这些示例展示了如何专门跟踪 ERC20 代币转移,但同样的技术可以应用于任何其他智能合约功能,具体取决于您的业务需求。在上面的示例中,我总结了一个简单的 node.js 服务,可以作为区块链探索的起点。

我们构建了一个特殊的存储库,其中包含描述本文中所有状态的完整工作示例。为了能够在您的下一个项目的演示中使用它:

区块链追踪器示例源码