Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create/Update Internal Functions #204

Merged
merged 10 commits into from
Aug 5, 2022
125 changes: 102 additions & 23 deletions pallets/rmrk-core/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

use super::*;
use codec::{Codec, Decode, Encode};
use frame_support::traits::tokens::Locker;
use frame_support::traits::{tokens::Locker, Get};

use sp_runtime::{
traits::{Saturating, TrailingZeroInput},
ArithmeticError,
Expand Down Expand Up @@ -69,6 +70,33 @@ where
Properties::<T>::insert((&collection_id, maybe_nft_id, &key), &value);
Ok(())
}

// Internal function to set a property for downstream `Origin::root()` calls.
fn do_set_property(
collection_id: CollectionId,
maybe_nft_id: Option<NftId>,
key: KeyLimitOf<T>,
value: ValueLimitOf<T>,
) -> sp_runtime::DispatchResult {
// Ensure collection exists
Collections::<T>::get(&collection_id).ok_or(Error::<T>::CollectionUnknown)?;
Properties::<T>::insert((&collection_id, maybe_nft_id, &key), &value);

Self::deposit_event(Event::PropertySet { collection_id, maybe_nft_id, key, value });
Ok(())
}

// Internal function to remove a property for downstream `Origin::root()` calls.
fn do_remove_property(
collection_id: CollectionId,
maybe_nft_id: Option<NftId>,
key: KeyLimitOf<T>,
) -> sp_runtime::DispatchResult {
Properties::<T>::remove((&collection_id, maybe_nft_id, &key));

Self::deposit_event(Event::PropertyRemoved { collection_id, maybe_nft_id, key });
Ok(())
}
}

impl<T: Config>
Expand Down Expand Up @@ -229,15 +257,30 @@ where
max: Option<u32>,
symbol: BoundedCollectionSymbolOf<T>,
) -> Result<CollectionId, DispatchError> {
let collection = CollectionInfo { issuer, metadata, max, symbol, nfts_count: 0 };
let collection =
CollectionInfo { issuer: issuer.clone(), metadata, max, symbol, nfts_count: 0 };
let collection_id =
<CollectionIndex<T>>::try_mutate(|n| -> Result<CollectionId, DispatchError> {
let id = *n;
ensure!(id != CollectionId::max_value(), Error::<T>::NoAvailableCollectionId);
*n += 1;
Ok(id)
})?;
// Call the pallet_uniques function to create collection
pallet_uniques::Pallet::<T>::do_create_collection(
collection_id,
issuer.clone(),
issuer.clone(),
T::CollectionDeposit::get(),
false,
pallet_uniques::Event::Created {
collection: collection_id,
creator: issuer.clone(),
owner: issuer.clone(),
},
)?;
Collections::<T>::insert(collection_id, collection);
Self::deposit_event(Event::CollectionCreated { issuer, collection_id });
Ok(collection_id)
}

Expand Down Expand Up @@ -278,7 +321,7 @@ where
}
}

impl<T: Config> Nft<T::AccountId, StringLimitOf<T>> for Pallet<T>
impl<T: Config> Nft<T::AccountId, StringLimitOf<T>, BoundedResourceTypeOf<T>> for Pallet<T>
where
T: pallet_uniques::Config<CollectionId = CollectionId, ItemId = NftId>,
{
Expand All @@ -292,6 +335,7 @@ where
royalty_amount: Option<Permill>,
metadata: StringLimitOf<T>,
transferable: bool,
resources: Option<BoundedResourceTypeOf<T>>,
) -> sp_std::result::Result<(CollectionId, NftId), DispatchError> {
let nft_id = Self::get_next_nft_id(collection_id)?;
let collection = Self::collections(collection_id).ok_or(Error::<T>::CollectionUnknown)?;
Expand All @@ -314,12 +358,12 @@ where
None => {
// If a royalty amount is passed but no recipient, defaults to the sender
royalty = Some(RoyaltyInfo { recipient: owner.clone(), amount });
}
},
}
};

let nft = NftInfo {
owner: AccountIdOrCollectionNftTuple::AccountId(owner),
owner: AccountIdOrCollectionNftTuple::AccountId(owner.clone()),
royalty,
metadata,
equipped: false,
Expand All @@ -337,6 +381,24 @@ where
Ok(())
})?;

// Call do_mint for pallet_uniques
pallet_uniques::Pallet::<T>::do_mint(collection_id, nft_id, owner.clone(), |_details| {
Ok(())
})?;

// Add all at-mint resources
if let Some(resources) = resources {
for res in resources {
Self::resource_add(sender.clone(), collection_id, nft_id, res, true)?;
}
}

Self::deposit_event(Event::NftMinted {
owner: AccountIdOrCollectionNftTuple::AccountId(owner),
collection_id,
nft_id,
});

Ok((collection_id, nft_id))
}

Expand All @@ -348,6 +410,7 @@ where
royalty_amount: Option<Permill>,
metadata: StringLimitOf<T>,
transferable: bool,
resources: Option<BoundedResourceTypeOf<T>>,
) -> sp_std::result::Result<(CollectionId, NftId), DispatchError> {
let nft_id = Self::get_next_nft_id(collection_id)?;
let collection = Self::collections(collection_id).ok_or(Error::<T>::CollectionUnknown)?;
Expand Down Expand Up @@ -395,6 +458,26 @@ where
Ok(())
})?;

// For Uniques, we need to decode the "virtual account" ID to be the owner
let uniques_owner = Self::nft_to_account_id(owner.0, owner.1);

pallet_uniques::Pallet::<T>::do_mint(collection_id, nft_id, uniques_owner, |_details| {
Ok(())
})?;

// Add all at-mint resources
if let Some(resources) = resources {
for res in resources {
Self::resource_add(sender.clone(), collection_id, nft_id, res, true)?;
}
}

Self::deposit_event(Event::NftMinted {
owner: AccountIdOrCollectionNftTuple::CollectionAndNftTuple(owner.0, owner.1),
collection_id,
nft_id,
});

Ok((collection_id, nft_id))
}

Expand Down Expand Up @@ -452,8 +535,6 @@ where
let mut sending_nft =
Nfts::<T>::get(collection_id, nft_id).ok_or(Error::<T>::NoAvailableNftId)?;

// TODO: Check NFT lock status

// Check NFT is transferable
Self::check_is_transferable(&sending_nft)?;

Expand Down Expand Up @@ -632,35 +713,33 @@ impl<T: Config> Pallet<T>
where
T: pallet_uniques::Config<CollectionId = CollectionId, ItemId = NftId>,
{
pub fn iterate_nft_children(collection_id: CollectionId, nft_id: NftId) -> impl Iterator<Item=NftChild> {
pub fn iterate_nft_children(
collection_id: CollectionId,
nft_id: NftId,
) -> impl Iterator<Item = NftChild> {
Children::<T>::iter_key_prefix((collection_id, nft_id))
.into_iter()
.map(|(collection_id, nft_id)| NftChild {
collection_id,
nft_id
})
.into_iter()
.map(|(collection_id, nft_id)| NftChild { collection_id, nft_id })
}

pub fn iterate_resources(collection_id: CollectionId, nft_id: NftId) -> impl Iterator<Item=ResourceInfoOf<T>> {
pub fn iterate_resources(
collection_id: CollectionId,
nft_id: NftId,
) -> impl Iterator<Item = ResourceInfoOf<T>> {
Resources::<T>::iter_prefix_values((collection_id, nft_id))
}

pub fn query_properties(
collection_id: CollectionId,
nft_id: Option<NftId>,
filter_keys: Option<BTreeSet<BoundedVec<u8, <T as pallet_uniques::Config>::KeyLimit>>>
) -> impl Iterator<Item=PropertyInfoOf<T>> {
filter_keys: Option<BTreeSet<BoundedVec<u8, <T as pallet_uniques::Config>::KeyLimit>>>,
) -> impl Iterator<Item = PropertyInfoOf<T>> {
Properties::<T>::iter_prefix((collection_id, nft_id))
.filter(move |(key, _)| match &filter_keys {
Some(filter_keys) => filter_keys.contains(key),
None => true
})
.map(|(key, value)| {
PropertyInfoOf::<T> {
key,
value
}
None => true,
})
.map(|(key, value)| PropertyInfoOf::<T> { key, value })
}

/// Encodes a RMRK NFT with randomness + `collection_id` + `nft_id` into a virtual account
Expand Down
78 changes: 14 additions & 64 deletions pallets/rmrk-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ pub mod pallet {
#[pallet::storage]
#[pallet::getter(fn properties)]
/// Arbitrary properties / metadata of an asset.
pub(super) type Properties<T: Config> = StorageNMap<
pub type Properties<T: Config> = StorageNMap<
_,
(
NMapKey<Blake2_128Concat, CollectionId>,
Expand Down Expand Up @@ -295,6 +295,11 @@ pub mod pallet {
key: KeyLimitOf<T>,
value: ValueLimitOf<T>,
},
PropertyRemoved {
collection_id: CollectionId,
maybe_nft_id: Option<NftId>,
key: KeyLimitOf<T>,
},
CollectionLocked {
issuer: T::AccountId,
collection_id: CollectionId,
Expand Down Expand Up @@ -400,36 +405,17 @@ pub mod pallet {
};

// Mint NFT for RMRK storage
let (collection_id, nft_id) = Self::nft_mint(
sender.clone(),
nft_owner.clone(),
Self::nft_mint(
sender,
nft_owner,
collection_id,
royalty_recipient,
royalty,
metadata,
transferable,
resources,
)?;

pallet_uniques::Pallet::<T>::do_mint(
collection_id,
nft_id,
nft_owner.clone(),
|_details| Ok(()),
)?;

// Add all at-mint resources
if let Some(resources) = resources {
for res in resources {
Self::resource_add(sender.clone(), collection_id, nft_id, res, true)?;
}
}

Self::deposit_event(Event::NftMinted {
owner: AccountIdOrCollectionNftTuple::AccountId(nft_owner),
collection_id,
nft_id,
});

Ok(())
}

Expand Down Expand Up @@ -466,39 +452,17 @@ pub mod pallet {
}

// Mint NFT for RMRK storage
let (collection_id, nft_id) = Self::nft_mint_directly_to_nft(
sender.clone(),
Self::nft_mint_directly_to_nft(
sender,
owner,
collection_id,
royalty_recipient,
royalty,
metadata,
transferable,
resources,
)?;

// For Uniques, we need to decode the "virtual account" ID to be the owner
let uniques_owner = Self::nft_to_account_id(owner.0, owner.1);

pallet_uniques::Pallet::<T>::do_mint(
collection_id,
nft_id,
uniques_owner,
|_details| Ok(()),
)?;

// Add all at-mint resources
if let Some(resources) = resources {
for res in resources {
Self::resource_add(sender.clone(), collection_id, nft_id, res, true)?;
}
}

Self::deposit_event(Event::NftMinted {
owner: AccountIdOrCollectionNftTuple::CollectionAndNftTuple(owner.0, owner.1),
collection_id,
nft_id,
});

Ok(())
}

Expand All @@ -513,22 +477,8 @@ pub mod pallet {
) -> DispatchResult {
let sender = ensure_signed(origin)?;

let collection_id = Self::collection_create(sender.clone(), metadata, max, symbol)?;

pallet_uniques::Pallet::<T>::do_create_collection(
collection_id,
sender.clone(),
sender.clone(),
T::CollectionDeposit::get(),
false,
pallet_uniques::Event::Created {
collection: collection_id,
creator: sender.clone(),
owner: sender.clone(),
},
)?;
Self::collection_create(sender, metadata, max, symbol)?;

Self::deposit_event(Event::CollectionCreated { issuer: sender, collection_id });
Ok(())
}

Expand Down
Loading