引言
本文将通过列举一些核心步骤的例子,确保大家看完之后能通过举一反三自行对接。
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>
上DEMO
0,建立波场链连接
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); } }
1,同步区块,
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; }
2,区块解析
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()); }
3,交易状态判断
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; }
4,交易转账如何打包
/** * 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); }
5,如果调用链上指定方法
6,本地钱包如何生成
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即可