EOS实践篇

目录

环境

文档/参考

合约与前端交互的解决方案

账号创建管理

账号的创建和管理交给插件Scatter,玩家进入游戏的时候获取账号,如果没有,则提示玩家创建账号

前端调用合约方法

前端通过eos.contract方法来调用合约方法,通过eos.getTableRows方法来查询调用结果

关于事件

由于eos合约不包含事件,因此采用轮询的机制获取表数据

另外客户端调用合约方法,客户端可以得到具体的结果,通过返回的正常调用结果来判断方法调用是否成功

关于转账

eos 开发一个记录转账信息的智能合约
EOS智能合约开发闯关(3)----合约内调用另一个合约的接口

EOS 智能合约内部调用 EOS 币转账功能

eos智能合约调用时序图


合约环境搭建

如果没有安装docker,请先安装docker,下载地址 https://www.docker.com/get-started

eos环境搭建已经合约部署,参考eos官方文档

eos常用命令

启动eos服务

docker start eosio

设置临时环境变量

alias cleos='docker exec -it eosio /opt/eosio/bin/cleos --url http://127.0.0.1:7777 --wallet-url http://127.0.0.1:5555'

进入eos控制台

docker exec -it eosio bash

进入钱包shell

docker exec -it eosio bash

创建钱包

cleos wallet create -n <钱包名称> --to-console

查询钱包

 cleos wallet list

加锁/解锁钱包

cleos wallet lock/unclock -n 钱包名

打开关闭钱包

查询不到任何钱包信息,说明此时所有钱包都是close状态。

cleos wallet open/close

创建密钥、导入密钥

cleos create key

cleos wallet import ${private_key}

查询密钥

cleos wallet keys

创建账户

authorizing_account 是为创建账户这个动作提供资金的账户。在EOS中,创建账户时需要付出一点成本,这个成本由authorizing_account来承担,在本文中使用默认的eosio账户。

new_account 被创建的账户。

owner_key 拥有new_account账户owner权限的公钥。

active_key 拥有new_account账户active权限的公钥。

 cleos create account ${authorizing_account} ${new_account} ${owner_key} ${active_key}
#cleos create account eosio hello EOS5FYZE9JAFkT4eDkAnHHyVpWzNsej5NXmQ2W1GxDsAWmeq3DQS7 -p eosio@active 
#cleos -u http://192.168.1.101:8888 create account eosio myaccount <public-key> <public-key> # 远程连接到nodeos节点,创建myaccount账户

#  cleos -u http://127.0.0.1:7777 create account eosio ac1 EOS5FYZE9JAFkT4eDkAnHHyVpWzNsej5NXmQ2W1GxDsAWmeq3DQS7 
# cleos -u http://127.0.0.1:7777 create account eosio ac2 EOS8FAtsVeLZsyQmA9KFCX4pZ38gFsjhiiJ1UEcsDRzfb8YankjNR
  • 修改账户权限

    account 被修改权限的账户

    permission 被修改的权限,如果存在则修改,不存在则新增。

    authority 账户权限信息,定义权限拥有者(key、account)、权重(weight)、阈值(threshold)

    parent permission的父权限,可选项,默认active。

cleos set account permission ${account} ${permission} ${authority} ${parent}
  • 查看用户信息
cleos -u http://127.0.0.1:7777  get account hello 

# cleos -u http://127.0.0.1:7777 get account ac1

eosjs的使用

连接


const Eos = require('eosjs')

var chain = {
    main: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906', // main network
    jungle: '038f4b0fc8ff18a4f0842a8f0564611f6e96e8535901dd45e43ac8691a1c4dca', // jungle testnet
    sys: 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f' // local developer
}

var eos = Eos({
    keyProvider: '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3',// private key
    httpEndpoint: 'http://127.0.0.1:7777',
    chainId: chain.sys,

    broadcast: true,
    debug: false,
    sign: true
});


用于得到相应的区块信息:getBlock(blockNumOrId)

eos.getBlock(1, (error, result) => {
    console.error(result);
})

// 获取指定区块信息
eos.getBlock({ block_num_or_id: 1 }).then(result => {
    console.log(result);
})

获取信息:eos.getInfo

eos.getInfo({}).then(result => {
    console.log(result)
})

获取账号:getAccount(accountName)

eos.getAccount("ac1").then(result => {
    console.log(result);
}).catch(err => {
    console.log(err);
});

返回信息

{ account_name: 'ac1',
  head_block_num: 76854,
  head_block_time: '2018-10-18T08:16:46.500',
  privileged: false,
  last_code_update: '1970-01-01T00:00:00.000',
  created: '2018-10-18T07:44:35.500',
  ram_quota: -1,
  net_weight: -1,
  cpu_weight: -1,
  net_limit: { used: -1, available: -1, max: -1 },
  cpu_limit: { used: -1, available: -1, max: -1 },
  ram_usage: 2724,
  permissions:
   [ 
     { perm_name: 'active', parent: 'owner', required_auth: [Object] },
     { perm_name: 'owner', parent: '', required_auth: [Object] } 
    ],
  total_resources: null,
  self_delegated_bandwidth: null,
  refund_request: null,
  voter_info: null 
}

account_name:这是EOS帐户名。
ram_quota:持有的RAM量,单位字节。
net_limit:帐户的总额、可用额、已用额,单位字节。
cpu_limit:CPU总量、可用CPU和已用CPU的总量,单位us。
ram_usage:帐户使用的RAM量,单位字节。
total_resources:分配给自己的EOS资源。
self_delegated_bandwidth:自己的委托信息。
voter_info:有关投票的信息。留意staked部分,显示我押注的数量。更具体地说,它的价值包括我委托给自己以及其他人委托的内容。

用于获取公钥对应的帐户: getKeyAccounts(publicKey)

eos.getKeyAccounts('EOS5FYZE9JAFkT4eDkAnHHyVpWzNsej5NXmQ2W1GxDsAWmeq3DQS7')
    .then(result => console.log(result))
    .catch(error => console.error(error));

获取账号余额: getCurrencyBalance(code, account, symbol)

eos.getCurrencyBalance({
    account: 'bob',
    code: 'eosio.token',
    symbol: 'SYS'
})
    .then(result => console.log(result))
    .catch(error => console.error(error));

#命令: cleos -u http://127.0.0.1:7777  get currency balance eosio.token bob SYS

获取账号状态: getCurrencyStats(code, symbol)

eos.getCurrencyStats('eosio.token', 'SYS')
    .then(result => console.log(result))
    .catch(error => console.error(error));
#命令: cleos -u http://127.0.0.1:7777 get currency stats eosio.token SYS

获取ABI: eos.getAbi(account_name)

eos.getAbi({ account_name: "eosio" }).then(result => {
    console.log(JSON.stringify(result));
}).catch(err => {
    console.error(err);
});

获取Actionseos.getActions(account_name, pos, offset)

pos和offset是指:从第pos条记录开始获取offset条Actions

eos.getActions({ account_name: "eosio", pos: 0, offset: 15 }, (error, result) => {
    if (error) {
        console.error(error);
    }
    if (result) {
        console.log(result);
    }
}); 

Scatter方法调用

依赖eosjs: https://cdn.jsdelivr.net/npm/eosjs@16.0.9/lib/eos.min.js

获取

var scatter = window['scatter'];
if (!scatter) return;
scatter.requireVersion(3.0);

window['scatter'] = null;

初始化eos

var config = {
        NETWORK_HOST: "dev.cryptolions.io",
        NETWORK_PORT: 38888,
        PROTOCAL: "http",
        CHAINID: "038f4b0fc8ff18a4f0842a8f0564611f6e96e8535901dd45e43ac8691a1c4dca"
    }

const host = config.NETWORK_HOST;
const port = config.NETWORK_PORT;
const network = { blockchain: 'eos', host: config.NETWORK_HOST, port: config.NETWORK_PORT, protocol: config.PROTOCAL, chainId: config.CHAINID };

const eosOptions = {};
const eos = scatter.eos(network, Eos, eosOptions, config.PROTOCAL);

获取账号

state.scatter.getIdentity({
    accounts: [eosNetwork]
}).then(res => {
    if (!res) return ;
    var identity = res;
    ...
}).catch(e => {
    console.log(e)
});

退出账号

scatter.forgetIdentity();

部署时遇到的问题

1. 在哪里获取EOS

注册:http://jungle.cryptolions.io/#account

获取代币:http://jungle.cryptolions.io/#faucet

2. cleos命令提示连接不到18888端口

解决方案:

  1. 设置临时变量

本地(官网例子)

alias cleos='docker exec -it eosio /opt/eosio/bin/cleos --url http://127.0.0.1:7777 --wallet-url http://127.0.0.1:5555'

测试网

alias cleos='docker exec -i keosd /opt/eosio/bin/cleos  --wallet-url http://127.0.0.1:8900  -u http://dev.cryptolions.io:38888'
  1. 进入到eosio控制台,以本地为例

-u <IP>即可

docker exec -it eosio bash

# cleos -u http://127.0.0.1:7777  get info

3. 设置合约的时候提示找不到路径

原因:在docker中没有该文件

解决方法:以账号test,合约hello为例

cd <项目目录>/todo
eosio-cpp -o hello.wasm hello.cpp --abigen

# 查看容器id

docker inspect -f '{{.ID}}' eosio

#将显示<ID>

docker cp <项目路径>/hello/ 488a19c71a50068fc91844b79fc1f97baf600c492c6e173832d7099ef53f6849:Users/<用户名称>/eosio-wallet/contracts/

# 设置合约
cleos set contract test /Users/<用户名称>/eosio-wallet/contracts/hello -p test@active

4. 部署合约提示ram不足

解决方案购买ram,购买方和接收方可以是同一个账号

 cleos system buyram -k <购买方> <接收方> 102

5. 如何调用eosjs和Scatter转账

调用eosjs转账

以本地为例

方法1:

eos.transaction(
    {
        // ...headers,
        // context_free_actions: [],
        actions: [
            {
                account: 'eosio.token',
                name: 'transfer',
                authorization: [{
                    actor: 'eosio',
                    permission: 'active'
                }],
                data: {
                    from: 'eosio',
                    to: 'bob',
                    quantity: '1.0000 SYS',
                    memo: 'ggg'
                }
            }
        ]
    },
    { broadcast: true, sign: true }
    // config -- example: {broadcast: false, sign: true}
).then(res => {
    console.log(res);
}).catch(err => {
    console.log(err);
})

方法2:

eos.contract("eosio.token").then(contract => {
    contract.transfer("alice", "bob", "1.000 SYS", {
        authorization: [
             {
                actor: "eosio",
                 permission: "active"
            }
        ]
    }).then(res => {
        console.log(res);
    }).catch(err => {
        console.log(err);
    });
}).catch(err => {
    console.log(err);
});

调用Scatter转账

以测试网为例

var config = {
        NETWORK_HOST: "dev.cryptolions.io",
        NETWORK_PORT: 38888,
        PROTOCAL: "http",
        CHAINID: "038f4b0fc8ff18a4f0842a8f0564611f6e96e8535901dd45e43ac8691a1c4dca"
    }
    
var eosNetwork =  { blockchain: 'eos', host: config.NETWORK_HOST, port: config.NETWORK_PORT, protocol: config.PROTOCAL, chainId: config.CHAINID }


#获取scatter

var scatter = window['scatter'];
    if (!scatter) return;
    scatter.requireVersion(3.0);

这里注意要引入eosJs才行
var eos = scatter.eos(eosNetwork, Eos, {}, config.PROTOCAL);

window['scatter'] = null;

scatter.getIdentity({
    accounts: [eosNetwork]
}).then(res => {
    if (!res) return ;
    
    var identity = res ? res.accounts.find(account => account.blockchain === 'eos') : undefined;
    
    var to = "<代币接收方账号>";
    var currency = "EOS";//代币
    var memo = "备注";
    
    eos.transaction({
        actions: [
            {
                account: 'eosio.token',
                name: 'transfer',
                authorization: [{
                    actor: identity.name,
                    permission: identity.authority
                }],
                data: {
                    from: identity.name,
                    to: to,
                    quantity: currency,//注意 要4位小数
                    memo: memo
                }
            }
        ],
        { broadcast: true, sign: true }
    }).then(()=>{
        //转账成功
    }).catch(err=>{
        console.log(err);
        
        //转账失败
    })
    
}).catch(e => {
    console.log(e)
});

6. 如何获取Scatter插件

看上面例子

7. 我想把合约部署到测试网

参考:https://zhuanlan.zhihu.com/p/37891815

步骤1

docker stop keosd
docker rm keosd
docker start keosd

docker run -d --restart=unless-stopped --name keosd   \
  -v /Users/<用户名>/<项目>/eosio-wallet:/opt/eosio/bin/data-dir  \
  -v /Users/<用户名>/<项目>/eosio-wallet:/Users/<用户名>/eosio-wallet \
  -t eosio/eos /opt/eosio/bin/keosd  \
  --wallet-dir /opt/eosio/bin/data-dir \
  --http-server-address=127.0.0.1:8900 

这是Mac上的例子,linux参考 https://zhuanlan.zhihu.com/p/37891815 ,
Window则把上面带用户名的路径替换,没有尝试过

步骤2

alias cleos='docker exec -i keosd /opt/eosio/bin/cleos  --wallet-url http://127.0.0.1:8900  -u http://dev.cryptolions.io:38888'

这样就连接到测试网了

接下来创建账号以及设置合约,参考官方文档:https://developers.eos.io/eosio-home/docs

8. 为啥我调不起Scatter插件

分析:

可能有几个原因可以参考

  1. 端口号和IP配置不对
  2. 每次调用action时,未获取Identity
  3. 调用eos.contract时设置得权限不匹配

其实最主要原因是权限设置不正确,其次初始化时const eos = scatter.eos(network, Eos, eosOptions, config.PROTOCAL);:如果这一步参数设置不正确,后面调用转账等活动是会报错

其中ChainID测试网(jungle)为:038f4b0fc8ff18a4f0842a8f0564611f6e96e8535901dd45e43ac8691a1c4dca,

本地为:cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f

另外使用Scatter不需要填写keyProvider,如果单纯用eosjs,则需要

var chain = {
    main: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906', // main network
    jungle: '038f4b0fc8ff18a4f0842a8f0564611f6e96e8535901dd45e43ac8691a1c4dca', // jungle testnet
    sys: 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f' // local developer
}

var eos = Eos({
    keyProvider: '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3',
    httpEndpoint: 'http://127.0.0.1:7777',
    chainId: chain.sys,
    expireInSeconds: 60,
    broadcast: true,
    debug: false,
    sign: true
});

9. 我看了这么多,还是不知道如何该如何下手,有一个简单的教程吗

官方文档:https://developers.eos.io/eosio-home/docs

看官方文档足够了

注意有提交内容的地方,需要将项目目录或者私钥填写上去,文档会做出相应的修改

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容