Java代码实现以太坊代币转账,从环境搭建到实战操作

以太坊代币转账概述

以太坊作为全球第二大公链,其生态中充斥着基于ERC-20标准的代币(如USDT、DAI、LINK等),代币转账本质上是以太坊网络上的一个交易调用,通过调用智能合约的transfer方法,实现代币在地址间的转移,Java作为企业级开发的主流语言,可通过Web3j等库与以太坊节点交互,完成代币转账的编程实现,本文将详细介绍如何使用Java代码实现以太坊代币转账,涵盖环境搭建、核心代码编写及异常处理等关键环节。

环境准备

安装JDK与Maven

确保已安装JDK 8或更高版本,并配置好环境变量,使用Maven管理项目依赖,可通过以下命令创建Maven项目:

mvn archetype:generate -DgroupId=com.ethereum.example -DartifactId=ethereum-token-transfer -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false

添加Web3j依赖

pom.xml中添加Web3j依赖(以最新稳定版为例):

<dependencies>
    <!-- Web3j核心依赖 -->
    <dependency>
        <groupId>org.web3j</groupId>
        <artifactId>core</artifactId>
        <version>4.9.8</version>
    </dependency>
    <!-- 以太坊单位工具类(可选) -->
    <dependency>
        <groupId>org.web3j</groupId>
        <artifactId>utils</artifactId>
        <version>4.9.8</version>
    </dependency>
</dependencies>

准备以太坊节点

代币转账需要连接以太坊节点,可通过以下方式获取:

  • 本地节点:搭建Geth或OpenEthereum节点(需同步区块数据,资源消耗大)。
  • Infura等第三方服务:注册Infura账号,创建项目获取节点URL(如https://mainnet.infura.io/v3/YOUR_PROJECT_ID)。
  • Alchemy等类似服务:提供稳定可靠的节点接口。

创建以太坊钱包

转账需要发送方账户的私钥,可通过MyEtherWallet(MEW)、MetaMask等工具生成,并妥善保存私钥(切勿泄露)。

核心代码实现

初始化Web3j客户端

首先创建Web3j客户端,连接到以太坊节点:

import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
public class EthereumClient {
    private static final String INFURA_URL = "https://mainnet.infura.io/v3/YOUR_PROJECT_ID";
    public static Web3j buildWeb3j() {
        return Web3j.build(new HttpService(INFURA_URL));
    }
}

加载代币合约

ERC-20代币需通过智能合约地址加载,获取合约实例,以USDT(主网合约地址:0xdAC17F958D2ee523a2206206994597C13D831ec7)为例:

import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web
随机配图
3j.protocol.core.methods.response.TransactionReceipt; import org.web3j.tx.Contract; import org.web3j.tx.gas.ContractGasProvider; import org.web3j.tx.gas.StaticGasProvider; import java.math.BigInteger; import java.util.Collections; import java.util.concurrent.ExecutionException; public class TokenTransfer { // 代币合约地址(以USDT为例) private static final String TOKEN_CONTRACT_ADDRESS = "0xdAC17F958D2ee523a2206206994597C13D831ec7"; // 代币ABI(简化版,实际需完整ABI) private static final String TOKEN_ABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"standard\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"type\":\"function\"}]"; private final Web3j web3j; private final Credentials credentials; public TokenTransfer(Web3j web3j, String privateKey) { this.web3j = web3j; this.credentials = Credentials.create(privateKey); } /** * 转账代币 * @param toAddress 接收方地址 * @param amount 转账数量(注意:需乘以decimals) * @return 交易哈希 */ public String transferToken(String toAddress, BigInteger amount) throws Exception { // 1. 构建transfer函数调用 Function function = new Function( "transfer", Collections.singletonList(new Address(toAddress)), Collections.singletonList(new TypeReference<Uint256>() {}) ); // 2. 编码函数调用数据 String data = FunctionEncoder.encode(function); // 3. 获取代币合约的nonce BigInteger nonce = web3j.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.LATEST) .send() .getTransactionCount(); // 4. 估算gas费用(简化版,实际可调用ethEstimateGas) BigInteger gasLimit = BigInteger.valueOf(300000); // 代币转账通常需要200k-300k gas BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice(); // 5. 构建交易 Transaction transaction = Transaction.createFunctionCallTransaction( TOKEN_CONTRACT_ADDRESS, nonce, gasPrice, gasLimit, BigInteger.ZERO, // 转ETH时value不为0,代币转账为0 data ); // 6. 签名并发送交易 EthSendTransaction transactionResponse = web3j.ethSendTransaction(transaction) .sendAsync() .get(); if (transactionResponse.hasError()) { throw new Exception("交易失败: " + transactionResponse.getError().getMessage()); } return transactionResponse.getTransactionHash(); } }

完整调用示例

public class Main {
    public static void main(String[] args) {
        try {
            // 1. 初始化Web3j客户端
            Web3j web3j = EthereumClient.buildWeb3j();
            // 2. 创建TokenTransfer实例(替换为实际私钥)
            String privateKey = "YOUR_PRIVATE_KEY"; // 发送方账户私钥
            TokenTransfer tokenTransfer = new TokenTransfer(web3j, privateKey);
            // 3. 设置接收方地址和转账数量(USDT的decimals=6,所以1 USDT = 1000000)
            String toAddress = "0x742d35Cc6634C0532925a3b844Bc454e4438f44e";
            BigInteger amount = new BigInteger("1000000"); // 1 USDT
            // 4. 执行转账
            String transactionHash = tokenTransfer.transferToken(toAddress, amount);
            System.out.println("交易哈希: " + transactionHash);
            // 5. 等待交易确认(可选)
            Thread.sleep(15000); // 等待15秒
            TransactionReceipt receipt = web3j.ethGetTransactionReceipt(transactionHash).send().getTransactionReceipt().orElse(null);
            if (receipt != null && receipt.getStatus().equals(BigInteger.ONE)) {
                System.out.println("转账成功!");
            } else {
                System.out.println("转账失败或未

本文由用户投稿上传,若侵权请提供版权资料并联系删除!