Search code examples
javascriptreactjsethereumblockchainmetamask

Metamask not returning "code 4001 User rejected the request." when closing login popup in Chrome, but works in Edge


I am trying to connect to the Metamask extension on Chrome by having a button that initiates the log in process on click. However in the event the user closes the log in pop up after clicking the button, no code 4001 exception is thrown in Chrome, the console log is completely empty. After that when I click the button again, it will no longer bring up the log in pop up but instead throw "RPC Error: Already processing eth_requestAccounts. Please wait." enter image description here

But when I tried in Edge, it throws just fine in the console (this is the expected result): enter image description here

Refreshing the Chrome page does not help, I have to close and reopen the entire browser to reset it.

Looking into the extension icon, I noticed that in Edge, whenever I close the login button, the blue "1" notification which signifies pending transactions will be gone:

enter image description here

However in Chrome that is not the case, the blue "1" notification remains:

enter image description here

Here is the relevant code for the button if it helps. Any assistance is greatly appreciated:

import { Card, CardContent, Button, Grid } from '@material-ui/core'
import React, { useEffect, useState } from "react";
import MetaMaskOnboarding from '@metamask/onboarding';

function MetaMaskConnectButton(props) {    
    const forwarderOrigin = 'http://localhost:3000';    
    const onboarding = new MetaMaskOnboarding({ forwarderOrigin });    
    const { ethereum } = window;    
    const [buttonText, setButtonText] = useState('Connect MetaMask')    
    const [isButtonDisabled, setIsButtonDisabled] = useState(false)    
    const [mmAccounts, setMmAccounts] = useState('')    

    useEffect(() => {        
        if (!isMetaMaskInstalled()) {            
            setButtonText('Click here to install MetaMask!')        
        }
    }, [])    

    useEffect(() => {        
        if (mmAccounts == null || mmAccounts.length === 0)
            setIsButtonDisabled(false)       
        else            
            setIsButtonDisabled(true)    
    }, [mmAccounts])    

    async function metaMaskClientCheck() {        
        if (!isMetaMaskInstalled()) {            
            await metamaskInstall()            
            setIsButtonDisabled(true)        
        } 
        else {            
            await metamaskConnect()            
            setIsButtonDisabled(false)        
        }    
    }    

    //Function checks if the MetaMask extension is installed    
    const isMetaMaskInstalled = () => {        
        //Have to check the ethereum binding on the window object to see if it's installed
          return Boolean(ethereum && ethereum.isMetaMask);    
    }    

    const metamaskInstall = async () => {        
        setButtonText('Onboarding in progress...')        
        setIsButtonDisabled(true)        
        onboarding.startOnboarding();    
    }    

    const metamaskConnect = async () => {        
        setIsButtonDisabled(true)        
        setButtonText('Connecting to MetaMask...')        
        try {            
            // Will open the MetaMask UI            
            let accounts = await ethereum.request({ method: 'eth_requestAccounts' }) 
            console.log('Ethereum Request over')            
            let account = accounts[0]            
            setMmAccounts(account)            
            setButtonText('MetaMask Connected')        
        } catch (error) {            
            console.error(error);            
            setIsButtonDisabled(false)            
            setButtonText('Connect MetaMask')        
        }    
    };    

    return (        
        <Grid container xs={12} sm={12}>
            <Grid container xs={6} sm={6} justify='flex-start'>
                <Button                    
                    disabled={isButtonDisabled}                    
                    variant='contained'                    
                    color='secondary'
                    className='button-blue originalText'
                    onClick={() => {
                        metaMaskClientCheck()
                    }}
                    classes={{ root: 'ng-button-filled-secondary' }}
                >
                    {buttonText}
                </Button>
            </Grid>
        </Grid>
    )}
export default MetaMaskConnectButton

Solution

  • You can add a timeout to your current code and thrown an error like this:

       let timeout;
    async function metamaskConnect() {
      setIsButtonDisabled(true);
      setButtonText('Connecting to MetaMask...');
      try {
        let accounts = await ethereum.request({ method: 'eth_requestAccounts' });
        console.log('Ethereum Request over');
        let account = accounts[0];
        setMmAccounts(account);
        setButtonText('MetaMask Connected');
        timeout = setTimeout(() => {
          setIsButtonDisabled(false);
          setButtonText('Connect MetaMask');
        }, 5000);
      } catch (error) {
        console.error(error);
        setIsButtonDisabled(false);
        setButtonText('Connect MetaMask');
      }
    }

    Or maybe use Promise.reject or thrown new Error as another option.