一、使用web3连接到以太坊网络(测试网、主网)
1. 什么是web3
web3是以太坊官方开提供的一个连接以太坊区块链的模块,允许您使用HTTP或IPC与本地或远程以太坊节点进行交互,它包含以太坊生态系统的几乎所有功能。web3模块主要连接以太坊暴露出来的RPC层。开发者利用web3连接RPC层,可以连接任何暴露了RPC接口的节点,从而与区块链交互。web3是一个集合库,支持多种开发语言使用wbe3,其中的JavaScript API叫做web3.js、另外还有web3.py、web3j,web3.js将是我们钱包开发项目的重点。
- web3.eth:用于与以太坊区块链和智能合约之间的交互。
- web3.utils:包含一些辅助方法。
- web3.shh:用于协议进行通信的P2P和广播。
- web3.bzz:用于与群网络交互的Bzz模块。
github地址:web3.js
web3.js开发文档::web3.js
2. 实例化web3对象
web3要与以坊节点进行交互,需要创建一个web3对象,下面看看如何创建。
var Web3 = require('web3');
// "Web3.providers.givenProvider" will be set if in an Ethereum supported browser.
var web3 = new Web3(Web3.givenProvider || 'ws://some.local-or-remote.node:8546');
根据API可知需要指定节点地址,我们将ws://some.local-or-remote.node:8546换成其它连接到以太坊网络的节点的地址,以此来确定连接的以太坊的网络。那么连接到以太坊网络的节点的地址是多少呢?这里我们需要使用到infura。
3. 获取连接到以太坊网络的节点地址
infura提供公开的 Ethereum主网和测试网络节点,到infura.io网站注册后即可获取各个网络的地址。请按照如下步骤获取地址。
第一步:打开 infura网站地址:https://infura.io/dashboard,使用邮箱注册后登陆如下所示:
第二步:点击上图标记的“create new project”按钮创建一个新项目。然后弹出如下弹框,在输入框输入项目名,如”MyEtherWallet“,然后点击“create project”按钮创建。
第三步:然后会显示如下界面,点击下图中的选择框,可以看到提供主网、Kovan测试网络、Ropsten测试网络、Rinkeby测试网络的节点地址。
第四步:选择Kovan测试网络,然后复制地址,将获取到类似这样的地址:https://kovan.infura.io/v3/d93f……cd67,如下。
- 连接到以太坊Kovan测试网络 现在将复制的地址替换掉实例化web对象的地址,如下
var Web3 = require("web3")
var web3 = new Web3(Web3.givenProvider || 'https://kovan.infura.io/v3/bc76cd31e8bf48f9a28b73770ffca805');
console.log("Web3:", Web3)
console.log("web3:", web3)
运行后如下所示
连接到以太坊主网与Kovan测试网络一样的,只需复制主网节点的地址去实例化web3即可。由于在主网上交易需要花费gas,因此我们基于Kovan测试网络进行开发,后续开发完成后可再切换到主网。在我们开发的项目源码中,我将获取web3实例的代码封装到了myUtils.js文件的getweb3()方法中,用于整个项目统一调用。
二、获取地址、私钥、keystore、助记词
1. 使用web3创建账号
创建账号需要使用web3.js的如下API
** API **
web3.eth.accounts.create([entropy]);
* 参数:*
- entropy – String (可选): 它是一个可选项,是一个随机字符串,将作为解锁账号的密码。如果没有传递字符串,则使用random生成随机字符串。
** 返回值: **
Object:包含以下字段的一个帐户对象:
- address- string:帐户地址。
- privateKey- string:帐户私钥。前端永远不应该在localstorage中以未加密的方式共享或存储!
- signTransaction(tx [, callback])- Function:签名交易的方法。
- sign(data)- Function:签名二进制交易的方法。
** 例子 **
web3.eth.accounts.create();
> {
address: "0xb8CE9ab6943e0eCED004cDe8e3bBed6568B2Fa01",
privateKey: "0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709",
signTransaction: function(tx){...},
sign: function(data){...},
encrypt: function(password){...}
}
web3.eth.accounts.create('2435@#@#@±±±±!!!!678543213456764321§34567543213456785432134567');
> {
address: "0xF2CD2AA0c7926743B1D4310b2BC984a0a453c3d4",
privateKey: "0xd7325de5c2c1cf0009fac77d3d04a9c004b038883446b065871bc3e831dcd098",
signTransaction: function(tx){...},
sign: function(data){...},
encrypt: function(password){...}
}
2. 获取地址
使用APIweb3.eth.accounts.create()创建了新账户后生成了一个账户对象,在该对象中拥有address属性,即账户的地址。
let account = web3.eth.accounts.create("123456")
let address = account.address
//address:0xfF0B5A0AA68249cD161b606679DB49CBD9a12cd0
3. 获取私钥
使用APIweb3.eth.accounts.create()创建了新账户后生成了一个账户对象,在该对象中拥有privateKey属性,即账户的私钥。
let account = web3.eth.accounts.create()
let privateKey = account.privateKey
//privateKey:0x348ce564d427a3311b6536bbcff9390d69395b06ed6c486954e971d960fe8709
4. 获取keystore
方式一
在账户对象中,我们可以发现它拥有encrypt对象方法,声明为encrypt: function(password){…},因此可以通过下面的方式去获取keystore。
let account = web3.eth.accounts.create(password)
let keystore = account.encrypt(password)
方式二
获取keystore文件使用web3.js的如下API
API*
web3.eth.accounts.encrypt(privateKey, password);
将私钥加密到keystore文件中。
** 参数: **
- privateKey- String:要加密的私钥。
- password- String:用于加密的密码。
** 返回值: **
Object:加密后的keystore文件
** 例子 **
web3.eth.accounts.encrypt('0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318', 'test!')
> {
version: 3,
id: '04e9bcbb-96fa-497b-94d1-14df4cd20af6',
address: '2c7536e3605d9c16a7a3d7b1898e529396a65c23',
crypto: {
ciphertext: 'a1c25da3ecde4e6a24f3697251dd15d6208520efc84ad97397e906e6df24d251',
cipherparams: { iv: '2885df2b63f7ef247d753c82fa20038a' },
cipher: 'aes-128-ctr',
kdf: 'scrypt',
kdfparams: {
dklen: 32,
salt: '4531b3c174cc3ff32a6a7a85d6761b410db674807b2d216d022318ceee50be10',
n: 262144,
r: 8,
p: 1
},
mac: 'b8b010fff37f9ae5559a352a185e86f9b9c1d7f7a9f1bd4e82a5dd35468fc7f6'
}
}
5. 使用bip39生成助记词
在以太坊常见钱包中,只有MetaMask钱包支持导出助记词,那么如何实现生成助记词呢?这就需要用到HD 钱包。HD 钱包和BIP协议的相关概念请查看”04-密码、私钥、keystore与助记词之间的爱恨情仇”章节中助记词的内容。
由于项目使用的是web3.js创建账号,所以这里只提供了生成助记词的示例,并没有将它集成到项目中,但是可以集成通过助记词解锁账号的功能。
下面通过bip39生成助记词,需要先安装bip39,cd到项目跟路径运行命令npm i bip39。
let bip39 = require('bip39')
let mnemonic = bip39.generateMnemonic()
console.log(mnemonic)
//输出:rotate boss click maximum exercise dune diagram because only any minute monitor
三、项目源码
后端使用web3.js的web3.eth.accounts.create()方法创建账号,然后通过account.encrypt()方法生成keystore文件,提供对应的keystore文件与私钥给前端。
1. newAccount.js
controllers文件夹下新建newAccount.js文件,后端实现返回创建账号的页面与创建账户。
let web3 = require("../utils/myUtils").getweb3()
let fs = require("fs")
let path = require("path")
module.exports = {
//获取创建账号的页面
newAccountHtml: async (ctx) => {
await ctx.render("newaccount.html")
},
//创建账户的表单提交被触发的方法
newAccount: async (ctx) => {
console.log("password:", ctx.request.body.password)
//1.创建钱包账号
let account = web3.eth.accounts.create(ctx.request.body.password)
console.log(account)
//2.根据账号和密码生成keystore文件
let keystore = account.encrypt(ctx.request.body.password)
console.log(keystore)
//3.将keysotr保存到文件
let keystoreString = JSON.stringify(keystore)
let time = new Date()
let fileName = 'UTC--'+time.toISOString()+'--'+account.address.slice(2)
console.log(fileName)
let filePath = path.join(__dirname, "../static/keystore", fileName)
fs.writeFileSync(filePath, keystoreString)
//4.将账号信息返回给客户端
await ctx.render("downloadkeystore.html", {
"downloadurl":"/keystore/"+fileName,
"privatekey":account.privateKey
})
}
}
2. router.js
将创建账户的页面与表单提交的接口绑定到路由。
......
let newAccountController = require("../controllers/newAccount")
//获取创建钱包账户的页面
router.get("/account/new.html", newAccountController.newAccountHtml)
//提交创建钱包账户的表单
router.post("/account/new", newAccountController.newAccount)
3. newaccount.html
在views文件夹下新建newaccount.html文件,实现前端创建账户的页面。
<html>
<head>
<title>创建钱包</title>
<script src="/js/lib/jquery-3.3.1.min.js"></script>
<link rel="stylesheet" href="/css/wallet.css">
</head>
<body>
<%include block/nav.html%>
<div id="main">
<h1>创建一个新的账号</h1>
<form method="POST" action="/account/new">
<input type="text" placeholder="请输入密码" name="password">
<button type="submit">创建账号</button>
</form>
</div>
</body>
</html>
4. downloadkeystore.html
在views文件夹下新建downloadkeystore.html文件,实现前端将创建后的账号信息提供给用户保存下来,如keystore文件、私钥。
<html>
<head>
<title>保存你的keystore</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/wallet.css">
</head>
<body>
<%include block/nav.html%>
<div id="main">
<div id="save-keystore">
<h1>保存你的keystore</h1>
<a class="button" href="<%= downloadurl %>">下载keystore文件</a>
<br><br>
<button onclick="saveKeystoreNext()">下一步</button>
</div>
<div id="save-privatekey" style="display: none">
<h1>保存你的私钥</h1>
<div>
<%= privatekey %>
</div>
</div>
</div>
</body>
</html>
5. wallet.js
编辑static文件夹下的wallet.js文件,实现隐藏keystore下载页面,显示私钥。
function saveKeystoreNext() {
$("#save-keystore").hide()
$("#save-privatekey").show()
}
四、项目运行效果
作者:李旭
来源:http://www.chaindesk.cn
根据央行等部门发布“关于进一步防范和处置虚拟货币交易炒作风险的通知”,本文内容来自网络,所有内容只做信息分享学习使用,不对任何经营与投资行为进行推广与背书,请读者严格遵守所在地区法律法规,不参与任何非法金融活动。内容不代表牛谈观点,发布者:比特老爹,转载请注明出处:https://niutan.com/24571.html