第十五篇 墨客区块链(MOAC BlockChain) 搭建自己的第一个DAPP

版权声明:Copyright Reserved © 2018-2020 https://blog.csdn.net/lyq13573221675/article/details/81698014

本文平台: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) 开发环境搭建》。

  • 下载并安装git;本文中,安装成功后,仅需配置到环境变量即可;
  • 下载并安装node.js,该步骤会自动安装npm;
  • 安装express;该命令中“express”和“-genetator”之间没有空格;
C:\>npm install -g express
C:\>npm install -g express-generator@4
  • 安装chain3;
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”;

  • 主要是侦听,扮演“Event listener for HTTP server”角色;
  • 一般不用修改,如果需要可以修改端口(默认3000);

node_modules:项目依赖的模块,通过npm install命令加载;

public:公共文件的存放位置,默认把公共文件比如images、javascript、stylesheets等放在该文件夹下面;

routes:express路由;

  • 路由是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET、POST 等)组成的,涉及到应用如何响应客户端对某个网站节点的访问;
  • 每一个路由都可以有一个或者多个处理器函数,当匹配到路由时,这个/些函数将被执行;
  • 可以通过next来控制路由是否向下进行,如果不调用next,则不会向下继续,而调用next则会触发下一个路由;

views:前端页面都放在该文件夹下面;视图的模板引擎是ejs;

app.js:项目入口;使用app.use()来配置中间件,中间件的效果和路由基本一致;

package.json:项目的相关信息,比如项目名称、版本、依赖项等;

package-lock.js:这是一个包锁,匹配package.json;

  • 描述依赖关系树的单一表示,以确保队友,部署和持续集成确保安装完全相同的依赖关系;
  • 为用户提供一个设施,使其能够“前往”以前的node_modules状态而不必提交目录本身;
  • 允许npm跳过先前安装的软件包的重复元数据来优化安装过程。

2.5 流程简单解析

每次重新启动项目,使用命令:

D:\nodeJS_Project\firstApp>npm start
  1. 在浏览器输入localhost:3000发送一个get请求,node服务监听到来自3000端口的请求时就会对这个请求进行处理;
  2. 它会对地址栏的地址和路由规则进行匹配,如果匹配成功它就会返回请求的处理,对相应的页面进行渲染;
  3. 本实例中,启动的是bin\www,后台响应的是routes\index.js,实际显示的是views\index.ejs;
  4. 发送get请求、函数回调和内容显示主要在routes\index.js和views\index.ejs之间进行。

注意: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。实现共建、共享、共赢!

阅读更多

更多精彩内容