c++ eos智能合约开发_[EOS智能合约]第二节:用EOS开发一个To-do List小应用
EOS Asia
本教程原文作者為EOS Asia,亞洲最具技術實力和最國際化的EOS超級節點競選者。EOS Asia 同時也是EOS Gems和Traffic Exchange Token這兩個項目背后的開發者。
本文由 DappReview 獲得 EOS Asia 授權進行翻譯并發表。
本篇是EOS智能合約系列第二彈,該系列教程旨在幫助開發者從0到1快速上手如何在EOS生態下開發DApp。如果有任何希望深入討論的主題,歡迎留言給我們!如果你還不知道怎么在EOS下部署智能合約,請先閱讀系列第一彈《[技術教程]EOS智能合約開發:第一節——準備發車》
在大部分的應用場景中,開發者都需要通過智能合約與區塊鏈上“永久保存”的數據進行交互。本次教程中,我們會一起通過 To-do List(待辦事項)這個實例,來教會你如何實現與數據交互的標準操作(CRUD - Create, Retrieve, Update, Delete)
深入了解 Boost.MultiIndex
由于EOS的智能合約基于C++,我們需要利用Boost.MultiIndex Containers這個庫。下面是該庫的說明:
Boost多索引容器庫提供了名為multi_index_container 的類模板,可以用于建造擁有一個或多個索引(indices) 的容器,不同的索引具有不同的排序和訪問語義。這些索引都提供了類似于STL容器的接口,因此使用起來也非常相似。在一組元素之上維護多個索引的想法來自 于關系數據庫,并且考慮到簡單的set和map無法滿足多索引表中的復雜數據結構的規范。讓我們把上述的一些概念拆分講解一下,并與開發者所熟知的傳統數據庫概念做類比:
容器(Containers)
- 包含很多元素的類(table/表)
元素(Elements)
- 數據對象(rows in a table/表中的行)
接口(Interface)
- 容器讀取元素的方法(query/查詢)
在EOS智能合約中,可以使用 eosio::multi_index 來定義多索引容器。如果我們讀一讀使用了這個特性的一些合約例子,比如這個“骰子合約”:
https://github.com/EOSIO/eos/blob/master/contracts/dice/dice.cpp
你會發現很難真正搞明白到底是哪一部分是在處理區塊鏈上的數據。不過別擔心,我們會帶你理解它,很快你就能自己實現一個有存儲功能的智能合約。
我們將通過開發一個To-do List (待辦事項表)小DApp來理解上述的內容。從功能上,要能勾掉已經完成的事情,添加新事項,以及刪除不需要的事項。在這個例子中,我們將用 todos 作為容器名,todo 作為元素結構。
從初始化第一個容器為開始,首先,我們向 eosio::multi_index 傳入兩個模板參數。第一個參數是我們的容器名,第二個參數是定義元素的數據結構。來給我們的todo模型創建一個小例子,如下:
struct todo {uint64_t id;uint64_t primary_key() const { return id; }EOSLIB_SERIALIZE(todo, (id)) };typedef eosio::multi_index<N(todos), todo> todo_table; todo_table todos;簡單有效!我們簡單地定義了一個64位無符號整型的ID,并通過primary_key來訪問它。把多索引定義成typedef,暫時還不需要把它實例化。目前為止,這個todo模型里面還沒有什么東西,下面來添加一些參數:
struct todo {uint64_t id;std::string description;uint64_t completed;EOSLIB_SERIALIZE(todo, (id)(description)(completed)) };typedef eosio::multi_index<N(todos), todo> todo_table; todo_table todos;現在我們更近了一步,加入了待辦事項的描述參數- description (比如 “完成小說撰寫”)和狀態參數- completed(用來記錄一個事項在當前是否完成了)。
為了方便自動生成我們的ABI(Application Binary Interface),我們在容器定義前面加一行注釋來幫助生成器:@abi table profiles i64
那么在注釋里的 i64 是什么意思呢,它是我們的查詢索引。默認情況下,我們需要一種在容器里查詢元素的方法,而我們的前64位(64位類型下,基本上是first key)就可以用來干這件事。一般情況下都用uint64_t id ;對于first key,也可以用 account_name 類型,因為在底層其實 account_name 類型也是一個 uint64_t 類型。參考如下:
https://github.com/EOSIO/eos/blob/2f2c8c7e3811caca178a7553192c8fe59a22576d/contracts/eosiolib/types.h#L22
此時我們應該有了一個功能簡單的容器, 代碼看起來是這樣的:
// @abi table todos i64 struct todo {uint64_t id;std::string description;uint64_t completed;uint64_t primary_key() const { return id; }EOSLIB_SERIALIZE(todo, (id)(description)(completed)) };typedef eosio::multi_index<N(todos), todo> todo_table; todo_table todos;使用你的新容器
現在已經有了一個定義好的容器,我們可以使用它里面的元素。在智能合約里,將通過不同的函數與這些元素進行交互。
對于鏈上的永久性儲存有四種基本函數:創建(Create),檢索 (Retrieve),更新 (Update),刪除 (Delete)。 在這個例子里,我們不需要考慮檢索,因為檢索是由前端讀取合約來處理的而不用函數。對其他的三個,我們將分別創建函數。
創建(Create)- 創建事項
添加一個待辦事項進入列表
可以用 emplace 完成
// @abi action void create(account_name author, const uint32_t id, const std::string& description) {todos.emplace(author, [&](auto& new_todo) {new_todo.id = id;new_todo.description = description;new_todo.completed = 0;});eosio::print("todo#", id, " created"); }一個重要細節是我們把author作為一個參數也傳入了。在 emplace 方法中第一個參量是必須的。
更新(Update)- 完成事項
創建一個完成事項的函數可以通過更新參數completed 的狀態來實現:
// @abi action void complete(account_name author, const uint32_t id) {auto todo_lookup = todos.find(id);eosio_assert(todo_lookup != todos.end(), "Todo does not exist");todos.modify(todo_lookup, author, [&](auto& modifiable_todo) {modifiable_todo.completed = 1;});eosio::print("todo#", id, " marked as complete"); }刪除(Delete)- 刪除事項
這是一個內部調用的智能合約,不用太擔心安全性和權限問題。 我們專心搞清楚刪除函數如何最簡化地實行就可以了:
// @abi action void destroy(account_name author, const uint32_t id) {auto todo_lookup = todos.find(id);todos.erase(todo_lookup);eosio::print("todo#", id, " destroyed"); }部署,測試,與前端打通
在上一篇教程中,我們用一個簡單的ping/pong實例講述了如何將一個EOS的智能合約與網頁前端連接起來。現在我們有了幾個與區塊鏈上的永久性數據交互的函數,下面可以為這個待辦事項制作一個前端了。
部署
部署合約的過程比較直觀,就下面這幾步:
1. 建立合約ABI和WASM:eosiocpp -o hello.wast hello.cpp && eosiocpp -g hello.abi hello.cpp
2. 建立賬戶/錢包:
cleos create account eosio todo.user EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4 EOS7ijWCBmoXBi3CgtK7DJxentZZeTkeUnaSDvyro9dq7Sd1C3dC4 cleos set contract todo.user ../todo -p todo.user3. 測試合約也很簡單:
$ cleos push action todo create '["todo", 1, "hello world"]' -p todo.user executed transaction: bc5bfbd1e07f6e3361d894c26d4822edcdc2e42420bdd38b46a4fe55538affcf 248 bytes 107520 cycles # todo <= todo::create {"author":"todo","id":1,"description":"hello world"} >> todo created4. 獲取數據:
$ cleos get table todo todo todos
在前端測試
在這里我們就節省讀者的時間,不在文章中深究React.js的代碼了,不過我強烈推薦大家去看下這個例子的代碼倉庫,里面有前端部分的全部代碼:
https://github.com/eosasia/eos-todo
如果你希望我們去更深入地探討一些關于瀏覽器前端和EOS智能合約交互的內容,不論是用React、Vue、Angular還是原生Javascript,歡迎留言或者在電報群里告訴我們。
電報群:https://t.me/EOSAsia
DAppReview往期精選
[深度干貨]淺談你們根本不懂的區塊鏈游戲
V神看好的Plasma使用指南第一卷:游戲落地
[技術教程]EOS智能合約開發:第一節——準備發車
爆發前夜的區塊鏈游戲——最大的特洛伊木馬已經進城
[獨家專訪]1周13W交易的EtherGoo開發者James & 你所不知道的數據
區塊鏈游戲生態搶灘登陸戰,誰能拔得頭籌?
總結
以上是生活随笔為你收集整理的c++ eos智能合约开发_[EOS智能合约]第二节:用EOS开发一个To-do List小应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 防止转义_python字符
- 下一篇: 不胖就是腿上的肉太多怎么能瘦下来