写在前面
上一篇 Vyper教程 安全的编程 中我们了解一些基本的安全编程方法。
我不喜欢翻译官方文档,也不喜欢枯燥学习各个知识点。我更愿意直接动手实践,在遇到问题或困难时逐步学习。
所以从这篇开始,包括之后的几篇文章,我们将用truffle构建一个基于以太坊的Dapp,然后一步一步完善它的功能,在这个过程中学习用到的知识点。
如果你想全面、系统的学习Vyper语言各个知识点,请阅读 官方文档。
如果你没使用过truffle,先学习 Vyper教程 使用Truffle框架开发Vyper。
本节我们先实现一个投票的合约。
投票合约
创建项目
我们最终想要创建一个Dapp,一个单纯的智能合约是不需要界面的,但是app需要界面,所以我们将使用react来写前端代码,实现超级简单的界面与我们的后台合约交互。(我都不会前端,请不要嫌弃我们的界面)所以我们将用react box来初始化我们的项目。
进入安装vyper的虚拟环境
source vyper-venv/bin/activate
创建truffle项目
mkdir demo
cd demo
truffle unbox react
删除不必要的文件
删除.contracts/SimpleStorage.sol 合约文件。
创建合约
在contracts里创建合约 Vote.vy
# @version 0.1.0b17
voteContainer: map(string[100], int128)
@public
def voteFor(optionName : string[100]):
self.voteContainer[optionName] += 1
@public
@constant
def getVoteNum(optionName : string[100])-> int128:
return self.voteContainer[optionName]
在这个合约中,我们使用一个mapping类型的变量voteContainer来记录每个选项的投票数。
对于mapping类型:
- 声明方式:map(_KeyType, _ValueType)
- keyType只能是基础类型,也就是不能用list、mapping、structs、contract作为key的类型。valueType可以是任意类型。
- mapping类型的变量只能是状态变量,也就是必须在函数之外声明。
进入控制台
如果你跟着我们完成了之前的教程,可能会遇到如下错误。
(vyper-venv) $ truffle develop
Connected to existing Truffle Develop session at http://127.0.0.1:8545/
> Something went wrong while attempting to connect to the network. Check your network configuration.
Could not connect to your Ethereum client.
Please check that your Ethereum client:
- is running
- is accepting RPC connections (i.e., "--rpc" option is used in geth)
- is accessible over the network
- is properly configured in your Truffle configuration file (truffle-config.js)
Truffle v5.1.19 (core: 5.1.19)
Node v12.16.1
原因是我们之前的教程已经启动过develop链,并且它运行在默认的9545端口。有两种方法都解决这个问题:
- 方法一:修改truffle-config.js文件,端口改为9545。
...
networks: {
develop: {
port: 9545
}
...
- 方法二:找到9545端口监听的进程(之前运行的develop链进程),kill掉。
$ lsof -i tcp:9545
$ kill *** //这里是你的进程号
接下来就可以正常启动develop控制台了!
(vyper-venv) $ truffle develop
编译 部署
truffle(develop)> migrate
migrate命令会先自动执行编译的~
与合约交互
truffle(develop)> Vote.deployed().then((token) => {contract = token;})
truffle(develop)> contract.voteFor('option1')
truffle(develop)> contract.voteFor('option1')
truffle(develop)> contract.voteFor('option1')
truffle(develop)> contract.getVoteNum('option1')
BN { negative: 0, words: [ 3, <1 empty item> ], length: 1, red: null }
可以看到我们已经可以给自定义的选项投票,并且获取它的票数了~
接下来我们会尝试完成简单的前端页面,来从网页端与我们的合约交互!