因为账户交易这一块内容比较多,分为两部分来讲,承上一篇我们继续关于以太坊账户交易的练习
普通交易
在以太坊链上有两种交易,1是普通交易,2是裸交易,它们有不同的定义, 其中普通交易由以太坊节点进行签名,而裸交易,不要想歪,只是由外部应用进行签名
public String normalTrade(Integer fromIndex, Integer toIndex, Long price) throws IOException {
List<String> accounts = web3j.ethAccounts().send().getAccounts();
String from = accounts.get(fromIndex);
String to = accounts.get(toIndex);
BigInteger tradeValue = BigInteger.valueOf(price);
BigInteger gasPrice = Convert.toWei("20", Convert.Unit.GWEI).toBigInteger();
BigInteger gasLimit = BigInteger.valueOf(60000);
Transaction tx = new Transaction(from, null, gasPrice, gasLimit, to, tradeValue, null);
String txHash = web3j.ethSendTransaction(tx).send().getTransactionHash();
System.out.println("交易哈希:" + txHash);
return txHash;
}
我们包装了一个Transaction 提交交易请求, 一个Transaction 里面包含了如下内容
交易基本信息:发送方、接收方、发送金额
有偿执行交易的报酬信息:gas价格、gas用量上限
交易标识信息:nonce,用来对抗重放攻击
补充数据信息:交易额外携带的数据,也将写入区块永存
在请求后我们会收到一个交易哈希,你可以理解这是一个订单号,我们可以通过这个订单号获取到交易收据, 下面我会放我的代码
public TransactionReceipt getTradeReceipt(String tradeHash) throws IOException, InterruptedException {
Optional<TransactionReceipt> receiptOptional = web3j.ethGetTransactionReceipt(tradeHash)
.send()
.getTransactionReceipt();
while (true) {
if (receiptOptional.isPresent()) {
TransactionReceipt transactionReceipt = receiptOptional.get();
System.out.println("*************************************");
System.out.println("交易收据 - 目标用户地址 :" + transactionReceipt.getTo());
System.out.println("交易收据 - 发送用户地址 :" + transactionReceipt.getFrom());
System.out.println("交易收据 - 交易哈希 :" + transactionReceipt.getTransactionHash());
System.out.println("*************************************");
return transactionReceipt;
} else {
System.out.println("交易收据还未生成");
Thread.sleep(500L);
continue;
}
}
}
下面是我的联系代码案例
public static void main(String[] args) throws Exception {
TradeService service = new TradeService();
System.out.println("节点第4个账户向第6个账户转1eth");
service.getAccountBalance(3, DefaultBlockParameterName.LATEST);
service.getAccountBalance(5, DefaultBlockParameterName.LATEST);
BigDecimal fromWei = service.convert("1", Unit.ETHER, Unit.WEI);
String tradeHash = service.normalTrade(3, 5, fromWei.longValue());
service.getTradeReceipt(tradeHash);
service.getAccountBalance(3, DefaultBlockParameterName.LATEST);
service.getAccountBalance(5, DefaultBlockParameterName.LATEST);
}
通过控制台我们能看到本次交易,我们从账户列表第4位用户给第6位用户转了1个eth
这就是普通交易,接下里我看看web3j如何实现的裸交易
public String rawTx(Integer toIndex, Convert.Unit unit, String num) throws Exception {
List<String> accounts = web3j.ethAccounts().send().getAccounts();
String to = accounts.get(toIndex);
BigInteger gasPrice = BigInteger.valueOf(0);
BigInteger gasLimit = BigInteger.valueOf(0);
BigInteger value = Convert.toWei(num, unit).toBigInteger();
String data = "";
BigInteger nonce = getNonce(credentials.getAddress());
RawTransaction rawTx = RawTransaction.createTransaction(nonce, gasPrice, gasLimit, to, value, data);
byte[] signedMessage = TransactionEncoder.signMessage(rawTx, credentials);
String hexValue = Numeric.toHexString(signedMessage);
System.out.println("本次交易生成hash:" + hexValue);
return hexValue;
}
|