上个笔记我们搭建好了开发环境,这次我们来写一个简单的合约。 写之前需要创建 wallet 和账户。
首先看一下都有哪些参数可用
本篇笔记涉及到的内容:
创建 wallet
创建账户
创建合约
发布合约
写测试案例
编码规范 Coding Standards
Type
Standardized Method
Structs
lower case with _ between words including constants
Classes
lower case with _ between words including constants
Methods
lower case with _ between words including constants
Types
lower case with _ between words including constants
Template
Arguments CamelCase, no spaces
Macros
UPPERCASE
Comment Blocks
/* Comment Block Comment Block */ Inline Comments /** Comments **/
Standard Account Names
Can only contain the characters .abcdefghijklmnopqrstuvwxyz12345. a-z (lowercase), 1-5 and . (period)
Must start with a letter
Must be 12 characters
Table Names, Structs, Functions, Classes
Can only contain up to 12 alpha characters
Symbols
Must be capitalized alpha characters between A and Z
Must be 7 characters or less
创建一个 wallet cleos wallet create -n testwallet --to-console Creating wallet: testwallet Save password to use in the future to unlock this wallet. Without password imported keys will not be retrievable. "PW5K6dE8RxWfHdoWc96YDAcVhvvHeu1J1PapcBLtZVXuLt1s2y5CN"
返回一个用于解锁钱包的密码。然后我们需要导入私钥
随机生成一个公私钥对 cleos create key --to-console 私钥: 5JBSnaNR9gKDBxq5TqE9yaX88w4gUPZfcT2WniB7BixBBWMozcK 公钥: EOS6Ax2grsDJiCxvg3n1LCLx68wt2SzfCG1meTMsyVbKrtWRKJyqw cleos wallet unlock -n testwallet cleos wallet import -n testwallet \ --private-key 5JBSnaNR9gKDBxq5TqE9yaX88w4gUPZfcT2WniB7BixBBWMozcK //this is eosio account private key cleos wallet import -n testwallet \ --private-key 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
wallet 相关操作
cleos wallet open cleos wallet list cleos wallet unlock cleos wallet unlock -n testwallet --password PW5K6dE8RxWfHdoWc96YDAcVhvvHeu1J1PapcBLtZVXuLt1s2y5CN
创建账号 Usage: ./cleos create account [OPTIONS] creator name OwnerKey ActiveKey cleos create account eosio acct1 EOS6Ax2grsDJiCxvg3n1LCLx68wt2SzfCG1meTMsyVbKrtWRKJyqw cleos create account eosio acct2 EOS6Ax2grsDJiCxvg3n1LCLx68wt2SzfCG1meTMsyVbKrtWRKJyqw 查询账号 EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV cleos get accounts EOS6Ax2grsDJiCxvg3n1LCLx68wt2SzfCG1meTMsyVbKrtWRKJyqw 查看账户信息 cleos get account acct1
创建合约 - use eosfactory with vscode 先把系统合约 eosio.token 部署上去,然后就可以创建 token 了。 再部署合约之前,必须创建一个账户用来承载部署的合约。
先下载这里的合约,eos 工程里面的是旧版的。 git clone https://github.com/EOSIO/eosio.contracts/ cleos create account eosio eosio.token EOS6Ax2grsDJiCxvg3n1LCLx68wt2SzfCG1meTMsyVbKrtWRKJyqw eosio-cpp ~/eosio.contracts/eosio.token/src/eosio.token.cpp -o eosio.token.wasm --abigen eosiocpp -o ./app.wast ~/eos/contracts/eosio.token/eosio.token.cpp eosiocpp -g token.abi token.cpp 如果报错: _S_create_c_locale name not valid 执行这个:export LC_ALL="C" cleos set contract eosio.token /home/ubuntu/eosio.contracts/build/eosio.token -p eosio.token@active
创建 token //创建 token cleos push action eosio.token create '[ "eosio", "1000000000.0000 EOS"]' -p eosio.token@active // 发行 token cleos push action eosio.token issue '[ "acct1", "100.0000 EOS", "for test" ]' -p eosio@active // 转账 2147483648 cleos push action eosio.token transfer '[ "acct1", "acct2", "100.0000 EOS", "trans test" ]' -p acct1@active cleos push action eosio.token transfer '{"from":"token","to":"eosio","quantity":"20.0000 TKN","memo":"my first transfer"}' -p token
创建合约 ref
这里使用 vscode 来做 IDE,把eos/contracts/eosio.token复制过来
新建 makefile,注意使用 tab 缩进,否则会提示错误
CC=eosiocpp Contract=mw-coin all: @echo "Building" $(CC) -o $(Contract).wast $(Contract).cpp clean: rm -f $(Contract).wast rm -f $(Contract).wasm deploy: cleos wallet unlock -n testwallet --password PW5K3Uwa3Dm73B9gnPMCyYD4TZKwkWVpMbxPojnL7E1Lz4RddkoA4 cleos set contract mistywest ../$(Contract) -p mistywest@active
includePath 里面添加 eosiolib 的路径。
新建一个 task.json,添加两个 task,一个 build 用于生成 wasm, 一个 deploy 用于发布合约
{ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version" : "2.0.0" , "tasks" : [ { "label" : "mw-coin build" , "type" : "shell" , "command" : "make" , "group" : { "kind" : "build" , "isDefault" : true } }, { "label" : "mw-coin deploy" , "type" : "shell" , "command" : "make deploy" , "group" : { "kind" : "build" , "isDefault" : true } } ] }
编译 wasm/wast 的时候,使用快捷键 command+shift+B,选择mw-coin build 发布合约的时候,使用快捷键 command+shift+B,选择mw-coin deploy
调用合约 mistywest 是合约的账户,create 是合约的函数,[…]是参数,-p 是使用 mistywest 签名该 action
// unlock wallet cleos wallet unlock -n testwallet --password PW5K3Uwa3Dm73B9gnPMCyYD4TZKwkWVpMbxPojnL7E1Lz4RddkoA4 // create token cleos push action mistywest create \ '["mistywest", "1000.00 MWC"]' -p mistywest@active// issue token to walker cleos push action mistywest issue \ '["walker", "10.00 MWC", "Hi Walker!"]' -p mistywest@active// check balance cleos get currency balance mistywest walker MWC
目前该合约已经实现了创建 token 和发布 token 的功能,下面添加投票功能
合约增加投票功能 在 hpp 里面添加
[[eosio::action]] void openpoll (int poll_number, string poll_desc) ;[[eosio::action]] void addvoter (account_name newvoter) ; [[eosio::action]] void vote (int poll_number, int desc) ;struct [[eosio : :table]] voter_table{ account_name voter; uint64_t primary_key () const { return voter; } }; typedef eosio::multi_index<N (votertable), voter_table> voter
[[eosio::action]] 是 c++ 属性,用来生成 abi 文件 Multi Index Table 是用来在区块链上持久化数据的,保存 voter 的列表,同时使用 “voter” 作为主键
void mw::addvoter(account_name newvoter) { require_auth(_self); votertable voterTable(_self, newvoter); voterTable.emplace(_self, [&](auto &s) { s.voter = newvoter; }); } void mw::openpoll(int poll_number, string poll_desc) { } void mw::vote(int poll_number, int desc) { } EOSIO_ABI( eosio::mw, (addvoter)(create)(issue)(transfer) )
require_auth(_self) 是说在调用之前需要 mistywest 对这个 action 签名授权 然后是声明 voter table 第一个参数时 “owner”,第二个参数是 “scope”。
手动添加 abi 文件 structs
, { "name" : "addvoter" , "base" : "" , "fields" : [ {"name" :"newvoter" , "type" :"account_name" } ] },{ "name" : "voter_table" , "base" : "" , "fields" : [ {"name" :"voter" , "type" :"account_name" } ] }
actions
,{ "name" : "addvoter" , "type" : "addvoter" , "ricardian_contract" : "" }
tables
, { "name" : "votertable" , "type" : "voter_table" , "index_type" : "i64" , "key_names" : ["voter" ], "key_types" : ["uint64" ] }
添加投票人
cleos push action mistywest addvoter \ '["walker"]' -p mistywest@active
现在有一个表存在的区块链上的某个地方,可以查询
cleos get table mistywest walker votertable
mistywest 是owner,walker 是 scope,votertable 是表名