區塊鏈EOS|智能合約入門4——瞭解數據持久性

點擊查看該系列文章


正文

  本文將使用一個簡單的例子幫助理解EOSIO中的數據持久性。

1. 在你的contract目錄下創建addressbook文件夾,並在其中創建addressbook.cpp文件。

cd /Users/yourUserName/Documents/EOS/contracts
mkdir addressbook
cd addressbook
touch addressbook.cpp

2. 在cpp文件中編寫一個繼承自eosio::contract的addressbook類。
  同時,在public方法中繼承eosio::contract的構造函數。

#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

public:
  using contract::contract;
private:
  
};  

3. 添加person表結構。
  使用name類型來定義一個叫做key的變量,同時,編寫一個叫做primary_key()的方法(返回key的值),於是key就是該結構的主鍵。

struct person {
 name key;
 std::string first_name;
 std::string last_name;
 std::string street;
 std::string city;
 std::string state;

 uint64_t primary_key() const { return key.value;}
};

4. 配置multi_index表。

typedef eosio::multi_index<"people"_n, person> address_index;

  “people”是該表的名稱(_n表示爲name類型),person是前面定義的結構體,address_index是該類型的類型名(後面將使用其實例化表)。


5. 編寫添加修改記錄的方法。

[[eosio::action]]
void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
  require_auth( user ); //只能操作自己的記錄,所以需要驗證操作的記錄是不是自己的。
  //multi_index的實例化需要兩個參數,code和scope。
  //code是擁有該合約的賬戶,scope是用於邏輯上的劃分(目前沒什麼作用)
  address_index addresses(get_self(), get_first_receiver().value);
  //創建一個查詢,使用find()方法查詢user並返回一個迭代器。
  auto iterator = addresses.find(user.value);
  //end()相當於null
  if( iterator == addresses.end() )
  {
    //使用multi_index的emplace方法來添加一條記錄,需要兩個參數:user和callback function。
    //user爲payer,這裏爲添加修改記錄的人;回調函數必須使用lamba函數創建引用。
    addresses.emplace(user, [&]( auto& row ) {
      row.key = user;
      row.first_name = first_name;
      row.last_name = last_name;
      row.street = street;
      row.city = city;
      row.state = state;
    });
  }
  else {
    //使用multi_index的modify方法來修改記錄。
    //回調函數將修改該用戶的記錄。
    addresses.modify(iterator, user, [&]( auto& row ) {
      row.key = user;
      row.first_name = first_name;
      row.last_name = last_name;
      row.street = street;
      row.city = city;
      row.state = state;
    });
  }
}

6. 添加刪除記錄的方法

[[eosio::action]]
void erase(name user) {
    require_auth(user);
    address_index addresses(get_self(), get_first_receiver().value);
    auto iterator = addresses.find(user.value);
    //若結果爲fail,會給出後半部分給出的文字提醒。
    check(iterator != addresses.end(), "Record does not exist");
    //將記錄刪除。
    addresses.erase(iterator);
  }

  完整代碼如下。

#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract("addressbook")]] addressbook : public eosio::contract {

public:

  // addressbook(name receiver, name code,  datastream<const char*> ds): contract(receiver, code, ds) {}
  using contract::contract;

  [[eosio::action]]
  void upsert(name user, std::string first_name, std::string last_name, std::string street, std::string city, std::string state) {
    require_auth( user );
    address_index addresses( get_self(), get_first_receiver().value );
    // print("hi,",get_self());
    print("hello,",get_first_receiver());
    auto iterator = addresses.find(user.value);
    if( iterator == addresses.end() )
    {
      addresses.emplace(user, [&]( auto& row ) {
       row.key = user;
       row.first_name = first_name;
       row.last_name = last_name;
       row.street = street;
       row.city = city;
       row.state = state;
      });
    }
    else {
      addresses.modify(iterator, user, [&]( auto& row ) {
        row.key = user;
        row.first_name = first_name;
        row.last_name = last_name;
        row.street = street;
        row.city = city;
        row.state = state;
      });
    }
  }

  [[eosio::action]]
  void erase(name user) {
    require_auth(user);

    address_index addresses( get_self(), get_first_receiver().value);

    auto iterator = addresses.find(user.value);
    check(iterator != addresses.end(), "Record does not exist");
    addresses.erase(iterator);
  }

private:
  struct [[eosio::table]] person {
    name key;
    std::string first_name;
    std::string last_name;
    std::string street;
    std::string city;
    std::string state;
    uint64_t primary_key() const { return key.value; }
  };
  typedef eosio::multi_index<"people"_n, person> address_index;

};  

7. 編譯並部署到addressbook賬戶
  編譯。

eosio-cpp addressbook.cpp -o addressbook.wasm

  創建一個叫addressbook的賬戶。

cleos create account eosio addressbook EOS6GwYrUANGhouVRR97W8ukiCPX49Z74toqMTTxGH8mViYiPuuPi -p eosio@active

  將合約部署到該賬戶。

cleos set contract addressbook /Users/yourUserName/Documents/EOS/contracts/addressbook -p addressbook@active

  若提示沒有解鎖的錢包,需要先解鎖一下(cleos wallet unlock解鎖默認錢包)。


8. 測試合約
  (1) alice爲自己添加記錄。

cleos push action addressbook upsert '["alice", "alice", "liddell", "123 drink me way", "wonderland", "amsterdam"]' -p alice@active

  結果如下。

executed transaction: 003f787824c7823b2cc8210f34daed592c2cfa66cbbfd4b904308b0dfeb0c811  152 bytes  692 us
#   addressbook <= addressbook::upsert          {"user":"alice","first_name":"alice","last_name":"liddell","street":"123 drink me way","city":"wonde...

  (2) 查詢一下alice的記錄。

cleos get table addressbook addressbook people --lower alice --limit 1

  結果如下。

{
  "rows": [{
      "key": "alice",
      "first_name": "alice",
      "last_name": "liddell",
      "street": "123 drink me way",
      "city": "wonderland",
      "state": "amsterdam"
    }
  ],
  "more": false,
  "next_key": ""
}

  (3) 如果alice想爲bob添加記錄,測試一下。

cleos push action addressbook upsert '["bob", "bob", "is a loser", "doesnt exist", "somewhere", "someplace"]' -p alice@active

  結果是失敗的,顯示如下。

Error 3090004: Missing required authority
Ensure that you have the related authority inside your transaction!;
If you are currently using 'cleos push action' command, try to add the relevant authority using -p option.
Error Details:
missing authority of bob

  (4) alice刪除自己的記錄。

cleos push action addressbook erase '["alice"]' -p alice@active

  顯示如下。

executed transaction: 0a690e21f259bb4e37242cdb57d768a49a95e39a83749a02bced652ac4b3f4ed  104 bytes  1623 us
#   addressbook <= addressbook::erase           {"user":"alice"}
warning: transaction executed locally, but may not be confirmed by the network yet    ]

  再次查詢。

cleos get table addressbook addressbook people --lower alice --limit 1

  結果如下。

{
  "rows": [],
  "more": false,
  "next_key": ""
}

注:參考自官方開發文檔。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章