精通 Sui DeepBook:实战 DeFi DEX 系列(3)

发布: (2025年12月18日 GMT+8 12:39)
7 min read
原文: Dev.to

Source: Dev.to

Source:

理解 Note 合约

下面是本教程中将使用的 Note 合约代码。该 Note 合约是一个非常简单的概念验证,允许用户创建和删除笔记。我们添加了详细的注释,帮助你理解代码的每一部分。

Note 模块

创建一个新文件 sources/notes.move 并添加以下代码:

#[lint_allow(self_transfer)]
module dacade_zklogin::notes {
    use sui::tx_context::{TxContext, Self};
    use sui::transfer::Self;
    use sui::object::{Self, UID};
    use std::string::String;

    /// Struct to store the ID of the Notes (Shared Object)
    struct Notes has key {
        id: UID
    }

    /// Struct to represent a Note
    struct Note has key, store {
        id: UID,
        title: String,
        body: String
    }

    /// Module initializer to create the Notes shared object
    #[allow(unused_function)]
    fun init(ctx: &mut TxContext) {
        let notes = Notes {
            id: sui::object::new(ctx),
        };
        // Share the Notes object so it can be accessed by everyone
        transfer::share_object(notes)
    }

    /// Function to create a new note
    /// @param title: The title of the note
    /// @param body: The body of the note
    /// @param ctx: The transaction context
    public fun create_note(title: String, body: String, ctx: &mut TxContext) {
        let note = Note {
            id: object::new(ctx),
            title,
            body
        };
        // Transfer the note to the sender of the transaction
        transfer::transfer(note, tx_context::sender(ctx))
    }

    /// Function to delete a note
    /// @param note: The note object to be deleted
    /// @param _ctx: The transaction context
    public fun delete_note(note: Note, _ctx: &mut TxContext) {
        // Unpack the Note struct to access its fields
        let Note { id, title: _, body: _ } = note;
        // Delete the object ID, effectively deleting the note
        sui::object::delete(id)
    }
}

代码拆解

合约相当直观。

结构体 – 有两个结构体:NotesNote

  • Notes – 一个共享对象(在 init 中创建并共享)。在这个简化版本中,它仅保存一个 UID。
  • Note – 表示单个笔记。它具有 keystore 能力,意味着它可以被地址拥有并可以转移。它存储笔记的 idtitlebody

init 函数 – 在包发布时运行一次。它创建 Notes 结构体并共享,使其对所有人可访问。

create_note 函数 – 允许任何用户创建新笔记。它接受标题和正文,创建一个 Note 对象,并将其转移给交易的发送者 (tx_context::sender(ctx))。调用者成为该笔记的所有者。

delete_note 函数 – 允许笔记的所有者删除它。它按值(消耗)接收 Note 对象,解构后删除其 UID,从而实现笔记的删除。

编写完整的测试

测试对智能合约开发至关重要。我们将编写一个测试模块,以验证我们能够正确创建和删除笔记。

创建一个新文件 sources/notes_tests.move(或将其添加到已有的测试文件中):

#[test_only]
module dacade_zklogin::notes_tests {
    use dacade_zklogin::notes::{Self, Note};
    use sui::test_scenario;
    use std::string::{Self};

    #[test]
    fun test_create_and_delete_note() {
        let user = @0xA;
        // Start a test scenario with `user` as the sender
        let scenario = test_scenario::begin(user);

        // 1. Create a note
        {
            let ctx = test_scenario::ctx(&mut scenario);
            let title = string::utf8(b"My First Note");
            let body = string::utf8(b"This is the body of my note.");
            notes::create_note(title, body, ctx);
        };

        // 2. Verify note creation and ownership
        test_scenario::next_tx(&mut scenario, user);
        {

Source:

 // Take the Note object from the sender's inventory
            let note = test_scenario::take_from_sender(&scenario);

            // If we successfully took it, the note was created and transferred to the user.
            // Now, let's delete it.

            // 3. Delete the note
            let ctx = test_scenario::ctx(&mut scenario);
            notes::delete_note(note, ctx);
        };

        // 4. Verify note deletion
        test_scenario::next_tx(&mut scenario, user);
        {
            // Check that the user no longer has the note.
            // `has_most_recent_for_sender` returns false if the object is no longer accessible/owned.
            assert!(!test_scenario::has_most_recent_for_sender(&scenario), 0);
        };

        test_scenario::end(scenario);
    }
}

运行测试

要运行测试,请在 contract 目录下打开终端并执行:

sui move test

您应该会看到指示测试通过的输出:

Running Move unit tests
[ PASS    ] dacade_zklogin::notes_tests::test_create_and_delete_note
Test result: OK. Total tests: 1; passed: 1; failed: 0

“Note” 合约教程结束。

Source:

发布合约

现在我们已经测试完合约,是时候将它发布到 Sui Devnet 了。

切换到 Devnet

确保你的 Sui 客户端已连接到 devnet 环境。

sui client switch --env devnet

发布

运行发布命令。我们设置了 gas 预算,以确保交易有足够的 gas 执行。

sui client publish --gas-budget 100000000

注意: 如果你还没有为地址充值,运行 sui client faucet 获取一些测试 SUI。

保存重要信息

当你发布一个包时,Sui CLI 会输出交易摘要。该输出包含后续将前端应用连接到智能合约时 必须保存 的关键信息。

在输出中查找 Object Changes 部分。识别并保存以下 ID:

  • Package ID – 已发布代码的 ID(在 Published Objects 下列出)。
  • Shared Object ID – 在 init 函数中创建的 Notes 对象的 ID(在 Created Objects 中,Owner: Shared)。

示例输出分析

╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes                                                                                   │
├──────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects:                                                                                 │
│  ┌──                                                                                             │
│  │ ObjectID: 0x81833f94d4019d03fdc0d63abdf179950740f513bf434ae182e1031e0568a2b7                  │
│  │ Owner: Shared( 5 )                                                                            │
│  │ ObjectType: 0xfea5f1839d675fa03d5b02208adf2e6167336b4646399cb2248b9a7347a48998::notes::Notes  │
│  └──                                                                                             │
│ ...                                                                                              │
│ Published Objects:                                                                               │
│  ┌──                                                                                             │
│  │ PackageID: 0xfea5f183d675fa03d5b02208adf2e6167336b4646399cb2248b9a7347a48998                 │
│  │ Version: 1                                                                                    │
│  │ Digest: 93isZkd3bCKDqeMUL1wUhWnxYvJT4KLc72U6buFAPS4F                                          │
│  │ Modules: notes                                                                                │
│  └──                                                                                             │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯

需要保存的内容

  • Package ID: 0xfea5...8998(来自 Published Objects 部分)
  • Notes Shared Object ID: 0x8183...a2b7(来自 Created Objects 部分且 Owner 为 Shared

提示: 现在在前端项目中创建一个 .env 文件或 constants.ts 文件,并将这些值保存进去。后续在 UI 中与合约交互时需要用到它们。


恭喜你!如果你已经看到这里,给自己一个应得的赞——你已经正式佩戴上区块链专业人士的徽章了。 😄

你已经成功编写、测试并发布了你的第一个 Sui Move 智能合约。相当不错。

接下来,我们将在 DeepBook DEX 前端构建核心组件时把这些概念付诸实践,理论与实践相结合,精彩即将展开。

Back to Blog

相关文章

阅读更多 »