Kiosk 标准 - 交易NFTs
NFT市场简介
NFT(非同质化代币)市场是NFT生态系统中的重要枢纽,能够买卖和交易独特的数字资产。它们的重要性体现在以下几个关键方面:
- 可访问性:NFT市场使人们能够轻松进入数字收藏品和独特内容的世界。
- 可发现性:这些平台为用户提供了工具,使他们能够找到符合自己兴趣的NFT,促进探索和连接。
- 信任和安全:区块链技术确保了透明性、真实性和安全的交易。
- 二级销售:NFT市场促进转售,使创作者能够赚取版税,投资者也有可能获利。
- 社区和互动:它们围绕NFT建立社区,促进互动和协作。
- 创作者的货币化:艺术家和创作者可以直接在这些平台上将作品变现。
Kiosk - Sui的市场标准
Sui Kiosk是一个对象市场的标准,支持上市和销售。它作为Sui框架的一部分,部署在0x2
,拥有许多强大的功能,可以很好地支持NFT交易。
Kiosk模块可以在这里找到,提供以下功能(也适用于非NFT对象):
- 创建和管理新的NFT市场(一个kiosk)
- 转移NFT市场的所有权
- 上市和下架NFT
- 购买上市的NFT
- TransferPolicy允许NFT类型所有者(创作者)为其NFT的每次交易定义自定义规则,包括版税执行(我们在之前的课程中看到的OriginByte)和白名单
Kiosk目前仅支持使用SUI代币作为支付方式,但开发者可以部署自己的Kiosk版本,以支持其他代币。
在Kiosk上交易
首先需要创建一个kiosk:
public struct KioskManagement has key {
id: UID,
owner_cap: KioskOwnerCap,
}
public fun create_kiosk(ctx: &mut TxContext) {
let (kiosk, owner_cap) = kiosk::new(ctx);
transfer::public_share_object(kiosk);
let kiosk_management = KioskManagement {
id: object::new(ctx),
owner_cap,
};
transfer::public_share_object(kiosk_management);
}
在上述示例中,我们调用了 kiosk::new
来创建 kiosk。由于它返回了两个都不可删除的对象,
我们需要将它们共享或转移。如果开发者选择转移并保留这些对象,那么这些 kiosks 可以被视为“个人 kiosks”,
因为所有列表和购买都需要对 kiosk 和/或所有者权限的可变访问,而这些只有所有者拥有。
在上述示例中,我们将 kiosk 对象设为共享,并将所有者权限添加到共享的 KioskManagement
对象中。
这将使 kiosk 无需权限——任何人都可以在其上进行列表,前提是遵守我们在列表函数中设定的任何规则:
public fun list_on_kiosk<T: key + store>(
kiosk: &mut Kiosk,
kiosk_management: &KioskManagement,
nft: T,
) {
// 想对列出的NFT进行的任何验证
kiosk::place(kiosk, &kiosk_management.owner_cap, nft);
// 跟踪列出者
}
kiosk::place
需要一个对 KioskOwnerCap
对象的引用,可以从共享的 kiosk_management
对象中获取。
用户必须调用我们的 list_on_kiosk
函数,而不能直接调用 kiosk::place
,因为他们无法直接访问 KioskManagement
中的所有者权限对象。
这里还有一个注意事项是,NFT要被列出售,其类型必须具有 store
能力。
卖家也可以下架NFT。需要确保调用 delist
的人是最初创建该列表的人。这可以通过具有动态字段的共享对象来跟踪。
public fun delist<T: key + store>(
kiosk: &mut Kiosk,
kiosk_management: &KioskManagement,
nft_id: ID,
) {
let sender = tx_context::sender(ctx);
// 验证发送者是否与创建列表的人相同。
let nft = kiosk::take<T>(kiosk, &kiosk_management.owner_cap, nft_id);
transfer::public_transfer(nft, sender);
}
由于 kiosk 是一个共享对象,任何人都可以直接调用 sui::kiosk::purchase
从列表中购买一个 NFT:
/// 进行交易:支付物品的所有者并请求转移到 `target` kiosk(以防止物品被批准方拿走)。
/// 收到的 `TransferRequest` 需要由 T 的发布者处理,如果他们有允许交易的方法实现,可以请求他们的批准(通过调用某个函数),以便最终完成交易。
public fun purchase<T: key + store>(
self: &mut Kiosk, id: ID, payment: Coin<SUI>
): (T, TransferRequest<T>) {
let price = df::remove<Listing, u64>(&mut self.id, Listing { id, is_exclusive: false });
let inner = dof::remove<Item, T>(&mut self.id, Item { id });
self.item_count = self.item_count - 1;
assert!(price == coin::value(&payment), EIncorrectAmount);
df::remove_if_exists<Lock, bool>(&mut self.id, Lock { id });
coin::put(&mut self.profits, payment);
event::emit(ItemPurchased<T> { kiosk: object::id(self), id, price });
(inner, transfer_policy::new_request(id, price, object::id(self)))
}
请注意,尽管这会返回购买的 NFT,但它也会返回一个不能丢弃的 TransferRequest,该请求需要在交易结束前“验证”。 我们将在下一课中讨论有关 TransferPolicy 的更多内容。