
上一节我们主要是环境搭建,主要是为了能够快速得去开发,有些地方只是简单的介绍,比如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余额查询
- /**
- * 功能描述:查询BNB余额
- * 修订记录:
- */
- 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);
- }
-
- /**
- * 功能描述:查询BEP20余额
- * 修订记录:
- *
- 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语言开发,那就不会出现问题
废话不多说,首先还是查找链上最大的交易块。
- Request, EthBlockNumber> request = web3j.ethBlockNumber();
- BigInteger blockNumber = request.send().getBlockNumber();
- /**
- * 功能描述:创建开始与结束区块, 重放这段时间内的交易,防止遗漏
- * 修订记录:
- */
- 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的监控代码,那用起来是非常舒心。