用EOS開(kāi)發(fā)一個(gè)To-do List小應(yīng)用

EOS Asia

本教程作者為 EOS Asia,亞洲最具技術(shù)實(shí)力和最國(guó)際化的 EOS 超級(jí)節(jié)點(diǎn)競(jìng)選者。EOS Asia 同時(shí)也是 EOS Gems 和 Traffic Exchange Token 這兩個(gè)項(xiàng)目背后的開(kāi)發(fā)者。

本篇是 EOS 智能合約系列第二彈,該系列教程旨在幫助開(kāi)發(fā)者從 0 到 1 快速上手如何在 EOS 生態(tài)下開(kāi)發(fā) DApp。如果有任何希望深入討論的主題,歡迎留言給我們!如果你還不知道怎么在 EOS 下部署智能合約,請(qǐng)先閱讀系列第一彈《EOS智能合約開(kāi)發(fā):第一課

在大部分的應(yīng)用場(chǎng)景中,開(kāi)發(fā)者都需要通過(guò)智能合約與區(qū)塊鏈上“永久保存”的數(shù)據(jù)進(jìn)行交互。本次教程中,我們會(huì)一起通過(guò) To-do List(待辦事項(xiàng))這個(gè)實(shí)例,來(lái)教會(huì)你如何實(shí)現(xiàn)與數(shù)據(jù)交互的標(biāo)準(zhǔn)操作(CRUD - Create, Retrieve, Update, Delete)

深入了解 Boost.MultiIndex

由于 EOS 的智能合約基于 C++,我們需要利用 Boost.MultiIndex Containers這個(gè)庫(kù)。下面是該庫(kù)的說(shuō)明:

Boost多索引容器庫(kù)提供了名為 multi_index_container 的類模板,可以用于建造擁有一個(gè)或多個(gè)索引(indices) 的容器,不同的索引具有不同的排序和訪問(wèn)語(yǔ)義。這些索引都提供了類似于STL容器的接口,因此使用起來(lái)也非常相似。在一組元素之上維護(hù)多個(gè)索引的想法來(lái)自 于關(guān)系數(shù)據(jù)庫(kù),并且考慮到簡(jiǎn)單的 set 和 map 無(wú)法滿足多索引表中的復(fù)雜數(shù)據(jù)結(jié)構(gòu)的規(guī)范。

讓我們把上述的一些概念拆分講解一下,并與開(kāi)發(fā)者所熟知的傳統(tǒng)數(shù)據(jù)庫(kù)概念做類比:

容器(Containers)

包含很多元素的類(table/表)

元素(Elements)

數(shù)據(jù)對(duì)象(rows in a table/表中的行)

接口(Interface)

容器讀取元素的方法(query/查詢)

在 EOS 智能合約中,可以使用eosio::multi_index?來(lái)定義多索引容器。如果我們讀一讀使用了這個(gè)特性的一些合約例子,比如這個(gè)“骰子合約”:

https://github.com/EOSIO/eos/blob/master/contracts/dice/dice.cpp

你會(huì)發(fā)現(xiàn)很難真正搞明白到底是哪一部分是在處理區(qū)塊鏈上的數(shù)據(jù)。不過(guò)別擔(dān)心,我們會(huì)帶你理解它,很快你就能自己實(shí)現(xiàn)一個(gè)有存儲(chǔ)功能的智能合約。

我們將通過(guò)開(kāi)發(fā)一個(gè)To-do List (待辦事項(xiàng)表)小 DApp 來(lái)理解上述的內(nèi)容。從功能上,要能勾掉已經(jīng)完成的事情,添加新事項(xiàng),以及刪除不需要的事項(xiàng)。在這個(gè)例子中,我們將用?todos?作為容器名,todo?作為元素結(jié)構(gòu)。

從初始化第一個(gè)容器為開(kāi)始,首先,我們向?eosio::multi_index?傳入兩個(gè)模板參數(shù)。第一個(gè)參數(shù)是我們的容器名,第二個(gè)參數(shù)是定義元素的數(shù)據(jù)結(jié)構(gòu)。來(lái)給我們的 todo 模型創(chuàng)建一個(gè)小例子,如下:

struct todo {

?uint64_t id;

?uint64_t primary_key() const { return id; }

?EOSLIB_SERIALIZE(todo, (id))

};

typedef eosio::multi_index todo_table;

todo_table todos;

簡(jiǎn)單有效!我們簡(jiǎn)單地定義了一個(gè) 64 位無(wú)符號(hào)整型的 ID,并通過(guò) primary_key 來(lái)訪問(wèn)它。把多索引定義成 typedef,暫時(shí)還不需要把它實(shí)例化。目前為止,這個(gè) todo 模型里面還沒(méi)有什么東西,下面來(lái)添加一些參數(shù):

struct todo {

?uint64_t id;

?std::string description;

?uint64_t completed;

?EOSLIB_SERIALIZE(todo, (id)(description)(completed))

};

typedef eosio::multi_index todo_table;

todo_table todos;

現(xiàn)在我們更近了一步,加入了待辦事項(xiàng)的描述參數(shù)-?description?(比如 “完成小說(shuō)撰寫(xiě)”)和狀態(tài)參數(shù)-?completed(用來(lái)記錄一個(gè)事項(xiàng)在當(dāng)前是否完成了)。

為了方便自動(dòng)生成我們的ABI(Application Binary Interface),我們?cè)谌萜鞫x前面加一行注釋來(lái)幫助生成器:@abi table profiles i64

那么在注釋里的i64是什么意思呢,它是我們的查詢索引。默認(rèn)情況下,我們需要一種在容器里查詢?cè)氐姆椒?,而我們的?4位(64位類型下,基本上是first key)就可以用來(lái)干這件事。一般情況下都用uint64_t id;對(duì)于first key,也可以用account_name類型,因?yàn)樵诘讓悠鋵?shí)account_name類型也是一個(gè)uint64_t類型。參考如下:

https://github.com/EOSIO/eos/blob/2f2c8c7e3811caca178a7553192c8fe59a22576d/contracts/eosiolib/types.h#L22

此時(shí)我們應(yīng)該有了一個(gè)功能簡(jiǎn)單的容器, 代碼看起來(lái)是這樣的:

// @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 todo_table;

todo_table todos;

使用你的新容器

現(xiàn)在已經(jīng)有了一個(gè)定義好的容器,我們可以使用它里面的元素。在智能合約里,將通過(guò)不同的函數(shù)與這些元素進(jìn)行交互。

對(duì)于鏈上的永久性儲(chǔ)存有四種基本函數(shù):創(chuàng)建(Create),檢索 (Retrieve),更新 (Update),刪除 (Delete)。 在這個(gè)例子里,我們不需要考慮檢索,因?yàn)闄z索是由前端讀取合約來(lái)處理的而不用函數(shù)。對(duì)其他的三個(gè),我們將分別創(chuàng)建函數(shù)。

創(chuàng)建(Create)- 創(chuàng)建事項(xiàng)

添加一個(gè)待辦事項(xiàng)進(jìn)入列表

可以用?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");

}

一個(gè)重要細(xì)節(jié)是我們把 author 作為一個(gè)參數(shù)也傳入了。在?emplace?方法中第一個(gè)參量是必須的。

更新(Update)- 完成事項(xiàng)

創(chuàng)建一個(gè)完成事項(xiàng)的函數(shù)可以通過(guò)更新參數(shù) completed 的狀態(tài)來(lái)實(shí)現(xiàn):

// @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)- 刪除事項(xiàng)

這是一個(gè)內(nèi)部調(diào)用的智能合約,不用太擔(dān)心安全性和權(quán)限問(wèn)題。 我們專心搞清楚刪除函數(shù)如何最簡(jiǎn)化地實(shí)行就可以了:

// @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");

}

部署,測(cè)試,與前端打通

在上一篇教程中,我們用一個(gè)簡(jiǎn)單的 ping/pong 實(shí)例講述了如何將一個(gè) EOS 的智能合約與網(wǎng)頁(yè)前端連接起來(lái)?,F(xiàn)在我們有了幾個(gè)與區(qū)塊鏈上的永久性數(shù)據(jù)交互的函數(shù),下面可以為這個(gè)待辦事項(xiàng)制作一個(gè)前端了。

部署

部署合約的過(guò)程比較直觀,就下面這幾步:

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.user

3.?測(cè)試合約也很簡(jiǎn)單:

$ 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 created

4.?獲取數(shù)據(jù):

$ cleos get table todo todo todos

在前端測(cè)試

在這里我們就節(jié)省讀者的時(shí)間,不在文章中深究 React.js 的代碼了,不過(guò)我強(qiáng)烈推薦大家去看下這個(gè)例子的代碼倉(cāng)庫(kù),里面有前端部分的全部代碼:?

https://github.com/eosasia/eos-todo

筆記來(lái)源:https://bihu.com/article/402751

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 學(xué)習(xí)區(qū)塊鏈,最刺激的莫過(guò)于發(fā)幣,第一篇文章里介紹了如何搭建EOS開(kāi)發(fā)環(huán)境,第二篇文章我們已經(jīng)介紹了如何部署調(diào)用合約...
    P叔閱讀 4,973評(píng)論 5 6
  • 1 EOS智能合約的介紹1.1 所需背景知識(shí)1.2 EOS智能合約基礎(chǔ)知識(shí)1.3 技術(shù)局限性 2 智能合約文件2....
    cenkai88閱讀 30,966評(píng)論 5 28
  • 1. 賬戶與錢包1.1 創(chuàng)造并管理錢包1.2 生成EOS Keys并導(dǎo)入1.3 備份您的錢包1.4 創(chuàng)建賬戶 2....
    cenkai88閱讀 4,145評(píng)論 1 7
  • 先啰嗦幾句:本人區(qū)塊鏈小白一枚,正在自學(xué)EOS應(yīng)用開(kāi)發(fā)(當(dāng)然目前也沒(méi)有培訓(xùn)班培訓(xùn)),我的這個(gè)系列文章是我的學(xué)習(xí)筆記...
    面壁者Z閱讀 2,829評(píng)論 1 3
  • 第十八章 覺(jué)醒(三)這是個(gè)問(wèn)題 第十九章 小小心事 哪怕是在一千年后,李袈瀾依然記得當(dāng)日的情形。 沖天的紅光下,明...
    筆間流年閱讀 664評(píng)論 1 1

友情鏈接更多精彩內(nèi)容