转载地址

https://blog.csdn.net/qq_33764491/article/details/80570266

前言

最近DAPP的开发貌似很火,学习了区块链的一些知识之后,相信有很多人和我一样,也想了解开发一个DAPP是一个怎样的流程。

下面将通过一个简单的栗子来初识一下DAPP的开发流程,届时,我们也将开发出第一个DAPP应用–《永存的留言》。

在线体验(Ludis):http://words.ldsun.com/

项目介绍

《永存的留言》是一个基于以太坊的在线留言平台。它的功能十分简单–用户可以在平台上进行留言,平台每10s随机的展示留言内容。

但是它的特点在于,利用区块链的特性,保证了数据的真实性、完整性和安全性。

  • 使用Solidity开发后端方法
  • 使用Truffle框架
  • 基于unbox react脚手架项目
  • 部署在以太坊测试网络上Ropoetn Test Network
  • 使用MetaMask钱包插件发布交易

开发步骤

下载react项目模板

确保本地已经准备好Truffle所需的环境,准备以下命令,下载react项目模板。

$ mkdir a && cd a

truffle unbox react

当看到 Unbox successful. Sweet!提示时,表明下载成功。

编写智能合约

这是我们唯一的实现合约,包含的发送留言和读取留言的方法。

pragma solidity ^0.4.19;

contract SimpleStorage {
// 留言结构体
struct Message {
string word; // 留言
address from; // 留言者地址
string timestamp ; // 留言unix时间戳
} Message[] private wordArr; /**
* 写入留言的方法
*/
function setWord(string s, string t) public {
wordArr.push(Message({
word: s,
from: msg.sender,
timestamp: t
}));
} /**
* 获取随机留言的方法
*/
function getRandomWord(uint random) public view returns (uint, string, address, string) {
if(wordArr.length==0){
return (0, "", msg.sender, "");
}else{
Message storage result = wordArr[random];
return (wordArr.length, result.word, result.from, result.timestamp);
}
}
}

编译、部署合约

修改发布的脚本。

var SimpleStorage = artifacts.require("./SimpleStorage.sol");
//var Words = artifacts.require("Words"); module.exports = function(deployer) {
deployer.deploy(SimpleStorage);
//deployer.deploy(Words);
};

执行truffle compile进行合约的编译。

获取合约地址。

  • 这里我们打开MetaMask钱包插件,左上角选择Ropoetn Test Network网络.

  • 利用Remix编译,发布合约到以太坊测试环境。

  • 通过MetaMask的交易hash查询,获取已经部署到以太坊测试网络中的合约地址。

编写前端页面

这个部分主要是编写前端的展示效果和与合约交互的逻辑,这一部分最难编写,也最耗时间。

  • 主要逻辑代码
const contractAddress = "0x39e5196750dcddb1aaf6dda7d6e8dbb633482905" // 合约地址(以太坊测试网络)
var simpleStorageInstance // 合约实例 class App extends Component {
// 初始化构造
constructor(props) {
super(props)
this.state = {
word: null,
from: null,
timestamp: null,
random: 0,
count: 0,
input: '',
web3: null,
emptyTip: "还没有留言,快来创建全世界第一条留言吧~",
firstTimeLoad: true,
loading: false,
loadingTip: "留言正在写入,请耐心等待~",
waitingTip: "留言正在写入,请耐心等待~",
successTip: "留言成功",
animate: "",
in: css(styles.in),
out: css(styles.out)
}
} // 获取Web3实例
componentWillMount() {
// Get network provider and web3 instance.
getWeb3
.then(results => {
this.setState({
web3: results.web3
})
// Instantiate contract once web3 provided.
this.instantiateContract()
})
.catch(() => {
console.log('Error finding web3.')
})
} // 获取合约实例
instantiateContract() {
/*
* SMART CONTRACT EXAMPLE
*
* Normally these functions would be called in the context of a
* state management library, but for convenience I've placed them here.
*/
const contract = require('truffle-contract')
const simpleStorage = contract(SimpleStorageContract)
simpleStorage.setProvider(this.state.web3.currentProvider) // Get accounts.
this.state.web3.eth.getAccounts((error, accounts) => {
simpleStorage.at(contractAddress).then(instance => {
simpleStorageInstance = instance /*simpleStorage.deployed().then((instance) => {
simpleStorageInstance = instance // 部署本地Ganache*/
console.log("合约实例获取成功")
})
.then(result => {
return simpleStorageInstance.getRandomWord(this.state.random)
})
.then(result => {
console.log("读取成功", result)
if(result[1]!=this.setState.word){
this.setState({
animate: this.state.out
})
setTimeout(() => {
this.setState({
count: result[0].c[0],
word: result[1],
from: result[2],
timestamp: result[3],
animate: this.state.in,
firstTimeLoad: false
})
}, 2000)
}else{
this.setState({
firstTimeLoad: false
})
}
this.randerWord()
}) })
} // 循环从区块上随机读取留言
randerWord() {
setInterval(() => {
let random_num = Math.random() * (this.state.count? this.state.count: 0)
this.setState({
random: parseInt(random_num)
})
console.log("setInterval读取", this.state.random)
simpleStorageInstance.getRandomWord(this.state.random)
.then(result => {
console.log("setInterval读取成功", result)
if(result[1]!=this.setState.word){
this.setState({
animate: this.state.out
})
setTimeout(() => {
this.setState({
count: result[0].c[0],
word: result[1],
from: result[2],
timestamp: result[3],
animate: this.state.in
})
}, 2000)
}
})
}, 10000)
} // 写入区块链
setWord(){
if(!this.state.input) return
this.setState({
loading: true
})
let timestamp = new Date().getTime()
simpleStorageInstance.setWord(this.state.input, String(timestamp), {from: this.state.web3.eth.accounts[0]})
.then(result => {
this.setState({
loadingTip: this.state.successTip
})
setTimeout(() => {
this.setState({
loading: false,
input: '',
loadingTip: this.state.waitingTip
})
}, 1500) })
.catch(e => {
// 拒绝支付
this.setState({
loading: false
})
})
}
// 时间戳转义
formatTime(timestamp) {
let date = new Date(Number(timestamp))
let year = date.getFullYear()
let month = date.getMonth() + 1
let day = date.getDate()
let hour = date.getHours()
let minute = date.getMinutes()
let second = date.getSeconds()
let fDate = [year, month, day, ].map(this.formatNumber)
return fDate[0] + '年' + fDate[1] + '月' + fDate[2] + '日' + ' ' + [hour, minute, second].map(this.formatNumber).join(':')
}
/** 小于10的数字前面加0 */
formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
} }

运行项目

使用npm start启动项目,浏览器的3000端口运行。

效果如下(一定要连接到Ropoetn Test Network网络才可以)。

总结

这样我们就开发出了我们的第一个DAPP,体会了开发的基本流程。

  • 明确项目需求
  • 确定开发环境
  • 编写、测试、部署合约
  • 设计前端页面,使前后端交互
  • 发布测试

项目源码

GitHub

参考文章

Ludis的博文

DAPP开发初探——永存的留言的更多相关文章

  1. Unity3D游戏开发初探—2.初步了解3D模型基础

    一.什么是3D模型? 1.1 3D模型概述 简而言之,3D模型就是三维的.立体的模型,D是英文Dimensions的缩写. 3D模型也可以说是用3Ds MAX建造的立体模型,包括各种建筑.人物.植被. ...

  2. 基于以太坊开发的类似58同城的DApp开发与应用案例

    今天,Origin开发团队很高兴地宣布在以太坊Rinkeby测试网络上推出Origin Protocol Demo DApp ! 在这个DApp中,你可以在不同垂直行业的solidarity econ ...

  3. 基于Unity的AR开发初探:第一个AR应用程序

    记得2014年曾经写过一个Unity3D的游戏开发初探系列,收获了很多好评和鼓励,不过自那之后再也没有用过Unity,因为没有相关的需求让我能用到.目前公司有一个App开发的需求,想要融合一下AR到A ...

  4. 以太仿DApp开发环境搭建

    在网上找了些以太仿的资料,是node.js写的,之前也了解过node.js,正好也可以用上.本篇主要学习以太仿DApp开发环境搭建. 一.安装 DApp 开发环境 1.1安装 Node.js 首先下载 ...

  5. DAPP 开发直通车-如何基于NEL 轻钱包来开发DAPP

    之前做了 DAPP 开发直通车,通讲了一下开发一个DAPP的过程.   但是涉及多工种,多步骤.入手还是非常困难的.   经过不懈的努力,做了很多铺垫工作之后,我终于可以告诉你:   开发DAPP f ...

  6. NEO区块链-DAPP开发直通车-第零篇

    什么是DAPP DAPP 是以太坊发明的词汇 Decentralized Application. 目前基于区块链技术开发的应用程序广泛的接受使用了这一名称.   NEL将为开发DAPP提供全面的服务 ...

  7. saltstack自动化运维系列⑩SaltStack二次开发初探

    saltstack自动化运维系列⑩SaltStack二次开发初探 1.当salt运行在公网或者网络环境较差的条件下,需要配置timeout时间vim /etc/salt/master timeout: ...

  8. EOS Dapp开发(1)-基于Docker的开发环境搭建

    随着EOS主网的上线,相信基于EOS的Dapp开发会越来越多,查阅了很多资料相关的开发资料都不是很多,只能自己摸索,按照网上仅有的几篇教程,先git clonehttps://github.com/E ...

  9. 《区块链DAPP开发入门、代码实现、场景应用》笔记5——区块链福利彩票的设计

    笔者一直强调,一定要利用区块链的特点来解决行业存在的问题,并且该问题最好用区块链解决或者说只能用区块链解决.彩票行业就是个例子. 在讲解代码之前,首先讲解一下业务设计,如图6.15所示. 图6.15 ...

随机推荐

  1. 转自fineui论坛:解决fineui框架开发中的Designer.aspx.cs丢失问题

    在开发的时候碰到个问题,本来好好的Edit.aspx  Edit.aspx.cs  Edit.Designer.aspx.cs编辑Edit.aspx然后保存,编译的时候 发现Edit.aspx.cs里 ...

  2. 第四章:View的工作原理

    4.1 ViewRoot和DecorView ViewRoot对应于ViewRootImplement类,它是连接WindowManager和DecorView的纽带,View的三大流程均是通过Vie ...

  3. 给咱的WP站点搬家

    前言 WordPress 作为全球最流行的博客系统,使用简单,功能丰富,用它来建站的用户非常多.对于站长们来说,网站搬家也是少不了的,有时我们需要更换主机空间,把网站从一个服务器迁移到另一个服务器上, ...

  4. PyQt5基础控件

    QLabel标签 功能:在界面上显示文字.图片.链接等 接口: 方法 描述 setText() 设置显示的内容 setAlignment() 设置文字对齐方式 setToolTip() 设置提示信息 ...

  5. 一些matlb会用到的函数

    matlab这种软件功能很强大,但是都不是常常会用到,尤其是像在学生中.每次用的时候总会把一些基本的函数忘记,还的去网上查.我之前在使用的时候也总结过,可惜在一次数据丢失中全没了(︶︹︺). 从现在开 ...

  6. 【laravel】Eloquent 模型事件和监听方式

    所有支持的模型事件 在 Eloquent 模型类上进行查询.插入.更新.删除操作时,会触发相应的模型事件,不管你有没有监听它们.这些事件包括: retrieved 获取到模型实例后触发 creatin ...

  7. animation动画汇总(一阶段项目)

    animation 属性 动画属性: 1.animation-name:规定需要绑定到选择器的 keyframe 名称. 2.animation-duration:规定完成动画所花费的时间,以秒或毫秒 ...

  8. Java线程池ThreadPoolExecutor面试总结思维导图速记

    优点 降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 提高响应速度,当任务到达时,可以不需要等待线程创建就能立即执行. 提高线程的可管理性 类关系 接 Executor 一个无返 ...

  9. TCP-三次握手和四次挥手简单理解

    TCP-三次握手和四次挥手简单理解 背景:TCP,即传输控制协议,是一种面向连接的可靠的,基于字节流的传输层协议.作用是在不可靠的互联网络上提供一个可靠的端到端的字节流服务,为了准确无误的将数据送达目 ...

  10. 什么是 PHP 过滤器?

    PHP 过滤器 PHP 过滤器用于验证和过滤来自非安全来源的数据,比如用户的输入. 什么是 PHP 过滤器? PHP 过滤器用于验证和过滤来自非安全来源的数据. 测试.验证和过滤用户输入或自定义数据是 ...