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

news2024/11/17 7:50:41

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

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

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

1. BNB转账

    /**
     *  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;
    }

   

2. BEP20转账

   /**
 *  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余额查询

/**
     * <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语言开发,那就不会出现问题

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

Request<?, EthBlockNumber> request = web3j.ethBlockNumber();
BigInteger blockNumber = request.send().getBlockNumber();
/**
     * <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));
    }

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

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

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1506936.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python判断语句+循环语句

一、Python判断语句 1.1 布尔类型和比较运算符 # 定义变量存储布尔类型的数据 bool_1 True bool_2 False print( f"bool_1变量的内容是&#xff1a;{ bool_1 }&#xff0c;类型为&#xff1a;{ type( bool_1 ) }" ) print( f"bool_2变量的内容是&#xff1a;{…

打卡--MySQL8.0 一(单机部署)

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; MySQL 8.0 简介 MySQL 8.0与5.7的区别主要体现在&#xff1a;1、性能提升&#xff1b;2、新的默认…

ELFK 分布式日志收集系统

ELFK的组成&#xff1a; Elasticsearch: 它是一个分布式的搜索和分析引擎&#xff0c;它可以用来存储和索引大量的日志数据&#xff0c;并提供强大的搜索和分析功能。 &#xff08;java语言开发&#xff0c;&#xff09;logstash: 是一个用于日志收集&#xff0c;处理和传输的…

04hive数仓内外部表复杂数据类型与分区分桶

hive内部表和外部表 默认为内部表&#xff0c;外部表的关键字 &#xff1a;external内部表&#xff1a;对应的文件夹就在默认路径下 /user/hive/warehouse/库名.db/外部表&#xff1a;数据文件在哪里都行&#xff0c;无须移动数据 # students.txt 1,Lucy,girl,23 2,Tom,boy,2…

2023年终总结——跌跌撞撞不断修正

目录 一、回顾1.一月&#xff0c;鼓足信心的开始2.二月&#xff0c;焦躁不安3.三月&#xff0c;路还是要一步一步的走4.四月&#xff0c;平平淡淡的前行5.五月&#xff0c;轰轰烈烈的前行6.六月&#xff0c;看事情更底层透彻了7.七月&#xff0c;设计模式升华月8.八月&#xff…

加速 Webpack 构建:提升效率的秘诀

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

LCR 112. 矩阵中的最长递增路径【leetcode】/dfs+记忆化搜索

LCR 112. 矩阵中的最长递增路径 给定一个 m x n 整数矩阵 matrix &#xff0c;找出其中 最长递增路径 的长度。 对于每个单元格&#xff0c;你可以往上&#xff0c;下&#xff0c;左&#xff0c;右四个方向移动。 不能 在 对角线 方向上移动或移动到 边界外&#xff08;即不允…

【C语言基础】:深入理解指针(终篇)

文章目录 深入理解指针一、函数指针变量4.1 函数指针变量的创建4.2 函数指针变量的使用4.3 typedef关键字 二、函数指针数组三、转移表四、回调函数4.1 什么是回调函数4.2 qsort使用举例4.2.1 使用qsort函数排序整形数据4.2.2 使用qsort排序结构数据4.2.3 qsort函数的模拟实现 …

贝叶斯优化的门控循环神经网络BO-GRU(时序预测)的Matlab实现

贝叶斯优化的门控循环神经网络&#xff08;BO-GRU&#xff09;是一种结合了贝叶斯优化&#xff08;Bayesian Optimization, BO&#xff09;和门控循环单元&#xff08;Gated Recurrent Unit, GRU&#xff09;的模型&#xff0c;旨在进行时序预测。这种模型特别适用于时间序列数…

python文件组织:包(package)、模块(module)、文件(file)

包&#xff1a; 模块所在的包&#xff0c;创建一个包用于组织多个模块&#xff0c;包文件夹中必须创建一个名为’__init__.py’的文件&#xff0c;以将其识别为包&#xff0c;否则只能算作是一个普通的目录。在使用该包时&#xff0c;init自动执行。 包可以多层嵌套&#xff…

C++变参模板

从c11开始&#xff0c;模板可以接受一组数量可变的参数&#xff0c;这种技术称为变参模板。 变参模板 下面一个例子&#xff0c;通过变参模板打印一组数量和类型都不确定的参数。 #include <iostream> #include <string>void print(void) {std::cout<<&quo…

数据结构小记【Python/C++版】——散列表篇

一&#xff0c;基础概念 散列表&#xff0c;英文名是hash table&#xff0c;又叫哈希表。 散列表通常使用顺序表来存储集合元素&#xff0c;集合元素以一种很分散的分布方式存储在顺序表中。 散列表是一个键值对(key-item)的组合&#xff0c;由键(key)和元素值(item)组成。键…

探索云原生数据库技术:构建高效可靠的云原生应用

数据库是应用开发中非常重要的组成部分&#xff0c;可以进行数据的存储和管理。随着企业业务向数字化、在线化和智能化的演进过程中&#xff0c;面对指数级递增的海量存储需求和挑战以及业务带来的更多的热点事件、突发流量的挑战&#xff0c;传统的数据库已经很难满足和响应快…

OpenCV filter2D函数详解

OpenCV filter2D函数简介 OpenCV filter2D将图像与内核进行卷积&#xff0c;将任意线性滤波器应用于图像。支持就地操作。当孔径部分位于图像之外时&#xff0c;该函数根据指定的边界模式插值异常像素值。 该函数实际上计算相关性&#xff0c;而不是卷积&#xff1a; filter…

【Spark编程基础】实验一Spark编程初级实践(附源代码)

文章目录 一、实验目的二、实验平台三、实验内容和要求1. 计算级数2. 模拟图形绘制3.统计学生成绩 一、实验目的 1.掌握 Scala 语言的基本语法、数据结构和控制结构&#xff1b; 2.掌握面向对象编程的基础知识&#xff0c;能够编写自定义类和特质&#xff1b; 3.掌握函数式编程…

vue3速查笔记

文章目录 一、创建Vue3.0工程1.使用 vue-cli 创建2.使用 vite 创建 二、常用 Composition API1.拉开序幕的setup2.ref函数3.reactive函数4.Vue3.0中的响应式原理vue2.x的响应式Vue3.0的响应式 5.reactive对比ref6.setup的两个注意点7.计算属性与监视1.computed函数2.watch函数3…

Windows电脑安装Linux(Ubuntu 22.04)系统(图文并茂)

Windows电脑安装Ubuntu 22.04系统&#xff0c;其它版本的Ubuntu安装方法相同 Ubuntu 16.04、Ubuntu 18.04安装方法相同&#xff0c;制作U盘启动项的镜像文件下载你需要的版本即可&#xff01; Ubuntu的中文官网网址&#xff1a;https://cn.ubuntu.com/&#xff0c;聪明的你一定…

【线程】封装 | 安全 | 互斥

线程封装&#xff08;面向对象&#xff09; 1.组件式的封装出一个线程类&#xff08;像C11线程库那样去管理线程&#xff09; 我们并不想暴露出线程创建&#xff0c;终止&#xff0c;等待&#xff0c;分离&#xff0c;获取线程id等POSIX线程库的接口&#xff0c;我们也想像C1…

IDEA管理Git + Gitee 常用操作

文章目录 IDEA管理Git Gitee 常用操作1.Gitee创建代码仓库1.创建仓库1.点击新建仓库2.完成仓库信息填写3.创建成功4.管理菜单可以修改这个项目的设置 2.设置SSH公钥免密登录基本介绍1.找到.ssh目录2.执行指令 ssh-keygen3.将公钥信息添加到码云账户1.点击设置2.ssh公钥3.复制.…

React-配置别名@

1.概念 说明&#xff1a;路径解析配置(webpack),把/解析为src/&#xff1b;路径联想配置(VsCode),VsCode在输入/时&#xff0c;自动联想出来对应的src/下的子级目录。CRA本身把webpacki配置包装到了黑盒里无法直接修改&#xff0c;需要借助一个插件-craco。 2.实现步骤 2.1安…