[轉]【比特幣錢包開發 五】新建錢包:生成子帳號地址與路徑

本文轉自:https://www.chaindesk.cn/witbook/9/74css

課程目標
掌握鏈接到比特幣正式網絡與測試網進行開發
學會建立錢包與備份錢包
生成帳號地址
前言
比特幣的帳號是經過bip協議生成種子,而後擴展成多個子地址,這些子地址都由同一個種子能夠推導出來,而知道其中一個子帳號的私鑰不能推導兄弟和父輩節點的私鑰,因此將同一個種子擴展生成的子帳號統一爲一個帳號,在每次交易時均可以使用它的新的子地址去交易,這樣更安全,也更難追蹤,也經常將這個大帳號稱爲錢包。所以對帳號的操做,咱們須要先來建立錢包帳號,那麼本章的內容就是學習如何建立錢包,和錢包的一些經常使用功能。html

1、獲取錢包客戶端對象
在上一章的內容中已經將建立錢包客戶端對象的方法封裝到了Models/walletClient.js文件中的getWalletClient()方法中,以下:前端

getWalletClient: () => {
var Client = require('bitcore-wallet-client');jquery

var client = new Client({
baseUrl: config.BWS_URL,
verbose: false,
});
return client
},

在實例化的時候須要指定bitcore-wallet服務端地址,咱們使用的是bitpay的地址BWS_URL: 'https://bws.bitpay.com/bws/api',你也能夠本身搭建一個錢包服務端。ajax

如今咱們在業務類wallet中調用該方法。express

var client = require("../models/walletClient").getWalletClient()
1json


如今client對象尚未生成認證,能夠看到在__proto下clien有不少個方法,接下來經過client對象調用建立錢包。後端

2、建立錢包的API文檔說明
建立錢包的API文檔以下:api

API.createWallet(walletName, copayerName, m, n, opts, opts.network, opts.walletPrivKey, opts.id, opts.withMnemonics, cb)
Create a wallet.安全

Parameters

walletName: String, Create a wallet.

copayerName: String, Create a wallet.

m: Number, Create a wallet.

n: Number, Create a wallet.

opts: object, (optional: advanced options)

opts.network: string, 'livenet' or 'testnet'

opts.walletPrivKey: String, set a walletPrivKey (instead of random)

opts.id: String, set a id for wallet (instead of server given)

opts.withMnemonics: String, generate credentials

cb: , Create a wallet.

Returns: undefined

根據API的定義可知,必傳參數有以下六個:

walletName: String, 建立的錢包名稱。

copayerName: String, 建立錢包的人,即錢包的擁有者。

m: Number, 該錢包擁有者個數。若爲1,則是我的錢包;若大於1,則是共享錢包,須要多重簽名。

n: Number, 與m對應,不能大於m,指定須要簽名的個數。如果我的錢包,則爲1。

opts: 可選參數,它是一個對象,包含的字斷以下:

opts.network: string, 錢包鏈接的網絡類型,支持正式網絡和測試網絡,分別表示爲:livenet、testnet。

opts.walletPrivKey: 錢包私鑰,能夠不用指定,會隨機生成。

opts.id: String, 錢包ID,能夠不用指定,會自動生成。

opts.withMnemonics: String, 助記詞,用於生成憑證,對錢包的操做都是用這個憑證進行的操做。

cb: 回調方法。該方法是沒有返回值的,響應的數據是經過callba回掉進行傳遞。

3、編碼實現建立錢包
1. 小試牛刀
根據上面的分析咱們進行以下的調用。

var client = require("../models/walletClient").getWalletClient()

client.createWallet("MyWallet", "lixu", 1, 1, {
network: "testnet",
coin: "btc",
}, function (err, ret) {
console.log(ret,ret)
console.log(client)
})

運行後生成的client對象以下:

 

可知建立後的錢包做爲client對象的credential屬性,裏面的字斷記錄了錢包的詳細數據。這樣咱們便建立了一個名稱爲「MyWallet」、擁有者是「lixu」、在測試網絡下的比特幣我的錢包,默認使用BIP44協議建立帳號、地址類型是P2PKH支付給公鑰哈希。另外,咱們沒有發現該帳號的助記詞,因此建立錢包的方法還需完善,那麼正確的步驟是這樣的呢?

2. 經過隨機助記詞生成種子
咱們須要在建立錢包之間調用seedFromRandomWithMnemonic()方法經過隨機助記詞生成種子,目的是爲了可以導出該錢包的助記詞備份錢包。下面API文檔就不做解釋了,你們能夠在GitHub查看,它的用法以下

client.seedFromRandomWithMnemonic({
passphrase: "12345678",
network: "testnet",
coin: "btc",
})

注意:

密碼字斷不能忘記,須要使用密碼與助記詞共同生成種子,密碼不同種子就不同,致使沒法找回帳號。如今運行後的結果以下所示。
network設置爲testnet則是鏈接到測試網,若鏈接到正式網絡則是「livenet」。


3. 導出錢包
咱們建立好錢包後,下次再次使用錢包時須要使用import()方法導入錢包去激活,因此咱們建立錢包後須要備份錢包數據,與以太坊中keystore相似。備份錢包數據須要用到export()方法,它將該錢包對象導出存到文件中,用於下次經過文件打開錢包。import()方法的用法接下來會進行介紹。

特別提醒:

本項目爲了讓你們快速開發比特幣錢包項目,對於非重點內容沒有花時間去講解。那麼這裏項目中導出的錢包爲了便於講解是放在的服務器中,這是很是不安全的作法,對於有經驗的開發者天然是瞭解如何處理這類敏感數據。另外,服務端是對同一個用戶」lixu「即代碼中「copayerName」字段建立的錢包,在實際開發中須要實現用戶模塊創建用戶體系,這裏就簡寫了。建議將此數據放到客戶端保存,而且須要加密。

......

var path = require('path');
var fs = require('fs');

client.createWallet("MyWallet", "lixu", 1, 1, {
network: "testnet",
coin: "btc",
}, function (err, ret) {
console.log(ret,ret)
let filePath = path.join(path.join(__dirname, "../static/wallet_file"), "MyWallet.dat")
fs.writeFileSync(filePath, client.export());
})

將錢包數據儲存在以.bat結尾的文件中,以錢包名稱命名,因此錢包名稱重複會覆蓋錢包帳號。運行後打開static/wallet_file文件夾下的MyWallet.bat文件,它的數據以json字符串儲存,以下圖,使用格式化工具後查看可知它的數據就是client.credentials字斷中的數據。

 

4. 新建地址
新建立的錢包沒有自動生成地址,爲了打開該錢包的時候有一個地址,因此咱們能夠在建立成功後調用新建地址的方法讓他擁有第一個帳號地址。固然,它的路徑確定就是「M/0/0」了。接下來咱們會獲取錢包的子帳號地址進行查看。

......

console.log(ret,ret)
let filePath = path.join(path.join(__dirname, "../static/wallet_file"), "MyWallet.dat")
fs.writeFileSync(filePath, client.export());

client.createAddress({}, function (err, addr) {
console.log(err, addr)
});

輸出以下:

 

4、完整源碼
1. controllers/wallet.js
在controllers文件夾下新建wallet.js文件,後端實現錢包模塊功能,下面先實現建立錢包的功能。

前端須要傳遞walletname, password兩個參數,最後將新建的第一個帳號地址返回給前端,數據結構以下:

{
code: 0,
status: 'success',
data: {
address: 'mrPo6ePcPKFezfRV4Q2pzpmFLTQERvNZKx'
}
}

將常量放在了config配置文件中,在上一章中已經做了介紹。


var client = require("../models/walletClient").getWalletClient()
var path = require('path');
var fs = require('fs');
var config = require("../config/config")
var { success, fail } = require("../utils/myUtils")

module.exports = {
walletCreate: (req, res) => {
let { walletname, password } = req.body
console.log(req.body)

client.seedFromRandomWithMnemonic({
passphrase: password,
network: config.networkType,
coin: config.coinType,
})
console.log(client.credentials.mnemonic)
client.createWallet(walletname, config.coinType, 1, 1, {
network: config.networkType,
withMnemonics: client.credentials.mnemonic,
coin: config.coinType,

}, function (err, ret) {
console.log(err, ret)
if (err) {
res.send(fail(err.message))
return
}
let filePath = path.join(config.walletFilePath, walletname + ".dat")
fs.writeFileSync(filePath, client.export());

client.createAddress({}, function (err, addr) {
console.log(err, addr)
if (err) {
res.send(fail(err.message))
return
}
res.send(success({ "address": addr.address }))
});
})
},
}

2. router/router.js
將建立錢包的接口綁定到路由。

let router = require('express').Router();

let walletController = require("../controllers/wallet")

//錢包
router.post("/wallet/create", walletController.walletCreate)

router.get("/wallet.html", (req, res) => {
res.render("wallet.html");
})

module.exports = router

3. static/js/wallet.js
在文檔加載完成後設置建立錢包表單的驗證與網絡請求。

$(document).ready(function () {

//建立錢包
$("#wallet-create-form").validate({
rules: {
walletname: {
required: true,
},
password: {
required: true,
},
},
messages: {
walletname: {
required: "請輸入新建的錢包名稱",
},
password: {
required: "請輸入新建的錢包密碼",
},
},
submitHandler: function (form) {
$(form).ajaxSubmit({
url: "/wallet/create",
type: "post",
dataType: "json",
success: function (res, status) {
console.log(status + JSON.stringify(res))
alert(JSON.stringify(res.data))
if (res.code == 0) {
window.location.reload()
}
},
error: function (res, status) {
console.log(status + JSON.stringify(res))
}
});
}
})

})

4. views/wallet.html
前端:錢包列表的初始頁面。

<html>

<head>
<title>錢包</title>
<script src="/js/lib/jquery-3.3.1.min.js"></script>
<script src="/js/lib/jquery.url.js"></script>
<script src="/js/wallet.js"></script>
<link rel="stylesheet" href="/css/btcwallet.css">
</head>

<body>
<%include block/nav.html%>

<div id="main">
<h1>錢包列表</h1>
<form id="wallet-create-form">
<button type="submit">建立錢包</button>
<input type="text" name="walletname" placeholder="請輸入錢包名稱">
<input type="text" name="password" placeholder="請輸入錢包密碼">
</form>
</div>
</body>

</html>

5、項目運行效果


項目源碼Github地址

版權聲明:博客中的文章版權歸博主全部,未經受權禁止轉載,轉載請聯繫做者(微信:lixu1770105)取得贊成並註明出處。

未經受權禁止轉載、改編,轉載請註明出處!

本文地址: https://www.chaindesk.cn/witbook/9/74
做者:李旭
連接:https://www.chaindesk.cn/witbook/9/74
來源:http://www.chaindesk.cn
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

其餘章節: https://www.chaindesk.cn/witbook/9

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息