Skip to main content

发布包

在你可以调用 Move 包中的函数(超出模拟 Sui 执行场景)之前,该包必须在 Sui 网络上可用。当你发布一个包时,实际上是在网络上创建一个不可变的 Sui 对象,任何人都可以访问。

要将你的包发布到 Sui 网络,你可以使用 Sui 客户端 CLI 的 sui client publish 命令。在包在网络上变得可用后,你可以使用 sui client call 命令来访问包中提供的函数。

模块初始化器

包中的每个模块都可以包含一个在发布时运行的特殊初始化函数。初始化函数的目标是预初始化模块特定的数据(例如创建单例对象)。初始化函数必须具有以下属性才能在发布时执行:

  • 函数名称必须是 init
  • 参数列表必须以 &mut TxContext&TxContext 类型结束
  • 没有返回值
  • 私有可见性
  • 可选地,参数列表以按值接受模块的一次性见证的方式开始

例如,以下 init 函数都是有效的:

  • fun init(ctx: &TxContext)
  • fun init(ctx: &mut TxContext)
  • fun init(otw: EXAMPLE, ctx: &TxContext)
  • fun init(otw: EXAMPLE, ctx: &mut TxContext)

虽然 sui move 命令不直接支持显式发布,但你仍然可以使用测试框架测试模块初始化器,将第一笔交易专门用于执行初始化函数。

继续使用幻想游戏的例子,init 函数应该创建一个 Forge 对象。

    /// Module initializer to be executed when this module is published
fun init(ctx: &mut TxContext) {
let admin = Forge {
id: object::new(ctx),
swords_created: 0,
};

// transfer the forge object to the module/package publisher
transfer::transfer(admin, tx_context::sender(ctx));
}

到目前为止,你的测试调用了 init 函数,但初始化函数本身没有被测试以确保它正确创建了一个 Forge 对象。为了测试这个功能,修改 sword_create 函数,使其接受锻造厂作为参数,并在函数末尾更新已创建的剑的数量:

    /// Constructor for creating swords
public fun new_sword(
forge: &mut Forge,
magic: u64,
strength: u64,
ctx: &mut TxContext,
): Sword {
forge.swords_created = forge.swords_created + 1;
// ...
}

现在,创建一个函数来测试模块初始化:

    #[test_only] use sui::test_scenario as ts;

#[test_only] const ADMIN: address = @0xAD;

#[test]
public fun test_module_init() {
let ts = ts::begin(@0x0);

// first transaction to emulate module initialization.
{
ts::next_tx(&mut ts, ADMIN);
init(ts::ctx(&mut ts));
};

// second transaction to check if the forge has been created
// and has initial value of zero swords created
{
ts::next_tx(&mut ts, ADMIN);

// extract the Forge object
let forge: Forge = ts::take_from_sender(&mut ts);

// verify number of created swords
assert!(swords_created(&forge) == 0, 1);

// return the Forge object to the object pool
ts::return_to_sender(&mut ts, forge);
};

ts::end(ts);
}

正如新的测试函数所示,第一笔交易(显式地)调用初始化器。接下来的交易检查 Forge 对象是否已创建并正确初始化。

如果此时尝试对整个包运行测试,你将遇到由于new_sword 函数签名更改而导致的现有测试的编译错误。为了使测试再次运行,需要进行适应的更改是你的练习。如果需要帮助,可以参考包的源代码(所有测试已经适当调整)first_package