Sui Move 前端共学(笔记一)

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |

HOH水分子社区,是一个专注于编程、教育和创新的社区。

需求

能够创建用户并统计用户数量,用户可以创建资源文件夹,文件夹可分类用户资产,如NFT,有价值的币跟无价值的币。

dependencies

合约中用到的依赖,依赖用于引用其他合约模块中的方法。

c 复制代码
use std::string::{String};

引用std合约中string模块的String类型。

rust 复制代码
use sui::event;

引用sui合约中event模块,用于定义合约事件。

rust 复制代码
use sui::table::{Self,Table};

引入Table类型和模块。

erro code

错误码,合约调用报错时根据错误码快速定位错误原因。 const EProfileExitsted: u64 = 0;

struct

用于存放合约结构体,结构体负责记录对象包含的属性以及能力信息,用于生成对象。

swift 复制代码
public struct State has key{
    id:UID,
    users:Table<address,address>, // owner:address 合约调用者 ,profile:address 用户凭据
}

定义State结构体,用于记录约中创建的用户信息。

arduino 复制代码
public struct Profile has key{
    id:UID,
    name:String,
    description:String,
}

定义了一个Profile结构体用于存放用户信息,结构体包含属性id作为唯一标识,name跟description为自定义属性,拥有key能力,key能力标识该结构体生成的对象可以存储且唯一,拥有key能力的对象必须包含一个UID类型的字段。

event Struct

定义事件结构,记录合约调用日志。

arduino 复制代码
public struct ProfileCreated has copy,drop{
  id:ID,
  owner:address
}

定义了一个ProfileCreated事件结构体,结构体包含copy和drop能力,表示该结构体创建的对象可以被复制、删除和忽略。

init

初始化函数,合约发布时执行。

kotlin 复制代码
fun init(ctx:&mut Txcontext){
    transfer::share_object(State{
        id:object::new(ctx),
        users:table::new(ctx),
    });
    //定义一个State对象并共享 
}

entry function

入口及函数定义,用于声明合约包含的方法以及被调用范围。

rust 复制代码
public entry fun create_profile(
    name: String,
    description:String,
    state: &mut State,
    ctx: &mut TxContext,
){
    let owner = tx_context::sender(ctx);
    //调用tx_context模块的sender方法获取调用者信息存储在owner变量中
     assert!(!table::contains(&state.users,owner),EProfileExitsted));
     //校验当前用户是否已创建过profile,&state中的&符号表示只需要其中的值而不需要获取所有权。
    let uid = object::new(ctx);
    //调用object模块的new方法通过ctx生成唯一标识存储在uid变量中
    let id = object::uid_to_inner(&uid);
    //调用object模块的uid_to_inner方法将uid转换为内部表示形式存储在di变量中
    let new_profile = Profile{
        id:uid,
        name,
        description,
    };
    //使用Profile结构体定义new_profile对象
    transfer::transfer(new_profile,owner);
    //调用transfer模块中的transfer方法将生成的对象发送到交易调用者账户中
    table::add(&mut state.users,owner,object::id_to_address(&id))
    event::emit(ProfileCreated(id,owner));
    //通过event模块的emit方法记录。
}

定义了一个入口函数create_profile用于创建用户,fun表示可在模块内调用,public表示可在模块外调用,entry表示可以被命令行调用,方法包含2个字符型参数name、description,1个TxContext参数ctx,TxContext参数表示合约上下文,记录了本次交易中的信息。

getter function

添加检查函数,用于合约对象属性查询等。

kotlin 复制代码
public fun check_if_has_profile(
    user_address:address,
    state:&State,
): Option<address>{
//表示返回值是一个可选的地址类型
    if(table::contains(&state.users,user_address)){
    //判断用户表中是否包含用户的地址
        option::some(*table::borrow(&state.users,user_address))
        //如果包含用户的地址则返回这个地址
    }else{
        option::none()
        //如果不包含则返回值为空
    }
}

Helper function

编写测试用例

kotlin 复制代码
#[test_only]
//仅测试时才使用的方法
public fun init_for_testing(ctx: &mut Txcontext){
    init(ctx);
}

合约测试部分

rust 复制代码
#[test_only]
module filling::filling_tests;
use filling::filling::{Self,State,Profile};
//引入需要测试的合约
use sui::test_scenario{Self};
//引入测试模块
use std::string::{Self,String};
//引入String类型
use sui::test_utils::assert_eq;
//引入测试比较函数

#[test]
fun test_create_profile(){
    let user = @0xa;
    //自定义虚拟用户用于合约调用
    let mut scenario_val = test_scenario::begin(user);
    //测试内容开始,此处传参无关紧要,因为事务开始时会随机选用Alice、Bob或者DIANE(文档这么写的,暂未求证真实性)
    let scenerio = &mut scenario_val;
    filling::init_for_testing(test_scenerio::ctx(scenerio));
    //调用合约中测试初始化方法
    test_scenerio::next_tx(scenerio,user);
    //第一个事务完成后,使用next_tx启动后续事务
    let name = string::uft8(b"Al17er");
    let desc = string::uft8(b"Al17er test description!");
    {
        let mut state = test_scenario::take_shared<State>(scenario);
        //获取初始化State对象
        filling::create_profile(
            name:name,
            description:desc,
            state: &mut state,
            ctx:test_scenario::ctx(scenario),
        );
        //测试合约create_profile方法
        test_scenario::return_share(state);
        //返还初始化对象
        let tx = test_scenario::next_tx(scenario,user);
        let expected_no_events = 1;
        assert_eq!(
            test_scenario::num_user_events(&tx),
            expected_no_events
         );
         // 对比测试场景中事件数量是否为1
         {
             let state = test_scenario::take_shared<State>(scenario);
             let profile = test_scenario::take_from_sender<Profile>(scenario);
             //从合约测试调用者账户中获取<Profile>
             assert!(
                 filling::check_if_has_profile(user,&state == 
                 option::some(object::it_to_address(object::borrow_id(&profile))),
                 0
              );
              //判断用户表中是否包含用户,如果包含则返回0
                 test_scenario::return_shared(state);
                 test_scenerio::return_to_sender(scenario,profile);
                 //返还对象
                 test_scenario::end(scenario_val);
                 //测试内容结束
             )
         }
        
    }
    
}

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| | | |

相关推荐
救救孩子把5 天前
JetBrains《2024 开发者生态系统现状报告》总结
编程语言
rrokoko5 天前
TIOBE 指数 12 月排行榜公布,VB.Net排行第九
编程语言·vb.net
蜗牛沐雨9 天前
深入探讨C++中的互斥锁管理:`std::lock_guard`与`std::unique_lock`
开发语言·c++·编程语言·系统编程
莹雨潇潇15 天前
未来将要被淘汰的编程语言
编程语言
叶庭云16 天前
Matlab 和 R 语言的数组索引都是从 1 开始,并且是左闭右闭的
matlab·编程语言·r·数组索引·从 1 开始
夜阳朔16 天前
《C++ Primer》第三章知识点
c++·编程语言
MoonBit月兔17 天前
MoonBit 核心编译器正式开源!
开发语言·开源·编程语言·moonbit
Amd79418 天前
数据库与编程语言的连接
mysql·编程语言·应用开发·数据库连接·crud操作·数据访问·数据库驱动
Moonbit19 天前
编程实践|用 MoonBit 实现线段树(三)
编程语言