Skip to main content

Set up your development environment

You can easily set up a simple dapp to integrate with MetaMask. For a full end-to-end tutorial using Vite, see the Create a simple React dapp tutorial.

Prerequisites

  • MetaMask installed in the browser of your choice on your development machine. We recommend running a development network on MetaMask when developing a dapp.

  • A text editor of your choice, such as VS Code. You can install the Live Server extension for VS Code to easily launch a local development server for your dapp.

  • A module bundler, such as Webpack.

  • npm.

Set up a new project

Create a project directory with the following structure:

simple-dapp/
├─ src/
│ ├─ index.js
├─ dist/
│ ├─ index.html

For any Ethereum dapp to work, your project script index.js must:

important

If you import any modules into your project, such as @metamask/detect-provider, use a bundler such as Webpack to compile the modules and create an output script dist/main.js. See Webpack's Getting Started guide for more information.

tip

We also recommend setting up MetaMask SDK to enable a reliable, secure, and seamless connection from your dapp to the MetaMask browser extension and MetaMask Mobile.

Example

The following is an example simple dapp script and HTML file:

index.js
/*****************************************/
/* Detect the MetaMask Ethereum provider */
/*****************************************/

import detectEthereumProvider from '@metamask/detect-provider';

const provider = await detectEthereumProvider();

if (provider) {
startApp(provider);
} else {
console.log('Please install MetaMask!');
}

function startApp(provider) {
if (provider !== window.ethereum) {
console.error('Do you have multiple wallets installed?');
}
}

/**********************************************************/
/* Handle chain (network) and chainChanged (per EIP-1193) */
/**********************************************************/

const chainId = await window.ethereum.request({ method: 'eth_chainId' });

window.ethereum.on('chainChanged', handleChainChanged);

function handleChainChanged(chainId) {
window.location.reload();
}

/***********************************************************/
/* Handle user accounts and accountsChanged (per EIP-1193) */
/***********************************************************/

let currentAccount = null;
window.ethereum.request({ method: 'eth_accounts' })
.then(handleAccountsChanged)
.catch((err) => {
console.error(err);
});

window.ethereum.on('accountsChanged', handleAccountsChanged);

function handleAccountsChanged(accounts) {
if (accounts.length === 0) {
console.log('Please connect to MetaMask.');
} else if (accounts[0] !== currentAccount) {
currentAccount = accounts[0];
showAccount.innerHTML = currentAccount;
}
}

/*********************************************/
/* Access the user's accounts (per EIP-1102) */
/*********************************************/

const ethereumButton = document.querySelector('.enableEthereumButton');
const showAccount = document.querySelector('.showAccount');

ethereumButton.addEventListener('click', () => {
getAccount();
});

async function getAccount() {
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' })
.catch((err) => {
if (err.code === 4001) {
console.log('Please connect to MetaMask.');
} else {
console.error(err);
}
});
const account = accounts[0];
showAccount.innerHTML = account;
}