iT邦幫忙

2022 iThome 鐵人賽

DAY 5
0
Web 3

Smart-Contract Language: Move系列 第 28

Day 28 Second Example - Create New Project

  • 分享至 

  • xImage
  •  

本篇會帶大家創建一個新項目,並部署到 Aptos 區塊鏈上。

設定部分沿用上一篇的設定即可,所以如果環境有問題的,最好先解決後在開始本篇內容。

會用到許多之前介紹的東西,如果有不熟悉的,記得再回去多看幾次,讓我們開始吧。

1. 創建目錄並使用 Package 進行初始化

$ mkdir userinfo
$ cd userinfo
$ ~/bin/aptos move init --name UserInfo

成功的話會看到資料夾內容如下

sources: 放置 module 的目錄

Move.toml 包的清單文件。包含使用的數據和依賴項地址

userinfo/
├── sources/
└── Move.toml

2. 新增發件人

在 Move.toml 文件新增 sender

| 上面步驟同時會自動將依賴項夾到 AptosFramework package 中

[addresses]
sender = "0x42"

3. 編譯 package

使用下面指令編譯 package,同時也會順便檢查是否正確
$ ~/bin/aptos move compile

如果有任何問題會看到類似下面這警告

Warning: unknown field name found. Expected one of [package, build, addresses, dev-addresses, dependencies, dev-dependencies], but found 'address'

如果一切順利會看到這樣

{
  "Result": []
}

這時候 package 裡會多一層 build 目錄:

build/
└── UserInfo
    ├── bytecode_modules
    ├── source_maps
    └── sources
        └── dependencies
            ├── AptosFramework
                ├── account.move
                ├── coin.move
                ........
            └── MoveStdlib
                ├── string.move
                ├── signer.move
                ├── vector.move
                ........

MoveStdlid - Move 語言的標準庫,例如處理向量和簽名者的函數

AptosFramework - 一組特定於 Aptos 區塊鏈的 coin 模塊,例如用於類似 ERC20 的可替代 token 的模塊,以及 account 用於帳戶元數據的模塊。

4. 資源和儲存

在 Move 裡,每個用戶地址都有自己的對象儲存

可以使用 Move 提供的內置方法來訪問

		/// 檢查對象是否存在於儲存中
    fun exists<T>(addr): bool;
    
    /// 返回對象的只讀引用
    fun borrow_global<T>(addr): &T;

    /// 返回對象的可變引用
    fun borrow_global_mut<T>(addr): &mut T;

    /// 將對象添加到儲存中
    fun move_to<T>(&signer, T);

    /// 從儲存中刪除對象
    fun move_from<T>(addr): T;

要將資源放在用戶地址上,可以使用 &signer 在範圍內擁有參數並調用 move_to 函數。

&signer 數據類型代表當前交易的發送者帳戶,主要用於模塊中的資源儲存和訪問限制,開發者可以使用函數汲取交易發送者的地址。signer::address_of(&signer)

5. 執行

用戶資料

添加一個 UserProfile 資源結構。將其用戶名儲存在 type 中
我們在 userinfo/sources 裡面新增一個名為 Sender.move 的文件,內容如下:

module sender::user_info {
	// 從位於地址 std 上的模塊字符串導入字符串類型
	// std 是 AptosFramework 依賴的傳遞 std 地址,提供給所有 package 使用
    use std::string::String;
    
    struct UserProfile has key { username: String }
}

Move 原生型別沒有 string, 只有 vector<u8>, 但本地標準庫提供一個 String struct 將 vector 包裝在裡面方便給開發者使用。也就是上面使用 std 拿出來的樣式。

方法

我們需要添加 gettersetter 方法給 username

getter:

需要 UserProfile 從用戶全局儲存中檢索對象。我們在之前篇章有介紹過,可以使用 borrow_global() 來實現。

module sender::user_info {
    use std::string::String;
    
    struct UserProfile has key { username: String }
    
    public fun get_username(user_addr: address): String acquires UserProfile {
        borrow_global<UserProfile>(user_addr).username
    }
}

這邊有兩個地方需要注意

  1. 我們使用關鍵字 acquires 在儲存中獲取對象資源的所有函數,都需要要加上此關鍵字,確保對全局儲存的引用是安全的。
  2. 函數內如過只有一行,可以不用加上分號 ;

setter:

setter 的實現有點複雜。setter 將是一個公共入口函數。與只能由其他模塊調用的通常函數不同,入口函數可以通過向 Aptos 區塊鏈發送交易來調用,其中包含函數中的參數、泛型和名稱/路徑。使用公共入口功能。

創建 if 判斷

首先對於全局存儲中沒有的情況UserProfile,if not 我們需要使用正確的用戶名創建一個

els 只更新現有的用戶名user_info

我們使用 entry 代表是公共入口函數

&signer 允許用戶修改個人資料

module sender::user_info {
    use std::string::{String, utf8};
    use std::signer;

    struct UserProfile has key { username: String }

    public fun get_username(user_addr: address): String acquires UserProfile {
        borrow_global<UserProfile>(user_addr).username
    }

    public entry fun set_username(user_account: &signer, username_raw: vector<u8>) acquires UserProfile {
        // 將 username_raw 包裝成 utf8
        let username = utf8(username_raw);

        // 透過 signer 拿到交易發送者地址
        let user_addr = signer::address_of(user_account);

        // 檢查資源是否存在於儲存中
        if (!exists<UserProfile>(user_addr)) {
					
		  // 產生新的 userName
          let info_store = UserProfile{ username: username };
					
		  // 發布 info_store 資源到帳戶 (user_account)
          move_to(user_account, info_store);

        } else {

		  // `borrow_global_mut` 是獲取可變引用,可以這樣改變儲存中的資源
          let existing_info_store = borrow_global_mut<UserProfile>(user_addr);
          existing_info_store.username = username;
        }
    }
}

備註

move_to 用法如下

需要一個 &signer 參數來發布 T 資源到帳戶,透過 &signer 確保經過身份認證的用戶才能更新。

move_to<T>(&signer, T)

恭喜,我們已經將完成一半,接下來會進行測試來確認一切是否正常,讓我們 Move to Day 29


上一篇
Day 27 First Example - Alice & Bob
下一篇
Day 29 Second Example - Create New Project part 2
系列文
Smart-Contract Language: Move30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言