Sui Framework
- Sui Framework 什么是 Sui Framework, 大家第一次看到 Framework的时候会觉得奇怪,不知道是什么, 简单来说就是Sui Move的标准库,官方已经封装好了一些常用的库供大家使用
- Sui Framework 是经过了长期打磨,和安全验证的代码,阅读Framework不仅仅能掌握常用的工具库, 而且能更好的学习Sui Move,Framework每一个包和库都值得大家精心阅读和学习
move-stdlib
move stdlib 是来自Move上游的核心标准库,可以理解成最核心的标准库,基本上是需要大家都掌握的
总览,可以这样说 就是最好把这个系列的都完全掌握
模块名 | 大概用途 | 需要掌握程度 |
---|---|---|
address.move | 地址长度 | 了解 |
ascii.move | ascii编码的字符串 | 完全掌握 |
bcs.move | 把数据序列化成二进制 | 掌握 |
bit_vector.move | bit 位标记的数组 | 掌握 |
debug.move | 调试代码,打印输出 | 完全掌握 |
fixed_point32.move | 浮点数 | 掌握 |
hash.move | hash函数 | 掌握 |
option.move | 可选值 | 完全掌握 |
type_name.move | 获取结构的类型 | 完全掌握 |
unit_test.move | 单元测试生成测试signers | 了解 |
vector.move | 数组 | 完全掌握 |
address.move
基本上没什么用处
module std::address {
public fun length(): u64 {
32
}
}
ascii.move
ascii 编码规则的字符串,说白了就是只有a-z A-Z 0-9这些编码的字符串,只支持早期的英文字符
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
/// The `ASCII` module defines basic string and char newtypes in Move that verify
/// that characters are valid ASCII, and that strings consist of only valid ASCII characters.
module std::ascii {
use std::vector;
use std::option::{Self, Option};
/// An invalid ASCII character was encountered when creating an ASCII string.
const EINVALID_ASCII_CHARACTER: u64 = 0x10000;
struct String has copy, drop, store {
bytes: vector<u8>,
}
/// An ASCII character.
struct Char has copy, drop, store {
byte: u8,
}
/// Convert a `byte` into a `Char` that is checked to make sure it is valid ASCII.
public fun char(byte: u8): Char {
assert!(is_valid_char(byte), EINVALID_ASCII_CHARACTER);
Char { byte }
}
/// Convert a vector of bytes `bytes` into an `String`. Aborts if
/// `bytes` contains non-ASCII characters.
public fun string(bytes: vector<u8>): String {
let x = try_string(bytes);
assert!(
option::is_some(&x),
EINVALID_ASCII_CHARACTER
);
option::destroy_some(x)
}
public fun try_string(bytes: vector<u8>): Option<String> {
let len = vector::length(&bytes);
let i = 0;
while ({
spec {
invariant i <= len;
invariant forall j in 0..i: is_valid_char(bytes[j]);
};
i < len
}) {
let possible_byte = *vector::borrow(&bytes, i);
if (!is_valid_char(possible_byte)) return option::none();
i = i + 1;
};
spec {
assert i == len;
assert forall j in 0..len: is_valid_char(bytes[j]);
};
option::some(String { bytes })
}
/// Returns `true` if all characters in `string` are printable characters
/// Returns `false` otherwise. Not all `String`s are printable strings.
public fun all_characters_printable(string: &String): bool {
let len = vector::length(&string.bytes);
let i = 0;
while ({
spec {
invariant i <= len;
invariant forall j in 0..i: is_printable_char(string.bytes[j]);
};
i < len
}) {
let byte = *vector::borrow(&string.bytes, i);
if (!is_printable_char(byte)) return false;
i = i + 1;
};
spec {
assert i == len;
assert forall j in 0..len: is_printable_char(string.bytes[j]);
};
true
}
public fun push_char(string: &mut String, char: Char) {
vector::push_back(&mut string.bytes, char.byte);
}
public fun pop_char(string: &mut String): Char {
Char { byte: vector::pop_back(&mut string.bytes) }
}
public fun length(string: &String): u64 {
vector::length(as_bytes(string))
}
/// Get the inner bytes of the `string` as a reference
public fun as_bytes(string: &String): &vector<u8> {
&string.bytes
}
/// Unpack the `string` to get its backing bytes
public fun into_bytes(string: String): vector<u8> {
let String { bytes } = string;
bytes
}
/// Unpack the `char` into its underlying byte.
public fun byte(char: Char): u8 {
let Char { byte } = char;
byte
}
/// Returns `true` if `b` is a valid ASCII character. Returns `false` otherwise.
public fun is_valid_char(b: u8): bool {
b <= 0x7F
}
/// Returns `true` if `byte` is an printable ASCII character. Returns `false` otherwise.
public fun is_printable_char(byte: u8): bool {
byte >= 0x20 && // Disallow metacharacters
byte <= 0x7E // Don't allow DEL metacharacter
}
}
bcs
bcs 大家可能比较模糊,有的人不太了解是什么东西,我举一个例子,就是你定义好一个json的数据结构,然后把它转成json字符串 字符串这个类型就是一个通用的数据类型 bsc存在的意义就是把Move的数据结构转成通用的序列化好的一种二进制 好处就是单一类型了,通用性很强,能在不同的编程语言之间传递,反序列化回来了也具有唯一的数据对应
module std::bcs {
/// Return the binary representation of `v` in BCS (Binary Canonical Serialization) format
native public fun to_bytes<MoveValue>(v: &MoveValue): vector<u8>;
}
bit_vector.move
数组的一种结构, [bool,length] [ture,false,ture],就是会标注index位置有没有被使用
module std::bit_vector {
struct BitVector has copy, drop, store {
length: u64,
bit_field: vector<bool>,
}
}
debug.move
提供了在开发节点,人工打印调试信息
module std::debug {
native public fun print<T>(x: &T);
native public fun print_stack_trace();
}
hash.move
提供了两个常用的hash函数
module std::hash {
native public fun sha2_256(data: vector<u8>): vector<u8>;
native public fun sha3_256(data: vector<u8>): vector<u8>;
}
option.move
一种容器类,表达的是,一个东西能为空,而且用这种类型会约束你强制处理为空的情况 简单来说一个NFT的图片,允许为空,或者必须填写
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
/// This module defines the Option type and its methods to represent and handle an optional value.
module std::option {
use std::vector;
struct Option<Element> has copy, drop, store {
vec: vector<Element>
}
/// Return an empty `Option`
public fun none<Element>(): Option<Element> {
Option { vec: vector::empty() }
}
/// Return an `Option` containing `e`
public fun some<Element>(e: Element): Option<Element> {
Option { vec: vector::singleton(e) }
}
/// Return true if `t` does not hold a value
public fun is_none<Element>(t: &Option<Element>): bool {
vector::is_empty(&t.vec)
}
/// Return true if `t` holds a value
public fun is_some<Element>(t: &Option<Element>): bool {
!vector::is_empty(&t.vec)
}
}
string.move
- 字符串的UTF-8版本
- 提供了一些ascii转换的方法和定义
module std::string {
use std::ascii;
use std::vector;
use std::option::{Self, Option};
/// An invalid UTF8 encoding.
const EINVALID_UTF8: u64 = 1;
/// Index out of range.
const EINVALID_INDEX: u64 = 2;
/// A `String` holds a sequence of bytes which is guaranteed to be in utf8 format.
struct String has copy, drop, store {
bytes: vector<u8>,
}
/// Creates a new string from a sequence of bytes. Aborts if the bytes do not represent valid utf8.
public fun utf8(bytes: vector<u8>): String {
assert!(internal_check_utf8(&bytes), EINVALID_UTF8);
String{bytes}
}
/// Convert an ASCII string to a UTF8 string
public fun from_ascii(s: ascii::String): String {
String { bytes: ascii::into_bytes(s) }
}
/// Convert an UTF8 string to an ASCII string.
/// Aborts if `s` is not valid ASCII
public fun to_ascii(s: String): ascii::String {
let String { bytes } = s;
ascii::string(bytes)
}
}
type_name.move
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
/// Functionality for converting Move types into values. Use with care!
module std::type_name {
use std::ascii::{Self, String};
use std::address;
use std::vector;
/// ASCII Character code for the `:` (colon) symbol.
const ASCII_COLON: u8 = 58;
struct TypeName has copy, drop, store {
name: String
}
/// Return a value representation of the type `T`.
public native fun get<T>(): TypeName;
/// Get the String representation of `self`
public fun borrow_string(self: &TypeName): &String {
&self.name
}
/// Get Address string (Base16 encoded), first part of the TypeName.
public fun get_address(self: &TypeName): String {
// Base16 (string) representation of an address has 2 symbols per byte.
let len = address::length() * 2;
let str_bytes = ascii::as_bytes(&self.name);
let addr_bytes = vector[];
let i = 0;
// Read `len` bytes from the type name and push them to addr_bytes.
while (i < len) {
vector::push_back(
&mut addr_bytes,
*vector::borrow(str_bytes, i)
);
i = i + 1;
};
ascii::string(addr_bytes)
}
/// Get name of the module.
public fun get_module(self: &TypeName): String {
// Starts after address and a double colon: `<addr as HEX>::`
let i = address::length() * 2 + 2;
let str_bytes = ascii::as_bytes(&self.name);
let module_name = vector[];
loop {
let char = vector::borrow(str_bytes, i);
if (char != &ASCII_COLON) {
vector::push_back(&mut module_name, *char);
i = i + 1;
} else {
break
}
};
ascii::string(module_name)
}
/// Convert `self` into its inner String
public fun into_string(self: TypeName): String {
self.name
}
}
sui-framework
sui 独有的标准库,和其他链的不一样
模块名 | 大概用途 | 需要掌握程度 |
---|---|---|
address.move | 提供了一些地址和其他类型的转换 | 掌握 |
bag.move | map结构,值可以类型不一样 | 完全掌握 |
bcs.move | 在核心标准库上做了补充 | 完全掌握 |
borrow.move | 掌握 | |
clock.move | 获取链上时间 | 完全掌握 |
coin.move | 类似ERC20标准 | 完全掌握 |
display.move | NFT展现标准 | 完全掌握 |
dynamic_field.move | 动态属性 | 掌握 |
dynamic_object_field.move | 动态对象属性 | 掌握 |
event.move | 打印日志 | 完全掌握 |
hex.move | hex编码 | 完全掌握 |
linked_table.move | table的一种 | 掌握 |
math.move | 常用数学工具函数 | 完全掌握 |
object.move | 对象工具库 | 完全掌握 |
object_bag.move | map结构,值是对象类型可以不一样 | 完全掌握 |
object_table.move | map结构,值是对象类型必须一样 | 完全掌握 |
package.move | 包管理和升级 | 掌握 |
pay.move | 对Coin的快捷处理函数, | 完全掌握 |
prover.move | 用不上自行了解 | 了解 |
sui.move | SUI 的定义 | 了解 |
table.move | map结构,值类型必须一样 | 完全掌握 |
table_vec.move | 用table实现的数组 | 掌握 |
transfer.move | 转移对象所有权, | 完全掌握 |
tx_context.move | 取得当前交易钱包信息的上下文 | 完全掌握 |
types.move | 类型工具,目前只有判断OWT类型 | 完全掌握 |
vec_map.move | 底层是vec数组的map | 掌握 |
vec_set.move | 底层是vec数组的Set | 掌握 |
versioned.move | 版本管理的工具类 | 掌握 |
kiosk 目录 | NFT交易的基础工具类 | 完全掌握 |
crypto 目录 | 高阶的加密算法 | 了解 |
test.move | 测试相关工具库 | 完全掌握 |
borrow.move
- 一个简单的库,支持烫手山芋的借用机制。
- 在可编程事务中,可以在内部借用值
- 一个事务,使用它并在最后放回。“Borrow”是个烫手山芋
- 确保返回的对象没有被替换为另一个对象。
如何理解呢? 就是用确定一个对象在不同的合约之间传递到还回来的时候没有被改变id
clock.move
- 提供了一个获取链上时间的方法,Sui上链上的时间在 0x6对象实例,只有这一个唯一的对象实例
module sui::clock {
use sui::object::{Self, UID};
struct Clock has key {
id: UID,
timestamp_ms: u64,
}
public fun timestamp_ms(clock: &Clock): u64 {
clock.timestamp_ms
}
}
hex.move
base16编码 就是把二进制的数据转成16进制表示让肉眼方便阅读和简短,比如 address
linked_table.move
链表数据结构
类似于sui::table
,但值是链接在一起的,允许有序插入和删除
math.move
- 最大值,最小值,平均值,差值,指数,开平方
集合的类型如何选择?
- bag 和 table的选择
如果值类型一样就选table,如果值类型不一样就选bas
- object_table 和 table的选择
如果值确定是 object就选 object_table ,否则选 table, table范围更广泛
- object_bag 和 bag
如果值确定是 object就选 object_bag ,否则选 table, bag范围更广泛
- vec相关的和 table 和bag
大小已知而且小于1000用 vec ,大小未知 数据比较大 用 table
vec相关的集合
- 使用vec相关的集合都要非常的小心, 不能存储大量的数据, 理论上必须小于1000,而且最好不要提供让用户来自行添加数据,也就是不确定长度的,很容易产生gas不足的安全攻击