美文网首页EOS学习日志
搭建EOS水龙头 (Express+MongoDB)

搭建EOS水龙头 (Express+MongoDB)

作者: 那个大螺丝 | 来源:发表于2018-11-01 16:58 被阅读0次
    • 大致思路,在服务器后端绑定一个很有足够多EOS的账户。
    • 接收前端提交过来的用户名和公钥,帮忙在EOS网络上注册账户。
    • 服务端用MVC模型处理请求。
    • 数据库用于储存注册新用户的信息,用户名、公钥匙、费用之类的。
    • 这里使用的是EOS公测网络
    • 总体逻辑不算复杂, 这是全部代码

    MongoDB的设置

    // mongodb安装比较简单,这里就不介绍了, 大致上就是官网下载个安装包,双击运行
    // https://docs.mongodb.com/manual/installation/
    
    // 启动数据库 (窗口不能关)
    // 启动mongodb的时候可能会遇到 /data/db/ 文件夹权限不够的情况,运行以下命令提权
    // sudo chmod -R 0777 /data/db
    $ mongod
    
    // 开启另外一个命令行窗口,进入数据库
    $ mongo
    
    // 创建一个名为 faucet 的数据库
    use faucet 
    
    // 创建一个名为 faucet 的集合
    db.createCollection('faucet')
    
    // 切换至admin数据库
    use admin
    
    // 创建admin数据库管理员,只是为了方便以后管理,不一定需要设置。
    // 用户名tmd,密码123,权限:读写、用户管理
    db.createUser({user:'tmd',pwd:'123',roles:[{role:'readWrite',db:'admin'},{role:'userAdminAnyDatabase',db:'admin'}]})
    
    // 创建faucet数据库的可读写账号
    // 要记住自己创建的用户与密码
    db.createUser({user:'eos',pwd:'eos',roles:[{role:'readWrite',db:'faucet'}]})
    
    

    到目前为止,数据库设置大致完成,现在需要把刚刚开启mongod 和 mongo 进程关闭,带认证参数重新启动一次

    // --auth 参数是设置  (窗口不能关)
    $ mongod --auth
    
    // 如果是在linux环境下运行
    // 编辑 /etc/mongod.conf文件,mongodb默认的配置文件
    // 修改以下代码,设置成enabled。(这是3.0以上版的设置方式,旧版本就不介绍了)
    
    security:
        authorization: "enabled"
    
    // linux环境下,在后台启动mongodb (窗口可以关)
    $ sudo service mongod start
    
    // 开启一个新命令行窗口进入数据库
    $ mongo
    
    // 进入数据库后,账号都需要进入admin数据库中进行验证, 
    use admin
    
    // 这里输入刚才设置的用户名和密码,如果返回1表示认证通过
    db.auth('eos','eos')
    
    // 切换至faucet数据库
    use faucet
    
    // 展示集合,一切顺利的话会展示集合列表
    show collections
    
    

    mongodb数据库设置完成

    附录

    mongodb配置文件设置
    https://docs.mongodb.com/manual/reference/configuration-options/


    Express安装与项目初始化

    // 全局安装一个 express-generator
    $ npm install express-generator -g
    
    // 初始化一个名为eos_faucet的项目
    $ express eos_faucet
    
    // 安装依赖包
    $ cd eos_faucet
    $ npm install eosjs@beta node-fetch text-encoding eosjs-ecc
    
    • 编辑/eos_faucet/app.js文件,
    //  在所有路由前面,设置允许跨域请求
    app.all('*', function(req, res, next) {
      res.header("Access-Control-Allow-Origin", "*");
      res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
      res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
      res.header("X-Powered-By",' 3.2.1');
      res.header("Content-Type", "application/json;charset=utf-8");
      next();
    });
    
    • 编辑/eos_faucet/routes/index.js文件
    const express = require('express');
    const router = express.Router();
    const registerController = require('../controllers/register');
    
    /* 保留get请求,测试服务器成功开启. */
    router.get('/', function(req, res) {
      res.send('you shall not pass')
    });
    
    // 增加一个post请求的路由,用于处理注册请求
    router.post('/',registerController.register);
    
    module.exports = router;
    
    • 创建并编辑 /eos_faucet/controllers/register.js文件
    • 以下api调用涉及到eosjs库的调用,如果不熟悉请参考我的前一篇文章 NODE.JS 调用EOS API
    const { Api, JsonRpc, JsSignatureProvider } = require('eosjs');
    const fetch = require('node-fetch');
    const { TextDecoder, TextEncoder } = require('text-encoding');
    const registerModel = new require('../models/register');
    // 设置一个账号,用于创建账号的,这个账号一定是存在并且有足够的EOS在里面的。
    const admin = 'tmd555555555';
    // 账号的私钥
    const privateKey = "5KX4fnaQWhc6Coz9uqk9GWkjiA8q8R8ditSTDjKcHqsHCwnhJpR";
    const signatureProvider = new JsSignatureProvider([privateKey]);
    const rpc = new JsonRpc('http://junglehistory.cryptolions.io:18888', { fetch });
    const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() });
    
    exports.register = async (req, res) => {
      try{
        const result = await api.transact({
          actions: [{
            account: 'eosio',
            name: 'newaccount',
            authorization: [{
              actor: admin,
              permission: 'active',
            }],
            data: {
              creator: admin,
              name: req.body.username,
              newact:req.body.username,
              owner: {
                threshold: 1,
                keys: [{
                  key: req.body.publicKey,
                  weight: 1
                }],
                accounts: [],
                waits: []
              },
              active: {
                threshold: 1,
                keys: [{
                  key: req.body.publicKey,
                  weight: 1
                }],
                accounts: [],
                waits: []
              },
            },
          }, {
            account: 'eosio',
            name: 'buyrambytes',
            authorization: [{
              actor: admin,
              permission: 'active',
            }],
            data: {
              payer: admin,
              receiver: req.body.username,
              bytes: 3000,
            },
          }, {
            account: 'eosio',
            name: 'delegatebw',
            authorization: [{
              actor: admin,
              permission: 'active',
            }],
            data: {
              from: admin,
              receiver: req.body.username,
              stake_net_quantity: '1.0000 EOS',
              stake_cpu_quantity: '1.0000 EOS',
              transfer: false,
            }
          }]
        }, {
          blocksBehind: 3,
          expireSeconds: 30,
        });
        // 合约运行成功后把结果发给前端。
        res.send(JSON.stringify(result))
    
      }catch(err){
        // 如果运行失败,把错误信息返回给前端。并且退出函数。
        if(!!err.json){
          res.send(JSON.stringify(err.json));
        }else{
          res.send(JSON.stringify(err));
        }
        return;
      }
    
      // 如果运行成功,把新用户信息存入数据库。运行失败的话,不会执行到这一步。
      await registerModel.create({
        username: req.body.username,
        publicKey: req.body.publicKey,
        creator: admin,
        cost:'',
        bytes:3000
      });
    };
    
    • 创建并编辑/eos_faucet/models/register.js
    const mongoose = require('mongoose');
    // 用账号和密码登录连接数据库,eos:eos这里的账号和密码都是eos,
    // 地址127.0.0.1,mongodb默认设置了只能本地访问
    // faucet,表示连接到faucet这个数据库
    // 数据库的账号名是在admin数据库中建立的 所以需要添加 ?authSource=admin
    mongoose.connect('mongodb://eos:eos@127.0.0.1/faucet?authSource=admin',{ useNewUrlParser: true } );
    mongoose.Promise = global.Promise;
    
    // 设置schema,虽然mongodb是非关系型数据库,但是一般都会给它设置模式
    const registerSchema = new mongoose.Schema({
      username:String,
      publicKey:String,
      creator: String,
      cost:String,
      bytes:Number,
      // 创建日期,默认值写成当前时间
      date:{type:Date, default:new Date()}
    });
    
    // 设置静态方法,给外外层调用
    registerSchema.statics.save = async function({username, publicKey, creator, cost, bytes}){
      return this.create({username, publicKey, creator, cost, bytes})
    };
    
    // 三个参数,第一个只是schema的名字,可以随便写,第二个是schema对象,第三个是数据库中集合的名字
    module.exports = mongoose.model('register', registerSchema, 'faucet');
    
    
    • 到目前Express设置完成,可以跑起来了
    • 注意:服务器的端口可以在./bin/www设置,我把端口设置了5000
    • 如果在产品环境运行,可以用pm2做进程守护,并且打开多线程模式,提高性能。
      如果不了解,可以参考我这篇文章 部署node服务器到产品环境
    // 只用于本地测试
    $ npm start
    
    // 产品环境开启进程守护和多线程
    $ pm2 start ./bin/www -i max --env production
    

    you shall not pass

    在浏览器测试服务器是否开启成功,成功展示我们设置文本you shall not pass,表示服务器已经正常开启

    success

    在postman测试一下请求,并收到成功的返回信息,表示流程没问题。

    QQ20181101-164850@2x.png

    mongo shell 中运行db.faucet.find({},{_id:0,__v:0}).sort({date:-1}).pretty()查到最近一条记录是我刚刚在前端请求存入的信息,说明储存流程没问题。

    最后附上 项目全部代码

    相关文章

      网友评论

        本文标题:搭建EOS水龙头 (Express+MongoDB)

        本文链接:https://www.haomeiwen.com/subject/oolwtqtx.html