上一节我们具体讲到Java实现Tron波场链的开发部署:通过trident源码编译组件,使用RPC的方式链接Tron波场链,并进行了代码实现,还有如何创建离线钱包。
这一节我们通过部署好的项目环境,具体如何使用代码来实现波场链的交易监控和交易转账.
1. 所有的开端就是获取链的接通(ApiWrapper)
private ApiWrapper getApiWrapper(String hexPrivateKey) {
//配置是否是测试链还是正式链
if (tronServiceConfig.getTronDomainOnline()) {
// 正式环境需要到Tron申请一个apiKey进行使用
// APIKEY获取往后会讲如何获取
return ApiWrapper.ofMainnet(hexPrivateKey, tronServiceConfig.getApiKey());
} else {
// 测试环境不需要apikey
return new ApiWrapper("grpc.nile.trongrid.io:50051", "grpc.nile.trongrid.io:50061", hexPrivateKey);
}
}
2. 查看Trc20(如USDT)余额
/**
* TRC20余额
* @param address 我的钱包地址
* @return 余额
*/
public BigDecimal getTrc20Balance(String address) {
ApiWrapper client = getApiWrapper(tronServiceConfig.getHexPrivateKey());
// Trc20合约地址
Contract contract = client.getContract(tronServiceConfig.getTrc20Address());
Trc20Contract token = new Trc20Contract(contract, address, client);
BigInteger balanceOf = token.balanceOf(address);
BigDecimal divisor = new BigDecimal(tronServiceConfig.getTrc20Decimals());
BigDecimal divide = new BigDecimal(balanceOf).divide(divisor, 4, RoundingMode.HALF_UP);
client.close();
return divide;
}
3. 查看Trx余额
/**
* TRx余额
* @param address
* @return
*/
@Override
public BigDecimal getTRxBalance(String address) {
ApiWrapper wrapper = getApiWrapper(tronServiceConfig.getHexPrivateKey());
Long balance = wrapper.getAccountBalance(address);
BigDecimal divisor = new BigDecimal(tronServiceConfig.getTrc20Decimals());
BigDecimal divide = new BigDecimal(balance).divide(divisor, 4, RoundingMode.HALF_UP);
wrapper.close();
return divide;
}
4. Trc20转账实现
/**
* TRC20 转账
* @param fromAddress
* @param toAddress
* @param amount
* @return
*/
@Override
public String transTrc20(String fromAddress, String toAddress, String amount) {
try {
ApiWrapper client = getApiWrapper(tronServiceConfig.getHexPrivateKey());
// 获取合约地址信息
Contract contract = client.getContract(tronServiceConfig.getTrc20Address());
Trc20Contract token = new Trc20Contract(contract, fromAddress, client);
String transfer;
// 获取转账账户的TRX余额
BigInteger trc20Value = token.balanceOf(fromAddress);
// 获取想要转账的数额
BigInteger sunAmountValue = Convert.toSun(amount, Convert.Unit.TRX).toBigInteger();
// 进行比较
if (trc20Value.compareTo(sunAmountValue) >= 0) {
log.info("开始转账.........");
// 设置最大矿工费用
long feeLimit = Convert.toSun("100", Convert.Unit.TRX).longValue();
//转账
transfer = token.transfer(toAddress, sunAmountValue.longValue(), 0, "转账", feeLimit);
} else {
return "error_error";
}
if (StrUtil.isEmpty(transfer)) {
return "error_error";
}
log.info("交易ID:{}", transfer);
client.close();
return transfer;
} catch (Exception ex) {
String message = ex.getMessage();
return "error_" + message;
}
}
5. TRX转账
/**
* TRX转账
* @param fromAddress 输入地址
* @param toAddress 转账地址
* @param amount 金额
* @return
*/
@Override
public String transferTRX(String fromAddress, String toAddress, int amount) {
ApiWrapper wrapper = getApiWrapper(tronServiceConfig.getHexPrivateKey());
try {
BigDecimal divisor = new BigDecimal(tronServiceConfig.getTrc20Decimals());
Long rechangeAmount = new BigDecimal(String.valueOf(amount)).multiply(divisor).longValue();
// 创建交易
Response.TransactionExtention transaction = wrapper.transfer(fromAddress, toAddress, rechangeAmount);
log.info("transaction:{}", transaction);
log.info("transaction.Txid:{}", transaction.getTxid());
// 签名交易
Chain.Transaction signTransaction = wrapper.signTransaction(transaction);
log.info("signTransaction:{}", signTransaction);
// 计算交易所需要的宽带
long byteSize = wrapper.estimateBandwidth(signTransaction);
log.info("byteSize:{}", byteSize);
// 广播交易
String hashTx = wrapper.broadcastTransaction(signTransaction);
log.info("hashTRX:{}", hashTx);
return hashTx;
} catch (Exception e) {
log.error("TransactionService#transfer error: {}", e.getMessage());
}
wrapper.close();
return null;
}
6. 交易监控
之所以交易监控放在最后,是因为本人在交易监控上做了很多很多的尝试,最后找到了JAVA实现自认为是最好的实例。
-- 交易监控说白话就是在链接波场链的同时,监控波场链上的交易信息,再把这些交易信息检索和反编码,获取到真实TRX和TRC20所需交易。
-- 不管怎么做,首先的想法就是要获取当前交易到的区块,或者自己想要从哪个区块高度进行开始交易监控
-- 不变的是,监控一定以及肯定的是将监控到最后一个块的交易,也就是链上最后一笔交易
// 获取目前最高交易块
Long number = wrapper.getNowBlock().getBlockHeader().getRawData().getNumber();
-- 为了避免程序抖动或者检索交易错误,我采取交易块区间式的检索 --
也就是一次监控,监控的事一个块区间而不是一个最新块。
// BLOCKS_20 后退区间高度数
Response.BlockListExtention blockByLimitNext = wrapper.getBlockByLimitNext(endNum - BLOCKS_20, endNum);
// 区间块列表
List<Response.BlockExtention> blockList = blockByLimitNext.getBlockList();
for (Response.BlockExtention blockExtention : blockList) {
Long trc20_target_block_number = blockExtention.getBlockHeader().getRawData().getNumber();
RedissonUtils.setBucket("EXCHANGE_LISTENER:TRC20", DateUtil.formatDateTime(new Date()) + " 区块高度:" + current_sync_block_number + " 扫描高度:" + trc20_target_block_number);
// 处理块信息
switchDataTransaction(blockExtention);
}
/**
* 检索块信息,获取交易信息
* @param blockExtention
* @throws Throwable
*/
public void switchDataTransaction(Response.BlockExtention blockExtention) throws Throwable {
List<Response.TransactionExtention> transactionsList = blockExtention.getTransactionsList();
for (Response.TransactionExtention transactionExtention : transactionsList) {
List<Chain.Transaction.Contract> contractList = transactionExtention.getTransaction().getRawData().getContractList();
for (Chain.Transaction.Contract contract : contractList) {
Class a = Class.forName("org.tron.trident.proto.Contract$" + contract.getType());
Message unpack = contract.getParameter().unpack(a);
// TriggerSmartContract是合约, 按照不同的交易类型检索
if (unpack instanceof Contract.TriggerSmartContract) {
// 合约地址
Contract.TriggerSmartContract contractStr = (Contract.TriggerSmartContract) unpack;
ByteString contractAddress = contractStr.getContractAddress();
String hex = ApiWrapper.toHex(contractAddress);
String contractAddressStr = TronUtils.toViewAddress(hex);
// 判断是否是自己需要监控的合约地址
if (tronServiceConfig.getTrc20Address().equalsIgnoreCase(contractAddressStr)) {
ByteString ownerAddress = contractStr.getOwnerAddress();
String hex2 = ApiWrapper.toHex(ownerAddress);
String fromAddress = TronUtils.toViewAddress(hex2);
ByteString data = contractStr.getData();
String hex1 = ApiWrapper.toHex(data);
// 交易类型是转账
String transferFunction = Hex.toHexString(new Keccak.Digest256().digest("transfer(address,uint256)".getBytes())).substring(0, 8);
String funcId = hex1.substring(0, 8);
if (!transferFunction.equals(funcId)) {
continue;
}
String toAddress = hex1.substring(32, 72);
String amount = hex1.substring(72, 136);
try {
Address address = (Address) TypeDecoder.instantiateType("address", toAddress);
// 地址
NumericType amountType = (NumericType) TypeDecoder.instantiateType("uint256", amount);
// 金额
BigDecimal trc20Decimals = new BigDecimal(tronServiceConfig.getTrc20Decimals());
BigDecimal amountee = new BigDecimal(amountType.getValue()).divide(trc20Decimals, 6, RoundingMode.FLOOR);
byte[] byteArray = transactionExtention.getTransaction().getRawData().toByteArray();
byte[] bytes = Hash.sha256(byteArray);
String txId = Hex.toHexString(bytes);
// 后续处理
// trc20.exchangeService.triggerSmartContract(address.getValue(), amountee, txId);
} catch (Exception e) {
log.error("TRON监控报错", e);
continue;
}
}
}
}
}
}
监控通知定时循环任务发起,注意循环任务的发起文章来源:https://www.toymoban.com/news/detail-838842.html
下一节:Tron波场链水龙头、web3、apikey如何获取文章来源地址https://www.toymoban.com/news/detail-838842.html
到了这里,关于Java实现Tron(波场)区块链的开发实践(二)交易监控与转账的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!