手把手教你开发一款基于星云链的DAPP

发布时间:2018年10月16日 价值:20000.00 / 共识:30

最近因为星云链主网上线推出的星云激励计划,导致nas的价格一定拉升,肯定有不少朋友感觉幸运链的DAPP挺神秘的,其实不然,这里手把手教你如何开发一款基于星云链的dapp。

星云链主页:https://nebulas.io/cn/index.html

哪类人群适合阅读本教程呢?

只要您具备 JavaScript 、 HTML 和 CSS一些基础知识,您就可以阅读本教程,进而开发出一款基于星云链的dapp。

话不多说,直接上截图:

屏幕快照 2018-05-14 下午7.26.50.png

背景图片是可以轮播变换的,这时候想象下放些从恋爱时约会、求婚、结婚、生娃、老年陪伴的图片做背景图,循环播放是不是很有感觉呢。

好了,上代码前先附上我的目录结构:

屏幕快照 2018-05-14 下午8.05.53.png

其中 lib 文件夹中的nebPay.js. 和nebulas.js 需要下载

1. 合约编写

跟以太坊类似,Nebulas实现了NVM虚拟机来运行智能合约,NVM的实现使用了JavaScript V8引擎,所以当前的开发版,我们可以使用JavaScript、TypeScript来编写智能合约。

编写智能合约的简要规范:

  1. 智能合约代码必须是一个Prototype的对象;

  2. 智能合约代码必须有一个init()的方法,这个方法只会在部署的时候被执行一次;

  3. 智能合约里面的私有方法是以_开头的方法,私有方法不能被外部直接调用;

定义文件:contract.js

  1. "use strict";
  2. // 合约 n1eMo1ANL5DymS7saJz67ou1Z7kRTCGoULU
  3. // hash ea3f9680c61b93262e9e031b82e676312dc53dbf82119de317bbc0af5b3b1a63
  4. // 作为单独的类,封装一些参数,这些参数都是页面提交过来或者想展示到页面上的集合体
  5. var LoveInfo = function (arrys) {
  6. if (arrys) {
  7. var obj = JSON.parse(arrys);
  8. this.mn = obj.mn;
  9. this.wm = obj.wm;
  10. this.ai = obj.ai;
  11. this.now = obj.now;
  12. this.author = obj.author;
  13. } else {
  14. this.mn = "";
  15. this.wm = "";
  16. this.ai = "";
  17. this.now = "";
  18. this.author = "";
  19. }
  20. };
  21. // 定义方法,转换成字符串
  22. LoveInfo.prototype = {
  23. toString: function () {
  24. return JSON.stringify(this);
  25. }
  26. };
  27. // 结婚登记
  28. var Married = function () {
  29. // LocalContractStorage.defineMapProperty是合约存储区内定义好的方法,可以直接使用,如果有小伙伴不知道怎么使用的话下面会给个链接讲解,很容易理解的
  30. // 简单的理解就是给当前合约申明了一个属性叫love,然后love内部又有两个方法,parse和stringify对应着从区块链读取数据,后面操作区块链可以直接使用this.love调用对应的存取方法完成操作
  31. LocalContractStorage.defineMapProperty(this, "love", {
  32. parse : function (arrys) {
  33. return new LoveInfo(arrys)
  34. },
  35. stringify: function (res) {
  36. return res.toString()
  37. }
  38. });
  39. };
  40. // 合约内定义的方法
  41. Married.prototype = {
  42. init: function() {
  43. },
  44. // 保存到区块链的方法 需要传递的三个参数,男人名字,女人名字,爱情宣言,当前时间
  45. save: function(mn,wm,ai,now) {
  46. // 做去空格处理
  47. mn = mn.trim();
  48. wm = wm.trim();
  49. ai = ai.trim();
  50. now = now.trim();
  51. // 空字符串处理
  52. if (mn === "" || mn === "" || mn === "" || mn === "") {
  53. throw new Error("请检查登记信息,禁止登记空信息")
  54. }
  55. if (ai.length > 1024) {
  56. throw new Error("可能你们彼此只想说一句简单的'我爱你'")
  57. }
  58. // 获取添加来自哪个地址
  59. var from = Blockchain.transaction.from;
  60. // 这里我们设定的key是两个名字加一起的字符串
  61. var loveInfo = this.repo.get(mn+wm);
  62. // 如果链上有信息,说明保存过,返回提示信息
  63. if (loveInfo) {
  64. throw new Error("信息已存在链上,可直接查看婚姻状况")
  65. }
  66. // 没有信息就添加到区块链中
  67. loveInfo = new LoveInfo();
  68. loveInfo.mn = mn;
  69. loveInfo.wm = wm;
  70. loveInfo.now = now;
  71. loveInfo.ai = ai;
  72. loveInfo.author = from;
  73. // 保存
  74. this.love.put(mn + wm, loveInfo);
  75. }
  76. // 从区块链获取的方法 我这里定义的是两个参数,拼接在一起就是要从区块链查询的key值了
  77. get: function (mn,wm) {
  78. mn = mn.trim();
  79. wm = wm.trim();
  80. if (mn === "") {
  81. throw new Error("男方姓名不能为空")
  82. }
  83. if ( wm === "" ) {
  84. throw new Error("女方姓名不能为空")
  85. }
  86. return this.love.get(mn+wm);
  87. }
  88. };
  89. module.exports = Married;

如果对上面调用的 LocalContractStorage.defineMapProperty 不太理解的可以点击下面的链接,有详细解释

智能合约存储区:https://github.com/nebulasio/wiki/blob/master/tutorials/%5B%E4%B8%AD%E6%96%87%5D%20Nebulas%20101%20-%2004%20%E6%99%BA%E8%83%BD%E5%90%88%E7%BA%A6%E5%AD%98%E5%82%A8%E5%8C%BA.md

这样只能合约就写好了,是不是很简单,接下来就是部署了,部署方法也很简单,如果有不会的可以查看我前面写的文章

使用星云WEB钱包部署合约:https://www.jianshu.com/p/9c990453767c

提示:如果你们去看其他已提交的基于星云的dapp,合约都大同小异,唯一不同的就是前端页面的变化,所以,如果你的前端技术不错的话,完全可以写出几十种不同的DAPP,

2 页面编写

我这里使用到了bootstrap

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>婚姻登记所</title>
  6. <script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
  7. <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  8. <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  9. <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  10. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  11. <link href="assets/css/bootstrap-responsive.css" rel="stylesheet">
  12. <!--这是我自定义的css文件,用来实现页面的一些效果 -->
  13. <link rel="stylesheet" href="css/style.css">
  14. </head>
  15. <body>
  16. <!-- <div class="div01">
  17. <div class="search">
  18. 男方姓名:<input id="mn" class="input-xlarge" type="text" placeholder="username"><br />
  19. 女方姓名:<input id="wm" class="input-xlarge" type="text" placeholder="username"><br />
  20. 爱情宣言:<br /><textarea rows="3" id = "ai"></textarea><br />
  21. <button id="add" class="btn btn-large btn-block btn-primary" type="button">登记</button>
  22. </div>
  23. </div> -->
  24. <div class="div01">
  25. <div class="form row">
  26. <div class="form-horizontal col-md-offset-3" id="login_form">
  27. <h3 class="form-title">婚姻登记</h3>
  28. <div class="col-md-9">
  29. <div class="form-group">
  30. <!--<i class="fa fa-user fa-lg"></i>-->
  31. 男方姓名:<input class="form-control required" type="text" placeholder="man name" id="mn" name="username" autofocus="autofocus" maxlength="20"/>
  32. </div>
  33. <div class="form-group">
  34. <!--<i class="fa fa-user fa-lg"></i>-->
  35. 女方姓名:<input class="form-control required" type="text" placeholder="woman name" id="wm" name="username" autofocus="autofocus" maxlength="20"/>
  36. </div>
  37. <div class="form-group">
  38. <!--<i class="fa fa-apple fa-lg"></i>-->
  39. 爱情宣言:
  40. <textarea maxlength="120"></textarea>
  41. </div>
  42. <div class="form-group col-md-offset-9">
  43. <button class="btn btn-large btn-block btn-primary" type="button" id = 'add'>登记结婚</button>
  44. </div>
  45. </div>
  46. </div>
  47. </div>
  48. </div>
  49. <script src=lib/nebPay.js></script>
  50. <script src=lib/nebulas.js></script>
  51. <script>
  52. "use strict";
  53. <!--合约地址-->
  54. var dappAddress = "n1eMo1ANL5DymS7saJz67ou1Z7kRTCGoULU";
  55. // 导包 nebulas 的 API
  56. var nebulas = require("nebulas"),
  57. // 账户
  58. Account = nebulas.Account,
  59. //neb:一套API
  60. neb = new nebulas.Neb();
  61. // 设置网络:主网 测试网 本地网 这里使用的是测试网,所以部署合约的时候就要把合约部署到测试网上
  62. neb.setRequest(new nebulas.HttpRequest("https://testnet.nebulas.io"));
  63. // 添加数据,需要支付手续费 这里导包
  64. var NebPay = require("nebpay"); //https://github.com/nebulasio/nebPay
  65. var nebPay = new NebPay();
  66. var serialNumber
  67. var intervalQuery
  68. // 添加信息功能: 像合约中添加婚姻登记信息
  69. $("#add").click (() => {
  70. // 获取当前时间
  71. function p(s) {
  72. return s < 10 ? '0' + s: s;
  73. }
  74. var myDate = new Date();
  75. // 获取当前年
  76. var year = myDate.getFullYear();
  77. // 获取当前月
  78. var month = myDate.getMonth()+1;
  79. // 获取当前日
  80. var date = myDate.getDate();
  81. var h = myDate.getHours(); // 获取当前小时数(0-23)
  82. var m = myDate.getMinutes(); // 获取当前分钟数(0-59)
  83. var s = myDate.getSeconds();
  84. var now = year+'-'+p(month)+"-"+p(date)+" "+p(h)+':'+p(m)+':'+p(s);
  85. console.log(now);
  86. // 合约地址
  87. var to = dappAddress;
  88. var value = "0";
  89. // 调用的合约内哪个方法
  90. var callFunction = "save";
  91. // 发送的参数
  92. var callArgs = "[ + $("#mn").val() + "," + $("#wm").val() + "," + $("#ai").val()+ "," + now + "]"
  93. // 调用nebpay自带的方法,开始往区块链添加数据
  94. serialNumber = nebPay.call(to, value, callFunction, callArgs, {
  95. // 使用nebpay的call接口去调用合约,
  96. listener: cbPush
  97. // 设置listener, 处理交易返回信息
  98. });
  99. // 定时器监听交易信息
  100. intervalQuery = setInterval(function () {
  101. funcIntervalQuery();
  102. }, 5000);
  103. });
  104. function funcIntervalQuery() {
  105. nebPay.queryPayInfo(serialNumber).then(function (resp) {
  106. console.log("tx result: " + resp)
  107. var respObject = JSON.parse(resp)
  108. if (respObject.code === 0) {
  109. console.log("已完成登记")
  110. clearInterval(intervalQuery)
  111. }
  112. }).catch(function (err) {
  113. console.log(err);
  114. });
  115. }
  116. function cbPush(resp) {
  117. console.log("response of push: " + JSON.stringify(resp))
  118. }
  119. </script>
  120. </body>
  121. </html>

定义的 style.css 文件

  1. .div01 {
  2. background: url("../img/love01.jpeg");
  3. height: 830px;
  4. animation-name:myPics;
  5. background-size: cover;
  6. animation-duration:30s;
  7. /*变换时间*/
  8. animation-delay:2s;
  9. /*动画开始时间*/
  10. animation-iteration-count:infinite;
  11. /*下一周期循环播放*/
  12. animation-play-state:running;
  13. /*动画开始运行*/
  14. }
  15. /* .search {
  16. width: 50%;
  17. height: 50%;
  18. margin: auto;
  19. }
  20. .search button {*/
  21. /*width: 18%;*/
  22. /*height: 30px;*/
  23. /*margin-left: 6px;*/
  24. /*box-shadow: 3px 5px grey, 1px 1px #333;*/
  25. /*}
  26. @keyframes myPics
  27. {
  28. 0% {background:url("../img/love01.jpeg");background-size: cover;}
  29. 25% {background:url("../img/love02.jpeg");background-size: cover;}
  30. /*50% {background:url("../img/love3.jpeg");background-size: cover;}*/
  31. /*75% {background:url("../img/love4.jpeg");background-size: cover;}*/
  32. /*100% {background:url("../img/love5.jpeg");background-size: cover;}*/
  33. }
  34. .form {
  35. background: rgba(255,255,255,0.2);
  36. width: 400px;
  37. margin: 120px auto;
  38. }
  39. /* 阴影 */
  40. .fa { display: inline-block;top: 27px;left: 6px;position: relative;color: #ccc; }
  41. input[type="text"] { padding-left:26px; }
  42. .checkbox { padding-left:21px; }

这样前端页面部分也就完成啦,现在让我测试下:

打开index.html

大功告成!!!!!!

如果有心的哥们,肯定会发现我没有写查询的方法,因为时间紧张还有其他事要做,这块就留给你们了。还是那句话,在我看来前端技术好了,写星云的dapp很简单。

另:如果你也想赢取星云dapp开发奖,可以去找些现成的项目改成合约版的啦,不说了,我要去再找些了。

  • 分享 收藏
0 条评论
  • 这篇文章暂无评论,赶紧评论一下吧~