简体   繁体   中英

Better pattern to detect web3 default account when using metamask

Context: I want to use blockies to render an identicon on the page, i get the defaultAccount from web3, for this, the user has to be logged on to metamask with a selected address from his wallet.

The problem: the web app seems to not detect the web3 object on the load event of the page, wchih is the recommended place to detect it.

The code: below is inspired from recommendations at:

https://github.com/MetaMask/metamask-plugin/issues/1158

https://github.com/MetaMask/faq/blob/master/DEVELOPERS.md#partly_sunny-web3---ethereum-browser-environment-check

I keep having intermittent behaviour, sometimes web3 is there and sometimes it is not, the only solution I can think of is to have a timer, but that seems to me a bit too simplistic, I would prefer something more elegant.

Question: Is there a better solution to detect the defaultAccount from web3 when the page loads?

 function startApp() { 
        GenerateIdenticon();  
}  


window.addEventListener('load', function () { 

// Checking if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {

    // Use Mist/MetaMask's provider
    window.web3 = new Web3(web3.currentProvider); 
    if (web3.currentProvider.isMetaMask === true) {
        if (typeof web3.eth.defaultAccount === 'undefined') {
            document.body.innerHTML = '<body><h1>Oops! Your browser does not support Ethereum Ðapps.</h1></body>';   
        }
        else {
            startApp();
        }
    }
    else {
         alert('No web3? Please use google chrome and metamask plugin to enter this Dapp!', null, null);
        // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
       window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
function _Connect(callback){
    if(typeof web3 !== 'undefined') {
          web3 = new Web3(window.web3.currentProvider);
          web3.version.getNetwork((err, netId) => {
              switch (netId) {
                case "1":
                    callback('Switch Network', null);   
                  break
                case "2":
                  console.log('This is the deprecated Morden test network.');
                  callback('Switch Network', null);
                  break
                case "3":
                    console.log('Connected to the ropsten test network.');
                    web3.eth.defaultAccount = web3.eth.accounts[0];
                    if(!web3.eth.defaultAccount){
                        console.log('Log into metamask');
                        _Connect(callback);
                    }else{ 
                                                    // Success
                        console.log(`Web3 ETH Account: ${web3.eth.defaultAccount}`);
                        callback(false, web3.eth.defaultAccount);
                    }   
                  break
                default:
                  console.log('This is an unknown network.');
                  callback('Switch Network', null);
              }
            });
        } else {
          console.log(`Failed: Web3 instance required, try using MetaMask.`);
          callback('Install Metamask', null);
        }   
}

There is a delay when Chrome inserts the MetaMask Web3 library so the timeout is necessary (1 second timeout should be enough).

After the timeout, you check if the web3 global object exists and then read the default account.

If it doesn't exist, then insert your own web3 object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM