本文解析Sui Move代币核心三件套:balance(价值存储层)、coin(代币操作层)、pay(支付抽象层)。通过原理图解和代码示例,揭示三层架构设计原理。
模块 | 层级 | 功能 | 场景 |
---|---|---|---|
sui::balance |
价值存储层(底层存储) | 管理地址与代币的余额映射关系 | 余额查询、代币所有权验证 |
sui::coin |
代币操作层(基础操作) | 聚焦代币本身的生命周期管理<br>包括:代币的创建、销毁和元数据管理等 | 自定义代币发行、代币元数据维护 |
sui::pay |
支付抽象层(高级封装) | 提供代币支付的复合操作<br>包括:单个或批量代币分割、合并、转账等 | 批量转账、分账逻辑、空投 |
pay
的方法比较简单,主要是调用了coin
中的方法,balance
方法在coin
中都会被调用,故本文重点图解coin
的核心方法。
监管币原理将在单独文章中介绍,本文忽略。
sui::balance
分类 | 函数名 | 参数 | 功能描述 |
---|---|---|---|
余额操作 | zero |
无参数 | 创建数量为零的余额对象 |
value |
self: &Balance<T> |
获取余额对象中存储的数量 | |
join |
self: &mut Balance<T>, balance: Balance<T> |
合并两个余额对象 | |
split |
self: &mut Balance<T>, value: u64 |
从余额对象中分离出指定数量的子余额对象 | |
withdraw_all |
self: &mut Balance<T> |
提取所有余额,剩余余额为0 | |
destroy_zero |
balance: Balance<T> |
销毁数量为零的余额对象 | |
供应量操作 | create_supply |
_: T |
为类型T创建新的供应量 |
supply_value |
supply: &Supply<T> |
获取供应量的值 | |
increase_supply |
self: &mut Supply<T>, value: u64 |
增加供应量并创建对应数量的余额 | |
decrease_supply |
self: &mut Supply<T>, balance: Balance<T> |
销毁余额并减少供应量 | |
destroy_supply |
self: Supply<T> |
销毁供应量,阻止进一步铸造和销毁 |
sui::coin
分类 | 函数名 | 参数 | 功能描述 |
---|---|---|---|
供应量操作 | total_supply |
cap: &TreasuryCap<T> |
返回流通中的代币总数量 |
treasury_into_supply |
treasury: TreasuryCap<T> |
解包TreasuryCap获取Supply(不可逆操作) | |
supply_immut |
treasury: &TreasuryCap<T> |
获取treasury的Supply不可变引用 | |
supply_mut |
treasury: &mut TreasuryCap<T> |
获取treasury的Supply可变引用 | |
余额操作 | value |
self: &Coin<T> |
获取币的价值 |
balance |
coin: &Coin<T> |
获取币的余额不可变引用 | |
balance_mut |
coin: &mut Coin<T> |
获取币的余额可变引用 | |
from_balance |
balance: Balance<T>, ctx: &mut TxContext |
将余额包装成可转移的币 | |
into_balance |
coin: Coin<T> |
解构币包装器并保留余额 | |
take |
balance: &mut Balance<T>, value: u64, ctx: &mut TxContext |
从余额中取出指定价值的币 | |
put |
balance: &mut Balance<T>, coin: Coin<T> |
将币放入余额中 | |
代币操作 | join |
self: &mut Coin<T>, c: Coin<T> |
合并两个币 |
split |
self: &mut Coin<T>, split_amount: u64, ctx: &mut TxContext |
将币分割成两部分 | |
divide_into_n |
self: &mut Coin<T>, n: u64, ctx: &mut TxContext |
将币平均分成n-1个币 | |
zero |
ctx: &mut TxContext |
创建价值为零的币 | |
destroy_zero |
c: Coin<T> |
销毁价值为零的币 | |
mint |
cap: &mut TreasuryCap<T>, value: u64, ctx: &mut TxContext |
铸造指定价值的币 | |
mint_balance |
cap: &mut TreasuryCap<T>, value: u64 |
铸造指定价值的余额 | |
burn |
cap: &mut TreasuryCap<T>, c: Coin<T> |
销毁币并减少总供应量 | |
create_currency |
witness: T, decimals: u8, symbol: vector<u8>, name: vector<u8>, description: vector<u8>, icon_url: Option<Url>, ctx: &mut TxContext |
创建新的货币类型 | |
mint_and_transfer |
c: &mut TreasuryCap<T>, amount: u64, recipient: address, ctx: &mut TxContext |
铸造币并转移给接收者 | |
元数据操作 | update_name |
_treasury: &TreasuryCap<T>, metadata: &mut CoinMetadata<T>, name: string::String |
更新币的名称 |
update_symbol |
_treasury: &TreasuryCap<T>, metadata: &mut CoinMetadata<T>, symbol: ascii::String |
更新币的符号 | |
update_description |
_treasury: &TreasuryCap<T>, metadata: &mut CoinMetadata<T>, description: string::String |
更新币的描述 | |
update_icon_url |
_treasury: &TreasuryCap<T>, metadata: &mut CoinMetadata<T>, url: ascii::String |
更新币的图标URL | |
get_decimals |
metadata: &CoinMetadata<T> |
获取币的小数位数 | |
get_name |
metadata: &CoinMetadata<T> |
获取币的名称 | |
get_symbol |
metadata: &CoinMetadata<T> |
获取币的符号 | |
get_description |
metadata: &CoinMetadata<T> |
获取币的描述 | |
get_icon_url |
metadata: &CoinMetadata<T> |
获取币的图标URL |
后续文章装门来介绍,这里略。
分类 | 函数名 | 参数 | 功能描述 |
---|---|---|---|
创建和迁移 | create_regulated_currency_v2 |
witness: T, decimals: u8, symbol: vector<u8>, name: vector<u8>, description: vector<u8>, icon_url: Option<Url>, allow_global_pause: bool, ctx: &mut TxContext |
创建带监管功能的货币 |
migrate_regulated_currency_to_v2 |
deny_list: &mut DenyList, cap: DenyCap<T>, allow_global_pause: bool, ctx: &mut TxContext |
将监管货币迁移到v2版本 | |
黑名单操作 | deny_list_v2_add |
deny_list: &mut DenyList, _deny_cap: &mut DenyCapV2<T>, addr: address, ctx: &mut TxContext |
将地址添加到拒绝列表 |
deny_list_v2_remove |
deny_list: &mut DenyList, _deny_cap: &mut DenyCapV2<T>, addr: address, ctx: &mut TxContext |
从拒绝列表中移除地址 | |
deny_list_v2_contains_current_epoch |
deny_list: &DenyList, addr: address, ctx: &TxContext |
检查当前纪元拒绝列表是否包含地址 | |
deny_list_v2_contains_next_epoch |
deny_list: &DenyList, addr: address |
检查下一纪元拒绝列表是否包含地址 | |
deny_list_v2_enable_global_pause |
deny_list: &mut DenyList, deny_cap: &mut DenyCapV2<T>, ctx: &mut TxContext |
启用全局暂停 | |
deny_list_v2_disable_global_pause |
deny_list: &mut DenyList, deny_cap: &mut DenyCapV2<T>, ctx: &mut TxContext |
禁用全局暂停 | |
deny_list_v2_is_global_pause_enabled_current_epoch |
deny_list: &DenyList, ctx: &TxContext |
检查当前纪元是否启用全局暂停 | |
deny_list_v2_is_global_pause_enabled_next_epoch |
deny_list: &DenyList |
检查下一纪元是否启用全局暂停 |
sui::pay
分类 | 函数名 | 参数 | 功能描述 |
---|---|---|---|
转移 | keep |
c: Coin<T>, ctx: &TxContext |
将币转移给当前交易的发送者 |
分割 | split |
coin: &mut Coin<T>, split_amount: u64, ctx: &mut TxContext |
将币分割成两部分,指定分割金额 |
split_vec |
self: &mut Coin<T>, split_amounts: vector<u64>, ctx: &mut TxContext |
将币分割成多个币,每个币的余额由向量指定 | |
split_and_transfer |
c: &mut Coin<T>, amount: u64, recipient: address, ctx: &mut TxContext |
分割指定数量的币并发送给接收者 | |
divide_and_keep |
self: &mut Coin<T>, n: u64, ctx: &mut TxContext |
将币平均分成n-1个币,余数保留 | |
合并 | join |
self: &mut Coin<T>, coin: Coin<T> |
将两个币合并(已弃用) |
join_vec |
self: &mut Coin<T>, coins: vector<Coin<T>> |
将向量中的所有币合并到主币中 | |
join_vec_and_transfer |
coins: vector<Coin<T>>, receiver: address |
将向量中的币合并后转移给接收者 |
module cookbook::aig_token {
use std::string::{Self, String};
use std::ascii;
use sui::coin::{Self, TreasuryCap};
use sui::balance::{Self, Balance};
use sui::url::{Self, Url};
use sui::event;
public struct EventMint has copy, drop {
sender: address,
amount: u64,
coin_left: u64
}
public struct EventAirdrop has copy, drop {
method: String,
sender: address,
amount: u64
}
public struct EventCoinMeta has copy, drop {
decimals: u8,
symbol: ascii::String,
name: String,
description: String,
icon_url: Option<Url>,
}
public struct EventTotalSupply has copy, drop {
total_supply: u64
}
public struct Vault has key {
id: UID,
balance: Balance<AIG_TOKEN>,
}
public struct AIG_TOKEN has drop {}
fun init(
witness: AIG_TOKEN,
ctx: &mut TxContext
) {
let decimals = 3;
let symbol = b"AIG";
let name = b"AIG Token";
let description = b"AIG Token is a token that is used to incentivize the community to achieve the goals of the AI Goal.";
let url = url::new_unsafe_from_bytes(b"https://ai-goal.vercel.app/");
let (treasury_cap, metadata) = coin::create_currency<AIG_TOKEN>(
witness,
decimals,
symbol,
name,
description,
option::some(url),
ctx
);
event::emit(
EventCoinMeta {
decimals: coin::get_decimals(&metadata),
symbol: coin::get_symbol(&metadata),
name: coin::get_name(&metadata),
description: coin::get_description(&metadata),
icon_url: option::some(url),
}
);
transfer::public_freeze_object(metadata);
transfer::public_transfer(treasury_cap, ctx.sender());
transfer::share_object(
Vault {
id: object::new(ctx),
balance: balance::zero(),
}
);
}
public(package) fun airdrop(
vault: &mut Vault,
amount: u64,
method: vector<u8>,
ctx: &mut TxContext
) {
let sender = ctx.sender();
let mut balance_drop = balance::split(&mut vault.balance, amount);
let coin_drop = coin::take(&mut balance_drop, amount, ctx);
transfer::public_transfer(coin_drop, sender);
balance::destroy_zero(balance_drop);
event::emit(
EventAirdrop {
method: string::utf8(method),
sender,
amount,
}
);
}
public fun mint_balance(
treasury_cap: &mut TreasuryCap<AIG_TOKEN>,
vault: &mut Vault,
amount: u64,
ctx: &mut TxContext
) {
let balance_minted = coin::mint_balance(treasury_cap, amount);
balance::join(&mut vault.balance, balance_minted);
event::emit(
EventMint {
sender: ctx.sender(),
amount: amount,
coin_left: balance::value(&vault.balance)
}
);
}
#[allow(lint(self_transfer))]
public fun mint_coin(
treasury_cap: &mut TreasuryCap<AIG_TOKEN>,
amount: u64,
ctx: &mut TxContext
) {
let coin_minted = coin::mint(treasury_cap, amount, ctx);
transfer::public_transfer(coin_minted, ctx.sender());
coin::mint_and_transfer(
treasury_cap,
amount,
ctx.sender(),
ctx
);
event::emit(
EventTotalSupply {
total_supply: coin::total_supply(treasury_cap)
}
)
}
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!