消费
由于 Token
类型没有 store
能力,因此无法将其“存储”在另一个对象中。因此,不可能采用类似于 Coin 的方式进行消费 - 接受 Token
作为支付的应用程序将无法将其添加到其余额中。为了解决这个问题,Token
有一个 "spend" 方法,允许在一个应用程序中 "消费" 它,然后将其作为 spent_balance
交付给 TokenPolicy 或者立即使用 TreasuryCap
进行销毁。
消费操作
通过调用 spend
方法,可以消费 Token
。它接受以下参数:
// module sui::token
public fun spend<T>(token: Token<T>, ctx: &mut TxContext): ActionRequest<T>;
从签名中可以看出,Token
对象被消耗。其余额将成为 ActionRequest 中的 spent_balance
。
消费的 Token
“消费” 操作的 ActionRequest
包含被消费的 Token
的 Balance
,可以通过 使用 TreasuryCap
确认 或者 交付给 TokenPolicy。在第一种情况下,余额将直接在 TreasuryCap
中 "销毁",在第二种情况下,它将被交付到 TokenPolicy 的 "spent_balance"。
已消费的余额无法以任何方式使用,也不可能 "提取" 它。唯一可用的操作是 "刷新" - 通过提供 TreasuryCap
来销毁 spent_balance
。
限制消费操作
通常,spend
操作应该至少有一个分配给它的 "Rule",以防止无谓的消费,并且在接受 Token 的应用程序中授权 spend
的推荐方式是在执行 spend
的函数中直接进行 "戳记"。例如:
/// Rule-like witness to stamp the ActionRequest
struct GiftShop has drop {}
/// Spend the token and return a Gift + ActionRequest
public fun buy_gift(
token: Token<CREDITS>,
ctx: &mut TxContext
): (Gift, ActionRequest<CREDITS>) {
// token is spent
let action_request = token::spend(token, ctx);
// stamp the ActionRequest as performed by GiftShop
token::add_approval(GiftShop {}, &mut action_request, ctx);
// return already "stamped" ActionRequest
(Gift { ... }, action_request)
}