新建项目
编译项目
Move 是一种编译语言,需要将源文件编译为 Move Bytecode,它仅包含有关模块、其成员和类型的必要信息,不包括注释和一些标识符(例如常量)。
Move Compiler 会创建一个文件夹,其中放置所有获取和编译的依赖项以及当前包模块的字节码。
生成的文件应该被添加到.gitignore
运行测试
1 2
| sui move test sui move test test_hello # 指定运行某个或多个测试
|
部署脚本
todo-list 复制链接中的代码,并按操作部署到测试网
1
| sui client publish --json
|
合约交互
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| # 找到合约部署后packageId "type": "published", "packageId": "0x102f24e8218fa6fb837137ada5a0ba30bac96e30b085bd6de99a11727b794a79",
# 准备变量 export PACKAGE_ID=0x102f24e8218fa6fb837137ada5a0ba30bac96e30b085bd6de99a11727b794a79 export MY_ADDRESS=$(sui client active-address)
# 调用合约 sui client ptb \ --gas-budget 100000000 \ --assign sender @$MY_ADDRESS \ --move-call $PACKAGE_ID::todo_list::new \ # 将new函数的返回值存储至 list 中 --assign list \ # 将 list 对象传输给 sender --transfer-objects "[list]" sender
# 执行成功后得到交互的响应信息,ObjectID类似一个TodoList的实例,拥有其所有权并可以调用其相关方法 Created Objects: ObjectID: 0x3ac554c410b36c309313eced79e6d86e251637b80ab54180c4d44b86c0538064 Sender: 0x7074c1cfb8327dcefcf6f44d14d1747bd24859df02a8ba2f31eaf6504385cf79 Owner: Account Address ( 0x7074c1cfb8327dcefcf6f44d14d1747bd24859df02a8ba2f31eaf6504385cf79 ) ObjectType: 0x102f24e8218fa6fb837137ada5a0ba30bac96e30b085bd6de99a11727b794a79::todo_list::TodoList
# 配置LIST_ID export LIST_ID=0x3ac554c410b36c309313eced79e6d86e251637b80ab54180c4d44b86c0538064
# 添加一个任务 sui client ptb \ --gas-budget 100000000 \ --move-call $PACKAGE_ID::todo_list::add @$LIST_ID "'0'"
# 查看 sui client object $LIST_ID
# 添加三个并删除两个, 验证同一个事务按下标删除 sui client ptb \ --gas-budget 100000000 \ --move-call $PACKAGE_ID::todo_list::add @$LIST_ID "'1'" \ --move-call $PACKAGE_ID::todo_list::add @$LIST_ID "'2'" \ --move-call $PACKAGE_ID::todo_list::add @$LIST_ID "'3'" \ --move-call $PACKAGE_ID::todo_list::remove @$LIST_ID 0 \ --move-call $PACKAGE_ID::todo_list::remove @$LIST_ID 0
# 删除多个的场景下会有错误,目前还没有找到啥原因 # 复现步骤: # 1.单独添加0 2.单独添加1 3.合并 删除0和1 sui client ptb \ --gas-budget 100000000 \ --move-call $PACKAGE_ID::todo_list::remove @$LIST_ID 0 \ --move-call $PACKAGE_ID::todo_list::remove @$LIST_ID 1 \ --move-call $PACKAGE_ID::todo_list::remove @$LIST_ID 2 \ --move-call $PACKAGE_ID::todo_list::remove @$LIST_ID 3
# Error executing transaction: Failure error: "MoveAbort(MoveLocation { module: ModuleId { address: 0000000000000000000000000000000000000000000000000000000000000001, name: Identifier(\"vector\") }, function: 14, instruction: 11, function_name: Some(\"remove\") }, 131072) in command 1"
|
相关概念
包
包由模块组成,包发布到区块链上并由地址
标识。
- 调用其函数的事务来与已发包的包交互
- 可以作为其他包的依赖,例如:自己编写的包可以依赖官方包
已发布的包
- 开发过程中包没有地址,一般需要设置为 0x0
- 已发布的包会有一个链上唯一地址,其中包含其模块的字节码,已发布的包不可变,并且可以通过发送交易与其交互
模块
- 模块包含函数、类型、常量、变量等
- 模块可以引入其他依赖包, 以todolist为例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| module todo_list :: todo_list 定义模块 包/address :: 模块名称
# 引入其他依赖包, std包/string模块/String类型 use std::string::String;
# 定义结构体 public struct TodoList has key, store { id: UID, items: vector<String> }
# 定义函数 public fun new(ctx: &mut TxContext): TodoList
|
Move.toml
[package]
: 包信息
- name: 导入时的包名称
- version: 包的版本号
- edition: Move的版本
[dependencies]
: 依赖包
- override = true, 解决版本冲突问题
- git 指定github仓库地址, local = path 指定本地路径
- subdir = “remote/path”
- rev = “main” 指定分支
[addresses]
: 地址
- 部分用于添加地址的别名,可以在此指定任意地址,然后在代码中用作别名
Address
地址是区块链上位置的唯一标识符。它用于识别包、帐户和对象
, 地址的固定大小为32字节,通常使用16进制表示
长度为 64 个字符(32 个字节),并以 0x 为前缀
1 2 3 4
| >>> len("0x04bde040cca2b5fec3c47a30cdeb3e11f011395c49886c91629b7dbd4713b319") 66 >>> len("04bde040cca2b5fec3c47a30cdeb3e11f011395c49886c91629b7dbd4713b319") 64
|
标准库的地址是 0x1 。小于 32 字节的地址在左侧用零填充。
1 2 3 4 5 6
| 0x1 = 0x0000000000000000000000000000000000000000000000000000000000000001 # Sui 标准库的地址(别名 std ) 0x2 - Sui 框架的地址(别名 sui ) 0x5 - Sui System 对象的地址 0x6 - 系统 Clock 对象的地址 0x8 - 系统 Random 对象的地址 0x403 - DenyList 系统对象的地址
|
Account
- 账户是识别用户的一种方式,账户由私钥生成并由地址标识。
- 账户可以拥有对象,并且可以发送交易,每笔交易都有一个发送者(地址)
- Sui支持多种密码算法生成账户,ed25519, secp256k1, zklogin
Transaction
与链交互的唯一方式,发起交易用于改变区块链的状态。
交易结构
- sender: 交互的操作者是谁
- list (or a chain) of commands: 要执行的操作
- command inputs: 简单类型值也可以是object
- gas object: 用于支付gas费用对象
- gas price and budget: 预估交易成本
commands
- 交易由多个命令组成,并按照它们列出的顺序执行。并且可以使用之前命令的结果
- 交易整体作为一个事务,要么全部成功,要么失败
1 2 3 4 5 6 7
| Inputs: - sender = 0xa11ce
Commands: - payment = SplitCoins(Gas, [ 1000 ]) - item = MoveCall(0xAAA::market::purchase, [ payment ]) - TransferObjects(item, sender)
|
- SplitCoins - 一个内置命令,用于从传递的对象(在本例中为 Gas 对象)中分离出新硬币
- MoveCall - 使用给定参数调用包 0xAAA 、模块 market 中的函数 purchase 的命令 - 给定参数 payment object
- TransferObjects - 将对象传输给接收者的内置命令
交易结果
交易对区块链状态的改变,可以通过以下方式更改状态:
- 使用 gas object 来支付交易
- 创建、更新和删除对象
- 记录事件
交易结果的组成:
- Transaction Digest: 交易摘要 - 交易的哈希值,用于识别交易
- Transaction Data: 交易数据 - 交易中使用的输入、命令和气体对象
- Transaction Effects: 交易效果 - 交易的状态和“效果”,更具体地说:交易的状态、对象及其新版本的更新、使用的气体对象、交易的气体成本以及交易发出的事件
- Events: 事件 - 交易发出的自定义事件
- Object Changes: 对象更改 - 对对象所做的更改,包括所有权的更改
- Balance Changes: 余额变化 - 交易涉及的账户总余额的变化