EOS钱包开发:新建钱包、解锁钱包、导入账号

一、使用RPC访问 EOS 区块链

我们使用官方提供RPC接口轻松访问EOS区块链,首先打开 开发者中心网站

在V1.1版本中支持wallet RPC API,而在v1.2版本中nodeos已经删除了钱包API,应该直接在keosd中使用API,它的API定义与之前一样。我们可以在v1.1的版本中查看钱包API,在nodeos中不能再添加钱包插件以启动keosd了,需要通过命令keosd单独启动keosd应用程序,注意它的端口不能与nodeos一样。另外最新的V1.3版本中将wallet RPC API单独放在了网站的keosd导航模块中。

我们使用wallet的第一个API创建钱包,文档如下

使用curl工具发起post请求访问EOS的命令如下

curl --request POST 
--url http://127.0.0.1:8889/v1/wallet/create 
--data '"mywallet"'

运行该命令的前提:

  1. 安装curl工具,这个太简单这里不作讲解了。
  2. 确保命令中的端口与keosd配置文件中的端口一致,我这里是8889(若未配置,请到EOS开发环境配置章节进行配置)。
  3. 启动keosd服务。若报错 Unable to connect to keosd, if keosd is running please kill the process and try again. ,则运行命令 pkill keosd 停止kesod。

成功运行后的效果如下所示,将会返回新钱包的密码,钱包15分钟不用将会自动锁定,注意一定要保存最后一行的密码,需要使用它解锁这个钱包。

二、项目源码

该部分源码包含钱包模块的如下功能:

  • 创建钱包
  • 打开钱包
  • 钱包列表
    • 解锁/锁定
    • 导入私钥/获取公私钥对

1. web.js

在controllers文件夹下新建web.js文件,用于实现后端返回给前端所有的页面,这里返回钱包模块的页面。

module.exports = {
getWalletHtml: async(ctx) => {
await ctx.render("wallet.html")
},
}

2. wallet.js

在controllers文件夹下新建wallet.js文件,后端实现钱包模块的所有功能。

let httpRequest = require("../utils/httpRequest") let config = require("../config/config")
module.exports = {
walletCreate: async(ctx) =>{
console.log(JSON.stringify(ctx.request.body))
let {wallet} = ctx.request.body 
let res = await httpRequest.postRequest(config.walletCreate, wallet)
if (res.code == 0) {
res.data = {"password":res.data, "wallet":wallet}
}
ctx.body = res
}, 
walletOpen: async(ctx) =>{
console.log(JSON.stringify(ctx.request.body))
let {wallet} = ctx.request.body 
let res = await httpRequest.postRequest(config.walletOpen, wallet)
ctx.body = res
}, 
walletList: async(ctx) => {
let res = await httpRequest.postRequest(config.walletList, null)
ctx.body = res
}, 
walletUnlock:async(ctx) => {
console.log(JSON.stringify(ctx.request.body))
let {wallet, password} = ctx.request.body 
let res = await httpRequest.postRequest(config.walletUnlock, [wallet, password])
ctx.body = res
}, 
walletLock: async(ctx) => {
console.log(JSON.stringify(ctx.request.body))
let {wallet} = ctx.request.body 
let res = await httpRequest.postRequest(config.walletLock, wallet)
ctx.body = res
}, 
walletImportPrivatekey:async(ctx) => {
console.log(JSON.stringify(ctx.request.body))
let {wallet, privatekey} = ctx.request.body 
let res = await httpRequest.postRequest(config.walletImportPrivatekey, [wallet, privatekey])
ctx.body = res
}, 
walletGetKeys:async(ctx) => {
console.log(JSON.stringify(ctx.request.body))
let {wallet, password} = ctx.request.body 
let res = await httpRequest.postRequest(config.walletGetKeys, [wallet, password])
ctx.body = res
}, 
walletCreateKey: async(ctx) =>{
let {wallet, type} = ctx.request.body
let res = await httpRequest.postRequest(config.walletCreateKey, [wallet, type])
ctx.body = res
}, 
walletPubkeyGetPrivatekey: async(ctx) => {
let {wallet, password, publickey} = ctx.request.body
let res = await httpRequest.postRequest(config.walletGetKeys, [wallet, password]) 
let privatekey = "无权查看"
for (const index in res.data) {
let keys = res.data[index]
if (keys[0] == publickey) {
privatekey = keys[1]
break
}
} 
res.data = privatekey
ctx.body = res
}
}

3. router.js

将钱包模块所有功能的接口绑定到路由。

let router = require("koa-router")()
let webController = require("../controllers/web")
let walletController = require("../controllers/wallet") 
//钱包
router.post("/wallet/create", walletController.walletCreate)
router.post("/wallet/open", walletController.walletOpen)
router.get("/wallet/list", walletController.walletList)
router.post("/wallet/unlock", walletController.walletUnlock)
router.post("/wallet/lock", walletController.walletLock)
router.post("/wallet/importkey", walletController.walletImportPrivatekey)
router.post("/wallet/keys", walletController.walletGetKeys)
router.post("/wallet/createkey", walletController.walletCreateKey)
router.post("/wallet/privatekey", walletController.walletPubkeyGetPrivatekey) 
//页面
router.get("/wallet.html", webController.getWalletHtml) 
module.exports = router

4. wallet.html

编辑views文件夹下的wallet.html文件,实现前端钱包模块的页面。

<html>
<head>
<title>钱包</title>
<script src="https://www.8btc.com/article/js/lib/jquery-3.3.1.min.js"></script>
<script src="https://www.8btc.com/js/lib/jquery.url.js"></script>
<script src="https://www.8btc.com/article/js/wallet.js"></script>
<link rel="stylesheet" href="https://www.8btc.com/article/css/eoswallet.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="wallet" placeholder="请输入钱包名称">
</form> 
<form id="wallet-open-form">
<button type="submit">打开钱包</button>
<input type="text" name="wallet" placeholder="请输入钱包名称">
</form> 
<table id="wallet-list-table">
</table>
</div>
</body> 
</html>

5. wallet.js

编辑static/js文件夹下的wallet.js文件,前端处理钱包模块的网络请求与页面的渲染。

//导入私钥 function importPrivatekey(wallet) { var privatekey = prompt("请输入您需要导入的私钥"); if(privatekey) { let params = {"wallet":wallet, "privatekey":privatekey} console.log(params) $.post("/wallet/importkey", params, function (res, status) { console.log(status, JSON.stringify(res)) if (res.code == 0) {
}
})
}
} 
//获取钱包的公私钥列表
function getPublickeyList(name) {
var password = prompt(`请输入"${name}"钱包的密码`);
if(password) {
let params = {"wallet":name, "password":password}
console.log(params)
$.post("/wallet/keys", params, function (res, status) {
console.log(status, JSON.stringify(res))
alert(JSON.stringify(res.data))
})
}
} 
//解锁钱包
function unlockWallet(name) {
var password = prompt(`请输入"${name}"钱包的密码`);
if(password) {
let params = {"wallet":name, "password":password}
console.log(params)
$.post("/wallet/unlock", params, function (res, status) {
console.log(status, JSON.stringify(res))
alert(JSON.stringify(res.data))
if (res.code == 0) {
unlockWalletComplete(name)
localStorage.setItem(name, password)
}
})
}
} 
//锁定钱包
function lockWallet(name) {
let params = {"wallet":name}
$.post("/wallet/lock", params, function (res, status) {
console.log(status, JSON.stringify(res))
alert(JSON.stringify(res.data))
if (res.code == 0) {
lockWalletComplete(name)
}
})
} 
function getAccountList(name) {
localStorage.setItem("currentwallet", name)
window.location.href = "/account.html"
} 
function unlockWalletComplete(name) {
console.log(name,name.length)
$(`#unlock${name}`).text("已解锁")
$(`#lock${name}`).text("未锁定")
$(`#unlock${name}`).attr({"disabled":"disabled"})
$(`#lock${name}`).attr({"disabled":false})
$(`#importkey${name}`).attr({"disabled":false})
$(`#getkeys${name}`).attr({"disabled":false})
$(`#getaccounts${name}`).attr({"disabled":false})
} 
function lockWalletComplete(name) {
$(`#unlock${name}`).text("未解锁")
$(`#lock${name}`).text("已锁定")
$(`#unlock${name}`).attr({"disabled":false})
$(`#lock${name}`).attr({"disabled":"disabled"})
$(`#importkey${name}`).attr({"disabled":"disabled"})
$(`#getkeys${name}`).attr({"disabled":"disabled"})
$(`#getaccounts${name}`).attr({"disabled":"disabled"})
} 
$(document).ready(function () { 
//获取钱包列表
$.get("/wallet/list", function (res, status) {
console.log(status, JSON.stringify(res)) 
if (res.code == 0) {
let walletTable = $("#wallet-list-table")
res.data.forEach(wallet => { 
let walletName = wallet
let isUnlock = false
if(wallet.charAt(wallet.length-1)=="*"){
isUnlock = true
walletName = wallet.slice(0,-2)
}
let walletTr = `<tr>
<td>${walletName}</td>
<td><button id="unlock${walletName}" onclick="unlockWallet('${walletName}')">未解锁</button></td>
<td><button id="lock${walletName}" disabled="disabled" onclick="lockWallet('${walletName}')">已锁定</button></td>
<td><button id="importkey${walletName}" disabled="disabled" onclick="importPrivatekey('${walletName}')">导入私钥</button></td>
<td><button id="getkeys${walletName}" disabled="disabled" onclick="getPublickeyList('${walletName}')">获取公私钥对</button></td>
<td><button id="getaccounts${walletName}" disabled="disabled" onclick="getAccountList('${walletName}')">账号列表</button></td>
</tr>`
walletTable.append(walletTr) 
if(isUnlock){
unlockWalletComplete(walletName)
}
});
}
}) 
//创建钱包
$("#wallet-create-form").validate({
rules: {
wallet: {
required: true,
},
},
messages: {
wallet: {
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()
localStorage.setItem(res.data.wallet, res.data.password)
}
},
error: function (res, status) {
console.log(status + JSON.stringify(res))
}
});
}
}) 
//打开钱包
$("#wallet-open-form").validate({
rules: {
wallet: {
required: true,
},
},
messages: {
wallet: {
required: "请输入要打开的钱包名称",
},
},
submitHandler: function (form) {
$(form).ajaxSubmit({
url: "/wallet/open",
type: "post",
dataType: "json",
success: function (res, status) {
console.log(status + JSON.stringify(res))
if (res.code == 0) {
window.location.reload()
} else {
alert(JSON.stringify(res.data))
}
},
error: function (res, status) {
console.log(status + JSON.stringify(res))
}
});
}
})
})

三、项目运行效果

在EOSV1.2之后的版本,钱包数据所在路径是 ~/eosio-wallet ,创建的钱包都能在该文件中查看。

  • 当你第一次使用该钱包应用程序时,前端显示的钱包列表将是空的,需要自己创建钱包。另外,重启keosd服务后,还需重新打开之前创建的钱包才能显示。创建钱包与打开钱包的效果演示如下:
  • 新创建的钱包没有公私钥对,自己可以导入。对钱包的操作效果演示如下:

项目源码Github地址

版权声明:博客中的文章版权归博主所有,未经授权禁止转载,转载请联系作者(微信:lixu1770105)取得同意并注明出处。

未经授权禁止转载、改编,转载请注明出处!

声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章