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

Trading trait and deal with metadata in Mutate trait for nonfungibles_v2 #1561

Merged
merged 10 commits into from
Oct 18, 2023
67 changes: 67 additions & 0 deletions substrate/frame/nfts/src/impl_nonfungibles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,33 @@ impl<T: Config<I>, I: 'static> Mutate<<T as SystemConfig>::AccountId, ItemConfig
})
}

fn set_metadata(
AlexD10S marked this conversation as resolved.
Show resolved Hide resolved
who: &T::AccountId,
jsidorenko marked this conversation as resolved.
Show resolved Hide resolved
collection: &Self::CollectionId,
item: &Self::ItemId,
data: &[u8],
) -> DispatchResult {
Self::do_set_item_metadata(
Some(who.clone()),
*collection,
*item,
Self::construct_metadata(data.to_vec())?,
None,
)
}

fn set_collection_metadata(
who: &T::AccountId,
AlexD10S marked this conversation as resolved.
Show resolved Hide resolved
collection: &Self::CollectionId,
data: &[u8],
) -> DispatchResult {
Self::do_set_collection_metadata(
Some(who.clone()),
*collection,
Self::construct_metadata(data.to_vec())?,
)
}

fn clear_attribute(
collection: &Self::CollectionId,
item: &Self::ItemId,
Expand Down Expand Up @@ -362,6 +389,21 @@ impl<T: Config<I>, I: 'static> Mutate<<T as SystemConfig>::AccountId, ItemConfig
<Self as Mutate<T::AccountId, ItemConfig>>::clear_collection_attribute(collection, k)
})
}

fn clear_metadata(
who: &T::AccountId,
jsidorenko marked this conversation as resolved.
Show resolved Hide resolved
collection: &Self::CollectionId,
item: &Self::ItemId,
) -> DispatchResult {
Self::do_clear_item_metadata(Some(who.clone()), *collection, *item)
}

fn clear_collection_metadata(
who: &T::AccountId,
collection: &Self::CollectionId,
) -> DispatchResult {
Self::do_clear_collection_metadata(Some(who.clone()), *collection)
}
AlexD10S marked this conversation as resolved.
Show resolved Hide resolved
}

impl<T: Config<I>, I: 'static> Transfer<T::AccountId> for Pallet<T, I> {
Expand Down Expand Up @@ -398,6 +440,31 @@ impl<T: Config<I>, I: 'static> Transfer<T::AccountId> for Pallet<T, I> {
}
}

impl<T: Config<I>, I: 'static> Trading<T::AccountId, ItemPrice<T, I>> for Pallet<T, I> {
fn buy_item(
collection: &Self::CollectionId,
item: &Self::ItemId,
buyer: &T::AccountId,
bid_price: &ItemPrice<T, I>,
) -> DispatchResult {
Self::do_buy_item(*collection, *item, buyer.clone(), *bid_price)
}

fn set_price(
collection: &Self::CollectionId,
item: &Self::ItemId,
sender: &T::AccountId,
price: Option<ItemPrice<T, I>>,
whitelisted_buyer: Option<T::AccountId>,
) -> DispatchResult {
Self::do_set_price(*collection, *item, sender.clone(), price, whitelisted_buyer)
}

fn item_price(collection: &Self::CollectionId, item: &Self::ItemId) -> Option<ItemPrice<T, I>> {
ItemPriceOf::<T, I>::get(collection, item).map(|a| a.0)
}
}

impl<T: Config<I>, I: 'static> InspectEnumerable<T::AccountId> for Pallet<T, I> {
type CollectionsIterator = KeyPrefixIterator<<T as Config<I>>::CollectionId>;
type ItemsIterator = KeyPrefixIterator<<T as Config<I>>::ItemId>;
Expand Down
3 changes: 2 additions & 1 deletion substrate/frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ pub use tokens::{
},
fungible, fungibles,
imbalance::{Imbalance, OnUnbalanced, SignedImbalance},
nonfungible, nonfungibles, BalanceStatus, ExistenceRequirement, Locker, WithdrawReasons,
nonfungible, nonfungible_v2, nonfungibles, nonfungibles_v2, BalanceStatus,
ExistenceRequirement, Locker, WithdrawReasons,
};

mod members;
Expand Down
16 changes: 15 additions & 1 deletion substrate/frame/support/src/traits/tokens/nonfungible_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ pub trait InspectEnumerable<AccountId>: Inspect<AccountId> {
}

/// Trait for providing an interface for NFT-like items which may be minted, burned and/or have
/// attributes set on them.
/// attributes and metadata set on them.
pub trait Mutate<AccountId, ItemConfig>: Inspect<AccountId> {
/// Mint some `item` to be owned by `who`.
///
Expand Down Expand Up @@ -158,6 +158,13 @@ pub trait Mutate<AccountId, ItemConfig>: Inspect<AccountId> {
key.using_encoded(|k| value.using_encoded(|v| Self::set_attribute(item, k, v)))
}

/// Set the metadata `data` of an `item`.
///
/// By default, this is not a supported operation.
fn set_metadata(_who: &AccountId, _item: &Self::ItemId, _data: &[u8]) -> DispatchResult {
Err(TokenError::Unsupported.into())
}

/// Clear attribute of `item`'s `key`.
///
/// By default, this is not a supported operation.
Expand All @@ -171,6 +178,13 @@ pub trait Mutate<AccountId, ItemConfig>: Inspect<AccountId> {
fn clear_typed_attribute<K: Encode>(item: &Self::ItemId, key: &K) -> DispatchResult {
key.using_encoded(|k| Self::clear_attribute(item, k))
}

/// Clear the metadata of an `item`.
///
/// By default, this is not a supported operation.
fn clear_metadata(_who: &AccountId, _item: &Self::ItemId) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
}

/// Trait for transferring and controlling the transfer of non-fungible sets of items.
Expand Down
70 changes: 69 additions & 1 deletion substrate/frame/support/src/traits/tokens/nonfungibles_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ pub trait Destroy<AccountId>: Inspect<AccountId> {
}

/// Trait for providing an interface for multiple collections of NFT-like items which may be
/// minted, burned and/or have attributes set on them.
/// minted, burned and/or have attributes and metadata set on them.
pub trait Mutate<AccountId, ItemConfig>: Inspect<AccountId> {
/// Mint some `item` of `collection` to be owned by `who`.
///
Expand Down Expand Up @@ -307,6 +307,29 @@ pub trait Mutate<AccountId, ItemConfig>: Inspect<AccountId> {
})
}

/// Set the metadata `data` of an `item` of `collection`.
///
/// By default, this is not a supported operation.
fn set_metadata(
_who: &AccountId,
_collection: &Self::CollectionId,
_item: &Self::ItemId,
_data: &[u8],
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}

/// Set the metadata `data` of a `collection`.
///
/// By default, this is not a supported operation.
fn set_collection_metadata(
_who: &AccountId,
_collection: &Self::CollectionId,
_data: &[u8],
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}

/// Clear attribute of `item` of `collection`'s `key`.
///
/// By default, this is not a supported operation.
Expand Down Expand Up @@ -345,6 +368,27 @@ pub trait Mutate<AccountId, ItemConfig>: Inspect<AccountId> {
) -> DispatchResult {
key.using_encoded(|k| Self::clear_collection_attribute(collection, k))
}

/// Clear the metadata of an `item` of `collection`.
///
/// By default, this is not a supported operation.
fn clear_metadata(
_who: &AccountId,
_collection: &Self::CollectionId,
_item: &Self::ItemId,
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}

/// Clear the metadata of a `collection`.
///
/// By default, this is not a supported operation.
fn clear_collection_metadata(
_who: &AccountId,
_collection: &Self::CollectionId,
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
}

/// Trait for transferring non-fungible sets of items.
Expand All @@ -370,3 +414,27 @@ pub trait Transfer<AccountId>: Inspect<AccountId> {
Err(TokenError::Unsupported.into())
}
}

/// Trait for trading non-fungible items.
pub trait Trading<AccountId, ItemPrice>: Inspect<AccountId> {
/// Allows `buyer` to buy an `item` of `collection` if it's up for sale with a `bid_price` to
/// pay.
fn buy_item(
collection: &Self::CollectionId,
item: &Self::ItemId,
buyer: &AccountId,
bid_price: &ItemPrice,
) -> DispatchResult;

/// Sets the item price for `item` to make it available for sale.
fn set_price(
collection: &Self::CollectionId,
item: &Self::ItemId,
sender: &AccountId,
price: Option<ItemPrice>,
whitelisted_buyer: Option<AccountId>,
) -> DispatchResult;

/// Returns the item price of `item` or `None` if the item is not for sale.
fn item_price(collection: &Self::CollectionId, item: &Self::ItemId) -> Option<ItemPrice>;
}
Loading