您正在查看: 2018年9月

清理MAC下CLion的安装记录

今天MAC下安装CLion编译EOS,结果一运行就推出,怀疑是之前安装过,有什么本地的记录,或者授权校验的问题,导致新版本安装后,无法运行。所以得清理下本地的缓存等文件
本地安装的版本为 CLion2018.2

rm -rfv ~/Library/Preferences/clion2018.2
rm -rfv ~/Library/Caches/clion2018.2
rm -rfv ~/Library/Application\ Support/clion2018.2
rm -rfv ~/Library/Logs/clion2018.2

参考文件 https://gist.githubusercontent.com/denji/9731967/raw/jetbrains-uninstall.sh


最简单的试用CLion的方式
编辑hosts

vim /private/etc/hosts

0.0.0.0 account.jetbrains.com添加到文件尾部
然后到http://idea.lanyus.com/ 获取注册码,然后到CLion 输入Activation code 即可

以传统的WEB开发方式,来举例理解Dapp开发

前言

常规的讲解DApp开发的文章,大都直接从区块链方式讲起,对于没有接触过区块链的同学,可能不太好理解,今天我们尝试从传统的web开发,对比讲解DApp开发。

对于目前常见的DApp大都是以Web的形式,其实DApp并不局限于Web形式,也可以是PC客户端,也可以是App。为了更好理解和演示,我们将以常见的Web形式的DApp讲起。

演示实例

我们将要演示的DApp例子为,一个计算器,合约中计算两个输入的值,并将值存入链上,并提供查询的接口。

如果我们拿常规的Web去实现下这个App。基本分为3部分,前端(获取输入的值),服务器Api接收程序(接收前端输入的值,并计算结果,并将结果写入数据库,以及提供查询的接口),数据库(存储计算后的值)。

实现和部署对比

实现 Web App Web DApp
前端 普通html 普通html
服务器Api接收程序 php开发的api程序 执行链上部署的合约
数据库 mysql 写入链上对应的RAM
服务器部署 云服务器 前端放在云服务器,合约部署在EOS网络

传统Web实现

1.前端

<form method="post" name="form" action="http://www.xxx.xx/postGet.php">
  <table >
      <tr>
       <td>第一个参数:</td>
       <td><input type="text" name="FirstParm"/></td>
      </tr>
      <tr>
       <td>第二个参数:</td>
       <td><input type="text" name="SecondParm"/></td>
      </tr>
      <tr>
       <td><input type="submit" name="Submit" value="计算两数和"/></td>
      </tr>
  </table>
</form>

2.创建数据库

CREATE DATABASE results;
CREATE TABLE result(name CHAR(13), iresult int);

3.Api接收程序

    <?php
    $firstparm = $_POST[FirstParm'];
    $secondparm = $_POST['SecondParm'];
    $result = $firstparm + $secondparm;
        $con = mysql_connect("localhost","cryptokylinq","5KKu8Nmm4XUavcZFzpvdGG5Mc9Rkg6LiwxuqXkSokEHKSXKXs9b");
        if (!$con) {
          die('Could not connect: ' . mysql_error());
          }
        mysql_select_db("results", $con);
        mysql_query("INSERT INTO result (iresult) VALUES ($result)");
        mysql_close($con);
    ?>

查询

    <?php
    $con = mysql_connect("localhost","cryptokylinq","5KKu8Nmm4XUavcZFzpvdGG5Mc9Rkg6LiwxuqXkSokEHKSXKXs9b");
    if (!$con) {
      die('Could not connect: ' . mysql_error());
      }
    mysql_select_db("results", $con);
    $result = mysql_query("SELECT * FROM result");
    while($row = mysql_fetch_array($result)) {
      echo $row['iresult'] ;
      echo "<br />";
      }
    mysql_close($con);
    ?>

上面三步简单的完成了,常规Web的计算,写入,查询操作。

Web DApp实现

1.编写合约

//Calculator.hpp
#include <eosiolib/asset.hpp>
#include <eosiolib/eosio.hpp>
#include <eosiolib/print.hpp>

class Calculator : public eosio::contract {
public:
    Calculator(account_name self)
            : eosio::contract(self)
            ,results(_self, _self){}

public:
    void doit(account_name from, const uint64_t firstParm, const uint64_t secoundParm);

private:
//@abi table results i64
    struct result{
        account_name name;
        uint8_t iresult;
        uint64_t primary_key()const { return name; }
        EOSLIB_SERIALIZE(result, (name)(iresult))
    };

    typedef eosio::multi_index<N(results),result> result_table;
    result_table results;
};
EOSIO_ABI( Calculator, (doit) )
#include "Calculator.hpp"


void Calculator::doit(account_name from, const uint64_t firstParm, const uint64_t secoundParm){
    require_auth(from);

    eosio_assert(firstParm >= 1, "firstParm mast >= 0"); //没有实际意义 只是做个数值的判断演示
    auto account_itr = results.find(from);
    if(account_itr == results.end()){
        account_itr = results.emplace(_self, [&](auto& result){
            result.name = from;
            result.iresult = firstParm + secoundParm;
        });
    }
    else{
        results.modify(account_itr, 0, [&](auto& result) {
            result.iresult = firstParm + secoundParm;
        });
    }
}

合约中包含了数据库的创建格式,合约部署后,相当于,数据库也创建好了,以及数据写入需要执行的api接口

2.合约编译,需要将合约初步编译,才能部署到链上

  • 生成API文件
    suroudeMacBook-Pro:Calculator surou$ eosiocpp -g Calculator.abi Calculator.cpp
  • 生成WAST文件
    suroudeMacBook-Pro:Calculator surou$ eosiocpp -o Calculator.wast Calculator.cpp

    执行完成后目录文件如下

    suroudeMacBook-Pro:Calculator surou$ ls
    Calculator.abi  Calculator.cpp  Calculator.hpp  Calculator.wasm Calculator.wast

3.创建麒麟测试网的测试账号,用于合约的部署,以及使用资源的购买

  • 创建账号:http://faucet.cryptokylin.io/create_account?new_account_name
    比如我们要创建的账号为cryptokylinq,访问链接:http://faucet.cryptokylin.io/create_account?cryptokylinq
    {
      msg: "succeeded",
      keys: - {
      active_key: - {
          public: "EOS6L7pr3AaKekTs1dbratDq1PutoSdmBWJFwbLcStsnKBbJtNUws",
          private: "5KKu8Nmm4XUavcZFzpvdGG5Mc9Rkg6LiwxuqXkSokEHKSXKXs9b"
      },
      owner_key: - {
          public: "EOS89vNXgGrkM4GYFAav78FgnX94QzVXYtcEKiKicSq4YcykPmnC7",
          private: "5KZbLRwZAZQJQKS6sM1RL1d2Af9s49zA9qka9f63ce7J2jUDWwQ"
      }
      },
      account: "cryptokylinq"
    }

    一个账号一般有两对秘钥,对应两个权限owner(类似网站后台的超级管理员)和active(部分权限的管理员),当然还可以创建多个自由配置权限的秘钥对。在EOS网络里,谁拥有这个私钥,谁就拥有对应账号的对应权限。相同的秘钥对可以创建多个账号。

  • 申请测试的EOS代币,访问 http://faucet.cryptokylin.io/get_token?cryptokylinq
    {
      msg: "succeeded"
    }
  • 查询账户余额 https://tools.cryptokylin.io/#/tx/

申请来的测试EOS代币,将用于购买EOS网络上的CPU,NET,RAM资源(RAM为购买,CPU和NET是按抵押EOS多少,计算分配你多少资源使用)。相当于云服务器中的增加对应的硬件资源。CPU和NET与云服务中的一样,计算和网络资源。RAM相当于云服务器中的RAM+磁盘存储,比如发起交易时会临时消耗,隔一段时间(暂时未确定恢复时间的规则,应该小于三天,稍后查证后,在做补充),如果是合约存储数据,那就相当于写入了磁盘,如果数据不删除的话,会持续占用。

下面开始购买所需的资源,之前统计一般部署合约需要消耗300k左右的 RAM(包含临时消耗)。 CPU和NET基本分别抵押 0.1EOS就可以了。

由于我们要操作账号,所以我们要先创建个钱包,可以使用eosio 自带的keosd,也可以使用其他三方的app 钱包中购买资源。
我们在开发环境,所以直接使用keosd操作了,

  • 创建钱包
    suroudeMacBook-Pro:eosio-wallet surou$ cleos  wallet create --to-console
    Creating wallet: default
    Save password to use in the future to unlock this wallet.
    Without password imported keys will not be retrievable.
    "PW5HxNY7tKndZp8c96afmhaHezq2CA9x1dbziYXzJcvK7sVdf7kQq"

    记得备份这个钱包的解锁密码"PW5HxNY7tKndZp8c96afmhaHezq2CA9x1dbziYXzJcvK7sVdf7kQq"

  • 将上面创建的账号cryptokylinq的私钥导入新创建的钱包 (一般常规操作只需要导入active权限的私钥)
    suroudeMacBook-Pro:eosio-wallet surou$ cleos wallet import
    private key: imported private key for: EOS6L7pr3AaKekTs1dbratDq1PutoSdmBWJFwbLcStsnKBbJtNUws

    导入完成后,购买所需的RAM,CPU,NET资源
    购买10EOS的RAM

    suroudeMacBook-Pro:contracts surou$ cleos -u http://kylin.fn.eosbixin.com system buyram cryptokylinq cryptokylinq "10 EOS"
    executed transaction: d59370bcb3dbf1d3aaa1b5c92de23283603c6d9bfc2e38e8def5e0de8eabe6e1  128 bytes  1511 us
    #         eosio <= eosio::buyram                {"payer":"cryptokylinq","receiver":"cryptokylinq","quant":"10.0000 EOS"}
    #   eosio.token <= eosio.token::transfer        {"from":"cryptokylinq","to":"eosio.ram","quantity":"9.9500 EOS","memo":"buy ram"}
    #  cryptokylinq <= eosio.token::transfer        {"from":"cryptokylinq","to":"eosio.ram","quantity":"9.9500 EOS","memo":"buy ram"}
    #     eosio.ram <= eosio.token::transfer        {"from":"cryptokylinq","to":"eosio.ram","quantity":"9.9500 EOS","memo":"buy ram"}
    #   eosio.token <= eosio.token::transfer        {"from":"cryptokylinq","to":"eosio.ramfee","quantity":"0.0500 EOS","memo":"ram fee"}
    #  cryptokylinq <= eosio.token::transfer        {"from":"cryptokylinq","to":"eosio.ramfee","quantity":"0.0500 EOS","memo":"ram fee"}
    #  eosio.ramfee <= eosio.token::transfer        {"from":"cryptokylinq","to":"eosio.ramfee","quantity":"0.0500 EOS","memo":"ram fee"}

CPU NET分别抵押10 EOS (实际使用量,一般在分别1 EOS就够了,测试网不花钱,可劲豪)

suroudeMacBook-Pro:contracts surou$ cleos -u http://kylin.fn.eosbixin.com system delegatebw cryptokylinq cryptokylinq "10 EOS" "10 EOS"
executed transaction: 4df295028046be07f669fd3dca1b496434f5ee36efb0cd6f31a738ff6e7b5602  144 bytes  2021 us
#         eosio <= eosio::delegatebw            {"from":"cryptokylinq","receiver":"cryptokylinq","stake_net_quantity":"10.0000 EOS","stake_cpu_quant...
#   eosio.token <= eosio.token::transfer        {"from":"cryptokylinq","to":"eosio.stake","quantity":"20.0000 EOS","memo":"stake bandwidth"}
#  cryptokylinq <= eosio.token::transfer        {"from":"cryptokylinq","to":"eosio.stake","quantity":"20.0000 EOS","memo":"stake bandwidth"}
#   eosio.stake <= eosio.token::transfer        {"from":"cryptokylinq","to":"eosio.stake","quantity":"20.0000 EOS","memo":"stake bandwidth"}

此时RAM,CPU,NET资源都准备好了,相当于云服务器硬件配置都买好了
下面开始部署合约,相当于传统的Web开发,将API程序部署到云服务器

suroudeMacBook-Pro:contracts surou$ cleos -u http://kylin.fn.eosbixin.com  set contract cryptokylinq Calculator/ -p  
Reading WASM from Calculator/Calculator.wasm...
Publishing contract...
executed transaction: f0086795a65644a96e282b165e1fc146869a37cfd6a2e51528367f7594d4d21f  3056 bytes  1329 us
#         eosio <= eosio::setcode               {"account":"cryptokylinq","vmtype":0,"vmversion":0,"code":"0061736d01000000015d1060047f7e7e7e0060000...
#         eosio <= eosio::setabi                {"account":"cryptokylinq","abi":"0e656f73696f3a3a6162692f312e30000206726573756c740002046e616d65046e6...

下一步我们直接测下合约action接口,相当于直接测试云服务器的API接口

suroudeMacBook-Pro:contracts surou$ cleos -u http://kylin.fn.eosbixin.com  push action cryptokylinq doit '["cryptokylinq","1","2"]' -p cryptokylinq
executed transaction: 7c0de68f77a656f98cd54e03f37dbb00a1a325cee844614968d7d05a2668f36c  120 bytes  1834 us
#  cryptokylinq <= cryptokylinq::doit           {"from":"cryptokylinq","firstParm":1,"secoundParm":2}

查询下结果

suroudeMacBook-Pro:contracts surou$ cleos -u http://kylin.fn.eosbixin.com  get table cryptokylinq cryptokylinq results
{
  "rows": [{
      "name": "cryptokylinq",
      "iresult": 3
    }
  ],
  "more": false
}

可以看到,已经将结果写到了链上 "iresult": 3,相当于常规Web程序数据库中已存入数据
目前此DApp对比常规Web程序已经完成了,API和数据库部分,下面开始完成前端的调用

DApp前端

前端与链交互,是通过rpc进行操作的,并且eosio 官方也提供了 eosjs.js 开发库,方便操作。
html中调用的关键js代码为

import EOS from 'eosjs'
const EOS_CONFIG = {
  contractName: "cryptokylinq", // Contract name 更好理解的应该是合约的部署所在的账号名
  contractReceiver: "cryptokylinq", // User executing the contract (should be paired with private key)
  clientConfig: {
    keyProvider: '5KKu8Nmm4XUavcZFzpvdGG5Mc9Rkg6LiwxuqXkSokEHKSXKXs9b', // Your private key
    httpEndpoint: 'http://api-kylin.starteos.io', // EOS http endpoint
    chainId: '5fff1dae8dc8e2fc4d5b23b2c7665c97f9e9d8edf2b6485a86ba311c25639191'
  }
}
//执行合约
DoContract(){
let eosClient = EOS(EOS_CONFIG.clientConfig)
    eosClient.contract(EOS_CONFIG.contractName)
      .then((contract) => {
      //执行链上合约
        contract.doit(EOS_CONFIG.contractReceiver,"1","2", { authorization: [EOS_CONFIG.contractReceiver] })
          .then((res) => { console.log("Success") })
          .catch((err) => {console.log("Fail"); console.log(err) })
      })
}

查询结果

eos.getTableRows(true,"cryptokylinq","cryptokylinq","results")

返回

{
    "rows":[
        {
        "name":"cryptokylinq",
        "iresult":3
        }
    ],
        "more":false
}

至此完成了DApp从合约编写,合约部署,账号创建,合约调用,eosjs使用,一整套简单的流程。

EOS开发库收集(持续更新)

开发语言

C Sharp

  • https://github.com/GetScatter/eos-sharp

    Eos eos = new Eos(new EosConfigurator()
    {    
      HttpEndpoint = "https://nodes.eos42.io", //Mainnet
      ChainId = "aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906",
      ExpireSeconds = 60,
      SignProvider = new DefaultSignProvider("myprivatekey")
    });
  • https://github.com/eosnewyork/EOSDotNet

      var chainAPI = new ChainAPI("https://api.eosnewyork.io");
    
      string  _code  =  "eosio.token", _action  =  "transfer", _memo  =  "";
      TransferArgs  _args  =  new  TransferArgs(){ from  =  "account1", to  =  "account2", quantity  =  "1.0000 EOS", memo  =  _memo };
    
      //called asynchronously
      var abiJsonToBinAsync = await chainAPI.GetAbiJsonToBinAsync(_code, _action, _args);
      //called synchronously
      var abiJsonToBinSync = chainAPI.GetAbiJsonToBin(_code, _action, _args);

    Go

  • https://github.com/eoscanada/eos-go

      api := eos.New("http://testnet1.eos.io")
    
      infoResp, _ := api.GetInfo()
      accountResp, _ := api.GetAccount("initn")
      fmt.Println("Permission for initn:", accountResp.Permissions[0].RequiredAuth.Keys)

Python

  • https://github.com/EvaCoop/eosjs_python

      from eosjs_python import Eos
    
      eos = Eos({
          'http_address': 'http://172.18.0.1:8888',
          'key_provider': '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3'
      })
    
      eos.newaccount({
          'creator': 'eosio',
          'name': 'mytestacc13',
          'owner_public_key': 'EOS7vTHtMbZ1g9P8BiyAGD7Ni7H6UALVLVCW13xZrXT4heCBke3it',
          'active_public_key': 'EOS8KKKYBBdwrmXRRynDXSxTX2qoT9TA4agahXXF4ccUgRCy81RNc',
          'buyrambytes_bytes': 8192,
          'delegatebw_stake_net_quantity': '100.0000 SYS',
          'delegatebw_stake_cpu_quantity': '100.0000 SYS',
          'delegatebw_transfer': 0
      })
  • https://github.com/eosnewyork/eospy

      # Get chain information
      pycleos --url https://api.eosnewyork.io get info
    
      # get information about a block
      pycleos --url https://api.eosnewyork.io get block 447
    
      # Retrieve an account from the blockchain
      pycleos --url https://api.eosnewyork.io get account --account eosio
    
      # Retrieve the code and ABI for an account
      pycleos --url https://api.eosnewyork.io get code --account eosio

PHP

  • https://github.com/zyq20130111/eos_php

      /* Create the rest client */
      EosApiRestClient eosApiRestClient = EosApiClientFactory.newInstance("http://127.0.0.1:8888").newRestClient();
    
      /* Create the json array of arguments */
      Map<String, String> args = new HashMap<>(4);
      args.put("from", "currency");
      args.put("to", "eosio");
      args.put("quantity", "44.0000 CUR");
      args.put("memo", "My First Transaction");
      AbiJsonToBin data = eosApiRestClient.abiJsonToBin("currency", "transfer", args);```
    
      /* Get the head block */
      Block block = eosApiRestClient.getBlock(eosApiRestClient.getChainInfo().getHeadBlockId());

Java

Dapp js 相关