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);
                 //测试内容结束
             )
         }
        
    }
    
}

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

相关推荐
潍坊老登7 小时前
90%的软件项目卡在第一步:需求“想得美、写不清”
编程语言
iiiiyu9 小时前
面向对象高级接口的综合案例
java·开发语言·数据结构·编程语言
Rust研习社14 小时前
Rust 是如何判断对象是否相等的?一起来聊一聊 PartialEq 与 Eq
后端·rust·编程语言
7年前端辞职转AI2 天前
Python 错误和异常处理
python·编程语言
7年前端辞职转AI2 天前
Python 面向对象编程
python·编程语言
7年前端辞职转AI2 天前
Python 文件操作
python·编程语言
7年前端辞职转AI2 天前
Python 容器数据类型
python·编程语言
7年前端辞职转AI2 天前
Python 流程控制语句
python·编程语言
7年前端辞职转AI2 天前
Python 运算符
python·编程语言
7年前端辞职转AI2 天前
Python 变量
python·编程语言