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