本文转自本人微信公众号的文章,所以带有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"
整体项目结构如下
修改后部署合约
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查询
create_transcript_object函数的代码中写明将创建的transcriptObject转移到交易发起者的账户中
transfer::transfer(transcriptObject, tx_context::sender(ctx))
所有可以看到owner是我自己的钱包地址
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 获取它的 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 │
│ └── │
通过浏览器查询也可以看到
如果调用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
这里就直接进行分数修改,调用update_score,将literature分数改为99
sui client call --package 0x30820336bffe4791e011be71013503cbbb40af06fb93c733ca643eaaceb27b2f --module transcript --function update_score --args 0x6540830eb30041a9cdc6f586126a6152dbbef37542798902473adcf2c709487d 99 --gas-budget 10000000
调用delete_transcript
sui client call --package 0x30820336bffe4791e011be71013503cbbb40af06fb93c733ca643eaaceb27b2f --module transcript --function delete_transcript --args 0x6540830eb30041a9cdc6f586126a6152dbbef37542798902473adcf2c709487d --gas-budget 10000000
在浏览器中就已经无法查询了,objectid已被删除
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转移给交易发起者
然后我们需要将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中
然后之前的wrappableTranscript已经无法直接查看了
如果需要直接查看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就被删除无法查询了
wrappableTranscript objectid则恢复可查询
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 │
│ └── │
通过浏览器查询
可以进行测试,在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 │
│ └── │
浏览器查询
当没有TeacherCap的地址调用时就会报错
注意:如果将: &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中包含了合约中所需要记录的信息
本文学习参考链接:
【《SUI MOVE中文系列课程》SUI官方认证 Move智能合约语言入门指南】 https://www.bilibili.com/video/BV1RY411v7YU/?p=11&share_source=copy_web&vd_source=9fb9dd214abbb6aaef97ccb3f9e740de
源代码参考链接:
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
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!