- 大致思路吐葱,在服務(wù)器后端綁定一個(gè)很有足夠多EOS的賬戶盒延。
- 接收前端提交過(guò)來(lái)的用戶名和公鑰,幫忙在EOS網(wǎng)絡(luò)上注冊(cè)賬戶滤港。
- 服務(wù)端用MVC模型處理請(qǐng)求廊蜒。
- 數(shù)據(jù)庫(kù)用于儲(chǔ)存注冊(cè)新用戶的信息,用戶名溅漾、公鑰匙山叮、費(fèi)用之類的。
- 這里使用的是EOS公測(cè)網(wǎng)絡(luò)
- 總體邏輯不算復(fù)雜添履, 這是全部代碼屁倔。
MongoDB的設(shè)置
// mongodb安裝比較簡(jiǎn)單,這里就不介紹了, 大致上就是官網(wǎng)下載個(gè)安裝包,雙擊運(yùn)行
// https://docs.mongodb.com/manual/installation/
// 啟動(dòng)數(shù)據(jù)庫(kù) (窗口不能關(guān))
// 啟動(dòng)mongodb的時(shí)候可能會(huì)遇到 /data/db/ 文件夾權(quán)限不夠的情況暮胧,運(yùn)行以下命令提權(quán)
// sudo chmod -R 0777 /data/db
$ mongod
// 開(kāi)啟另外一個(gè)命令行窗口汰现,進(jìn)入數(shù)據(jù)庫(kù)
$ mongo
// 創(chuàng)建一個(gè)名為 faucet 的數(shù)據(jù)庫(kù)
use faucet
// 創(chuàng)建一個(gè)名為 faucet 的集合
db.createCollection('faucet')
// 切換至admin數(shù)據(jù)庫(kù)
use admin
// 創(chuàng)建admin數(shù)據(jù)庫(kù)管理員,只是為了方便以后管理叔壤,不一定需要設(shè)置。
// 用戶名tmd口叙,密碼123炼绘,權(quán)限:讀寫(xiě)、用戶管理
db.createUser({user:'tmd',pwd:'123',roles:[{role:'readWrite',db:'admin'},{role:'userAdminAnyDatabase',db:'admin'}]})
// 創(chuàng)建faucet數(shù)據(jù)庫(kù)的可讀寫(xiě)賬號(hào)
// 要記住自己創(chuàng)建的用戶與密碼
db.createUser({user:'eos',pwd:'eos',roles:[{role:'readWrite',db:'faucet'}]})
到目前為止妄田,數(shù)據(jù)庫(kù)設(shè)置大致完成俺亮,現(xiàn)在需要把剛剛開(kāi)啟mongod 和 mongo 進(jìn)程關(guān)閉,帶認(rèn)證參數(shù)重新啟動(dòng)一次
// --auth 參數(shù)是設(shè)置 (窗口不能關(guān))
$ mongod --auth
// 如果是在linux環(huán)境下運(yùn)行
// 編輯 /etc/mongod.conf文件疟呐,mongodb默認(rèn)的配置文件
// 修改以下代碼脚曾,設(shè)置成enabled。(這是3.0以上版的設(shè)置方式启具,舊版本就不介紹了)
security:
authorization: "enabled"
// linux環(huán)境下本讥,在后臺(tái)啟動(dòng)mongodb (窗口可以關(guān))
$ sudo service mongod start
// 開(kāi)啟一個(gè)新命令行窗口進(jìn)入數(shù)據(jù)庫(kù)
$ mongo
// 進(jìn)入數(shù)據(jù)庫(kù)后,賬號(hào)都需要進(jìn)入admin數(shù)據(jù)庫(kù)中進(jìn)行驗(yàn)證,
use admin
// 這里輸入剛才設(shè)置的用戶名和密碼,如果返回1表示認(rèn)證通過(guò)
db.auth('eos','eos')
// 切換至faucet數(shù)據(jù)庫(kù)
use faucet
// 展示集合,一切順利的話會(huì)展示集合列表
show collections
mongodb數(shù)據(jù)庫(kù)設(shè)置完成
附錄
mongodb配置文件設(shè)置
https://docs.mongodb.com/manual/reference/configuration-options/
Express安裝與項(xiàng)目初始化
// 全局安裝一個(gè) express-generator
$ npm install express-generator -g
// 初始化一個(gè)名為eos_faucet的項(xiàng)目
$ express eos_faucet
// 安裝依賴包
$ cd eos_faucet
$ npm install eosjs@beta node-fetch text-encoding eosjs-ecc
- 編輯
/eos_faucet/app.js
文件萌腿,
// 在所有路由前面拖刃,設(shè)置允許跨域請(qǐng)求
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請(qǐng)求荔燎,測(cè)試服務(wù)器成功開(kāi)啟. */
router.get('/', function(req, res) {
res.send('you shall not pass')
});
// 增加一個(gè)post請(qǐng)求的路由,用于處理注冊(cè)請(qǐng)求
router.post('/',registerController.register);
module.exports = router;
- 創(chuàng)建并編輯
/eos_faucet/controllers/register.js
文件 - 以下api調(diào)用涉及到eosjs庫(kù)的調(diào)用秧了,如果不熟悉請(qǐng)參考我的前一篇文章 NODE.JS 調(diào)用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');
// 設(shè)置一個(gè)賬號(hào),用于創(chuàng)建賬號(hào)的序无,這個(gè)賬號(hào)一定是存在并且有足夠的EOS在里面的验毡。
const admin = 'tmd555555555';
// 賬號(hào)的私鑰
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,
});
// 合約運(yùn)行成功后把結(jié)果發(fā)給前端。
res.send(JSON.stringify(result))
}catch(err){
// 如果運(yùn)行失敗帝嗡,把錯(cuò)誤信息返回給前端晶通。并且退出函數(shù)。
if(!!err.json){
res.send(JSON.stringify(err.json));
}else{
res.send(JSON.stringify(err));
}
return;
}
// 如果運(yùn)行成功丈探,把新用戶信息存入數(shù)據(jù)庫(kù)录择。運(yùn)行失敗的話,不會(huì)執(zhí)行到這一步碗降。
await registerModel.create({
username: req.body.username,
publicKey: req.body.publicKey,
creator: admin,
cost:'',
bytes:3000
});
};
- 創(chuàng)建并編輯
/eos_faucet/models/register.js
const mongoose = require('mongoose');
// 用賬號(hào)和密碼登錄連接數(shù)據(jù)庫(kù)隘竭,eos:eos這里的賬號(hào)和密碼都是eos,
// 地址127.0.0.1讼渊,mongodb默認(rèn)設(shè)置了只能本地訪問(wèn)
// faucet动看,表示連接到faucet這個(gè)數(shù)據(jù)庫(kù)
// 數(shù)據(jù)庫(kù)的賬號(hào)名是在admin數(shù)據(jù)庫(kù)中建立的 所以需要添加 ?authSource=admin
mongoose.connect('mongodb://eos:eos@127.0.0.1/faucet?authSource=admin',{ useNewUrlParser: true } );
mongoose.Promise = global.Promise;
// 設(shè)置schema,雖然mongodb是非關(guān)系型數(shù)據(jù)庫(kù)爪幻,但是一般都會(huì)給它設(shè)置模式
const registerSchema = new mongoose.Schema({
username:String,
publicKey:String,
creator: String,
cost:String,
bytes:Number,
// 創(chuàng)建日期菱皆,默認(rèn)值寫(xiě)成當(dāng)前時(shí)間
date:{type:Date, default:new Date()}
});
// 設(shè)置靜態(tài)方法,給外外層調(diào)用
registerSchema.statics.save = async function({username, publicKey, creator, cost, bytes}){
return this.create({username, publicKey, creator, cost, bytes})
};
// 三個(gè)參數(shù)挨稿,第一個(gè)只是schema的名字仇轻,可以隨便寫(xiě),第二個(gè)是schema對(duì)象奶甘,第三個(gè)是數(shù)據(jù)庫(kù)中集合的名字
module.exports = mongoose.model('register', registerSchema, 'faucet');
- 到目前Express設(shè)置完成篷店,可以跑起來(lái)了
- 注意:服務(wù)器的端口可以在
./bin/www
設(shè)置,我把端口設(shè)置了5000
- 如果在產(chǎn)品環(huán)境運(yùn)行臭家,可以用
pm2
做進(jìn)程守護(hù)疲陕,并且打開(kāi)多線程模式,提高性能钉赁。
如果不了解蹄殃,可以參考我這篇文章 部署node服務(wù)器到產(chǎn)品環(huán)境
// 只用于本地測(cè)試
$ npm start
// 產(chǎn)品環(huán)境開(kāi)啟進(jìn)程守護(hù)和多線程
$ pm2 start ./bin/www -i max --env production
you shall not pass
在瀏覽器測(cè)試服務(wù)器是否開(kāi)啟成功,成功展示我們?cè)O(shè)置文本you shall not pass
你踩,表示服務(wù)器已經(jīng)正常開(kāi)啟
success
在postman測(cè)試一下請(qǐng)求诅岩,并收到成功的返回信息讳苦,表示流程沒(méi)問(wèn)題。
QQ20181101-164850@2x.png
mongo shell 中運(yùn)行db.faucet.find({},{_id:0,__v:0}).sort({date:-1}).pretty()
查到最近一條記錄是我剛剛在前端請(qǐng)求存入的信息按厘,說(shuō)明儲(chǔ)存流程沒(méi)問(wèn)題医吊。