Ethers.js 事件侦听器 - 许多 getLogs/chainId/blocknumber 请求的预期行为?

Ethers.js event listeners - Expected behavior for many getLogs/chainId/blocknumber requests?

我正在构建一个铸造网站,要求我检查铸造的 NFT 数量并实时向用户显示该数字。

起初我只是每隔几秒发出一个请求来检索号码,但后来我想我可以使用事件侦听器来减少请求,因为人们只会在短时间内铸造。

但是,在使用了事件监听器之后,请求量上升了很多。看起来它一直在调用 blockNumber、chainId 和 getLogs。这就是事件监听器在幕后的工作方式吗?还是我做错了什么?

这是下一个 js API 路由,代码如下:

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import { ethers } from 'ethers'
import { contractAddress } from '../../helpers'
import type { NextApiRequest, NextApiResponse } from 'next'
import abi from '../../data/abi.json'
const NEXT_PUBLIC_ALCHEMY_KEY_GOERLI =
  process.env.NEXT_PUBLIC_ALCHEMY_KEY_GOERLI

let count = 0
let lastUpdate = 0

const provider = new ethers.providers.JsonRpcProvider(
  NEXT_PUBLIC_ALCHEMY_KEY_GOERLI,
  'goerli'
)

const getNumberMinted = async () => {
  console.log('RUNNING NUMBER MINTED - MAKING REQUEST', Date.now())
  const provider = new ethers.providers.JsonRpcProvider(
    NEXT_PUBLIC_ALCHEMY_KEY_GOERLI,
    'goerli'
  )
  const contract = new ethers.Contract(contractAddress, abi.abi, provider)
  const numberMinted = await contract.functions.totalSupply()
  count = Number(numberMinted)
  lastUpdate = Date.now()
}
const contract = new ethers.Contract(contractAddress, abi.abi, provider)
contract.on('Transfer', (to, amount, from) => {
  console.log('running event listener')
  if (lastUpdate < Date.now() - 5000) {
    getNumberMinted()
  }
})

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  try {
    res.setHeader('Content-Type', 'application/json')
    res.status(200).json({ count })
  } catch (err) {
    res
      .status(500)
      .json({ error: 'There was an error from the server, please try again' })
  }
}

如果您使用 AlchemyProvider 或直接使用 StaticJsonRpcProvider(ApchemyProvider 继承),您将消除 chainId 调用;这些用于确保网络没有改变,但如果您使用 third-party 服务,如 Alchemy 或 INFURA,这不是问题,这就是 StaticJsonRpcProvider 存在的原因。 :)

然后每pollingInterval,进行一次getBlockNumber(因为这是一个相对便宜的调用)来检测新块何时发生;当一个新块出现时,它使用 getLogs 方法查找该块期间发生的任何日志。这最大限度地减少了昂贵的getLogs方法的数量。

您可以增加或减少 pollingInterval 到 trade-off 的服务器资源成本延迟。

这就是活动的运作方式。 :)

这有意义吗?