Let's move - Sui Obejct相关学习实例

  • stom698
  • 更新于 2024-03-28 16:24
  • 阅读 807

本文转自本人微信公众号的文章,所以带有wx水印,希望大家能理解一下。后续新文会自己留存不带水印。

1.1 创建sui object

#新建一个move项目
sui move new courcetwo && cd courcetwo/

然后在source/文件夹下创建一个coursetwo.move文件

module coursetwo::transcript{
​
    use sui::object::{Self, UID};
    use sui::tx_context::{Self, TxContext};
    use sui::transfer;
​
    // Define a structure named TranscriptObject that possesses a 'key' attribute.
    struct TranscriptObject has key {
        id :UID,
        history: u8,
        math: u8,
        literature: u8,
    }
​
    //Create a TranscriptObject and transfer it to the sender's address for this transaction.
    public entry fun create_transcript_object(history: u8, math: u8, literature: u8, ctx: &mut TxContext) {
        let transcriptObject = TranscriptObject {
            id: object::new(ctx),
            history,
            math,
            literature,
        };
        //tx_context::sender(ctx) to get the sender's address for this transaction.
        transfer::transfer(transcriptObject, tx_context::sender(ctx))
    }
​
}

然后修改move.toml,当前终端的RPC是testnet然后配置文件中testnet改为mainnet

[package]
name = "coursetwo"
version = "0.0.1"
​
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/mainnet" }
​
[addresses]
coursetwo = "0x0"
​

整体项目结构如下

img

修改后部署合约

sui client publish --gas-budget 100000000 --skip-dependency-verification

获取packageid

│  ┌──                                                                                             │
│  │ PackageID: 0xc7c3af19001f4c6e520430413353111bdcbd010151de4207dc89a8b5b6f360f4                 │
│  │ Version: 1                                                                                    │
│  │ Digest: B6yX72wDgJZhm92RG7Mj2KGKQs9C6TdVFU5ckwFE2JGs                                          │
│  │ Modules: transcript                                                                           │
│  └──                                                                                             │

然后发起交易

sui client call --package 0xc7c3af19001f4c6e520430413353111bdcbd010151de4207dc89a8b5b6f360f4 --module transcript --function create_transcript_object --args 70 80 90 --gas-budget 10000000
传入的参数--args 70 80 90
对应:
history ---> 70
math ---> 80
literature ---> 90

找到创建的obejctid

│                                                                                                                  │
│ Created Objects:                                                                                                 │
│  ┌──                                                                                                             │
│  │ ObjectID: 0x2c7519d08e26bbfef292d54a81ef516638dced63ab78acde83377e7def3468e6                                  │
│  │ Sender: 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988                                    │
│  │ Owner: Account Address ( 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988 )                 │
│  │ ObjectType: 0xc7c3af19001f4c6e520430413353111bdcbd010151de4207dc89a8b5b6f360f4::transcript::TranscriptObject  │
│  │ Version: 924660                                                                                               │
│  │ Digest: 8BmnjKpYrR99ZsuMqE8NbBn3f8ctiKjJFAVrfnCToyBR                                                          │
│  └──                                                                                                             │

然后在https://suiexplorer.com/中切换到testnet查询

img

create_transcript_object函数的代码中写明将创建的transcriptObject转移到交易发起者的账户中

transfer::transfer(transcriptObject, tx_context::sender(ctx))

所有可以看到owner是我自己的钱包地址

img

img

1.2 sui object 所有权类型

(1)被一个地址拥有

transfer::transfer(transcriptObject, tx_context::sender(ctx))

(2)不可变的共享object

transfer::freeze_object(obj);

(3)可变的共享object

transfer::share_object(obj);

1.3 参数传递

引用参数的传递,在TranscriptObject前添加&,用来获取这个传入的object里的参数。

public fun view_score(transcriptObject: &TranscriptObject): u8{
    transcriptObject.literature
}

可变引用参数的传递和值的传递,在TranscriptObject前添加&mut,用来获取这个传入的object里的参数,并且可以进行修改。

public entry fun update_score(transcriptObject: &mut TranscriptObject, score: u8){
    transcriptObject.literature = score
}

1.4 解包struct和删除object

要删除一个 object, 你首先要解包这个 object 并且获取它的 object ID. 解包的操作只能够在定义了这个 object 的 module 内进行。这是为了遵守 Move 的专用结构操作规则:

  • struct 类型只能在定义了该 struct 的 module 内创建("打包") 或 销毁("解包")
  • struct 的属性也只能在定义了该 struct 的 module 内获取

在解包 struct 获取它的 ID 之后,可以通过调用 framework 里头的 object::delete 方法处理它的 object ID 来实现删除。

#下划线用来标注没用被使用的参数,参数被传入值后则会消耗掉
public entry fun delete_transcript(transcriptObject: TranscriptObject){
    let TranscriptObject {id, history: _, math: _, literature: _ } = transcriptObject;
    object::delete(id);
}

1.5 不可变的共享object实例验证

验证不可变的共享object,可以修改coursetwo.move文件内容

module coursetwo::transcript{
​
    use sui::object::{Self, UID};
    use sui::tx_context::{Self, TxContext};
    use sui::transfer;
​
    // Define a structure named TranscriptObject that possesses a 'key' attribute.
    struct TranscriptObject has key {
        id :UID,
        history: u8,
        math: u8,
        literature: u8,
    }
​
    //Create a TranscriptObject and transfer it to the sender's address for this transaction.
    public entry fun create_transcript_object(history: u8, math: u8, literature: u8, ctx: &mut TxContext) {
        let transcriptObject = TranscriptObject {
            id: object::new(ctx),
            history,
            math,
            literature,
        };
        //tx_context::sender(ctx) to get the sender's address for this transaction.
        // transfer::transfer(transcriptObject, tx_context::sender(ctx))
        transfer::freeze_object(transcriptObject)
    }
​
    // You are allowed to view the scores, but you cannot change them.
    public fun view_score(transcriptObject: &TranscriptObject): u8{
        transcriptObject.literature
    }
​
    // You are allowed to view and edit the scores, but you cannot delete them.
    public entry fun update_score(transcriptObject: &mut TranscriptObject, score: u8){
        transcriptObject.literature = score
    }
​
    // delete transcriptObject
    public entry fun delete_transcript(transcriptObject: TranscriptObject){
        let TranscriptObject {id, history: _, math: _, literature: _ } = transcriptObject;
        object::delete(id);
    }
​
}

部署合约后

 Published Objects:                                                                               │
│  ┌──                                                                                             │
│  │ PackageID: 0x070643a49faf874c7fef2b9e646afe8791d15feb156fb6b83b4079afec621032                 │
│  │ Version: 1                                                                                    │
│  │ Digest: 9UkuQc2uqcLHiwX7MCVGwoUtpie4uTDgEZefDJipvoCR                                          │
│  │ Modules: transcript                                                                           │
│  └──                                                                                             │

调用create_transcript_object

sui client call --package 0x070643a49faf874c7fef2b9e646afe8791d15feb156fb6b83b4079afec621032 --module transcript --function create_transcript_object --args 70 80 90 --gas-budget 10000000

然后可以看到获取的objectid,Owner:Immutable,意思为不可变的

│ Created Objects:                                                                                                │
│  ┌──                                                                                                            │
│  │ ObjectID: 0xfd4f9af670bae8627323ec3f228d6d6a56e7979fc3e6413997181c461b4e988b                                 │
│  │ Sender: 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988                                   │
│  │ Owner: Immutable                                                                                             │
│  │ ObjectType: 0x70643a49faf874c7fef2b9e646afe8791d15feb156fb6b83b4079afec621032::transcript::TranscriptObject  │
│  │ Version: 924662                                                                                              │
│  │ Digest: 7Npa7G2JWtU6osfBPtHwppjPA828L1sRFYeLQfL3uaQy                                                         │
│  └──                                                                                                            │

通过浏览器查询也可以看到

img

如果调用view_score,只查询分数是可以的

sui client call --package 0x070643a49faf874c7fef2b9e646afe8791d15feb156fb6b83b4079afec621032 --module transcript --function view_score --args 0xfd4f9af670bae8627323ec3f228d6d6a56e7979fc3e6413997181c461b4e988b --gas-budget 10000000

当调用update_score则会出现报错,报错大致意思为试图以不允许的方式使用了一个可变引用,所以会发生报错。

(base) root@DESKTOP-8UK78GU:~/sui_program/courcetwo# sui client call --package 0x070643a49faf874c7fef2b9e646afe8791d15feb156fb6b83b4079afec621032 --module transcript --function update_score --args 0xfd4f9af670bae8
627323ec3f228d6d6a56e7979fc3e6413997181c461b4e988b 99 --gas-budget 10000000
[warn] Client/Server api version mismatch, client api version : 1.16.2, server api version : 1.17.3
Error executing transaction: Failure {
    error: "CommandArgumentError { arg_idx: 0, kind: InvalidObjectByMutRef } in command 0",
}

调用delete_transcript也是一样的

(base) root@DESKTOP-8UK78GU:~/sui_program/courcetwo# sui client call --package 0x070643a49faf874c7fef2b9e646afe8791d15feb156fb6b83b4079afec621032 --module transcript --function delete_transcript --args 0xfd4f9af67
0bae8627323ec3f228d6d6a56e7979fc3e6413997181c461b4e988b --gas-budget 10000000
[warn] Client/Server api version mismatch, client api version : 1.16.2, server api version : 1.17.3
Error executing transaction: Failure {
    error: "CommandArgumentError { arg_idx: 0, kind: InvalidObjectByValue } in command 0",
}

1.6 可变的共享object实例验证

验证可变的共享object,可以修改coursetwo.move文件内容

module coursetwo::transcript{
​
    use sui::object::{Self, UID};
    use sui::tx_context::{Self, TxContext};
    use sui::transfer;
​
    // Define a structure named TranscriptObject that possesses a 'key' attribute.
    struct TranscriptObject has key {
        id :UID,
        history: u8,
        math: u8,
        literature: u8,
    }
​
    //Create a TranscriptObject and transfer it to the sender's address for this transaction.
    public entry fun create_transcript_object(history: u8, math: u8, literature: u8, ctx: &mut TxContext) {
        let transcriptObject = TranscriptObject {
            id: object::new(ctx),
            history,
            math,
            literature,
        };
        //tx_context::sender(ctx) to get the sender's address for this transaction.
        // transfer::transfer(transcriptObject, tx_context::sender(ctx))
        transfer::share_object(transcriptObject);
    }
​
    // You are allowed to view the scores, but you cannot change them.
    public fun view_score(transcriptObject: &TranscriptObject): u8{
        transcriptObject.literature
    }
​
    // You are allowed to view and edit the scores, but you cannot delete them.
    public entry fun update_score(transcriptObject: &mut TranscriptObject, score: u8){
        transcriptObject.literature = score
    }
​
    // delete transcriptObject
    public entry fun delete_transcript(transcriptObject: TranscriptObject){
        let TranscriptObject {id, history: _, math: _, literature: _ } = transcriptObject;
        object::delete(id);
    }
​
}

部署合约

 Published Objects:                                                                               │
│  ┌──                                                                                             │
│  │ PackageID: 0x30820336bffe4791e011be71013503cbbb40af06fb93c733ca643eaaceb27b2f                 │
│  │ Version: 1                                                                                    │
│  │ Digest: 6vz6f646jnhdKGTtfi6BNZJgeP4ACr7EdZrYPJxPAW42                                          │
│  │ Modules: transcript                                                                           │

调用create_transcript_object

sui client call --package 0x30820336bffe4791e011be71013503cbbb40af06fb93c733ca643eaaceb27b2f --module transcript --function create_transcript_object --args 70 80 90 --gas-budget 10000000

│ Created Objects:                                                                                                 │
│  ┌──                                                                                                             │
│  │ ObjectID: 0x6540830eb30041a9cdc6f586126a6152dbbef37542798902473adcf2c709487d                                  │
│  │ Sender: 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988                                    │
│  │ Owner: Shared                                                                                                 │
│  │ ObjectType: 0x30820336bffe4791e011be71013503cbbb40af06fb93c733ca643eaaceb27b2f::transcript::TranscriptObject  │
│  │ Version: 924667                                                                                               │
│  │ Digest: JcdUThM2JCLeYXpS7eCNFbFYV9VPqzRWghoR6jxepUq                                                           │
│  └──                                                                                                             │

浏览器查看owner为Shared,可变的共享object

img

这里就直接进行分数修改,调用update_score,将literature分数改为99

sui client call --package 0x30820336bffe4791e011be71013503cbbb40af06fb93c733ca643eaaceb27b2f --module transcript --function update_score --args 0x6540830eb30041a9cdc6f586126a6152dbbef37542798902473adcf2c709487d 99 --gas-budget 10000000

img

调用delete_transcript

sui client call --package 0x30820336bffe4791e011be71013503cbbb40af06fb93c733ca643eaaceb27b2f --module transcript --function delete_transcript --args 0x6540830eb30041a9cdc6f586126a6152dbbef37542798902473adcf2c709487d --gas-budget 10000000

在浏览器中就已经无法查询了,objectid已被删除

img

1.7 Object Wrapping

修改coursetwo.move文件内容

module coursetwo::transcript{
​
    use sui::object::{Self, UID};
    use sui::tx_context::{Self, TxContext};
    use sui::transfer;
​
    //create a WrappableTranscript
    struct WrappableTranscript has key, store {
        id: UID,
        history: u8,
        math: u8,
        literature: u8,
    }
​
    //wrapping WrappableTranscript
    struct Folder has key {
        id: UID,
        transcript: WrappableTranscript,
        intended_address: address
    }
​
    // Error code for when a non-intended address tries to unpack the transcript wrapper
    const ENotIntendedAddress: u64 = 1;

    public entry fun create_wrappable_transcript_object(history: u8, math: u8, literature: u8, ctx: &mut TxContext) {
        let wrappableTranscript = WrappableTranscript {
            id: object::new(ctx),
            history,
            math,
            literature,
        };
        transfer::transfer(wrappableTranscript, tx_context::sender(ctx))
    }
​
    // You are allowed to retrieve the score but cannot modify it
    public fun view_score(transcriptObject: &WrappableTranscript): u8{
        transcriptObject.literature
    }
​
    // You are allowed to view and edit the score but not allowed to delete it
    public entry fun update_score(transcriptObject: &mut WrappableTranscript, score: u8){
        transcriptObject.literature = score
    }
​
    // You are allowed to do anything with the score, including view, edit, delete the entire transcript itself.
    public entry fun delete_transcript(transcriptObject: WrappableTranscript){
        let WrappableTranscript {id, history: _, math: _, literature: _ } = transcriptObject;
        object::delete(id);
    }
​
    public entry fun request_transcript(transcript: WrappableTranscript, intended_address: address, ctx: &mut TxContext){
        let folderObject = Folder {
            id: object::new(ctx),
            transcript,
            intended_address
        };
        //We transfer the wrapped transcript object directly to the intended address
        transfer::transfer(folderObject, intended_address)
    }
​
    public entry fun unpack_wrapped_transcript(folder: Folder, ctx: &mut TxContext){
        // Check that the person unpacking the transcript is the intended viewer
        assert!(folder.intended_address == tx_context::sender(ctx), ENotIntendedAddress);
        let Folder {
            id,
            transcript,
            intended_address:_,
        } = folder;
        transfer::transfer(transcript, tx_context::sender(ctx));
        object::delete(id)
    }
​
}

发布合约

│ Published Objects:                                                                               │
│  ┌──                                                                                             │
│  │ PackageID: 0x9cafbe821fbf7dc1e60dc39473ec3f96c71ef6a8c71aac68e417d35094b7edfd                 │
│  │ Version: 1                                                                                    │
│  │ Digest: 81mMBdHoyHjGjiyUC6x4hhoA5B17bna8V8WCuoyVqcVA                                          │
│  │ Modules: transcript                                                                           │
│  └──                                                                                             │

根据上面合约,需要先调用create_wrappable_transcript_object函数

sui client call --package 0x9cafbe821fbf7dc1e60dc39473ec3f96c71ef6a8c71aac68e417d35094b7edfd --module transcript --function create_wrappable_transcript_object --args 70 80 90 --gas-budget 10000000

│ Created Objects:                                                                                                    │
│  ┌──                                                                                                                │
│  │ ObjectID: 0xc47af86dc5b2839e76b19db8e66c833f56f5b8d3448ed97ff4bcc9c299cf4a5f                                     │
│  │ Sender: 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988                                       │
│  │ Owner: Account Address ( 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988 )                    │
│  │ ObjectType: 0x9cafbe821fbf7dc1e60dc39473ec3f96c71ef6a8c71aac68e417d35094b7edfd::transcript::WrappableTranscript  │
│  │ Version: 924671                                                                                                  │
│  │ Digest: HgMXZTUDo1i3sQZiNDYqYmkqrRUuxZ6xbV64iwyqXgTc                                                             │
│  └──                                                                                                                │

在create_wrappable_transcript_object中是将wrappableTranscript转移给交易发起者

img

然后我们需要将wrappableTranscript通过Folder 封装起来并且配置观察者地址,这里传入两个参数:

1、wrappableTranscript objectid

0xc47af86dc5b2839e76b19db8e66c833f56f5b8d3448ed97ff4bcc9c299cf4a5f                                

2、intended_address

0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988

调用request_transcript函数将wrappableTranscript封装并且观察者地址为我自己的地址

sui client call --package 0x9cafbe821fbf7dc1e60dc39473ec3f96c71ef6a8c71aac68e417d35094b7edfd --module transcript --function request_transcript --args 0xc47af86dc5b2839e76b19db8e66c833f56f5b8d3448ed97ff4bcc9c299cf4a5f 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988 --gas-budget 10000000

│                                                                                                        │
│ Created Objects:                                                                                       │
│  ┌──                                                                                                   │
│  │ ObjectID: 0xee170c3d8517db65a6e090f21fcf40702eb7449358bd055b43ba476a54a4665f                        │
│  │ Sender: 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988                          │
│  │ Owner: Account Address ( 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988 )       │
│  │ ObjectType: 0x9cafbe821fbf7dc1e60dc39473ec3f96c71ef6a8c71aac68e417d35094b7edfd::transcript::Folder  │
│  │ Version: 924672                                                                                     │
│  │ Digest: HyWwQ1TfvF8D2mtu6sYZMVWmv2M7hKoMCWnKT6FymuPW                                                │
│  └──                                                                                                   │

通过浏览器查看,可以看到之前的wrappableTranscript封装到Folder中

img

然后之前的wrappableTranscript已经无法直接查看了

img

如果需要直接查看wrappableTranscript则需要解封装,通过调用unpack_wrapped_transcript

sui client call --package 0x9cafbe821fbf7dc1e60dc39473ec3f96c71ef6a8c71aac68e417d35094b7edfd --module transcript --function unpack_wrapped_transcript --args 0xee170c3d8517db65a6e090f21fcf40702eb7449358bd055b43ba476a54a4665f --gas-budget 10000000

在unpack_wrapped_transcript中有断言,用来判断观察者地址是否跟wrappableTranscript的owner是否一致

assert!(folder.intended_address == tx_context::sender(ctx), ENotIntendedAddress);

解包之后folder objectid就被删除无法查询了

img

wrappableTranscript objectid则恢复可查询

img

1.8 Capability设计模式

修改coursetwo.move文件内容,这里新增了TeacherCap来作为校验权限的参数,并且通过_: &TeacherCap传入

module coursetwo::transcript{
​
    use sui::object::{Self, UID};
    use sui::tx_context::{Self, TxContext};
    use sui::transfer;
​
    struct WrappableTranscript has key, store {
        id: UID,
        history: u8,
        math: u8,
        literature: u8,
    }
​
    struct Folder has key {
        id: UID,
        transcript: WrappableTranscript,
        intended_address: address
    }
​
    struct TeacherCap has key {
        id: UID
    }
​
    // Error code for when a non-intended address tries to unpack the transcript wrapper
    const ENotIntendedAddress: u64 = 1;
​
    /// Module initializer is called only once on module publish.
    fun init(ctx: &mut TxContext) {
        transfer::transfer(TeacherCap {
            id: object::new(ctx)
        }, tx_context::sender(ctx))
    }

    public entry fun add_additional_teacher(_: &TeacherCap, new_teacher_address: address, ctx: &mut TxContext){
        transfer::transfer(
            TeacherCap {
                id: object::new(ctx)
            },
        new_teacher_address
        )
    }
​
    public entry fun create_wrappable_transcript_object(_: &TeacherCap, history: u8, math: u8, literature: u8, ctx: &mut TxContext){
        let wrappableTranscript = WrappableTranscript {
            id: object::new(ctx),
            history,
            math,
            literature,
        };
        transfer::transfer(wrappableTranscript, tx_context::sender(ctx))
    }
​
    // You are allowed to retrieve the score but cannot modify it
    public fun view_score(transcriptObject: &WrappableTranscript): u8{
        transcriptObject.literature
    }
​
    // You are allowed to view and edit the score but not allowed to delete it
    public entry fun update_score(_: &TeacherCap, transcriptObject: &mut WrappableTranscript, score: u8){
        transcriptObject.literature = score
    }
​
    // You are allowed to do anything with the score, including view, edit, delete the entire transcript itself.
    public entry fun delete_transcript(_: &TeacherCap, transcriptObject: WrappableTranscript){
        let WrappableTranscript {id, history: _, math: _, literature: _ } = transcriptObject;
        object::delete(id);
    }
​
    public entry fun request_transcript(transcript: WrappableTranscript, intended_address: address, ctx: &mut TxContext){
        let folderObject = Folder {
            id: object::new(ctx),
            transcript,
            intended_address
        };
        //We transfer the wrapped transcript object directly to the intended address
        transfer::transfer(folderObject, intended_address)
    }
​
    public entry fun unpack_wrapped_transcript(folder: Folder, ctx: &mut TxContext){
        // Check that the person unpacking the transcript is the intended viewer
        assert!(folder.intended_address == tx_context::sender(ctx), ENotIntendedAddress);
        let Folder {
            id,
            transcript,
            intended_address:_,
        } = folder;
        transfer::transfer(transcript, tx_context::sender(ctx));
        object::delete(id)
    }
​
}

部署合约,在部署时会自动调用init函数为发起者创建一个TeacherCap

│ Created Objects:                                                                                  │
│  ┌──                                                                                              │
│  │ ID: 0x9ca95e7f1d45bd7e37a2c5ab306a177862fca6b0e440aa1cf84d259c6c8e2322                         │
│  │ Owner: Immutable                                                                               │
│  │ Version: 1                                                                                     │
│  │ Digest: CCwyAXAyEm7qXWwUkgj2NJbarXthjAGiVxtrXECgr3mJ                                           │
│  └──                                                                                              │
│  ┌──                                                                                              │
│  │ ID: 0xbb7df67de2331620eded37e8d794f2fddf0859a1ff6144a8d8af0fbdb3acfad7                         │
│  │ Owner: Account Address ( 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988 )  │
│  │ Version: 924674                                                                                │
│  │ Digest: G1hMGRXdZRwanHraFS75JEgHK43jTAYSNSsePw55bszT                                           │
│  └──                                                                                              │
│  ┌──                                                                                              │
│  │ ID: 0xdcb7eb0b6963aa5439f1c35495fb104f4e6c7d009aa9d3bb3afdd1327075b414                         │
│  │ Owner: Account Address ( 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988 )  │
│  │ Version: 924674                                                                                │
│  │ Digest: Cxv3yHExxpnnPy9DYcBf1Tc7maJyDqiabnsg6F7euBcH                                           │
│  └──                                                                                              │

│ Published Objects:                                                                                         │
│  ┌──                                                                                                       │
│  │ PackageID: 0x9ca95e7f1d45bd7e37a2c5ab306a177862fca6b0e440aa1cf84d259c6c8e2322                           │
│  │ Version: 1                                                                                              │
│  │ Digest: CCwyAXAyEm7qXWwUkgj2NJbarXthjAGiVxtrXECgr3mJ                                                    │
│  │ Modules: transcript                                                                                     │
│  └──                                                                                                       │

通过浏览器查询

img

可以进行测试,在create_wrappable_transcript_object函数中含有

_: &TeacherCap,表明含有TeacherCap的才可以调用这个函数

sui client call --package 0x9ca95e7f1d45bd7e37a2c5ab306a177862fca6b0e440aa1cf84d259c6c8e2322 --module transcript --function create_wrappable_transcript_object --args 0xdcb7eb0b6963aa5439f1c35495fb104f4e6c7d009aa9d3bb3afdd1327075b414 70 80 90 --gas-budget 10000000

│ Created Objects:                                                                                                    │
│  ┌──                                                                                                                │
│  │ ObjectID: 0xff38a8c79d99bf9c9c1c63e6748969755df35aa95d1a790fdd5e8a51678a1953                                     │
│  │ Sender: 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988                                       │
│  │ Owner: Account Address ( 0x772b31a5738f0ceb70d313c7f1361bb1a9fa9732f9f1c9255cb191a592cbf988 )                    │
│  │ ObjectType: 0x9ca95e7f1d45bd7e37a2c5ab306a177862fca6b0e440aa1cf84d259c6c8e2322::transcript::WrappableTranscript  │
│  │ Version: 924675                                                                                                  │
│  │ Digest: 7gmxfUBSxxfp9wq65GwbWWeyibcyfEr4RzNRU7mPDHoN                                                             │
│  └──                                                                                                                │

浏览器查询

img

当没有TeacherCap的地址调用时就会报错

img

注意:如果将: &TeacherCap 改为: TeacherCap时,那么函数将期望接受一个 TeacherCap 的值而不是对 TeacherCap 的引用。这种行为改变可能会导致原有的权限校验逻辑失效,因为资源不再是作为一个引用传入,而是作为一个值被移动或消耗。

1.9 Events

Events功能类似于,web2的日志记录功能,可以用来记录交易的objectid,交易发起者,观察者地址等信息。

修改coursetwo.move文件内容

module coursetwo::transcript{
​
    use sui::object::{Self, ID, UID};
    use sui::tx_context::{Self, TxContext};
    use sui::transfer;
    use sui::event;
​
    struct WrappableTranscript has key, store {
        id: UID,
        history: u8,
        math: u8,
        literature: u8,
    }
​
    struct Folder has key {
        id: UID,
        transcript: WrappableTranscript,
        intended_address: address
    }
​
    struct TeacherCap has key {
        id: UID
    }
​
    /// Event marking when a transcript has been requested
    struct TranscriptRequestEvent has copy, drop {
        // The Object ID of the transcript wrapper
        wrapper_id: ID,
        // The requester of the transcript
        requester: address,
        // The intended address of the transcript
        intended_address: address,
    }
​
    // Error code for when a non-intended address tries to unpack the transcript wrapper
    const ENotIntendedAddress: u64 = 1;
​
    /// Module initializer is called only once on module publish.
    fun init(ctx: &mut TxContext) {
        transfer::transfer(TeacherCap {
            id: object::new(ctx)
        }, tx_context::sender(ctx))
    }

    public fun add_additional_teacher(_: &TeacherCap, new_teacher_address: address, ctx: &mut TxContext){
        transfer::transfer(
            TeacherCap {
                id: object::new(ctx)
            },
        new_teacher_address
        )
    }
​
    public fun create_wrappable_transcript_object(_: &TeacherCap, history: u8, math: u8, literature: u8, ctx: &mut TxContext){
        let wrappableTranscript = WrappableTranscript {
            id: object::new(ctx),
            history,
            math,
            literature,
        };
        transfer::transfer(wrappableTranscript, tx_context::sender(ctx))
    }
​
    // You are allowed to retrieve the score but cannot modify it
    public fun view_score(transcriptObject: &WrappableTranscript): u8{
        transcriptObject.literature
    }
​
    // You are allowed to view and edit the score but not allowed to delete it
    public fun update_score(_: &TeacherCap, transcriptObject: &mut WrappableTranscript, score: u8){
        transcriptObject.literature = score
    }
​
    // You are allowed to do anything with the score, including view, edit, delete the entire transcript itself.
    public fun delete_transcript(_: &TeacherCap, transcriptObject: WrappableTranscript){
        let WrappableTranscript {id, history: _, math: _, literature: _ } = transcriptObject;
        object::delete(id);
    }
​
    public fun request_transcript(transcript: WrappableTranscript, intended_address: address, ctx: &mut TxContext){
        let folderObject = Folder {
            id: object::new(ctx),
            transcript,
            intended_address
        };
        event::emit(TranscriptRequestEvent {
            wrapper_id: object::uid_to_inner(&folderObject.id),
            requester: tx_context::sender(ctx),
            intended_address,
        });
        //We transfer the wrapped transcript object directly to the intended address
        transfer::transfer(folderObject, intended_address);
    }
​
    public fun unpack_wrapped_transcript(folder: Folder, ctx: &mut TxContext){
        // Check that the person unpacking the transcript is the intended viewer
        assert!(folder.intended_address == tx_context::sender(ctx), ENotIntendedAddress);
        let Folder {
            id,
            transcript,
            intended_address:_,
        } = folder;
        transfer::transfer(transcript, tx_context::sender(ctx));
        object::delete(id)
    }
}

然后发布合约

│ Published Objects:                                                                                         │
│  ┌──                                                                                                       │
│  │ PackageID: 0x86cac9f3c094c7e0bfed3aae880a4400130626d4aacc2ada137554b6b7ae50c3                           │
│  │ Version: 1                                                                                              │
│  │ Digest: DpXwGn24HnJECkBU1Um9DkdZxoxbdDzrU4UV3HPMb8Cp                                                    │
│  │ Modules: transcript                                                                                     │
│  └──                                                                                                       │

然后需要调用create_wrappable_transcript_object,这里也需要填入TeacherCap的objectid,获取方法1.8小节一致

sui client call --package 0x86cac9f3c094c7e0bfed3aae880a4400130626d4aacc2ada137554b6b7ae50c3 --module transcript --function create_wrappable_transcript_object --args 0xb364f935722a19333ff3ddf7b7c3e5fccdf212cb667156cbeb23475c6f78af27 70 80 90 --gas-budget 10000000

│                                                                                                   │
│ Created Objects:                                                                                  │
│  ┌──                                                                                              │
│  │ ID: 0x4cff5988934710f70a8f425af38e74ffb0ebf1863ebf7bc69be2d18b60c40cb0                         │
│  │ Owner: Account Address ( 0x21f62d821142d1a72d2b78ce0e3fee2ae01f38293e583c46e9a4be3f91544767 )  │
│  │ Version: 980181                                                                                │
│  │ Digest: 8UGmSMz3DzeVW9hEzsGid8eCm6XkewjQN5Texz6FBurp                                           │
│  └──

create_wrappable_transcript_object之后,再调用request_transcript来测试event

sui client call --package 0x86cac9f3c094c7e0bfed3aae880a4400130626d4aacc2ada137554b6b7ae50c3 --module transcript --function request_transcript --args 0x4cff5988934710f70a8f425af38e74ffb0ebf1863ebf7bc69be2d18b60c40cb0 0x21f62d821142d1a72d2b78ce0e3fee2ae01f38293e583c46e9a4be3f91544767 --gas-budget 10000000

╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Effects                                                                               │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Digest: J51JimxBsyP73J9L6VV9f8N2K8qqvxp2Nu9Jug8PnjrH                                              │
│ Status: Success                                                                                   │
│ Executed Epoch: 265                                                                               │
│                                                                                                   │
│ Created Objects:                                                                                  │
│  ┌──                                                                                              │
│  │ ID: 0x6b2a315363bb27da5628a2271b161c78eeb364826f68c0b84cc34e750cbcb0e5                         │
│  │ Owner: Account Address ( 0x21f62d821142d1a72d2b78ce0e3fee2ae01f38293e583c46e9a4be3f91544767 )  │
│  │ Version: 980182                                                                                │
│  │ Digest: 8S5aYwaKG7BMXYptYtn2dHRo5PbUuaLAr3btvj37KbFL                                           │
│  └──                                                                                              │

可以通过Digest在浏览器中查询,可以看到Events中包含了合约中所需要记录的信息

img

本文学习参考链接:

【《SUI MOVE中文系列课程》SUI官方认证 Move智能合约语言入门指南】 https://www.bilibili.com/video/BV1RY411v7YU/?p=11&share_source=copy_web&vd_source=9fb9dd214abbb6aaef97ccb3f9e740de

源代码参考链接:

https://github.com/sui-foundation/sui-move-intro-course/blob/main/unit-two/example_projects/transcript/sources/transcript.move#L14

Sui move_cn社交账号

telegram: https://t.me/move_cn

X(twitter): https://twitter.com/move_cn

QQ群: 79489587

微信公众号:Move中文

Sui中文开发群: https://t.me/sui_dev_cn

  • 原创
  • 学分: 3
  • 分类: Sui
  • 标签:
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
5 订阅 9 篇文章

0 条评论

请先 登录 后评论
stom698
stom698
0x06CC...099B
努力提升