This is a hands-on developer workflow for deploying contracts and interacting with dApps using the MetaMask software wallet as an injected provider in Chrome. I explain step-by-step code examples, how to run MetaMask on Chrome and enable it, and how to detect and authenticate a MetaMask wallet from a React app.
How I tested this guide (so you can reproduce it):
There are concrete commands and snippets below so you can repeat everything on your machine.
If you need to know how to enable MetaMask on Chrome or how to run MetaMask on Chrome, the basic steps are:
And if a site can’t see MetaMask, check that the popup hasn’t blocked the connection request and that "site access" is permitted.
Run a local node so you can deploy fast and without real funds. Two repeatable steps I use:
# Hardhat local node
npx hardhat node
You can import one of the unlocked private keys from the local node into MetaMask (only for testing). But never import a seed phrase tied to real funds.
This example shows a minimal browser deploy flow using ethers.js and the injected provider.
// connect.js
import { ethers } from 'ethers';
async function connect() {
if (!window.ethereum) throw new Error('MetaMask not detected');
const provider = new ethers.providers.Web3Provider(window.ethereum);
// how to authenticate metamask wallet
await provider.send('eth_requestAccounts', []);
const signer = provider.getSigner();
return { provider, signer };
}
import contractJson from './MyContract.json'; // compiled ABI + bytecode
async function deploy(signer) {
const factory = new ethers.ContractFactory(contractJson.abi, contractJson.bytecode, signer);
const contract = await factory.deploy(/* constructor args */, {
// optional overrides
gasLimit: 6000000,
});
console.log('txHash', contract.deployTransaction.hash);
await contract.deployed();
console.log('deployed at', contract.address);
return contract;
}
Note: you can pass EIP-1559 fields (maxFeePerGas, maxPriorityFeePerGas) in the overrides if needed.
If you prefer a UI IDE, the browser IDE can use the injected provider option (select "Injected Web3") so MetaMask handles signing.
A common pattern in React apps is using @metamask/detect-provider. Example:
import detectEthereumProvider from '@metamask/detect-provider';
import { useEffect, useState } from 'react';
function useMetaMask() {
const [provider, setProvider] = useState(null);
useEffect(() => {
(async () => {
const p = await detectEthereumProvider();
if (p) setProvider(p);
})();
}, []);
return provider;
}
You can also check window.ethereum and window.ethereum.isMetaMask directly if you want a lightweight approach.
For authentication, issue a short challenge from your backend, ask the user to sign that message with signer.signMessage(challenge), and verify the signature server-side. That proves control of the account without moving funds.
MetaMask exposes EIP-1559 fields in its send flow. When you deploy from the browser you can set overrides on the transaction. Example:
await factory.deploy(args…, {
maxFeePerGas: ethers.utils.parseUnits('100', 'gwei'),
maxPriorityFeePerGas: ethers.utils.parseUnits('2', 'gwei'),
});
But remember: MetaMask will surface a confirmation popup and may change suggested fees based on the network. Test on your local node first to avoid unexpected cost or dropped transactions.
A frequent mistake I made early on was deploying with an incorrect constructor signature (so the deploy reverted). Read the contract ABI and verify constructor args before sending.
But even with caution, mistakes happen. I once approved an unlimited allowance to a test contract and had to walk through revoking it — that taught me to use minimal allowances in tests.
Q: Is it safe to deploy from a hot wallet?
A: It's common for testing and rapid iteration. For high-value mainnet deployments use a hardware signer or a CI process with strict key management. See integrate-hardware-ledger-trezor.
Q: How do I revoke token approvals?
A: Use a revoke UI (or call an approval reset transaction) and check the allowance on-chain. See token-approvals-and-revoke.
Q: How do I detect MetaMask provider in React?
A: Use @metamask/detect-provider or check window.ethereum and isMetaMask. Example above shows the pattern.
Who this is well-suited for:
Who should look elsewhere:
If you want a repeatable starting point: run npx hardhat node, add the local RPC to MetaMask, and try the example deployment above from a simple React page. That exercise shows how the provider detects, how signing works, and how MetaMask surfaces confirmations.
For step-by-step installation and troubleshooting see install-metamask-chrome, local-development-ganache-geth, and add-networks-custom-rpc. And if you’re building richer integrations, check out snaps-dev and developer-integration for advanced developer tools.
Want a checklist or a minimal repo to copy? Try the sample flow above and adapt it into your own project—then iterate on gas settings, error handling, and signature authentication. Good luck, and test safely.