rmrk-team / rmrk-substrate

[WIP] RMRK Substrate pallets

Home Page:https://rmrk.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

NFT info struct should contain a link to an equipper

mrshiposha opened this issue · comments

According to the spec of the equip interaction the NFT info struct should contain a field equipped filled with base/slot info.

Currently, the NFT info contains only a boolean flag equipped.

pub equipped: bool,

It's redundant info in the storage. However we can provide a RPC or SubQuery indexer to populate the field better

Hmm... I still can't understand how to extract such information from the chain...

The Equippings storage contains only a link to a resource id. The problem is that the resource id is not unique.
So we can have different equipped NFTs with the same base/slot and resource id (remember, resource ids are bounded to NFT, so we can the same resource ids on different NFTs).

How can we determine which NFT is equipped? All we can see is what child NFTs are equipped with the corresponding resource id.

And what if an equipped NFT gets transferred to another user/token?

Interesting...

So first, on you last point, PR #189 should prevent sending an equipped item.

On the "How can we determine which NFT is equipped", that's a good point...since as you say, resources are bounded to the NFT...

So ALICE could have two NFTs, both equippable to the same slot, and we'd never be able to tell which is equipped...

Maybe we need to change this:

#[pallet::storage]
#[pallet::getter(fn equippings)]
/// Stores Equippings info ((equipper, base, slot), equipped_resource)
pub type Equippings<T: Config> = StorageNMap<
_,
(
NMapKey<Blake2_128Concat, (CollectionId, NftId)>, // Equipper
NMapKey<Blake2_128Concat, BaseId>, // Base ID
NMapKey<Blake2_128Concat, SlotId>, // Slot ID
),
ResourceId, // Equipped Resource
OptionQuery,
>;

to this:

 #[pallet::getter(fn equippings)] 
 /// Stores Equippings info ((equipper, base, slot), equipped_resource) 
 pub type Equippings<T: Config> = StorageNMap< 
 	_, 
 	( 
 		NMapKey<Blake2_128Concat, (CollectionId, NftId)>, // Equipper 
 		NMapKey<Blake2_128Concat, BaseId>,                // Base ID 
 		NMapKey<Blake2_128Concat, SlotId>,                // Slot ID 
 	), 
 	(CollectionId, NftId, ResourceId), // Equipped NFT and Resource 
 	OptionQuery, 
 >; 

Thoughts? Or would this be better:

 #[pallet::getter(fn equippings)] 
 /// Stores Equippings info ((equipper, base, slot), equipped_resource) 
 pub type Equippings<T: Config> = StorageNMap< 
 	_, 
 	( 
 		NMapKey<Blake2_128Concat, (CollectionId, NftId)>, // Equipper 
 		NMapKey<Blake2_128Concat, BaseId>,                // Base ID 
 		NMapKey<Blake2_128Concat, SlotId>,                // Slot ID 
 		NMapKey<Blake2_128Concat, (CollectionId, NftId)>, // Item 
 	), 
 	ResourceId, // Resource 
 	OptionQuery, 
 >; 

Since it will be impossible to send an equipped item, maybe it would be easier just to change the equipped field inside the NftInfo?
Maybe to something like this:

equipped: Option<(ResourceId, SlotId)>

When equipped, the equipped.0 will point to the corresponding ComposableResource associated with the equipper (a composable resource with an appropriate base id) and the equipped.1 will tell us in what slot this NFT is equipped.

So, here is the method to extract the equipping info from the chain: to get all equipped items you can just use RPC nft_children and filter the equipped children and you will know in what base and slot they are equipped.

I am attempting this.