转载地址
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 ; }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");
module.exports =
function(deployer) {deployer.deploy(SimpleStorage);
};
执行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)}}componentWillMount() {getWeb3.then(results => {
this.setState({web3: results.web3})
this.instantiateContract()}).catch(() => {console.log(
'Error finding web3.')})}instantiateContract() {
const contract =
require(
'truffle-contract')
const simpleStorage = contract(SimpleStorageContract)simpleStorage.setProvider(
this.state.web3.currentProvider)
this.state.web3.eth.getAccounts((error, accounts) => {simpleStorage.at(contractAddress).then(instance => {simpleStorageInstance = instanceconsole.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)
returnthis.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() +
1let 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(
':') }formatNumber(n) {n = n.toString()
return n[
1] ? n :
'0' + n}}
运行项目
使用npm start启动项目,浏览器的3000端口运行。
效果如下(一定要连接到Ropoetn Test Network网络才可以)。
总结
这样我们就开发出了我们的第一个DAPP,体会了开发的基本流程。
- 明确项目需求
- 确定开发环境
- 编写、测试、部署合约
- 设计前端页面,使前后端交互
- 发布测试
项目源码
GitHub
参考文章
Ludis的博文
转载于:https://www.cnblogs.com/qq874455953/p/10264443.html
总结
以上是生活随笔为你收集整理的DAPP开发初探——永存的留言的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。