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

Initial RMRK Market pallet skeleton #65

Merged
merged 14 commits into from
Feb 1, 2022
Merged
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
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
'node',
'pallets/template',
'pallets/rmrk-core',
'pallets/rmrk-market',
'runtime',
]
[profile.release]
Expand Down
13 changes: 6 additions & 7 deletions pallets/rmrk-core/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,6 @@ where
let max: u32 = collection.max;

// Prevent minting when next NFT id is greater than the collection max.
// TODO: do we need nft_id < max || max == max - max
ensure!(nft_id < max, Error::<T>::CollectionFullOrLocked);

let recipient = recipient.unwrap_or_else(|| owner.clone());
Expand All @@ -209,7 +208,7 @@ where

let nft = NftInfo { owner: owner_as_maybe_account, recipient, royalty, metadata };

NFTs::<T>::insert(collection_id, nft_id, nft);
Nfts::<T>::insert(collection_id, nft_id, nft);
NftsByOwner::<T>::append(owner, (collection_id, nft_id));

// increment nfts counter
Expand All @@ -229,7 +228,7 @@ where
max_recursions: u32,
) -> sp_std::result::Result<(CollectionId, NftId), DispatchError> {
ensure!(max_recursions > 0, Error::<T>::TooManyRecursions);
NFTs::<T>::remove(collection_id, nft_id);
Nfts::<T>::remove(collection_id, nft_id);
let kids = Children::<T>::take((collection_id, nft_id));
for (child_collection_id, child_nft_id) in kids {
// Remove child from Children StorageMap
Expand Down Expand Up @@ -263,14 +262,14 @@ where
ensure!(sender == root_owner, Error::<T>::NoPermission);
// Get NFT info
let mut sending_nft =
NFTs::<T>::get(collection_id, nft_id).ok_or(Error::<T>::NoAvailableNftId)?;
Nfts::<T>::get(collection_id, nft_id).ok_or(Error::<T>::NoAvailableNftId)?;

// Prepare transfer
let new_owner_account = match new_owner.clone() {
AccountIdOrCollectionNftTuple::AccountId(id) => id,
AccountIdOrCollectionNftTuple::CollectionAndNftTuple(cid, nid) => {
// Check if NFT target exists
ensure!(NFTs::<T>::contains_key(cid, nid), Error::<T>::NoAvailableNftId);
ensure!(Nfts::<T>::contains_key(cid, nid), Error::<T>::NoAvailableNftId);
// Check if sending to self
ensure!(
(collection_id, nft_id) != (cid, nid),
Expand All @@ -287,7 +286,7 @@ where
};

sending_nft.owner = new_owner;
NFTs::<T>::insert(collection_id, nft_id, sending_nft);
Nfts::<T>::insert(collection_id, nft_id, sending_nft);

if let Some(current_owner) = parent {
// Handle Children StorageMap for NFTs
Expand Down Expand Up @@ -480,7 +479,7 @@ where
max_recursions: u32,
) -> DispatchResult {
ensure!(max_recursions > 0, Error::<T>::TooManyRecursions);
NFTs::<T>::remove(collection_id, nft_id);
Nfts::<T>::remove(collection_id, nft_id);
let kids = Children::<T>::take((collection_id, nft_id));
for (child_collection_id, child_nft_id) in kids {
Pallet::<T>::recursive_burn(child_collection_id, child_nft_id, max_recursions - 1)?;
Expand Down
4 changes: 2 additions & 2 deletions pallets/rmrk-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub mod pallet {
#[pallet::storage]
#[pallet::getter(fn nfts)]
/// Stores nft info
pub type NFTs<T: Config> =
pub type Nfts<T: Config> =
StorageDoubleMap<_, Twox64Concat, CollectionId, Twox64Concat, NftId, InstanceInfoOf<T>>;

#[pallet::storage]
Expand Down Expand Up @@ -249,7 +249,7 @@ pub mod pallet {
if let Some(collection_issuer) = pallet_uniques::Pallet::<T>::class_owner(&collection_id) {
ensure!(collection_issuer == sender, Error::<T>::NoPermission);
} else {
Err(Error::<T>::CollectionUnknown)?;
return Err(Error::<T>::CollectionUnknown.into())
}

let (collection_id, nft_id) =
Expand Down
54 changes: 54 additions & 0 deletions pallets/rmrk-market/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
[package]
name = "pallet-rmrk-market"
version = "4.0.0-dev"
description = "RMRK Market"
authors = ["RMRK Team"]
homepage = ""
edition = "2021"
license = "Apache-2.0"
publish = false
repository = "https://github.com/rmrk-team/rmrk-substrate"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
serde = { version = "1.0.111", default-features = false, features = ["derive"] }
sp-runtime = { default-features = false, version = "4.0.0", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01" }
sp-std = { default-features = false, version = "4.0.0", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01" }
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [
"derive",
] }
scale-info = { version = "1.0", default-features = false, features = ["derive"] }
frame-support = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01"}
frame-system = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01" }
frame-benchmarking = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01", optional = true }

pallet-uniques = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01" }
pallet-balances = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01" }

# Local Dependencies
pallet-rmrk-core = { default-features = false, version = "4.0.0-dev", path = "../rmrk-core" }
rmrk-traits = { default-features = false, version = "0.0.1", path = "../../traits" }

[dev-dependencies]
sp-core = { default-features = false, version = "4.1.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01" }
sp-io = { default-features = false, version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01" }
sp-runtime = { default-features = false, version = "4.0.0", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01" }
sp-std = { default-features = false, version = "4.0.0", git = "https://github.com/paritytech/substrate.git", tag = "monthly-2022-01" }

[features]
default = ["std"]
std = [
"pallet-uniques/std",
"pallet-balances/std",
"serde/std",
"codec/std",
"scale-info/std",
"frame-support/std",
"frame-system/std",
"frame-benchmarking/std",
]

runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"]
try-runtime = ["frame-support/try-runtime"]
107 changes: 107 additions & 0 deletions pallets/rmrk-market/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Market Pallet
Market pallet design for the RMRK NFT Market. The Market pallet should extend [NFT Core](https://hackmd.io/GNJXyhXnTJiXvg3X-r3l3Q).

## Calls
- `buy(origin, collection_id, nft_id)`
- `list(origin, collection_id, nft_id, amount: T::Balance, expires: Option<T::BlockNumber>)`
- `unlist(origin, collection_id, nft_id)`
- `make_offer(origin, collection_id, nft_id, amount: BalanceOf<T>, expires: Option<T::BlockNumber>)`
- `withdraw_offer(origin, collection_id, nft_id)`

## Storages
```rust
#[pallet::storage]
#[pallet::getter(fn listed_nfts)]
/// Stores listed NFT price info
pub type ListedNfts<T: Config> = StorageDoubleMap<
_,
Blake2_128Concat,
CollectionId,
Blake2_128Concat,
NftId,
ListInfoOf<T>,
OptionQuery,
>;

#[pallet::storage]
#[pallet::getter(fn offers)]
/// Stores offer on a NFT info
pub type Offers<T: Config> = StorageDoubleMap<
_,
Blake2_128Concat,
(CollectionId, NftId),
Blake2_128Concat,
T::AccountId,
OfferOf<T>,
OptionQuery,
>;
```

## Types
```rust
pub type ListInfoOf<T> = ListInfo<
<T as frame_system::Config>::AccountId, BalanceOf<T>, <T as frame_system::Config>::BlockNumber>;

pub type OfferOf<T> = Offer<
<T as frame_system::Config>::AccountId, BalanceOf<T>, <T as frame_system::Config>::BlockNumber>;
```

## Events

```rust
pub enum Event<T: Config> {
/// The price for a token was updated \[owner, collection_id, nft_id, price\]
TokenPriceUpdated {
owner: T::AccountId,
collection_id: CollectionId,
nft_id: NftId,
price: Option<BalanceOf<T>>,
},
/// Token was sold to a new owner
/// \[owner, buyer, collection_id, nft_id, price, author\]
TokenSold {
owner: T::AccountId,
buyer: T::AccountId,
collection_id: CollectionId,
nft_id: NftId,
price: BalanceOf<T>,
},
/// Token listed on Marketplace \[owner, collection_id, nft_id\]
TokenListed {
owner: T::AccountId,
collection_id: CollectionId,
nft_id: NftId,
price: BalanceOf<T>,
},
/// Token unlisted on Marketplace \[owner, collection_id, nft_id\]
TokenUnlisted {
owner: T::AccountId,
collection_id: CollectionId,
nft_id: NftId,
},
/// Offer was placed on a token \[offerer, collection_id, nft_id, price\]
OfferPlaced {
offerer: T::AccountId,
collection_id: CollectionId,
nft_id: NftId,
price: BalanceOf<T>,
},
/// Offer was withdrawn \[sender, collection_id, nft_id\]
OfferWithdrawn {
sender: T::AccountId,
collection_id: CollectionId,
nft_id: NftId,
},
/// Offer was accepted \[owner, buyer, collection_id, nft_id\]
OfferAccepted {
owner: T::AccountId,
buyer: T::AccountId,
collection_id: CollectionId,
nft_id: NftId,
},
}
```

## RMRK Spec
- [LIST](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/list.md)
- [BUY](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/buy.md)
Loading