转载地址

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. react实战 : react 与 svg

    有一个需求是这样的. 一个组件里若干个区块.区块数量不定. 区块里面是一个波浪效果组件,而这个一般用 SVG 做. 所以就变成了在 react 中使用 SVG 的问题. 首先是波浪效果需要的样式. . ...

  2. Java 线程与同步的性能优化

    本文探讨的主题是,如何挖掘出Java线程和同步设施的最大性能. 1.线程池与ThreadPoolExecutor 1)线程池与ThreadPoolExecutor 线程池的实现可能有所不同,但基本概念 ...

  3. Spring框架零基础学习(一):IOC|DI、AOP

    文章目录 一.IDEA创建Spring项目 二.Spring: IOC和DI 三.Spring: AOP 参考链接: HOW2J.CN:Spring idea创建一个spring项目 一.IDEA创建 ...

  4. package.json中dependencies和devDependencies区别

    package.json中dependencies和devDependencies区别 dependencies: 应用能够正常运行依赖的包.用户发布环境,依赖的包不仅开发环境能够使用,生产环境也能使 ...

  5. python thrift 实现 单端口多服务的过程

    Thrift 是一种接口描述语言和二进制通信协议.以前也没接触过,最近有个项目需要建立自动化测试,这个项目之间的微服务都是通过 Thrift 进行通信的,然后写自动化脚本之前研究了一下. 需要定义一个 ...

  6. python txt装换成excel

    工作中,我们需要经常吧一些导出的数据文件,例如sql查出来的结果装换成excel,用文件发送.这次为大家带上python装换excel的脚本 记得先安装wlwt模块,适用版本,python2-3 #c ...

  7. 使用jwt进行token认证

    简单说明:最近在搞权限这一块的东西,需要用到jwt进行token认证,才有了如下的demo演示   具体细节可以看gitbug,噗,不是bug是hub  github地址:https://github ...

  8. git常用命令操作

    git常用命令 #查看配置 git config -l #查看系统config git config --system --list #查看当前用户(global)配置 git config --gl ...

  9. sed在文本第一行和最后一行添加字符串

    shell在文本第一行和最后一行添加字符串 sed -i '1 i\ApiInterfaceName ResposeTime' /tmp/apiLog/apiLogFromatSecond.logse ...

  10. Fortify Audit Workbench 笔记 Privacy Violation: Heap Inspection 隐私泄露(堆检查)

    Privacy Violation: Heap Inspection 隐私泄露(堆检查) Abstract 将敏感数据存储在 String 对象中使系统无法从内存中可靠地清除数据. Explanati ...