Rust区块链NFT管理库pallet-uniques的使用,Substrate框架中创建和管理独特数字资产的插件库
Uniques Module
一个简单、安全的模块,用于处理非同质化资产。
概述
Uniques模块提供了非同质化代币(NFT)的管理功能,包括:
- 集合创建
- 代币铸造
- 代币转移
- 代币交易方法
- 属性管理
- 代币销毁
要在你的运行时中使用它,你需要实现uniques::Config
。
支持的调度函数记录在uniques::Call
枚举中。
术语
- 集合创建:创建新集合
- 代币铸造:在集合中创建新代币的行为
- 代币转移:将代币从一个账户发送到另一个账户的行为
- 代币销毁:销毁代币的行为
- 非同质化代币(NFT):每个单位具有独特特征的代币。这样的代币只有一个实例存在,并且只有一个拥有账户。
目标
Substrate中的Uniques模块旨在实现以下功能:
- 允许账户无许可地创建NFT集合
- 允许指定(许可)账户在集合中铸造和销毁独特代币
- 无许可地在账户之间转移代币
- 允许指定(许可)账户冻结和解冻集合中的独特代币或整个集合
- 允许代币所有者将转移代币的能力委托给指定的第三方
接口
无许可调度函数
create
:通过放置押金创建新集合transfer
:将代币转移给新所有者redeposit
:更新代币的押金金额,可能释放资金approve_transfer
:指定可以授权转移的委托cancel_approval
:撤销之前approve_transfer
的效果
许可调度函数
destroy
:销毁集合mint
:在集合中铸造新代币burn
:销毁集合中的代币freeze
:防止单个代币被转移thaw
:撤销之前freeze
的效果freeze_collection
:防止集合中的所有代币被转移thaw_collection
:撤销之前freeze_collection
的效果transfer_ownership
:更改集合的所有者,转移所有相关押金set_team
:更改集合的许可账户
元数据(许可)调度函数
set_attribute
:设置代币或集合的属性clear_attribute
:移除代币或集合的属性set_metadata
:设置代币的通用元数据clear_metadata
:移除代币的通用元数据set_collection_metadata
:设置集合的通用元数据clear_collection_metadata
:移除集合的通用元数据
强制(即治理)调度函数
force_create
:创建新集合force_asset_status
:更改集合的基本特征
相关模块
System
Support
Assets
许可证:Apache-2.0
完整示例代码
以下是内容中提供的示例代码:
// 在runtime/src/lib.rs中添加pallet-uniques
use frame_support::traits::{Currency, ReservableCurrency};
use sp_runtime::traits::StaticLookup;
// 配置pallet-uniques
impl pallet_uniques::Config for Runtime {
type Event = Event;
type CollectionId = u32;
type ItemId = u32;
type Currency = Balances; // 使用Balances作为货币类型
type ForceOrigin = frame_system::EnsureRoot<AccountId>;
type CreateOrigin = frame_system::EnsureSigned<AccountId>;
type Locker = ();
type WeightInfo = ();
}
// 示例调用代码
// 创建集合
let collection_id = 1;
let call = pallet_uniques::Call::<Runtime>::create {
collection: collection_id,
admin: account_id,
};
let origin = Origin::signed(account_id);
call.dispatch(origin)?;
// 铸造NFT
let item_id = 1;
let call = pallet_uniques::Call::<Runtime>::mint {
collection: collection_id,
item: item_id,
owner: recipient_account_id,
};
let origin = Origin::signed(account_id); // 需要是集合管理员
call.dispatch(origin)?;
// 转移NFT
let call = pallet_uniques::Call::<Runtime>::transfer {
collection: collection_id,
item: item_id,
dest: new_owner_account_id,
};
let origin = Origin::signed(current_owner_account_id);
call.dispatch(origin)?;
// 设置元数据
let metadata = b"Unique Artwork #1".to_vec();
let call = pallet_uniques::Call::<Runtime>::set_metadata {
collection: collection_id,
item: item_id,
data: metadata.clone(),
};
let origin = Origin::signed(account_id); // 需要是集合管理员
call.dispatch(origin)?;
安装命令:
cargo add pallet-uniques
或者在Cargo.toml中添加:
pallet-uniques = "41.0.0"
扩展完整示例
以下是一个更完整的NFT管理示例:
// runtime/src/lib.rs
use frame_support::{parameter_types, traits::Everything};
use sp_runtime::traits::ConstU32;
parameter_types! {
pub const CollectionDeposit: Balance = 100 * UNITS; // 集合创建押金
pub const ItemDeposit: Balance = 10 * UNITS; // 代币创建押金
pub const MetadataDepositBase: Balance = 10 * UNITS; // 元数据基础押金
pub const AttributeDepositBase: Balance = 10 * UNITS;// 属性基础押金
}
impl pallet_uniques::Config for Runtime {
type Event = Event;
type CollectionId = u32; // 集合ID类型
type ItemId = u32; // 代币ID类型
type Currency = Balances; // 使用的货币类型
type ForceOrigin = frame_system::EnsureRoot<AccountId>;
type CreateOrigin = frame_system::EnsureSigned<AccountId>;
type Locker = ();
type CollectionDeposit = CollectionDeposit;
type ItemDeposit = ItemDeposit;
type MetadataDepositBase = MetadataDepositBase;
type AttributeDepositBase = AttributeDepositBase;
type DepositPerByte = ConstU32<1>; // 每字节押金
type StringLimit = ConstU32<256>; // 字符串长度限制
type KeyLimit = ConstU32<64>; // 键长度限制
type ValueLimit = ConstU32<64>; // 值长度限制
type WeightInfo = pallet_uniques::weights::SubstrateWeight<Runtime>;
type RemoveItemsLimit = ConstU32<1000>;
type CreateOrigin = EnsureSigned<AccountId>;
type Features = PalletFeatures;
}
// 创建一个完整的NFT生命周期示例
fn nft_lifecycle_example() -> DispatchResult {
let alice = 1;
let bob = 2;
let collection_id = 1;
let item_id = 1;
// 1. 创建集合
Uniques::create(
RuntimeOrigin::signed(alice),
collection_id,
alice // 设置alice为集合管理员
)?;
// 2. 设置集合元数据
Uniques::set_collection_metadata(
RuntimeOrigin::signed(alice),
collection_id,
b"My Awesome Collection".to_vec(),
false
)?;
// 3. 铸造NFT
Uniques::mint(
RuntimeOrigin::signed(alice),
collection_id,
item_id,
alice // 初始拥有者为alice
)?;
// 4. 设置NFT元数据
Uniques::set_metadata(
RuntimeOrigin::signed(alice),
collection_id,
item_id,
b"Unique Artwork #1".to_vec(),
false
)?;
// 5. 转移NFT给bob
Uniques::transfer(
RuntimeOrigin::signed(alice),
collection_id,
item_id,
bob
)?;
// 6. bob授权alice可以转移此NFT
Uniques::approve_transfer(
RuntimeOrigin::signed(bob),
collection_id,
item_id,
alice
)?;
// 7. alice使用授权转移NFT给自己
Uniques::transfer(
RuntimeOrigin::signed(alice),
collection_id,
item_id,
alice
)?;
// 8. 销毁NFT
Uniques::burn(
RuntimeOrigin::signed(alice),
collection_id,
item_id
)?;
// 9. 销毁集合
Uniques::destroy(
RuntimeOrigin::signed(alice),
collection_id,
DestroyWitness {
items: 0,
item_metadatas: 1,
attributes: 0
}
)?;
Ok(())
}
这个完整示例展示了NFT的完整生命周期:
- 创建集合
- 设置集合元数据
- 铸造NFT
- 设置NFT元数据
- 转移NFT
- 授权转移
- 使用授权转移
- 销毁NFT
- 销毁集合
1 回复
Rust区块链NFT管理库pallet-uniques的使用指南
完整示例代码
下面是一个完整的pallet-uniques使用示例,展示了如何创建NFT集合、铸造NFT、设置元数据和转移所有权:
// runtime/src/lib.rs
// 1. 在runtime中集成pallet-uniques
impl pallet_uniques::Config for Runtime {
type Event = Event;
type CollectionId = u32;
type ItemId = u32;
type Currency = Balances;
type CreateOrigin = frame_system::EnsureRoot<AccountId>;
type ForceOrigin = frame_system::EnsureRoot<AccountId>;
type Locker = ();
type WeightInfo = ();
}
construct_runtime!(
pub enum Runtime {
// ... 其他pallet
Uniques: pallet_uniques::{Pallet, Call, Storage, Event<T>},
}
);
// 示例代码 - 在链上操作NFT
fn main() {
// 初始化Substrate客户端等代码...
// 2. 创建NFT集合
let collection_id = 1;
let admin = alice_account_id();
let create_call = pallet_uniques::Call::create {
collection: collection_id,
admin: admin.clone(),
};
submit_extrinsic(create_call);
// 3. 在集合中创建NFT
let item_id = 1;
let owner = bob_account_id();
let mint_call = pallet_uniques::Call::mint {
collection: collection_id,
item: item_id,
owner: owner.clone(),
};
submit_extrinsic(mint_call);
// 4. 设置NFT元数据
let metadata = b"https://example.com/nft/1.json".to_vec();
let metadata_call = pallet_uniques::Call::set_metadata {
collection: collection_id,
item: item_id,
data: metadata,
is_frozen: false,
};
submit_extrinsic(metadata_call);
// 5. 转移NFT所有权
let new_owner = charlie_account_id();
let transfer_call = pallet_uniques::Call::transfer {
collection: collection_id,
item: item_id,
dest: new_owner,
};
submit_extrinsic(transfer_call);
// 高级功能示例
// 1. 批量创建NFT
for i in 2..=10 {
let mint_call = pallet_uniques::Call::mint {
collection: collection_id,
item: i,
owner: owner.clone(),
};
submit_extrinsic(mint_call);
}
// 2. 设置集合属性
let attributes = b"{\"description\":\"Premium Art Collection\"}".to_vec();
let collection_metadata_call = pallet_uniques::Call::set_collection_metadata {
collection: collection_id,
data: attributes,
is_frozen: false,
};
submit_extrinsic(collection_metadata_call);
// 3. 冻结NFT
let freeze_call = pallet_uniques::Call::freeze {
collection: collection_id,
item: item_id,
};
submit_extrinsic(freeze_call);
}
// 辅助函数 - 提交交易到链上
fn submit_extrinsic(call: pallet_uniques::Call<Runtime>) {
// 实际实现会使用Substrate客户端API提交交易
unimplemented!()
}
// 辅助函数 - 查询NFT信息
fn query_nft_info(collection_id: u32, item_id: u32) {
// 1. 查询集合所有者
let collection_owner = Uniques::collection_owner(collection_id);
println!("Collection owner: {:?}", collection_owner);
// 2. 查询NFT所有者
let item_owner = Uniques::owner(collection_id, item_id);
println!("NFT owner: {:?}", item_owner);
// 3. 查询NFT元数据
let item_metadata = Uniques::item_metadata(collection_id, item_id);
println!("NFT metadata: {:?}", item_metadata);
// 4. 查询集合元数据
let collection_metadata = Uniques::collection_metadata(collection_id);
println!("Collection metadata: {:?}", collection_metadata);
}
代码说明
- runtime集成:首先在Substrate runtime中配置和集成pallet-uniques
- NFT集合创建:使用
create
方法创建新的NFT集合 - NFT铸造:使用
mint
方法在集合中创建单个NFT - 元数据设置:使用
set_metadata
为NFT设置链上元数据 - 所有权转移:使用
transfer
方法转移NFT所有权
高级功能实现
- 批量操作:通过循环批量创建多个NFT
- 集合元数据:为整个集合设置描述性元数据
- NFT冻结:冻结NFT防止进一步修改
查询功能
代码中包含了查询NFT信息的示例函数,可以查询:
- 集合所有者
- NFT当前所有者
- NFT元数据
- 集合元数据
注意事项
- 实际使用时需要替换示例中的账户ID为真实账户
- 提交交易需要完整的Substrate客户端实现
- 生产环境应考虑错误处理和交易费用
- 元数据大小应符合链上存储限制
这个完整示例演示了pallet-uniques从集成到使用的完整流程,可以作为开发NFT功能的起点。