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

上一节我们主要是环境搭建,主要是为了能够快速得去开发,有些地方只是简单的介绍,比如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的监控代码,那用起来是非常舒心。

  • 25
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
要归集BSC链上的USDT,您需要执行以下步骤: 1. 创建BSC钱包地址并获取私钥。 2. 使用Binance Smart Chain的RPC接口连接到BSC网络。 3. 使用USDT的合约地址和ABI,调用USDT合约的transfer方法将USDT从原地址转移到BSC钱包地址。 以下是Java代码示例: ```java import java.math.BigInteger; import java.util.Arrays; import org.web3j.abi.FunctionEncoder; import org.web3j.abi.FunctionReturnDecoder; import org.web3j.abi.TypeReference; import org.web3j.abi.datatypes.Function; import org.web3j.abi.datatypes.Type; import org.web3j.abi.datatypes.generated.Uint256; import org.web3j.crypto.Credentials; import org.web3j.protocol.Web3j; import org.web3j.protocol.core.DefaultBlockParameterName; import org.web3j.protocol.core.methods.request.Transaction; import org.web3j.protocol.core.methods.response.EthGetTransactionCount; import org.web3j.protocol.core.methods.response.EthSendTransaction; import org.web3j.protocol.http.HttpService; import org.web3j.tx.RawTransactionManager; import org.web3j.utils.Convert; import org.web3j.utils.Numeric; public class USDTTransfer { public static void main(String[] args) throws Exception { // BSC钱包地址和私钥 String fromAddress = "0x..."; String privateKey = "..."; Credentials credentials = Credentials.create(privateKey); // BSC节点地址 String bscRpcUrl = "https://bsc-dataseed.binance.org/"; Web3j web3j = Web3j.build(new HttpService(bscRpcUrl)); // USDT合约地址和ABI String usdtContractAddress = "0x..."; String usdtContractAbi = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialSupply\",\"type\":\"uint256\"},{\"name\":\"tokenName\",\"type\":\"string\"},{\"name\":\"decimalUnits\",\"type\":\"uint8\"},{\"name\":\"tokenSymbol\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}]"; // 获取USDT的decimals参数 Function decimalsFunction = new Function("decimals", Arrays.asList(), Arrays.asList(new TypeReference<Uint256>() {})); String encodedDecimals = FunctionEncoder.encode(decimalsFunction); org.web3j.protocol.core.methods.response.EthCall decimalsCall = web3j.ethCall(Transaction.createEthCallTransaction(fromAddress, usdtContractAddress, encodedDecimals), DefaultBlockParameterName.LATEST).send(); String decimalsHex = decimalsCall.getValue(); int decimals = Integer.parseInt(Numeric.cleanHexPrefix(decimalsHex), 16); // 转移USDT的数量 BigInteger amount = Convert.toWei("1", Convert.Unit.ETHER).multiply(BigInteger.TEN.pow(decimals)); // 获取BSC钱包地址的nonce EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST).send(); BigInteger nonce = ethGetTransactionCount.getTransactionCount(); // 构造USDT转移交易数据 Function transferFunction = new Function("transfer", Arrays.asList(credentials.getAddress(), new Uint256(amount)), Arrays.asList(new TypeReference<Type>() {})); String encodedTransfer = FunctionEncoder.encode(transferFunction); // 使用USDT合约地址、nonce、gasPrice、gasLimit和交易数据构造交易 BigInteger gasPrice = Convert.toWei("5", Convert.Unit.GWEI).toBigInteger(); BigInteger gasLimit = BigInteger.valueOf(100000); Transaction transaction = Transaction.createFunctionCallTransaction(fromAddress, nonce, gasPrice, gasLimit, usdtContractAddress, encodedTransfer); // 签名交易并发送到BSC网络 RawTransactionManager rawTransactionManager = new RawTransactionManager(web3j, credentials); EthSendTransaction ethSendTransaction = rawTransactionManager.signAndSend(transaction); String transactionHash = ethSendTransaction.getTransactionHash(); System.out.println("USDT transfer transaction hash: " + transactionHash); } } ``` 请注意,您需要将代码中的钱包地址、私钥、USDT合约地址和ABI替换为您自己的值,并确保您的钱包具有足够的USDT余额以支付交易费用。此外,gasPrice和gasLimit参数应根据当前网络状况进行调整以确保交易能够成功被打包。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员大猩猩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值