ethereumblockchainweb3jsmetamask

Retrieving 24-hour Historic Token Balance in Ethereum (or Arbitrum) with MetaMask and Rabby Wallets


I'm working on a project where I need to find the balance of a specific token (not necessarily ETH) from 24 hours ago for a connected account. I have the block number from 24 hours ago from BE. Here's the code snippet I'm using:

export const getTokenBalanceByBlock = async (
  account: string,
  blockNumber: number,
  contractAddress: string,
  tokenPriceInETH: number,
): Promise<number> => {
  const tokenAbi: AbiItem[] = [
    {
      constant: true,
      inputs: [{ name: '_owner', type: 'address' }],
      name: 'balanceOf',
      outputs: [{ name: 'balance', type: 'uint256' }],
      type: 'function',
    },
  ]

  try {
    const web3 = new Web3(_window.ethereum)
    if (contractAddress) {
      const tokenContract = new web3.eth.Contract(tokenAbi, contractAddress)
      const tokenBalanceWei = await tokenContract.methods.balanceOf(account).call({}, blockNumber)
      console.log({ tokenBalanceWei })
      const tokenBalance = divideOnWei(tokenBalanceWei)
      return tokenPriceInETH ? tokenBalance * tokenPriceInETH : tokenBalance
    } else {
      const ethBalanceWei = await web3.eth.getBalance(account, blockNumber)
      const ethBalance = divideOnWei(ethBalanceWei)
      return ethBalance
    }
  } catch (error) {
    console.log(error)   
  }
}

This approach works fine when the user is connected via MetaMask. However, I encounter issues with the Rabby wallet and when the user switches to the Arbitrum Network. With Rabby wallet: { "code": -32000, "message": "missing trie node 907b6....fd2 (path ) state 0x907...8fd2 is not available, not found" } Or when switching to the Arbitrum Network, I get the same error.

  1. Is there a more efficient or reliable method to retrieve a 24-hour historic token balance for specific account?
  2. How can I address the errors encountered with the Rabby wallet and when switching to the Arbitrum Network?

Solution

  • The Historical state needed to fetch a token balance at a specific block is only available at archive nodes.

    You are hijacking your wallet's RPC connection. Whatever RPC connection you get from your wallet does not give you any guarantees you can use it for much of anything.