EOS实践篇

作者: 陨石坠灭 | 来源:发表于2018-10-27 21:10 被阅读163次

    目录

    环境

    文档/参考

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

    账号创建管理

    账号的创建和管理交给插件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

    看官方文档足够了

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

    相关文章

      网友评论

        本文标题:EOS实践篇

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