15

I don't want metamask to pop up on page load forcing a user to connect, so we only connect via a button - but after a user is connected if they refresh the page - they need to press the button again to connect (although nothing happens in metamask, it just calls ethereum.enable() and closes).

I'd like to be able to do something like:

If user has already connected (after reloading the page or coming back next week), call enable and get their wallet info/address.

If the user has not already connected - do not call the connect function for metamask until the user presses the connect button.

Here is my code for connecting a wallet and I'm unsure how to do the initial check for - "if they have already connected".

export const loadUserWeb3 = async () => {
  try {
    if (window.ethereum) {
      window.web3 = new Web3(window.ethereum);
      await window.ethereum.enable();
      window.ethereum.on("chainChanged", () => {
        document.location.reload();
      });
      return window.web3;
    } else if (window.web3) {
      window.web3 = new Web3(window.web3.currentProvider);
      return window.web3;
    } else {
      window.web3 = new Web3(
        new Web3.providers.HttpProvider(INFURA_ENDPOINT[1])
      );
      return window.web3;
    }
  } catch {
    window.web3 = new Web3(new Web3.providers.HttpProvider(INFURA_ENDPOINT[1]));
    return window.web3;
  }
};

Again the key here is that if they have not already connected then it would not call enable() because that would show the metamask pop up without the user asking for it to be shown.

TL;DR:

How to get the user's wallet info if their wallet is ALREADY connected and they just reload the page - without forcing metamask to ask them to connect if they HAVEN'T connected.

1
  • MetaMask might not have this functionality because of privacy reasons. At least all dApps I use always ask to reconnect with MetaMask. Nov 19, 2020 at 18:51

4 Answers 4

6
+50

The solution will depend a little bit on your front-end. This is how I did to cover your requirements with React in TypeScript:

    React.useEffect(() => {
       const checkConnection = async () => {

           // Check if browser is running Metamask
           let web3: any;
           if (window.ethereum) {
               web3 = new Web3(window.ethereum);
           } else if (window.web3) {
               web3 = new Web3(window.web3.currentProvider);
           };

           // Check if User is already connected by retrieving the accounts
           web3.eth.getAccounts()
               .then(async (addr: string) => {
                   // Set User account into state
               });
       };
       checkConnection();
   }, []);

When Users connect to the web page, I check if there is a web3 plugin in browser and try to retrieve the accounts. If I get any result, it means the User is already connected to Metamask and don't need to trigger any pop-up to connect.

If the User is not connected to Metamask, then you can trigger the pop-up by pressing the button you mentioned, and you will execute a similar code but including await window.ethereum.enable();

If you are not using React, then you just need to execute this function the first time you load the page and skip the useEffect method.

3
  • 1
    Thanks. So easy. My problem was I was automatically calling enable without checking accounts first.
    – Zach
    Nov 22, 2020 at 16:11
  • Note that getAccounts is deprecated in favour of the eth_accounts RPC call Jun 28, 2021 at 12:12
  • when the user is not logged into metamask, a login window appears...
    – ricardo
    Jul 10, 2021 at 16:28
2

you can also use ethers js.

import { ethers } from "ethers";
const provider = new ethers.providers.Web3Provider(
  (window as any).ethereum
);
const addresses = await provider.listAccounts(); 
// it doesn't create metamask popup
if (addresses.length) 
// permission already granted so request account address from metamask
else { do other stuff }
0

Well, I had the same problem. I think I came up with a complete solution:

//For Metamask detection
<script src="https://unpkg.com/@metamask/detect-provider/dist/detect-provider.min.js"></script>

<script type="text/javascript">
//wait till page loads up, and than call startApp function
window.addEventListener('load', function () {
  startApp();
})

async function startApp() {

 const provider = await detectEthereumProvider()//uses function from "detect-provider.min.js" 

 if (provider) {
  console.log('Metamask successfully detected!');
  
  //RPC call that check if there are address in this wallet
  window.ethereum.sendAsync({
  method: "eth_accounts",
  params: [],
  jsonrpc: "2.0",
  id: new Date().getTime()
  } , function (error, result){
      console.log(result);
      if (result["result"]!="") alert("wallet connected");//addresses found. result["result"] contains wallet address
      else alert("wallet not connected");//found not address, which mean this wallet is not logged in
   });
  
 }
 else {// Metamask is not installed
  alert("Please install Metamask");
 }  
}
</script>
0

Modifying Sergi's answer with this code will prevent MetaMask from popping up on pageload if no wallet is found.

const loggedIn = (await web3.eth.getAccounts()).length > 0;

if (loggedIn) {
    web3.eth.getAccounts().then(async (addr) => {
        const accounts = await web3.eth.requestAccounts();
        setAccount(accounts[0])
    });
}

Your Answer

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

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