基於truffle react box的投票demo
阿新 • • 發佈:2018-12-19
1. 環境搭建
如果對truffle react box的環境部署不熟請移步
https://blog.csdn.net/oulingcai/article/details/85088967
2. solidity合約
pragma solidity ^0.4.24; contract Voting { //候選人 string[] public candidates=new string[](0); //票數 mapping(string=>uint) ballots; constructor() public{ } //是否在候選人中 function checkCandidate(string _candidate) public view returns(bool){ for(uint i=0; i<candidates.length; i++){ if(hashCompareInternal(candidates[i],_candidate)){ return true; } } return false; } //投票 function vote(string _candidate) public{ assert(checkCandidate(_candidate)); ballots[_candidate]+=1; } //得到票數 function getBallot(string _candidate) public view returns(uint){ assert(checkCandidate(_candidate)); return ballots[_candidate]; } //得到候選人個數 function getCandidatesCount() public view returns(uint){ return candidates.length; } //對比兩個string是否相等 function hashCompareInternal(string a, string b) pure private returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } //新增候選人 function addCandidate(string _person) public{ if(checkCandidate(_person)){ return; }else{ candidates.push(_person); } } //得到候選人名稱 function getCandidates(uint index) view public returns(string){ return candidates[index]; } }
3. react
3.1 state欄位
state = { storageValue: 0, candidates:[], web3: null, accounts: null, contract: null };
3.2 得到合約物件和使用者錢包地址
componentDidMount = async () => { try { // Get network provider and web3 instance. const web3 = await getWeb3(); // Use web3 to get the user's accounts. const accounts = await web3.eth.getAccounts(); // Get the contract instance. const Contract = truffleContract(Voting); Contract.setProvider(web3.currentProvider); //得到合約物件 const instance = await Contract.at("0xd3a404902012f84dc625e8de00c02f1648a5bfad"); // Set web3, accounts, and contract to the state, and then proceed with an // example of interacting with the contract's methods. this.setState({ web3, accounts, contract: instance }, this.runExample); } catch (error) { // Catch any errors for any of the above operations. alert( `Failed to load web3, accounts, or contract. Check console for details.` ); console.log(error); } };
3.3 查詢目前投票的資訊
render() { //渲染器 if (!this.state.web3) { return <div>Loading Web3, accounts, and contract...</div>; } return ( <div className="App"> <h1>Good to Go!</h1> <h1>當前候選人{this.state.storageValue}個</h1> <ul>{ this.state.candidates.map((person,i)=>{ return <li key={i}>候選人: {person.name} 當前票數:{person.count} <button onClick={async ()=>{ const {candidates,accounts,contract } = this.state; //呼叫合約 投票 await contract.vote(person.name,{from:accounts[0]}); let response=await contract.getBallot(person.name); candidates[i].count=response.toNumber(); this.setState({candidates: candidates}); }}>投票</button></li> }) } </ul> <input ref="candidateName" style={{width:200,height:20}}></input> <button onClick={async ()=>{ let value=this.refs.candidateName.value; const {storageValue,candidates,accounts,contract } = this.state; console.log(value+"===="+candidates.length); //呼叫合約 新增候選人 await contract.addCandidate(value,{from:accounts[0]}); var element={name:value,count:0}; candidates[candidates.length]=element; this.setState({storageValue: storageValue+1,candidates: candidates}); }}>新增候選人</button> </div> ); } }
3.5 完整程式碼
import React, { Component } from "react";
import Voting from "./contracts/Voting.json";
import getWeb3 from "./utils/getWeb3";
import truffleContract from "truffle-contract";
import "./App.css";
class App extends Component {
state = { storageValue: 0, candidates:[], web3: null, accounts: null, contract: null };
componentDidMount = async () => {
try {
// Get network provider and web3 instance.
const web3 = await getWeb3();
// Use web3 to get the user's accounts.
const accounts = await web3.eth.getAccounts();
// Get the contract instance.
const Contract = truffleContract(Voting);
Contract.setProvider(web3.currentProvider);
//得到合約物件
const instance = await Contract.at("0xd3a404902012f84dc625e8de00c02f1648a5bfad");
// Set web3, accounts, and contract to the state, and then proceed with an
// example of interacting with the contract's methods.
this.setState({ web3, accounts, contract: instance }, this.runExample);
} catch (error) {
// Catch any errors for any of the above operations.
alert(
`Failed to load web3, accounts, or contract. Check console for details.`
);
console.log(error);
}
};
runExample = async () => {
const { accounts,candidates,contract } = this.state;
const response=await contract.getCandidatesCount();
console.log(response.toNumber());
//得到投票資訊,注意,這裡每個候選人都要查詢區塊,效率太低,真正專案不能這麼做,要一次性返回所以資訊
for (var i = 0; i < response.toNumber(); i++) {
// 候選人名字和票數的結構體
var element={name:"",count:0};
element.name=await contract.getCandidates(i);
let response=await contract.getBallot(element.name);
element.count=response.toNumber();
candidates[i]=element;
console.log(candidates[i]);
}
this.setState({ storageValue: response.toNumber(),candidates: candidates});
};
render() {
//渲染器
if (!this.state.web3) {
return <div>Loading Web3, accounts, and contract...</div>;
}
return (
<div className="App">
<h1>Good to Go!</h1>
<h1>當前候選人{this.state.storageValue}個</h1>
<ul>{
this.state.candidates.map((person,i)=>{
return <li key={i}>候選人: {person.name} 當前票數:{person.count}
<button onClick={async ()=>{
const {candidates,accounts,contract } = this.state;
//呼叫合約 投票
await contract.vote(person.name,{from:accounts[0]});
let response=await contract.getBallot(person.name);
candidates[i].count=response.toNumber();
this.setState({candidates: candidates});
}}>投票</button></li>
})
}
</ul>
<input ref="candidateName" style={{width:200,height:20}}></input>
<button onClick={async ()=>{
let value=this.refs.candidateName.value;
const {storageValue,candidates,accounts,contract } = this.state;
console.log(value+"===="+candidates.length);
//呼叫合約 新增候選人
await contract.addCandidate(value,{from:accounts[0]});
var element={name:value,count:0};
candidates[candidates.length]=element;
this.setState({storageValue: storageValue+1,candidates: candidates});
}}>新增候選人</button>
</div>
);
}
}
}
}
export default App;