• Java对接(BSC)币安链 | BNB与BEP20的开发实践(二)BNB转账、BEP20转账、链上交易监控


    上一节我们主要是环境搭建,主要是为了能够快速得去开发,有些地方只是简单的介绍,比如ETH 、web3j等等这些。

    这一节我们来用代码来实现BNB转账、BEP20转账、链上交易监控

    话不多说,我们直接用代码实现吧

    1. BNB转账

    1. /**
    2. * BNB转账
    3. * @param toAddress 接收地址地址
    4. * @param amount 金额
    5. * @return
    6. */
    7. @Override
    8. public String transBscBnbJson(String toAddress, String amount) throws Exception {
    9. Web3j web3j = Web3j.build(new HttpService(tronServiceConfig.getBscUrl()));
    10. EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(tronServiceConfig.getBscFromAddress(), DefaultBlockParameterName.LATEST).sendAsync().get();
    11. BigInteger nonce = ethGetTransactionCount.getTransactionCount();
    12. BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
    13. BigInteger gasLimit = BigInteger.valueOf(60000);
    14. BigInteger functionAmount = Convert.toWei(new BigDecimal(amount), Convert.Unit.ETHER).toBigInteger();
    15. RawTransaction rawTransaction = RawTransaction.createEtherTransaction(nonce, gasPrice, gasLimit, toAddress, functionAmount);
    16. // 私钥
    17. Credentials credentials = Credentials.create(tronServiceConfig.getBscFromPrivateKey());
    18. //进行签名操作
    19. byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
    20. String hexValues = Numeric.toHexString(signMessage);
    21. //发起交易
    22. EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValues).sendAsync().get();
    23. String hash = ethSendTransaction.getTransactionHash();
    24. if (hash != null) {
    25. //执行业务
    26. log.info("BNB转账执行成功:" + hash);
    27. }
    28. return hash;
    29. }

       

    2. BEP20转账

    1. /**
    2. * BEP20转账
    3. * @param toAddress 接受地址地址
    4. * @param amount 金额
    5. * @return
    6. */
    7. @Override
    8. public String transBscJson(String toAddress, String amount) {
    9. BigInteger gasLimit = BigInteger.valueOf(60000);
    10. try {
    11. BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
    12. StaticGasProvider staticGasProvider = new StaticGasProvider(gasPrice, gasLimit);
    13. // 私钥
    14. Credentials credentials1 = Credentials.create(MarketConstruct.BOCT_STAKE_CONTRACT_OWER_PRIVATE_KEY);
    15. // load合约
    16. BEP2E bep2e = BEP2E.load(MarketConstruct.BOCT_CONTRACT_ADDRESS, web3j, credentials1, staticGasProvider);
    17. // 转账
    18. BigInteger pow = BigInteger.valueOf(10L).pow(18);
    19. BigInteger multiply = new BigDecimal(amount).multiply(new BigDecimal(pow.toString())).toBigInteger();
    20. TransactionReceipt send = bep2e.transfer(toAddress, multiply).send();
    21. String transactionHash = send.getTransactionHash();
    22. if (StrUtil.isEmpty(transactionHash)) {
    23. log.info("error_");
    24. return "error_error";
    25. }
    26. return transactionHash;
    27. } catch (Exception ex) {
    28. log.info("error_", ex);
    29. return "error_" + ex.getMessage();
    30. }
    31. }

       

    当我们转账成功后,需要进行账户余额查询

    BNB与BEP20余额查询

    1. /**
    2. * 功能描述:查询BNB余额
    3. * 修订记录:
    4. */
    5. public BigDecimal queryBNBBalance(String address) throws Exception {
    6. DefaultBlockParameter defaultBlockParameter = new DefaultBlockParameterNumber(web3b.ethBlockNumber().send().getBlockNumber());
    7. EthGetBalance balance = web3b.ethGetBalance(address, defaultBlockParameter).send();
    8. BigDecimal bigDecimal = new BigDecimal(balance.getBalance());
    9. BigInteger pow = BigInteger.valueOf(10L).pow(18);
    10. return bigDecimal.divide(new BigDecimal(pow), 4, RoundingMode.HALF_UP);
    11. }
    12. /**
    13. * 功能描述:查询BEP20余额
    14. * 修订记录:
    15. *
    16. 20240309  |    |  创建方法

  • */
  • public BigDecimal queryBEP2EBBalance(String contractAddr, String address) throws Exception {
  • try {
  • BigInteger gasPrice = web3b.ethGasPrice().send().getGasPrice();
  • TransactionManager transactionManager = new ReadonlyTransactionManager(web3b, address);
  • StaticGasProvider staticGasProvider = new StaticGasProvider(gasPrice, BigInteger.valueOf(4700000));
  • BEP2E bep2e = BEP2E.load(contractAddr, web3b, transactionManager, staticGasProvider);
  • BigInteger balance = bep2e.balanceOf(address).send();
  • BigDecimal bigDecimal = new BigDecimal(balance);
  • BigInteger pow = BigInteger.valueOf(10L).pow(18);
  • return bigDecimal.divide(new BigDecimal(pow), 4, RoundingMode.HALF_UP);
  • } catch (Exception ex) {
  • return BigDecimal.ZERO;
  • }
  • }
  • 3.链上交易监控

    和之前TRON TRC20同样的艰辛,BNB的监控逻辑和业务包括web3j的支持,以及RPC接口的稳定性,简直是折腾了一个够。

    最终的最好的解决办法:自建一个区块链节点,可惜本人没有那么大的财力,去长期购买大容量的服务器支持,只能做了一个服务接口,服务不稳定时,自动重启连接。效果还过得去吧。目前为止,没有丢块现象了。

    假如是自建区块链节点,又不是JAVA语言开发,那就不会出现问题

    废话不多说,首先还是查找链上最大的交易块。

    1. Request request = web3j.ethBlockNumber();
    2. BigInteger blockNumber = request.send().getBlockNumber();
    1. /**
    2. * 功能描述:创建开始与结束区块, 重放这段时间内的交易,防止遗漏
    3. * 修订记录:
    4. */
    5. public void startReplayListen_BiAn(Web3j web3j, BigInteger startBlockNum) {
    6. //创建开始与结束区块, 重放这段时间内的交易,防止遗漏
    7. DefaultBlockParameter startBlock = new DefaultBlockParameterNumber(startBlockNum);
    8. web3j.replayPastTransactionsFlowable(startBlock, DefaultBlockParameterName.LATEST).subscribe(tx -> {
    9. String fromAddress = tx.getFrom();
    10. String toAddress = tx.getTo();
    11. // 发现了指定地址上的交易
    12. BigInteger blockNumber = tx.getBlockNumber();
    13. KeyValue keyValueNum = keyValueMapper.selectByKey(MarketConstruct.BOCT_STAKE_CONTRACT_ADDRESS);
    14. if (keyValueNum.getValue().equalsIgnoreCase(toAddress)) {
    15. String transactionHash = tx.getHash();
    16. String timestamp = "";
    17. try {
    18. DefaultBlockParameter defaultBlockParameter = DefaultBlockParameter.valueOf(blockNumber);
    19. EthBlock ethBlock = web3j.ethGetBlockByNumber(defaultBlockParameter, false).send();
    20. timestamp = String.valueOf(ethBlock.getBlock().getTimestamp());
    21. Long timestamp1 = Long.parseLong(timestamp) * 1000L;
    22. BigDecimal amount = new BigDecimal(new BigInteger(tx.getInput().substring(12), 16)).divide(BigDecimal.valueOf(1000000000000000000.0), 18, BigDecimal.ROUND_HALF_EVEN);
    23. checkBlock(transactionHash, tx.getBlockNumber(), fromAddress, amount, timestamp1.toString(), 1L, BigInteger.valueOf(1L), BigInteger.valueOf(1L));
    24. } catch (IOException e) {
    25. log.error("Block timestamp get failure,block number is {}", blockNumber);
    26. log.error("Block timestamp get failure,{}", e.getMessage());
    27. }
    28. }
    29. }, error -> log.error(" ### replayPastTransactionsFlowable error= ", error));
    30. }

    全网的监控代码基本清一色的是下方代码方法:

    1. web3j.ethLogFlowable(ethFilter).subscribe(logs -> {
    2. // ......
    3. }, error -> log.error("contractExtract subscribe in error", error));

    可惜运行大概一个小时之后,就无法正常使用,web3j内部错误,github上寻求了各种方法,包括改web3j版本,将web3j的监控改为websocket都无法完美实现,也是通过研究和大量的调试,才找到了最好办法。

    假如有大神可完美,那就不吝赐教000

    目前市面上Java开发虽然也是主流,但是可以使用其他开发语言实现区块链功能,那就改变下,比如Go。

    本人只是为了业务代码工程只停留在Java一个项目内才死脑筋JAVA开发的,其实还是还做了一套Go的监控代码,那用起来是非常舒心。

  • 相关阅读:
    关于docker启动时报错binlog权限问题
    Webserve(2): HTTP解析
    常用的排序算法
    2022/7/2做题总结
    [PowerQuery] PowerAutoMate 刷新PowerBI 数据
    Angular 由一个bug说起之二:trackBy的一点注意事项
    【Go】Fyne跨平台图形界面框架使用
    当你学会这项python数据提取神器时,请做好升职准备!
    单机版和网络版的区别
    SpringMVC
  • 原文地址:https://blog.csdn.net/t610654893/article/details/136589087