Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
[Uniques v2] Refactoring (#12570)
Browse files Browse the repository at this point in the history
* Move do_set_price() and do_buy_item() to buy_sell.rs

* Move approvals to feature file

* Move metadata to feature files

* Move the rest of methods to feature files

* Remove artifacts
  • Loading branch information
jsidorenko authored Nov 14, 2022
1 parent cfa90dd commit d667fb7
Show file tree
Hide file tree
Showing 13 changed files with 1,074 additions and 837 deletions.
42 changes: 42 additions & 0 deletions frame/nfts/src/common_functions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// This file is part of Substrate.

// Copyright (C) 2017-2022 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Various pieces of common functionality.
use super::*;

impl<T: Config<I>, I: 'static> Pallet<T, I> {
/// Get the owner of the item, if the item exists.
pub fn owner(collection: T::CollectionId, item: T::ItemId) -> Option<T::AccountId> {
Item::<T, I>::get(collection, item).map(|i| i.owner)
}

/// Get the owner of the item, if the item exists.
pub fn collection_owner(collection: T::CollectionId) -> Option<T::AccountId> {
Collection::<T, I>::get(collection).map(|i| i.owner)
}

#[cfg(any(test, feature = "runtime-benchmarks"))]
pub fn set_next_id(id: T::CollectionId) {
NextCollectionId::<T, I>::set(Some(id));
}

#[cfg(test)]
pub fn get_next_id() -> T::CollectionId {
NextCollectionId::<T, I>::get().unwrap_or(T::CollectionId::initial_value())
}
}
132 changes: 132 additions & 0 deletions frame/nfts/src/features/approvals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// This file is part of Substrate.

// Copyright (C) 2022 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::*;
use frame_support::pallet_prelude::*;

impl<T: Config<I>, I: 'static> Pallet<T, I> {
pub(crate) fn do_approve_transfer(
maybe_check_origin: Option<T::AccountId>,
collection: T::CollectionId,
item: T::ItemId,
delegate: T::AccountId,
maybe_deadline: Option<<T as SystemConfig>::BlockNumber>,
) -> DispatchResult {
ensure!(
Self::is_pallet_feature_enabled(PalletFeature::Approvals),
Error::<T, I>::MethodDisabled
);
let mut details =
Item::<T, I>::get(&collection, &item).ok_or(Error::<T, I>::UnknownItem)?;

let collection_config = Self::get_collection_config(&collection)?;
ensure!(
collection_config.is_setting_enabled(CollectionSetting::TransferableItems),
Error::<T, I>::ItemsNonTransferable
);

if let Some(check_origin) = maybe_check_origin {
let is_admin = Self::has_role(&collection, &check_origin, CollectionRole::Admin);
let permitted = is_admin || check_origin == details.owner;
ensure!(permitted, Error::<T, I>::NoPermission);
}

let now = frame_system::Pallet::<T>::block_number();
let deadline = maybe_deadline.map(|d| d.saturating_add(now));

details
.approvals
.try_insert(delegate.clone(), deadline)
.map_err(|_| Error::<T, I>::ReachedApprovalLimit)?;
Item::<T, I>::insert(&collection, &item, &details);

Self::deposit_event(Event::ApprovedTransfer {
collection,
item,
owner: details.owner,
delegate,
deadline,
});

Ok(())
}

pub(crate) fn do_cancel_approval(
maybe_check_origin: Option<T::AccountId>,
collection: T::CollectionId,
item: T::ItemId,
delegate: T::AccountId,
) -> DispatchResult {
let mut details =
Item::<T, I>::get(&collection, &item).ok_or(Error::<T, I>::UnknownItem)?;

let maybe_deadline = details.approvals.get(&delegate).ok_or(Error::<T, I>::NotDelegate)?;

let is_past_deadline = if let Some(deadline) = maybe_deadline {
let now = frame_system::Pallet::<T>::block_number();
now > *deadline
} else {
false
};

if !is_past_deadline {
if let Some(check_origin) = maybe_check_origin {
let is_admin = Self::has_role(&collection, &check_origin, CollectionRole::Admin);
let permitted = is_admin || check_origin == details.owner;
ensure!(permitted, Error::<T, I>::NoPermission);
}
}

details.approvals.remove(&delegate);
Item::<T, I>::insert(&collection, &item, &details);

Self::deposit_event(Event::ApprovalCancelled {
collection,
item,
owner: details.owner,
delegate,
});

Ok(())
}

pub(crate) fn do_clear_all_transfer_approvals(
maybe_check_origin: Option<T::AccountId>,
collection: T::CollectionId,
item: T::ItemId,
) -> DispatchResult {
let mut details =
Item::<T, I>::get(&collection, &item).ok_or(Error::<T, I>::UnknownCollection)?;

if let Some(check_origin) = maybe_check_origin {
let is_admin = Self::has_role(&collection, &check_origin, CollectionRole::Admin);
let permitted = is_admin || check_origin == details.owner;
ensure!(permitted, Error::<T, I>::NoPermission);
}

details.approvals.clear();
Item::<T, I>::insert(&collection, &item, &details);

Self::deposit_event(Event::AllApprovalsCancelled {
collection,
item,
owner: details.owner,
});

Ok(())
}
}
123 changes: 123 additions & 0 deletions frame/nfts/src/features/attributes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// This file is part of Substrate.

// Copyright (C) 2022 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::*;
use frame_support::pallet_prelude::*;

impl<T: Config<I>, I: 'static> Pallet<T, I> {
pub(crate) fn do_set_attribute(
maybe_check_owner: Option<T::AccountId>,
collection: T::CollectionId,
maybe_item: Option<T::ItemId>,
key: BoundedVec<u8, T::KeyLimit>,
value: BoundedVec<u8, T::ValueLimit>,
) -> DispatchResult {
ensure!(
Self::is_pallet_feature_enabled(PalletFeature::Attributes),
Error::<T, I>::MethodDisabled
);

let mut collection_details =
Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;

if let Some(check_owner) = &maybe_check_owner {
ensure!(check_owner == &collection_details.owner, Error::<T, I>::NoPermission);
}

let collection_config = Self::get_collection_config(&collection)?;
match maybe_item {
None => {
ensure!(
collection_config.is_setting_enabled(CollectionSetting::UnlockedAttributes),
Error::<T, I>::LockedCollectionAttributes
)
},
Some(item) => {
let maybe_is_locked = Self::get_item_config(&collection, &item)
.map(|c| c.has_disabled_setting(ItemSetting::UnlockedAttributes))?;
ensure!(!maybe_is_locked, Error::<T, I>::LockedItemAttributes);
},
};

let attribute = Attribute::<T, I>::get((collection, maybe_item, &key));
if attribute.is_none() {
collection_details.attributes.saturating_inc();
}
let old_deposit = attribute.map_or(Zero::zero(), |m| m.1);
collection_details.total_deposit.saturating_reduce(old_deposit);
let mut deposit = Zero::zero();
if collection_config.is_setting_enabled(CollectionSetting::DepositRequired) &&
maybe_check_owner.is_some()
{
deposit = T::DepositPerByte::get()
.saturating_mul(((key.len() + value.len()) as u32).into())
.saturating_add(T::AttributeDepositBase::get());
}
collection_details.total_deposit.saturating_accrue(deposit);
if deposit > old_deposit {
T::Currency::reserve(&collection_details.owner, deposit - old_deposit)?;
} else if deposit < old_deposit {
T::Currency::unreserve(&collection_details.owner, old_deposit - deposit);
}

Attribute::<T, I>::insert((&collection, maybe_item, &key), (&value, deposit));
Collection::<T, I>::insert(collection, &collection_details);
Self::deposit_event(Event::AttributeSet { collection, maybe_item, key, value });
Ok(())
}

pub(crate) fn do_clear_attribute(
maybe_check_owner: Option<T::AccountId>,
collection: T::CollectionId,
maybe_item: Option<T::ItemId>,
key: BoundedVec<u8, T::KeyLimit>,
) -> DispatchResult {
let mut collection_details =
Collection::<T, I>::get(&collection).ok_or(Error::<T, I>::UnknownCollection)?;
if let Some(check_owner) = &maybe_check_owner {
ensure!(check_owner == &collection_details.owner, Error::<T, I>::NoPermission);
}

if maybe_check_owner.is_some() {
match maybe_item {
None => {
let collection_config = Self::get_collection_config(&collection)?;
ensure!(
collection_config.is_setting_enabled(CollectionSetting::UnlockedAttributes),
Error::<T, I>::LockedCollectionAttributes
)
},
Some(item) => {
// NOTE: if the item was previously burned, the ItemConfigOf record might
// not exist. In that case, we allow to clear the attribute.
let maybe_is_locked = Self::get_item_config(&collection, &item)
.map_or(false, |c| c.has_disabled_setting(ItemSetting::UnlockedAttributes));
ensure!(!maybe_is_locked, Error::<T, I>::LockedItemAttributes);
},
};
}

if let Some((_, deposit)) = Attribute::<T, I>::take((collection, maybe_item, &key)) {
collection_details.attributes.saturating_dec();
collection_details.total_deposit.saturating_reduce(deposit);
T::Currency::unreserve(&collection_details.owner, deposit);
Collection::<T, I>::insert(collection, &collection_details);
Self::deposit_event(Event::AttributeCleared { collection, maybe_item, key });
}
Ok(())
}
}
Loading

0 comments on commit d667fb7

Please sign in to comment.