Hardhat plugin that integrates Web3.js 1.x into the Hardhat development environment
npx @tessl/cli install tessl/npm-nomiclabs--hardhat-web3@2.1.0Hardhat Web3 Plugin integrates Web3.js 1.x into the Hardhat development environment. This plugin extends the Hardhat Runtime Environment with both the Web3 module and an initialized Web3 instance connected to the selected network, enabling developers to use familiar Web3.js APIs within Hardhat tasks, scripts, and tests.
npm install --save-dev @nomiclabs/hardhat-web3 web3@^1.0.0-beta.36The plugin is imported by requiring or importing it in your Hardhat configuration file:
require("@nomiclabs/hardhat-web3");For TypeScript:
import "@nomiclabs/hardhat-web3";For direct access to provider adapter components:
import {
JsonRpcRequest,
JsonRpcResponse,
Web3HTTPProviderAdapter,
} from "@nomiclabs/hardhat-web3/dist/src/web3-provider-adapter";After importing the plugin in your hardhat.config.js or hardhat.config.ts, Web3.js becomes available through the Hardhat Runtime Environment:
require("@nomiclabs/hardhat-web3");
// Access Web3 in tasks
task("accounts", "Prints accounts", async (_, { web3 }) => {
console.log(await web3.eth.getAccounts());
});
// Access Web3 in scripts
async function main() {
const accounts = await hre.web3.eth.getAccounts();
console.log("Available accounts:", accounts);
const balance = await hre.web3.eth.getBalance(accounts[0]);
console.log("Balance:", hre.web3.utils.fromWei(balance, 'ether'), "ETH");
}The plugin uses Hardhat's extension mechanism to add Web3.js functionality:
extendEnvironment() to extend the Hardhat Runtime EnvironmentProvides access to the Web3.js constructor through the Hardhat Runtime Environment.
interface HardhatRuntimeEnvironment {
Web3: typeof Web3;
}The Web3 property gives you access to the Web3.js constructor, allowing you to create new Web3 instances if needed.
Provides a pre-configured Web3.js instance connected to the selected Hardhat network.
interface HardhatRuntimeEnvironment {
web3: Web3;
}The web3 property provides an already initialized Web3 instance that automatically connects to whatever network is configured in Hardhat (localhost, mainnet, testnet, etc.).
The plugin includes a provider adapter that bridges Hardhat's internal provider to Web3.js. While primarily used internally by the plugin, these components are also exported and can be imported directly if needed.
// From hardhat/types
interface EthereumProvider {
send(method: string, params?: any[]): Promise<any>;
}
interface JsonRpcRequest {
jsonrpc: string;
method: string;
params: any[];
id: number;
}
interface JsonRpcResponse {
jsonrpc: string;
id: number;
result?: any;
error?: {
code: number;
message: string;
data?: any;
};
}
class Web3HTTPProviderAdapter {
constructor(provider: EthereumProvider);
send(
payload: JsonRpcRequest,
callback: (error: Error | null, response?: JsonRpcResponse) => void
): void;
send(
payload: JsonRpcRequest[],
callback: (error: Error | null, response?: JsonRpcResponse[]) => void
): void;
isConnected(): boolean;
}The Web3HTTPProviderAdapter class adapts Hardhat's Ethereum provider interface to work with Web3.js. It supports both single and batch JSON-RPC requests and provides proper error handling.
task("balance", "Get account balance")
.addParam("account", "The account's address")
.setAction(async (taskArgs, { web3 }) => {
const balance = await web3.eth.getBalance(taskArgs.account);
console.log(web3.utils.fromWei(balance, 'ether'), "ETH");
});// scripts/deploy.js
async function main() {
const [deployer] = await hre.web3.eth.getAccounts();
console.log("Deploying contracts with account:", deployer);
const balance = await hre.web3.eth.getBalance(deployer);
console.log("Account balance:", hre.web3.utils.fromWei(balance, 'ether'), "ETH");
// Deploy contract using Web3
const contract = new hre.web3.eth.Contract(abi);
const deployedContract = await contract.deploy({
data: bytecode,
arguments: []
}).send({
from: deployer,
gas: 1500000,
gasPrice: '30000000000'
});
console.log("Contract deployed at:", deployedContract.options.address);
}describe("MyContract", function () {
it("Should deploy and work correctly", async function () {
const accounts = await web3.eth.getAccounts();
const owner = accounts[0];
const contract = new web3.eth.Contract(abi);
const deployedContract = await contract.deploy({
data: bytecode
}).send({
from: owner,
gas: 1500000
});
expect(deployedContract.options.address).to.not.be.empty;
});
});async function customWeb3Example() {
// Access the Web3 constructor
const CustomWeb3 = hre.Web3;
// Create a custom instance with different provider
const customWeb3 = new CustomWeb3('https://mainnet.infura.io/v3/YOUR_KEY');
// Use the custom instance
const blockNumber = await customWeb3.eth.getBlockNumber();
console.log("Current block:", blockNumber);
}The plugin extends the Hardhat Runtime Environment with Web3.js types:
declare module "hardhat/types/runtime" {
interface HardhatRuntimeEnvironment {
Web3: typeof Web3;
web3: Web3;
}
}The provider adapter handles JSON-RPC errors by wrapping them in the proper response format: