一:Testnet
S
u
i
\mathit {Sui}
Sui 拥有主网、开发网和测试网网络,其中,测试网网络又可以分为
D
e
v
n
e
t
\mathit {Devnet}
Devnet 和
T
e
s
t
n
e
t
\mathit {Testnet}
Testnet,当然,你也可以构建本地
S
u
i
\mathit {Sui}
Sui 网络进行纯本地开发,但是本地的开发环境不是持久的,每一次启动,本地网络都会作为一个全新的网络启用。
这里我们选择连接到
T
e
s
t
n
e
t
\mathit {Testnet}
Testnet 尝试发布我们的第一个程序,当然,你也可以选择
D
e
v
n
e
t
\mathit {Devnet}
Devnet 或者本地网络再或者其它,原理都是一样的,只是代码细节需要根据实际选择进行调整。
如果你还没有安装
S
u
i
\mathit {Sui}
Sui 的话,可以根据之前的文章布置环境,现在,在命令行输入 sui client
,如果此前没有运行过相关命令,那么系统将为您配置客户端信息,显示为:Config file ["<PATH-TO-FILE>/client.yaml"] doesn't exist, do you want to connect to a Sui Full node server [y/N]?
按
y
\mathit y
y 并回车后,终端会提示:Sui Full node server URL (Defaults to Sui Devnet if not specified) :
这里将默认连接到
D
e
v
n
e
t
\mathit {Devnet}
Devnet,如果要在初次连接就一步到位选择我们即将使用的
T
e
s
t
n
e
t
\mathit {Testnet}
Testnet 的话,需要在这里键入对应的地址。不过,由于后续也可以更换连接的网络,并且之后的那种方法更加通用~~(这也是为什么要选 Testnet,方便展现那种方法)~~,所以我们这里不如直接回车,得到如下提示:Select key scheme to generate keypair (0 for ed25519, 1 for secp256k1, 2 for secp256r1):
这里有
0
,
1
,
2
\text 0,\ \text 1,\ \text 2
0, 1, 2 三种加密方案可供选择,选哪个都行,键入任何一个供选择的数字后回车,根据具体情况,你将得到类似的,包含地址和
12
\text {12}
12 个恢复时使用的单词信息:Generated new keypair for address with scheme "ed25519" [0xb9c83a8b40d3263c9ba40d551514fbac1f8c12e98a4005a0dac072d3549c2442] Secret Recovery Phrase : [cap wheat many line human lazy few solid bored proud speed grocery]
这条信息最好能记录一下,说不定往后哪天就用到了呢。
此时,可以通过sui client envs
来查看当前的网络环境,不难发现只有一个
d
e
v
n
e
t
\mathit {devnet}
devnet 的网络正在活跃,换句话说,也就是我们当前的网络环境是
D
e
v
n
e
t
\mathit {Devnet}
Devnet。
如果想要切换到
T
e
s
t
n
e
t
\mathit {Testnet}
Testnet,就需要使用添加新网络环境的命令:sui client new-env --alias <ALIAS> --rpc <RPC-SERVER-URL>
其中,尖括号里的内容是需要替换的,
A
L
I
A
S
\mathit {ALIAS}
ALIAS 是自定义的别名,
P
R
C
\mathit {PRC}
PRC-
S
E
R
V
E
R
\mathit {SERVER}
SERVER-
U
R
L
\mathit{URL}
URL 是想要连接到的新的网络的地址,已知
T
e
s
t
n
e
t
\mathit {Testnet}
Testnet 的
U
R
L
\mathit {URL}
URL 为 https://fullnode.devnet.sui.io:443
,如果将其命名为testnet
,就可以通过这条命令来添加:sui client new-env --alias testnet --rpc https://fullnode.devnet.sui.io:443
此时再通过sui client envs
来查看网络环境,就可以看到有两条,但是当前依旧处于
d
e
v
n
e
t
\mathit {devnet}
devnet,用如下命令就可以将其切换到
t
e
s
t
n
e
t
\mathit {testnet}
testnet:sui client switch --env testnet
同理,如果你想要添加新的网络,或者切换到别的网络,就可以以此举一反三。
二:重写 a + b
这是我们上一篇写的 a + b \mathit a + \mathit b a+b:
module my_first_package::my_module {
public fun add(a: u64, b: u64): u64 {
a + b
}
}
发布到链上之后测试代码都无法使用了,似乎也没有什么好的输出手段让用户得到
a
+
b
\mathit a + \mathit b
a+b 的结果,那么我们来考虑一个问题,对象和拥有者。
m
o
v
e
\mathit {move}
move 代码中,任何一个东西都是对象,如果丧失了拥有者,那么这个所谓的对象也将走向消亡,当然,这里的“消亡”有的时候必须手动进行,这就不是这篇文章需要讨论的内容了。
回到上述问题,如果我们将
a
+
b
\mathit a + \mathit b
a+b 的结果对象,拥有权从当前函数转交到程序的拥有者(在这里,也就是我们)的手上,这样一来,就增加了该结果对象的寿命,我们再通过对象的地址去询问答案,是不是就完美解决了问题?
稍加拓展,如果我们想要重新定义一个对象呢?
在 m o v e \mathit {move} move 语言当中,定义一个类型可以有四种修饰词:
- C o p y \mathit {Copy} Copy:被修饰的值可以被复制。
- D r o p \mathit {Drop} Drop:被修饰的值在作用域结束时可以被丢弃。
- K e y \mathit {Key} Key:被修饰的值可以作为键值对全局状态进行访问。
- S r o t e \mathit {Srote} Srote:被修饰的值可以被存储到全局状态。
基本类型和内建类型的修饰词都是预先定义并且不可更改的,比如整型、布尔类型同时拥有除了 K e y \mathit {Key} Key 之外的其它三项。
显然,针对上述问题,我们需要对自定义的对象,添加 K e y \mathit {Key} Key 修饰词,让它能够被唯一标识并全局访问。因此,我们可以将代码进行如下修改:
module my_first_package::my_module {
use sui::object::{Self, UID};
use sui::tx_context::{Self, TxContext};
use sui::transfer;
struct Result has key {
id: UID,
res: u64,
}
public fun add(a: u64, b: u64, ctx: &mut TxContext) {
let result = Result {
id: object::new(ctx),
res: a + b,
};
transfer::transfer(result, tx_context::sender(ctx));
}
}
导入相关模块后,定义了一个名为
R
e
s
u
l
t
\mathit {Result}
Result 的结构体,它拥有唯一表示用的
i
d
\mathit {id}
id 以及用来存储
a
+
b
\mathit a + \mathit b
a+b 结果的整型字段
r
e
s
\mathit {res}
res。
在
a
d
d
\mathit {add}
add 函数当中,我们创建了一个
R
e
s
u
l
t
\mathit {Result}
Result 存储在
r
e
s
u
l
t
\mathit {result}
result 当中,
i
d
\mathit {id}
id 是通过自带的方式唯一生成的,
r
e
s
\mathit {res}
res 自然就是通过传入的两个参数相加得到。
很容易注意到
T
x
C
o
n
t
e
x
t
\mathit {TxContext}
TxContext,这是一个特殊参数,不需要用户自己传递,这也是为什么一般作为函数最后一个参数而不写在前面的原因,它记录有有关交易的基本信息,本篇文章不适合深究,有兴趣的小伙伴可以去官方文档查看。
最后,有一个
t
r
a
n
s
f
e
r
\mathit {transfer}
transfer 操作,目的就是将
r
e
s
u
l
t
\mathit {result}
result 的拥有权转交到“我们”手上。
三:发布
链上的交易都是需要开销的,即使是测试网络,那么,开销怎么来?既然是测试用网,肯定不需要自己掏腰包,只需要一行命令就可以搞定:sui client faucet
,回车后会提示你到账有延迟,大概等个一分钟左右,通过sui client gas
查看余额。
如果你申请了多次,就会到账多次,对于每一笔金额,可以拆分也可以合并,这不是本篇文章的重点也就不再赘述。
现在,我们就可以用领到的测试用水去发布上链第一个程序:sui client publish --gas-budget 5000000
,其中--gas-budget
表示本次交易的最大开销,如果超过了这个金额,那么发布将会失败。
如果你得到了error: InsufficientGas
,这就是金额设置的不够大,扩大金额重新发布即可。
成功之后终端会返回交易的详细信息,包括交易数据、交易效果、交易块事件、对象更改和余额更改。
在
O
b
j
e
c
t
C
h
a
n
g
e
s
\mathit {Object\ Changes}
Object Changes 表中,可以查看到以发布内容的详细信息,包括它的
I
D
\mathit {ID}
ID,这也是我们通过调用链上程序时所需要的信息。
sui client call --function <FUNCTION_NAME> --package <PACKAGE_ID> --module <MODULE_NAME> --args <...> --gas-budget 10000000
- F U N C T I O N _ N A M E \mathit {FUNCTION\_NAME} FUNCTION_NAME 是调用的函数名。
- P A C K A G E _ I D \mathit {PACKAGE\_ID} PACKAGE_ID 是从 O b j e c t C h a n g e s \mathit {Object\ Changes} Object Changes 表中得到的 I D \mathit {ID} ID 信息。
- M O D U L E _ N A M E \mathit {MODULE\_NAME} MODULE_NAME 是调用的模块名。
- a r g s \mathit {args} args 后的尖括号内依次填传入函数的参数,之间用空格隔开。
- 最后的数据,同样的,代表本次交易的最大开销。
按照要求填入并执行命令,例如:sui client call --function add --package 0xe2496799139225a06e7251857cdf46a32c20d773030c62b9bf24095cd60aac43 --module my_module --args 333 666 --gas-budget 10000000
同样的,终端会返回交易的详细信息,其中可以在
O
b
j
e
c
t
C
h
a
n
g
e
s
\mathit {Object\ Changes}
Object Changes 表当中,看到这一笔交易过后我们有了一个自己所拥有的对象,这其中就存储有
a
+
b
\mathit a + \mathit b
a+b 的结果,可以借助其
O
b
j
e
c
t
I
D
\mathit {ObjectID}
ObjectID 进行查询。
通过 sui client object <OBJECT_ID>
就可以看这个对象的详细信息,如下图所示:
333 + 666 = 999 \text {333} + \text {666} = \text {999} 333+666=999, r e s \mathit {res} res 当中存储的就是这个值,大成功(๑•̀ㅂ•́)و✧!
四:加入组织,共同进步!
- Sui 中文开发群(TG)
- M o v e \mathit{Move} Move 语言学习交流群: 79489587