当前位置:   article > 正文

Java实现Tron(波场)区块链的开发实践(二)交易监控与转账_tron交易监听

tron交易监听

上一节我们具体讲到Java实现Tron波场链的开发部署:通过trident源码编译组件,使用RPC的方式链接Tron波场链,并进行了代码实现,还有如何创建离线钱包。

这一节我们通过部署好的项目环境,具体如何使用代码来实现波场链的交易监控和交易转账.

1. 所有的开端就是获取链的接通(ApiWrapper)

  1. private ApiWrapper getApiWrapper(String hexPrivateKey) {
  2. //配置是否是测试链还是正式链
  3. if (tronServiceConfig.getTronDomainOnline()) {
  4. // 正式环境需要到Tron申请一个apiKey进行使用
  5. // APIKEY获取往后会讲如何获取
  6. return ApiWrapper.ofMainnet(hexPrivateKey, tronServiceConfig.getApiKey());
  7. } else {
  8. // 测试环境不需要apikey
  9. return new ApiWrapper("grpc.nile.trongrid.io:50051", "grpc.nile.trongrid.io:50061", hexPrivateKey);
  10. }
  11. }

2. 查看Trc20(如USDT)余额

  1. /**
  2. * TRC20余额
  3. * @param address 我的钱包地址
  4. * @return 余额
  5. */
  6. public BigDecimal getTrc20Balance(String address) {
  7. ApiWrapper client = getApiWrapper(tronServiceConfig.getHexPrivateKey());
  8. // Trc20合约地址
  9. Contract contract = client.getContract(tronServiceConfig.getTrc20Address());
  10. Trc20Contract token = new Trc20Contract(contract, address, client);
  11. BigInteger balanceOf = token.balanceOf(address);
  12. BigDecimal divisor = new BigDecimal(tronServiceConfig.getTrc20Decimals());
  13. BigDecimal divide = new BigDecimal(balanceOf).divide(divisor, 4, RoundingMode.HALF_UP);
  14. client.close();
  15. return divide;
  16. }

3. 查看Trx余额

  1. /**
  2. * TRx余额
  3. * @param address
  4. * @return
  5. */
  6. @Override
  7. public BigDecimal getTRxBalance(String address) {
  8. ApiWrapper wrapper = getApiWrapper(tronServiceConfig.getHexPrivateKey());
  9. Long balance = wrapper.getAccountBalance(address);
  10. BigDecimal divisor = new BigDecimal(tronServiceConfig.getTrc20Decimals());
  11. BigDecimal divide = new BigDecimal(balance).divide(divisor, 4, RoundingMode.HALF_UP);
  12. wrapper.close();
  13. return divide;
  14. }

4. Trc20转账实现

  1. /**
  2. * TRC20 转账
  3. * @param fromAddress
  4. * @param toAddress
  5. * @param amount
  6. * @return
  7. */
  8. @Override
  9. public String transTrc20(String fromAddress, String toAddress, String amount) {
  10. try {
  11. ApiWrapper client = getApiWrapper(tronServiceConfig.getHexPrivateKey());
  12. // 获取合约地址信息
  13. Contract contract = client.getContract(tronServiceConfig.getTrc20Address());
  14. Trc20Contract token = new Trc20Contract(contract, fromAddress, client);
  15. String transfer;
  16. // 获取转账账户的TRX余额
  17. BigInteger trc20Value = token.balanceOf(fromAddress);
  18. // 获取想要转账的数额
  19. BigInteger sunAmountValue = Convert.toSun(amount, Convert.Unit.TRX).toBigInteger();
  20. // 进行比较
  21. if (trc20Value.compareTo(sunAmountValue) >= 0) {
  22. log.info("开始转账.........");
  23. // 设置最大矿工费用
  24. long feeLimit = Convert.toSun("100", Convert.Unit.TRX).longValue();
  25. //转账
  26. transfer = token.transfer(toAddress, sunAmountValue.longValue(), 0, "转账", feeLimit);
  27. } else {
  28. return "error_error";
  29. }
  30. if (StrUtil.isEmpty(transfer)) {
  31. return "error_error";
  32. }
  33. log.info("交易ID:{}", transfer);
  34. client.close();
  35. return transfer;
  36. } catch (Exception ex) {
  37. String message = ex.getMessage();
  38. return "error_" + message;
  39. }
  40. }

5. TRX转账

  1. /**
  2. * TRX转账
  3. * @param fromAddress 输入地址
  4. * @param toAddress 转账地址
  5. * @param amount 金额
  6. * @return
  7. */
  8. @Override
  9. public String transferTRX(String fromAddress, String toAddress, int amount) {
  10. ApiWrapper wrapper = getApiWrapper(tronServiceConfig.getHexPrivateKey());
  11. try {
  12. BigDecimal divisor = new BigDecimal(tronServiceConfig.getTrc20Decimals());
  13. Long rechangeAmount = new BigDecimal(String.valueOf(amount)).multiply(divisor).longValue();
  14. // 创建交易
  15. Response.TransactionExtention transaction = wrapper.transfer(fromAddress, toAddress, rechangeAmount);
  16. log.info("transaction:{}", transaction);
  17. log.info("transaction.Txid:{}", transaction.getTxid());
  18. // 签名交易
  19. Chain.Transaction signTransaction = wrapper.signTransaction(transaction);
  20. log.info("signTransaction:{}", signTransaction);
  21. // 计算交易所需要的宽带
  22. long byteSize = wrapper.estimateBandwidth(signTransaction);
  23. log.info("byteSize:{}", byteSize);
  24. // 广播交易
  25. String hashTx = wrapper.broadcastTransaction(signTransaction);
  26. log.info("hashTRX:{}", hashTx);
  27. return hashTx;
  28. } catch (Exception e) {
  29. log.error("TransactionService#transfer error: {}", e.getMessage());
  30. }
  31. wrapper.close();
  32. return null;
  33. }

6. 交易监控

之所以交易监控放在最后,是因为本人在交易监控上做了很多很多的尝试,最后找到了JAVA实现自认为是最好的实例。

-- 交易监控说白话就是在链接波场链的同时,监控波场链上的交易信息,再把这些交易信息检索和反编码,获取到真实TRX和TRC20所需交易。

-- 不管怎么做,首先的想法就是要获取当前交易到的区块,或者自己想要从哪个区块高度进行开始交易监控

-- 不变的是,监控一定以及肯定的是将监控到最后一个块的交易,也就是链上最后一笔交易

  1. // 获取目前最高交易块
  2. Long number = wrapper.getNowBlock().getBlockHeader().getRawData().getNumber();

-- 为了避免程序抖动或者检索交易错误,我采取交易块区间式的检索 -- 

    也就是一次监控,监控的事一个块区间而不是一个最新块。

  1. // BLOCKS_20 后退区间高度数
  2. Response.BlockListExtention blockByLimitNext = wrapper.getBlockByLimitNext(endNum - BLOCKS_20, endNum);
  1. // 区间块列表
  2. List<Response.BlockExtention> blockList = blockByLimitNext.getBlockList();
  3. for (Response.BlockExtention blockExtention : blockList) {
  4. Long trc20_target_block_number = blockExtention.getBlockHeader().getRawData().getNumber();
  5. RedissonUtils.setBucket("EXCHANGE_LISTENER:TRC20", DateUtil.formatDateTime(new Date()) + " 区块高度:" + current_sync_block_number + " 扫描高度:" + trc20_target_block_number);
  6. // 处理块信息
  7. switchDataTransaction(blockExtention);
  8. }
  1. /**
  2. * 检索块信息,获取交易信息
  3. * @param blockExtention
  4. * @throws Throwable
  5. */
  6. public void switchDataTransaction(Response.BlockExtention blockExtention) throws Throwable {
  7. List<Response.TransactionExtention> transactionsList = blockExtention.getTransactionsList();
  8. for (Response.TransactionExtention transactionExtention : transactionsList) {
  9. List<Chain.Transaction.Contract> contractList = transactionExtention.getTransaction().getRawData().getContractList();
  10. for (Chain.Transaction.Contract contract : contractList) {
  11. Class a = Class.forName("org.tron.trident.proto.Contract$" + contract.getType());
  12. Message unpack = contract.getParameter().unpack(a);
  13. // TriggerSmartContract是合约, 按照不同的交易类型检索
  14. if (unpack instanceof Contract.TriggerSmartContract) {
  15. // 合约地址
  16. Contract.TriggerSmartContract contractStr = (Contract.TriggerSmartContract) unpack;
  17. ByteString contractAddress = contractStr.getContractAddress();
  18. String hex = ApiWrapper.toHex(contractAddress);
  19. String contractAddressStr = TronUtils.toViewAddress(hex);
  20. // 判断是否是自己需要监控的合约地址
  21. if (tronServiceConfig.getTrc20Address().equalsIgnoreCase(contractAddressStr)) {
  22. ByteString ownerAddress = contractStr.getOwnerAddress();
  23. String hex2 = ApiWrapper.toHex(ownerAddress);
  24. String fromAddress = TronUtils.toViewAddress(hex2);
  25. ByteString data = contractStr.getData();
  26. String hex1 = ApiWrapper.toHex(data);
  27. // 交易类型是转账
  28. String transferFunction = Hex.toHexString(new Keccak.Digest256().digest("transfer(address,uint256)".getBytes())).substring(0, 8);
  29. String funcId = hex1.substring(0, 8);
  30. if (!transferFunction.equals(funcId)) {
  31. continue;
  32. }
  33. String toAddress = hex1.substring(32, 72);
  34. String amount = hex1.substring(72, 136);
  35. try {
  36. Address address = (Address) TypeDecoder.instantiateType("address", toAddress);
  37. // 地址
  38. NumericType amountType = (NumericType) TypeDecoder.instantiateType("uint256", amount);
  39. // 金额
  40. BigDecimal trc20Decimals = new BigDecimal(tronServiceConfig.getTrc20Decimals());
  41. BigDecimal amountee = new BigDecimal(amountType.getValue()).divide(trc20Decimals, 6, RoundingMode.FLOOR);
  42. byte[] byteArray = transactionExtention.getTransaction().getRawData().toByteArray();
  43. byte[] bytes = Hash.sha256(byteArray);
  44. String txId = Hex.toHexString(bytes);
  45. // 后续处理
  46. // trc20.exchangeService.triggerSmartContract(address.getValue(), amountee, txId);
  47. } catch (Exception e) {
  48. log.error("TRON监控报错", e);
  49. continue;
  50. }
  51. }
  52. }
  53. }
  54. }
  55. }

监控通知定时循环任务发起,注意循环任务的发起

下一节:Tron波场链水龙头、web3、apikey如何获取

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/265526
推荐阅读
相关标签
  

闽ICP备14008679号