本文給大家介紹了 Web3j Java 版本的框架的基本使用,大家可根據本文的內容進行擴展性的練習,對其他 API 的使用進行嘗試。
使用web3j對接以太坊錢包
一、開發准備事項
啟動 Geth
此操作在(二)中已經詳細介紹過了,可以參考其內容進行 Geth 節點啟動,也算是對之前內容的復習,這里不再贅述操作步驟。
開發環境准備
-
- JDK 版本 1.8;
- 開發工具 Intellij idea(本教程使用,也可以使用 Eclipse 等其他 IDE);
- Maven 版本管理(本教程使用,要依賴一些通用的 jar 包,采用 Maven 項目管理模式,也可自行下載依賴 jar 包使用其他方式,建議用 Maven 來操作)。
二、項目實戰
創建 Maven 項目
在 idea 中單擊創建新項目,進入如下頁面,選擇 Maven 項目:
單擊 Next 按鈕,填寫 Maven 項目中的 GroupId 和 ArtifactId:
單擊 Next 按鈕,設置項目名稱和項目路徑:
單擊 Finish 按鈕,這樣就創建好了一個 Maven 項目:
添加依賴
在 pom.xml 文件中新增依賴父元素和 Maven 編譯指定 jdk 版本:
<dependencies> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build>
然后在其中父依賴中添加一下依賴信息:
<dependency> <groupId>org.web3j</groupId> <artifactId>core</artifactId> <version>3.2.0</version> </dependency> <dependency> <groupId>org.web3j</groupId> <artifactId>geth</artifactId> <version>3.2.0</version> </dependency>
上面引入的是一套開源的支持 Web3j 調用以太坊的依賴核心包和 Geth 操作包。Web3j 開源框架提供了一套 Java 版本的操作封裝,讓開發人員可以方便快捷的進行 JSON-RPC 的調用。
公共代碼示例
創建 package:com.secbro.eth,並在 package 下面創建 EthService 類,后面針對 ETH 的操作,都會封裝在 EthService 中做為靜態方法呈現,類內容如下,后面代碼講解不再粘貼類內容,直接展示使用到的方法:
1 package com.secbro.eth; 2 /** 3 * @author zzs 4 */ 5 public class EthService { 6 /** 7 * geth節點可調用的json-rpc接口地址和端口 8 */ 9 private static final String URL = "http://127.0.0.1:8545/"; 10 }
其中需要注意的是上面的靜態變量為 Geth 節點啟動的 JSON-RPC 訪問的地址和端口,如果不是本地啟動可修改 IP 和端口,確保網絡暢通。
初始化 Web3j、Geth 和 Admin 接口
Web3j 框架中提供了多類操作,我們重點介紹 Web3j、Geth 和 Admin 這三個接口,其中 Web3j 和 Admin 都在核心包 core 中,Geth 是在 Geth 包中,這三個接口與我們講的 JSON-RPC 中說到的操作有對應的關系,其中 Web3j 接口封裝了常見的 net、eth、db 等操作,與官方提供的操作一一對應。
Admin 接口對應的是 personal 的一部分操作:
-
- personalListAccounts()
- personalNewAccount(String password)
- personalUnlockAccount( String address, String passphrase, BigInteger duration)
- personalUnlockAccount( String address, String passphrase)
- personalSendTransaction( Transaction transaction, String password)
Geth 接口繼承了 Admin 接口,並新增了以下操作:
-
- personalImportRawKey(String keydata, String password)
- personalLockAccount(String accountId)
- personalSign(String message, String accountId, String password)
- personalEcRecover(String message, String signiture)
下面在 EthService 類中新增如下實例化方法,來獲得這三個接口的實現:
/** * 初始化web3j普通api調用 * * @return web3j */ public static Web3j initWeb3j() { return Web3j.build(getService()); } /** * 初始化personal級別的操作對象 * @return Geth */ public static Geth initGeth(){ return Geth.build(getService()); } /** * 初始化admin級別操作的對象 * @return Admin */ public static Admin initAdmin(){ return Admin.build(getService()); } /** * 通過http連接到geth節點 * @return */ private static HttpService getService(){ return new HttpService(URL); }
代碼上的注釋已經明確說明每個方法的用戶,這里值得一提的是這里采用的是 HttpService 來初始化一個與 geth 通信的 http 連接,在真實生產中可以采用 OkHttpClient 來對此鏈接進行設置超時時間等參數。
通過上面的步驟就完成了三個接口對應的類的實例化操作,后面的內容就可以直接使用它們提供的方法來實現進行相應的業務處理。
三、常用接口使用示例
下面提供一些常用的接口(開發錢包或交易所)的具體實現的代碼和解析。
創建地址
根據輸入的密碼創建地址,對應 personal_newAccount
操作,返回地址 hash:
/** * 輸入密碼創建地址 * * @param password 密碼(建議同一個平台的地址使用一個相同的,且復雜度較高的密碼) * @return 地址hash * @throws IOException */ public static String newAccount(String password) throws IOException { Admin admin = initAdmin(); Request<?, NewAccountIdentifier> request = admin.personalNewAccount(password); NewAccountIdentifier result = request.send(); return result.getAccountId(); }
查詢區塊高度
查詢區塊高度,對應eth_blockNumber
操作,返回當前區塊高度。
/** * 獲得當前區塊高度 * * @return 當前區塊高度 * @throws IOException */ public static BigInteger getCurrentBlockNumber() throws IOException { Web3j web3j = initWeb3j(); Request<?, EthBlockNumber> request = web3j.ethBlockNumber(); return request.send().getBlockNumber(); }
解鎖賬戶
解鎖賬戶,發送交易前需要對賬戶進行解鎖,對應personal_unlockAccount
操作。
/** * 解鎖賬戶,發送交易前需要對賬戶進行解鎖 * * @param address 地址 * @param password 密碼 * @param duration 解鎖有效時間,單位秒 * @return * @throws IOException */ public static Boolean unlockAccount(String address, String password, BigInteger duration) throws IOException { Admin admin = initAdmin(); Request<?, PersonalUnlockAccount> request = admin.personalUnlockAccount(address, password, duration); PersonalUnlockAccount account = request.send(); return account.accountUnlocked(); }
鎖定賬戶
賬戶解鎖,使用完成之后需要鎖定,對應操作personal_lockAccount
。
/** * 賬戶解鎖,使用完成之后需要鎖定 * * @param address * @return * @throws IOException */ public static Boolean lockAccount(String address) throws IOException { Geth geth = initGeth(); Request<?, BooleanResponse> request = geth.personalLockAccount(address); BooleanResponse response = request.send(); return response.success(); }
獲取交易信息
根據 hash 值獲取交易信息,對應操作eth_getTransactionByHash
。
/** * 根據hash值獲取交易 * * @param hash * @return * @throws IOException */ public static EthTransaction getTransactionByHash(String hash) throws IOException { Web3j web3j = initWeb3j(); Request<?, EthTransaction> request = web3j.ethGetTransactionByHash(hash); return request.send(); }
查詢區塊內容
根據區塊編號查詢區塊內容,對應操作eth_getBlockByNumber
。
/** * 獲得ethblock * * @param blockNumber 根據區塊編號 * @return * @throws IOException */ public static EthBlock getBlockEthBlock(Integer blockNumber) throws IOException { Web3j web3j = initWeb3j(); DefaultBlockParameter defaultBlockParameter = new DefaultBlockParameterNumber(blockNumber); Request<?, EthBlock> request = web3j.ethGetBlockByNumber(defaultBlockParameter, true); EthBlock ethBlock = request.send(); return ethBlock; }
發送交易
發送交易並獲得交易 hash 值,對應操作personal_sendTransaction
。
/** * 發送交易並獲得交易hash值 * * @param transaction * @param password * @return * @throws IOException */ public static String sendTransaction(Transaction transaction, String password) throws IOException { Admin admin = initAdmin(); Request<?, EthSendTransaction> request = admin.personalSendTransaction(transaction, password); EthSendTransaction ethSendTransaction = request.send(); return ethSendTransaction.getTransactionHash(); }
獲取指定地址 nonce
指定地址發送交易所需 nonce 獲取,對應操作eth_getTransactionCount
。
/** * 指定地址發送交易所需nonce獲取 * * @param address 待發送交易地址 * @return * @throws IOException */ public static BigInteger getNonce(String address) throws IOException { Web3j web3j = initWeb3j(); Request<?, EthGetTransactionCount> request = web3j.ethGetTransactionCount(address, DefaultBlockParameterName.LATEST); return request.send().getTransactionCount(); }
使用接口注意事項
在使用上面的接口調用時,request.send() 方法是同步返回結果,在某些情況下可能會導致響應比較慢,因此此框架提供了 request.sendAsync() 異步操作,當進行異步操作時只是將操作的執行發送出去,並沒有獲得相應的操作結果,需要通過監聽器獲取結果的通知。
本文中示例的代碼大家在真實生產環境使用時需要進行相應的優化處理,比如網絡優化、初始化鏈接優化、超時時間設定、冷錢包設置、私鑰與 Geth 節點分離、系統安全考慮等。
BIZZAN(幣嚴) 數字貨幣交易所官方網址:
www.bizzan.com