Hardhat MetaMask Connector is a tool to connect your MetaMask wallet with your Hardhat development environment. Deploy and interact with smart contracts using your MetaMask wallet without exposing your mnemonic or private key in code.
- Connect to MetaMask directly from Hardhat scripts
- Deploy contracts using your MetaMask wallet
- Sign transactions through MetaMask UI
- Support for multiple networks (localhost, Polygon, Ethereum, etc.)
- Automatic network switching
- No private keys in code - ever!
npm install @web3camp/hardhat-metamask-connectoror
yarn add @web3camp/hardhat-metamask-connector
⚠️ Important: You must callawait signer.getAddress()after getting the signer. This is what triggers the browser to open and establishes the MetaMask connection!
import { MetamaskConnector } from "@web3camp/hardhat-metamask-connector";or
const { MetamaskConnector } = require("@web3camp/hardhat-metamask-connector");import { ethers } from "hardhat";
import { MetamaskConnector } from "@web3camp/hardhat-metamask-connector";
async function main() {
// Initialize the connector
const connector = new MetamaskConnector();
// Get signer from MetaMask
const signer = await connector.getSigner();
// IMPORTANT: You MUST call getAddress() to trigger the browser to open
// and wait for MetaMask connection. This is a required step!
const signerAddr = await signer.getAddress();
console.log("Signer Address:", signerAddr);
// Now you can deploy contracts using MetaMask
const MyContract = await ethers.getContractFactory("MyContract");
const contract = await MyContract.connect(signer).deploy();
await contract.waitForDeployment();
console.log("Contract deployed to:", await contract.getAddress());
// Close the connector when done
connector.close();
}
main();# For localhost network
npx hardhat run scripts/deploy.ts --network localhost
# For Polygon network
npx hardhat run scripts/deploy.ts --network polygon
# For any configured network
npx hardhat run scripts/deploy.ts --network <network-name>- Initialize connector:
new MetamaskConnector()creates a local web server (default port 8989) - Get signer:
await connector.getSigner()returns a signer object - Trigger browser:
await signer.getAddress()opens the browser and waits for MetaMask connection - Connect MetaMask: Click "Connect to MetaMask" in the browser and approve the connection
- Network switch: MetaMask automatically switches to the correct network
- Sign transactions: Approve transactions in MetaMask as they come
- Script continues: Your Hardhat script receives the signed transactions
Important: You must call
await signer.getAddress()before using the signer. This triggers the browser to open and establishes the MetaMask connection. Without this call, the browser won't open!
// Use a custom port (default is 8989)
const connector = new MetamaskConnector(9000);Configure networks in your hardhat.config.ts:
import { HardhatUserConfig } from "hardhat/config";
// You can use any dummy private key here - it won't be used
// This is just to satisfy Hardhat's requirement
const DUMMY_PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
const config: HardhatUserConfig = {
networks: {
localhost: {
url: "http://127.0.0.1:8545",
chainId: 31337,
},
polygon: {
url: "https://polygon-mainnet.infura.io/v3/YOUR_INFURA_KEY",
chainId: 137,
// IMPORTANT: Hardhat requires the accounts field even though we use MetaMask
// You can use any dummy private key here - it will NOT be used
accounts: [DUMMY_PRIVATE_KEY]
},
mainnet: {
url: "https://eth.llamarpc.com",
chainId: 1,
accounts: [DUMMY_PRIVATE_KEY]
}
}
};
export default config;
⚠️ Important Hardhat Quirk: Even though MetaMask Connector doesn't use private keys, Hardhat still requires theaccountsfield in network configuration for non-localhost networks. You can use any dummy private key (like the default Hardhat test key shown above) - it will never be used. Your actual transactions will be signed by MetaMask!
See the example folder for a full working example:
cd example
npm install
npx hardhat node # In one terminal
npx hardhat run scripts/deploy.ts --network localhost # In another terminalWhen using the connector, you'll see helpful logs in the browser console (F12):
Current MetaMask chainId: 0x89- Shows the connected networkSwitched to chainId: 0x89- Confirms network switchTransaction sent: 0x123...- Transaction hashVerify at: https://polygonscan.com/tx/0x123...- Block explorer link
- Make sure you called
await signer.getAddress()- this is what triggers the browser to open - If you still have issues, manually open the URL shown in the console (e.g.,
http://localhost:8989/send-tx)
- The connector will prompt MetaMask to switch to the correct network
- Make sure to approve the network switch in MetaMask
- Check the browser console for the chainId - ensure it matches your expected network
- Verify MetaMask is on the correct network
- Make sure you have the
accountsfield in your network configuration inhardhat.config.ts - Hardhat requires this field even though MetaMask Connector doesn't use it
- Use a dummy private key:
accounts: ["0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"]
- Change the port:
new MetamaskConnector(9000) - Or kill the process using port 8989
The connector automatically shows block explorer links for:
- Ethereum Mainnet (etherscan.io)
- Polygon (polygonscan.com)
- Optimism (optimistic.etherscan.io)
- Arbitrum (arbiscan.io)
- Base (basescan.org)
- Any Hardhat local network
- Inject signer to ethers
- Optimize the launch of the browser
- Optimize the webpage
- Add support of other wallets
- Coinbase Wallet
- OKX Wallet
- WalletConnect
