Connect MetaMask wallet #JavaScript

İnanç Akduvan - Apr 24 '22 - - Dev Community

We will connect MetaMask wallet and get accounts with javascript basically.

Try demo here:
https://inancakduvan.github.io/connect-metamask-wallet/

Find source code on github:
https://github.com/inancakduvan/connect-metamask-wallet

1) Check if MetaMask plugin installed on browser
If not, redirect user to MetaMask download page.

const connectButton = document.getElementById("connectButton");

connectButton.addEventListener("click", () => {
   if (typeof window.ethereum !== "undefined") {
       console.log("MetaMask installed")
   } else {
       window.open("https://metamask.io/download/", "_blank");
   }
})
Enter fullscreen mode Exit fullscreen mode

2) Get accounts if MetaMask installed
MetaMask plugin will automatically open when we send a request to get accounts.

const connectButton = document.getElementById("connectButton");
const walletID = document.getElementById("walletID");

if (typeof window.ethereum !== "undefined") {
    ethereum
      .request({ method: "eth_requestAccounts" })
      .then((accounts) => {
        const account = accounts[0]

        walletID.innerHTML = `Wallet connected: ${account}`;
      })
} else {
      window.open("https://metamask.io/download/", "_blank");
}
Enter fullscreen mode Exit fullscreen mode

3) Handle errors
Handling errors is a good practise to guide the user correctly.
(For example: show a loader while user is connecting wallet and hide it if user cancel process)

const connectButton = document.getElementById("connectButton");
const walletID = document.getElementById("walletID");

connectButton.addEventListener("click", () => {
   if (typeof window.ethereum !== "undefined") {
        ethereum
         .request({ method: "eth_requestAccounts" })
         .then((accounts) => {
           const account = accounts[0]

           walletID.innerHTML = `Wallet connected: ${account}`;
        }).catch((error) => {
           // Handle error
           console.log(error, error.code);

           // 4001 - The request was rejected by the user
           // -32602 - The parameters were invalid
           // -32603- Internal error
       });
   } else {
       window.open("https://metamask.io/download/", "_blank");
   }
})
Enter fullscreen mode Exit fullscreen mode
It is done here, we can say. But if you are interested in some extra suggestions, keep reading:

EXTRA SUGGESTIONS

4) Show a loader while user is connecting wallet via plugin

const connectButton = document.getElementById("connectButton");
const walletID = document.getElementById("walletID");

connectButton.addEventListener("click", () => {
   // Start loader while connecting
   connectButton.classList.add("loadingButton");

   if (typeof window.ethereum !== "undefined") {
      ethereum
        .request({ method: "eth_requestAccounts" })
        .then((accounts) => {
           const account = accounts[0]

           walletID.innerHTML = `Wallet connected: ${account}`;

           // Stop loader when connected
           connectButton.classList.remove("loadingButton");
      }).catch((error) => {
        // Handle error
        console.log(error, error.code);

        // Stop loader if error occured

        connectButton.classList.remove("loadingButton");

        // 4001 - The request was rejected by the user
        // -32602 - The parameters were invalid
        // -32603- Internal error
      });
   } else {
      window.open("https://metamask.io/download/", "_blank");
   }
})
Enter fullscreen mode Exit fullscreen mode

5) Show a "Reload page" warning when user is redirected to download page
User needs to refresh page after plugin installed and so browser can re-fetch scripts. It would be a good practise to let user know about this.

const connectButton = document.getElementById("connectButton");
const walletID = document.getElementById("walletID");
const reloadButton = document.getElementById("reloadButton");
const installAlert = document.getElementById("installAlert");

connectButton.addEventListener("click", () => {
   // Start loader while connecting
   connectButton.classList.add("loadingButton");

   if (typeof window.ethereum !== "undefined") {
      ethereum
        .request({ method: "eth_requestAccounts" })
        .then((accounts) => {
           const account = accounts[0]

           walletID.innerHTML = `Wallet connected: ${account}`;

           // Stop loader when connected
           connectButton.classList.remove("loadingButton");
      }).catch((error) => {
        // Handle error
        console.log(error, error.code);

        // Stop loader if error occured
        // For example, when user cancelled request 
        // and closed plugin
        connectButton.classList.remove("loadingButton");

        // 4001 - The request was rejected by the user
        // -32602 - The parameters were invalid
        // -32603- Internal error
      });
   } else {
      window.open("https://metamask.io/download/", "_blank");

      // Show 'Reload page' warning to user
      installAlert.classList.add("show");
   }
})

// Reload the page on reload button click
reloadButton.addEventListener("click", () => {
  window.location.reload();
});
Enter fullscreen mode Exit fullscreen mode

6) Check if user is on mobile device
If user is on mobile device, MetaMask application's browser should be used to be connected.

const connectButton = document.getElementById("connectButton");
const walletID = document.getElementById("walletID");
const reloadButton = document.getElementById("reloadButton");
const installAlert = document.getElementById("installAlert");
const mobileDeviceWarning = document.getElementById("mobileDeviceWarning");

connectButton.addEventListener("click", () => {
      // Start loader while connecting
      connectButton.classList.add("loadingButton");

      if (typeof window.ethereum !== "undefined") {
        ethereum
          .request({ method: "eth_requestAccounts" })
          .then((accounts) => {
             const account = accounts[0]

             walletID.innerHTML = `Wallet connected: ${account}`;

             // Stop loader when connected
             connectButton.classList.remove("loadingButton");
         }).catch((error) => {
           // Handle error
           console.log(error, error.code);

           // Stop loader if error occured
           // For example, when user cancelled request 
           // and closed plugin
           connectButton.classList.remove("loadingButton");

           // 4001 - The request was rejected by the user
           // -32602 - The parameters were invalid
           // -32603- Internal error
         });
      } else { 
          // Find the function which checks if device is mobile
          // at my github repo or anywhere
         if (isMobile()) {
           mobileDeviceWarning.classList.add("show");
         } else {
           window.open("https://metamask.io/download/", "_blank");

           // Show 'Reload page' warning to user
           installAlert.classList.add("show");
         }
      }
})

// Reload the page on reload button click
reloadButton.addEventListener("click", () => {
  window.location.reload();
});
Enter fullscreen mode Exit fullscreen mode

Here is html and css:

 <div class="container">
      <button class="button" id="connectButton">
        Connect wallet

        <span id="loading">
         <span>&bull;</span><span>&bull;</span><span>&bull;</span> 
        </span>
      </button>

      <div id="walletID">Your wallet is not connected yet.</div>

     <div id="mobileDeviceWarning">
        If you are on a mobile phone, please use MetaMask 
        application's browser to connect.
     </div>
 </div>

<div class="alert" id="installAlert">
  Please refresh your browser after installing the Metamask plugin

  <button class="button" id="reloadButton">Reload page</button>
</div>
Enter fullscreen mode Exit fullscreen mode
.container {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100vh;
}

.button {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    outline: none;
    box-shadow: 0 1px 5px 0 #e6e9ef;
    background: #ffffff;
    color: #000;
    border-radius: 99px;
    padding: 16px 32px;
    font-family: 'Quicksand', sans-serif;
    font-size: 24px;
    font-weight: 500;
    cursor: pointer;
}

#connectButton {
    margin-bottom: 16px;
    color: #eb874b;
}

#walletID span{
    max-width: 90%;
    margin: 0 auto;
    font-size: 12px;
    font-weight: 600;
}

#mobileDeviceWarning {
    display: none;
    margin-top: 24px;
    color: rgb(247, 47, 47);
}

#mobileDeviceWarning.show {
    display: block;
}

.alert {
    z-index: 10;
    position: fixed;
    left: 0;
    top: 0;
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100vh;
    background: #ffffff;
}

.alert.show {
    display: flex;
}

.alert .button {
    margin-top: 24px;
}

/* Loading dots styles */
@keyframes opacity {
    0% { opacity: 1; }
    100% { opacity: 0; }
}

.loadingButton {
    pointer-events: none;
}

.loadingButton #loading {
    display: flex;
}

#loading {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: none;
    align-items: center;
    justify-content: center;
    background: #fff;
    border-radius: 99px;
}

#loading span:not(:last-child) {
    margin-right: 5px;
}

#loading span {
    animation-name: opacity;
    animation-duration: 1s;
    animation-iteration-count: infinite;
}

#loading span:nth-child(2) {
    animation-delay: 100ms;
    animation-delay: 100ms;
}

#loading span:nth-child(3) {
    animation-delay: 300ms;
    animation-delay: 300ms;
}
Enter fullscreen mode Exit fullscreen mode

Find source code on github:
https://github.com/inancakduvan/connect-metamask-wallet


Follow me on:

Github: https://github.com/inancakduvan/
Twitter: https://twitter.com/InancAkduvan

Thank you for reading 🙂

. . . . . . . . . . . .