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

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

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

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

  1. BNB转账
java 复制代码
    /**
     *  BNB转账
     * @param toAddress 接收地址地址
     * @param amount 金额
     * @return
     */
    @Override
    public String transBscBnbJson(String toAddress, String amount) throws Exception {
        Web3j web3j = Web3j.build(new HttpService(tronServiceConfig.getBscUrl()));
        EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(tronServiceConfig.getBscFromAddress(), DefaultBlockParameterName.LATEST).sendAsync().get();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();
        BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
        BigInteger gasLimit = BigInteger.valueOf(60000);

        BigInteger functionAmount = Convert.toWei(new BigDecimal(amount), Convert.Unit.ETHER).toBigInteger();
        RawTransaction rawTransaction = RawTransaction.createEtherTransaction(nonce, gasPrice, gasLimit, toAddress, functionAmount);
        // 私钥
        Credentials credentials = Credentials.create(tronServiceConfig.getBscFromPrivateKey());
        //进行签名操作
        byte[] signMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValues = Numeric.toHexString(signMessage);
        //发起交易
        EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValues).sendAsync().get();
        String hash = ethSendTransaction.getTransactionHash();
        if (hash != null) {
            //执行业务
            log.info("BNB转账执行成功:" + hash);
        }
        return hash;
    }

  1. BEP20转账
java 复制代码
   /**
 *  BEP20转账
 * @param toAddress 接受地址地址
 * @param amount 金额
 * @return
 */
@Override
public String transBscJson(String toAddress, String amount) {
    BigInteger gasLimit = BigInteger.valueOf(60000);
    try {
        BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
        StaticGasProvider staticGasProvider = new StaticGasProvider(gasPrice, gasLimit);
        // 私钥
        Credentials credentials1 = Credentials.create(MarketConstruct.BOCT_STAKE_CONTRACT_OWER_PRIVATE_KEY);
        // load合约
        BEP2E bep2e = BEP2E.load(MarketConstruct.BOCT_CONTRACT_ADDRESS, web3j, credentials1, staticGasProvider);
        // 转账
        BigInteger pow = BigInteger.valueOf(10L).pow(18);
        BigInteger multiply = new BigDecimal(amount).multiply(new BigDecimal(pow.toString())).toBigInteger();
        TransactionReceipt send = bep2e.transfer(toAddress, multiply).send();
        String transactionHash = send.getTransactionHash();
        if (StrUtil.isEmpty(transactionHash)) {
            log.info("error_");
            return "error_error";
        }
        return transactionHash;
    } catch (Exception ex) {
        log.info("error_", ex);
        return "error_" + ex.getMessage();
    }
}

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

BNB与BEP20余额查询

java 复制代码
/**
     * <b>功能描述:</b>查询BNB余额<br>
     * <b>修订记录:</b><br>
     */
    public BigDecimal queryBNBBalance(String address) throws Exception {
        DefaultBlockParameter defaultBlockParameter = new DefaultBlockParameterNumber(web3b.ethBlockNumber().send().getBlockNumber());
        EthGetBalance balance = web3b.ethGetBalance(address, defaultBlockParameter).send();
        BigDecimal bigDecimal = new BigDecimal(balance.getBalance());
        BigInteger pow = BigInteger.valueOf(10L).pow(18);
        return bigDecimal.divide(new BigDecimal(pow), 4, RoundingMode.HALF_UP);
    }

    /**
     * <b>功能描述:</b>查询BEP20余额<br>
     * <b>修订记录:</b><br>
     * <li>20240309&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;创建方法</li><br>
     */
    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语言开发,那就不会出现问题

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

java 复制代码
Request<?, EthBlockNumber> request = web3j.ethBlockNumber();
BigInteger blockNumber = request.send().getBlockNumber();
java 复制代码
/**
     * <b>功能描述:</b>创建开始与结束区块, 重放这段时间内的交易,防止遗漏<br>
     * <b>修订记录:</b><br>
     */
    public void startReplayListen_BiAn(Web3j web3j, BigInteger startBlockNum) {
        //创建开始与结束区块, 重放这段时间内的交易,防止遗漏
        DefaultBlockParameter startBlock = new DefaultBlockParameterNumber(startBlockNum);
        web3j.replayPastTransactionsFlowable(startBlock, DefaultBlockParameterName.LATEST).subscribe(tx -> {
            String fromAddress = tx.getFrom();
            String toAddress = tx.getTo();
            // 发现了指定地址上的交易
            BigInteger blockNumber = tx.getBlockNumber();
            KeyValue keyValueNum = keyValueMapper.selectByKey(MarketConstruct.BOCT_STAKE_CONTRACT_ADDRESS);
            if (keyValueNum.getValue().equalsIgnoreCase(toAddress)) {
                String transactionHash = tx.getHash();
                String timestamp = "";
                try {
                    DefaultBlockParameter defaultBlockParameter = DefaultBlockParameter.valueOf(blockNumber);
                    EthBlock ethBlock = web3j.ethGetBlockByNumber(defaultBlockParameter, false).send();
                    timestamp = String.valueOf(ethBlock.getBlock().getTimestamp());
                    Long timestamp1 = Long.parseLong(timestamp) * 1000L;
                    BigDecimal amount = new BigDecimal(new BigInteger(tx.getInput().substring(12), 16)).divide(BigDecimal.valueOf(1000000000000000000.0), 18, BigDecimal.ROUND_HALF_EVEN);
                    checkBlock(transactionHash, tx.getBlockNumber(), fromAddress, amount, timestamp1.toString(), 1L, BigInteger.valueOf(1L), BigInteger.valueOf(1L));
                } catch (IOException e) {
                    log.error("Block timestamp get failure,block number is {}", blockNumber);
                    log.error("Block timestamp get failure,{}", e.getMessage());
                }
            }
        }, error -> log.error("   ### replayPastTransactionsFlowable  error= ", error));
    }

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

java 复制代码
web3j.ethLogFlowable(ethFilter).subscribe(logs -> {
     // ......
     }, error -> log.error("contractExtract subscribe in error", error));

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

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

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

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

相关推荐
2401_85327573几秒前
LinkedList 源码分析
java·面试·职场和发展
TPCloud5 分钟前
快速利用c语言实现线性表(lineList)
c语言·开发语言·线性表·linelist
如意.75911 分钟前
【C++】—— map 与 set 深入浅出:设计原理与应用对比
开发语言·c++
子非吾喵18 分钟前
IDEA在设置里边更改了JDK版本没生效问题解决
java·ide·intellij-idea
陆业聪23 分钟前
基本数据类型:Kotlin、Dart (Flutter)、Java 和 C++ 的比较
java·flutter·kotlin
程序修理员24 分钟前
2个word内容合并
java·word
醇氧24 分钟前
【idea】更换快捷键
java·ide·intellij-idea
容器( ु⁎ᴗ_ᴗ⁎)ु.。oO38 分钟前
java中的定时器
java·开发语言
m0_5474866639 分钟前
一道C语言关于距离的期末题及答案
c语言·开发语言
蹊黎41 分钟前
C++模版初阶
开发语言·c++