The signpost
- Ether square
- Block chain
- Dapp
- Taifang hello world
Environmental Science
windows 10 64bit
Reference blog
youclavier -- Voting Dapp Course in ETF
background
To take over an IPFS+Ethereum project, learn about Ethereum and try to complete a Hello World project.
step
- Refer to my other blog. Install nvm
- Install node 9.11.1 and switch environment
nvm install 9.11.1 nvm use 9.11.1
- Create a new working directory and index it to that path on the command line
- Install ganche-cli, web3, solc
npm install ganache-cli npm install web3@0.20.1 npm install solc@0.4.21 //There is no version of the original blog here, and it will install a version higher than 0.4, which will cause subsequent compilation of smart contract to fail.
When ganache-cli and web3 are installed, errors will occur due to the edition of the tutorial, but they will not affect it.
- Start ganache-cli
node_modules\.bin\ganache-cli
6. Use Solidity to create Smart Contract named Voting.sol
pragma solidity ^0.4.18; contract Voting { mapping (bytes32 => uint8) public votesReceived; bytes32[] public candidateList; function Voting(bytes32[] candidateNames) public { candidateList = candidateNames; } function totalVotesFor(bytes32 candidate) view public returns (uint8) { require(validCandidate(candidate)); return votesReceived[candidate]; } function voteForCandidate(bytes32 candidate) public { require(validCandidate(candidate)); votesReceived[candidate] += 1; } function validCandidate(bytes32 candidate) view public returns (bool) { for(uint i = 0; i < candidateList.length; i++) { if (candidateList[i] == candidate) { return true; } } return false; }}
- Start the node interactive console and enter the following commands in turn
> Web3 = require('web3') > web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")) > web3.eth.accounts
When you enter the last command above, you will get 10 accounts created by Ganache, as follows
> code = fs.readFileSync('Voting.sol').toString() > solc = require('solc') > compiledCode = solc.compile(code)
When completed, the output of the following screenshot is obtained, indicating that smart contract compiled successfully. 8. Deploy smart contract
> abi = JSON.parse(compiledCode.contracts[':Voting'].interface) > VotingContract = web3.eth.contract(abi) > byteCode = compiledCode.contracts[':Voting'].bytecode > deployedContract = VotingContract.new(['James', 'Norah', 'Jones'],{data: byteCode, from: web3.eth.accounts[0], gas: 4700000}) > deployedContract.address
At this point, you get address and note that it will be used later.
> contractInstance = VotingContract.at(deployedContract.address)
- Download the web3.js file and place it in the working root directory.
cdn is unavailable for some reason, so download the source file directly. The link is as follows web3.js 0.20.6
- Create the index.html file in the root directory and paste the following code. You need to replace the address of the smart contract you deployed in step 8 from the source of the truncation icon.
<!DOCTYPE html> <html> <head> <title>DApp</title> <link href='https://fonts.googleapis.com/css?family=Open Sans:400,700' rel='stylesheet' type='text/css'> <link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'> </head> <body class="container"> <h1>Voting Application</h1> <div class="table-responsive"> <table class="table table-bordered"> <thead> <tr> <th>Candidate</th> <th>Votes</th> </tr> </thead> <tbody> <tr> <td>James</td> <td id="candidate-1"></td> </tr> <tr> <td>Norah</td> <td id="candidate-2"></td> </tr> <tr> <td>Jones</td> <td id="candidate-3"></td> </tr> </tbody> </table> </div> <input type="text" id="candidate" /> <a href="#" onclick="voteForCandidate()" class="btn btn-primary">Vote</a> </body> <script src="web3.js"></script> <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script> <script language="javascript" type="text/javascript"> web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); abi = JSON.parse('[{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"totalVotesFor","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"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":"x","type":"bytes32"}],"name":"bytes32ToString","outputs":[{"name":"","type":"string"}],"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"},{"constant":true,"inputs":[],"name":"contractOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[{"name":"candidateNames","type":"bytes32[]"}],"payable":false,"type":"constructor"}]') VotingContract = web3.eth.contract(abi); contractInstance = VotingContract.at('0x47f49b300eb86d972f91f103913376fb0a8e52e7'); candidates = {"James": "candidate-1", "Norah": "candidate-2", "Jones": "candidate-3"} function voteForCandidate(candidate) { candidateName = $("#candidate").val(); try { contractInstance.voteForCandidate(candidateName, {from: web3.eth.accounts[0]}, function() { let div_id = candidates[candidateName]; $("#"+div_id).html(contractInstance.totalVotesFor.call(candidateName).toString()); }); } catch (err) { } } $(document).ready(function() { candidateNames = Object.keys(candidates); for (var i = 0; i < candidateNames.length; i++) { let name = candidateNames[i]; let val = contractInstance.totalVotesFor.call(name).toString() $("#"+candidates[name]).html(val); } }); </script> </html>
- After the browser opens index.html and enters the name of the person in Candidate, click Vote to vote. The voting results are as follows. Each click on the vote also generates a new block, the effect is as follows.
Epilogue
The above steps have completed a complete construction process of Ethereum-based voting Dapp, which should be completed smoothly without pits.
Like the literal meaning of "hello world", the 0-1 process is the most difficult, but at the beginning, the remaining 1-n will be much smoother.
For more original Haytham articles, please pay attention to the public number "Xu Julong":