web3j操作和以太坊基础知识
以太坊中的基本单位
单位很多,主要需要关注的是下面3种。
- 最小单位是wei
- 其中 ether就是常说的1个ETH。1个ETH是1e18 wei。
- 1个Gwei就是常说的gas,一个gas即一个Gwei=1e9 wei。
单位 | wei值 | Wei |
---|---|---|
wei | 1 | 1 wei |
Gwei (shannon) | 1e9 wei | 1,000,000,000 |
ether | 1e18 wei | 1,000,000,000,000,000,000 |
web3j操作
官方提供jar包可供java开发者与链交互,如余额查询、发布合约、发交易等。
maven座标如下所示,其中core是各种API用来做交互的,codegen是用来将合约的abi文件生成java的操作类,类似于gRPC的skeleton生成对应stub文件。具体业务代码使用时直接当作工具类一样调用即可。
<dependency>
<groupId>org.web3j</groupId>
<artifactId>core</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>org.web3j</groupId>
<artifactId>codegen</artifactId>
<version>5.0.0</version>
</dependency>
查询原生币余额
如果是链的原生币(如ETH相对于以太坊),则直接调用web3j.ethGetBalance()方法即可查询地址的余额。需要注意的是这里的余额是需要做精度处理的,详见[以太坊中的基本单位](# 以太坊中的基本单位) ,这里返回的余额单位是wei,要转换成ETH,需要除以
1e18
如果是稳定币,则需要调用合约地址进行查询,因为稳定比都是通过发布智能合约实现的。
public BigDecimal getBalance(String symbol, String address) {
Web3j web3j = Web3jWrapper.get(ChainNetworkEnum.PlatON);
try {
BigInteger balance;
// 原生币直接通过地址查询,USDC,USDT用合约查询
if(symbol.equals(TokenSymbolEnum.LAT.getDesc())){
balance = web3j.ethGetBalance(address, DefaultBlockParameterName.LATEST).send().getBalance();
int decimal = SystemConfig.CHAIN_CONFIG_MAP.get(ChainNetworkEnum.PlatON.getChainCode()).getDecimals();
return AmountHandleUtils.device(new BigDecimal(balance), decimal);
}else {
TAssetsConfig tAssetsConfig = SystemConfig.ASSET_CONFIG_MAP.get(symbol);
String contractAddress= tAssetsConfig.getAddress();
TransactionManager transactionManager = new ReadonlyTransactionManager(web3j, address);
ERC20 erc20 = ERC20.load(contractAddress, web3j, transactionManager, new DefaultGasProvider());
balance = erc20.balanceOf(address).send();
return AmountHandleUtils.device(new BigDecimal(balance), tAssetsConfig.getDecimals());
}
} catch (Exception e) {
log.error("getBalance error", e);
throw new BusinessException(BaseResultEnum.GET_BALANCE_EXCEPTION);
}
}
查询预估gas费用
private BigInteger getEstimateGasUsed(BigInteger gasPrice) {
//查询三方接口预估gasUsed发生异常时直接取默认值
BigInteger gasUsed = BigInteger.valueOf(Long.parseLong(SystemConfig.SYSTEM_CONFIG_MAP.get(SystemConfigEnum.LAT_ESTIMATE_GAS_USED_DEFAULT_VALUE.getKey())));
try {
BigInteger value = Convert.toWei("0.0001", Convert.Unit.GWEI).toBigInteger();
final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(ERC20.FUNC_TRANSFER,
Arrays.asList(new Address(160, "0x9D12656c3f14A35744874FA5A5d89a33B7354bf1"), new Uint256(value)), Collections.emptyList());
String data = FunctionEncoder.encode(function);
// 拼交易Transaction
Transaction transaction=new Transaction(
senderAddress,
BigInteger.ZERO,
gasPrice,
// new DefaultGasProvider().getGasLimit(),
null,
"0x9D12656c3f14A35744874FA5A5d89a33B7354bf1",
value,
data
);
// 估算gasUsed
gasUsed = platOnChainManager.getEstimateGas(transaction);
} catch (Exception e) {
log.error("getEstimateGasUsed error", e);
}
return gasUsed;
}