Sui Move,一切以对象为核心。
官方文档:
开发文档:
$ cargo install --locked --git https://github.com/MystenLabs/sui.git --branch devnet sui sui-node
$ sui client
$ sui client addresses
可以看到,sui的地址长度与以太坊相同,都是20个字节,与Aptos不同。
在插件钱包页面上申请测试币。
在sui浏览器中查看钱包地址信息:
在sui app页面可以测试NFT mint。
还有几款网页游戏和NFT市场可以体验。
向命令行测试地址转账一些SUI,之后可以使用如下指令查看地址余额(不转账测试币的话命令查不到信息):
$ sui client gas
$ sui client objects
通过objects命令可以看到地址下数据对象信息,可以看到sui token默认的数据结构和地址是:0x2::coin::Coin<0x2::sui::SUI> 这里与Aptos不同。(Aptos是0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>,可以看到地址与数据类型均不同)
使用如下指令可以创建命令行新地址,新地址助记词在命令执行后展示,请自行备份。
$ sui client new-address ed25519
SUI token默认的decimals是9,这里与Aptos默认是8不同。
SUI的每次转账都会为接收地址创建一个新的Coin对象,默认不会自动合并。这里与Aptos不同。
用户可以自己通过命令来拆分或合并objects。
在调用transfer转账时,必须有另一个object来支付gas费,才能将一个object转走。因此,我们可以总结一个命令行转账过程如下:
1)拆分ojbect,将想要转出的部分拆分出独立的object,剩余部分是另一个object;
2)将拆分好的object转给对方;
3)接收方可以根据需要,决定是否要合并接收到的object到自己现有的object。
这个合并和拆分的过程,看起来有点类似于BTC的UTXO。估计是为了提升TPS而做出的设计。
$ sui client call --function transfer --module sui --package 0x2 --args 0x187f2af1f680bc1c9ae103dbcb28dc98b151c7fa 0xb5dede8f99c57266a221f1a88bc8cb71da6dd241 --gas-budget 1000
使用call指令,指定function名称,module名称,package地址和传入参数即可完成Move接口调用。
这里需要注意,这里即使是使用Move合约接口转账,依然需要有独立的object来支付gas费。与上一节转账时提到过程类似。
Object内容每次发生变更时,version号回自动加一。
新建一个工程目录:
$ sui move new my_first_package
sui的代码目录结构与Aptos相似:
用户代码放在sources目录下,这里需要注意几点与Aptos不同:
1)框架库在sui::下面,标准库std::位置和内容与Aptos有所差别
2)module的默认初始化函数名和定义不同,sui是fun init(ctx: &mut TxContext)
, Aptos是:fun init_module(sender: &signer)
sui的函数入口参数中没有默认的signer对象,sui的entry函数可以包含一个ctx: &mut TxContext
对象作为函数的最后一个参数,另外参数只能传入owner为sender或shared的object
sui使用transfer::transfer的方式来转移对象,而不是Aptos的move_to
一个object的owner既可以是一个地址,也可以是另一个object
编译Move使用指令:
$ sui move build
(这里与Aptos不同,aptos用的是aptos move compile)
单元测试指令:
$ sui move test
官方文档:
$ sui client publish --path $PATH_TO_PACKAGE/my_move_package --gas-budget 30000
部署完成后的合约默认是一个不可变更的对象(object)。部署过程中,会消耗gas费对象,生成合约对象和数据对象。
Sui提供了一系列在Move中操作object的接口。
Sui中对象的ownership所有权限分为:
owner为地址;
owner为另一个对象;
owner为shared and immutable, 即对象公开但不可再更改;
owner为可shared and mutable, 对象公开并且任何人均可以更改;(未开发完成功能)
操作object的接口包括:
use sui::transfer;
transfer::transfer(obj, recipient);
transfer::transfer_to_object(obj, &mut owner);
transfer::transfer_to_object_id(child, parent);
transfer::transfer_child_to_object(child, child_ref, &mut new_parent);
transfer::transfer_child_to_address(child, child_ref, recipient);
transfer::freeze_object(obj);
transfer::share_object(obj);
Transaction Context:
// assmue `ctx` has type `&mut TxContext`.
let info = sui::object::new(ctx);
sui::tx_context::sender(ctx)
一个可以创建sui对象的结构体,第一个参数必须为id,并且定义key能力(key代表其具有全局索引的能力):
use sui::object::UID;
struct ColorObject has key {
id: UID,
red: u8,
green: u8,
blue: u8,
}
UID可以使用object::new(ctx)
接口创建,其中ctx是entry类型函数参数可选自带的交易信息(只能是最后一个参数)。entry类型函数表示是可以被交易直接调用的函数。
使用transfer函数可以将object的owner转给对应的地址。每一个object必须有对应的owner,owner可以是一个地址,一个obj,或者shared。
因为Sui的全局对象存储在Move之外,因此不使用Move全局api语法。同时,单元测试的时候,也只能通过test_scenario来访问内部对象。
test_scenario的主要接口包括:
test_scenario::begin
test_scenario::next_tx
test_scenario::ctx
test_scenario::has_most_recent_for_sender
test_scenario::take_from_sender
test_scenario::return_to_sender
object::id_from_address(tx_context::last_created_object_id(ctx))
test_scenario::take_from_sender_by_id
test_scenario::take_immutable
test_scenario::return_immutable
...
例如:
let owner = @0x1;
// Create a ColorObject and transfer it to @owner.
let scenario_val = test_scenario::begin(owner);
let scenario = &mut scenario_val;
{
let ctx = test_scenario::ctx(scenario);
color_object::create(255, 0, 255, ctx);
};
(大括号外面的分号是必须的)
在Sui中,只有Owner可以在交易中使用Object,不论是读或者写。
删除不用的Object可使用:
public fun delete(id: UID) { ... }
在多个struct结构体互相包含时,子结构体需要具备store能力。
当一个对象被包装在另一个对象中时,子对象不能作为函数参数传递,除非将其转移出来完成解包。
const Permissions = ['viewAccount','suggestTransactions'] as const;
// Check connection status of wallet
const result = await window.suiWallet.requestPermissions(Permissions);
const result = await window.suiWallet.mi(Permissions);
const result = await window.suiWallet.getAccounts();
// Note
interface MoveCallTransaction {
packageObjectId: ObjectId;
module: string;
function: string;
typeArguments: string[];
arguments: SuiJsonValue[];
gasPayment?: ObjectId;
gasBudget: number;
}
// Sign transaction
const result = await window.suiWallet.executeMoveCall(txs)
// Sign transaction (with Serialized)
const result = await window.suiWallet.executeSerializedMoveCall(tx.toString())
JavaScript SDK: