前言
开发前看一下EOS白皮书最好,先了解EOS的架构及相关历程。有助于后续的开发。本地安装个EOS,试一试命令。博主本人是只本地启动钱包wallet,其它api调用其它节点提供的接口。(本篇文章需要本地启动一个钱包服务keosd或者eosio. 最新一篇文章采用离线签名无需启动服务https://blog.csdn.net/liu1765686161/article/details/83308819)
EOS测试网络https://tools.cryptokylin.io
1,首选需要下载eos.java.rpc.wrapper-1.0-SNAPSHOT.jar包
https://download.csdn.net/download/liu1765686161/10633193
或者查看源码 https://github.com/EOSEssentials/eos-java-rpc-wrapper
2,加入项目工程 maven的话有可能需要额外加入依赖
<dependency>
<groupId>com.github-eos</groupId>
<artifactId>eos-java-rpc-wrapper</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>converter-jackson</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.6.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.4</version>
</dependency>
3,开始调用
package com.tn.web.service.coin;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.tn.base.Log;
import com.tn.constant.CoinConstant;
import com.tn.util.BigDecimalUtil;
import com.tn.util.DateUtil;
import com.tn.util.JsonUtil;
import client.EosApiClientFactory;
import client.EosApiRestClient;
import client.domain.common.ActionTrace;
import client.domain.common.transaction.PackedTransaction;
import client.domain.common.transaction.SignedPackedTransaction;
import client.domain.common.transaction.TransactionAction;
import client.domain.common.transaction.TransactionAuthorization;
import client.domain.response.chain.AbiJsonToBin;
import client.domain.response.chain.Block;
import client.domain.response.chain.ChainInfo;
import client.domain.response.chain.transaction.PushedTransaction;
import client.domain.response.history.action.Action;
import client.domain.response.history.action.Actions;
/**
* eos操作
* @author xhl
* @create 2017/10/27
**/
@Service
public class CoinEosService {
private Logger log = Log.get();
private String walletUrl = "";//本地启动的wallet
//正式网络https://api-v2.eosasia.one
private String chainUrl = "https://api-kylin.eosasia.one";//测试网络
//建议用active账户
private String ownerAccount = "";
private String ownerAccountPublicKey = "";
private String walletName = "";//创建的钱包名
private String walletPassword = "";//钱包密码
private static final String EOS_TOKEN = "eosio.token";
private static final String ACTION_TRANSFER = "transfer";
EosApiRestClient eosApiRestClient = null;
@PostConstruct
public void init(){
this.eosApiRestClient = EosApiClientFactory.newInstance(walletUrl,
chainUrl, chainUrl).newRestClient();
}
/**
* 获取账户交易信息
{
"actions": [{
"global_action_seq": 1322,
"account_action_seq": 0,
"block_num": 1184,
"block_time": "2018-07-11T05:41:33.000",
"action_trace": {
"receipt": {
"receiver": "eosasia11111",
"act_digest": "80cde1e12d88867d38f0dcdfec98e5e9906b18d94fe5a30e2c151d74d678c3c9",
"global_sequence": 1322,
"recv_sequence": 1,
"auth_sequence": [
["eosio", 1317]
],
"code_sequence": 1,
"abi_sequence": 1
},
"act": {
"account": "eosio.token",
"name": "transfer",
"authorization": [{
"actor": "eosio",
"permission": "active"
}],
"data": {
"from": "eosio",
"to": "eosasia11111",
"quantity": "100000000.0000 EOS",
"memo": ""
},
"hex_data": "0000000000ea3055104208c1386c30550010a5d4e800000004454f530000000000"
},
"elapsed": 4,
"cpu_usage": 0,
"console": "",
"total_cpu_usage": 0,
"trx_id": "a2288e4a729f157df06a31755ad4c802e51a7838fb2ab06d3dc37309069856ea",
"inline_traces": []
}
}],
"last_irreversible_block": 7224863
}
**/
public boolean getActions(int index){
try {
Actions actions = eosRpcService.getActions(account, index,CoinConstant.EOS_TOTLE);
if (actions != null) {
List<Action> list = actions.getActions();
if (list==null || list.size() == 0) {
return false;
}
//不可变更区块高度
int lastIrreversibleBlock = actions.getLastIrreversibleBlock();
//每次处理一条数据,不需要去重
//list = this.removeDuplicate(list);
for (Action action : list) {
ActionTrace actionTrace = action.getActionTrace();
String account = actionTrace.getAct().getAccount();
if (!EOS_TOKEN.equals(account)) {
log.info("非EOS交易记录:{}",account);
return true;
}
if (action.getBlockNum() > lastIrreversibleBlock) {
log.info("未确认交易:{}",account);
return false;
}
String name = actionTrace.getAct().getName();
if (!ACTION_TRANSFER.equals(name)) {
log.info("非EOS转账交易记录:{}",account);
return true;
}
//{from=eosqxyx11111, to=eosqxyx22222, quantity=10.0000 EOS, memo=test}
log.info("交易详情:{}",actionTrace.getAct().getData().toString());
JSONObject json = JSONObject.parseObject(JsonUtil.getSting(actionTrace.getAct().getData()));
if (!account.equals(json.getString("to"))) {
log.info("非充值记录:{}",actionTrace.getTrxId());
return true;
}
String[] quantity = json.getString("quantity").split(" ");
if (!CoinConstant.COIN_EOS.equals(quantity[1])) {
log.info("非EOS充值记录:{}",json.getString("quantity"));
return true;
}
String memo = json.getString("memo");
if (StringUtils.isEmpty(memo)) {
log.info("记录memo为空");
return true;
}
//判断是否存在用户,并添加充值记录
/*UserEntity user = userService.getUserById(Integer.parseInt(memo));
if (user == null) {
log.info("用户信息不存在:memo:{}",memo);
return true;
}
record.setUserId(user.getUserId());
rechargeParse(record);*/
return true;
}
}
} catch (Exception e1) {
e1.printStackTrace();
log.error("获取用户交易记录失败:{}",e1.getMessage());
}
return false;
}
/**
* 去重
* @param list
* @return
*/
public List<Action> removeDuplicate(List<Action> list) {
for (int i = 0; i < list.size() - 1; i++) {
for (int j = list.size() - 1; j > i; j--) {
if (list.get(j).getActionTrace().getTrxId()
.equals(list.get(i).getActionTrace().getTrxId())) {
list.remove(j);
}
}
}
return list;
}
public String getAddress(){
return ownerAccount;
}
public double getBalance(){
List<String> list = eosApiRestClient.getCurrencyBalance(EOS_TOKEN, ownerAccount, CoinConstant.COIN_EOS);
if (list != null && list.size() > 0) {
return Double.parseDouble(list.get(0).replaceAll(" EOS", ""));
}
return 0.00;
}
public String getJsonToBin(String from, String to, Double amount, String memo){
Map<String, String> args = new HashMap<>(4);
args.put("from", from);
args.put("to", to);
//amount 必须要保留4位小数,不够补0
args.put("quantity", BigDecimalUtil.getFourString(amount)+" EOS");
args.put("memo", memo);
AbiJsonToBin data = eosApiRestClient.abiJsonToBin(EOS_TOKEN, "transfer", args);
if (data != null) {
return data.getBinargs();
}
return null;
}
/**
* 发送交易
* @param fromAccount
* @param toAccount
* @param amount 保留4位小数点
* @param memo
* @return
*/
public String send(String toAccount,double amount,String memo){
String binargs = this.getJsonToBin(ownerAccount, toAccount, amount, memo);
ChainInfo chainInfo = eosApiRestClient.getChainInfo();
Block block = eosApiRestClient.getBlock(chainInfo.getHeadBlockId());
TransactionAuthorization transactionAuthorization = new TransactionAuthorization();
transactionAuthorization.setActor(ownerAccount);
//发送者权限等级 这一步要注意账户和权限要对应上
transactionAuthorization.setPermission("owner");
//transactionAuthorization.setPermission("active");
TransactionAction transactionAction = new TransactionAction();
transactionAction.setAccount(EOS_TOKEN);
transactionAction.setName(ACTION_TRANSFER);
transactionAction.setData(binargs);
transactionAction.setAuthorization(Collections.singletonList(transactionAuthorization));
//设置交易期限
Date date = DateUtil.getStringToDate(block.getTimeStamp(),"yyyy-MM-dd'T'HH:mm:ss");
date = DateUtil.addMin(date, 1);
String exPiration = DateUtil.dateToString(date,"yyyy-MM-dd'T'HH:mm:ss");
PackedTransaction packedTransaction = new PackedTransaction();
packedTransaction.setRefBlockPrefix(block.getRefBlockPrefix().toString());
packedTransaction.setRefBlockNum(block.getBlockNum().toString());
packedTransaction.setExpiration(exPiration);
packedTransaction.setRegion("0");
packedTransaction.setMax_net_usage_words("0");
packedTransaction.setActions(Collections.singletonList(transactionAction));
//打开钱包
eosApiRestClient.openWallet(walletName);
//解锁钱包
eosApiRestClient.unlockWallet(walletName, walletPassword);
SignedPackedTransaction signedPackedTransaction = eosApiRestClient.signTransaction(packedTransaction,
Collections.singletonList(ownerAccountPublicKey), chainInfo.getChainId());
PushedTransaction pushedTransaction= eosApiRestClient.pushTransaction("none", signedPackedTransaction);
if (pushedTransaction != null) {
log.info("EOS转账成功:transactionId:{}",pushedTransaction.getTransactionId());
return pushedTransaction.getTransactionId();
}else {
log.info("EOS转账失败");
}
return null;
}
}
4,定时任务 获取用户交易记录 来确认用户充值 这是我的示例。具体可以根据自己业务来
/**
* EOS处理
*/
private void eosJob(){
//代表的是账户记录处理到第几条,不是区块高度
Integer eosIndex = coinParseService.getBlockHeight("EOS");
log.info("EOS当前处理记录数:{}",eosIndex);
if (coinEosService.getActions(eosIndex)) {
log.info("eos执行完毕");
eosIndex += 1;
//更新处理进度
coinParseService.updateBlockRecord("EOS", reIndex);
}
}
希望能帮到大家,欢迎大家一起分享。