环境
- 开发环境:egret
- 浏览器:Chrome
- 钱包和账号管理插件:Scatter
- 第三方库依赖:eosjs
- 测试网:http://jungle.cryptolions.io/
- docker:https://www.docker.com/get-started
文档/参考
- eos官方文档
- EOS 智能合约
- eosjs: https://www.npmjs.com/package/eosjs
- EOS各种问题汇总,EOS入门必读
- EOS开发调试环境搭建(全部流程)
- EOSIO开发(一)使用Docker构建本地环境
- 5分钟学会cleos注册EOS主网账户、投票和发币
- 怎样使用EOS.JS的API
- 如何安装 EOS 网页版钱包Scatter和使用指南
- 账号管理
- EOS区块链上EOSJS和scatter开发dApp
- Demo:eos-todo
- EOS教程如何创建EOS测试账号并且使用SCATTER插件
- EOS内存即RAM如何买卖
合约与前端交互的解决方案
账号创建管理
账号的创建和管理交给插件Scatter,玩家进入游戏的时候获取账号,如果没有,则提示玩家创建账号
前端调用合约方法
前端通过eos.contract
方法来调用合约方法,通过eos.getTableRows
方法来查询调用结果
关于事件
由于eos合约不包含事件,因此采用轮询的机制获取表数据
另外客户端调用合约方法,客户端可以得到具体的结果,通过返回的正常调用结果来判断方法调用是否成功
关于转账
eos 开发一个记录转账信息的智能合约 EOS智能合约开发闯关(3)—-合约内调用另一个合约的接口
EOS 智能合约内部调用 EOS 币转账功能
合约环境搭建
如果没有安装docker,请先按照docker,下载地址 https://www.docker.com/get-started
eos环境搭建已经合约部署,参考eos官方文档
eos常用命令
启动eos服务
代码语言:javascript复制docker start eosio
设置临时环境变量
代码语言:javascript复制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控制台
代码语言:javascript复制docker exec -it eosio bash
进入钱包shell
代码语言:javascript复制docker exec -it eosio bash
创建钱包
代码语言:javascript复制cleos wallet create -n <钱包名称> --to-console
查询钱包
代码语言:javascript复制 cleos wallet list
加锁/解锁钱包
代码语言:javascript复制cleos wallet lock/unclock -n 钱包名
打开关闭钱包
查询不到任何钱包信息,说明此时所有钱包都是close状态。
代码语言:javascript复制cleos wallet open/close
创建密钥、导入密钥
代码语言:javascript复制cleos create key
cleos wallet import ${private_key}
查询密钥
代码语言:javascript复制cleos wallet keys
创建账户
authorizing_account 是为创建账户这个动作提供资金的账户。在EOS中,创建账户时需要付出一点成本,这个成本由authorizing_account来承担,在本文中使用默认的eosio账户。
new_account 被创建的账户。
owner_key 拥有new_account账户owner权限的公钥。
active_key 拥有new_account账户active权限的公钥。
代码语言:javascript复制 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。
代码语言:javascript复制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的使用
连接
代码语言:javascript复制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);
});
返回信息
代码语言:javascript复制{ 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);
});
获取Actions
:eos.getActions(account_name, pos, offset)
pos和offset是指:从第pos条记录开始获取offset条Actions
代码语言:javascript复制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
获取
代码语言:javascript复制var scatter = window['scatter'];
if (!scatter) return;
scatter.requireVersion(3.0);
window['scatter'] = null;
初始化eos
代码语言:javascript复制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);
获取账号
代码语言:javascript复制state.scatter.getIdentity({
accounts: [eosNetwork]
}).then(res => {
if (!res) return ;
var identity = res;
...
}).catch(e => {
console.log(e)
});
退出账号
代码语言:javascript复制scatter.forgetIdentity();
部署时遇到的问题
1. 在哪里获取EOS
币
注册:http://jungle.cryptolions.io/#account
获取代币:http://jungle.cryptolions.io/#faucet
2. cleos
命令提示连接不到18888
端口
解决方案:
- 设置临时变量
本地(官网例子)
代码语言:javascript复制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'
测试网
代码语言:javascript复制alias cleos='docker exec -i keosd /opt/eosio/bin/cleos --wallet-url http://127.0.0.1:8900 -u http://dev.cryptolions.io:38888'
- 进入到
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:
代码语言:javascript复制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:
代码语言:javascript复制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转账
以测试网为例
代码语言:javascript复制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
代码语言:javascript复制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
代码语言:javascript复制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插件
分析:
可能有几个原因可以参考
- 端口号和IP配置不对
- 每次调用
action
时,未获取Identity
- 调用
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
看官方文档足够了
注意有提交的地方,需要将项目目录或者是要填写上去,文档会做出相应的修改