Search code examples
javascriptethereumweb3jsmetamask

How to check if Metamask is connected after page refreshing


My dApp have to connect to MetaMask. There are two rude solutions in the docs: make user to click connect btn every time manually or just pop up connection confirmation after page load. I want to implement the only convenient solution: first time user connect manually by clicking the connect btn and interacting with MetaMask popup and then my dApp detect that connection is still established and use this connection. I can't find the solution, but i saw this in other dApps (Capture the ether for example) I use:

import detectEthereumProvider from '@metamask/detect-provider';

const provider = await detectEthereumProvider(); 

if (provider) {
  connect(provider)
} else {
  // kind of "Install the MetaMask please!"
}

function connect(provider) {
  // How to check if the connection is here
  if (//connection established) {
    // Show the user connected account address
  } else {
    // Connect
    provider.request({ method: "eth_requestAccounts" })
      .then // some logic
  }
}

Solution

  • I finally found a possible solution and it turned out to be as simple as it should be. There is an eth_accounts method in Ethereum JSON-RPC which allow us to ask for available accounts without actually requesting them. This way we can check if metamask is still connected (if there are any accounts) and avoid auto requesting or need of manually clicking "connect" every time. Simple example implementation could be:

    // detect provider using @metamask/detect-provider
    detectEthereumProvider().then((provider) => {
      if (provider && provider.isMetaMask) {
        provider.on('accountsChanged', handleAccountsChanged);
        // connect btn is initially disabled
        $('#connect-btn').addEventListener('click', connect);
        checkConnection();
      } else {
        console.log('Please install MetaMask!');
      }
    });
    
    function connect() {
      ethereum
        .request({ method: 'eth_requestAccounts' })
        .then(handleAccountsChanged)
        .catch((err) => {
          if (err.code === 4001) {
            console.log('Please connect to MetaMask.');
          } else {
            console.error(err);
          }
        });
    }
    
    function checkConnection() {
      ethereum.request({ method: 'eth_accounts' }).then(handleAccountsChanged).catch(console.error);
    }
    
    function handleAccountsChanged(accounts) {
      console.log(accounts);
    
      if (accounts.length === 0) {
        $('#connection-status').innerText = "You're not connected to MetaMask";
        $('#connect-btn').disabled = false;
      } else if (accounts[0] !== currentAccount) {
        currentAccount = accounts[0];
        $('#connection-status').innerText = `Address: ${currentAccount}`;
        $('#connect-btn').disabled = true;
      }
    }