The web3-eth package is an essential library for interacting with the Ethereum blockchain and smart contracts. This guide will walk you through the foundational steps to harness its capabilities using web3.js version 4 and TypeScript.
Setting Up Your Development Environment
Before diving into coding, it's crucial to prepare your workspace with the necessary tools:
- Ganache: A personal blockchain for Ethereum development that simulates real-world scenarios. It allows you to test smart contracts locally.
- Node.js: A JavaScript runtime that enables server-side execution of JavaScript code.
- npm (Node Package Manager): A tool for managing and installing JavaScript packages. You can also use Yarn as an alternative.
Ensure all tools are correctly installed and configured before proceeding.
Initializing a New Node.js Project
Start by creating a new directory for your project and initialize it with Node.js:
mkdir smart-contract-tutorial
cd smart-contract-tutorial
npm init -yThis command generates a package.json file. Next, install TypeScript and necessary type definitions:
npm i typescript @types/nodeInstalling web3.js and Connecting to Ganache
Install the web3 package:
npm i web3Create an index.ts file and add the following code to establish a connection to your local Ganache instance:
import { Web3 } from 'web3';
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545'));
const block = await web3.eth.getBlockNumber();
console.log('Last block:', block);Run the script to test the connection:
npx ts-node index.tsIf successful, the current block number will be displayed. If you encounter a connection error, verify that Ganache is running on port 7545.
Deploying Smart Contracts and Managing Transactions
Sending a Simple Transaction
Create a transaction.ts file with the following code to execute a basic Ether transfer:
import { Web3 } from 'web3';
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545'));
web3.eth.Contract.handleRevert = true;
async function interact() {
const accounts = await web3.eth.getAccounts();
let balance1 = await web3.eth.getBalance(accounts[0]);
let balance2 = await web3.eth.getBalance(accounts[1]);
const transaction = {
from: accounts[0],
to: accounts[1],
value: web3.utils.toWei('1', 'ether'),
};
const transactionHash = await web3.eth.sendTransaction(transaction);
balance1 = await web3.eth.getBalance(accounts[0]);
balance2 = await web3.eth.getBalance(accounts[1]);
const gasPrice = await web3.eth.getGasPrice();
console.log(gasPrice);
}
(async () => {
await interact();
})();Execute the script:
npx ts-node transaction.tsYou should see updated account balances and transaction details.
Estimating Gas for Contract Deployment
Gas estimation is critical for efficient contract deployment. Create an estimate.ts file:
import { Web3, ETH_DATA_FORMAT, DEFAULT_RETURN_FORMAT } from 'web3';
async function estimate() {
const abi = [ /* Your ABI here */ ];
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545'));
const accounts = await web3.eth.getAccounts();
let acc = accounts[0];
let contract = new web3.eth.Contract(abi);
const deployment = contract.deploy({
data: '0x...', // Your contract bytecode
arguments: [1],
});
let estimatedGas = await deployment.estimateGas({ from: acc }, DEFAULT_RETURN_FORMAT);
console.log('Default format:', estimatedGas);
estimatedGas = await deployment.estimateGas({ from: acc }, ETH_DATA_FORMAT);
console.log('Eth format:', estimatedGas);
}
(async () => {
await estimate();
})();Run the script to see gas estimates in different formats.
Sending Signed Transactions
For enhanced security, transactions can be signed before being broadcasted. Create a sendSigned.ts file:
import { Web3 } from 'web3';
const web3 = new Web3('http://localhost:7545');
const privateKey = 'YOUR_PRIVATE_KEY'; // Replace with a key from Ganache
const value = web3.utils.toWei('1', 'ether');
async function sendSigned() {
const accounts = await web3.eth.getAccounts();
const tx = {
from: accounts[0],
to: accounts[1],
value: value,
gas: 21000,
gasPrice: web3.utils.toWei('10', 'gwei'),
nonce: await web3.eth.getTransactionCount(accounts[0]),
};
const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey);
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
console.log('Transaction receipt:', receipt);
}
(async () => {
await sendSigned();
})();Execute to send a signed transaction.
Importing Specific Packages
To optimize bundle size, import only the necessary modules:
import { Web3Eth } from 'web3-eth';
const eth = new Web3Eth('http://localhost:7545');
async function test() {
const accounts = await eth.getAccounts();
const currentBalance = await eth.getBalance(accounts[0]);
console.log('Current balance:', currentBalance);
}
(async () => {
await test();
})();Configuration settings can be applied directly:
import { Web3Eth } from 'web3-eth';
const eth = new Web3Eth('http://localhost:8545');
eth.setConfig({ defaultTransactionType: '0x1' });Handling Different Transaction Types
Legacy Transactions
Legacy transactions involve manually setting gas prices, which can fluctuate with network demand. They were standard before EIP-1559.
const tx = {
from: account.address,
to: '0x...',
value: '0x1',
gas: BigInt(21000),
gasPrice: await web3.eth.getGasPrice(),
type: BigInt(0),
};
const receipt = await web3.eth.sendTransaction(tx);EIP-2930 Transactions
EIP-2930 introduced access lists for better gas efficiency in state accesses.
const tx = {
from: account.address,
to: '0x...',
value: '0x1',
gasLimit: BigInt(21000),
type: BigInt(1),
};
const receipt = await web3.eth.sendTransaction(tx);EIP-1559 Transactions
EIP-1559 reformed the fee market with a base fee and priority tip mechanism.
const tx = {
from: account.address,
to: '0x...',
value: '0x1',
gasLimit: BigInt(21000),
type: BigInt(2),
};
const receipt = await web3.eth.sendTransaction(tx);👉 Explore advanced transaction strategies
Conclusion
This guide covered the core functionalities of the web3-eth package, from environment setup to executing various transaction types. With this knowledge, you can begin developing and interacting with the Ethereum blockchain efficiently.
Remember, the Ethereum ecosystem is dynamic. Continuously explore new tools and practices to enhance your decentralized application development skills.
Frequently Asked Questions
What is the web3-eth package used for?
The web3-eth package provides a comprehensive suite of methods to interact with the Ethereum blockchain. It allows developers to send transactions, deploy contracts, read state, and manage accounts programmatically.
How do I estimate gas costs for a transaction?
Use the estimateGas method available in web3.js. This function simulates the transaction and returns the estimated gas required, helping you set appropriate gas limits and avoid overpaying.
What are the benefits of EIP-1559 transactions?
EIP-1559 introduces a base fee that adjusts dynamically with network congestion, making transaction costs more predictable. It also includes a priority fee for miners, improving user experience and network efficiency.
Can I use web3-eth without importing the entire web3 library?
Yes, you can import specific modules like web3-eth to reduce your application's bundle size. This is particularly useful for front-end projects where optimization is critical.
How do I securely manage private keys in web3.js?
Always keep private keys environment variables or secure vaults. Never hardcode them in your source code. Use web3.js' wallet management features to handle signing securely.
What is the purpose of access lists in EIP-2930?
Access lists specify which storage slots and addresses a transaction will access, allowing for gas savings by preloading these states. This reduces the overall cost of executing complex transactions.