Stuck trying to write web3 RPC BalanceOf to get users metamask smartcontract token balance

Viewed 1460

I've been trying to use the new JSON RPC methods https://docs.metamask.io/guide/rpc-api.html#ethereum-json-rpc-methods to create a simple web page that can return the token balance of an ERC20 smart contract in metamask account.

I've only been able to successfully retrieve the balance of ethereum (with the following code)

  try {
     balance = await ethereum
    .request({
      method: 'eth_getBalance',
      params: [address,"latest"],
    })
    // covert to readable format (account for decimals)
     read = parseInt(balance) / 10**18; // will need change based on what token
    console.log( "Smart Contract Token Balance:" + read.toFixed(5) );

  } catch (error) {
    console.log(error);
  }

Of course, the above returns the ethereum amount for the address.

For the life of me, I haven't been able to figure version of this using the new JSON-RPC methods and don't see any examples of calling a smart contract method like "balanceOf":

  var contract = new web3.eth.Contract(theAbi, theTokenAddress);

  balance = await contract.methods.balanceOf(theTokenAddress).call().then(console.log);

I've been stuck on this for weeks on/off as a side project and well, any pointers as I'm sure what I'm trying to do is basic - I just setup an account on StackOverflow for the first time to post. Thank you

Also note, I'm linking this version of web3 https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js

2 Answers

Hi I came across your question while I was looking for similar issues. web3.eth methods are not working for me.

As per MetaMask there are breaking changes, check following link https://medium.com/metamask/breaking-changes-to-the-metamask-provider-are-here-7b11c9388be9 as per this

As of today, MetaMask has stopped injecting window.web3, and made a limited number of breaking changes to our Ethereum Provider API (window.ethereum).

MetaMask has library for legacy code, but they don't recommend it.

So instead of window.web3 we have to use window.ethereum. Web3 docs still has old ways and tutorials which are there are older. No use.

In my case I am trying to convert existing react tutorial from Dapp university ( https://www.youtube.com/watch?v=CgXQC4dbGUE ) to Angular 11, truffle (v5.4.1), web3.js ( v1.4.0), Ganache. But not able to move ahead from getting balance.

Here is my code

import { Component, OnInit } from '@angular/core';
import Web3 from 'web3';
import DaiToken from '../../build/contracts/DaiToken.json';
import DappToken from '../../build/contracts/DappToken.json';
import TokenFarm from '../../build/contracts/TokenFarm.json';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})

export class AppComponent implements OnInit {
  accounts: any;
  investorAccount: string = '0x0';
  daiToken: any = {};
  dappToken: any = {};
  tokenFarm: any = {};
  daiTokenBalance: string = '0';
  dappTokenBalance: string = '0';
  stakingBalance: string = '0';
  loading: boolean = true;
  web3: any;

  constructor() {}
    ngOnInit() {
      this.bootstrapWeb3();
    }
    async bootstrapWeb3() {
      await this.loadWeb3();
      await this.loadBlockchainData();
    }

    async loadWeb3() {
      if (window.ethereum) {
        // await window.ethereum.enable();  
        // no longer required, as line below does the same thing

        this.accounts = await window.ethereum.request({
          method: 'eth_requestAccounts'
        });
        window.web3 = new Web3(window.ethereum);

      } else if (window.web3) {
        window.web3 = new Web3(window.web3.currentProvider);
      } else {
        window.alert('Non-Ethereum browser detected. You should consider trying MetaMask!');
      }
    }

    async loadBlockchainData() {
      this.web3 = window.web3;
      // const accounts = await web3.eth.getAccounts();  <-----   Not working with latest metamask changes
      this.investorAccount = this.accounts[0];
      try {
        // Get networkId
        const networkId = await window.ethereum.request({
          method: 'net_version'
        });
        // const networkId = await web3.eth.net.getId().then(id => console.log(id)); // Not working

        const daiTokenData = DaiToken.networks[networkId];

        // Load DaiToken
        if (daiTokenData) {
          const daiToken = new window.web3.eth.Contract(DaiToken.abi, daiTokenData.address);
          this.daiToken = daiToken;

          //  balanceOf not working
          let daiTokenBalance = await daiToken.methods.balanceOf(this.investorAccount).call();

          this.daiTokenBalance = daiTokenBalance.toString();
        } else {
          window.alert('DaiToken contract not deployed to detected network.');
        }
      } catch (error) {
        console.log(error);
      }
    }
}

Whenever I try to call window.web3.eth or other methods it won't run or return any error. Not sure what changes needed to be done. Still looking for example with latest changes with MetaMask and web3.js. Will try to update once I find anything.

If anyone has more info on latest MetaMask, web3js please share.

Short answer is to get user account address from client side, and then retrieve balance of the account for whatever token you are interested in from server side.

Related