iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 29
0
Blockchain

又LAG的EOS.IO技術筆記系列 第 29

EOS智能合約範例-TODO工作事項管理合約

這份合約是參考Building a To-do list with EOS而來。
原本就已經是舊的寫法。這次重寫,連原本使用的v1.4.1使用的方式,有不少也變了。
除了之前提到的,不再需要EOSIO_DISPATCH()(原本沒寫的話,ABI會生成錯誤)。
現在eosio_assert的使用,要改成check。而原本的eosio_assert變得非常的長eosio::internal_use_do_not_use::eosio_assert。他被放到了一個蠻深的地方(建議不要使用了)/images/emoticon/emoticon01.gif
這次看原始碼,才知道這個eosio_assert函式有些特殊。不過,不是會編譯成WASM嗎?
(我只挖到新版本的位置,舊版本的目前要挖有些困難...)

首先,先看看標頭檔:

include/todo.hpp

#include <eosio/eosio.hpp>

using namespace std;
using namespace eosio;

CONTRACT todo : public contract {
  public:
    using contract::contract;

/*
    ACTION create_list(name owner, string list_name);
    ACTION rename_list(name owner, uint64_t id, string new_name);
    ACTION delete_list(name owner, uint64_t id);

    ACTION new_task(uint64_t list_id, string tast_content);
    ACTION update_task(uint64_t list_id, string task_id, string new_status);
    ACTION delete_task(uint64_t list_id, string task_id, string new_status);
*/

    ACTION create(name owner, string task);
    ACTION update(uint64_t id, string new_status);
    ACTION remove(uint64_t id);

  private:
    TABLE task {
      uint64_t id;
      name owner;
      string task;
      string status;
      auto primary_key() const { return id; }
    };
    typedef multi_index<"tasks"_n, task> tasks_table;
};

雖然我很想做一個,可以多個人建立多個待辦清單;在每個清單上,有各自的任務;任務主要有任務內容與狀態。不過這樣合約太過複雜了,不適合作為一個入門的範例,所以決定維持原本,只有建立任務、更新任務狀態和刪除任務,僅這些活動的合約。


然後來看看實現:

src/todo.cpp

#include <todo.hpp>

ACTION todo::create(name owner, string task){
  require_auth(owner);

  tasks_table tasks(_self, _self.value);
  auto id = tasks.available_primary_key();

  tasks.emplace(owner, [&](auto& new_task) {
    new_task.id  = id;
    new_task.task = task;
    new_task.owner = owner;
    new_task.status = "TODO";
  });

  eosio::print("task#", id, " created");
}

ACTION todo::update(uint64_t id, string new_status){
  tasks_table tasks(_self, _self.value);

  auto task_lookup = tasks.find(id);

  eosio::check(task_lookup != tasks.end(), "Todo does not exist");
  //eosio::internal_use_do_not_use::eosio_assert(task_lookup != tasks.end(), "Todo does not exist");
  
  name owner = task_lookup->owner;
  require_auth(owner);

  tasks.modify(task_lookup, eosio::same_payer, [&](auto& row) {
    row.status = new_status;
  });

  eosio::print("todo#", id, " marked as complete");
}

ACTION todo::remove(uint64_t id){
  tasks_table tasks(_self, _self.value);

  auto todo_lookup = tasks.find(id);
  tasks.erase(todo_lookup);

  eosio::print("todo#", id, " destroyed");
}

//EOSIO_DISPATCH(todo, (new_task)(update_task)(delete_task))

關於資料的儲存型態TABLE,基本上應該不難理解。複雜的在於multi_index,不過我想在這個範例還足夠好理解,佔不多做解釋,有問題可以留言問。

對於建立任務

透過tasks.emplace()儲存新任務到合約裡面。比較少人會去注意的是,還得決定由誰支付使用的記憶體空間(記得EOS的三大資源)?這裡,我們而外指定一個Owner,當然也可以由智能合約本身負擔。

另外,其實可以建立多個TABLEtasks_table tasks(_self, _self.value);使用時,第二個參數是scope。不同scope的資料不會互相影響,可以平行處理。不過這裡簡單使用合約本身謹此一個TABLE

對於更新任務:

透過tasks.find(id);找到要更新的任務;tasks.modify()修改任務。在這部份,還需要驗證身份require_auth(owner);,避免被不當修改。

刪除任務

最後,與更新合約做一個對照,故意不驗證身份,讓所有任都可以去刪除任務(tasks.erase();)。


OK,嘗試看看:

https://ithelp.ithome.com.tw/upload/images/20191015/20112470nelSTMZHOl.png


上一篇
分享一些智能合約
下一篇
Scatter 錢包管理管理 - 設定
系列文
又LAG的EOS.IO技術筆記31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言