使用web3j構建以太坊錢包

創(chuàng)建一個以太坊錢包有多種方式,一般情況下可以通過geth、EtherumWallet等客戶端。對于前端,可以使用插件MetaMask進行創(chuàng)建。這幾種方式技術實現(xiàn)雖然不同,但底層原理是一致的。本文主要介紹如何通過web3j架構創(chuàng)建一個以太坊的冷錢包,從而實現(xiàn)將這一過程部署在服務端或者android端。

文中涉及到的技術棧有:

Web3j :輕量級java庫,用于連接以太坊客戶端或節(jié)點

Infura :以太坊基礎設施,用于訪問以太坊主網(wǎng)絡或測試網(wǎng)絡

Java:編程語言

1.Web3j的安裝

無論是java工程還是android工程,web3j都提供了maven和grade 兩種依賴方式:

  1. java工程
  • manen依賴
<dependency>
  <groupId>org.web3j</groupId>
  <artifactId>core</artifactId>
  <version>3.3.1</version>
</dependency>
  • gradle依賴
compile ('org.web3j:core:3.3.1')
  1. android工程
  • maven依賴
<dependency>
  <groupId>org.web3j</groupId>
  <artifactId>core</artifactId>
  <version>3.3.1-android</version>
</dependency>
  • gradle依賴
compile ('org.web3j:core:3.3.1-android')

值得注意的是,目前的web3j對于高版本JDK存在不兼容的問題,如果出現(xiàn)如下類似的問題,直接更換JDK為version 8即可。

<u>Could not determine Java version using executable /Library/Java/JavaVirtualMachines/jdk-10.jdk/Contents/Home/bin/java.</u>

2.關于Infura

以太坊的客戶端實現(xiàn)有多種,但很多都需要在本地同步所有的節(jié)點數(shù)據(jù)而占用大量硬盤存儲空間,并且需要消耗同步的時間。Infura就是提供一種中心化的服務,通過web3.js或者web3j使前端或服務端能便捷的訪問以太坊所有節(jié)點??梢岳斫鉃橐环N以太坊客戶端的云端版本。使用過程需要注冊,一個專屬的訪問token。本文中使用的客戶端都是Infura提供的Rinkeby測試網(wǎng)絡。

3.新建錢包文件keyfile

在以太坊中,錢包(wallet)和賬戶(account)是兩個不同的概念。賬戶是以太坊的核心,由一對秘鑰組成-公鑰和私鑰。賬戶可以分為兩種,外部賬戶和合約賬戶。而錢包是指保存 地址、公鑰、私鑰的文件或其他機構,每個錢包文件至少包含一個賬戶。創(chuàng)建錢包的同時也是創(chuàng)建一個以太坊賬戶的過程不同的客戶端創(chuàng)建錢包的方式不一致但原理相同,有關錢包是具體是如何生成的可以查看另外這篇文章。

  1. 新建一個java工程,初始化gradle或者maven
  2. 依賴web3j
  3. 新建Application.java文件,設置程序入口main函數(shù)
  4. 調(diào)用錢包工具類生成錢包文件
/*************創(chuàng)建一個錢包文件**************/
private void creatAccount() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException, CipherException, IOException {
    String walletFileName0="";//文件名
    String walletFilePath0="/Users/yepeng/MyGitHub/z_wallet_temp";
    //錢包文件保持路徑,請?zhí)鎿Q位自己的某文件夾路徑

    walletFileName0 = WalletUtils.generateNewWalletFile("123456", new File(walletFilePath0), false);
    //WalletUtils.generateFullNewWalletFile("password1",new File(walleFilePath1));
    //WalletUtils.generateLightNewWalletFile("password2",new File(walleFilePath2));
    log.info("walletName: "+walletFileName0);
}

錢包構建的過程中需要輸入的三個參數(shù),分別設置錢包的密碼、保存路徑、以及是否輕量級錢包。

執(zhí)行創(chuàng)建函數(shù)后,會自動在指定路徑生成一個json 文件,即錢包keyfiles。


屏幕快照 2018-04-10 上午11.04.24.png

錢包文件結構:


屏幕快照 2018-04-10 上午11.14.03.png
  • cipher:加密算法,AES算法,用于加密以太坊私鑰
  • cipherparams:cipher算法需要的參數(shù),參數(shù)iv,是aes-128-ctr加密算法需要的初始化向量
  • ciphertext:加密后的密文,aes-128-ctr函數(shù)的加密輸入密文;
  • kdf:秘鑰生成函數(shù),用于使用密碼加密keystore文件
  • kdfparams:kdf算法所需要的參數(shù)
  • mac:驗證密碼的編碼

生成錢包的逆向過程 為加載錢包。

4.加載錢包文件

加載錢包的過程需要提供錢包文件和密碼

/********加載錢包文件**********/
private void loadWallet() throws IOException, CipherException {
    String walleFilePath="/Users/yepeng/MyGitHub/z_wallet_temp/UTC--2018-04-10T02-51-24.815000000Z--12571f46ec3f81f7ebe79112be5883194d683787.json";
    String passWord="123456";
    credentials = WalletUtils.loadCredentials(passWord, walleFilePath);
    String address = credentials.getAddress();
    BigInteger publicKey = credentials.getEcKeyPair().getPublicKey();
    BigInteger privateKey = credentials.getEcKeyPair().getPrivateKey();

    log.info("address="+address);
    log.info("public key="+publicKey);
    log.info("private key="+privateKey);

}

函數(shù)運行的結果:


屏幕快照 2018-04-10 上午11.10.19-3417487.png

通過工具類 WalletUtols的函數(shù) loadCredentials(),會返回一個對象Credentials,這個對象即包含了錢包文件的所有信息,包括地址、秘鑰對。

至此,錢包的創(chuàng)建和加載已經(jīng)完成,但這一過程全部發(fā)生在本地,并未同步到以太坊區(qū)塊鏈。查詢地址余額前,需要連接以太坊結點。

5.構建Web3j實體,連接以太坊結點

web3j是連接java端與以太坊的橋梁,廣播交易,查詢賬戶都需要通過web3j實體。web3j支持通過http進行構建,而且兼容了infura。在本文中,使用的是infura的測試網(wǎng)絡Rinkeby。

/*******連接以太坊客戶端**************/
private void conectETHclient() throws IOException {
    //連接方式1:使用infura 提供的客戶端
    web3j = Web3j.build(new HttpService("https://rinkeby.infura.io/zmd7VgRt9go0x6qlJ2Mk"));// TODO: 2018/4/10 token更改為自己的
    //連接方式2:使用本地客戶端
    //web3j = Web3j.build(new HttpService("127.0.0.1:7545"));
    //測試是否連接成功
    String web3ClientVersion = web3j.web3ClientVersion().send().getWeb3ClientVersion();
    log.info("version=" + web3ClientVersion);
}

web3j實體構建完成后,可以打印出版本號以測試是否連接成功。如果成功,就可以做其他的事情了。值得注意的是,web3j采用的是RxJava的設計,所以許多函數(shù)的返回值是 Request<?,?>,這個對象有兩種執(zhí)行方式,異步和同步,即send()和sendAsyn()。

6.查詢賬戶余額

查詢賬戶的余額的方式:

/***********查詢指定地址的余額***********/
private void getBlanceOf() throws IOException {
    if (web3j == null) return;
    String address = "0x41F1dcbC0794BAD5e94c6881E7c04e4F98908a87";//等待查詢余額的地址
    //第二個參數(shù):區(qū)塊的參數(shù),建議選最新區(qū)塊
    EthGetBalance balance = web3j.ethGetBalance(address, DefaultBlockParameter.valueOf("latest")).send();
    //格式轉(zhuǎn)化 wei-ether
    String blanceETH = Convert.fromWei(balance.getBalance().toString(), Convert.Unit.ETHER).toPlainString().concat(" ether");
    log.info(blanceETH);
}

其中核心方法 web3j.ethGetBalance(address, defaultBlockParameter) 中的第二個參數(shù)比較特殊,指默認的區(qū)塊參數(shù)。當請求余額的方法作用與以太坊的區(qū)塊網(wǎng)絡時,這個參數(shù)決定了查詢區(qū)塊的高度。

  • HEX String - 一個整數(shù)塊號
  • String "earliest" 為最早/起源塊
  • String "latest" - 為最新的采礦塊
  • String "pending" - 待處理狀態(tài)/交易

一般情況下,選擇“l(fā)atest”即可。

以太坊中,如果沒有特殊標示,數(shù)字的單位都是小數(shù)點后18位,因此查詢賬戶余額有必要將wei轉(zhuǎn)化成ether。

6.使用錢包進行轉(zhuǎn)賬

作為一個錢包,除了保存賬戶資產(chǎn)外,最重要的就是轉(zhuǎn)賬或交易了,利用web3j可以便捷的實現(xiàn)eth的轉(zhuǎn)移。

/    /****************交易*****************/
    private void transto() throws Exception {
        if (web3j == null) return;
        if (credentials == null) return;
        //開始發(fā)送0.01 =eth到指定地址
        String address_to = "0x41F1dcbC0794BAD5e94c6881E7c04e4F98908a87";
        TransactionReceipt send = Transfer.sendFunds(web3j, credentials, address_to, BigDecimal.ONE, Convert.Unit.FINNEY).send();

        log.info("Transaction complete:");
        log.info("trans hash=" + send.getTransactionHash());
        log.info("from :" + send.getFrom());
        log.info("to:" + send.getTo());
        log.info("gas used=" + send.getGasUsed());
        log.info("status: " + send.getStatus());
    }

核心方法需要提供4個參數(shù):

  • web3j實體
  • Credentials 源賬戶
  • address 轉(zhuǎn)出地址
  • value 數(shù)量
  • uint 單位

等待片刻后,會返回轉(zhuǎn)賬結果

屏幕快照 2018-04-11 上午11.32.12.png

可以看到交易hash、轉(zhuǎn)入轉(zhuǎn)出地址、gas消耗等信息。同時可以在etherscan-rinkeby上進行查看本次交易詳情

7.總結

上面的代碼已經(jīng)完成了一個以太坊錢包所需的所有基本功能,包括創(chuàng)建、加載、轉(zhuǎn)賬、查詢。本文中采用的網(wǎng)絡是infura提供的Rinkeby測試網(wǎng)絡,創(chuàng)建的錢包地址為 0x12571F46Ec3f81F7EbE79112Be5883194d683787。

在具體的業(yè)務場景中,只要將測試網(wǎng)絡更換為以太坊主網(wǎng)絡即可。

源碼地址 https://github.com/initsysctrl/we3jdemo

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容