I want to create a simple front-end for my DApp. The DApp fetches values about the smart contract to display on the site. If the reader wants to interact (eg. buy) with the smart contract, I have a 'connect' button that prompts the user to allow MetaMask access.

How do I approach separating something basic like this - the separation between read-only values Web3 needs, and the user-calling Web3 performs?

Here's the issue I'm facing;

export function App() {
  async function connectPrompt() {
    const chainId = await web3.eth.getChainId()

    if(chainId != 80001) {
      alert("Wrong network! Switch to Polygon (Matic)");

    const provider = await web3Modal.connect();
    setWeb3(new Web3(provider))
    const firstAccount = await web3.eth.getAccounts()

  async function disconnect() {
    await web3Modal.clearCachedProvider();

  const [account, setAccount] = useState('');
  const [web3, setWeb3] = useState(new Web3('https://rpc-mumbai.matic.today'));

  const providerOptions = {};
  const web3Modal = new Web3Modal({
    network: "mainnet", 
    cacheProvider: true,
    providerOptions // required

  const address = '0x...0'

  const contract = new web3.eth.Contract(abi, contract)

  return ( //rest of app...)

This is my setup. I use Web3 to connect to Matic, where my contract is. I can then use this to get whatever read-only values I want (eg. totalSupply). The user can click a button which calls connectPrompt(), which handles logging in. If the user isn't on Matic, don't connect. If they are, connect.

The issue I'm having is that if the user is that web3 is always on Matic, since I set it that way in useState. If I use givenProvider() instead to check, like;

  async function connectPrompt() {
    const tempWeb3 = new Web3(Web3.givenProvider)
    const chainId = await tempWeb3.eth.getChainId()
    //const chainId = await web3.eth.getChainId()

    if(chainId != 80001) {
      alert("Wrong network! Switch to Polygon (Matic)");

this sort of works, but it's super janky. Sometimes, on the first click, it will actually connect, but then it'll trigger the alert on subsequent connects after disconnecting.

Then there's the issue of connecting with Matic, but then the user switching networks. This breaks everything. I also find that the app just breaks randomly for seemingly no reason. Sometimes if I just refresh a couple times the error will go away

This approach seems fundamentally misguided - what do I do? Again, I just want to be able to get all my read-only values printed on whatever pages I need them. Then, if the user wants to interact with the DApp (buy something), they can login and click whichever buttons to do whatever.

Do I need to use two instances of Web3 - one that's always connected to the matic to get my read-only values, and another that's connected to whatever the user is using? This has to be redundant, right?

1 Answer 1


a way is iterating over contract

for (var i = 0; i < contract.abi.length; i++) {
    if (contract.abi[i]["type"] === "function" && contract.abi[i]["stateMutability"] === "view") {
        console.log("read-only function:", contract.abi[i]["name"])

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.