美文网首页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