Metamask wallet will not connect if coinbase is installed.
This is a critical issue for anyone trying to execute transactions on their website. Asking users to remove their coinbase wallet is a major deterrent.
https://docs.metamask.io/guide/ethereum-provider.html#using-the-provider
This link on the metamask website demonstrates that they are aware of the issue but no documentation addresses it.
This issue can't be impossible to fix because sites like uniswap allow users to select which wallet. So I think it would be helpful if this was addressed in the documentation.
This is the original code for the connect function:
const connectMetamask = async (setAlert, setCurrentAccount) => {
const {ethereum} = window
const isInstalled = () => {
return Boolean(ethereum && ethereum.isMetaMask)
}
const isConnect = () => {
return Boolean(ethereum && ethereum.isConnected()) // <-- this is the issue
}
try {
if (!isInstalled()) {
console.log("No metamask!"); // <-- this works
setAlert(true);
return;
}
if (!isConnect()) {
console.log("Metamask not connected!");
setAlert(true)
return;
}
const chainId = await ethereum.request({ method: "eth_chainId" });
} catch (error) {
console.error(error);
}
};
This code works fine to connect metamask IF coinbase wallet is not installed.
https://docs.cloud.coinbase.com/wallet-sdk/docs/injected-provider-guidance This link suggests what to do- but it doesn't work (for me at least).
if (window.ethereum.providers?.length) {
window.ethereum.providers.forEach(async (p) => {
if (p.isMetaMask) provider = p;
});
}
window.ethereum.providers returns an array, first element being the coinbase wallet which works fine, second being a proxy containing metamask. The properties of this proxy object are not accessible.
As per some answers I've written (which is the same as the code in the coinbase example):
const metamaskProvider = await window.ethereum.providers.find((provider) => provider.isMetaMask);
ethereum.setSelectedProvider(metamaskProvider)
Logging metamaskProvider
returns undefined.
Logging window.ethereum.providers
returns an array:
0: v {_events: {…}, _eventsCount: 0, _maxListeners: undefined, _filterPolyfill: e.FilterPolyfill, _subscriptionManager: e.SubscriptionManager, …}
1: Proxy {_events: {…}, _eventsCount: 0, _maxListeners: 100, _log: u, _state: {…}, …}
1 is the metamask provider. It contains the following properties:
1: Proxy
[[Handler]]: Object
deleteProperty: ()=>!0
[[Prototype]]: Object
[[Target]]: l
chainId: "0x1"
enable: ƒ ()
isMetaMask: true
....
metamaskProvider
returns undefined
. How do I access the isMetaMask
property, and set my selectedProvider to metamaskProvider
?My fix:
const connectMetamask = async (setAlert, setCurrentAccount) => {
let { ethereum } = window;
try {
if (!ethereum) {
console.log("No metamask!");
setAlert(true);
return;
}
try{
if (!ethereum.isConnected()) {
console.log("Metamask not connected!");
setAlert(true)
return;
}
} catch (error){
console.error(error)
try{
console.log('providers',window.ethereum.providers);
console.log('ethVar',ethereum)
ethereum = await window.ethereum.providers.find(
(provider) => provider.isMetaMask );
console.log('ethVarAfterFind', ethereum)
} catch (error){
console.error(error)
}
}
const chainId = await ethereum.request({ method: "eth_chainId" });
.....
} catch (error) {
console.log('error:')
console.error(error);
}
};
export default connectMetamask;
Basically just :
ethereum = await window.ethereum.providers.find( (provider) => provider.isMetaMask );
const chainId = await ethereum.request({ method: "eth_chainId" });
Honestly I'm pretty sure I tried this already and it wasn't working but, it is now ¯\_(ツ)_/¯