用户登陆
正在加载
EOS钱包开发:新建钱包、解锁钱包、导入账号
互联网 · 2018-11-12 13:34:00

一、使用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导航模块中。

105D5793-D840-49CC-B095-0FDE5E97EEA6

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

F2121582-16F1-430F-9927-331761AD63D6

使用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分钟不用将会自动锁定,注意一定要保存最后一行的密码,需要使用它解锁这个钱包。

5DEA32F0-9D0B-4E07-994F-7531BA8922BA

二、项目源码

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

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

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="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/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服务后,还需重新打开之前创建的钱包才能显示。创建钱包与打开钱包的效果演示如下:2018-10-09 09.21.50
  • 新创建的钱包没有公私钥对,自己可以导入。对钱包的操作效果演示如下:2018-10-09 09.34.21

项目源码Github地址

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

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

免责声明:
本网站所提供的所有信息仅供参考,不构成任何投资建议。用户在使用本网站的信息时应自行判断和承担风险。币界网不对用户因使用本网站信息而导致的任何损失负责。用户在进行任何投资活动前应自行进行调查和研究,并谨慎决策。币界网不对用户基于本网站信息做出的任何投资决策负责。用户在本网站发布的任何内容均由其个人负责,与币界网无关。
免责声明:本网站、超链接、相关应用程序、论坛、博客等媒体账户以及其他平台和用户发布的所有内容均来源于第三方平台及平台用户。币界网对于网站及其内容不作任何类型的保证,网站所有区块链相关数据以及其他内容资料仅供用户学习及研究之用,不构成任何投资、法律等其他领域的建议和依据。币界网用户以及其他第三方平台在本网站发布的任何内容均由其个人负责,与币界网无关。币界网不对任何因使用本网站信息而导致的任何损失负责。您需谨慎使用相关数据及内容,并自行承担所带来的一切风险。强烈建议您独自对内容进行研究、审查、分析和验证。
s_logo
App内打开