ABI 文件

ABI 是什麼

ABI 全稱 Application Binary Interface,中文名“應用程序二進制接口”,顧名思義是一個接口文件,描述了智能合約與上層應用之間的數據交換格式。ABI 文件格式類似 JSON,具備很好的可讀性,有利於智能合約工程師與上層應用工程師之間的工作銜接。

智能合約 ABI 文件由 5 部分組成:

1
2
3
4
5
6
7
{
"version": "eosio::abi/1.0",//定義 ABI 的版本號
"types":[...], //定義類型的別名
"structs":[...], //各個類型的數據結構
"actions":[...], //智能合約的 action
"tables":[...] //數據結構體
}

我們將按照 actions -> tables -> structs -> types 的順序瞭解 DMC 智能合約 ABI 的開發方法。

ABI 開發

actions

action 部分的作用是聲明智能合約有哪些可以調用的 action。如下所示。

1
2
3
4
5
"actions": [{
"name": "hi",
"type": "hi",
"ricardian_contract": ""
}]

其中每一項的 name 就是 action 的名字,type 用來在 structs 中查找數據結構,ricardian_contract 是李嘉圖合約。

李嘉圖合約是一種特殊的結構化文本,主要用作交易中明確雙方的意圖。在 DMC 上,你所發送的每一條action,都是可以附加上合約。這種合約很特殊,有著固定的格式,既能夠被程序讀取,也能為人類閱讀。這一合約,就叫做李嘉圖合約。

注意: 目前 action 中 name 命名規則約束:只支持數字1~5和小寫英文字母;字符長度最大為12。

後期如果改動,我們會及時修改文檔的。

tables

tables 列出了智能合約中需要建立的數據表名稱,以及數據表中所儲存的結構體名稱。

1
2
3
4
5
6
7
"tables": [{
"name": "players",
"type": "player",
"index_type": "i64",
"key_names": ["id"],
"key_types": ["int64"]
}]

上述代碼構造了一個 table 名是 players,結構體類型是 player,主鍵名稱是 id,類型是 int64 的數據表。

structs

structs 部分的內容與 actions 部分的內容存在一一對應的關係,剛才我們在上方 actions 中,聲明瞭一個 action 的名稱,我們還要在 structs 裡聲明各個 action 需要傳入的參數,如下所示。

1
2
3
4
5
6
7
8
"structs":  [{
"name": "shape",
"base": "",
"fields": [{
"name": "area",
"type": "flout64"
}]
}]
1
2
3
4
5
6
7
8
"structs":  [{
"name": "colorshape",
"base": "shape",
"fields": [{
"name": "color",
"type": "int64"
}]
}]

通過 base 字段繼承相當於:

1
2
3
4
5
6
7
8
9
10
11
"structs":  [{
"name": "colorshape",
"base": "",
"fields": [{
"name": "area",
"type": "flout64"
},{
"name": "color",
"type": "int64"
}]
}]

DMC 系統會根據 actions 部分中聲明的 type ,在 structs 部分尋找對應的數據結構,每個數據結構的 fields 中,會列出每個參數的名稱和類型。

除此以外,不光是 actions 裡的項目需要在 structs 裡列出詳細的數據結構,tables 中的項目也需要。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"structs": [{
"name": "player",
"base": "",
"fields": [{
"name": "nickname",
"type": "my_account_name"
}, {
"name": "age",
"type": "int32"
}]
}, {
"name": "hi",
"base": "",
"fields": [{
"name": "nickname",
"type": "my_account_name"
}]
}]

這樣,在 structs 中,我們就定義了一個名為 player 的 struct,用來列出數據表 player 包含兩個字段 nicknameage ,類型分別是 my_account_nameint32

types

types 用於自定義數據的類型:

1
2
3
4
{
"new_type_name": "my_account_name",
"type": "name"
}

這樣在這個 ABI 文件裡就自定義了一個類型名稱為 my_account_name 的類型,類型是 namenew_type_nametype 是關鍵字,類型 name 是系統定義的數據類型。

總結

這樣,一個完整的 ABI 文件就編寫完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
{
"version": "eosio::abi/1.0",
"types": [{
"new_type_name": "my_account_name",
"type": "name"
}],
"structs": [{
"name": "player",
"base": "",
"fields": [{
"name": "nickname",
"type": "my_account_name"
}, {
"name": "age",
"type": "int32"
}]
}, {
"name": "hi",
"base": "",
"fields": [{
"name": "nickname",
"type": "my_account_name"
}]
}],
"actions": [{
"name": "hi",
"type": "hi",
"ricardian_contract": ""
}],
"tables": [{
"name": "players",
"type": "player",
"index_type": "i64",
"key_names": ["id"],
"key_types": ["int64"]
}]
};

通過該 ABI 文件,我們就定義了一個有 id 、 nickname 、 age 三個字段,類型分別是 int64 、my_account_name 、 int32 ,主鍵是 id 的數據表 player 和一個傳遞參數名是 nickname ,類型是 my_account_name 的名為 hi 的 action 方法。