您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
DAPP开发初探
 
作者:呢喃北上
  1359  次浏览      14
 2020-3-13
 
编辑推荐:
本文通过一个简单的例子来初识一下DAPP的开发流程,希望对您有所帮助
本文来自于简书,由火龙果软件Delores编辑、推荐。

项目介绍

《永存的留言》是一个基于以太坊的在线留言平台。它的功能十分简单–用户可以在平台上进行留言,平台每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,体会了开发的基本流程。

明确项目需求

确定开发环境

编写、测试、部署合约

设计前端页面,使前后端交互

发布测试

   
1359 次浏览       14
 
相关文章

iOS应用安全开发,你不知道的那些事术
Web安全之SQL注入攻击
移动APP安全在渗透测试中的应用
从Google备份互联网看“数据安全”
 
相关文档

web安全设计与防护
互联网海量内容安全处理技术
黑客攻击与防范技术
WEB黑盒安全检测
 
相关课程

WEB网站与应用安全原理与实践
web应用安全架构设计
创建安全的J2EE Web应用代码
信息安全问题与防范