Infura calls eth_getBlockByNumber ten times for each eth_call

Viewed 722

I am trying to make a simple nextjs API route (https://nextjs.org/docs/api-routes/introduction) that is connected to the Ethereum blockchain to perform a view function (requires no gas) from a smart contract.

I have a system where you can buy the rights to mint a NFT (ERC721), and this functions checks if the user has paid for any collectionIds that is not yet minted.


import Web3 from 'web3'

import { getPaidForCollectionsIds } from '../../database'
const mnemonic2 = 'main check ...'
var HDWalletProvider = require('truffle-hdwallet-provider')

export default async function (req, res) {
  const paidFor = await getPaidForCollectionsIds(req.body.userId)

  if (paidFor.length < 1) return res.json({ data: [] })

  const provider = new HDWalletProvider(mnemonic2, 'https://rinkeby.infura.io/v3/INFURAAPIKEY', 0)
  const web3 = new Web3(provider)

  const TheContractAddress = '0xfbeF...'
  const { abi } = require('../../abis/TheContract.json')
  const KS = new web3.eth.Contract(abi, TheContractAddress, {
    from: '0x5EE...', // default from address
    gasPrice: '20000000000' // default gas price in wei, 20 gwei in this case
  })

  const unminted = []

  await Promise.all(paidFor.data.map(async pf => KS.methods.readCollectionIdIsUsed(pf.collectionId).call().then(d => {
        console.log(d, 'readCollectionIdIsUsed', pf.collectionId)
      }).catch(e => {
         unminted.push(sign)
      })
    )
  }))

  res.statusCode = 200
  res.json({ data: unminted })
}


here is the code from the readCollectionIdIsUsed method in the smart contract:

    mapping (uint256 => bool) collectionIdIsUsed;

    function readCollectionIdIsUsed(uint256 collectionId) external view returns (bool res) {
        require(collectionIdIsUsed[collectionId], 'This signature has not been used');
        res = collectionIdIsUsed[collectionId];
    }

This all works fine, except for that after a while, I reach the 100 000 request limit of infura.

infura top methods

I dont know why it is calling eth_getBlockByNumber 10 times for each call, is this necessary or is there a way around it?

1 Answers

Web3.js should not do this for calls, but should do for sends.

This is because when you await any web3.js contract methods, it has internal, somewhat unexpected, implied "wait X number of blocks before tx is confirmed" mechanism and somehow this get triggered, although your example code does not seem to have any contract writes. It is documented here.

Because you are using HTTPS connections instead of WebSocket connection, Web3.js needs to poll the new block numbers for confirmations. But if you switch to WebSocket infura provider, these calls should disappear, as Web3.js can simply subscribe to WebSocket new block detected events.

Related