以太坊作为全球最大的去中心化应用平台,其主网络承载着价值数百亿美元的数字资产和无数智能合约,对于Java开发者而言,想要与以太坊主网络进行交互,即读取链上数据、发送交易、调用智能合约等,Web3j是一个强大且流行的选择,本文将详细介绍如何使用Web3j来调用以太坊主网络,涵盖环境搭建、节点连接、账户管理、交易发送及智能合约交互等核心环节。

Web3j是一个轻量级的、响应式的Java和Android库,用于与以太坊节点进行集成,它提供了丰富的API,使得Java开发者能够方便地与以太坊区块链进行交互,而无需深入了解底层协议(如JSON-RPC)。
在开始之前,你需要准备以下环境:
在你的Maven项目的pom.xml文件中添加Web3j依赖:

<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>4.9.8</version> <!-- 请使用最新版本 -->
</dependency>
编写Java代码来建立与以太坊主网络的连接,如果你使用Infura,获取到的主网络RPC URL通常类似于:https://mainnet.infura.io/v3/YOUR_PROJECT_ID。
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
public class EthereumConnection {
public static void main(String[] args) {
// 替换为你的Infura项目ID或其他以太坊节点的RPC URL
String infuraUrl = "https://mainnet.infura.io/v3/YOUR_PROJECT_ID";
// 创建Web3j实例,连接到以太坊主网络
Web3j web3j = Web3j.build(new HttpService(infuraUrl));
// 测试连接
try {
String clientVersion = web3j.web3ClientVersion().send().getWeb3ClientVersion();
System.out.println("成功连接到以太坊节点,客户端版本: " clientVersion);
System.out.println("当前最新区块号: " web3j.ethBlockNumber().send().getBlockNumber());
} catch (Exception e) {
System.err.println("连接以太坊节点失败: " e.getMessage());
e.printStackTrace();
} finally {
// 关闭连接
web3j.shutdown();
}
}
}
运行上述代码,如果成功打印出客户端版本和最新区块号,说明你已经成功通过Web3j连接到了以太坊主网络。
连接到主网络后,你可以查询以太坊地址的余额,以太坊余额单位是Wei,1 ETH = 10^18 Wei。

import org.web3j.protocol.core.methods.response.EthGetBalance;
import java.math.BigInteger;
public class GetBalance {
public static void main(String[] args) {
String infuraUrl = "https://mainnet.infura.io/v3/YOUR_PROJECT_ID";
Web3j web3j = Web3j.build(new HttpService(infuraUrl));
// 要查询余额的以太坊地址
String address = "0x742d35Cc6634C0532925a3b844Bc9e7595f8e52a"; // 示例地址
try {
// 获取地址余额,单位是Wei
EthGetBalance balance = web3j.ethGetBalance(address, DefaultBlockParameterName.LATEST).send();
BigInteger balanceInWei = balance.getBalance();
// 将Wei转换为ETH (1 ETH = 10^18 Wei)
double balanceInEth = balanceInWei.doubleValue() / Math.pow(10, 18);
System.out.println("地址: " address);
System.out.println("余额 (ETH): " balanceInEth);
} catch (Exception e) {
System.err.println("获取余额失败: " e.getMessage());
e.printStackTrace();
} finally {
web3j.shutdown();
}
}
}
发送交易需要支付Gas费用,并且需要使用发送者的私钥对交易进行签名。请务必注意私钥的安全性,切勿在代码中硬编码私钥,生产环境中应使用硬件钱包或安全的密钥管理方案。
以下是一个发送ETH转账的示例(简化版,实际使用时需更严谨的Gas管理和错误处理):
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;
import java.math.BigInteger;
public class SendTransaction {
public static void main(String[] args) {
String infuraUrl = "https://mainnet.infura.io/v3/YOUR_PROJECT_ID";
Web3j web3j = Web3j.build(new HttpService(infuraUrl));
// 发送者的私钥 (仅用于示例,实际请妥善保管!)
String privateKey = "YOUR_PRIVATE_KEY";
// 发送者地址
String fromAddress = "0xYourFromAddress";
// 接收者地址
String toAddress = "0xYourToAddress";
// 转账金额 (0.01 ETH)
BigInteger value = Convert.toWei("0.01", Convert.Unit.ETH).toBigInteger();
try {
// 1. 获取当前Gas价格
BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
System.out.println("当前Gas价格 (Gwei): " gasPrice.divide(BigInteger.valueOf(10**9)));
// 2. 估算交易Gas限制 (这里使用一个预估值,实际应调用ethEstimateGas)
BigInteger gasLimit = BigInteger.valueOf(21000); // 转账ETH的典型Gas限制
// 3. 创建原始交易
RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
null, // nonce (需要从节点获取)
gasPrice,
gasLimit,
toAddress,
value);
// 4. 凭证化 (使用私钥签名)
Credentials credentials = Credentials.create(privateKey);
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
String hexValue = Numeric.toHexString(signedMessage);
// 5. 发送交易
EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).send();
if (ethSendTransaction.getTransactionHash() != null) {
System.out.println("交易发送成功!交易哈希: " ethSendTransaction.getTransactionHash());
// 可以通过交易哈希在Etherscan等浏览器上查看交易状态
} else {
System.err.println("交易发送失败: " ethSendTransaction.getError().getMessage());
}
} catch (Exception e) {
System.err.println("发送交易时出错: " e.getMessage());
e.printStackTrace();
} finally {
web3j.shutdown();
}
}
}
重要提示:在实际发送交易前,你需要获取正确的nonce值(每个账户发送交易的序号,从0开始递增),并且更准确地估算gasLimit,上述代码中nonce设为null是为了让Web3j自动获取,但在某些情况下可能需要手动获取。
如果你的Java应用需要与以太坊主网络上的智能合约进行交互(例如调用读函数或写函数),Web3j同样提供了强大的支持。
免责声明:本文为转载,非本网原创内容,不代表本网观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
如有疑问请发送邮件至:bangqikeconnect@gmail.com