美文网首页Dapp开发
全栈投票Dapp教程—第三部分

全栈投票Dapp教程—第三部分

作者: rajs20222007 | 来源:发表于2018-08-26 22:02 被阅读10次

本教程翻译自Mahesh Murthy的教程.
文章链接如下:

  1. https://medium.com/@mvmurthy/full-stack-hello-world-voting-ethereum-dapp-tutorial-part-1-40d2d0d807c2
  2. https://medium.com/@mvmurthy/full-stack-hello-world-voting-ethereum-dapp-tutorial-part-2-30b3d335aa1f
  3. https://medium.com/@mvmurthy/full-stack-hello-world-voting-ethereum-dapp-tutorial-part-3-331c2712c9df

教程的所有代码可以在这里看到.

在第1部分中, 我们构建了一个简单的投票Dapp, 并使其在本地运行. 在第2部分中, 我们将应用移至truffle框架, 并将其部署到Ropsten测试网络, 通过truffle控制台和网页与其进行交互. 在本教程中, 我们将为投票Dapp添加更多功能, 以便学习一些关键概念. 以下是你将在本教程中学到的内容:

  1. 学习新数据类型, 例如使用结构体来组织和存储区块链上的数据.
  2. 了解令牌的概念及其用法.
  3. 学习使用以太币, 即以太坊区块链平台的货币进行付款.

通常在投票中, 每个公民都可以给他喜欢的候选人投一张选票. 然而有一些特色的投票中, 比如选举公司董事会时, 股东可以根据在公司拥有的股票数量进行投票. 当其拥有的股票越多, 其可以投的票数也就越多.

我们要增加我们的Dapp功能, 让其支持这样的选举. 我们会添加功能让每个人都可以购买公司的股票. 他们可以用他们的股票数来给候选人投票. 我们还会添加一个功能来查看投票人的信息. 在以太坊区块链中, 股票更像是令牌的概念. 因此本文的后部分将使用令牌数量来代替股票.

第一步是声明我们用来存储我们感兴趣信息的变量. 下面是带有注释的合约变量:

// 我们使用结构体来存储投票人的信息
struct voter {
    address voterAddress; // 投票人地址
    uint tokensBought;    // 投票人拥有令牌数
    uint[] tokensUsedPerCandidate; // 投票人给每个候选人的投票数
    /* 我们有一个candidateList数组在下面初始化了.
    每一次这个投票人用他的令牌投票的时候, 数组中候选人所在的次序就会增加.
    例如: 如果候选人列表声明为「"Rana", "Nick", "Jose"」,
    投票人用十个令牌投票给Nick, tokensUsedPerCanditate[1]就会增加10.
     */
}
/* mapping等效一个关系数组或者哈希.
   mapping的键是以bytes32类型存储的候选人名.
   mapping的值是以无符号整型存储的得票数量.
 */
mapping (bytes32 => uint) public votesReceived;
mapping (address => voter) public voterInfo;
/* Solidity目前还不允许返回数组或者字符串.
   我们使用一组bytes32类型来替代存储候选人名单.
 */
bytes32[] public candidateList;
uint public totalTokens; // 可供选举的总的令牌数
uint public balanceTokens; // 仍然可以购买的令牌数
uint public tokenPrice; // 每个令牌的价格

在教程1和教程2中, 我们初始化了在构造函数中的候选者列表. 在区块链上部署合约时, 只调用一次构造函数. 本文中, 我们还必须使用可供销售的令牌总数和每个令牌的成本初始化合约. 所以, 我们更新我们的合约构造函数, 如下所示:

/* 当合约部署在区块链上时,
   我们会初始化我们所有提供销售的令牌, 
   每个令牌的价格和所有的候选人.
 */
function Voting(uint tokens, uint pricePerToken, bytes32[] candidateNames) public {
    candidateList = candidateNames;
    totalTokens = tokens;
    balanceTokens = tokens;
    tokenPrice = pricePerToken;
}

在truffle中, 你可以使用migrations将代码部署到区块链. 点击这里可以查看migration文件. Truffle的migration文件中的示例部署调用如下所示:

deployer.deploy(Voting, 1000, web3.toWei('0.1', 'ether'), ['Rama', 'Nick', 'Jose']);
// 1000是总的提供出售的令牌数, 每个令牌的价格是0.1以太币.
// 我们会在教程的后面再说到这个代码.

现在我们已经初始化了令牌并设定了价格, 让我们看看如何使用以太币来购买令牌. 下面是购买令牌的功能.

/* 这个方法是用来交易令牌的. 注意下面的关键字'payable'.
 仅仅给方法增加一个关键字, 你的合约就可以接受任何人的以太币来调用这个方法.
 没比这更简单的赚钱方法了.
 */
function buy() payable public returns (uint) {
    uint tokensToBuy = msg.value / tokenPrice;
    if (tokensToBuy > balanceTokens) throw;
    voterInfo[msg.sender].voterAddress = msg.sender;
    voterInfo[msg.sender].tokensBought += tokensToBuy;
    balanceTokens -= tokensToBuy;
    return tokensToBuy;
}

一个交易调用例子如下:

truffle(development)> Voting.deployed().then(function(contract) {contract.buy({value: web3.toWei('1', 'ether'), from: web3.eth.accounts[1]})})

buy()方法中的value: web3.toWei(‘1’, ‘ether’)参数使用msg.value和msg.sender传递web3.eth.accounts[1]中的用户地址. 每个令牌的价值被设置为0.1以太币, web3.eth.accounts[1]会收到1以太币=10个令牌.

让我们暂时不去查看代码, 想象一下选民和合约之间的互动.

交互内容

合约中需要增加一些getter类型的方法, 很容易理解.

index.html文件也有一些新的更新:

  1. 要为候选人投票, 必须指定投票的令牌数量.
  2. 购买令牌的功能.
  3. 查看投票人信息 - 他们拥有多少令牌而不是他们投给每位候选人的令牌数.
  4. 候选人不再是硬编码, 我们从区块链中取出候选人并填充它.

app.js文件具有支持上述所有UI功能的更新.

更新部署文件2_deploy_contracts.js以传递总令牌和令牌价格以及候选人名称.

var Voting = artifacts.require("./Voting.sol");
module.exports = function(deployer) {
  deployer.deploy(Voting, 1000, web3.toWei('0.1', 'ether'), ['Rama', 'Nick', 'Jose']);
};

总而言之,我们在本教程中更新的四个文件是Voting.sol, index.html, app.js和2_deploy_contracts.js. 使用这些文件更新truffle仓库后, 我们可以将合约部署到区块链. 部署过程与上一个教程完全相同.

只需使用truffle命令进行编译和迁移.

truffle migrate
Using network 'development'.
Compiling Migrations.sol...
Compiling Voting.sol...
Writing artifacts to ./build/contracts
Running migration: 1_initial_migration.js
Deploying Migrations...
Migrations: 0xc9249947010675b8a3b1defb12334148f7f59010
Saving successful migration to network...
![3.2.png](https://img.haomeiwen.com/i13040345/995e57bfb91ca567.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying Voting...
Voting: 0x795d6d1f7cf467f27e48181da5f1ebd5bbd0a8df
Saving successful migration to network...
Saving artifacts...

如果你能够成功部署合同并启动Web服务器, 那么您的页面将如下所示:

Web页面

正如在上面的屏幕截图中所看到的, 你可以购买令牌, 使用令牌为候选人投票并按地址查找选民信息. 如果您能够使所有这些功能正常工作, 恭喜!

相关文章

网友评论

    本文标题:全栈投票Dapp教程—第三部分

    本文链接:https://www.haomeiwen.com/subject/apdaiftx.html