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

[Uniques V2] Basic marketplace functions #12189

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1476,6 +1476,10 @@ impl pallet_uniques::Config for Runtime {
type Locker = ();
}

parameter_types! {
pub const SellerTipsLimit: u32 = 10;
}

impl pallet_nfts::Config for Runtime {
type Event = Event;
type CollectionId = u32;
Expand All @@ -1495,6 +1499,7 @@ impl pallet_nfts::Config for Runtime {
type Helper = ();
type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
type Locker = ();
type SellerTipsLimit = SellerTipsLimit;
}

impl pallet_transaction_storage::Config for Runtime {
Expand Down
9 changes: 8 additions & 1 deletion frame/nfts/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {
Account::<T, I>::insert((&dest, &collection, &item), ());
let origin = details.owner;
details.owner = dest;

if let Some(ref seller) = details.seller.clone() {
details.seller = None;
Seller::<T, I>::remove((seller, &collection, &item));
}

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

Expand Down Expand Up @@ -168,7 +174,8 @@ impl<T: Config<I>, I: 'static> Pallet<T, I> {

let owner = owner.clone();
Account::<T, I>::insert((&owner, &collection, &item), ());
let details = ItemDetails { owner, approved: None, is_frozen: false, deposit };
let details =
ItemDetails { owner, approved: None, is_frozen: false, deposit, seller: None };
Item::<T, I>::insert(&collection, &item, details);
Ok(())
},
Expand Down
130 changes: 130 additions & 0 deletions frame/nfts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ mod tests;
mod functions;
mod impl_nonfungibles;
mod types;
mod user_features;

pub mod weights;

Expand Down Expand Up @@ -155,6 +156,10 @@ pub mod pallet {

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;

/// The maximum amount of seller tips records an item could have.
#[pallet::constant]
type SellerTipsLimit: Get<u32>;
}

#[pallet::storage]
Expand Down Expand Up @@ -267,6 +272,19 @@ pub mod pallet {
pub(super) type CollectionMaxSupply<T: Config<I>, I: 'static = ()> =
StorageMap<_, Blake2_128Concat, T::CollectionId, u32, OptionQuery>;

#[pallet::storage]
/// Sellers and items they could sell.
pub(super) type Seller<T: Config<I>, I: 'static = ()> = StorageNMap<
_,
(
NMapKey<Blake2_128Concat, T::AccountId>, // seller
NMapKey<Blake2_128Concat, T::CollectionId>,
NMapKey<Blake2_128Concat, T::ItemId>,
),
ItemSellData<ItemPrice<T, I>, ItemTip<T, I>, T::SellerTipsLimit>,
OptionQuery,
>;

#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config<I>, I: 'static = ()> {
Expand Down Expand Up @@ -375,6 +393,24 @@ pub mod pallet {
seller: T::AccountId,
buyer: T::AccountId,
},
/// A tip was sent.
TipSent {
collection: T::CollectionId,
item: T::ItemId,
sender: T::AccountId,
receiver: T::AccountId,
amount: DepositBalanceOf<T, I>,
},
/// A seller was set for an item.
SellerSet {
collection: T::CollectionId,
item: T::ItemId,
seller: T::AccountId,
price: ItemPrice<T, I>,
tips: SellerTipsOf<T, I>,
},
/// A seller was removed from an item.
SellerRemoved { collection: T::CollectionId, item: T::ItemId, seller: T::AccountId },
}

#[pallet::error]
Expand Down Expand Up @@ -415,6 +451,12 @@ pub mod pallet {
NotForSale,
/// The provided bid is too low.
BidTooLow,
/// Wrong seller provided.
WrongSeller,
/// Wrong price provided.
WrongPrice,
/// Wrong tips provided.
WrongTips,
}

impl<T: Config<I>, I: 'static> Pallet<T, I> {
Expand Down Expand Up @@ -1493,5 +1535,93 @@ pub mod pallet {
let origin = ensure_signed(origin)?;
Self::do_buy_item(collection, item, origin, bid_price)
}

/// Allows to pay the tips.
///
/// Origin must be Signed.
///
/// - `tips`: Tips array.
///
/// Emits `TipSent` on every tip transfer.
#[pallet::weight(0)]
#[transactional]
pub fn pay_tips(origin: OriginFor<T>, tips: Vec<ItemTip<T, I>>) -> DispatchResult {
let origin = ensure_signed(origin)?;
Self::do_pay_tips(origin, tips)
}

/// Allows to set the seller for an item and to set the tips those should be paid.
///
/// Origin must be Signed and must not be the owner of the `item`.
///
/// - `collection`: The collection of the item.
/// - `item`: The item the owner wants to set the seller for.
/// - `seller`: Seller's account.
/// - `price`: The price for an item.
/// - `tips`: Tips those should be paid.
///
/// Emits `SellerSet` on success.
#[pallet::weight(0)]
pub fn set_seller(
origin: OriginFor<T>,
collection: T::CollectionId,
item: T::ItemId,
seller: AccountIdLookupOf<T>,
price: ItemPrice<T, I>,
tips: SellerTipsOf<T, I>,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
let seller = T::Lookup::lookup(seller)?;
Self::do_set_seller(collection, item, origin, seller, price, tips)
}

/// Removes the seller from an item.
///
/// Origin must be Signed and must not be the owner of the `item`.
///
/// - `collection`: The collection of the item.
/// - `item`: The item the owner wants to remove the seller from.
/// - `seller`: Previously set seller's account.
///
/// Emits `SellerRemoved` on success.
#[pallet::weight(0)]
pub fn remove_seller(
origin: OriginFor<T>,
collection: T::CollectionId,
item: T::ItemId,
seller: AccountIdLookupOf<T>,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
let seller = T::Lookup::lookup(seller)?;
Self::do_remove_seller(collection, item, origin, seller)
}

/// Allows to buy an item from the seller.
///
/// Origin must be Signed and must not be the owner of the `item`.
///
/// Note: the `price` and `tips` params need to be provided to ensure it won't be
/// possible to change them in the state by front-running that call.
///
/// - `collection`: The collection of the item.
/// - `item`: The item the sender wants to buy.
/// - `seller`: Previously set seller's account.
/// - `price`: Previously set price.
/// - `tips`: Previously set tips.
///
/// Emits `ItemBought` on success.
#[pallet::weight(0)]
pub fn buy_from_seller(
origin: OriginFor<T>,
collection: T::CollectionId,
item: T::ItemId,
seller: AccountIdLookupOf<T>,
price: ItemPrice<T, I>,
tips: SellerTipsOf<T, I>,
) -> DispatchResult {
let origin = ensure_signed(origin)?;
let seller = T::Lookup::lookup(seller)?;
Self::do_buy_from_seller(collection, item, origin, seller, price, tips)
}
}
}
1 change: 1 addition & 0 deletions frame/nfts/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ impl Config for Test {
type WeightInfo = ();
#[cfg(feature = "runtime-benchmarks")]
type Helper = ();
type SellerTipsLimit = ConstU32<10>;
}

pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
Expand Down
Loading