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."
But when I tried in Edge, it throws just fine in the console (this is the expected result):
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:
However in Chrome that is not the case, the blue "1" notification remains:
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
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.