有了前一章节使用Truffle框架搭建的一个小Demo后,我们现在来尝试自己写一个小应用;——一个链上Flags记事本
基于Truffle框架,我们只需要关注三部分文件:
-
智能合约.sol文件(本demo的MyFlag.sol)——智能合约主体
-
web页面页面(index.html, index.js, index.css等)——我们应用的页面展示部分
-
合约部署文件(3_deploy_myFlag.js)——我们要部署哪一个智能合约
好,我们现在就开始以上面3步的顺序完成我们的小应用吧;
一、智能合约.sol文件——MyFlag.sol
比较简单的一个合约内容,直接贴代码:
// SPDX-License-Identifier: MIT pragma solidity >=0.4.24; contract MyFlag { struct Topic{ string title; //标题 string content; //内容 address owner; //发布人 uint ts; //发布时的时间戳 } Topic[] public topics; //立Flag function postTopic(string memory title, string memory content) public { topics.push(Topic(title, content, msg.sender, block.timestamp)); } //获取Flag的总条数 function getCount() public view returns(uint) { return topics.length; } }
二、web前端页面
1、index.html,很简单的内容,没有任何设计感:
<!DOCTYPE html> <html> <head> <title>MyFlag</title> <script src="index.js"></script> </head> <body> <h1>展示所有的Flags</h1> <div>共<span id="count">0</span>条Flags</div> <ol id="topics"> </ol> 标题:<input type="text" id="title"> <br/><br/> 内容:<textarea name="" id="content" cols="30" rows="10"></textarea> <button onclick="App.postTopic()">立新Flag</button> </body> </html>
2、重点,index.js部分:
import Web3 from "web3"; import myFlagArtifact from "../../build/contracts/MyFlag.json"; const App = { web3: null, account: null, meta: null, start: async function() { const { web3 } = this; try { // 获取合约部署后的实例 const networkId = await web3.eth.net.getId(); const deployedNetwork = myFlagArtifact.networks[networkId]; this.meta = new web3.eth.Contract( myFlagArtifact.abi, deployedNetwork.address, ); // 初始化账户信息,取第一个地址账户作为默认账户; const accounts = await web3.eth.getAccounts(); this.account = accounts[0]; this.getTopics(); //本方法可以初始化页面(刷新页面) } catch (error) { console.error("Could not connect to contract or chain."); } }, //读链上数据(总条数,和每一条数据) getTopics: async function() { let meta = this.meta; const { topics, getCount } = meta.methods; const countDiv = document.getElementById("count"); const topicsDiv = document.getElementById("topics"); const count = await getCount().call(); countDiv.innerHTML = count; topicsDiv.innerHTML = ''; for(let i=0; i<count; i++){ const topic = await topics(i).call(); const title = topic[0]; const content = topic[1]; const owner = topic[2]; const ts = topic[3]; topicsDiv.innerHTML += `<li>${title} | ${content} | ${owner} | ${ts}</li>` } }, // 向链上写数据,需要消耗gas的; postTopic: async function() { const title = document.getElementById("title").value; const content = document.getElementById("content").value; const { postTopic } = this.meta.methods; await postTopic(title, content).send({ from: this.account, gas: 1000000 }); this.getTopics(); }, }; window.App = App; //Truffle帮我们自动生成好的,获取Web3,有小狐狸就用小狐狸当前的网络,没有就用我们自己不急部署的8545端口上的区块链网络 window.addEventListener("load", function() { if (window.ethereum) { // use MetaMask's provider App.web3 = new Web3(window.ethereum); window.ethereum.enable(); // get permission to access accounts } else { console.warn( "No web3 detected. Falling back to http://127.0.0.1:8545. You should remove this fallback when you deploy live", ); // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail) App.web3 = new Web3( new Web3.providers.HttpProvider("http://127.0.0.1:8545"), ); } App.start(); });
三、合约部署文件——3_deploy_myFlag.js
const MyFlag = artifacts.require("MyFlag"); module.exports = function(deployer) { deployer.deploy(MyFlag); };
四、测试
1、使用truffle启动测试环境并编译、部署合约(三步);
truffle develop truffle(develop)> compile truffle(develop)> migrate
2、启动我们的web应用:
npm install npm run dev ... i 「wds」: Project is running at http://localhost:8080/ i 「wds」: webpack output is served from / i 「wds」: Content not from webpack is served from D:\Study\Blockchain\Truffle\myDapp\app\dist i 「wdm」: Hash: 0ce8bf089f79211b4b86 Version: webpack 4.41.2 ...
3、现在打开 http://localhost:8080/ 页面,就可以看到我们的应用啦
我先立几条Flags:
再立条新的Flag:“第五条Flag”
好啦,由此,我们的第一个Dapp小应用就完成啦。
补充:传统web/app应用和基于区块链的Dapp应用的区别
其实理解起来也很简单:
传统web/app应用 | 基于区块链+智能合约的Dapp |
前端页面 | 前端页面 |
后端服务 | 智能合约 |
Mysql数据库 | 区块链 |