P(A)是一个不错的NFT项目。NFT是目前非常热门的一个赛道,而Move在NFT领域有很大的优势。P(A)使用Move实现,可以说很好地结合了Move的特性。
P(A)是首届Move黑客松NFT赛道的一个项目,由MemeX团队设计的。本届黑客松有多个NFT项目,从功能完整性、项目完成度、创意性、展示度等多个方面综合考虑,P(A)是一个不错的NFT项目。NFT是目前非常热门的一个赛道,而Move在NFT领域有很大的优势。P(A)使用Move实现,可以说很好地结合了Move的特性。
这里我们通过对合约源码进行分析,来学习一下如何使用Move实现一个简单的NFT。我们先来看 一 下P(A)项目的整体设计图:
从上面的图中可以看出一些重要的信息:
从逻辑上来说,简单直接,合约Owner通过init_market初始化一个Market,普通用户可以mint来购买NFT。接下来我们深入分析一下源码。
P(A)包含多个数据结构:Art、NFT、UniqList、NFT_INFO、MARKET,之间的关系如下图所示:
1. Art
struct Art has store, copy, drop {
prob_a: u8,
prob_b: u8,
param_1: vector<u64>,
param_2: vector<u64>
}
这是NFT渲染需要用到的元数据信息,没有key的ability,意味着能拷贝、能丢弃、能存储。这里建议NFT的元数据不能拷贝和丢弃。
struct NFT has store {
id: u8,// 唯一标识
next_nft_id: u8,// 通过链表的形式把NFT标识串起来,方便追踪
next_nft_owner: address,// 通过链表的形式把address串起来,方便追踪
data: Art,// NFT元数据
sell_status: bool,// 状态
price: u128,// 价格
}
这是NFT具体数据,只有存储的能力,意味着不能拷贝和丢弃。非常方便的发挥了Move的优势,利用虚拟机保障NFT的完整性、唯一性等等。
struct UniqList has key {
data: vector<NFT> // 存储用户拥有的NFT列表
}
UniqList虽然使用了数组,但是这里不用担心大数组的问题,因为每个用户的NFT是存储在自己的账号下的,并不会影响到所有的用户。
struct NFT_INFO has store, drop {
id: u8,// NFT标识
next_nft_id: u8,
next_nft_owner: address,
data: Art,
price: u128,// 价格
}
这是NFT生成之后的信息,用于展示。有NFT的id了,Art在这里有点冗余。
struct MARKET has key {
head: address,
cur_num: u8,// 当前数量
min_price: u128,// 最小价格
market_nft_info: vector<NFT_INFO>// 所有的NFT信息
}
这里存放了所有的NFT信息。看上去有大数组的问题,因为P(A)限制了最多只能生成100个NFT,所以这里也不用担心。但是,类似这种列表展示数据,建议通过Event的方式,在链下聚合。
Function定义
public(script) fun init_market(account: signer)
这是合约初始化入口,在合约的Owner账号下初始化一个Market。函数使用了public(script)可见性。
public(script) fun mint(account: signer, amount: u128) acquires UniqList, MARKET
这是用户购买NFT的入口,也是public(script) 可见性。acquires表示使用到了当前Module定义的UniqList和MARKET两个数据结构。
P(A)项目从合约实现细节来说,代码相对比较简洁,充分利用了Move在NFT场景的优势,省去了很多不必要的安全检查,比如防止NFT丢失等等。我们来总结一下合约代码实现上的优缺点。
总的来说,P(A)巧妙地应用了Move的优势,在NFT的方向上做了很好的尝试,这里查看完整代码。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!