前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >蚂蚁区块链第13课 如何搭建一个DAPP应用(以姓名年龄为例)

蚂蚁区块链第13课 如何搭建一个DAPP应用(以姓名年龄为例)

作者头像
辉哥
发布2019-04-18 16:06:11
1.2K0
发布2019-04-18 16:06:11
举报
文章被收录于专栏:区块链入门区块链入门

1,摘要

本文介绍如何使用Cloud IDE完成name-age智能合约的编译,获取其ABI和二进制码信息。 接着,本文介绍基于EXPRESS框架搭建的前端页面,完成已部署智能合约的调用,完成了相关功能的呈现。 本文假设用户已经熟悉蚂蚁BAAS的Cloud IDE和Solidity开发编译,不熟悉的查看辉哥的其他文档完成知识准备。

2,智能合约的开发和部署

2.1 需求和智能合约开发

本需求主要是作为入门级DAPP,主要能读取智能合约中的姓名/年龄信息,同时也能写入更新姓名/年龄。 solidity代码实现如下:

代码语言:javascript
复制
pragma solidity ^0.4.23;

contract InfoContract {
    string name;
    uint age;

    event Instructor(string name, uint age);

    function setInfo(string _name, uint _age) public {
        name = _name;
        age = _age;
        emit Instructor(name, age);
    }

    function getInfo() public view returns(string, uint) {
        return (name, age);
    }
}

2.2 账号切换和编译

Cloud IDE默认的账户为test002,我们并不知道其解密私钥。所以需要在Cloud IDE下切换为用户自己创建的账号,例如辉哥的duncanwang账号,输入其中的解密私钥。 然后点击编译完成智能合约的编译工作。

4. 环境配置-更换账户

不知道怎么产生账号和机密私钥的,可参考文章《蚂蚁区块链第8课 如何创建新的账户,获取私钥和identity标识?》

2.3 部署name-age合约并测试

(1)部署合约

5.部署合约

部署成功后,获得其交易信息:

合约ID: 0xe72056692f46ae2443bbfefaa9ffddc09c8952a488afd345118aa295d85c8aba tx hash: 0x1750e6156b63ada81fb54473fe54a97ef565e3c7fa2123ab9f033dfd7fc01672

(2)测试合约 设置辉哥的姓名为duncanwang,年龄为18岁,先完成setInfo,后调用getInfo,发现结果跟预期一致,智能合约测试完成。

6. 调试合约(duncanwang-18)

记录下HASH信息,便于在浏览器查询:

function setInfo("duncanwang", 18) tx hash: 0x46b2289c4fe175bcd80599e91fa8a55e1822f6280ffc90a4e0bd2af6ee832114

function getInfo tx hash: 0x46b2289c4fe175bcd80599e91fa8a55e1822f6280ffc90a4e0bd2af6ee832114

3,前端页面和代码

前端UI页面如下。

对应的代码(home.ejs)实现:

代码语言:javascript
复制
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<style>
div{
  width: 600px;
    margin: 0 auto;
    font-size: 21px;
}
input{
  width: 300px;
    height: 30px;
    font-size: 20px;
}
.submitBtn{
    width: 100px;
    background: #2196F3;
    color: #fff;
    height: 46px;
    border-radius: 13px;
}
</style>
<body>
<div>
    <h1>This is my homepage</h1>

    <form name="name" method="get">
      <p>姓名: <input type="text" name="fname" value="<%= name[0] %>" /></p>
      <p>年龄: <input type="text" name="age" value="<%= name[1] %>"/></p>
      <input type="submit" class="submitBtn" value="获取" onclick="searchAction()" style="width: 100px;"/>
      <input type="submit" class="submitBtn" value="更新" onclick="updateAction()" style="width: 100px;margin-left: 150px;">
    </form>
    <p><%= name[0] %></p>
    <p><%= name[1] %></p>
    <p><%= info %></p>
</div>

</body>
<script>
  function searchAction(){

    document.name.action="/search";

    document.name.submit();

    }

function updateAction(){

    document.name.action="/update";

    document.name.submit();

    }
</script>
</html>

4, 蚂蚁BAAS SDK调用代码

《JS SDK 快速开始》 讲解了如何通过JS SDK连接BAAS的方法。

代码语言:javascript
复制
let express = require("express");
let app = express();

const Chain = require("@alipay/mychain/index.node") //在 node 环境使用 TLS 协议
const fs = require("fs")
 
const accountKey = fs.readFileSync("./certs/duncanwang-user.pem", { encoding: "utf8" })
const accountPassword = "2018ceshi"  //需要替换为自定义的 user.pem 密码
 
const keyInfo = Chain.utils.getKeyInfo(accountKey, accountPassword)
//可打印私钥和公钥,使用 16 进制
//console.log('private key:', keyInfo.privateKey.toString('hex'))
//console.log('public key:', keyInfo.publicKey.toString('hex'))
 
const passphrase = "2018ceshi" //需要替换为自定义的 client.key 密码
//配置选项
let opt = {
  host: '139.196.136.94',    //目标区块链网络节点的 IP
  port: 18130,          //端口号
  timeout: 30000,       //连接超时时间配置
  cert: fs.readFileSync("./certs/client.crt", { encoding: "utf8" }),
  ca: fs.readFileSync("./certs/ca.crt", { encoding: "utf8" }),
  key: fs.readFileSync("./certs/client.key", { encoding: "utf8" }),
  userPublicKey: keyInfo.publicKey,
  userPrivateKey: keyInfo.privateKey,
  userRecoverPublicKey: keyInfo.publicKey,
  userRecoverPrivateKey: keyInfo.privateKey,
  passphrase: passphrase
}
 
//初始化一个连接实例
const chain = Chain(opt)
 
//调用 API 查询最新的一个区块数据
chain.ctr.QueryLastBlock({}, (err, data) => {
  // console.log('raw data:', data)                                     //区块结构数据
  // console.log('block hash:', data.block.block_header.hash)             //区块哈希
  // console.log('block number:', data.block.block_header.block_number) //区块高度
})

//设置ABI信息
const abi = 
[{"constant":true,"inputs":[],"name":"getInfo","outputs":[{"name":"","type":"string"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_age","type":"uint256"}],"name":"setInfo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"name","type":"string"},{"indexed":false,"name":"age","type":"uint256"}],"name":"Instructor","type":"event"}]
const contractName = "name-age";
const bytecode = "0x608060405234801561001057600080fd5b506103be806100206000396000f30060806040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680635a9b0b89146100515780638262963b146100e8575b600080fd5b34801561005d57600080fd5b5061006661015b565b6040518080602001838152602001828103825284818151815260200191508051906020019080838360005b838110156100ac578082015181840152602081019050610091565b50505050905090810190601f1680156100d95780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156100f457600080fd5b50610159600480360381019080803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919291929080359060200190929190505050610207565b005b6060600080600154818054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101f85780601f106101cd576101008083540402835291602001916101f8565b820191906000526020600020905b8154815290600101906020018083116101db57829003601f168201915b50505050509150915091509091565b816000908051906020019061021d9291906102ed565b50806001819055507f010becc10ca1475887c4ec429def1ccc2e9ea1713fe8b0d4e9a1d009042f6b8e600060015460405180806020018381526020018281038252848181546001816001161561010002031660029004815260200191508054600181600116156101000203166002900480156102da5780601f106102af576101008083540402835291602001916102da565b820191906000526020600020905b8154815290600101906020018083116102bd57829003601f168201915b5050935050505060405180910390a15050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061032e57805160ff191683800117855561035c565b8280016001018555821561035c579182015b8281111561035b578251825591602001919060010190610340565b5b509050610369919061036d565b5090565b61038f91905b8082111561038b576000816000905550600101610373565b5090565b905600a165627a7a723058208ecb5a3721f4deee06f2f384b8ba7b90a47f803f1acbe2ad128b2eebc045bb240029";

// 初始化一个合约实例
let myContract = chain.ctr.contract(contractName, abi) 

// 部署合约,可传递初始化函数需要的参数
/*
myContract.new(bytecode, {
  from: 'duncanwang',
  // parameters: [param1, param2]
}, (err, contract, data) => {
  console.log(data)
})*/

//调用合约getInfo函数,查看当前用户的姓名和年龄
// myContract.getInfo( { from: 'duncanwang' }, (err, name, age) => {
//     console.log('output is:', name, age)
//   })

//调用合约getInfo函数,查看当前用户的姓名和年龄
// myContract.setInfo( "duncanwang", 20,{ from: 'duncanwang' }, (err,data1,data2) => {
//     console.log('output1 is------>:', data1)
//     console.log('output2 is------>:', data2)
//   })

// 调用合约getInfo函数,查看当前用户的姓名和年龄
// myContract.getInfo( { from: 'duncanwang' }, (err, name, age) => {
//     console.log('output is:', name, age)
//   })  



//初始返回一个home页面
app.get("/", function(req ,res) {
  res.render("home.ejs",{
    name: "",
    info: ''
  });
});

//更新接口
app.get("/update", function(req, res){
  myContract.setInfo( req.query.fname, req.query.age >> 0,{ from: 'duncanwang' }, (err,data) => {
    myContract.getInfo( { from: "duncanwang" }, (err, name, age) => {
      console.log('output is:', name)
      res.render("home.ejs",{
        name: name,
        info: '更新成功'
      });
    })
  })
});
//获取接口
app.get("/search", function(req ,res) {
  myContract.getInfo( { from: "duncanwang" }, (err, name, age) => {
    res.render("home.ejs",{
      name: name,
      info: '获取成功'
    });
  })
});

let server = require('http').createServer(app);
      server.listen(5000);{
        console.log("Sever Ready! open on http://localhost:5000");
      }

说明: (1)accountPassword,passphrase为用户自己的私钥密码。还需要在工程对应的地方存放各种证书文件。 (2)abi,contractName, bytecode都是在Cloud IDE编译部署后产生的。用户也可以通过solcjs编译产生。 (3)节点IP和端口从区块链浏览器处获得。

代码语言:javascript
复制
let opt = {
  host: '139.196.136.94',    //目标区块链网络节点的 IP
  port: 18130,          //端口号
...

4个节点IP以及对一个的端口:

2.节点IP

5,工程

辉哥建立了一个name-age的文件夹,里面的目标结构如下所示。

代码语言:javascript
复制
|   alipay-mychain-0.2.27.tgz
|   app.js
|   
+---certs
|       ca.crt
|       client.crt
|       client.key
|       duncanwang-user.key
|       duncanwang-user.pem
|       package-lock.json
|       tee_rsa_public_key.pem
|       
+---contracts
|       InfoContract.sol
|       
+---node_modules
|               
\---views
        home.ejs

说明下: (1)alipay-mychain-0.2.27.tgz 为蚂蚁的JS-SDK包,解压文件会到node_modules。 (2)app.js 调用JS-SDK的代码。 (3)certs为duncanwang账号对应的各种证书和公私钥文件。 (4)contracts/InfoContract.sol 为name-age智能合约文件。 (5)node_modules的内容很多,为NPM安装的各种依赖包。 (6)views/home.ejs 为采用采用node.js实现的前端页面。

6,运行测试

6.1 安装JS SDK

npm i alipay-mychain-0.2.27.tgz --save

安装成功结果:

1. 安装alipay-mychain

6.2 安装EXPRESS框架

npm install express npm install express-generator

6.3 运行NODE服务器

node app

输出结果:

9.node APP运行

6.4 运行界面

在chrome浏览器上打开网址:http://localhost:5000 点击获取”按钮,可以获得智能合约的姓名/年龄数据; 输入姓名:王登辉,年龄:25,可以更新智能合约的姓名/年龄数据。

就这样,依赖于蚂蚁BAAS的第一个DAPP应用已经产生了。

7, 参考

(1)JS SDK 快速开始 https://tech.antfin.com/docs/2/107128 (2)windows下node.js的安装及express使用命令配置 https://jingyan.baidu.com/article/7f41ecec0e3a25593d095c26.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.04.09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1,摘要
  • 2,智能合约的开发和部署
    • 2.1 需求和智能合约开发
      • 2.2 账号切换和编译
        • 2.3 部署name-age合约并测试
        • 3,前端页面和代码
        • 4, 蚂蚁BAAS SDK调用代码
        • 5,工程
        • 6,运行测试
          • 6.1 安装JS SDK
            • 6.2 安装EXPRESS框架
              • 6.3 运行NODE服务器
                • 6.4 运行界面
                • 7, 参考
                相关产品与服务
                访问管理
                访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档