本文平台:MOAC Nuwa v1.0.2
操作系统:64位 Windows 10 中文版
开发环境:node.js v8.11.1 + npm v5.6.0 + express v4.16.0 + chain3
1.开发环境
1.1 安装moac节点
请参考文档《第三篇 墨客区块链(MOAC BlockChain) 节点安装教程》。
启动节点使用命令:
D:\nuwa1.0.2.win>moac --rpc
1.2 安装开发环境
请参考文档《第七篇 墨客区块链(MOAC BlockChain) 开发环境搭建》。
C:\>npm install -g express
C:\>npm install -g express-generator@4
C:\>npm install -g chain3 //Node.js
2.创建项目
2.1 创建express项目
D:\>cd D:\nodeJS_Project
D:\nodeJS_Project>express -e firstApp
2.2 按提示做三步
第1步.进入目录(change directory)
D:\nodeJS_Project>cd firstApp
第2步.安装依赖(install dependencies)
D:\nodeJS_Project\firstApp>npm install
第3步.运行app(run the app)
D:\nodeJS_Project\firstApp>SET DEBUG=nodeProject1:* & npm start
2.3 到浏览器查看
表示项目创建成功。
2.4 项目简单解析
经过以上步骤,目录显示为:
bin\www:启动项,在package.json中定义的“start”;
node_modules:项目依赖的模块,通过npm install命令加载;
public:公共文件的存放位置,默认把公共文件比如images、javascript、stylesheets等放在该文件夹下面;
routes:express路由;
views:前端页面都放在该文件夹下面;视图的模板引擎是ejs;
app.js:项目入口;使用app.use()来配置中间件,中间件的效果和路由基本一致;
package.json:项目的相关信息,比如项目名称、版本、依赖项等;
package-lock.js:这是一个包锁,匹配package.json;
node_modules
状态而不必提交目录本身;2.5 流程简单解析
每次重新启动项目,使用命令:
D:\nodeJS_Project\firstApp>npm start
注意:1、本文即依据这些简单的express框架知识,实现第一个DAPP的构建;
2、本文的DAPP实现将自定义数据写入墨客区块链,并能依据返回的hash值读出已经写入区块链中的内容。有关此处的内容及代码主要参考《第十篇 墨客区块链(MOAC BlockChain) 如何将自定义数据写到区块链中》。
3.将自定义数据写入区块链
3.1 下载 jquery.min.js
本实例中会用到jquery.min.js,下载该文件放到目录:D:\nodeJS_Project\firstApp\public\javascripts。
3.2 将数据写入区块链的js文件
将sendDataToBlockchain.js文件放到目录:D:\nodeJS_Project\firstApp\routes。
var Chain3 = require('chain3');
var chain3 = new Chain3(new Chain3.providers.HttpProvider('http://localhost:8545'));
var address = "0x745c57ca5318093115d61bbca368XXXXXXXXXXXX";
var account = {address:"0x745c57ca5318093115d61bbca368XXXXXXXXXXXX",secret:"bb673026deda3c3cd0c63f6ccddfb02a7ae320078aa8XXXXXXXXXXXXXXXXXXXX"};
//该函数用于回调,取得前端要发送上链的数据message,并返回hash
exports.sendMessage = function(message) {
return send(message, chain3, account.address, account.secret, txCount = -1);
}
function send(message, chain3, fromAddress, fromSecret, txCount = -1){
var mc = chain3.mc;
var txcount = txCount >= 0 ? txCount : chain3.mc.getTransactionCount(fromAddress);
console.log("Get tx account", chain3.mc.getTransactionCount(fromAddress));
console.log("Get tx account", txcount);
var gasPrice = 25000000000;
var gasLimit = 100000;
var gasTotal = gasPrice * gasLimit;
//console.log(gasPrice, gasLimit, chain3.fromSha(gasTotal, 'sha'));
//以下定义写入数据log
let log = {
time:(new Date).getTime(),
type:"info",
msg:message
};
//转换log数据格式
let str = JSON.stringify(log);
console.log(str);
let data = Buffer.from(str).toString('hex');
data = '0x'+data;
console.log(data);
var rawTx = {
from: fromAddress,
//to: toAddress,
nonce: chain3.intToHex(txcount),
gasPrice: chain3.intToHex(gasPrice),
gasLimit: chain3.intToHex(gasLimit),
//value: chain3.intToHex(value),
data: data ,
shardingFlag: 0, //default is global contract
chainId: chain3.version.network
};
var signedTx = chain3.signTransaction(rawTx, fromSecret);
return new Promise (function(resolve, reject){ //用于异步函数回调
mc.sendRawTransaction(signedTx, function(err, hash) {
if (!err){
console.log("succeed: ", hash);
resolve(hash);
}else{
console.log("error:", err);
console.log('raw tx:', rawTx);
reject(err);
}
});
})
}
3.3 修改后端代码
将D:\nodeJS_Project\firstApp\routes目录下的index.js文件增加交互功能。
var express = require('express');
var router = express.Router();
//引入发送数据方法,就是3.2步骤中的sendDataToBlockchain.js
var sendData = require('./sendDataToBlockchain.js');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
/* POST message ,return hash. */
//接口'/api/sendData'与前端views\index.ejs交互
//调用sendMessage,发送req.body.text,并返回hash
router.post('/api/sendData', function(req, res, next) {
//发送完成后,异步回调
sendData.sendMessage(req.body.text).then(function(hash){
res.send({hash: hash});
})
});
module.exports = router;
3.4 修改前端代码
将D:\nodeJS_Project\firstApp\views目录下的index.ejs文件增加交互功能。
该代码中引入3.1节的jquery.min.js。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div style="margin-bottom:10px;">上链内容:</div>
<input id="text" style="width:500px;height:20px;"></input>
<button onclick="onSend()">发送</button>
<br/>
<div id="result"></div>
</body>
<script src="/javascripts/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
function onSend() {
$.ajax({
type: 'POST',
url: '/api/sendData', //与后端routes\index.js交互接口
data: {
text: $('#text').val()
},
success: function (result) { //成功回调方法
$('#result').html("hash:"+result.hash);
},
error: function () { //失败回调方法
}
});
}
</script>
</html>
3.5 实测发送数据
启动本地节点:
D:\nuwa1.0.2.win>moac --rpc
启动本地项目:
D:\nodeJS_Project\firstApp>npm start
登录浏览器:
输入上链内容,比如“hello,world!”,点击按钮发送:
返回hash值,到浏览器查询该hash:
显示已经正确写到区块链上,使用《第十篇 墨客区块链(MOAC BlockChain) 如何将自定义数据写到区块链中》的代码读出并解析内容,结果如下:
4.读取区块链上的数据
注意:此处数据特指本文第三节写入到区块链交易的data字段中的数据。
4.1 增加功能配置
在app.js里增加定义该功能的模块。
var getDataRouter = require('./routes/getData');
app.use('/getData', getDataRouter);
4.2 读取区块链数据的js文件
将getDataFromBlockchain.js文件放到目录:D:\nodeJS_Project\firstApp\routes。
var Chain3 = require('chain3');
var chain3 = new Chain3(new Chain3.providers.HttpProvider('http://localhost:8545'));
exports.getMessage = function(hash) {
var receipt = chain3.mc.getTransaction(hash);
res_str = Buffer.from(receipt.input.replace('0x',''),'hex').toString();
res_json = JSON.parse(res_str);
console.log('get transaction from hash :'+ JSON.stringify(receipt));
return res_json.msg;
}
4.3 后端代码
在D:\nodeJS_Project\firstApp\routes目录下新建getData.js文件。
var express = require('express');
var router = express.Router();
//引入解析数据方法,就是4.1步骤中的getDataFromBlockchain.js
var callData = require('./getDataFromBlockchain.js');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('getData', { title: 'Express', moac:'hello moac'});
});
/* POST hash ,return message. */
//接口'/api/getData'与前端views\getData.ejs交互
//调用getMessage,发送req.body.text,并返回message
router.post('/api/getData', function(req, res, next) {
res.send({message:callData.getMessage(req.body.text)});
});
module.exports = router;
4.4 前端代码
在D:\nodeJS_Project\firstApp\views目录下新建getData.ejs文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div style="margin-bottom:10px;">查询哈希:</div>
<input id="text" style="width:500px;height:20px;"></input>
<button onclick="onSend()">发送</button>
<br/>
<div id="result"></div>
</body>
<script src="/javascripts/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
function onSend() {
$.ajax({
type: 'POST',
url: '/getData/api/getData', //与后端routes\getData.js交互接口
data: {
text: $('#text').val()
},
success: function (result) { //成功回调方法
$('#result').html("message:"+result.message);
},
error: function () { //失败回调方法
}
});
}
</script>
</html>
4.5 实测读取数据
注意:后端修改后需要重新启动项目。
D:\nodeJS_Project\firstApp>npm start
登录浏览器:
输入hash值,比如“0x57e0a3aa859402499a211113bda757466b15aee18cd9613228406eee7fc16ce7”,点击按钮发送:
立即得到结果,与第3节的上链数据吻合。
墨客(MOAC)作为开放、对DAPP友好的底层区块链平台,欢迎大家来开发自己的DAPP。实现共建、共享、共赢!