MetaMask provides the following way currently to find a provider for their upcoming 2020 breaking change:
// Running on the page, in the browser
// This API will go live in Q1 2020
// It will be the only API available after a 6-week deprecation period
if (!ethereum || !ethereum.isMetaMask) {
throw new Error('Please install MetaMask.')
}
/*********************************************************/
/* Handle chain (network) and chainChanged, per EIP 1193 */
/*********************************************************/
let currentChainId = null
ethereum.send('eth_chainId')
.then(handleChainChanged)
.catch(err => console.error(err)) // This should never happen
ethereum.on('chainChanged', handleChainChanged)
function handleChainChanged (chainId) {
if (currentChainId !== chainId) {
currentChainId = chainId
// Run any other necessary logic...
}
}
/**********************************************************/
/* Handle user accounts and accountsChanged, per EIP 1193 */
/**********************************************************/
let currentAccount = null
ethereum.send('eth_accounts')
.then(handleAccountsChanged)
.catch(err => {
// In the future, maybe in 2020, this will return a 4100 error if
// the user has yet to connect
if (err.code === 4100) { // EIP 1193 unauthorized error
console.log('Please connect to MetaMask.')
} else {
console.error(err)
}
})
// Note that this event is emitted on page load.
// If the array of accounts is non-empty, you're already
// connected.
ethereum.on('accountsChanged', handleAccountsChanged)
// For now, 'eth_accounts' will continue to always return an array
function handleAccountsChanged (accounts) {
if (accounts.length === 0) {
// MetaMask is locked or the user has not connected any accounts
console.log('Please connect to MetaMask.')
} else if (accounts[0] !== currentAccount) {
currentAccount = accounts[0]
// Run any other necessary logic...
}
}
/***********************************/
/* Handle connecting, per EIP 1102 */
/***********************************/
// You should only attempt to connect in response to user interaction,
// such as a button click. Otherwise, you're popup-spamming the user
// like it's 1999.
// If you can't retrieve the user's account(s), you should encourage the user
// to initiate a connection attempt.
document.getElementById('connectButton', connect)
function connect () {
// This is equivalent to ethereum.enable()
ethereum.send('eth_requestAccounts')
.then(handleAccountsChanged)
.catch(err => {
if (err.code === 4001) { // EIP 1193 userRejectedRequest error
console.log('Please connect to MetaMask.')
} else {
console.error(err)
}
})
}
I am struggling to get my frontend to recognize a web3.js provider that is not MetaMask. The above code works perfectly with the current version of MetaMask, but does not work in any other Web3 browsers. If I inject my own web3.js, I get Can't find variable: Web3
and Can't find variable: ethereum
MetaMask's documentation is highly confusing, especially in light of the fact that it still injects v0.2 of web3.js while forcing you soon to completely change the way you find a provider. I don't even know which version of web3.js the above code is for, 1.2 or 2.0. It is all unclear from all their convoluted press releases and blogs that seem to come from a different person on the team.
How can I make the above code work for other web3.js browsers like Cipher or Parity?
Currently I do this with v0.2:
if (typeof web3 !== 'undefined') {
console.log('Web3 Detected! ' + web3.currentProvider.constructor.name)
window.web3 = new Web3(web3.currentProvider);
web3.eth.defaultAccount = web3.eth.accounts[0];
} else {
console.log('No Web3 Detected, Using HTTP Provider')
web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/v3/xxxxxxx"));
alert("You are not logged into a Web 3.0 enabled wallet such as MetaMask. You will be able to see the current status of the contract via Infura Web 3.0 services, but you will not be able to interact with the Dapp. Please login to a Web 3.0 wallet and refresh the page to use all functions.");
}