在区块链应用开发中,与以太坊网络的交互是核心环节,Web3.js 是以太坊官方提供的 JavaScript API 库,它让开发者能够通过浏览器或 Node.js 环境与以太坊节点通信,实现账户查询、交易发送、智能合约交互等功能,本文将详细介绍如何使用 Web3.js 连接以太坊节点,涵盖环境准备、连接方式、代码示例及常见问题解决,助你快速上手 Web3.js 开发。
环境准备:安装 Web3.js
在连接以太坊节点之前,首先需要安装 Web3.js 库,根据开发环境的不同,安装方式略有差异:
浏览器环境(CDN 引入)
如果在前端项目中使用 Web3.js,可通过 CDN 直接引入最新版本,在 HTML 文件的 <head> 或 <body> 标签中添加以下代码:
<script src="https://cdn.jsdelivr.net/npm/web3@4.10.0/dist/web3.min.js"></script>
引入后,全局对象 window 上会挂载 Web3 实例,可直接通过 window.Web3 使用。
Node.js 环境(npm 安装)
如果是后端(Node.js)项目,或需要更灵活的模块化管理,可通过 npm 安装:
npm install web3
安装完成后,在代码中通过 require 或 import 引入:
const Web3 = require('web3'); // CommonJS 方式
// 或
import Web3 from 'web3'; // ES Module 方式
连接以太坊节点的核心方式
以太坊节点是区块链网络的数据中转站,开发者需要通过 RPC(Remote Procedure Call)端点与节点通信,Web3.js 支持多种连接方式,以下是常见场景的实践方法。
连接本地节点(如 Geth 或 Parity)
如果你在本地运行了以太坊节点(如通过 Geth 或 Parity 启动),可直接通过本地 RPC 端点连接。
步骤 1:启动本地节点
以 Geth 为例,启动一个同步以太坊主网的节点(默认 RPC 端口为 8545):
geth --http --http.addr "0.0.0.0" --http.port "8545" --http.corsdomain "*"
--http:启用 HTTP-RPC 服务--http.addr "0.0.0.0":允许任何 IP 访问(开发环境可用,生产环境需限制)--http.corsdomain "*":允许跨域请求(前端开发时需配置)
步骤 2:Web3.js 连接本地节点
const Web3 = require('web3');
// 创建 Web3 实例,传入节点 RPC 地址
const web3 = new Web3('http://localhost:8545');
// 验证连接是否成功
web3.eth.getBlockNumber().then(console.log).catch(console.error);
如果连接成功,控制台会输出当前以太坊网络的最新区块号(如 19000000 左右,具体取决于同步进度)。
连接远程节点(Infura 或 Alchemy)
本地节点同步速度慢且需要高性能设备,开发时更推荐使用第三方远程节点服务(如 Infura、Alchemy),它们提供稳定的 RPC 端点,无需同步全量数据,适合快速开发。
步骤 1:获取 RPC 端点
以 Infura 为例:
- 访问 Infura 官网,注册并创建新项目;
- 选择网络(如 Mainnet、Ropsten 测试网等),获取项目 ID;
- 拼接 RPC 端点格式:
https://<网络名称>.infura.io/v3/<项目 ID>。- 主网:
https://mainnet.infura.io/v3/YOUR_PROJECT_ID - Ropsten 测试网:
https://ropsten.infura.io/v3/YOUR_PROJECT_ID
- 主网:
步骤 2:Web3.js 连接远程节点
const Web3 = require('web3');
// 使用 Infura RPC 端点
const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_PROJECT_ID');
// 验证连接
web3.eth.getBalance('0x742d35Cc6634C0532925a3b844Bc9e7595f8bE8c').then(console.log);
上述代码会查询指定地址的以太坊余额(单位是 wei),可通过 web3.utils.fromWei() 转换为 ETH:
web3.eth.getBalance('0x742d35Cc6634C0532925a3b844Bc9e7595f8bE8c').then(balance => {
console.log(`Balance: ${web3.utils.fromWei(balance, 'ETH')} ETH`);
});
连接 MetaMask 提供的节点
MetaMask 是主流的浏览器钱包插件,它会在用户浏览器中注入 ethereum 对象,可通过该对象获取节点 RPC 地址。
步骤 1:检测 MetaMask 是否安装
if (typeof window.ethereum !== 'undefined') {
console.log('MetaMask is installed!');
} else {
console.log('MetaMask is not installed. Please install it.');
}
步骤 2:通过 MetaMask 连接节点
const Web3 = require('web3');
// 使用 MetaMask 提供的 RPC
const web3 = new Web3(window.ethereum);
// 请求用户授权连接账户
async function connectAccount() {
try {
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
console.log('Connected account:', accounts[0]);
return accounts[0];
} catch (error) {
console.error('User denied account access:', error);
}
}
// 调用连接函数
connectAccount();
注意:MetaMask 仅支持 HTTPS 协议或 localhost,且用户需手动授权连接账户,符合 Web3 钱包的安全机制。
连接 WebSocket 节点(实时通信场景)
HTTP-RPC 是请求-响应模式,适合查询类操作;但如果需要实时监听链上事件(如新区块、交易确认),WebSocket 协议更高效(长连接,避免重复请求)。
步骤 1:启动 WebSocket 节点
以 Geth 为例,启动时添加 --ws 参数:
geth --ws --ws.addr "0.0.0.0" --ws.port "8546" --ws.origins "*"
步骤 2:Web3.js 连接 WebSocket 节点
const Web3 = require('web3');
// 创建 WebSocket 提供者
const web3 = new Web3('ws://localhost:8546');
// 监听新区块事件
web3.eth.subscribe('newBlocks', (error, block) => {
if (error) console.error(error);
console.log('New block received:', block.number);
}).on('connected', (subscriptionId) => {
console.log('Subscription ID:', subscriptionId);
});
连接后的常见操作验证
连接节点后,可通过以下代码验证功能是否正常:
查询当前网络信息
// 获取当前链 ID(主网为 1,Ropsten 测试网为 3) web3.eth.getChainId().then(console.log); // 获取当前节点同步状态 web3.eth.getBlockNumber().then(console.log);
查询账户信息
// 查询节点管理的账户列表(需本地节点解锁)
web3.eth.getAccounts().then(console.log);
// 查询指定地址的余额
const address = '0x742d35Cc6634C0532925a3b844Bc9e7595f8bE8c';
web3.eth.getBalance(address).then(balance => {
console.log(`${web3.utils.toChecksumAddress(address)} 的余额: ${web3.utils.fromWei(balance, 'ETH')} ETH`);
});
发送交易(示例)
发送交易需要私钥签名,建议使用 web3.eth.accounts.signTransaction 安全处理:
const senderPrivateKey = 'YOUR_PRIVATE_KEY'; // 替换为实际私钥(开发环境勿泄露)
const senderAddress = '0xYourSenderAddress';
const receiverAddress = '0xReceiverAddress';
const amount = web3.utils.toWei('0.01', 'ETH'); // 0.01 ETH
// 构建交易对象
const transaction = {
to: receiverAddress,
value: amount,
gas: 21000