图解Sui Move标准库——代币核心三件套(balance、coin、pay)

  • rzexin
  • 发布于 3小时前
  • 阅读 33

本文解析Sui Move代币核心三件套:balance(价值存储层)、coin(代币操作层)、pay(支付抽象层)。通过原理图解和代码示例,揭示三层架构设计原理。

图解Sui Move标准库——代币核心三件套(balance、coin、pay)

1 模块说明

模块 层级 功能 场景
sui::balance 价值存储层(底层存储) 管理地址与代币的余额映射关系 余额查询、代币所有权验证
sui::coin 代币操作层(基础操作) 聚焦代币本身的生命周期管理<br>包括:代币的创建、销毁和元数据管理等 自定义代币发行、代币元数据维护
sui::pay 支付抽象层(高级封装) 提供代币支付的复合操作<br>包括:单个或批量代币分割、合并、转账等 批量转账、分账逻辑、空投

2 源码路径

3 方法图解

pay的方法比较简单,主要是调用了coin中的方法,balance方法在coin中都会被调用,故本文重点图解coin的核心方法。

监管币原理将在单独文章中介绍,本文忽略。

Clipboard_Screenshot_1750951772.png

4 方法说明

4.1 sui::balance

分类 函数名 参数 功能描述
余额操作 zero 无参数 创建数量为零的余额对象
value self: &Balance&lt;T> 获取余额对象中存储的数量
join self: &mut Balance&lt;T>, balance: Balance&lt;T> 合并两个余额对象
split self: &mut Balance&lt;T>, value: u64 从余额对象中分离出指定数量的子余额对象
withdraw_all self: &mut Balance&lt;T> 提取所有余额,剩余余额为0
destroy_zero balance: Balance&lt;T> 销毁数量为零的余额对象
供应量操作 create_supply _: T 为类型T创建新的供应量
supply_value supply: &Supply&lt;T> 获取供应量的值
increase_supply self: &mut Supply&lt;T>, value: u64 增加供应量并创建对应数量的余额
decrease_supply self: &mut Supply&lt;T>, balance: Balance&lt;T> 销毁余额并减少供应量
destroy_supply self: Supply&lt;T> 销毁供应量,阻止进一步铸造和销毁

4.2 sui::coin

(1)普通代币

分类 函数名 参数 功能描述
供应量操作 total_supply cap: &TreasuryCap&lt;T> 返回流通中的代币总数量
treasury_into_supply treasury: TreasuryCap&lt;T> 解包TreasuryCap获取Supply(不可逆操作)
supply_immut treasury: &TreasuryCap&lt;T> 获取treasury的Supply不可变引用
supply_mut treasury: &mut TreasuryCap&lt;T> 获取treasury的Supply可变引用
余额操作 value self: &Coin&lt;T> 获取币的价值
balance coin: &Coin&lt;T> 获取币的余额不可变引用
balance_mut coin: &mut Coin&lt;T> 获取币的余额可变引用
from_balance balance: Balance&lt;T>, ctx: &mut TxContext 将余额包装成可转移的币
into_balance coin: Coin&lt;T> 解构币包装器并保留余额
take balance: &mut Balance&lt;T>, value: u64, ctx: &mut TxContext 从余额中取出指定价值的币
put balance: &mut Balance&lt;T>, coin: Coin&lt;T> 将币放入余额中
代币操作 join self: &mut Coin&lt;T>, c: Coin&lt;T> 合并两个币
split self: &mut Coin&lt;T>, split_amount: u64, ctx: &mut TxContext 将币分割成两部分
divide_into_n self: &mut Coin&lt;T>, n: u64, ctx: &mut TxContext 将币平均分成n-1个币
zero ctx: &mut TxContext 创建价值为零的币
destroy_zero c: Coin&lt;T> 销毁价值为零的币
mint cap: &mut TreasuryCap&lt;T>, value: u64, ctx: &mut TxContext 铸造指定价值的币
mint_balance cap: &mut TreasuryCap&lt;T>, value: u64 铸造指定价值的余额
burn cap: &mut TreasuryCap&lt;T>, c: Coin&lt;T> 销毁币并减少总供应量
create_currency witness: T, decimals: u8, symbol: vector&lt;u8>, name: vector&lt;u8>, description: vector&lt;u8>, icon_url: Option&lt;Url>, ctx: &mut TxContext 创建新的货币类型
mint_and_transfer c: &mut TreasuryCap&lt;T>, amount: u64, recipient: address, ctx: &mut TxContext 铸造币并转移给接收者
元数据操作 update_name _treasury: &TreasuryCap&lt;T>, metadata: &mut CoinMetadata&lt;T>, name: string::String 更新币的名称
update_symbol _treasury: &TreasuryCap&lt;T>, metadata: &mut CoinMetadata&lt;T>, symbol: ascii::String 更新币的符号
update_description _treasury: &TreasuryCap&lt;T>, metadata: &mut CoinMetadata&lt;T>, description: string::String 更新币的描述
update_icon_url _treasury: &TreasuryCap&lt;T>, metadata: &mut CoinMetadata&lt;T>, url: ascii::String 更新币的图标URL
get_decimals metadata: &CoinMetadata&lt;T> 获取币的小数位数
get_name metadata: &CoinMetadata&lt;T> 获取币的名称
get_symbol metadata: &CoinMetadata&lt;T> 获取币的符号
get_description metadata: &CoinMetadata&lt;T> 获取币的描述
get_icon_url metadata: &CoinMetadata&lt;T> 获取币的图标URL

(2)监管代币

后续文章装门来介绍,这里略。

分类 函数名 参数 功能描述
创建和迁移 create_regulated_currency_v2 witness: T, decimals: u8, symbol: vector&lt;u8>, name: vector&lt;u8>, description: vector&lt;u8>, icon_url: Option&lt;Url>, allow_global_pause: bool, ctx: &mut TxContext 创建带监管功能的货币
migrate_regulated_currency_to_v2 deny_list: &mut DenyList, cap: DenyCap&lt;T>, allow_global_pause: bool, ctx: &mut TxContext 将监管货币迁移到v2版本
黑名单操作 deny_list_v2_add deny_list: &mut DenyList, _deny_cap: &mut DenyCapV2&lt;T>, addr: address, ctx: &mut TxContext 将地址添加到拒绝列表
deny_list_v2_remove deny_list: &mut DenyList, _deny_cap: &mut DenyCapV2&lt;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&lt;T>, ctx: &mut TxContext 启用全局暂停
deny_list_v2_disable_global_pause deny_list: &mut DenyList, deny_cap: &mut DenyCapV2&lt;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 检查下一纪元是否启用全局暂停

4.3 sui::pay

分类 函数名 参数 功能描述
转移 keep c: Coin&lt;T>, ctx: &TxContext 将币转移给当前交易的发送者
分割 split coin: &mut Coin&lt;T>, split_amount: u64, ctx: &mut TxContext 将币分割成两部分,指定分割金额
split_vec self: &mut Coin&lt;T>, split_amounts: vector&lt;u64>, ctx: &mut TxContext 将币分割成多个币,每个币的余额由向量指定
split_and_transfer c: &mut Coin&lt;T>, amount: u64, recipient: address, ctx: &mut TxContext 分割指定数量的币并发送给接收者
divide_and_keep self: &mut Coin&lt;T>, n: u64, ctx: &mut TxContext 将币平均分成n-1个币,余数保留
合并 join self: &mut Coin&lt;T>, coin: Coin&lt;T> 将两个币合并(已弃用)
join_vec self: &mut Coin&lt;T>, coins: vector&lt;Coin&lt;T>> 将向量中的所有币合并到主币中
join_vec_and_transfer coins: vector&lt;Coin&lt;T>>, receiver: address 将向量中的币合并后转移给接收者

5 代码示例

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&lt;Url>,
    }

    public struct EventTotalSupply has copy, drop {
        total_supply: u64
    }

    public struct Vault has key {
        id: UID,
        balance: Balance&lt;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&lt;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&lt;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&lt;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&lt;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)
            }
        )
    }
}
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
rzexin
rzexin
0x6Fa5...8165
江湖只有他的大名,没有他的介绍。