Modified from https://docs.metamask.io/guide/create-dapp.html
Project Setup
Before you set up make sure you've visited and gone through our Getting Started Guide
Make sure you have:
- The MetaMask Extension downloaded.
- Node.js Downloaded and Installed
- Clone/Download the Project Files from GitHub.
Open Project Folder
Open the project folder. Navigate to
start
->index.html
, and look at the comment stating part 1
. This is the UI for the Simple Dapp with all of the layout and buttons that will help us learn the basics of connecting to our MetaMask extension. We will be using/building off of this entire section for the first part of the tutorial.Install Dependencies
Open a terminal and make sure your terminal is inside the base directory of the
start/
folder. Inside the folder, the files should look like this:plain text. ├─ index.html ├─ contract.js ├─ metamask.css ├─ package.json └─ README.md
Open your terminal and navigate into the start folder. In this folder run:
bashyarn install
Next run:
bashyarn run serve
Navigate to
http://localhost:9011
Basic Action
Now let's navigate into the
contract.js
file inside your start folder.javascriptconst forwarderOrigin = 'http://localhost:9010'; const initialize = () => { //You will start here }; window.addEventListener('DOMContentLoaded', initialize);
As soon as the content in the DOM is loaded we are calling our initialize function. Now before we start writing any code let's look at our task list for the first part of this app.
Connecting to the MetaMask Wallet
MetaMask Extension Check
We create a check function called
isMetaMaskInstalled
to see if the MetaMask extension is installed.And, we need to create a
MetaMaskClientCheck
function to see if we need to change the button text based on if the MetaMask Extension is installed or not.javascriptconst initialize = () => { //Basic Actions Section const onboardButton = document.getElementById('connectButton'); //Created check function to see if the MetaMask extension is installed const isMetaMaskInstalled = () => { //Have to check the ethereum binding on the window object to see if it's installed const { ethereum } = window; return Boolean(ethereum && ethereum.isMetaMask); }; //------Inserted Code------\\ const MetaMaskClientCheck = () => { //Now we check to see if MetaMask is installed if (!isMetaMaskInstalled()) { //If it isn't installed we ask the user to click to install it onboardButton.innerText = 'Click here to install MetaMask!'; } else { //If it is installed we change our button text onboardButton.innerText = 'Connect'; } }; MetaMaskClientCheck(); //------/Inserted Code------\\ };
MetaMask "Not Installed" Dapp Flow
In our code block where MetaMask isn't installed and we ask the user to
'Click here to install MetaMask!'
, we need to ensure that if our button is clicked we:- Redirect the user to the proper page to install the extension
- Disable the button
javascriptconst MetaMaskClientCheck = () => { //Now we check to see if Metmask is installed if (!isMetaMaskInstalled()) { //If it isn't installed we ask the user to click to install it onboardButton.innerText = 'Click here to install MetaMask!'; //When the button is clicked we call this function onboardButton.onclick = onClickInstall; //The button is now disabled onboardButton.disabled = true; } else { //If it is installed we change our button text onboardButton.innerText = 'Connect'; } }; MetaMaskClientCheck();
Tip
For this part we will be using the '@metamask/onboarding' library we installed during the npm install. To learn more visit here
Inside the
onClickInstall
function we want to:- Change the text of the button to
Onboarding in progress
- Disable the button
- Start the onboarding process
Above your
MetaMaskClientCheck
function write/insert this code.javascript//We create a new MetaMask onboarding object to use in our app const onboarding = new MetaMaskOnboarding({ forwarderOrigin }); //This will start the onboarding proccess const onClickInstall = () => { onboardButton.innerText = 'Onboarding in progress'; onboardButton.disabled = true; //On this object we have startOnboarding which will start the onboarding process for our end user onboarding.startOnboarding(); };
GREAT! Now if our end user doesn't have the MetaMask Extension they can install it. When they refresh the page the ethereum window object will be there and we can get on to connecting their MetaMask wallet to our Dapp!
MetaMask "Installed" Dapp Flow
Next we need to revisit our
MetaMaskClientCheck
function and create similar functionality that we did in our "MetaMask Not Installed" block in our "MetaMask Is Installed" block of code.javascriptconst MetaMaskClientCheck = () => { //Now we check to see if Metmask is installed if (!isMetaMaskInstalled()) { ... } else { //If MetaMask is installed we ask the user to connect to their wallet onboardButton.innerText = 'Connect'; //When the button is clicked we call this function to connect the users MetaMask Wallet onboardButton.onclick = onClickConnect; //The button is now enabled onboardButton.disabled = false; } }; MetaMaskClientCheck();
Inside the
onClickConnect
function we want to:- Create an async function that will try to call the 'eth_requestAccounts' RPC method
- Catch any errors and log them to the console
Under your
onClickInstall
function write/insert this code.javascriptconst onClickConnect = async () => { try { // Will open the MetaMask UI // You should disable this button while the request is pending! await ethereum.request({ method: 'eth_requestAccounts' }); } catch (error) { console.error(error); } };
Great! Now once you click the button the MetaMask Extension will pop up and connect your wallet.
Get Ethereum Accounts
After this what we'd like to do next is whenever we press the
eth_accounts
button we'd like to get our Ethereum account and display it. Replace the existing const onboardButton
at the top of the initialize()
function with the following three buttons:javascript//Basic Actions Section const onboardButton = document.getElementById('connectButton'); const getAccountsButton = document.getElementById('getAccounts'); const getAccountsResult = document.getElementById('getAccountsResult');
Now that we've grabbed our eth_accounts button and our paragraph field to display it in we now have to grab the data.
Under our
MetaMaskClientCheck()
function let's write/insert the code below.javascript//Eth_Accounts-getAccountsButton getAccountsButton.addEventListener('click', async () => { //we use eth_accounts because it returns a list of addresses owned by us. const accounts = await ethereum.request({ method: 'eth_accounts' }); //We take the first address in the array of addresses and display it getAccountsResult.innerHTML = accounts[0] || 'Not able to get accounts'; });
If you have already connected to your wallet in the previous section of the tutorial, you can go into MetaMask's "Connected Sites" menu and remove the localhost connection. This will enable us to test both buttons again. If we refresh our page, and click the "ETH_ACCOUNTS" button, we should see
'eth_accounts result: Not able to get accounts'
.Let's go ahead and press the "Connect" button again, and confirm the "Connect With MetaMask" prompt and "Connect". Now we can click the "ETH_ACCOUNTS" button again and we should see our MetaMask account public address.
CONGRATULATIONS!
We have just completed building out our Simple Dapp. You know how to Connect to MetaMask, see your connected apps and remove them, as well as retrieve accounts.
Preview of the completed code up until this point of the tutorial:
javascriptconst forwarderOrigin = 'http://localhost:9010'; const initialize = () => { //Basic Actions Section const onboardButton = document.getElementById('connectButton'); const getAccountsButton = document.getElementById('getAccounts'); const getAccountsResult = document.getElementById('getAccountsResult'); //Created check function to see if the MetaMask extension is installed const isMetaMaskInstalled = () => { //Have to check the ethereum binding on the window object to see if it's installed const { ethereum } = window; return Boolean(ethereum && ethereum.isMetaMask); }; //We create a new MetaMask onboarding object to use in our app const onboarding = new MetaMaskOnboarding({ forwarderOrigin }); //This will start the onboarding proccess const onClickInstall = () => { onboardButton.innerText = 'Onboarding in progress'; onboardButton.disabled = true; //On this object we have startOnboarding which will start the onboarding process for our end user onboarding.startOnboarding(); }; const onClickConnect = async () => { try { // Will open the MetaMask UI // You should disable this button while the request is pending! await ethereum.request({ method: 'eth_requestAccounts' }); } catch (error) { console.error(error); } }; const MetaMaskClientCheck = () => { //Now we check to see if Metmask is installed if (!isMetaMaskInstalled()) { //If it isn't installed we ask the user to click to install it onboardButton.innerText = 'Click here to install MetaMask!'; //When the button is clicked we call th is function onboardButton.onclick = onClickInstall; //The button is now disabled onboardButton.disabled = false; } else { //If MetaMask is installed we ask the user to connect to their wallet onboardButton.innerText = 'Connect'; //When the button is clicked we call this function to connect the users MetaMask Wallet onboardButton.onclick = onClickConnect; //The button is now disabled onboardButton.disabled = false; } }; //Eth_Accounts-getAccountsButton getAccountsButton.addEventListener('click', async () => { //we use eth_accounts because it returns a list of addresses owned by us. const accounts = await ethereum.request({ method: 'eth_accounts' }); //We take the first address in the array of addresses and display it getAccountsResult.innerHTML = accounts[0] || 'Not able to get accounts'; }); MetaMaskClientCheck(); }; window.addEventListener('DOMContentLoaded', initialize);