以太坊去中心化網頁錢包開發系列,將從零開始開發出一個可以實際使用的錢包,本系列文章是理論與實戰相結合,一共有四篇:建立錢包賬號、賬號Keystore檔案匯入匯出、展示錢包資訊及發起簽名交易、傳送Token(代幣),這是第一篇,主要介紹錢包將實現哪些功能及怎麼建立錢包賬號,本錢包是基於ethers.js 進行開發。
去中心化網頁錢包
先明確一下定義,什麼是去中心化錢包,賬號祕鑰的管理,交易的簽名,都是在客戶端完成, 即私鑰相關的資訊都是在使用者手中,錢包的開發者接觸不到私鑰資訊。
對應的中心化錢包則是私鑰由中心伺服器託管,如交易所的錢包就是這種。
網頁錢包,或者叫web錢包,是指錢包以網頁的形式展現,去中心化網頁錢包則交易的簽名等操作是在瀏覽器裡完成。
其他形式的錢包,如Android錢包或iOS錢包其開發思路和web錢包一樣,因此文字對開發其他平臺的錢包也有參考意義,不過本系列文章主要側重在錢包功能的實現,並未過多考慮使用者體驗。
錢包功能
一個錢包通常主要包含的功能有:
- 賬號管理(主要是私鑰的管理):建立賬號、賬號匯入匯出
- 賬號資訊展示:如以太幣餘額、Token(代幣)餘額。
- 轉賬功能:傳送以太幣及傳送Token(代幣)
這些功能將基於 ethers.js 進行開發, ethers.js 和web3.js 一樣,也是一套和以太坊區塊鏈進行互動的庫,不僅如此,ethers.js 還對BIP 39等相關的提案進行了實現,可以在這個連結閱讀其文件。
這些功能主要表現為錢包的兩個介面,一個介面是:賬號管理,一個介面是進行賬號資訊展示及轉賬。下面逐個進行介紹
建立錢包賬號
讀過上一篇文章理解開發HD 錢包涉及的 BIP32、BIP44、BIP39的同學,會知道建立賬號,可以有兩種方式:
- 直接生成32個位元組的數當成私鑰
- 通過助記詞進行確定性推匯出私鑰
使用隨機數作為私鑰建立錢包賬號
即方式一,可以使用ethers.utils.randomBytes生成一個隨機數,然後使用這個隨機數來建立錢包,如程式碼:
var privateKey = ethers.utils.randomBytes(32);
var wallet = new ethers.Wallet(privateKey);
console.log("賬號地址: " + wallet.address);
上面程式碼的 wallet 是 ethers 中的一個錢包物件,它除了有程式碼中出現的.address 屬性之外,還有如 獲取餘額、傳送交易等方法,在後面的文章會進行介紹。
注意ethers.utils.randomBytes 生成的是一個位元組陣列,如果想用十六進位制數顯示出來表示,需要轉化為BigNumber程式碼如下:
let keyNumber = ethers.utils.bigNumberify(privateKey);
console.log(randomNumber._hex);
現在我們結合介面,完整的實現建立賬號,其效果圖如下,載入私鑰時建立賬號。
介面程式碼(HTML)程式碼如下(主要是在表格中定義個一個輸入框及一個按鈕):
<table>
<tr>
<th>私鑰:</th>
<td><input type="text" placeholder="(private key)" id="select-privatekey" /></td>
</tr>
<tr>
<td> </td>
<td>
<div id="select-submit-privatekey" class="submit">載入私鑰</div>
</td>
</tr>
</table>
對應的邏輯程式碼(JavaScript)如下:
// 使用JQuery獲取兩個UI標籤
var inputPrivatekey = $('#select-privatekey');
var submit = $('#select-submit-privatekey');
// 生成一個預設的私鑰
let randomNumber = ethers.utils.bigNumberify(ethers.utils.randomBytes(32));
inputPrivatekey.val(randomNumber._hex);
// 點選“載入私鑰”時, 建立對應的錢包
submit.click(function() {
var privateKey = inputPrivatekey.val();
if (privateKey.substring(0, 2) !== '0x') { privateKey = '0x' + privateKey; }
var wallet = new ethers.Wallet(privateKey));
});
如果使用者提供一個已有賬號的私鑰,則會匯入其原有賬號。
通過助記詞方式建立錢包賬號
這是目前主流常見錢包的方式,關於助記詞推導過程請閱讀理解開發HD 錢包涉及的 BIP32、BIP44、BIP39。
我們需要先生成一個隨機數,然後用隨機數生成助記詞,隨後用助記詞建立錢包賬號,設計到的API有:
var rand = ethers.utils.randomBytes(16);
// 生成助記詞
var mnemonic = ethers.utils.HDNode.entropyToMnemonic(rand);
var path = "m/44'/60'/0'/0/0";
// 通過助記詞建立錢包
ethers.Wallet.fromMnemonic(mnemonic, path);
現在我們結合介面來實現一下通過助記詞方式建立錢包賬號,其效果圖如下:
介面程式碼(HTML)程式碼如下(主要是在表格中定義個兩個輸入框及一個按鈕):
<table>
<tr>
<th>助記詞:</th>
<td><input type="text" placeholder="(mnemonic phrase)" id="select-mnemonic-phrase" /></td>
</tr>
<tr>
<th>Path:</th>
<td><input type="text" placeholder="(path)" id="select-mnemonic-path" value="m/44'/60'/0'/0/0" /></td>
</tr>
<tr>
<td> </td>
<td>
<div id="select-submit-mnemonic" class="submit">推倒</div>
</td>
</tr>
</table>
對應的邏輯程式碼(JavaScript)如下:
var inputPhrase = $('#select-mnemonic-phrase');
var inputPath = $('#select-mnemonic-path');
var submit = $('#select-submit-mnemonic');
// 生成助記詞
var mnemonic = ethers.utils.HDNode.entropyToMnemonic(ethers.utils.randomBytes(16));
inputPhrase.val(mnemonic);
submit.click(function() {
// 檢查助記詞是否有效。
if (!ethers.utils.HDNode.isValidMnemonic(inputPhrase.val())) {
return;
}
// 通過助記詞建立錢包物件
var wallet = ethers.Wallet.fromMnemonic(inputPhrase.val(), inputPath.val());
});
同樣使用者可以提供一個其儲存的助記詞來匯入其錢包,有一些遺憾的是,ethers.js 暫時不支援通過新增密碼作為Salt來保護種子(也可能是我沒有找到,如果知道的同學,希望反饋下),如果需要此功能可以引入bip39 和 ethereumjs-wallet 庫來實現,程式碼可參考理解開發HD 錢包涉及的 BIP32、BIP44、BIP39。
小結
其實 ethers 還提供了一個更簡單的方法來建立錢包:
// 直接建立一個隨機錢包
ethers.Wallet.createRandom();
哈哈,恭喜大家,到這裡這裡就完整的實現了一個基於以太坊去中心化網頁錢包。
這是一條硬廣,歡迎訂閱深入淺出區塊鏈技術小專欄,目前僅需69元, 訂閱就可以檢視完整原始碼,還有其他驚喜哦~。
戳連結收看詳細的視訊課程講解。
參考文件
深入淺出區塊鏈 - 系統學習區塊鏈,打造最好的區塊鏈技術部落格。
深入淺出區塊鏈知識星球最專業技術問答社群,加入社群還可以在微信群裡和300多位區塊鏈技術愛好者一起交流。