本文将通过列举一些核心步骤的例子,确保大家看完之后能通过举一反三自行对接。 0,建立波场链连接 1,同步区块, 2,区块解析 3,交易状态判断 4,交易转账如何打包 5,如何调用链上指定方法 6,本地钱包如何生成
首先引入tron核心pom依赖,由于科学上网的原因,我是直接从官网下的包,jar包我放在文章最后面 依赖配置如下
<dependency>
<groupId>com.github.tronprotocol</groupId>
<artifactId>java-tron</artifactId>
<version>Odyssey-v3.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/java-tron-Odyssey-v3.2.jar</systemPath>
</dependency>
资源下载:java-tron-Odyssey-v3.2.jar
import com.alibaba.fastjson.JSONObject;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class TronRpcUtil {
private static final Logger log = LoggerFactory.getLogger(TronRpcUtil.class);
private static final RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
public TronRpcUtil() {
dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
/**
* get请求,返回JSONObject
* @param url
* @return
*/
public ResponseEntity<JSONObject> get(String url) {
ResponseEntity<JSONObject> responseEntity = null;
try {
responseEntity = restTemplate.getForEntity(url, JSONObject.class);
} catch (Exception e) {
e.printStackTrace();
}
return responseEntity;
}
/**
* get请求,返回String
* @param url
* @return
*/
public ResponseEntity<String> getResponseString(String url) {
ResponseEntity<String> responseEntity = null;
try {
responseEntity = restTemplate.getForEntity(url, String.class);
} catch (Exception e) {
e.printStackTrace();
}
return responseEntity;
}
/**
* post请求
* @param url
* @param parameterJson
* @return
*/
public ResponseEntity<JSONObject> post(String url, String parameterJson) {
ResponseEntity<JSONObject> responseEntity = null;
try {
responseEntity = restTemplate.postForEntity(url, parameterJson, JSONObject.class);
} catch (Exception e) {
e.printStackTrace();
}
return responseEntity;
}
/**
* post请求
*
* @param url 测试网:https://api.shasta.trongrid.io/
* @param parameterJson
* @return
*/
public ResponseEntity<String> postResponseString(String url, String parameterJson) {
ResponseEntity<String> responseEntity = null;
try {
responseEntity = restTemplate.postForEntity(url, parameterJson, String.class);
} catch (Exception e) {
log.error("广播请求异常",e);
}
return responseEntity;
}
/**
* 配置HttpClient超时时间
* @return
*/
private static ClientHttpRequestFactory getClientHttpRequestFactory() {
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(6000)
.setConnectTimeout(10000).build();
CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
return new HttpComponentsClientHttpRequestFactory(client);
}
}
public JSONObject getNewBlock() {
String url = tronConfig.getInstance().getUrl() + WALLET + GET_NOW_BLOCK;
ResponseEntity<String> responseEntity = tronRpc.getResponseString(url);
if (responseEntity == null) return null;
return JSONObject.parseObject(responseEntity.getBody());
}
public BigInteger getNewBlocknNumber() {
JSONObject jsonObject = getNewBlock();
if(jsonObject != null){
return jsonObject.getJSONObject("block_header").getJSONObject("raw_data").getBigInteger("number");
}
return null;
}
JSONObject jsonObject = tronWalletUtilService.getBlockByNum(blockNumber);
public JSONObject getBlockByNum(BigInteger num) {
String url = tronConfig.getInstance().getUrl() + WALLET + GET_BLOCK_BY_NUM;
Map<String, BigInteger> map = new HashMap<>();
map.put("num", num);
String param = JsonUtils.objectToJson(map);
return getPost(url, param);
}
private JSONObject getPost(String url, String param) {
ResponseEntity<String> stringResponseEntity = tronRpc.postResponseString(url, param);
if (stringResponseEntity == null) return null;
return JSONObject.parseObject(stringResponseEntity.getBody());
}
public JSONObject getTransaction(String hashId) {
String url = tronConfig.getInstance().getUrl() + WALLET + GET_TRANSACTION;
Map<String, String> map = new HashMap<>();
map.put("value", hashId);
String param = JsonUtils.objectToJson(map);
ResponseEntity<String> stringResponseEntity = tronRpc.postResponseString(url, param);
try {
if (stringResponseEntity != null) return JSONObject.parseObject(stringResponseEntity.getBody());
} catch (Exception e) {
return null;
}
return null;
}
/**
* trx
* @param owner
* @param privateKey
* @param to
* @param amount
* @return
*/
@Override
public String handleTransactionTRX(String owner, String privateKey, String to, BigInteger amount) {
log.info("Tron 转账入参:{}, {}, {}, {}",owner,privateKey,to,amount);
// 创建交易
String url = tronConfig.getInstance().getUrl() + WALLET + CREATE_TRANSACTION;
Map<String, Object> map = new HashMap<>();
map.put("to_address", to);
map.put("owner_address", owner);
map.put("amount", amount);
String param = JsonUtils.objectToJson(map);
ResponseEntity<String> stringResponseEntity = tronRpc.postResponseString(url, param);
log.info("创建交易:{}",stringResponseEntity);
return signAndBroadcast(stringResponseEntity.getBody(), privateKey);
}
/**
* 交易TRC20
*
* @param owner
* @param privateKey
* @param to
* @param amount
* @param tokenHexAddr
* @return
*/
@Override
public String handleTransactionTRC20(String owner, String privateKey, String to, BigInteger amount, String tokenHexAddr) {
log.debug("trc20转账入参:owner:{},privateKey:{},to:{},amount:{},tokenHexAddr:{}",owner,privateKey,to,amount,tokenHexAddr);
String url = tronConfig.getInstance().getUrl() + WALLET + TRIGGER_SMART_CONTRACT;
// 格式化参数
log.info("owner:{}, parameter:{}",owner,to);
String parameter = formatParameter(to) + formatParameter(amount.toString(16));
Map<String, Object> map = new HashMap<>();
map.put("contract_address", tokenHexAddr);
map.put("function_selector", "transfer(address,uint256)");
//最高gas 不超过30trx
map.put("fee_limit", 30000000);
map.put("parameter", parameter);
map.put("owner_address", owner);
log.info(JsonUtils.objectToJson(map));
ResponseEntity<String> stringResponseEntity = tronRpc.postResponseString(url, JsonUtils.objectToJson(map));
JSONObject data = JSONObject.parseObject(stringResponseEntity.getBody());
JSONObject transaction = data.getJSONObject("transaction");
transaction.remove("visible");
transaction.remove("raw_data_hex");
return signAndBroadcast(JsonUtils.objectToJson(transaction), privateKey);
}
import org.spongycastle.math.ec.ECPoint;
import org.tron.common.crypto.ECKey;
import org.tron.common.crypto.Hash;
import org.tron.common.crypto.Sha256Sm3Hash;
import org.tron.common.utils.Base58;
import org.tron.common.utils.ByteArray;
import org.tron.common.utils.Utils;
import org.tron.core.exception.CipherException;
import org.tron.walletserver.WalletApi;
import java.math.BigInteger;
import static java.util.Arrays.copyOfRange;
public class ECCreateKey {
private static byte[] private2PublicDemo(byte[] privateKey) {
BigInteger privKey = new BigInteger(1, privateKey);
ECPoint point = ECKey.CURVE.getG().multiply(privKey);
return point.getEncoded(false);
}
private static byte[] public2AddressDemo(byte[] publicKey) {
byte[] hash = Hash.sha3(copyOfRange(publicKey, 1, publicKey.length));
//System.out.println("sha3 = " + ByteArray.toHexString(hash));
byte[] address = copyOfRange(hash, 11, hash.length);
address[0] = WalletApi.getAddressPreFixByte();
return address;
}
public static String address2Encode58CheckDemo(byte[] input) {
byte[] hash0 = Sha256Sm3Hash.hash(input);
byte[] hash1 = Sha256Sm3Hash.hash(hash0);
byte[] inputCheck = new byte[input.length + 4];
System.arraycopy(input, 0, inputCheck, 0, input.length);
System.arraycopy(hash1, 0, inputCheck, input.length, 4);
return Base58.encode(inputCheck);
}
public static String private2Address() throws CipherException {
ECKey eCkey = new ECKey(Utils.getRandom()); //
String privateKey=ByteArray.toHexString(eCkey.getPrivKeyBytes());
System.out.println("Private Key: " + privateKey);
byte[] publicKey0 = eCkey.getPubKey();
byte[] publicKey1 = private2PublicDemo(eCkey.getPrivKeyBytes());
if (!ECCreateKey.equals(publicKey0, publicKey1)) {
throw new CipherException("publickey error");
}
String publicKey=ByteArray.toHexString(publicKey0);
System.out.println("Public Key: " + publicKey);
byte[] address0 = eCkey.getAddress();
byte[] address1 = public2AddressDemo(publicKey0);
if (!ECCreateKey.equals(address0, address1)) {
throw new CipherException("address error");
}
String address=ByteArray.toHexString(address0);
System.out.println("Address: " +address);
String base58checkAddress0 = WalletApi.encode58Check(address0);
String base58checkAddress1 = address2Encode58CheckDemo(address0);
if (!base58checkAddress0.equals(base58checkAddress1)) {
throw new CipherException("base58checkAddress error");
}
String dataList=privateKey+ TronConstant.DELIMIT+base58checkAddress1+TronConstant.DELIMIT+address;
return dataList;
}
public static boolean equals(byte[] a, byte[] a2) {
if (a==a2)
return true;
if (a==null || a2==null){
System.out.println("都为null");
return false;
}
int length = a.length;
if (a2.length != length){
System.out.println("长度不等");
return false;
}
for (int i=0; i<length; i++)
if (a[i] != a2[i]){
System.out.println("值不等");
return false;
}
return true;
}
public static void main(String[] args) throws CipherException {
System.out.println("================================================================\r\n");
String dataList = private2Address();
System.out.println("base58Address: " + dataList);
String[] split = dataList.split(TronConstant.DELIMIT);
String privateKey = split[0];
String address = split[1];
String hexAddress =split[2];
System.out.println("privateKey:"+privateKey+" address:"+address+" hexAddress:"+hexAddress);
}
}
到这里基本上一套完整的流程已经对接完了,剩下的稍微琢磨一下就全明白了,至于详细的波场链字段说明,参考api即可