Java实现Tron(波场)区块链的开发实践(二)交易监控与转账

上一节我们具体讲到Java实现Tron波场链的开发部署:通过trident源码编译组件,使用RPC的方式链接Tron波场链,并进行了代码实现,还有如何创建离线钱包。

这一节我们通过部署好的项目环境,具体如何使用代码来实现波场链的交易监控和交易转账.

1. 所有的开端就是获取链的接通(ApiWrapper)


private ApiWrapper getApiWrapper(String hexPrivateKey) {
        //配置是否是测试链还是正式链
        if (tronServiceConfig.getTronDomainOnline()) {
            // 正式环境需要到Tron申请一个apiKey进行使用
            // APIKEY获取往后会讲如何获取
            return ApiWrapper.ofMainnet(hexPrivateKey, tronServiceConfig.getApiKey());
        } else {
            // 测试环境不需要apikey
            return new ApiWrapper("grpc.nile.trongrid.io:50051", "grpc.nile.trongrid.io:50061", hexPrivateKey);
        }
    }

2. 查看Trc20(如USDT)余额


    /**
     * TRC20余额
     * @param address 我的钱包地址
     * @return 余额
     */
    public BigDecimal getTrc20Balance(String address) {
        ApiWrapper client = getApiWrapper(tronServiceConfig.getHexPrivateKey());
        // Trc20合约地址
        Contract contract = client.getContract(tronServiceConfig.getTrc20Address());
        Trc20Contract token = new Trc20Contract(contract, address, client);
        BigInteger balanceOf = token.balanceOf(address);
        BigDecimal divisor = new BigDecimal(tronServiceConfig.getTrc20Decimals());
        BigDecimal divide = new BigDecimal(balanceOf).divide(divisor, 4, RoundingMode.HALF_UP);
        client.close();
        return divide;
    }

3. 查看Trx余额

 /**
     * TRx余额
     * @param address
     * @return
     */
    @Override
    public BigDecimal getTRxBalance(String address) {
        ApiWrapper wrapper = getApiWrapper(tronServiceConfig.getHexPrivateKey());
        Long balance = wrapper.getAccountBalance(address);
        BigDecimal divisor = new BigDecimal(tronServiceConfig.getTrc20Decimals());
        BigDecimal divide = new BigDecimal(balance).divide(divisor, 4, RoundingMode.HALF_UP);
        wrapper.close();
        return divide;
    }

4. Trc20转账实现

/**
     * TRC20 转账
     * @param fromAddress
     * @param toAddress
     * @param amount
     * @return
     */
    @Override
    public String transTrc20(String fromAddress, String toAddress, String amount) {
        try {
            ApiWrapper client = getApiWrapper(tronServiceConfig.getHexPrivateKey());
            // 获取合约地址信息
            Contract contract = client.getContract(tronServiceConfig.getTrc20Address());
            Trc20Contract token = new Trc20Contract(contract, fromAddress, client);
            String transfer;
            // 获取转账账户的TRX余额
            BigInteger trc20Value = token.balanceOf(fromAddress);
            // 获取想要转账的数额
            BigInteger sunAmountValue = Convert.toSun(amount, Convert.Unit.TRX).toBigInteger();
            // 进行比较
            if (trc20Value.compareTo(sunAmountValue) >= 0) {
                log.info("开始转账.........");
                // 设置最大矿工费用
                long feeLimit = Convert.toSun("100", Convert.Unit.TRX).longValue();
                //转账
                transfer = token.transfer(toAddress, sunAmountValue.longValue(), 0, "转账", feeLimit);
            } else {
                return "error_error";
            }
            if (StrUtil.isEmpty(transfer)) {
                return "error_error";
            }
            log.info("交易ID:{}", transfer);
            client.close();
            return transfer;
        } catch (Exception ex) {
            String message = ex.getMessage();
            return "error_" + message;
        }
    }

5. TRX转账

/**
     * TRX转账
     * @param fromAddress 输入地址
     * @param toAddress 转账地址
     * @param amount 金额
     * @return
     */
    @Override
    public String transferTRX(String fromAddress, String toAddress, int amount) {
        ApiWrapper wrapper = getApiWrapper(tronServiceConfig.getHexPrivateKey());
        try {
            BigDecimal divisor = new BigDecimal(tronServiceConfig.getTrc20Decimals());
            Long rechangeAmount = new BigDecimal(String.valueOf(amount)).multiply(divisor).longValue();
            // 创建交易
            Response.TransactionExtention transaction = wrapper.transfer(fromAddress, toAddress, rechangeAmount);
            log.info("transaction:{}", transaction);
            log.info("transaction.Txid:{}", transaction.getTxid());
            // 签名交易
            Chain.Transaction signTransaction = wrapper.signTransaction(transaction);
            log.info("signTransaction:{}", signTransaction);
            // 计算交易所需要的宽带
            long byteSize = wrapper.estimateBandwidth(signTransaction);
            log.info("byteSize:{}", byteSize);
            // 广播交易
            String hashTx = wrapper.broadcastTransaction(signTransaction);
            log.info("hashTRX:{}", hashTx);
            return hashTx;
        } catch (Exception e) {
            log.error("TransactionService#transfer error: {}", e.getMessage());
        }
        wrapper.close();
        return null;
    }

6. 交易监控

之所以交易监控放在最后,是因为本人在交易监控上做了很多很多的尝试,最后找到了JAVA实现自认为是最好的实例。

-- 交易监控说白话就是在链接波场链的同时,监控波场链上的交易信息,再把这些交易信息检索和反编码,获取到真实TRX和TRC20所需交易。

-- 不管怎么做,首先的想法就是要获取当前交易到的区块,或者自己想要从哪个区块高度进行开始交易监控

-- 不变的是,监控一定以及肯定的是将监控到最后一个块的交易,也就是链上最后一笔交易

// 获取目前最高交易块
Long number = wrapper.getNowBlock().getBlockHeader().getRawData().getNumber();

-- 为了避免程序抖动或者检索交易错误,我采取交易块区间式的检索 -- 

    也就是一次监控,监控的事一个块区间而不是一个最新块。

// BLOCKS_20 后退区间高度数
Response.BlockListExtention blockByLimitNext = wrapper.getBlockByLimitNext(endNum - BLOCKS_20, endNum);
// 区间块列表
List<Response.BlockExtention> blockList = blockByLimitNext.getBlockList();
for (Response.BlockExtention blockExtention : blockList) {
    Long trc20_target_block_number = blockExtention.getBlockHeader().getRawData().getNumber();
    RedissonUtils.setBucket("EXCHANGE_LISTENER:TRC20", DateUtil.formatDateTime(new Date()) + " 区块高度:" + current_sync_block_number + " 扫描高度:" + trc20_target_block_number);
    // 处理块信息
    switchDataTransaction(blockExtention);
}
/**
     * 检索块信息,获取交易信息
     * @param blockExtention
     * @throws Throwable
     */
    public void switchDataTransaction(Response.BlockExtention blockExtention) throws Throwable {
        List<Response.TransactionExtention> transactionsList = blockExtention.getTransactionsList();
        for (Response.TransactionExtention transactionExtention : transactionsList) {
            List<Chain.Transaction.Contract> contractList = transactionExtention.getTransaction().getRawData().getContractList();
            for (Chain.Transaction.Contract contract : contractList) {
                Class a = Class.forName("org.tron.trident.proto.Contract$" + contract.getType());
                Message unpack = contract.getParameter().unpack(a);
                // TriggerSmartContract是合约, 按照不同的交易类型检索
                if (unpack instanceof Contract.TriggerSmartContract) {
                    // 合约地址
                    Contract.TriggerSmartContract contractStr = (Contract.TriggerSmartContract) unpack;
                    ByteString contractAddress = contractStr.getContractAddress();
                    String hex = ApiWrapper.toHex(contractAddress);
                    String contractAddressStr = TronUtils.toViewAddress(hex);
                    // 判断是否是自己需要监控的合约地址
                    if (tronServiceConfig.getTrc20Address().equalsIgnoreCase(contractAddressStr)) {
                        ByteString ownerAddress = contractStr.getOwnerAddress();
                        String hex2 = ApiWrapper.toHex(ownerAddress);
                        String fromAddress = TronUtils.toViewAddress(hex2);
                        ByteString data = contractStr.getData();
                        String hex1 = ApiWrapper.toHex(data);
                        // 交易类型是转账
                        String transferFunction = Hex.toHexString(new Keccak.Digest256().digest("transfer(address,uint256)".getBytes())).substring(0, 8);
                        String funcId = hex1.substring(0, 8);
                        if (!transferFunction.equals(funcId)) {
                            continue;
                        }
                        String toAddress = hex1.substring(32, 72);
                        String amount = hex1.substring(72, 136);
                        try {
                            Address address = (Address) TypeDecoder.instantiateType("address", toAddress);
                            // 地址
                            NumericType amountType = (NumericType) TypeDecoder.instantiateType("uint256", amount);
                            // 金额
                            BigDecimal trc20Decimals = new BigDecimal(tronServiceConfig.getTrc20Decimals());
                            BigDecimal amountee = new BigDecimal(amountType.getValue()).divide(trc20Decimals, 6, RoundingMode.FLOOR);

                            byte[] byteArray = transactionExtention.getTransaction().getRawData().toByteArray();
                            byte[] bytes = Hash.sha256(byteArray);
                            String txId = Hex.toHexString(bytes);
                            // 后续处理
                            // trc20.exchangeService.triggerSmartContract(address.getValue(), amountee, txId);
                        } catch (Exception e) {
                            log.error("TRON监控报错", e);
                            continue;
                        }
                    }
                }
            }
        }
    }

监控通知定时循环任务发起,注意循环任务的发起

下一节:Tron波场链水龙头、web3、apikey如何获取

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
“智慧农业”是中国人端稳饭碗的关键。

)">
< <上一篇
下一篇>>