摘要:查看文件內(nèi)容這個(gè)文件主要是封裝了一個(gè)的供我們直接使用,可以從直接獲取到對(duì)象供文件中使用。
如何編寫智能合約(Smart Contract)- 從零構(gòu)建和部署去中心化投票App,decentralization Voting Dapp
課程目標(biāo)孔壹學(xué)院:國內(nèi)區(qū)塊鏈職業(yè)教育領(lǐng)先品牌
作者:黎躍春,區(qū)塊鏈、高可用架構(gòu)工程師
微信:liyc1215 QQ群:348924182 博客:http://liyuechun.org
了解區(qū)塊鏈智能合約
學(xué)會(huì)搭建智能合約開發(fā)環(huán)境
學(xué)會(huì)如何編譯智能合約
學(xué)會(huì)如何將智能合約部署到區(qū)塊鏈
學(xué)會(huì)如何通過WebApp和智能合約盡心互動(dòng)
掌握DApp(去中心化App)的整個(gè)開發(fā)部署流程
掌握去中心化在實(shí)戰(zhàn)產(chǎn)品中應(yīng)用的重大意義
項(xiàng)目效果圖 編輯器選擇理論上講任何編輯器都可以編寫Solidity合約代碼,比如:WebStorm,VSCode,Sublime,等等。我選擇的是Atom,沒有任何理由,因?yàn)锳tom輕量并且界面漂亮。
移步https://atom.io/地址,下載安裝Atom。
autocomplete-solidity代碼自動(dòng)補(bǔ)齊
linter-solium、linter-solidity代碼錯(cuò)誤檢查
language-ethereum支持Solidity代碼高亮以及Solidity代碼片段
安裝所需工具首先開發(fā)機(jī)上必須裝好Node.js,再使用以下命令安裝所需的工具:
$ npm install -g ethereumjs-testrpc truffle
liyuechun:~ yuechunli$ npm install -g ethereumjs-testrpc truffle /usr/local/bin/testrpc -> /usr/local/lib/node_modules/ethereumjs-testrpc/build/cli.node.js /usr/local/bin/truffle -> /usr/local/lib/node_modules/truffle/build/cli.bundled.js + truffle@3.4.9 + ethereumjs-testrpc@4.1.3 added 1 package and updated 7 packages in 76.132s liyuechun:~ yuechunli$創(chuàng)建項(xiàng)目
/Users/liyuechun/Desktop/1012/Voting liyuechun:Voting yuechunli$ ls liyuechun:Voting yuechunli$ pwd /Users/liyuechun/Desktop/1012/Voting liyuechun:Voting yuechunli$ truffle unbox react-box Downloading... Unpacking... Setting up... Unbox successful. Sweet! Commands: Compile: truffle compile Migrate: truffle migrate Test contracts: truffle test Test dapp: npm test Run dev server: npm run start Build for production: npm run build liyuechun:Voting yuechunli$項(xiàng)目結(jié)構(gòu)
contracts:編寫智能合約的文件夾,所有的智能合約文件都放置在這里
migrations:部署合約配置的文件夾
src:基于React的Web端源碼
test:智能合約測試用例文件夾
編寫投票Dapp智能合約在contracts文件夾下創(chuàng)建Voting.sol文件,將下面的代碼拷貝到文件中。
pragma solidity ^0.4.4; contract Voting { // liyuechun -> 10 // xietingfeng -> 5 // liudehua -> 20 mapping (bytes32 => uint8) public votesReceived; // 存儲(chǔ)候選人名字的數(shù)組 bytes32[] public candidateList; // 構(gòu)造函數(shù) 初始化候選人名單 function Voting(bytes32[] candidateNames) { candidateList = candidateNames; } // 查詢某個(gè)候選人的總票數(shù) function totalVotesFor(bytes32 candidate) constant returns (uint8) { require(validCandidate(candidate) == true); // 或者 // assert(validCandidate(candidate) == true); return votesReceived[candidate]; } // 為某個(gè)候選人投票 function voteForCandidate(bytes32 candidate) { assert(validCandidate(candidate) == true); votesReceived[candidate] += 1; } // 檢索投票的姓名是不是候選人的名字 function validCandidate(bytes32 candidate) constant returns (bool) { for(uint i = 0; i < candidateList.length; i++) { if (candidateList[i] == candidate) { return true; } } return false; } }通過remix + metamask部署合約到Kovan Test Net
在Google瀏覽器里面安裝MetaMask插件
打開https://remix.ethereum.org將合約代碼拷貝到里面
確保MetaMask賬號(hào)處于等于狀態(tài),并且有一定的以太幣支付給礦工。
確保Environment是Injected Web3,如果切換不過來,關(guān)掉瀏覽器重新啟動(dòng)
在create函數(shù)中輸入一個(gè)數(shù)組,數(shù)組里面的內(nèi)容為候選人名單
點(diǎn)擊create按鈕,會(huì)彈出MetaMask界面讓你確認(rèn),確認(rèn)提交,過一會(huì)兒,合約就部署成功
可以測試給某個(gè)候選人投票,查詢某個(gè)候選人的票數(shù)
拷貝合約地址0xd3f33a2e553b363b432d7f81f721a2a6202ecc67編譯合約
liyuechun:Voting yuechunli$ truffle compile Compiling ./contracts/Migrations.sol... Compiling ./contracts/SimpleStorage.sol... Compiling ./contracts/Voting.sol... Writing artifacts to ./build/contracts liyuechun:Voting yuechunli$
編譯完合約以后在build/contracts文件夾下面會(huì)有一個(gè)Voting.json的abi文件。
查看Voting.json文件內(nèi)容{ "contract_name": "Voting", "abi": [ { "constant": true, "inputs": [ { "name": "candidate", "type": "bytes32" } ], "name": "totalVotesFor", "outputs": [ { "name": "", "type": "uint8" } ], "payable": false, "type": "function" }, { "constant": true, "inputs": [ { "name": "candidate", "type": "bytes32" } ], "name": "validCandidate", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "type": "function" }, { "constant": true, "inputs": [ { "name": "", "type": "bytes32" } ], "name": "votesReceived", "outputs": [ { "name": "", "type": "uint8" } ], "payable": false, "type": "function" }, { "constant": true, "inputs": [ { "name": "", "type": "uint256" } ], "name": "candidateList", "outputs": [ { "name": "", "type": "bytes32" } ], "payable": false, "type": "function" }, { "constant": false, "inputs": [ { "name": "candidate", "type": "bytes32" } ], "name": "voteForCandidate", "outputs": [], "payable": false, "type": "function" }, { "inputs": [ { "name": "candidateNames", "type": "bytes32[]" } ], "payable": false, "type": "constructor" } ], "unlinked_binary": "0x6060604052341561000f57600080fd5b6040516103113803806103118339810160405280805190910190505b600181805161003e929160200190610046565b505b506100b5565b828054828255906000526020600020908101928215610083579160200282015b828111156100835782518255602090920191600190910190610066565b5b50610090929150610094565b5090565b6100b291905b80821115610090576000815560010161009a565b5090565b90565b61024d806100c46000396000f300606060405263ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632f265cf78114610069578063392e6678146100955780637021939f146100bf578063b13c744b146100eb578063cc9ab26714610113575b600080fd5b341561007457600080fd5b61007f60043561012b565b60405160ff909116815260200160405180910390f35b34156100a057600080fd5b6100ab60043561015d565b604051901515815260200160405180910390f35b34156100ca57600080fd5b61007f6004356101af565b60405160ff909116815260200160405180910390f35b34156100f657600080fd5b6101016004356101c4565b60405190815260200160405180910390f35b341561011e57600080fd5b6101296004356101e7565b005b60006101368261015d565b151560011461014457600080fd5b5060008181526020819052604090205460ff165b919050565b6000805b6001548110156101a457600180548491908390811061017c57fe5b906000526020600020900160005b5054141561019b57600191506101a9565b5b600101610161565b600091505b50919050565b60006020819052908152604090205460ff1681565b60018054829081106101d257fe5b906000526020600020900160005b5054905081565b6101f08161015d565b15156001146101fb57fe5b6000818152602081905260409020805460ff8082166001011660ff199091161790555b505600a165627a7a723058206783a7ff47eae16f18011a9db2a3cc983350b779bf3181b7623c18d4bce363180029", "networks": {}, "schema_version": "0.0.5", "updated_at": 1507806214330 }
這個(gè)文件是編譯后的abi文件,待會(huì)兒需要將這個(gè)文件的json導(dǎo)入到App.json中。
查看src/utils/getWeb3.js文件內(nèi)容import Web3 from "web3" let getWeb3 = new Promise(function(resolve, reject) { // Wait for loading completion to avoid race conditions with web3 injection timing. window.addEventListener("load", function() { var results var web3 = window.web3 // Checking if Web3 has been injected by the browser (Mist/MetaMask) if (typeof web3 !== "undefined") { // Use Mist/MetaMask"s provider. web3 = new Web3(web3.currentProvider) results = { web3: web3 } console.log("Injected web3 detected."); resolve(results) } else { // Fallback to localhost if no web3 injection. var provider = new Web3.providers.HttpProvider("http://localhost:8545") web3 = new Web3(provider) results = { web3: web3 } console.log("No web3 instance injected, using Local web3."); resolve(results) } }) }) export default getWeb3
這個(gè)文件主要是封裝了一個(gè)getWeb3的promiss供我們直接使用,可以從getWeb3直接獲取到web3對(duì)象供App.js文件中使用。
修改app.js前端代碼和合約進(jìn)行互動(dòng)import React, { Component } from "react" import VotingContract from "../build/contracts/Voting.json" import getWeb3 from "./utils/getWeb3" import "./css/oswald.css" import "./css/open-sans.css" import "./css/pure-min.css" import "./App.css" const contractAddress = "0xd3f33a2e553b363b432d7f81f721a2a6202ecc67"; var votingContractInstance; var _modifyVotingCount = (candidates,i,votingCount) => { console.log("---------"); console.log(candidates); console.log(i); console.log(votingCount); let obj = candidates[i]; obj.votingCount = votingCount; return candidates; } class App extends Component { constructor(props) { super(props) this.state = { candidates: [ { "name": "Rama", "id": 100, "votingCount": 0 }, { "name": "Nick", "id": 101, "votingCount": 0 }, { "name": "Jose", "id": 102, "votingCount": 0 }, { "name": "liyuechun", "id": 103, "votingCount": 0 } ], candidatesVoteCount: ["0","0","0","0"], web3: null } } componentWillMount() { // Get network provider and web3 instance. // See utils/getWeb3 for more info. 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 votingContract = contract(VotingContract) votingContract.setProvider(this.state.web3.currentProvider) // Declaring this for later so we can chain functions on SimpleStorage. // Get accounts. this.state.web3.eth.getAccounts((error, accounts) => { votingContract.at(contractAddress).then((instance) => { votingContractInstance = instance; for (let i = 0; i < this.state.candidates.length; i++) { let object = this.state.candidates[i]; console.log(accounts[0]); console.log(votingContractInstance); console.log(votingContractInstance.totalVotesFor(object.name)); votingContractInstance.totalVotesFor(object.name).then(result => { console.log(i); console.log(result.c[0]); this.setState({ candidates: _modifyVotingCount(this.state.candidates,i,result.c[0]) }); }); } }) }) } render() { return (打賞地址); } } export default App{ this.state.candidates.map((object) => { console.log(object); return (
- 候選人:{object.name} 支持票數(shù):{object.votingCount}
) }) }
比特幣:1FcbBw62FHBJKTiLGNoguSwkBdVnJQ9NUn
以太坊:0xF055775eBD516e7419ae486C1d50C682d4170645
區(qū)塊鏈技術(shù)交流QQ群:348924182
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/27088.html
摘要:原文發(fā)表于以太坊智能合約開發(fā)第二篇理解以太坊相關(guān)概念很多人都說比特幣是區(qū)塊鏈,以太坊是區(qū)塊鏈。它是以太坊智能合約的運(yùn)行環(huán)境。是由以太坊節(jié)點(diǎn)提供。以太坊社區(qū)把基于智能合約的應(yīng)用稱為去中心化的應(yīng)用。 原文發(fā)表于:以太坊智能合約開發(fā)第二篇:理解以太坊相關(guān)概念 很多人都說比特幣是區(qū)塊鏈1.0,以太坊是區(qū)塊鏈2.0。在以太坊平臺(tái)上,可以開發(fā)各種各樣的去中心化應(yīng)用,這些應(yīng)用構(gòu)成了以太坊的整個(gè)生態(tài)...
摘要:原文發(fā)表于以太坊智能合約開發(fā)第六篇開發(fā)框架在前面幾篇教程中,我們實(shí)現(xiàn)了一個(gè)簡單的合約,并通過編譯器將合約代碼編譯后,部署在私有鏈上。 原文發(fā)表于:以太坊智能合約開發(fā)第六篇:truffle開發(fā)框架 在前面幾篇教程中,我們實(shí)現(xiàn)了一個(gè)簡單的 Hello 合約,并通過 solc 編譯器將合約代碼編譯后,部署在私有鏈Ganache上。本篇將介紹通過truffle框架來構(gòu)建自動(dòng)編譯、部署合約代碼...
摘要:第一節(jié)課程概述本課程面向初學(xué)者,內(nèi)容涵蓋以太坊開發(fā)相關(guān)的基本概念,并將手把手地教大家如何構(gòu)建一個(gè)基于以太坊的完整去中心化應(yīng)用區(qū)塊鏈投票系統(tǒng)。第七節(jié)以太坊世界計(jì)算機(jī)以太坊是一種區(qū)塊鏈的實(shí)現(xiàn)。交易數(shù)據(jù)以太坊中每筆交易都存儲(chǔ)在區(qū)塊鏈上。 第一節(jié) 課程概述 本課程面向初學(xué)者,內(nèi)容涵蓋以太坊開發(fā)相關(guān)的基本概念,并將手把手地教大家如何構(gòu)建一個(gè) 基于以太坊的完整去中心化應(yīng)用 —— 區(qū)塊鏈投票系統(tǒng)。 ...
摘要:第一節(jié)課程概述本課程面向初學(xué)者,內(nèi)容涵蓋以太坊開發(fā)相關(guān)的基本概念,并將手把手地教大家如何構(gòu)建一個(gè)基于以太坊的完整去中心化應(yīng)用區(qū)塊鏈投票系統(tǒng)。第七節(jié)以太坊世界計(jì)算機(jī)以太坊是一種區(qū)塊鏈的實(shí)現(xiàn)。交易數(shù)據(jù)以太坊中每筆交易都存儲(chǔ)在區(qū)塊鏈上。 第一節(jié) 課程概述 本課程面向初學(xué)者,內(nèi)容涵蓋以太坊開發(fā)相關(guān)的基本概念,并將手把手地教大家如何構(gòu)建一個(gè) 基于以太坊的完整去中心化應(yīng)用 —— 區(qū)塊鏈投票系統(tǒng)。 ...
摘要:上周末,來自硅谷團(tuán)隊(duì)的游戲作品獲得思否區(qū)塊鏈黑客馬拉松北京站冠軍。本次黑客馬拉松有來自基金會(huì)科學(xué)家楊耀東合伙人劉海核心開發(fā)者姜家志星云鏈實(shí)驗(yàn)室負(fù)責(zé)人劉杜然等多位嘉賓出席。 上周末,來自硅谷團(tuán)隊(duì)的游戲作品Crypto Bird - An Implement of NabBoard獲得 SegmentFault 思否區(qū)塊鏈黑客馬拉松北京站冠軍。本次黑客馬拉松有來自 QuarkChain 基...
閱讀 2585·2019-08-30 10:53
閱讀 3189·2019-08-29 16:20
閱讀 2942·2019-08-29 15:35
閱讀 1765·2019-08-29 12:24
閱讀 2871·2019-08-28 18:19
閱讀 1848·2019-08-23 18:07
閱讀 2327·2019-08-23 15:31
閱讀 1166·2019-08-23 14:05