Java实现以太坊地址币数量检验的完整指南

 :2026-02-20 9:15    点击:1  

在区块链应用开发中,经常需要查询以太坊地址中持有的代币数量,本文将详细介绍如何使用Java语言实现以太坊地址币数量的检验功能,包括环境搭建、核心代码实现和常见问题解决方案。

技术准备

在开始之前,我们需要准备以下技术栈:

  1. Java 8或更高版本
  2. Web3j库(Java的以太坊交互库)
  3. 以太坊节点或Infura等第三方服务

在项目中添加Web3j依赖(Maven配置):

<dependency>
    <groupId>org.web3j</groupId>
    <artifactId>core</artifactId>
    <version>4.9.8</version>
</dependency>

实现以太坊地址余额查询

连接到以太坊网络

import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
public class EthereumConnector {
    private Web3j web3j;
    public EthereumConnector(String nodeUrl) {
        this.web3j = Web3j.build(new HttpService(nodeUrl));
    }
    public Web3j getWeb3j() {
        return web3j;
    }
}

查询ETH余额

import org.web3j.protocol.core.methods.response.EthGetBalance;
import java.io.IOException;
import java.math.BigInteger;
public class EthBalanceChecker {
    public static BigInteger getEthBalance(Web3j web3j, String address) throws IOException {
        EthGetBalance ethGetBalance = web3j.ethGetBalance(address, DefaultBlockParameterName.LATEST)
                .send();
        return ethGetBalance.getBalance();
    }
    public static void main(String[] args) {
        String nodeUrl = "https://mainnet.infura.io/v3/YOUR_PROJECT_ID";
        String ethAddress = "0x742d35Cc6634C0532925a3b844Bc9e7595f8e9e9";
        EthereumConnector connector = new EthereumConnector(nodeUrl);
        try {
            BigInteger balance = getEthBalance(connector.getWeb3j(), ethAddress);
            System.out.println("ETH Balance: " + balance.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

查询ERC20代币余额

要查询ERC20代币余额,我们需要与代币合约进行交互。

定义代币合约接口

使用Web3j的代码生成功能生成Java合约包装类:

web3j generate solidity -a Token.sol -o ./src/main/java -p com.example.contracts

实现代币余额查询

import org.web3j.protocol.core.methods.response.TransactionReceipt;
import java.math.BigDecimal;
import java.math.BigInteger;
public class TokenBalanceChecker {
    public static BigDecimal getTokenBalance(Web3j web3j, String tokenContractAddress, 
                                           String userAddress, int decimals) throws Exception {
        // 加载代币合约
        Token token = Token.load(tokenContractAddress, web3j, 
                                new Credentials("YOUR_PRIVATE_KEY"), 
                                Contract.GAS_PRICE, Contract.GAS_LIMIT);
        // 调用balanceOf方法
        BigInteger balance = token.balanceOf(userAddress).send();
        // 根据精度转换
        BigDecimal tokenBalance = new BigDecimal(balance).divide(
            new BigDecimal(Math.pow(10, decimals)), 
            decimals, 
            BigDecimal.ROUND_DOWN
        );
        return tokenBalance;
    }
    public static void main(String[] args) {
        String nodeUrl = "https://mainnet.infura.io/v3/YOUR_PROJECT_ID";
        String tokenAddress = "0xdAC17F958D2ee523a2206206994597C13D831ec7"; // USDT合约地址
        String userAddress = "0x742d35Cc6634C0532925a3b844Bc9e7595f8e9e9";
        int decimals = 6; // USDT精度
        EthereumConnector connector = new EthereumConnector(nodeUrl);
        try {
            BigDecimal balance = getTokenBalance(connector.getWeb3j(), tokenAddress, userAddress, decimals);
            System.out.println("Token Balance: " + balance.toPlainString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

完整封装与异常处理

为了使代码更加健壮,我们可以添加异常处理和参数验证:

import org.web3j.utils.Convert;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.regex.Pattern;
public class EthereumBalanceService {
    private static final Pattern ETHEREUM_ADDRESS_PATTERN = Pattern.compile("^0x[0-9a-fA-F]{40}$");
    public static BigDecimal getEthBalanceInEth(Web3j web3j, String address) throws InvalidAddressException, IOException {
        if (!isValidEthereumAddress(address)) {
            throw new InvalidAddressException("Invalid Ethereum address: " + address);
        }
        BigInteger balance = EthBalanceChecker.getEthBalance(web3j, address);
        return Convert.fromWei(new BigDecimal(balance), Convert.Unit.ETH);
    }
    public static BigDecimal getTokenBalance(Web3j web3j, String tokenContractAddress, 
                                           String userAddress, int decimals) 
        throws InvalidAddressException, ContractCallException {
        if (!isValidEthereumAddress(tokenContractAddress) || !isValidEthereumAddress(userAddress)) {
            throw new InvalidAddressException("Invalid address provided");
        }
        try {
            return TokenBalanceChecker.getTokenBalance(web3j, tokenContractAddress, userAddress, decimals);
        } catch (Exception e) {
            throw new ContractCallException("Failed to get token balance: " + e.getMessage(), e);
        }
    }
    public static boole
随机配图
an isValidEthereumAddress(String address) { return ETHEREUM_ADDRESS_PATTERN.matcher(address).matches(); } // 自定义异常类 public static class InvalidAddressException extends Exception { public InvalidAddressException(String message) { super(message); } } public static class ContractCallException extends Exception { public ContractCallException(String message, Throwable cause) { super(message, cause); } } }

使用示例

public class Main {
    public static void main(String[] args) {
        String nodeUrl = "https://mainnet.infura.io/v3/YOUR_PROJECT_ID";
        String ethAddress = "0x742d35Cc6634C0532925a3b844Bc9e7595f8e9e9";
        String usdtAddress = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
        EthereumConnector connector = new EthereumConnector(nodeUrl);
        try {
            // 查询ETH余额
            BigDecimal ethBalance = EthereumBalanceService.getEthBalanceInEth(
                connector.getWeb3j(), ethAddress);
            System.out.println("ETH Balance: " + ethBalance + " ETH");
            // 查询USDT余额
            BigDecimal usdtBalance = EthereumBalanceService.getTokenBalance(
                connector.getWeb3j(), usdtAddress, ethAddress, 6);
            System.out.println("USDT Balance: " + usdtBalance);
        } catch (EthereumBalanceService.InvalidAddressException | 
                 EthereumBalanceService.ContractCallException | IOException e) {
            System.err.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

优化与注意事项

  1. 性能优化:对于频繁查询的场景,可以考虑缓存结果或使用批量查询方法。
  2. 错误处理:网络不稳定或节点不可用时需要有重试机制。
  3. 安全性:不要在代码中硬编码私钥,应使用安全的方式存储和管理。
  4. Gas费用:查询代币余额需要支付Gas费用,虽然是小额费用。
  5. 测试网络:开发阶段建议在Ropsten等测试网络进行测试。

本文详细介绍了如何使用Java和Web3j库实现以太坊地址ETH和ERC20代币余额的查询功能,通过封装和异常处理,我们可以构建健壮的区块链交互服务,随着区块链技术的发展,类似的查询功能在DeFi、NFT等应用场景中将发挥越来越重要的作用,开发者可以根据实际需求进一步扩展功能,如添加多地址批量查询、历史余额查询等高级特性。

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