前期准备
- 编辑器
理论上讲任何编辑器都可以编写Solidity合约代码,比如:WebStorm,VSCode,Sublime等。我选择atom
autocomplete-solidity
代码自动补齐
linter-solium、linter-solidity
代码错误检查
language-ethereum
支持Solidity代码高亮以及Solidity代码片段 - 环境
node.js
开发框架:truffle(用react box)
安装truffle
$ npm install -g ethereumjs-testrpc truffle
创建项目
luoxuedeMacBook-Pro:~ luoxue$ cd desktop
luoxuedeMacBook-Pro:desktop luoxue$ mkdir voting
luoxuedeMacBook-Pro:desktop luoxue$ cd voting
luoxuedeMacBook-Pro:voting luoxue$ 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
-
项目结构
image.png
- contracts:编写智能合约的文件夹,所有的智能合约文件都放置在这里
- migrations:部署合约配置的文件夹
- src:基于React的Web端源码
- test:智能合约测试用例文件夹
编写智能合约
- 在contracts文件夹下创建Voting.sol文件
- 编译环境: remix-online (remix.ethereum.org)
- 创建合约对象Voting,存candidtae,bytes23[]是可变的
contract Voting{
// luo
// xue
// ll
// xx
// mm
bytes32[] candidates = new bytes32[](5);
}
- 构造函数
function Voting(bytes32[] _candidates) public{
for(uint i =0; i<_candidates.length;i++){
candidates[i] = _candidates[i];
}
}
- 创建一个字典:候选人-》票数
mapping(bytes32 => uint) candidatesVotingCount;
- 创建投票方法
function votingToPerson(bytes32 person) public {
candidatesVotingCount[person]+=1;
}
- 检查是否是合法的候选人
function isValidPerson(bytes32 person) constant internal returns(bool){
for(uint i = 0; i<candidates.length; i++){
if(candidates[i] == person){
return true;
}
}
return false;
}
- 完整版
pragma solidity ^0.4.4;
contract Voting{
// luo
// xue
// ll
// xx
// mm
// ["luo","xue","ll","xx","mm"]
bytes32[] candidates = new bytes32[](5);
mapping(bytes32 => uint)candidatesVotingCount;
function Voting(bytes32[] _candidates) public {
for(uint i =0; i<_candidates.length;i++){
candidates[i] = _candidates[i];
}
}
function votingToPerson(bytes32 person) public {
assert(isValidPerson(person));
candidatesVotingCount[person]+=1;
}
function votingTotalToPerson(bytes32 person) constant public returns (uint) {
return candidatesVotingCount[person];
}
function isValidPerson(bytes32 person) constant internal returns(bool){
for(uint i = 0; i<candidates.length; i++){
if(candidates[i] == person){
return true;
}
}
return false;
}
}
-
remix 检查调用情况
image.png
image.png
-
复制粘贴并更换掉simple sample.sol 替换成voting
image.png
-
在migration换掉部署文件中相应部分
image.png
-
编译Voting.sol
打开truffle控制台
$ truffle develop
编译合约

发现build文件夹里多了一个 voting.json文件

-
App.js里面 改json的import
image.png
-
改this.state里面的状态,存储候选人相关信息
constructor(props) {
super(props)
this.state = {
canddidates:[
{
name:"luo",
count:0,
id:101
},
{
name:"xue",
count:0,
id:102
},
{
name:"ll",
count:0,
id:103
},
{
name:"xx",
count:0,
id:104
},
{
name:"mm",
count:0,
id:105
}
],
-
改路由
image.png
-
与链上交互
通过get web3交互
注:
=>
是个js 的箭头函数
this.instantiateContract() 初始化合约
image.png
-
修改合约初始化,获取合约实例
image.png
-
取到候选人的票数
image.png
看控制台输出:
两个1票3个0票

-
修改状态机, 让网页上显示合约上的票数
image.png
-
写修改函数,注意参数不用var 定义变量
image.png
- 在remix里投票,看网页上也有实时变化
-
加投票按钮
image.png
-
从input 里获取资料,ref
image.png
从name里获得了input的value
把contract变成全局变量
在点击button里面调用
image.png
但要注意,这里from 的要用web3来调用 -
然后刷新票数,直接复制上面即可
image.png
网友评论