Skip to content

Commit

Permalink
Merge pull request #5 from bmacer/feat/core-children-send-and-burn
Browse files Browse the repository at this point in the history
implement children and iterative burning
  • Loading branch information
ilionic authored Dec 11, 2021
2 parents 757b451 + 588baf6 commit bc5497d
Show file tree
Hide file tree
Showing 3 changed files with 348 additions and 5 deletions.
29 changes: 29 additions & 0 deletions pallets/rmrk-core/src/functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use super::*;

impl<T: Config> Pallet<T> {
pub fn is_x_descendent_of_y(
child_collection_id: T::CollectionId,
child_nft_id: T::NftId,
parent_collection_id: T::CollectionId,
parent_nft_id: T::NftId,
) -> bool {
let mut found_child = false;
if let Some(children) = Children::<T>::get(parent_collection_id, parent_nft_id) {
for child in children {
if child == (child_collection_id, child_nft_id) {
return true;
} else {
if Pallet::<T>::is_x_descendent_of_y(
child_collection_id,
child_nft_id,
child.0,
child.1,
) {
found_child = true;
}
}
}
}
found_child
}
}
62 changes: 57 additions & 5 deletions pallets/rmrk-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use sp_std::{convert::TryInto, vec::Vec};

use types::{AccountIdOrCollectionNftTuple, ClassInfo, InstanceInfo};

mod functions;

#[cfg(test)]
mod mock;

Expand Down Expand Up @@ -107,6 +109,18 @@ pub mod pallet {
InstanceInfoOf<T>,
>;

#[pallet::storage]
#[pallet::getter(fn children)]
/// Stores nft info
pub type Children<T: Config> = StorageDoubleMap<
_,
Twox64Concat,
T::CollectionId,
Twox64Concat,
T::NftId,
Vec<(T::CollectionId, T::NftId)>,
>;

#[pallet::storage]
#[pallet::getter(fn resources)]
/// Stores resource info
Expand Down Expand Up @@ -163,6 +177,7 @@ pub mod pallet {
NoPermission,
NoWitness,
CollectionNotEmpty,
CannotSendToDescendent,
}

#[pallet::call]
Expand Down Expand Up @@ -270,19 +285,23 @@ pub mod pallet {
}

/// burn nft
/// TODO: If an NFT that contains other NFTs is being burnt, the owned NFTs are also burned.
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn burn_nft(
origin: OriginFor<T>,
collection_id: T::CollectionId,
nft_id: T::NftId,
) -> DispatchResult {
let sender = ensure_signed(origin)?;
let sender = ensure_signed(origin.clone())?;
pallet_uniques::Pallet::<T>::do_burn(collection_id.into(), nft_id.into(), |_, _| {
Ok(())
})?;
NFTs::<T>::remove(collection_id, nft_id);
if let Some(kids) = Children::<T>::take(collection_id, nft_id) {
for child in kids {
Pallet::<T>::burn_nft(origin.clone(), child.0, child.1)?;
}
}
Self::deposit_event(Event::NFTBurned(sender, nft_id));
Ok(())
}
Expand Down Expand Up @@ -339,15 +358,48 @@ pub mod pallet {

match new_owner.clone() {
AccountIdOrCollectionNftTuple::AccountId(account_id) => {
// Remove previous parental relationship
if let AccountIdOrCollectionNftTuple::CollectionAndNftTuple(cid, nid) =
sending_nft.owner
{
if let Some(mut kids) = Children::<T>::take(cid, nid) {
kids.retain(|&kid| kid != (collection_id, nft_id));
Children::<T>::insert(cid, nid, kids);
}
}
sending_nft.rootowner = account_id.clone();
},
}
AccountIdOrCollectionNftTuple::CollectionAndNftTuple(cid, nid) => {
let recipient_nft =
NFTs::<T>::get(cid, nid).ok_or(Error::<T>::NoAvailableNftId)?;
// Check if sending NFT is already a child of recipient NFT
ensure!(
!Pallet::<T>::is_x_descendent_of_y(cid, nid, collection_id, nft_id),
Error::<T>::CannotSendToDescendent
);

// Remove parent if exists: first we only care if the owner is a non-AccountId)
if let AccountIdOrCollectionNftTuple::CollectionAndNftTuple(cid, nid) =
sending_nft.owner
{
// second we only care if the parent has children (it should)
if let Some(mut kids) = Children::<T>::take(cid, nid) {
// third we only "retain" the other children
kids.retain(|&kid| kid != (collection_id, nft_id));
Children::<T>::insert(cid, nid, kids);
}
}
if sending_nft.rootowner != recipient_nft.rootowner {
sending_nft.rootowner = recipient_nft.rootowner
}
},
match Children::<T>::take(cid, nid) {
None => Children::<T>::insert(cid, nid, vec![(collection_id, nft_id)]),
Some(mut kids) => {
kids.push((collection_id, nft_id));
Children::<T>::insert(cid, nid, kids);
}
}
}
};
sending_nft.owner = new_owner.clone();

Expand Down Expand Up @@ -383,7 +435,7 @@ pub mod pallet {
// collection.issuer = dest.clone();
// Collections::<T>::insert(collection_id, collection);
// Ok(())
// })?;
// })?;

// Check that sender is current issuer
let mut collection =
Expand Down
Loading

0 comments on commit bc5497d

Please sign in to comment.