HOH水分子社区,是一个专注于编程、教育和创新的社区。
<img width="200" height="200" src="https://img.learnblockchain.cn/attachments/2024/12/ktg1svMN67739fffb1360.webp" href="https://github.com/hoh-zone/0.1-to-Sui-Fullstack"> <br>
HOH水分子社区,是一个专注于编程、教育和创新的社区。
能够创建用户并统计用户数量,用户可以创建资源文件夹,文件夹可分类用户资产,如NFT,有价值的币跟无价值的币。
合约中用到的依赖,依赖用于引用其他合约模块中的方法。
use std::string::{String};
引用std合约中string模块的String类型。
use sui::event;
引用sui合约中event模块,用于定义合约事件。
use sui::table::{Self,Table};
引入Table类型和模块。
错误码,合约调用报错时根据错误码快速定位错误原因。 const EProfileExitsted: u64 = 0;
用于存放合约结构体,结构体负责记录对象包含的属性以及能力信息,用于生成对象。
public struct State has key{
id:UID,
users:Table<address,address>, // owner:address 合约调用者 ,profile:address 用户凭据
}
定义State结构体,用于记录约中创建的用户信息。
public struct Profile has key{
id:UID,
name:String,
description:String,
}
定义了一个Profile结构体用于存放用户信息,结构体包含属性id作为唯一标识,name跟description为自定义属性,拥有key能力,key能力标识该结构体生成的对象可以存储且唯一,拥有key能力的对象必须包含一个UID类型的字段。
定义事件结构,记录合约调用日志。
public struct ProfileCreated has copy,drop{
id:ID,
owner:address
}
定义了一个ProfileCreated事件结构体,结构体包含copy和drop能力,表示该结构体创建的对象可以被复制、删除和忽略。
初始化函数,合约发布时执行。
fun init(ctx:&mut Txcontext){
transfer::share_object(State{
id:object::new(ctx),
users:table::new(ctx),
});
//定义一个State对象并共享
}
入口及函数定义,用于声明合约包含的方法以及被调用范围。
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参数表示合约上下文,记录了本次交易中的信息。
添加检查函数,用于合约对象属性查询等。
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()
//如果不包含则返回值为空
}
}
编写测试用例
#[test_only]
//仅测试时才使用的方法
public fun init_for_testing(ctx: &mut Txcontext){
init(ctx);
}
#[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);
//测试内容结束
)
}
}
}
<table> <tr> <td> <img width="300px" src="https://img.learnblockchain.cn/attachments/2024/12/qbVOGYSg6773a16f3cb0f.webp" alt="HOH水分子公众号"> </td> <td> <img width="300px" src="https://img.learnblockchain.cn/attachments/2024/12/zC2WnPAW6773a8349dd85.jpg" alt="Alya @HOH"> </td> <td> <img width="300px" src="https://img.learnblockchain.cn/attachments/2024/12/IXUOsFri6773a834a1293.jpg" alt="Jane @HOH"> </td> </tr> </table>
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!