- 启动ganache-cli
//cmd
ganache-cli
-
创建Voting目录,安装truffle模板
-
编写智能合约
// Voting/contracts/Voting.sol
pragma solidity >=0.4.22 <0.8.0;
contract Voting{
bytes32[] public candidateList;
mapping(bytes32 => uint8) public votesReceived;
constructor(bytes32[] memory candidateListName) public {
candidateList = candidateListName;
}
function voteForCandidate(bytes32 candidateName) public {
require(validateCandidate(candidateName));
votesReceived[candidateName] += 1;
}
function totalVotesFor(bytes32 candidateName) view public returns (uint8) {
require(validateCandidate(candidateName));
return votesReceived[candidateName];
}
function validateCandidate(bytes32 candidateName) internal view returns (bool) {
for (uint8 i=0; i < candidateList.length; i++) {
if (candidateName == candidateList[i]) {
return true;
}
}
return false;
}
}
- 编译并部署智能合约
// Voting 目录下用cmd命令
truffle compile
truffle migrate
- 修改配置文件
// Voting/migrations/2_deploy_contracts.js
const Voting = artifacts.require('Voting')
module.exports = function(deployer) {
deployer.deploy(Voting, [
// 以下为ganache默认10个地址
'0xdDc0eB90f015BCCa3FE5E66A3fA93bE2A85C295D',
'0x60879543aeBfe29003bB4Ed1ba2A0eb52Ad2C4Db',
'0x7a454ce98fA1579Dca442976C70A08b193Acf25a',
'0xfC17042417b07cb401a084dabA2c3A1522E6a103',
'0xe785cA40212beBb80c12c083fA558AAa325cF038',
'0xE086301df6b83CdDc4Cb8414674FA95c9cF21fF4',
'0x06739F807D0d466C33dD077C75B406293ECcc67d',
'0x88CfaD631CD6776fB224c242e02074021B2DEc88',
'0xB9e130a95965d34a9700630238E2C6edDde3bCe3',
'0x9E824340973B7f0D00A839390411340D6E740a5D'
]
)
};
- 修改html
// Voting/app/src/index.html
<!DOCTYPE html>
<html>
<head>
<title>My Voting Dapp</title>
</head>
<style>
</style>
<body>
<h1>Voting Dapp</h1>
<p>Alice: <strong id="alice">loading...</strong> tickets</p>
<p>Bob: <strong id="bob">loading...</strong> tickets</p>
<label>VoteFor:</label>
<input type="text" id="candidate" />
<button onclick="App.voteForCandidate()">vote</button>
<script src="index.js"></script>
</body>
</html>
- 修改js
// Voting/app/src/index.js
import Web3 from "web3";
import votingArtifact from "../../build/contracts/Voting.json";
const ainBytes32 = "0x60879543aeBfe29003bB4Ed1ba2A0eb52Ad2C4Db"
const binBytes32 = "0x7a454ce98fA1579Dca442976C70A08b193Acf25a"
const App = {
web3: null,
account: null,
voting: null,
start: async function() {
const { web3 } = this;
try {
// get contract instance
const networkId = await web3.eth.net.getId();
const deployedNetwork = votingArtifact.networks[networkId];
this.voting = new web3.eth.Contract(
votingArtifact.abi,
deployedNetwork.address,
);
// get accounts
const accounts = await web3.eth.getAccounts();
this.account = accounts[0];
// this.refreshBalance()
this.ready()
} catch (error) {
console.error("Could not connect to contract or chain.");
}
},
refresh: async function(id, nameInBytes32) {
const {totalVotesFor} = this.voting.methods;
const tickets = await totalVotesFor(nameInBytes32).call()
const element = document.getElementById(id)
element.innerHTML = tickets.toString()
},
ready: async function() {
try {
this.refresh("alice", ainBytes32)
this.refresh("bob", binBytes32)
} catch (err) {
console.log(err)
}
},
voteForCandidate: async function() {
try {
const {voteForCandidate} = this.voting.methods
const candidateName = document.getElementById('candidate').value
if (candidateName === "Alice") {
await voteForCandidate(ainBytes32).send({from: this.account})
this.refresh('alice', ainBytes32)
} else if (candidateName === "Bob") {
await voteForCandidate(binBytes32).send({from: this.account})
this.refresh('bob', binBytes32)
}
} catch (err) {
console.log(err)
}
}
};
window.App = App;
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();
});
- 测试
npm run dev
效果如下
Q.E.D.