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

最近因为星云链主网上线推出的星云激励计划,导致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

"use strict";
​
​
//合约 n1eMo1ANL5DymS7saJz67ou1Z7kRTCGoULU
//hash ea3f9680c61b93262e9e031b82e676312dc53dbf82119de317bbc0af5b3b1a63
​
//作为单独的类,封装一些参数,这些参数都是页面提交过来或者想展示到页面上的集合体
var LoveInfo = function (arrys) {
 if (arrys) {
 var obj = JSON.parse(arrys);
 this.mn = obj.mn;
 this.wm = obj.wm;
 this.ai = obj.ai;
 this.now = obj.now;
 this.author = obj.author;
 } else {
 this.mn = "";
 this.wm = "";
 this.ai = "";
 this.now = "";
 this.author = "";
 }
};
//定义方法,转换成字符串
LoveInfo.prototype = {
 toString: function () {
 return JSON.stringify(this);
 }
};
​
​
//结婚登记
var Married = function () {
 //LocalContractStorage.defineMapProperty是合约存储区内定义好的方法,可以直接使用,如果有小伙伴不知道怎么使用的话下面会给个链接讲解,很容易理解的
 //简单的理解就是给当前合约申明了一个属性叫love,然后love内部又有两个方法,parse和stringify对应着从区块链读取数据,后面操作区块链可以直接使用this.love调用对应的存取方法完成操作
 LocalContractStorage.defineMapProperty(this,"love",{
 parse : function (arrys) {
 return new LoveInfo(arrys)
 },
​
 stringify: function (res) {
 return res.toString()
 }
 });
};
//合约内定义的方法
Married.prototype = {
 init:function() {
​
 },
 //保存到区块链的方法 需要传递的三个参数,男人名字,女人名字,爱情宣言,当前时间
 save:function (mn,wm,ai,now) {
 //做去空格处理
 mn = mn.trim();
 wm = wm.trim();
 ai = ai.trim();
 now = now.trim();
 //空字符串处理
 if (mn === ""|| mn === ""||mn === ""||mn === ""){
 throw new Error("请检查登记信息,禁止登记空信息")
 }
 if (ai.length > 1024){
 throw new Error("可能你们彼此只想说一句简单的'我爱你'")
 }
​
 //获取添加来自哪个地址
 var from = Blockchain.transaction.from;
 //这里我们设定的key是两个名字加一起的字符串
 var loveInfo =  this.repo.get(mn+wm);
 //如果链上有信息,说明保存过,返回提示信息
 if (loveInfo){
 throw  new Error("信息已存在链上,可直接查看婚姻状况")
 }
 //没有信息就添加到区块链中
 loveInfo = new LoveInfo();
 loveInfo.mn = mn;
 loveInfo.wm = wm;
 loveInfo.now = now;
 loveInfo.ai = ai;
 loveInfo.author = from;
 //保存
 this.love.put(mn+wm,loveInfo);
 }
 //从区块链获取的方法 我这里定义的是两个参数,拼接在一起就是要从区块链查询的key值了
 get: function (mn,wm) {
 mn = mn.trim();
 wm = wm.trim();
 if ( mn === "" ) {
 throw new Error("男方姓名不能为空")
 }
 if ( wm === "" ) {
 throw new Error("女方姓名不能为空")
 }
 return this.love.get(mn+wm);
 }
​
};
​
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

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>婚姻登记所</title>
​
 <script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.min.js"></script>
 <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
 <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
 <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <link href="assets/css/bootstrap-responsive.css" rel="stylesheet">
 <!--这是我自定义的css文件,用来实现页面的一些效果  -->
 <link rel="stylesheet" href="css/style.css"> 

​
</head>
<body>
<!-- <div class="div01">
 <div class="search">
 男方姓名:<input id="mn" class="input-xlarge" type="text" placeholder="username"><br />
 女方姓名:<input id="wm" class="input-xlarge" type="text" placeholder="username"><br />
 爱情宣言:<br /><textarea rows="3" id = "ai"></textarea><br />
 <button id="add" class="btn btn-large btn-block btn-primary" type="button">登记</button>
 </div>
</div> -->
<div class="div01">
 <div class="form row">
 <div class="form-horizontal col-md-offset-3" id="login_form">
 <h3 class="form-title">婚姻登记</h3>
 <div class="col-md-9">
 <div class="form-group">
 <!--<i class="fa fa-user fa-lg"></i>-->
 男方姓名:<input class="form-control required" type="text" placeholder="man name" id="mn" name="username" autofocus="autofocus" maxlength="20"/>
 </div>
 <div class="form-group">
 <!--<i class="fa fa-user fa-lg"></i>-->
 女方姓名:<input class="form-control required" type="text" placeholder="woman name" id="wm" name="username" autofocus="autofocus" maxlength="20"/>
 </div>
 <div class="form-group">
 <!--<i class="fa fa-apple fa-lg"></i>-->
 爱情宣言:
 <textarea maxlength="120"></textarea>
 </div>
 <div class="form-group col-md-offset-9">
 <button class="btn btn-large btn-block btn-primary" type="button" id = 'add'>登记结婚</button>
 </div>
 </div>
 </div>
 </div>
</div>
​
<script src=lib/nebPay.js></script>
<script src=lib/nebulas.js></script>
​
<script>
​
 "use strict";
 <!--合约地址-->
 var dappAddress = "n1eMo1ANL5DymS7saJz67ou1Z7kRTCGoULU";
 //导包 nebulas 的 API
 var nebulas = require("nebulas"),
 //账户
 Account = nebulas.Account,
 //neb:一套API
 neb = new nebulas.Neb();
 //设置网络:主网  测试网 本地网 这里使用的是测试网,所以部署合约的时候就要把合约部署到测试网上
 neb.setRequest(new nebulas.HttpRequest("https://testnet.nebulas.io"));
​
 //添加数据,需要支付手续费 这里导包
 var NebPay = require("nebpay");     //https://github.com/nebulasio/nebPay
 var nebPay = new NebPay();
​
 var serialNumber
 var intervalQuery
​
 // 添加信息功能: 像合约中添加婚姻登记信息
 $("#add").click (() => {
​
 //获取当前时间
 function p(s) {
 return s < 10 ? '0' + s: s;
 }
​
 var myDate = new Date();
 //获取当前年
 var year=myDate.getFullYear();
 //获取当前月
 var month=myDate.getMonth()+1;
 //获取当前日
 var date=myDate.getDate();
 var h=myDate.getHours();       //获取当前小时数(0-23)
 var m=myDate.getMinutes();     //获取当前分钟数(0-59)
 var s=myDate.getSeconds();
​
 var now = year+'-'+p(month)+"-"+p(date)+" "+p(h)+':'+p(m)+':'+p(s);
 console.log(now);
 //合约地址
 var to = dappAddress;
 var value = "0";
 //调用的合约内哪个方法
 var callFunction = "save";
 //发送的参数
 var callArgs = "[\"" + $("#mn").val() + "\",\"" + $("#wm").val() +"\",\"" +$("#ai").val()+ "\",\"" + now +"\"]"
​
 //调用nebpay自带的方法,开始往区块链添加数据
 serialNumber = nebPay.call(to, value, callFunction, callArgs, {    //使用nebpay的call接口去调用合约,
 listener: cbPush        //设置listener, 处理交易返回信息
 });
 //定时器监听交易信息
 intervalQuery = setInterval(function () {
 funcIntervalQuery();
 }, 5000);
 });
​
 function funcIntervalQuery() {
 nebPay.queryPayInfo(serialNumber)
 .then(function (resp) {
 console.log("tx result: " + resp)
 var respObject = JSON.parse(resp)
 if(respObject.code === 0){
 console.log("已完成登记")
 clearInterval(intervalQuery)
 }
 })
 .catch(function (err) {
 console.log(err);
 });
 }
​
 function cbPush(resp) {
 console.log("response of push: " + JSON.stringify(resp))
 }
</script>
</body>
</html>

定义的 style.css 文件

.div01{
 background: url("../img/love01.jpeg");
 height: 830px;
 animation-name:myPics;
 background-size: cover;
 animation-duration:30s;
 /*变换时间*/
 animation-delay:2s;
 /*动画开始时间*/
 animation-iteration-count:infinite;
 /*下一周期循环播放*/
 animation-play-state:running;
 /*动画开始运行*/
}
​
/* .search {
 width: 50%;
 height: 50%;
 margin: auto;
}
​
.search button {*/
 /*width: 18%;*/
 /*height: 30px;*/
 /*margin-left: 6px;*/
 /*box-shadow: 3px 5px grey, 1px 1px #333;*/
/*}
​
@keyframes myPics
{
 0%   {background:url("../img/love01.jpeg");background-size: cover;}
 25%  {background:url("../img/love02.jpeg");background-size: cover;}
 /*50%  {background:url("../img/love3.jpeg");background-size: cover;}*/
 /*75%  {background:url("../img/love4.jpeg");background-size: cover;}*/
 /*100% {background:url("../img/love5.jpeg");background-size: cover;}*/
}
​
.form{background: rgba(255,255,255,0.2);width:400px;margin:120px auto;}
/*阴影*/
.fa{display: inline-block;top: 27px;left: 6px;position: relative;color: #ccc;}
input[type="text"]{padding-left:26px;}
.checkbox{padding-left:21px;}

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

打开index.html

image
image
image

大功告成!!!!!!

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

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

版权声明:博客中的文章版权归博主所有,转载请注明出处,联系方式:lixuan111222(微信)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容

  • 今天我开始写项目解读这个系列专题。 要搞懂一个区块链项目,首先要从白皮书阅读开始。区块链是一种数据库技术,如果懂技...
    小波有话说阅读 1,521评论 0 5
  • 首先要说一下为什么要开发一个星云Dapp?因为现在星云正在做推广每成功提交一个DApp即可获得 100 NAS,就...
    RhainL阅读 1,424评论 1 1
  • 以下是我看到的几篇关于ipV6适配问题的几篇比较好的博文,收藏!适配iOS应用兼容IPv6 DNS64/NAT64...
    Peak_One阅读 1,244评论 0 6
  • 今天我回到家之后,我先写完作业。写完之后又玩儿了一会儿,玩完之后我们又去给我买帽子啦。我买了一个粉色的帽子。妈妈说...
    张雪涵阅读 135评论 0 0
  • 这是vivian的第21篇文字。爱你❤ Vivian,自律的瑜伽习练者兼瑜伽老师一枚,自虐的强迫症患者(自虐...
    舒涵vivian阅读 756评论 1 2