EOS nodejs 合约交互 ( 一 ) - 创建合约和 eosjs 环境配置

yufei       6 年 前       2540

这几天工作中遇到需要后端的 nodejsEOS 合约 进行交互的需求,简单记录下一些开始的配置项目

合约

假设我们有一个 micromsg 合约,有两个动作 actionsend 用于留言,read 用于设置留言已经读过和一张表 messages 用于记录用户留言

留言的字段如下

字段 类型 说明
id uint64_t 自增 id
from eosio::name 谁留的言
to eosio::name 给谁的留言
msg std::string 留言内容
tm uint64_t 留言时间
readed uint8_t 是否已读

索引

这里为了简单起见,我们只给自增 id 添加索引,实际上,应该给 to 也添加一个索引

uint64_t primary_key() const { return id;}

动作 send

用于发送留言,原型如下

[[eosio::action]] void send(name from, name to, string msg);

动作 read

用于设置留言已经读取,原型如下

[[eosio::action]] void read(name to, uint64_t msg_id);

完整的合约代码如下

microsmg/micromsg.cpp

#include <eosiolib/eosio.hpp>
#include <eosiolib/multi_index.hpp>
#include <eosiolib/system.h>

using namespace std;
using namespace eosio;

class [[eosio::contract]] micromsg: eosio::contract {
public:
    using eosio::contract::contract;

    [[eosio::action]] void send(name from, name to, string msg)
    {
        require_auth(from);
        eosio_assert(msg.size() > 0, "msg must not be empty");

        // 通知发送者
        require_recipient(from);
        // 通知接受者
        require_recipient(to);

        messages _tbl(_self,_self.value);
        auto id = _tbl.available_primary_key();

        _tbl.emplace(_self, [&](auto &s) {
            s.id        = id;
            s.from      = from;
            s.to        = to;
            s.msg       = msg;
            s.tm        = now();
            s.readed    =0;
        });
        print("#", id, " ",from , " send '" ,std::string(msg) , "' to " , to ," at " , now());
    }


    [[eosio::action]] void read(name to ,uint64_t msg_id)
    {
        require_auth(to);
        messages _tbl(_self,_self.value);

        auto it = _tbl.find(msg_id);
        if ( it != _tbl.end()) {
            if ( it->to == to && it->readed == 0 ) {
                _tbl.modify(it,same_payer,[&](auto &s){
                    s.readed = 1;
                });
            }
            print("ok");
        }
    }


    struct [[eosio::table]] message {
        uint64_t    id;
        name        from;
        name        to;
        string      msg;
        uint64_t    tm;
        bool        readed;

        uint64_t primary_key() const { return id;}
    };

    typedef multi_index<"messages"_n, message> messages;
};

EOSIO_DISPATCH(micromsg,(send)(read))

编译部署合约

使用下面的命令编译

eosio-cpp -o micromsg.wasm micromsg.cpp --abigen

接着在本地 nodeos 环境中使用下面的命令创建三个账号

你需要将公钥换成你自己的

  1. 合约账号

    cleos create account eosio  micromsg EOS8iQXBhFiiBogGiqacVRCuk3mxPzELe15iA89A8wuw5SKpXzoZr EOS8iQXBhFiiBogGiqacVRCuk3mxPzELe15iA89A8wuw5SKpXzoZr
    
  2. 小明

    cleos create account eosio  xiaoming EOS8iQXBhFiiBogGiqacVRCuk3mxPzELe15iA89A8wuw5SKpXzoZr EOS8iQXBhFiiBogGiqacVRCuk3mxPzELe15iA89A8wuw5SKpXzoZr
    
  3. 小红

    cleos create account eosio  xiaohong EOS8iQXBhFiiBogGiqacVRCuk3mxPzELe15iA89A8wuw5SKpXzoZr EOS8iQXBhFiiBogGiqacVRCuk3mxPzELe15iA89A8wuw5SKpXzoZr
    

接着使用下面的命令部署合约

cleos set contract  micromsg ../micromsg -p micromsg

测试

最后,我们使用下面的命令来检查下合约是否正确

  1. 首先 小明给小红发信息

    cleos push action micromsg send '["xiaoming","xiaohong","i miss you"]' -p xiaoming
    

    可以看到输出如下

    cleos push action micromsg send '["xiaoming","xiaohong","i miss you"]' -p xiaoming
    executed transaction: 56d236d199415fc14b2a711c296014131b9a2504439567fcc2c24c4a824fff97  120 bytes  705 us
    #      micromsg <= micromsg::send               {"from":"xiaoming","to":"xiaohong","msg":"i miss you"}
    >> #0 xiaoming send 'i miss you' to xiaohong at 1543709972
    #      xiaoming <= micromsg::send               {"from":"xiaoming","to":"xiaohong","msg":"i miss you"}
    #      xiaohong <= micromsg::send               {"from":"xiaoming","to":"xiaohong","msg":"i miss you"}
    

    从输出结果中可以看出,我们发送的消息 id 是 0

    重复使用该命令多发送几条

  2. 然后我们使用 cleos get table 命令查看下我们发送的数据,完整命令如下

    micromsg yufei$ cleos get table micromsg micromsg messages
    

    输出结果如下:

    {
      "rows": [{
          "id": 0,
          "from": "xiaoming",
          "to": "xiaohong",
          "msg": "i miss you",
          "tm": 1543709972,
          "readed": 0
        },{
          "id": 1,
          "from": "xiaoming",
          "to": "xiaohong",
          "msg": "i miss you",
          "tm": 1543710047,
          "readed": 0
        },{
          "id": 2,
          "from": "xiaoming",
          "to": "xiaohong",
          "msg": "i miss you",
          "tm": 1543710048,
          "readed": 0
        },{
          "id": 3,
          "from": "xiaoming",
          "to": "xiaohong",
          "msg": "i miss you",
          "tm": 1543710048,
          "readed": 0
        },{
          "id": 4,
          "from": "xiaoming",
          "to": "xiaohong",
          "msg": "i miss you",
          "tm": 1543710049,
          "readed": 0
        },{
          "id": 5,
          "from": "xiaoming",
          "to": "xiaohong",
          "msg": "i miss you",
          "tm": 1543710049,
          "readed": 0
        }
      ],
      "more": false
    }
    
  3. 接着, 我们使用小红的账号,设置 #id0 的信息设置为已读

    cleos push action micromsg read '["xiaohong",1]' -p xiaohong
    executed transaction: b82ca3430652c6a07c1d73c15096d54397bf516d097f090cdc6f4d7109740157  112 bytes  367 us
    #      micromsg <= micromsg::read               {"to":"xiaohong","msg_id":1}
    >> ok
    

好了,关于合约方面,我们已经开发、部署、测试完毕了,现在开始使用 nodejs 与合约进行交互

nodejs eos 环境搭建

nodejs 与 EOS 合约交互一般使用 eosjs 包,可以使用下面的命令来安装

npm i eosjs

接着在当前目录下新建一个文件 micromsg.js ,这个文件将包含所有与 EOS 合约交互的代码

touch micormsg.js

然后打开 micormsg.js 文件,开始我们的代码之旅

首先,我们需要引入 eosjs

const Eos = require('eosjs');

其次,我们要做的就是创建 EOS 链配置,需要配置的项目有

const config = {
    account: {
        contract: "micormsg",   // 合约账号
        from: "xiaoming",       // 发送者账号
        to: "xiaohong"          // 接收者账号
    },
    network: {
        protocol:'http',        // 协议 http or https
        host: 'localhost',      // 远程主机
        port: '8080',           // 远程端口号
        keys:['5J6Ly95q876iEwG1c4bBcWAWqHbibRmhDsxtSrnsSswpT7r7gAC'], // 私钥
        chainId: 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f', // EOS 链 id
        timeout: 10000          // 10s 超时
    }
}

配置项需要根据你自己的 nodeos 的节点配置,尤其是是 keys,因为我三个账号共用一个公钥,所以它们的私钥也就一个了。

3. 创建 Eos 的实例

var eos = Eos(config);

4. 测试获取 Eos 链信息,用户检查我们的配置项是否正确

这里,我们需要使用到 eos.getInfo 函数。

注意,所有的 eosjs 函数,如果不传递任何参数,那么就是显示该函数的帮助信息

console.log(eos.getInfo());

输出结果如下

USAGE
getInfo - Return general network information.

PARAMETERS
none

RETURNS
"string"

ERRORS
nothing special

如果函数参数为空,则需要传递空对象 {}

如果函数执行成功,那么就会返回一个 Promise

console.log(eos.getInfo({}));

输出结果如下

Promise { <pending> }

对于返回的 Promise,我们可以调用 then() 来获取返回结果,而调用 catch 来捕获错误,使用方式大概如下

eos.getInfo({}).then(rs => console.log(rs)).catch(e => console.log(e))

运行结果如下

{ server_version: '59626f1e',
  chain_id:
   'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f',
  head_block_num: 67187,
  last_irreversible_block_num: 67186,
  last_irreversible_block_id:
   '00010672d813e96d11b5d32f0123fc3b64a7328e68b15f45f067d382d7a3647b',
  head_block_id:
   '00010673664500983ec1d7a6a004f62f98f70af18462d6a0acc7e4ae98985ba1',
  head_block_time: '2018-12-02T00:53:52.500',
  head_block_producer: 'eosio',
  virtual_block_cpu_limit: 200000000,
  virtual_block_net_limit: 1048576000,
  block_cpu_limit: 199900,
  block_net_limit: 1048576,
  server_version_string: 'v1.4.4' }

看到这个结果,表示我们的配置是正确的。

所有的代码如下

const Eos = require('eosjs');

const config = {
    account: {
        contract: "micormsg",   // 合约账号
        from: "xiaoming",       // 发送者账号
        to: "xiaohong"          // 接收者账号
    },
    network: {
        protocol:'http',        // 协议 http or https
        host: 'localhost',      // 远程主机
        port: '8080',           // 远程端口号
        keyProvider:['5J6Ly95q876iEwG1c4bBcWAWqHbibRmhDsxtSrnsSswpT7r7gAC'], // 私钥
        chainId: 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f', // EOS 链 id
        timeout: 10000          // 10s 超时
    }
}

var eos = Eos(config.network);
eos.getInfo({}).then(rs => console.log(rs)).catch(e => console.log(e))
目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.