上一节我们具体讲到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如何获取
 
             我要评论
我要评论 
                                             
                                             
                                             
                                             
                                            
发表评论