1. 北竹林首页
  2. 资讯
  3. 技术指南

EOS钱包开发之新建账号:设置多权限配置

一、介绍说明
在开发账号模块之前,我们需要先用cleos工具帮我们创建一个账号,是什么原因需要它去创建和如何创建的请查看“使用cleos管理账号权限”章节的内容,这样我们才好使用开发的钱包项目查看账号详情以及创…

一、介绍说明


在开发账号模块之前,我们需要先用cleos工具帮我们创建一个账号,是什么原因需要它去创建和如何创建的请查看“使用cleos管理账号权限”章节的内容,这样我们才好使用开发的钱包项目查看账号详情以及创建账号。

创建账号属于一个交易,若使用RPC接口是非常的繁琐容易出错,这里我们使用eosjs库中封装的交易的接口,使用及其简单,eosjs的使用说明请查看“深入浅出EOSJS:连接到主网、测试网、交易”章节的内容。

本项目在配置eos对象时,获取了钱包里面所有的私钥进行配置,这样简化了用户每次交易都输入秘钥的操作,只需要输入钱包密码即可。

二、项目源码一:获取账号列表

账号模块的主要功能包括:

  • 账号列表
  • 通过私钥导入账号
  • 新建账号
  • 查看账号详情
    • 查询余额
    • 获取公私钥对
    • 查询权限配置

这部分源码先介绍获取账号列表的前后端实现。

1. web.js

编辑controllers文件夹下的web.js文件,实现后端返回给前端账号列表的页面。

module.exports = {
......

getAccountHtml:async(ctx) => { await ctx.render("account.html") }, }

2. account.js

在controllers文件夹下新建account.js文件,后端实现获取账号列表的功能。

let httpRequest = require("../utils/httpRequest")
let config = require("../config/config")
let {success, fail} = require("../utils/myUtils")
let myUtils = require("../utils/myUtils")

module.exports = { //通过钱包名称获取账号列表 accountListForWallet: async (ctx) => { console.log(JSON.stringify(ctx.request.body)) let { wallet, password } = ctx.request.body //获取钱包管理的所有公私钥对 let res = await httpRequest.postRequest(config.walletGetKeys, [wallet, password])

let accountList = [] if (res.code == 0) { for (const index in res.data) { let keys = res.data[index] console.log(keys[0]) //查询公钥关联的所有账号 let resData = await httpRequest.postRequest(config.accountListForKey, { "public_key": keys[0] }) if (resData.code == 0) { resData.data.account_names.forEach(account => { //去重 if (accountList.indexOf(account) < 0) { accountList.push(account) } }) } }; } console.log("accountList:", accountList)

res.data = accountList ctx.body = res }, }

3. router.js

将获取账号列表的接口绑定到路由。

......

let accountController = require("../controllers/account")

//账号 router.post("/account/listforwallet", accountController.accountListForWallet)

//页面 router.get("/account.html", webController.getAccountHtml)

4. account.html

在views文件夹下新建account.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/account.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> <div> <a href="https://www.8btc.com/accountnew.html" class="button">去新建账号</a> </div> <br>

<form id="account-import-form"> <button type="submit">导入账号</button> <input type="text" name="wallet" hidden="hidden"> <input type="text" name="privatekey" placeholder="请输入账号私钥"> </form>

<table id="account-list-table"> </table> </div> </body>

</html>

5. account.js

在static/js文件夹下新建account.js文件,前端处理账号列表的网络请求与页面的渲染。

function accountInfo(acocunt) {
localStorage.setItem("currentAccount", acocunt)
window.location.href = "/accountinfo.html"
}

function goTransaction(account) { localStorage.setItem("currentAccount", account) window.location.href = "/transaction.html" }

$(document).ready(function () { let currentwallet = localStorage.getItem("currentwallet") $("h1").text(currentwallet+" 钱包") if (!currentwallet) { return } let walletPassword = localStorage.getItem(currentwallet) $("input[name=wallet][hidden=hidden]").val(currentwallet)

//获取账号列表 let params = {"wallet":currentwallet, "password":walletPassword} $.post("/account/listforwallet", params, function (res, status) { console.log(status + JSON.stringify(res)) if (res.code == 0) { let accountTable = $("#account-list-table") res.data.forEach(account => { let accountTr = ` <tr> <td>${account}</td> <td><button onclick="accountInfo('${account}')">查看详情</button></td> <td><button onclick="goTransaction('${account}')">去转账</button></td> </tr>` accountTable.append(accountTr) });

sessionStorage.setItem(`wallet-${currentwallet}-accounts`, JSON.stringify(res.data)) } })

//导入账户 $("#account-import-form").validate({ rules: { privatekey: { required: true, }, }, messages: { privatekey: { required: "请输入要导入的账号的私钥", }, }, submitHandler: function (form) { $(form).ajaxSubmit({ url: "/wallet/importkey", 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)) } }); } }) })

三、项目源码一:新建账号

1. web.js

编辑controllers文件夹下的web.js文件,实现后端返回给前端创建账号的页面。

module.exports = {
......

getAccountCreateHtml:async(ctx) => { await ctx.render("accountNew.html") }, }

2. account.js

编辑controllers文件夹下的account.js文件,后端实现创建账号的功能。

module.exports = {
......

//创建账号 accountCreate: async (ctx) => { console.log(JSON.stringify(ctx.request.body)) let {account, creator, wallet, password, activepubkey, ownerpubkey} = ctx.request.body

//1.获取钱包里面所有的私钥 let privatekeyList = [] let res = await httpRequest.postRequest(config.walletGetKeys, [wallet, password]) if (res.code == 0 && res.data.length > 0) { for (const index in res.data) { let keys = res.data[index] privatekeyList.push(keys[1]) } //2.设置创建账号默认的公钥 let defaultKey = res.data[0][0]

activepubkey = activepubkey || defaultKey ownerpubkey = ownerpubkey || defaultKey }

console.log("privatekeyList:", privatekeyList) console.log("activepubkey:", activepubkey,"n ownerpubkey:", ownerpubkey)

//3.配置EOSJS eos = myUtils.getEOSJS(privatekeyList)

//4.交易(创建账号) let data = await eos.transaction(tr => { tr.newaccount({ creator: creator, name: account, owner: ownerpubkey, active: activepubkey })

tr.buyrambytes({ payer: creator, receiver: account, bytes: 8192 })

tr.delegatebw({ from: creator, receiver: account, stake_net_quantity: '10.0000 EOS', stake_cpu_quantity: '10.0000 EOS', transfer: 0 }) }) // console.log(JSON.stringify(data))

//5.返回给前端执行的状态 let resData if (data) { resData = success("创建账号成功") } else { resData = fail("创建账号失败") } ctx.body = resData }, }

3. router.js

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

......

//账号 router.post("/account/create", accountController.accountCreate)

//页面 router.get("https://www.8btc.com/accountnew.html", webController.getAccountCreateHtml)

4. accountNew.html

在views文件夹下新建accountNew.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/accountNew.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> <h2>新建账号</h2>

<form id="account-create-form"> <input type="text" name="account" placeholder="请输入账号名称"> <label>账号名称</label> <br><br>

<select name="creator" id="account-create-creator-select"> </select> <label>创建者名称</label> <br><br>

<div>以下内容可以选择填写</div>

<button type="button" onclick="createKey()">新建公钥私钥</button> <br>

<input type="text" name="activepubkey" placeholder="请输入active权限的公钥"> <label>active公钥</label> <br>

<input type="text" name="ownerpubkey" placeholder="请输入owner权限的公钥"> <label>owner公钥</label> <br><br> <input type="text" name="wallet" hidden="hidden"> <input type="text" name="password" hidden="hidden"> <button type="submit">新建账号</button> </form>

</div> </body>

</html>

5. accountNew.js

在static/js文件夹下新建accountNew.js文件,前端处理新建账号的网络请求与页面的渲染。

function createKey() {
let currentwallet = localStorage.getItem("currentwallet")
let params = {"wallet": currentwallet, "type":"k1"}
$.post("/wallet/createkey", params, function (res, status) {
console.log(status, JSON.stringify(res))
alert(res.data)
})
}

$(document).ready(function () { let currentwallet = localStorage.getItem("currentwallet") $("h1").text(currentwallet+" 钱包") if (!currentwallet) { return }

let walletPassword = localStorage.getItem(currentwallet)

$("input[name=wallet][hidden=hidden]").val(currentwallet) $("input[name=password][hidden=hidden]").val(walletPassword)

//选择新建者账号列表 let accountList = sessionStorage.getItem(`wallet-${currentwallet}-accounts`) accountList = JSON.parse(accountList) console.log("accountList",accountList) let accountSelectList = $("#account-create-creator-select") for(let i = 0; accountList && i < accountList.length; i++) { let account = accountList[i] let accountOption = `<option value="${account}">${account}</option>` accountSelectList.append(accountOption) }

//新建账号 $("#account-create-form").validate({ rules: { name: {required: true,}, creator: {required: true,}, }, messages: { name: {required: "请输入要新建的账号名称",}, creator: {required: "该钱包没有可供新建账号的创者账号,可将该钱包的任意一个公钥发送给其它钱包新建该账号,或者导入其他账号的私钥到该钱包再进行新建账号"}, }, submitHandler: function (form) { $(form).ajaxSubmit({ url: "/account/create", type: "post", dataType: "json", success: function (res, status) { console.log(status + JSON.stringify(res)) if (res.code == 0) { alert("账号新建成功") window.location.href = history.go(-1); } else { alert("账号新建失败") } }, error: function (res, status) { console.log(status + JSON.stringify(res)) alert(res.data) } }); } }) })

四、项目源码一:查看账号详情

1. web.js

编辑controllers文件夹下的web.js文件,实现后端返回给前端账号详情的页面。

module.exports = {
......

getAccountInfoHtml:async(ctx) => { await ctx.render("accountInfo.html") }, }

2. account.js

编辑controllers文件夹下的account.js文件,后端实现查看账号详情的功能。

module.exports = {
......

accountBalance: async (ctx) => { let {code, account} = ctx.request.body let params = {"code":code,"account":account} let res = await httpRequest.postRequest(config.accountBalance, params)

let currencyList = [] if (res.code == 0) { for (const index in res.data) { let currency = res.data[index] //"9996.0000 EOS" let currencys = currency.split(" ")//currencys[0]=9996.0000, currencys[1]=EOS currencyList.push({ "symbol":currencys[1], "amount":currencys[0] }) } } res.data = currencyList console.log("currencyList:", currencyList) res.data = currencyList ctx.body = res },

accountInfo: async (ctx) =>{ let {account} = ctx.request.body let res = await httpRequest.postRequest(config.accountInfo, {"account_name":account}) ctx.body = res }, }

3. router.js

将查看账号详情的接口绑定到路由。

......

//账号 router.post("/account/balance", accountController.accountBalance) router.post("/account/info", accountController.accountInfo)

//页面 router.get("/accountinfo.html", webController.getAccountInfoHtml)

4. accountInfo.html

在views文件夹下新建accountInfo.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/accountInfo.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>

<table id="account-balance-table"> <tr> <th>代币</th> <th>金额</th> </tr> </table>

<table id="account-permission-table"> <tr> <th>权限</th> <th>阈值</th> <th>公钥</th> <th>私钥</th> <th>权重</th> </tr> </table>

</div> </body>

</html>

5. accountInfo.js

在static/js文件夹下新建accountInfo.js文件,前端处理查看账号详情的网络请求与页面的渲染。

function getAccountPermissionPrivateKey(publicKey) {
let currentwallet = localStorage.getItem("currentwallet")
let currentPassword = localStorage.getItem(currentwallet)
let params = {"wallet":currentwallet, "password":currentPassword, "publickey":publicKey}
console.log(params)
$.post("/wallet/privatekey", params, function (res, status) {
console.log(status, JSON.stringify(res))
alert(JSON.stringify(res.data))
})
}

$(document).ready(function () { let currentAccount = localStorage.getItem("currentAccount") $("h1").text(currentAccount+" 账号") if (!currentAccount) { return }

//账号金额 let params = {"code":"eosio.token","account":currentAccount} $.post("/account/balance", params, function (res, status) { console.log(status + JSON.stringify(res)) //后端返回的数据结构如下 //[{"symbol":"EOS", "amout":100}, {"symbol":"SYS", "amount":200}] if (res.code == 0) { let balanceTable = $("#account-balance-table") res.data.forEach(balanceData => { let balanceTr = `<tr> <td>${balanceData.symbol}</td> <td>${balanceData.amount}</td> </tr>` balanceTable.append(balanceTr) }); } })

//账号权限详情 $.post("/account/info", {"account":currentAccount}, function (res, status) { console.log(status + JSON.stringify(res)) if (res.code == 0) { let permissionTable = $("#account-permission-table") for (const index in res.data.permissions) { let permission = res.data.permissions[index] let publicKey = permission.required_auth.keys[0].key let rowTr = `<tr> <td>${permission.perm_name}</td> <td>${permission.required_auth.threshold}</td> <td>${publicKey}</td> <td><button onclick="getAccountPermissionPrivateKey('${publicKey}')">点击查看</button></td> <td>${permission.required_auth.keys[0].weight}</td> </tr>` permissionTable.append(rowTr)

for(let i = 1; i < permission.required_auth.keys.length; i++) { let keyData = permission.required_auth.keys[i] let rowTr = `<tr> <td></td> <td></td> <td>${keyData.key}</td> <td><button onclick="getAccountPermissionPrivateKey('${keyData.key}')">点击查看</button></td> <td>${keyData.weight}</td> </tr>` permissionTable.append(rowTr) }; }; } }) })

五、项目运行效果

  1. 获取钱包mywallet1的账号列表如下

97FD6D99-1DF2-4597-9E04-46B763AD5922

  1. 新建账号的效果如下在mywallet1钱包中使用账号lixu新建账号account1,控制的权限的两个公钥都是一样的,对应的私钥并且在mywallet2钱包中的,所以创建后将会在mywallet2钱包中看到该账号。

2018-10-12 15.50.17

  1. 查看账号详情我们查看使用cleos配置的多个主体共同管理的账号lixu,为了简化前端的代码量,只显示了主体是公钥的数据,并没有显示主体是账号的数据,其中的一个公私钥主体无权获取私钥,因为它没有到当前钱包中。2018-10-12 15.58.20

项目源码Github地址

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

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

声明:登载此文出于传递更多信息之目的,观点仅代表作者本人,绝不代表北竹林赞同其观点或证实其描述。

提示:投资有风险,入市须谨慎。本资讯不作为投资理财建议。

联系我们

QQ:

1739447883

邮箱:

1739447883@qq.com