主页 > 华为手机怎么安装不了imtoken > 【比特币钱包开发5】新钱包:生成子账户地址和路径
【比特币钱包开发5】新钱包:生成子账户地址和路径
课程目标掌握连接比特币官方网络和测试网络进行开发学习创建钱包和备份钱包生成账户地址前言
比特币账户通过bip协议做种子,然后扩展成多个子段地址,这些子地址可以从同一个种子中推导出来,知道其中一个子账户的私钥不能推导出该子账户的私钥兄弟节点和父节点,所以同一种子扩容产生的子账户统一为一个账户。每次进行交易时,您都可以使用其新的子地址进行交易,这样更安全,更难追踪。这个大账户通常被称为钱包。因此,要操作账户,我们需要先创建一个钱包账户,所以本章的内容就是学习如何创建钱包以及钱包的一些常用功能。
一、获取钱包客户端对象
在上一章的内容中,创建钱包客户端对象的方法已经封装在Models/walletClient.js文件中。在getWalletClient()方法中,如下:
getWalletClient: () => {
var Client = require('bitcore-wallet-client');
var client = new Client({
baseUrl: config.BWS_URL,
verbose: false,
});
return client
},
实例化时需要指定bitcore-wallet服务器地址,我们使用bitpay地址BWS_URL:'#39;,你也可以自己搭建一个钱包服务器。
现在我们在业务类钱包中调用这个方法。
var client = require("../models/walletClient").getWalletClient()
client对象还没有生成鉴权,可以看到__proto方法下有很多client,然后调用client对象创建钱包。
二、创建钱包的 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的定义,必须传递的参数有六个:
三、编码创建钱包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)
})
运行后生成的客户端对象如下:
可以看出,创建的钱包作为客户端对象的凭证属性,其中的分词记录了钱包的详细数据。这样,我们创建了一个名为“MyWallet”的比特币个人钱包,由“lixu”拥有,并在测试网络下。默认使用 BIP44 协议创建账户,地址类型为 P2PKH 支付给公钥哈希。另外怎么创建钱包地址,我们没有找到账户的助记词,所以创建钱包的方法有待改进,那么正确的步骤是什么?
2.随机助记词生成种子
我们需要在创建钱包之间调用seedFromRandomWithMnemonic()方法,通过随机助记词生成种子,以便能够导出钱包的助记词来备份钱包。以下 API 文档将不做解释。你可以在 GitHub 上查看。其用法如下
client.seedFromRandomWithMnemonic({
passphrase: "12345678",
network: "testnet",
coin: "btc",
})
注意:
@ >
3.导出钱包
我们创建钱包后,需要使用import()方法导入钱包,以便下次再次使用钱包时激活,所以创建钱包后需要备份钱包数据,类似于以太坊中的密钥库。需要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)
});
输出如下:
四、完整源码1.controllers/wallet.js
在controllers文件夹新建wallet.js文件,在后台实现wallet模块功能。先实现创建钱包的功能。
前端需要传入walletname和password两个参数,最后将第一个新账户的地址返回给前端。数据结构如下:
{
代码:0,
状态:'成功',
数据:{
地址:'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.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. 静态/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. 意见/wallet.html
前端:钱包列表的初始页面。
钱包
<%include block/nav.html%>
钱包列表
五、项目运行效果
项目源码Github地址