Sui生态概念入门Sui是从零开始设计的区块链平台,在2023年5月份完成主网的上线,使用Move编程语言进行应用开发。而本次训练营里会教大家使用Move的基础语法帮助完成Sui上的应用开发。训练营分为8个task,每个task里都能学到Sui平台上的一部分知识点,全部知识点都学完了以后,对于小
Sui是从零开始设计的区块链平台,在2023年5月份完成主网的上线,使用Move编程语言进行应用开发。而本次训练营里会教大家使用Move的基础语法帮助完成Sui上的应用开发。训练营分为8个task,每个task里都能学到Sui平台上的一部分知识点,全部知识点都学完了以后,对于小白来说,直接进行应用开发还有点难度,但是也算是踏进了Sui平台的门槛。
task1的目标是向Sui测试网上发布自己的包,并在包里面打印出自己的github id,我的github id是 coachafei
。
Move起源于Facebook(现在的Meta)的明星项目Diem(前身为Libra,https://github.com/diem/diem
)。Move诞生自Diem,
Diem最开始是想做一个跨全球的区块链支付系统,但是Diem的开发者调研了目前存在的区块链编程语言和通用的编程语言后,认为通用的语言里没有包含区块链所需的特性,而现有的区块链编程语言又太过复杂,不太适用于这样一个系统。又或者特性满足,但是性能和安全性不能满足,于是大佬们就从通用语言中选择了Rust作为基础样本。
因为Rust里的很多安全概念可以很好的满足这样一个系统的要求,例如所有权机制,可以避免资产的双花诞生。因此就借鉴Rust的特性和语法习惯,简化出一些只和资产处理有关的特性。于是面向资产编程的Move语言就诞生了。
Move语言的特点:
Move的官方仓库是https://github.com/move-language/move-sui
,对于开发能力强的大佬,可以去直接看Move语言的源码。
Move是一门编程语言的同时,还是面向资产编程的特定语言,业界称为智能合约编程语言。智能合约是一种运行在区块链上的计算机程序,类比现实生活中,智能合约就像是程序世界的法律,规定了程序必须如何执行,双方都要遵守这个约定,并且都不能违反这个合约,目前对于智能合约还只有初步的模糊印象。
智能合约编程语言可以实现:
Move编程语言和其他编程语言的差别
上面的内容主要都是Move语言的一些基本概念介绍,下面才是 task1 完成的基本流程。
下面是一个简单的move语言编程示例:
public struct Hello has key {
id: UID,
say: String
}
fun init(ctx: &mut TxContext) {
let hello_move = Hello {
id: object::new(ctx),
say: string(b"move"),
};
transfer(hello_move, sender(ctx));
}
上面就是我们用来完成task1的文件模板,在训练营仓库的完整文件路径是:
https://github.com/move-cn/letsmove/tutorial/bootcamp/01_hello/hello_move/sources/hello.move
要完成task1,我们需要先在github上把训练营仓库fork到自己的名称空间中,github的fork操作这里就不过多赘述了。fork完成后,在自己的开发电脑上执行命令:
git clone https://github.com:coachafei/letsmove.git
把训练营仓库克隆到本地,供后面的流程使用。因为已经有大量用户向这个仓库里提交pr并且合入了,因此这个项目会比较大,最好是通过科学上网才能够顺利克隆到本地。
主要有下面3个目标:
brew install sui
命令直接安装安装chrome浏览器钱包(这一步需要科学上网),基本步骤是:
打开chrome浏览器,点击右上角头像旁边的3个点,然后点击extensions,在打开的菜单里点击Visit Chrome Web Store
,如下所示:
在打开的Chrome 插件商店中间的搜索框里输入 Sui wallet,然后在搜索结果中点击 Slush - A Sui wallet
,如下所示,这个是改版后的Sui插件钱包:
在搜索结果中找到Slush Sui walllet,并点击它,进入Slush Sui Wallet界面后,点击右边的添加到Chrome
按钮安装,
安装好了以后,会自动弹开Slush钱包的配置页面,点击页面下面的More Option
,然后选择Create a passphrase account
:
会自动打开助记词页面,助记词是为了帮助你恢复钱包账户,因此一定要像密码一样严格保管。点击copy按钮复制助记词保存下来。
确认保存好以后,点击next进入下一步,为你的钱包设置一个密码,确保密码有足够的强度,确认完毕后点击next:
为钱包设置一个不用锁定的时间,超过这个时间点击浏览器上的钱包插件图标时,会要求你输入密码,同时记得勾选下面的 Confirm Transaction,表示通过钱包进行事务交易的时候要输入密码,为了安全起见新手一定要勾选,最后点击next:
到这里Chrome浏览器上的插件钱包就安装完毕,点击钱包图标后,看到的钱包界面如下所示:
左上角以0x开头的就是我们的账户地址,这里需要注意区分一个概念,钱包里可以存多个账户地址,就和每个人可以有多个银行账户一样。然后可以在一个手机上管理多个银行账户。交易的时候一般用的是账户地址,而不是钱包,钱包只是为了方便账户管理而开发的一个工具。
到这里,我们的基本环境就差不多准备好了。
使用vscode或者rustover打开我们克隆到本地的letmove项目,我这里用的是vscode。打开vscode的终端页面,执行下面的命令切换到mover子目录,然后复制社区提供的模板文件并重命名为github id同名用户目录,
cd mover/
cp 001 coachafei
创建存放任务代码的task1子目录,然后切换到这个目录下创建新的项目hellomove
:
mkdir coachafei/code/task1
cd coachafei/code/task1
sui move new hellomove
把项目根目录开始的tutorial/bootcamp/01_hello/sources/hello.move
文件里的内容复制并粘贴到我们task1里的hellomove/sources/hellomove.move
文件中。
复制的时候需要注意,示例文件里的模块名称叫hello_move
,我们上面命令里使用的是hellomove
,因此需要把复制的文件内容里的hello_move
修改为hellomove
。
复制完成后,把hellomove.move
文件中的b"move"
修改为b"coachafei"
,即你自己的github id。那么task1的配置就完成了,下面需要把它发布到区块链的测试网上。
在vscode的终端窗口执行下面的内容把我们自己的项目发布上链
sui client publish
这个命令必须在项目目录下执行,后续会下载sui代码库,需要科学上网。
在这个命令执行过程中会有几个操作,分别是:
它在编译完成上链的时候可能会因为没有足够的gas费用导致上链失败,每一次区块链交易都需要支付一定的gas费用,而gas费用则来自于区块链网络上的币(Coin),如果没有足够的币就会出现下面的报错:
出现这种错误时,需要通过下面两步来处理:
sui client faucet
新版本在执行这个命令后,可能会出现下面的提示:
要求你到这个地址上去请求测试网络的Sui币,打开这个地址后,如下所示:
在页面中输入你之前执行sui client publish
命令时创建的本地账户地址,然后点击下面的按钮来申请测试网络Sui 币。
sui client gas
正常情况下如果获取到了测试网上的Sui 币,就会出现下面的显示:
[warn] Client/Server api version mismatch, client api version : 1.37.1, server api version : 1.44.2
╭────────────────────────────────────────────────────────────────────┬────────────────────┬──────────────────╮
│ gasCoinId │ mistBalance (MIST) │ suiBalance (SUI) │
├────────────────────────────────────────────────────────────────────┼────────────────────┼──────────────────┤
│ 0xddc8864c968c04067b00692ec9fca7e71af321b3aea85b85b2b21fd9a1645416 │ 982111440 │ 0.98 │
╰────────────────────────────────────────────────────────────────────┴────────────────────┴──────────────────╯
对于测试网络,通过这两个命令确认拿到了测试Sui 币后,再执行publish
子命令才能正常发布。发布成功后,会出现大量输出的内容,在输出内容中找到package_id
,类似下面这样:
package id: 0xcbb694013c7c846a30899d7882b770b193d461f14266239bce04f1d4172cce3d
Sui目前有4套网络,分别是:
除了本地部署的local网络你可以自己获取测试币以后,devnet和testnet都需要通过水龙头来获取测试币,我们上面发布hellomove包时获取的就是测试网络的Sui币。而主网上币则是可以换到钱的币,因此需要购买或者通过参加活动由其他拥有币的开发者转给你。
可以通过命令 sui client envs
查看本地的网络配置,示例输出如下:
╭─────────┬─────────────────────────────────────┬────────╮
│ alias │ url │ active │
├─────────┼─────────────────────────────────────┼────────┤
│ testnet │ https://fullnode.testnet.sui.io:443 │ │
│ mainnet │ https://fullnode.mainnet.sui.io:443 │ │
│ devnet │ https://fullnode.devnet.sui.io:443 │ │
│ local │ http://127.0.0.1:9000 │ * │
╰─────────┴─────────────────────────────────────┴────────╯
网络后面的*
号表示是正在使用的网络。可以使用命令 sui client switch --env netname
命令切换到不同的网络,例如切换到主网就是 sui client switch --env mainnet
。
执行 sui client publish
命令后,就相当于执行了一次事务,每次执行事务都需要支付一次交易的gas费用。发布事务时会输出大量的数据信息。信息解析如下。
事务摘要是本次事务的唯一性标识,可以在链上通过这个唯一性标识来查询事务的详细信息。
Transaction Digest: VTZGbGrd2MVuP1sqVRgCYAnhwrw7VkW9DD45Yex9V4N
事务数据里包含本次事务的详细信息,包括
等等,如下所示:
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Data │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Sender: 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 │
│ Gas Owner: 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 │
│ Gas Budget: 10253600 MIST │
│ Gas Price: 1000 MIST │
│ Gas Payment: │
│ ┌── │
│ │ ID: 0x32ac5c34019e37774fce9977978c033211f9eca1b86494aac051403f87255fa5 │
│ │ Version: 349174470 │
│ │ Digest: A94DtyGCtuVBWrirWikxgj6ayY1JdzfNB95p98ptBbr7 │
│ └── │
│ │
│ Transaction Kind: Programmable │
│ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ Input Objects │ │
│ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 Pure Arg: Type: address, Value: "0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635" │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
│ ╭─────────────────────────────────────────────────────────────────────────╮ │
│ │ Commands │ │
│ ├─────────────────────────────────────────────────────────────────────────┤ │
│ │ 0 Publish: │ │
│ │ ┌ │ │
│ │ │ Dependencies: │ │
│ │ │ 0x0000000000000000000000000000000000000000000000000000000000000001 │ │
│ │ │ 0x0000000000000000000000000000000000000000000000000000000000000002 │ │
│ │ └ │ │
│ │ │ │
│ │ 1 TransferObjects: │ │
│ │ ┌ │ │
│ │ │ Arguments: │ │
│ │ │ Result 0 │ │
│ │ │ Address: Input 0 │ │
│ │ └ │ │
│ ╰─────────────────────────────────────────────────────────────────────────╯ │
│ │
│ Signatures: │
│ grPQYvgfutC5zJTUvtgqixVtTM7Uklqnva6UsJD8XT/dB5LhzugPRrhiAeEcVo/jb8WJnPpebG/r5czMOJVGBA== │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
这部分内容包含了交易的状态,交易对网络状态所做的更改,以及交易所涉及的对象。
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Transaction Effects │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Digest: VTZGbGrd2MVuP1sqVRgCYAnhwrw7VkW9DD45Yex9V4N │
│ Status: Success │
│ Executed Epoch: 679 │
│ │
│ Created Objects: │
│ ┌── │
│ │ ID: 0x50d2ae11dba3be2e4fa0088530a6c6f3637183e0818f7b0b423453070e16b8c3 │
│ │ Owner: Account Address ( 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 ) │
│ │ Version: 349174471 │
│ │ Digest: 83xSwgve3E6himz8K6qsqDD7PMoxDFuqPoyiHhuPxdA │
│ └── │
│ ┌── │
│ │ ID: 0x9f02ee0c66dbd5dcdf7a7f4f89499a4203bf49a2230b280e394b5bf54795617f │
│ │ Owner: Immutable │
│ │ Version: 1 │
│ │ Digest: Eqr4zwM8PtPVmKGuRzbPSR52D5zdqGnBPueoEtRqYbeS │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ID: 0x32ac5c34019e37774fce9977978c033211f9eca1b86494aac051403f87255fa5 │
│ │ Owner: Account Address ( 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 ) │
│ │ Version: 349174471 │
│ │ Digest: CKvkXMoxmnviZRV2579sCdMh6Bt8vjNA7bv8gedsPm1Y │
│ └── │
│ Gas Object: │
│ ┌── │
│ │ ID: 0x32ac5c34019e37774fce9977978c033211f9eca1b86494aac051403f87255fa5 │
│ │ Owner: Account Address ( 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 ) │
│ │ Version: 349174471 │
│ │ Digest: CKvkXMoxmnviZRV2579sCdMh6Bt8vjNA7bv8gedsPm1Y │
│ └── │
│ Gas Cost Summary: │
│ Storage Cost: 8253600 MIST │
│ Computation Cost: 1000000 MIST │
│ Storage Rebate: 978120 MIST │
│ Non-refundable Storage Fee: 9880 MIST │
│ │
│ Transaction Dependencies: │
│ 5MBY2WgzpjRKma7TGK46GoszzwssZKaXZgW5DBe3PY5z │
│ 5XvhL1EeEbZcMfKaGHzkiVvbkVk1DM7Adp4cMbku4gQ4 │
│ J4Uru4JqPRC4PpFmVDfMBKqvcaiNdfkpHewqGdnfJMPZ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
如果触发了任何事件,会在这个部分被看到,但是我们的示例里没有使用任何包,所以这里看不到相关的内容,如下所示:
╭─────────────────────────────╮
│ No transaction block events │
╰─────────────────────────────╯
后面会学习怎么主动触发事件。
这部分记录了本次交易里变更的对象,在本次交易里
╭──────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Object Changes │
├──────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x50d2ae11dba3be2e4fa0088530a6c6f3637183e0818f7b0b423453070e16b8c3 │
│ │ Sender: 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 │
│ │ Owner: Account Address ( 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 ) │
│ │ ObjectType: 0x2::package::UpgradeCap │
│ │ Version: 349174471 │
│ │ Digest: 83xSwgve3E6himz8K6qsqDD7PMoxDFuqPoyiHhuPxdA │
│ └── │
│ Mutated Objects: │
│ ┌── │
│ │ ObjectID: 0x32ac5c34019e37774fce9977978c033211f9eca1b86494aac051403f87255fa5 │
│ │ Sender: 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 │
│ │ Owner: Account Address ( 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 ) │
│ │ ObjectType: 0x2::coin::Coin<0x2::sui::SUI> │
│ │ Version: 349174471 │
│ │ Digest: CKvkXMoxmnviZRV2579sCdMh6Bt8vjNA7bv8gedsPm1Y │
│ └── │
│ Published Objects: │
│ ┌── │
│ │ PackageID: 0x9f02ee0c66dbd5dcdf7a7f4f89499a4203bf49a2230b280e394b5bf54795617f │
│ │ Version: 1 │
│ │ Digest: Eqr4zwM8PtPVmKGuRzbPSR52D5zdqGnBPueoEtRqYbeS │
│ │ Modules: todo_list │
│ └── │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
这部分记录了账号上的SUI代币变化情况,如下所示:
╭───────────────────────────────────────────────────────────────────────────────────────────────────╮
│ Balance Changes │
├───────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ┌── │
│ │ Owner: Account Address ( 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 ) │
│ │ CoinType: 0x2::sui::SUI │
│ │ Amount: -8275480 │
│ └── │
╰───────────────────────────────────────────────────────────────────────────────────────────────────╯
例如本次交易话费了8275480MISTs,约等于0.083 SUI币。
除了命令行里的输出外,我们还可以通过区块链浏览器到Sui的区块链网络上去查看我们发布上链的内容详细信息。常用的区块链浏览器有:
打开以后就可以看到Sui区块链网络,默认打开的是Sui区块链的主网,如下所示。
这个时候点击右上角的Mainnet
图标,就可以看到下面的内容:
在这里可以切换主网Mainet、测试网Testnet和开发网Devnet,我们刚才测试上链的是测试网,因此要点击第三个Testnet进行网络切换。
在切换完成后,在页面中间的搜索框中输入发布成功时记录下来的那一串哈希值Package id
,就能搜索到你上链的内容,如下所示:
要在页面上能看到输出你的github id信息,例如图中的coachafei,表示我第一个任务就完成了。然后需要记录3个信息:
记录下来以后,把这3个内容填写到个人目录下的README.md文件中,截图保存在个人目录下的images子目录中。保存好以后执行命令:
git add .
git commit -m '完成task1'
git push
把第一次任务的内容推送到自己的仓库中,然后到github页面上提交第一次任务的PR,等待小管家的合入。合入成功后,小管家就会向你的钱包账户里转入本次任务的奖励。
在上面的示例中,我们向链上发布了一个hello_move
包。下面是另一个演示向链上发布包todoList
的示例,和链上的对象进行交互,主要流程包括:
1.创建todoList项目并发布;
2.通过CLI命令调用发布的对象并构建交易
3.把对象传递给函数
4.链式调用
首先执行命令
sui move new todo_list
创建todo_list包,然后打开包里的sources/todo_list.move
文件,内容如下:
module todo_list::todo_list {
use std::string::String;
// List of todos, Can be managed by the owner and shared with others
public struct TodoList has key, store {
id: UID,
items: vector<String>
}
// Create a new todo list.
public fun new(ctx: &mut TxContext): TodoList {
let list = TodoList {
id: object::new(ctx),
items: vector[],
};
(list)
}
// Add a new todo item to the list.
public fun add(list: &mut TodoList, item: String) {
list.items.push_back(item)
}
// Remove a todo item from the list.
public fun remove(list: &mut TodoList, index: u64): String {
list.items.remove(index)
}
// Delete the list and the capability to manage it.
public fun delete(list: TodoList) {
let TodoList {id, items: _} = list;
id.delete();
}
// Get the number of items in the list.
public fun length(list: &TodoList): u64 {
list.items.length()
}
}
在模块todo_list里定义了TodoList对象,以及和它交互的5个方法。方法的作用分别是:
然后执行命令
sui client publish
把这个todo_list
包发布到测试网上,发布完成后,在事务数据中能够找到创建的todo_list包的PackageId
,如下所示:
│ Published Objects: │
│ ┌── │
│ │ PackageID: 0x9f02ee0c66dbd5dcdf7a7f4f89499a4203bf49a2230b280e394b5bf54795617f │
│ │ Version: 1 │
│ │ Digest: Eqr4zwM8PtPVmKGuRzbPSR52D5zdqGnBPueoEtRqYbeS │
│ │ Modules: todo_list │
│ └── │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
我们记下这个PackageID
的值。
为了演示和todo_list包的交互,会使用CLI命令来构建一个交易,调用包里的new
方法在链上创建一个TodoList
列表对象,并向列表里添加一个项目。
首先需要使用export命令把两个值保存在环境变量里:
export PACKAGE_ID=0x9f02ee0c66dbd5dcdf7a7f4f89499a4203bf49a2230b280e394b5bf54795617f
export MY_ADDRESS=$(sui client active-address)
第一个变量是todo_list包在链上的对象地址,第二个变量是本地账户地址。
构建交易会使用sui clint ptb
命令,详细的交易命令如下所示:
sui client ptb \
--gas-budget 100000000 \
--assign sender @$MY_ADDRESS \
--move-call $PACKAGE_ID::todo_list::new \
--assign list \
--transfer-objects "[list]" sender
参数说明:
--gas-budget
,交易费用预算;--assign sender $MY_ADDRESS
,指定发送者。--move-call $PACKAGE_ID::tod_list::new
,表示是一个调用操作,调用链上$PACKGE_ID
对象里的todo_list
模块中的new
方法--assign list
,表示把这个方法的返回结果分配给list变量。--transfer-objects "[list]" sender
,表示把[list]
对象所有权转移给sender对象,即本地账户。这个命令执行完成后,会看到类似之前sui client publish
命令的输出。我们需要关注的是信息里面的Created Objects
内容,即我们新建的对象,它包含了新建的TodoList的对象ID、类型和版本信息,如下所示:
├─────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Created Objects: │
│ ┌── │
│ │ ObjectID: 0x433b2981e439c1e3eaef42a12736b72322ef9e3bc6996ff122526660d0743ca8 │
│ │ Sender: 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 │
│ │ Owner: Account Address ( 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 ) │
│ │ ObjectType: 0x9f02ee0c66dbd5dcdf7a7f4f89499a4203bf49a2230b280e394b5bf54795617f::todo_list::TodoList │
│ │ Version: 349174472 │
│ │ Digest: HgrsygxErokz9JEDJAXT7gaXvRUSHjYWnhJNnvzgQ2gt
│ └── │ │
从输出信息中可以看到新建的对象ID是:0x433b2981e439c1e3eaef42a12736b72322ef9e3bc6996ff122526660d0743ca8
,发送者是我们本地账户的地址。所有者也是我们本地账户地址。还可以通过命令:
sui client objects
来确认,在输出信息中能找到类似如下所示的内容:
│ ╭────────────┬──────────────────────────────────────────────────────────────────────╮ │
│ │ objectId │ 0x433b2981e439c1e3eaef42a12736b72322ef9e3bc6996ff122526660d0743ca8 │ │
│ │ version │ 349174472 │ │
│ │ digest │ 9/EKaBhcvkj8qbE+uHtAZATouVfKmfrwvWD5sD2haJU= │ │
│ │ objectType │ 0x9f02..617f::todo_list::TodoList │ │
│ ╰────────────┴──────────────────────────────────────────────────────────────────────╯ │
上一步创建了TodoList对象列表,我们作为它的所有者,也可以和它进行交互。可以在它上面调用todo_list
模块里的函数并获取返回结果。首先我们向它里面添加一个项目。
定义一个环境变量关联到创建好的列表对象:
export LIST_ID=0x433b2981e439c1e3eaef42a12736b72322ef9e3bc6996ff122526660d0743ca8
交易的命令是:
sui client ptb \
--gas-budget 10000000 \
--move-call $PACKAGE_ID::todo_list::add @$LIST_ID "'Finish the Hello, Sui chapter'"
上面的命令中调用了todo_list模块里的add函数,并向他传递了两个参数,分别是 @LIST_ID和后面的项目,项目是一个字符串。
这个命令调用只对现有对象进行操作,并没有生成新的对象,因此在实际的输出结果中不会有Created Objects
信息,只有Mutable Objects
信息。
通过命令 sui client object $LIST_ID
,可以看到变化后的TodoList对象内容如下:
╭───────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ objectId │ 0x433b2981e439c1e3eaef42a12736b72322ef9e3bc6996ff122526660d0743ca8 │
│ version │ 349174473 │
│ digest │ 6AQ8i83Sx7QKD6Xkq1QjQfymCEnC3rZvpXbyQczLZ97z │
│ objType │ 0x9f02ee0c66dbd5dcdf7a7f4f89499a4203bf49a2230b280e394b5bf54795617f::todo_list::TodoList │
│ owner │ ╭──────────────┬──────────────────────────────────────────────────────────────────────╮ │
│ │ │ AddressOwner │ 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 │ │
│ │ ╰──────────────┴──────────────────────────────────────────────────────────────────────╯ │
│ prevTx │ HSZyJxA1oLo9fFzer8qouJp8iQmAntjooNTrSHQ81bZ3 │
│ storageRebate │ 1558000 │
│ content │ ╭───────────────────┬───────────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ │ dataType │ moveObject │ │
│ │ │ type │ 0x9f02ee0c66dbd5dcdf7a7f4f89499a4203bf49a2230b280e394b5bf54795617f::todo_list::TodoList │ │
│ │ │ hasPublicTransfer │ true │ │
│ │ │ fields │ ╭───────┬───────────────────────────────────────────────────────────────────────────────╮ │ │
│ │ │ │ │ id │ ╭────┬──────────────────────────────────────────────────────────────────────╮ │ │ │
│ │ │ │ │ │ │ id │ 0x433b2981e439c1e3eaef42a12736b72322ef9e3bc6996ff122526660d0743ca8 │ │ │ │
│ │ │ │ │ │ ╰────┴──────────────────────────────────────────────────────────────────────╯ │ │ │
│ │ │ │ │ items │ ╭─────────────────────────────────╮ │ │ │
│ │ │ │ │ │ │ Finish the Hello, Sui chapter │ │ │ │
│ │ │ │ │ │ ╰─────────────────────────────────╯ │ │ │
│ │ │ │ ╰───────┴───────────────────────────────────────────────────────────────────────────────╯ │ │
│ │ ╰───────────────────┴───────────────────────────────────────────────────────────────────────────────────────────╯ │
╰───────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
从输出中可以看到,这个TodoList
对象里有我们新添加进去的字符串Finish the Hello, Sui chapter
。
链式调用指的是,我们在ptb
子命令构建的单个交易里可以同时跟上多次函数调用,对同一个对象进行多次操作。例如下面的示例交易命令,对上面的列表对象添加3个项目并删除1个项目:
sui client ptb \
--gas-budget 100000000 \
--move-call $PACKAGE_ID::todo_list::add @$LIST_ID "'Finish Concepts chapter'" \
--move-call $PACKAGE_ID::todo_list::add @$LIST_ID "'Read the Move Basics chapter'" \
--move-call $PACKAGE_ID::todo_list::add @$LIST_ID "'Learn about Object Model'" \
--move-call $PACKAGE_ID::todo_list::remove @$LIST_ID 0
命令执行成功后,再使用命令sui client object $LIST_ID,看到的列表对象内容如下:
╭───────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ objectId │ 0x433b2981e439c1e3eaef42a12736b72322ef9e3bc6996ff122526660d0743ca8 │
│ version │ 349174474 │
│ digest │ 26BYuhizgqWKFWaaAZQ3w1CCzNPLK36U9Mvgf7AirNJU │
│ objType │ 0x9f02ee0c66dbd5dcdf7a7f4f89499a4203bf49a2230b280e394b5bf54795617f::todo_list::TodoList │
│ owner │ ╭──────────────┬──────────────────────────────────────────────────────────────────────╮ │
│ │ │ AddressOwner │ 0xd95ac7e46d610afd67d3862ca3db7ef8afc7c753c7b963e2a385bf5e2d638635 │ │
│ │ ╰──────────────┴──────────────────────────────────────────────────────────────────────╯ │
│ prevTx │ EhQ44T89qEUz7DvNuavsk3vefgvC3o2zJ9TtYvkmGjCb │
│ storageRebate │ 1922800 │
│ content │ ╭───────────────────┬───────────────────────────────────────────────────────────────────────────────────────────╮ │
│ │ │ dataType │ moveObject │ │
│ │ │ type │ 0x9f02ee0c66dbd5dcdf7a7f4f89499a4203bf49a2230b280e394b5bf54795617f::todo_list::TodoList │ │
│ │ │ hasPublicTransfer │ true │ │
│ │ │ fields │ ╭───────┬───────────────────────────────────────────────────────────────────────────────╮ │ │
│ │ │ │ │ id │ ╭────┬──────────────────────────────────────────────────────────────────────╮ │ │ │
│ │ │ │ │ │ │ id │ 0x433b2981e439c1e3eaef42a12736b72322ef9e3bc6996ff122526660d0743ca8 │ │ │ │
│ │ │ │ │ │ ╰────┴──────────────────────────────────────────────────────────────────────╯ │ │ │
│ │ │ │ │ items │ ╭────────────────────────────────╮ │ │ │
│ │ │ │ │ │ │ Finish Concepts chapter │ │ │ │
│ │ │ │ │ │ │ Read the Move Basics chapter │ │ │ │
│ │ │ │ │ │ │ Learn about Object Model │ │ │ │
│ │ │ │ │ │ ╰────────────────────────────────╯ │ │ │
│ │ │ │ ╰───────┴───────────────────────────────────────────────────────────────────────────────╯ │ │
│ │ ╰───────────────────┴───────────────────────────────────────────────────────────────────────────────────────────╯ │
╰───────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
从结果中可以看到,新增了3个新的字符串,并且上一步添加的字符串通过索引0把它删除了,因此TodoList对象中还剩下新增的3个字符串。
task1里涉及到的知识点包括:
ptb
子命令调用链上对象;如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!