EOS:入门踩坑之理解ABI 5

继续跟随EOS开发者教程:https://developers.eos.io/eosio-home/docs 从踩坑中进步(就怕项目黄了…),踩坑的总体思路是:学习 -> 开发dapp->源码
本文仅代表个人观点,不足之处还望大神们谅解。
The Application Binary Interface (ABI) is a JSON-based description on how to convert user actions between their JSON and Binary representations. 应用程序二进制接口是基于JSON,描述怎样转换用户动作和JSON,二进制文件。
The ABI also describes how to convert the database state to/from JSON. Once you have described your contract via an ABI then developers and users will be able to interact with your contract seamlessly via JSON.
ABI也描述怎样将数据状态转换为JSON,讲的是你通过ABI描述了合约,别人就能自由的通过JSON使用它。有时候C++的高级特性,工具无法生成ABI,这个时候只能自己手动调试生成了。

这是eosio.token.cpp生成的ABI
{
   "version": "eosio::abi/1.0",
   "types": [{
      "new_type_name": "account_name",
      "type": "name"
   }],
  "structs": [{
      "name": "transfer",
      "base": "",
      "fields": [
        {"name":"from", "type":"account_name"},
        {"name":"to", "type":"account_name"},
        {"name":"quantity", "type":"asset"},
        {"name":"memo", "type":"string"}
      ]
    },{
     "name": "create",
     "base": "",
     "fields": [
        {"name":"issuer", "type":"account_name"},
        {"name":"maximum_supply", "type":"asset"}
     ]
  },{
     "name": "issue",
     "base": "",
     "fields": [
        {"name":"to", "type":"account_name"},
        {"name":"quantity", "type":"asset"},
        {"name":"memo", "type":"string"}
     ]
  },{
      "name": "account",
      "base": "",
      "fields": [
        {"name":"balance", "type":"asset"}
      ]
    },{
      "name": "currency_stats",
      "base": "",
      "fields": [
        {"name":"supply", "type":"asset"},
        {"name":"max_supply", "type":"asset"},
        {"name":"issuer", "type":"account_name"}
      ]
    }
  ],
  "actions": [{
      "name": "transfer",
      "type": "transfer",
      "ricardian_contract": ""
    },{
      "name": "issue",
      "type": "issue",
      "ricardian_contract": ""
    }, {
      "name": "create",
      "type": "create",
      "ricardian_contract": ""
    }

  ],
  "tables": [{
      "name": "accounts",
      "type": "account",
      "index_type": "i64",
      "key_names" : ["currency"],
      "key_types" : ["uint64"]
    },{
      "name": "stat",
      "type": "currency_stats",
      "index_type": "i64",
      "key_names" : ["currency"],
      "key_types" : ["uint64"]
    }
  ],
  "ricardian_clauses": [],
  "abi_extensions": []
}

1.ABI文件格式

{
   "version": "eosio::abi/1.0",     // 版本
   "types": [],                             //类型
   "structs": [],                          //结构
   "actions": [],                         //动作
   "tables": [],                          //列表
   "ricardian_clauses": [],
   "abi_extensions": [],      //ABI扩展
   "___comment" : ""       //注释
}

2.ABI的组成元素
a.types

For this to work in a consistent manner, describe the custom types that are used as a parameter in any public action or struct that needs to be described in the ABI.

这里官方提供了内置类型,不需要在ABI中描述出来。
https://github.com/EOSIO/eos/blob/master/libraries/chain/abi_serializer.cpp#L65-L103

{
     "new_type_name":"name",
     "type" : "name"
   }

b.struct

creat 动作的ABI文件描述:
从源码分析可以得出struct用于描述函数名字,参数类型,继承关系。

{
  "name": "create",   // 名字
     "base": "",           //继承,父结构
     "fields": [
        {"name":"issuer", "type":"account_name"},
        {"name":"maximum_supply", "type":"asset"}
     ]
  }

Fields ,从下面源码中我们能看出fields主要是描述函数参数的一个数组。
void create( name issuer,asset maximum_supply);
参数类型名 name 参数 issuser

{
   "name":"", // The field's name  函数参数
   "type":""   // The field's type  函数类型
} 

eosio.token.cpp

void token::create( name   issuer,
                    asset  maximum_supply )
{
    require_auth( _self );

    auto sym = maximum_supply.symbol;
    eosio_assert( sym.is_valid(), "invalid symbol name" );
    eosio_assert( maximum_supply.is_valid(), "invalid supply");
    eosio_assert( maximum_supply.amount > 0, "max-supply must be positive");

    stats statstable( _self, sym.code().raw() );
    auto existing = statstable.find( sym.code().raw() );
    eosio_assert( existing == statstable.end(), "token with symbol already exists" );

    statstable.emplace( _self, [&]( auto& s ) {
       s.supply.symbol = maximum_supply.symbol;
       s.max_supply    = maximum_supply;
       s.issuer        = issuer;
    });
}

再看这个例子:

 void transfer( name    from,
                        name    to,
                        asset   quantity,
                        string  memo );

 "structs": [{
      "name": "transfer",
      "base": "",
      "fields": [
        {"name":"from", "type":"account_name"},
        {"name":"to", "type":"account_name"},
        {"name":"quantity", "type":"asset"},
        {"name":"memo", "type":"string"}
      ]
    }

c. action(动作)

Then describe each action’s type according to its previously described struct. In most situations, the function name and the struct name will be equal, but are not required to be equal.
根据前面的结构描述动作(action)类型,大多数情况下函数名和结构名相等,但不一定非要一样。()

{
  "name": "transfer", 			//The name of the action as defined in the contract
                                                        //在合约中定义的动作名称
  "type": "transfer", 			//The name of the implicit struct as described in the ABI
                                                         //ABI中描述隐性结构定义的民称
  "ricardian_contract": "" 	//An optional ricardian clause to associate to this action describing its intended functionality.
  //
}

例:

{
      "name": "issue",
      "type": "issue",
      "ricardian_contract": ""
    

d. TABLE (表)

结构如下:

{
  "name": "",       //The name of the table, determined during instantiation. 
                          //表名,在实例化过程中确定
  "type": "", 			//The table's corresponding struct  //表的对应结构
                                       
  "index_type": "", //The type of primary index of this table //表的首个索引类型
  "key_names" : [], //An array of key names, length must equal length of key_types member  //键名的数组,长度必须等于key_types成员的长度
  "key_types" : []  //An array of key types that correspond to key names array member, length of array must equal length of key names array.
  //与键名数组成员相对应的键类型数组,数组的长度必须等于键名数组的长度。
}

这是eosio.token合约中的两张表,account 和 stas。

 {
      "name": "accounts",
      "type": "account",    //对应先前定义的结构
      "index_type": "i64",
      "key_names" : ["currency"],
      "key_types" : ["uint64"]
    }

The accounts table is an i64 index, based on the account struct, has a uint64 as it’s primary key

{
      "name": "stat",
      "type": "currency_stats",//对应先前定义的结构
      "index_type": "i64",
      "key_names" : ["currency"],
      "key_types" : ["uint64"]
    }
  

The stat table is an i64 index, based on the currenct_stats struct, has a uint64 as it’s primary key

Ricardian Clauses (李嘉图条款)

Ricardian clauses describe the intended outcome of a particular actions. It may also be utilized to establish terms between the sender and the contract.
李嘉图条款描述了特定行为的预期结果。它也可以用于在发送方和合同之间建立条款。(来源百度翻译)不是很明白。。。。
ABI Extensions(AB扩展)
暂时没用

把上边的成员放在一起,就是一个ABI文件了。

二 : 描述其他合约

vectors
When describing a vector in your ABI file, simply append the type with [], so if you need to describe a vector of permission levels, you would describe it like so: permission_level[]
对于vectors合约。简单的添加一个类型[],如果你需要描述vectors的权限等级,可以:permission_level[]

Struct Base (父结构)

It’s a rarely used property worth mentioning. You can use base ABI struct property to reference another struct for inheritance, as long as that struct is also described in the same ABI file. Base will do nothing or potentially throw an error if your smart contract logic does not support inheritance.
主要是关于结构继承的。。。。(很少被使用)

维护:每次更新合约,都要记得更新ABI文件。

你可能感兴趣的:(EOS学习)