用EOS开发一个To-do List小应用

EOS Asia

本教程作者为 EOS Asia,亚洲最具技术实力和最国际化的 EOS 超级节点竞选者。EOS Asia 同时也是 EOS Gems 和 Traffic Exchange Token 这两个项目背后的开发者。

本篇是 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 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 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 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.user

3. 测试合约也很简单:

$ 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. 获取数据:

$ cleos get table todo todo todos

在前端测试

在这里我们就节省读者的时间,不在文章中深究 React.js 的代码了,不过我强烈推荐大家去看下这个例子的代码仓库,里面有前端部分的全部代码: 

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

笔记来源:https://bihu.com/article/402751

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,907评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,546评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,705评论 0 238
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,624评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,940评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,371评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,672评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,396评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,069评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,350评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,876评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,243评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,847评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,004评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,755评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,378评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,266评论 2 259

推荐阅读更多精彩内容