轉載地址
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开发初探——永存的留言的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。