difftreelog
style reformat code
in: master
19 files changed
client/rpc/src/lib.rsdiffbeforeafterboth--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -30,8 +30,7 @@
// RMRK
use rmrk_rpc::RmrkApi as RmrkRuntimeApi;
use up_data_structs::{
- RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName,
- RmrkResourceId,
+ RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName, RmrkResourceId,
};
pub use rmrk_unique_rpc::RmrkApi;
node/cli/src/service.rsdiffbeforeafterboth--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -364,7 +364,8 @@
RmrkBaseInfo<AccountId>,
RmrkPartType,
RmrkTheme,
- >*/ + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ >*/
+ + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ sp_api::Metadata<Block>
+ sp_offchain::OffchainWorkerApi<Block>
+ cumulus_primitives_core::CollectCollationInfo<Block>,
@@ -656,7 +657,8 @@
RmrkBaseInfo<AccountId>,
RmrkPartType,
RmrkTheme,
- >*/ + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ >*/
+ + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ sp_api::Metadata<Block>
+ sp_offchain::OffchainWorkerApi<Block>
+ cumulus_primitives_core::CollectCollationInfo<Block>
@@ -800,7 +802,8 @@
RmrkBaseInfo<AccountId>,
RmrkPartType,
RmrkTheme,
- >*/ + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ >*/
+ + substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ sp_api::Metadata<Block>
+ sp_offchain::OffchainWorkerApi<Block>
+ cumulus_primitives_core::CollectCollationInfo<Block>
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -501,7 +501,6 @@
PhantomType<(
TokenData<T::CrossAccountId>,
RpcCollection<T::AccountId>,
-
// RMRK
RmrkCollectionInfo<T::AccountId>,
RmrkInstanceInfo<T::AccountId>,
@@ -526,19 +525,34 @@
if !v.offchain_schema.is_empty() {
props.push(Property {
key: b"_old_offchainSchema".to_vec().try_into().unwrap(),
- value: v.offchain_schema.clone().into_inner().try_into().expect("offchain schema too big"),
+ value: v
+ .offchain_schema
+ .clone()
+ .into_inner()
+ .try_into()
+ .expect("offchain schema too big"),
});
}
if !v.variable_on_chain_schema.is_empty() {
props.push(Property {
key: b"_old_variableOnChainSchema".to_vec().try_into().unwrap(),
- value: v.variable_on_chain_schema.clone().into_inner().try_into().expect("offchain schema too big"),
+ value: v
+ .variable_on_chain_schema
+ .clone()
+ .into_inner()
+ .try_into()
+ .expect("offchain schema too big"),
});
}
if !v.const_on_chain_schema.is_empty() {
props.push(Property {
key: b"_old_constOnChainSchema".to_vec().try_into().unwrap(),
- value: v.const_on_chain_schema.clone().into_inner().try_into().expect("offchain schema too big"),
+ value: v
+ .const_on_chain_schema
+ .clone()
+ .into_inner()
+ .try_into()
+ .expect("offchain schema too big"),
});
}
props.push(Property {
@@ -546,13 +560,17 @@
value: match v.schema_version {
SchemaVersion::ImageURL => b"ImageUrl".as_slice(),
SchemaVersion::Unique => b"Unique".as_slice(),
- }.to_vec().try_into().unwrap(),
+ }
+ .to_vec()
+ .try_into()
+ .unwrap(),
});
Self::set_scoped_collection_properties(
id,
PropertyScope::None,
props.into_iter(),
- ).expect("existing data larger than properties");
+ )
+ .expect("existing data larger than properties");
let mut new = CollectionVersion2::from(v.clone());
new.permissions.access = Some(v.access);
new.permissions.mint_mode = Some(v.mint_mode);
@@ -644,18 +662,12 @@
let token_property_permissions = <CollectionPropertyPermissions<T>>::get(collection)
.into_iter()
- .map(|(key, permission)| PropertyKeyPermission {
- key,
- permission,
- })
+ .map(|(key, permission)| PropertyKeyPermission { key, permission })
.collect();
let properties = <CollectionProperties<T>>::get(collection)
.into_iter()
- .map(|(key, value)| Property {
- key,
- value,
- })
+ .map(|(key, value)| Property { key, value })
.collect();
let permissions = CollectionPermissions {
@@ -751,7 +763,9 @@
.unwrap_or_else(|| Ok(CollectionLimits::default()))?,
permissions: data
.permissions
- .map(|permissions| Self::clamp_permissions(data.mode.clone(), &Default::default(), permissions))
+ .map(|permissions| {
+ Self::clamp_permissions(data.mode.clone(), &Default::default(), permissions)
+ })
.unwrap_or_else(|| Ok(CollectionPermissions::default()))?,
};
@@ -1005,10 +1019,7 @@
.unwrap_or_else(|| {
properties
.into_iter()
- .map(|(key, value)| Property {
- key,
- value,
- })
+ .map(|(key, value)| Property { key, value })
.collect()
});
@@ -1037,10 +1048,7 @@
.unwrap_or_else(|| {
permissions
.into_iter()
- .map(|(key, permission)| PropertyKeyPermission {
- key,
- permission,
- })
+ .map(|(key, permission)| PropertyKeyPermission { key, permission })
.collect()
});
@@ -1276,17 +1284,9 @@
budget: &dyn Budget,
) -> DispatchResult;
- fn nest(
- &self,
- under: TokenId,
- to_nest: (CollectionId, TokenId)
- );
+ fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId));
- fn unnest(
- &self,
- under: TokenId,
- to_nest: (CollectionId, TokenId)
- );
+ fn unnest(&self, under: TokenId, to_nest: (CollectionId, TokenId));
fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;
fn collection_tokens(&self) -> Vec<TokenId>;
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -298,17 +298,9 @@
fail!(<Error<T>>::FungibleDisallowsNesting)
}
- fn nest(
- &self,
- _under: TokenId,
- _to_nest: (CollectionId, TokenId)
- ) {}
+ fn nest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}
- fn unnest(
- &self,
- _under: TokenId,
- _to_nest: (CollectionId, TokenId)
- ) {}
+ fn unnest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}
fn collection_tokens(&self) -> Vec<TokenId> {
vec![TokenId::default()]
pallets/fungible/src/lib.rsdiffbeforeafterboth--- a/pallets/fungible/src/lib.rs
+++ b/pallets/fungible/src/lib.rs
@@ -184,11 +184,7 @@
if balance == 0 {
<Balance<T>>::remove((collection.id, owner));
- <PalletStructure<T>>::unnest_if_nested(
- owner,
- collection.id,
- TokenId::default()
- );
+ <PalletStructure<T>>::unnest_if_nested(owner, collection.id, TokenId::default());
} else {
<Balance<T>>::insert((collection.id, owner), balance);
}
@@ -249,18 +245,14 @@
to,
collection.id,
TokenId::default(),
- nesting_budget
+ nesting_budget,
)?;
if let Some(balance_to) = balance_to {
// from != to
if balance_from == 0 {
<Balance<T>>::remove((collection.id, from));
- <PalletStructure<T>>::unnest_if_nested(
- from,
- collection.id,
- TokenId::default()
- );
+ <PalletStructure<T>>::unnest_if_nested(from, collection.id, TokenId::default());
} else {
<Balance<T>>::insert((collection.id, from), balance_from);
}
@@ -333,7 +325,11 @@
<TotalSupply<T>>::insert(collection.id, total_supply);
for (user, amount) in balances {
<Balance<T>>::insert((collection.id, &user), amount);
- <PalletStructure<T>>::nest_if_sent_to_token_unchecked(&user, collection.id, TokenId::default());
+ <PalletStructure<T>>::nest_if_sent_to_token_unchecked(
+ &user,
+ collection.id,
+ TokenId::default(),
+ );
<PalletEvm<T>>::deposit_log(
ERC20Events::Transfer {
from: H160::default(),
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -22,7 +22,7 @@
PropertyKeyPermission, PropertyValue,
};
use pallet_common::{
- CommonCollectionOperations, CommonWeightInfo, with_weight, weights::WeightInfo as _
+ CommonCollectionOperations, CommonWeightInfo, with_weight, weights::WeightInfo as _,
};
use sp_runtime::DispatchError;
use sp_std::vec::Vec;
@@ -353,19 +353,11 @@
<Pallet<T>>::check_nesting(self, sender, from, under, budget)
}
- fn nest(
- &self,
- under: TokenId,
- to_nest: (CollectionId, TokenId)
- ) {
+ fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId)) {
<Pallet<T>>::nest((self.id, under), to_nest);
}
- fn unnest(
- &self,
- under: TokenId,
- to_unnest: (CollectionId, TokenId)
- ) {
+ fn unnest(&self, under: TokenId, to_unnest: (CollectionId, TokenId)) {
<Pallet<T>>::unnest((self.id, under), to_unnest);
}
@@ -415,10 +407,7 @@
.unwrap_or_else(|| {
properties
.into_iter()
- .map(|(key, value)| Property {
- key,
- value,
- })
+ .map(|(key, value)| Property { key, value })
.collect()
})
}
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -426,11 +426,10 @@
Ok(a)
}
-fn has_token_permission<T: Config>(
- collection_id: CollectionId,
- key: &PropertyKey,
-) -> bool {
- if let Ok(token_property_permissions) = CollectionPropertyPermissions::<T>::try_get(collection_id) {
+fn has_token_permission<T: Config>(collection_id: CollectionId, key: &PropertyKey) -> bool {
+ if let Ok(token_property_permissions) =
+ CollectionPropertyPermissions::<T>::try_get(collection_id)
+ {
return token_property_permissions.contains_key(key);
}
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -164,31 +164,44 @@
fn on_runtime_upgrade() -> Weight {
if StorageVersion::get::<Pallet<T>>() < StorageVersion::new(1) {
let mut had_consts = BTreeSet::new();
- <TokenData<T>>::translate::<ItemDataVersion1<T::CrossAccountId>, _>(|(collection, token), v| {
- let mut props = vec![];
- if !v.const_data.is_empty() {
- props.push(Property {
- key: b"_old_constData".to_vec().try_into().unwrap(),
- value: v.const_data.clone().into_inner().try_into().expect("const too long"),
- });
- had_consts.insert(collection);
- }
- if !v.variable_data.is_empty() {
- props.push(Property {
- key: b"_old_variableData".to_vec().try_into().unwrap(),
- value: v.variable_data.clone().into_inner().try_into().expect("variable too long"),
- })
- }
- if !props.is_empty() {
- Self::set_scoped_token_properties(
- collection,
- token,
- PropertyScope::None,
- props.into_iter(),
- ).expect("existing token data exceeds property storage");
- }
- Some(<ItemDataVersion2<T::CrossAccountId>>::from(v))
- });
+ <TokenData<T>>::translate::<ItemDataVersion1<T::CrossAccountId>, _>(
+ |(collection, token), v| {
+ let mut props = vec![];
+ if !v.const_data.is_empty() {
+ props.push(Property {
+ key: b"_old_constData".to_vec().try_into().unwrap(),
+ value: v
+ .const_data
+ .clone()
+ .into_inner()
+ .try_into()
+ .expect("const too long"),
+ });
+ had_consts.insert(collection);
+ }
+ if !v.variable_data.is_empty() {
+ props.push(Property {
+ key: b"_old_variableData".to_vec().try_into().unwrap(),
+ value: v
+ .variable_data
+ .clone()
+ .into_inner()
+ .try_into()
+ .expect("variable too long"),
+ })
+ }
+ if !props.is_empty() {
+ Self::set_scoped_token_properties(
+ collection,
+ token,
+ PropertyScope::None,
+ props.into_iter(),
+ )
+ .expect("existing token data exceeds property storage");
+ }
+ Some(<ItemDataVersion2<T::CrossAccountId>>::from(v))
+ },
+ );
for collection in had_consts {
<PalletCommon<T>>::set_property_permission_unchecked(
collection,
@@ -199,8 +212,9 @@
collection_admin: true,
token_owner: false,
},
- }
- ).expect("failed to configure permission");
+ },
+ )
+ .expect("failed to configure permission");
}
}
@@ -263,7 +277,7 @@
collection_id: CollectionId,
token_id: TokenId,
scope: PropertyScope,
- properties: impl Iterator<Item=Property>,
+ properties: impl Iterator<Item = Property>,
) -> DispatchResult {
TokenProperties::<T>::try_mutate((collection_id, token_id), |stored_properties| {
stored_properties.try_scoped_set_from_iter(scope, properties)
@@ -347,11 +361,7 @@
<AccountBalance<T>>::insert((collection.id, token_data.owner.clone()), balance);
}
- <PalletStructure<T>>::unnest_if_nested(
- &token_data.owner,
- collection.id,
- token
- );
+ <PalletStructure<T>>::unnest_if_nested(&token_data.owner, collection.id, token);
<Owned<T>>::remove((collection.id, &token_data.owner, token));
<TokensBurnt<T>>::insert(collection.id, burnt);
@@ -589,16 +599,12 @@
to,
collection.id,
token,
- nesting_budget
+ nesting_budget,
)?;
// =========
- <PalletStructure<T>>::unnest_if_nested(
- from,
- collection.id,
- token
- );
+ <PalletStructure<T>>::unnest_if_nested(from, collection.id, token);
<TokenData<T>>::insert(
(collection.id, token),
@@ -709,7 +715,11 @@
},
);
- <PalletStructure<T>>::nest_if_sent_to_token_unchecked(&data.owner, collection.id, TokenId(token));
+ <PalletStructure<T>>::nest_if_sent_to_token_unchecked(
+ &data.owner,
+ collection.id,
+ TokenId(token),
+ );
if let Err(e) = Self::set_token_properties(
collection,
@@ -958,31 +968,24 @@
Ok(())
}
- fn nest(
- under: (CollectionId, TokenId),
- to_nest: (CollectionId, TokenId),
- ) {
- <TokenChildren<T>>::insert(
- (under.0, under.1, (to_nest.0, to_nest.1)),
- true
- );
+ fn nest(under: (CollectionId, TokenId), to_nest: (CollectionId, TokenId)) {
+ <TokenChildren<T>>::insert((under.0, under.1, (to_nest.0, to_nest.1)), true);
}
- fn unnest(
- under: (CollectionId, TokenId),
- to_unnest: (CollectionId, TokenId),
- ) {
- <TokenChildren<T>>::remove(
- (under.0, under.1, to_unnest)
- );
+ fn unnest(under: (CollectionId, TokenId), to_unnest: (CollectionId, TokenId)) {
+ <TokenChildren<T>>::remove((under.0, under.1, to_unnest));
}
fn collection_has_tokens(collection_id: CollectionId) -> bool {
- <TokenData<T>>::iter_prefix((collection_id,)).next().is_some()
+ <TokenData<T>>::iter_prefix((collection_id,))
+ .next()
+ .is_some()
}
fn token_has_children(collection_id: CollectionId, token_id: TokenId) -> bool {
- <TokenChildren<T>>::iter_prefix((collection_id, token_id)).next().is_some()
+ <TokenChildren<T>>::iter_prefix((collection_id, token_id))
+ .next()
+ .is_some()
}
/// Delegated to `create_multiple_items`
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -21,7 +21,9 @@
use sp_runtime::{DispatchError, Permill, traits::StaticLookup};
use sp_std::vec::Vec;
use up_data_structs::*;
-use pallet_common::{Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations};
+use pallet_common::{
+ Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,
+};
use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};
use pallet_evm::account::CrossAccountId;
use core::convert::AsRef;
@@ -38,18 +40,17 @@
#[frame_support::pallet]
pub mod pallet {
- use super::*;
- use pallet_evm::account;
+ use super::*;
+ use pallet_evm::account;
#[pallet::config]
- pub trait Config: frame_system::Config
- + pallet_common::Config
- + pallet_nonfungible::Config
- + account::Config {
+ pub trait Config:
+ frame_system::Config + pallet_common::Config + pallet_nonfungible::Config + account::Config
+ {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
}
- #[pallet::storage]
+ #[pallet::storage]
#[pallet::getter(fn collection_index)]
pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;
@@ -60,33 +61,33 @@
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
- CollectionCreated {
+ CollectionCreated {
issuer: T::AccountId,
collection_id: RmrkCollectionId,
},
- CollectionDestroyed {
+ CollectionDestroyed {
issuer: T::AccountId,
collection_id: RmrkCollectionId,
},
- IssuerChanged {
+ IssuerChanged {
old_issuer: T::AccountId,
new_issuer: T::AccountId,
collection_id: RmrkCollectionId,
},
- CollectionLocked {
+ CollectionLocked {
issuer: T::AccountId,
collection_id: RmrkCollectionId,
},
- NftMinted {
+ NftMinted {
owner: T::AccountId,
collection_id: RmrkCollectionId,
nft_id: RmrkNftId,
},
- NFTBurned {
+ NFTBurned {
owner: T::AccountId,
nft_id: RmrkNftId,
},
- PropertySet {
+ PropertySet {
collection_id: RmrkCollectionId,
maybe_nft_id: Option<RmrkNftId>,
key: RmrkKeyString,
@@ -96,24 +97,24 @@
#[pallet::error]
pub enum Error<T> {
- /* Unique-specific events */
- CorruptedCollectionType,
- NftTypeEncodeError,
- RmrkPropertyKeyIsTooLong,
- RmrkPropertyValueIsTooLong,
+ /* Unique-specific events */
+ CorruptedCollectionType,
+ NftTypeEncodeError,
+ RmrkPropertyKeyIsTooLong,
+ RmrkPropertyValueIsTooLong,
- /* RMRK compatible events */
- CollectionNotEmpty,
- NoAvailableCollectionId,
- NoAvailableNftId,
- CollectionUnknown,
- NoPermission,
- CollectionFullOrLocked,
+ /* RMRK compatible events */
+ CollectionNotEmpty,
+ NoAvailableCollectionId,
+ NoAvailableNftId,
+ CollectionUnknown,
+ NoPermission,
+ CollectionFullOrLocked,
}
#[pallet::call]
impl<T: Config> Pallet<T> {
- #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn create_collection(
origin: OriginFor<T>,
@@ -121,127 +122,141 @@
max: Option<u32>,
symbol: RmrkCollectionSymbol,
) -> DispatchResult {
- let sender = ensure_signed(origin)?;
+ let sender = ensure_signed(origin)?;
- let limits = CollectionLimits {
- owner_can_transfer: Some(false),
- token_limit: max,
- ..Default::default()
- };
+ let limits = CollectionLimits {
+ owner_can_transfer: Some(false),
+ token_limit: max,
+ ..Default::default()
+ };
- let data = CreateCollectionData {
- limits: Some(limits),
- token_prefix: symbol.into_inner()
- .try_into()
- .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
- ..Default::default()
- };
+ let data = CreateCollectionData {
+ limits: Some(limits),
+ token_prefix: symbol
+ .into_inner()
+ .try_into()
+ .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
+ ..Default::default()
+ };
- let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);
+ let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);
- if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
- return Err(<Error<T>>::NoAvailableCollectionId.into());
- }
+ if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
+ return Err(<Error<T>>::NoAvailableCollectionId.into());
+ }
- let collection_id = collection_id_res?;
+ let collection_id = collection_id_res?;
- <PalletCommon<T>>::set_scoped_collection_properties(
- collection_id,
- PropertyScope::Rmrk,
- [
- Self::rmrk_property(Metadata, &metadata)?,
- Self::rmrk_property(CollectionType, &misc::CollectionType::Regular)?,
- ].into_iter()
- )?;
+ <PalletCommon<T>>::set_scoped_collection_properties(
+ collection_id,
+ PropertyScope::Rmrk,
+ [
+ Self::rmrk_property(Metadata, &metadata)?,
+ Self::rmrk_property(CollectionType, &misc::CollectionType::Regular)?,
+ ]
+ .into_iter(),
+ )?;
- <CollectionIndex<T>>::mutate(|n| *n += 1);
+ <CollectionIndex<T>>::mutate(|n| *n += 1);
- Self::deposit_event(Event::CollectionCreated {
- issuer: sender,
- collection_id: collection_id.0
- });
+ Self::deposit_event(Event::CollectionCreated {
+ issuer: sender,
+ collection_id: collection_id.0,
+ });
- Ok(())
- }
+ Ok(())
+ }
- #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn destroy_collection(
origin: OriginFor<T>,
collection_id: RmrkCollectionId,
) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+ let sender = ensure_signed(origin)?;
+ let cross_sender = T::CrossAccountId::from_sub(sender.clone());
- let unique_collection_id = collection_id.into();
+ let unique_collection_id = collection_id.into();
- let collection = Self::get_typed_nft_collection(unique_collection_id, misc::CollectionType::Regular)?;
+ let collection = Self::get_typed_nft_collection(
+ unique_collection_id,
+ misc::CollectionType::Regular,
+ )?;
- ensure!(collection.total_supply() == 0, <Error<T>>::CollectionNotEmpty);
+ ensure!(
+ collection.total_supply() == 0,
+ <Error<T>>::CollectionNotEmpty
+ );
- <PalletNft<T>>::destroy_collection(collection, &cross_sender)
- .map_err(Self::map_common_err_to_proxy)?;
+ <PalletNft<T>>::destroy_collection(collection, &cross_sender)
+ .map_err(Self::map_common_err_to_proxy)?;
- Self::deposit_event(Event::CollectionDestroyed { issuer: sender, collection_id });
+ Self::deposit_event(Event::CollectionDestroyed {
+ issuer: sender,
+ collection_id,
+ });
- Ok(())
- }
+ Ok(())
+ }
- #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn change_collection_issuer(
origin: OriginFor<T>,
collection_id: RmrkCollectionId,
new_issuer: <T::Lookup as StaticLookup>::Source,
) -> DispatchResult {
- let sender = ensure_signed(origin)?;
+ let sender = ensure_signed(origin)?;
- let new_issuer = T::Lookup::lookup(new_issuer)?;
+ let new_issuer = T::Lookup::lookup(new_issuer)?;
- Self::change_collection_owner(
- collection_id.into(),
- misc::CollectionType::Regular,
- sender.clone(),
- new_issuer.clone()
- )?;
+ Self::change_collection_owner(
+ collection_id.into(),
+ misc::CollectionType::Regular,
+ sender.clone(),
+ new_issuer.clone(),
+ )?;
- Self::deposit_event(Event::IssuerChanged {
+ Self::deposit_event(Event::IssuerChanged {
old_issuer: sender,
new_issuer,
collection_id,
});
- Ok(())
- }
+ Ok(())
+ }
- #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn lock_collection(
origin: OriginFor<T>,
collection_id: RmrkCollectionId,
) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+ let sender = ensure_signed(origin)?;
+ let cross_sender = T::CrossAccountId::from_sub(sender.clone());
- let collection = Self::get_typed_nft_collection(
- collection_id.into(),
- misc::CollectionType::Regular
- )?;
+ let collection = Self::get_typed_nft_collection(
+ collection_id.into(),
+ misc::CollectionType::Regular,
+ )?;
- Self::check_collection_owner(&collection, &cross_sender)?;
+ Self::check_collection_owner(&collection, &cross_sender)?;
- let token_count = collection.total_supply();
+ let token_count = collection.total_supply();
- let mut collection = collection.into_inner();
- collection.limits.token_limit = Some(token_count);
- collection.save()?;
+ let mut collection = collection.into_inner();
+ collection.limits.token_limit = Some(token_count);
+ collection.save()?;
- Self::deposit_event(Event::CollectionLocked { issuer: sender, collection_id });
+ Self::deposit_event(Event::CollectionLocked {
+ issuer: sender,
+ collection_id,
+ });
- Ok(())
- }
+ Ok(())
+ }
- #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn mint_nft(
origin: OriginFor<T>,
@@ -251,47 +266,49 @@
royalty_amount: Option<Permill>,
metadata: RmrkString,
) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let sender = T::CrossAccountId::from_sub(sender);
- let cross_owner = T::CrossAccountId::from_sub(owner.clone());
+ let sender = ensure_signed(origin)?;
+ let sender = T::CrossAccountId::from_sub(sender);
+ let cross_owner = T::CrossAccountId::from_sub(owner.clone());
- let royalty_info = royalty_amount.map(|amount| rmrk::RoyaltyInfo {
- recipient: recipient.unwrap_or_else(|| owner.clone()),
- amount
- });
+ let royalty_info = royalty_amount.map(|amount| rmrk::RoyaltyInfo {
+ recipient: recipient.unwrap_or_else(|| owner.clone()),
+ amount,
+ });
- let collection = Self::get_typed_nft_collection(
- collection_id.into(),
- misc::CollectionType::Regular,
- )?;
+ let collection = Self::get_typed_nft_collection(
+ collection_id.into(),
+ misc::CollectionType::Regular,
+ )?;
- let nft_id = Self::create_nft(
- &sender,
- &cross_owner,
- &collection,
- NftType::Regular,
- [
- Self::rmrk_property(RoyaltyInfo, &royalty_info)?,
- Self::rmrk_property(Metadata, &metadata)?,
- Self::rmrk_property(Equipped, &false)?,
- Self::rmrk_property(ResourceCollection, &None::<CollectionId>)?,
- Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,
- ].into_iter()
- ).map_err(|err| match err {
- DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),
- err => Self::map_common_err_to_proxy(err)
- })?;
+ let nft_id = Self::create_nft(
+ &sender,
+ &cross_owner,
+ &collection,
+ NftType::Regular,
+ [
+ Self::rmrk_property(RoyaltyInfo, &royalty_info)?,
+ Self::rmrk_property(Metadata, &metadata)?,
+ Self::rmrk_property(Equipped, &false)?,
+ Self::rmrk_property(ResourceCollection, &None::<CollectionId>)?,
+ Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,
+ ]
+ .into_iter(),
+ )
+ .map_err(|err| match err {
+ DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),
+ err => Self::map_common_err_to_proxy(err),
+ })?;
- Self::deposit_event(Event::NftMinted {
- owner,
- collection_id,
- nft_id: nft_id.0
- });
+ Self::deposit_event(Event::NftMinted {
+ owner,
+ collection_id,
+ nft_id: nft_id.0,
+ });
- Ok(())
- }
+ Ok(())
+ }
- #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn burn_nft(
origin: OriginFor<T>,
@@ -299,21 +316,24 @@
nft_id: RmrkNftId,
) -> DispatchResult {
let sender = ensure_signed(origin)?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+ let cross_sender = T::CrossAccountId::from_sub(sender.clone());
- Self::destroy_nft(
- cross_sender,
- collection_id.into(),
- misc::CollectionType::Regular,
- nft_id.into()
- )?;
+ Self::destroy_nft(
+ cross_sender,
+ collection_id.into(),
+ misc::CollectionType::Regular,
+ nft_id.into(),
+ )?;
- Self::deposit_event(Event::NFTBurned { owner: sender, nft_id });
+ Self::deposit_event(Event::NFTBurned {
+ owner: sender,
+ nft_id,
+ });
- Ok(())
- }
+ Ok(())
+ }
- #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
pub fn set_property(
origin: OriginFor<T>,
@@ -322,323 +342,346 @@
key: RmrkKeyString,
value: RmrkValueString,
) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let sender = T::CrossAccountId::from_sub(sender);
+ let sender = ensure_signed(origin)?;
+ let sender = T::CrossAccountId::from_sub(sender);
- let collection_id: CollectionId = rmrk_collection_id.into();
+ let collection_id: CollectionId = rmrk_collection_id.into();
- match maybe_nft_id {
- Some(nft_id) => {
- let token_id: TokenId = nft_id.into();
+ match maybe_nft_id {
+ Some(nft_id) => {
+ let token_id: TokenId = nft_id.into();
- Self::ensure_nft_owner(collection_id, token_id, &sender)?;
- Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;
+ Self::ensure_nft_owner(collection_id, token_id, &sender)?;
+ Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;
- <PalletNft<T>>::set_scoped_token_property(
- collection_id,
- token_id,
- PropertyScope::Rmrk,
- Self::rmrk_property(UserProperty(key.as_slice()), &value)?
- )?;
- },
- None => {
- let collection = Self::get_typed_nft_collection(
- collection_id,
- misc::CollectionType::Regular
- )?;
+ <PalletNft<T>>::set_scoped_token_property(
+ collection_id,
+ token_id,
+ PropertyScope::Rmrk,
+ Self::rmrk_property(UserProperty(key.as_slice()), &value)?,
+ )?;
+ }
+ None => {
+ let collection = Self::get_typed_nft_collection(
+ collection_id,
+ misc::CollectionType::Regular,
+ )?;
- Self::check_collection_owner(&collection, &sender)?;
+ Self::check_collection_owner(&collection, &sender)?;
- <PalletCommon<T>>::set_scoped_collection_property(
- collection_id,
- PropertyScope::Rmrk,
- Self::rmrk_property(UserProperty(key.as_slice()), &value)?
- )?;
- }
- }
+ <PalletCommon<T>>::set_scoped_collection_property(
+ collection_id,
+ PropertyScope::Rmrk,
+ Self::rmrk_property(UserProperty(key.as_slice()), &value)?,
+ )?;
+ }
+ }
- Self::deposit_event(
- Event::PropertySet {
- collection_id: rmrk_collection_id,
- maybe_nft_id,
- key,
- value
- }
- );
+ Self::deposit_event(Event::PropertySet {
+ collection_id: rmrk_collection_id,
+ maybe_nft_id,
+ key,
+ value,
+ });
- Ok(())
- }
+ Ok(())
+ }
}
}
impl<T: Config> Pallet<T> {
- pub fn rmrk_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {
- let key = rmrk_key.to_key::<T>()?;
+ pub fn rmrk_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {
+ let key = rmrk_key.to_key::<T>()?;
- let scoped_key = PropertyScope::Rmrk.apply(key)
- .map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;
+ let scoped_key = PropertyScope::Rmrk
+ .apply(key)
+ .map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;
- Ok(scoped_key)
- }
+ Ok(scoped_key)
+ }
- pub fn rmrk_property<E: Encode>(rmrk_key: RmrkProperty, value: &E) -> Result<Property, DispatchError> {
- let key = rmrk_key.to_key::<T>()?;
+ pub fn rmrk_property<E: Encode>(
+ rmrk_key: RmrkProperty,
+ value: &E,
+ ) -> Result<Property, DispatchError> {
+ let key = rmrk_key.to_key::<T>()?;
- let value = value.encode()
- .try_into()
- .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;
+ let value = value
+ .encode()
+ .try_into()
+ .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;
- let property = Property {
- key,
- value,
- };
+ let property = Property { key, value };
- Ok(property)
- }
+ Ok(property)
+ }
- pub fn create_nft(
- sender: &T::CrossAccountId,
- owner: &T::CrossAccountId,
- collection: &NonfungibleHandle<T>,
- nft_type: NftType,
- properties: impl Iterator<Item=Property>
- ) -> Result<TokenId, DispatchError> {
- todo!("store nft type");
- let data = CreateNftExData {
- properties: BoundedVec::default(),
- owner: owner.clone(),
- };
+ pub fn create_nft(
+ sender: &T::CrossAccountId,
+ owner: &T::CrossAccountId,
+ collection: &NonfungibleHandle<T>,
+ nft_type: NftType,
+ properties: impl Iterator<Item = Property>,
+ ) -> Result<TokenId, DispatchError> {
+ todo!("store nft type");
+ let data = CreateNftExData {
+ properties: BoundedVec::default(),
+ owner: owner.clone(),
+ };
- let budget = budget::Value::new(2);
+ let budget = budget::Value::new(2);
- <PalletNft<T>>::create_item(
- collection,
- sender,
- data,
- &budget,
- )?;
+ <PalletNft<T>>::create_item(collection, sender, data, &budget)?;
- let nft_id = <PalletNft<T>>::current_token_id(collection.id);
+ let nft_id = <PalletNft<T>>::current_token_id(collection.id);
- <PalletNft<T>>::set_scoped_token_properties(
- collection.id,
- nft_id,
- PropertyScope::Rmrk,
- properties
- )?;
+ <PalletNft<T>>::set_scoped_token_properties(
+ collection.id,
+ nft_id,
+ PropertyScope::Rmrk,
+ properties,
+ )?;
- Ok(nft_id)
- }
+ Ok(nft_id)
+ }
- fn destroy_nft(
- sender: T::CrossAccountId,
- collection_id: CollectionId,
- collection_type: misc::CollectionType,
- token_id: TokenId
- ) -> DispatchResult {
- let collection = Self::get_typed_nft_collection(
- collection_id,
- collection_type
- )?;
+ fn destroy_nft(
+ sender: T::CrossAccountId,
+ collection_id: CollectionId,
+ collection_type: misc::CollectionType,
+ token_id: TokenId,
+ ) -> DispatchResult {
+ let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;
- <PalletNft<T>>::burn(&collection, &sender, token_id)
- .map_err(Self::map_common_err_to_proxy)?;
+ <PalletNft<T>>::burn(&collection, &sender, token_id)
+ .map_err(Self::map_common_err_to_proxy)?;
- Ok(())
- }
+ Ok(())
+ }
- fn change_collection_owner(
- collection_id: CollectionId,
- collection_type: misc::CollectionType,
- sender: T::AccountId,
- new_owner: T::AccountId,
- ) -> DispatchResult {
- let collection = Self::get_typed_nft_collection(
- collection_id,
- collection_type
- )?;
- Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;
+ fn change_collection_owner(
+ collection_id: CollectionId,
+ collection_type: misc::CollectionType,
+ sender: T::AccountId,
+ new_owner: T::AccountId,
+ ) -> DispatchResult {
+ let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;
+ Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;
- let mut collection = collection.into_inner();
+ let mut collection = collection.into_inner();
- collection.owner = new_owner;
- collection.save()
- }
+ collection.owner = new_owner;
+ collection.save()
+ }
- fn check_collection_owner(collection: &NonfungibleHandle<T>, account: &T::CrossAccountId) -> DispatchResult {
- collection.check_is_owner(account)
- .map_err(Self::map_common_err_to_proxy)
- }
+ fn check_collection_owner(
+ collection: &NonfungibleHandle<T>,
+ account: &T::CrossAccountId,
+ ) -> DispatchResult {
+ collection
+ .check_is_owner(account)
+ .map_err(Self::map_common_err_to_proxy)
+ }
- pub fn last_collection_idx() -> RmrkCollectionId {
- <CollectionIndex<T>>::get()
- }
+ pub fn last_collection_idx() -> RmrkCollectionId {
+ <CollectionIndex<T>>::get()
+ }
- pub fn get_nft_collection(collection_id: CollectionId) -> Result<NonfungibleHandle<T>, DispatchError> {
- let collection = <CollectionHandle<T>>::try_get(collection_id)
- .map_err(|_| <Error<T>>::CollectionUnknown)?;
+ pub fn get_nft_collection(
+ collection_id: CollectionId,
+ ) -> Result<NonfungibleHandle<T>, DispatchError> {
+ let collection = <CollectionHandle<T>>::try_get(collection_id)
+ .map_err(|_| <Error<T>>::CollectionUnknown)?;
- match collection.mode {
- CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),
- _ => Err(<Error<T>>::CollectionUnknown.into())
- }
- }
+ match collection.mode {
+ CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),
+ _ => Err(<Error<T>>::CollectionUnknown.into()),
+ }
+ }
- pub fn collection_exists(collection_id: CollectionId) -> bool {
- <CollectionHandle<T>>::try_get(collection_id).is_ok()
- }
+ pub fn collection_exists(collection_id: CollectionId) -> bool {
+ <CollectionHandle<T>>::try_get(collection_id).is_ok()
+ }
- pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {
- <TokenData<T>>::contains_key((collection_id, nft_id))
- }
+ pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {
+ <TokenData<T>>::contains_key((collection_id, nft_id))
+ }
- pub fn get_collection_property(collection_id: CollectionId, key: RmrkProperty) -> Result<PropertyValue, DispatchError> {
- let collection_property = <PalletCommon<T>>::collection_properties(collection_id)
- .get(&Self::rmrk_property_key(key)?)
- .ok_or(<Error<T>>::CollectionUnknown)?
- .clone();
+ pub fn get_collection_property(
+ collection_id: CollectionId,
+ key: RmrkProperty,
+ ) -> Result<PropertyValue, DispatchError> {
+ let collection_property = <PalletCommon<T>>::collection_properties(collection_id)
+ .get(&Self::rmrk_property_key(key)?)
+ .ok_or(<Error<T>>::CollectionUnknown)?
+ .clone();
- Ok(collection_property)
- }
+ Ok(collection_property)
+ }
- pub fn get_collection_type(collection_id: CollectionId) -> Result<misc::CollectionType, DispatchError> {
- let value = Self::get_collection_property(collection_id, CollectionType)?;
+ pub fn get_collection_type(
+ collection_id: CollectionId,
+ ) -> Result<misc::CollectionType, DispatchError> {
+ let value = Self::get_collection_property(collection_id, CollectionType)?;
- let mut value = value.as_slice();
+ let mut value = value.as_slice();
- misc::CollectionType::decode(&mut value)
- .map_err(|_| <Error<T>>::CorruptedCollectionType.into())
- }
+ misc::CollectionType::decode(&mut value)
+ .map_err(|_| <Error<T>>::CorruptedCollectionType.into())
+ }
- pub fn ensure_collection_type(collection_id: CollectionId, collection_type: misc::CollectionType) -> DispatchResult {
- let actual_type = Self::get_collection_type(collection_id)?;
- ensure!(actual_type == collection_type, <CommonError<T>>::NoPermission);
+ pub fn ensure_collection_type(
+ collection_id: CollectionId,
+ collection_type: misc::CollectionType,
+ ) -> DispatchResult {
+ let actual_type = Self::get_collection_type(collection_id)?;
+ ensure!(
+ actual_type == collection_type,
+ <CommonError<T>>::NoPermission
+ );
- Ok(())
- }
+ Ok(())
+ }
- pub fn get_nft_property(collection_id: CollectionId, nft_id: TokenId, key: RmrkProperty) -> Result<PropertyValue, DispatchError> {
- let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))
- .get(&Self::rmrk_property_key(key)?)
- .ok_or(<Error<T>>::NoAvailableNftId)?
- .clone();
+ pub fn get_nft_property(
+ collection_id: CollectionId,
+ nft_id: TokenId,
+ key: RmrkProperty,
+ ) -> Result<PropertyValue, DispatchError> {
+ let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))
+ .get(&Self::rmrk_property_key(key)?)
+ .ok_or(<Error<T>>::NoAvailableNftId)?
+ .clone();
- Ok(nft_property)
- }
+ Ok(nft_property)
+ }
- pub fn get_nft_type(_collection_id: CollectionId, _token_id: TokenId) -> Result<NftType, DispatchError> {
- todo!("should get it from properties?")
- }
+ pub fn get_nft_type(
+ _collection_id: CollectionId,
+ _token_id: TokenId,
+ ) -> Result<NftType, DispatchError> {
+ todo!("should get it from properties?")
+ }
- pub fn ensure_nft_type(collection_id: CollectionId, token_id: TokenId, nft_type: NftType) -> DispatchResult {
- let actual_type = Self::get_nft_type(collection_id, token_id)?;
- ensure!(actual_type == nft_type, <Error<T>>::NoPermission);
+ pub fn ensure_nft_type(
+ collection_id: CollectionId,
+ token_id: TokenId,
+ nft_type: NftType,
+ ) -> DispatchResult {
+ let actual_type = Self::get_nft_type(collection_id, token_id)?;
+ ensure!(actual_type == nft_type, <Error<T>>::NoPermission);
- Ok(())
- }
+ Ok(())
+ }
- pub fn ensure_nft_owner(
- collection_id: CollectionId,
- token_id: TokenId,
- possible_owner: &T::CrossAccountId
- ) -> DispatchResult {
- let token_data = <TokenData<T>>::get((collection_id, token_id))
- .ok_or(<Error<T>>::NoAvailableNftId)?;
+ pub fn ensure_nft_owner(
+ collection_id: CollectionId,
+ token_id: TokenId,
+ possible_owner: &T::CrossAccountId,
+ ) -> DispatchResult {
+ let token_data =
+ <TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;
- ensure!(token_data.owner == *possible_owner, <Error<T>>::NoPermission);
+ ensure!(
+ token_data.owner == *possible_owner,
+ <Error<T>>::NoPermission
+ );
- Ok(())
- }
+ Ok(())
+ }
- pub fn filter_user_properties<Key, Value, R, Mapper>(
- collection_id: CollectionId,
- token_id: Option<TokenId>,
- filter_keys: Option<Vec<RmrkPropertyKey>>,
- mapper: Mapper,
- ) -> Result<Vec<R>, DispatchError>
- where
- Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
- Value: Decode + Default,
- Mapper: Fn(Key, Value) -> R
- {
- filter_keys.map(|keys| {
- let properties = keys.into_iter()
- .filter_map(|key| {
- let key: Key = key.try_into().ok()?;
+ pub fn filter_user_properties<Key, Value, R, Mapper>(
+ collection_id: CollectionId,
+ token_id: Option<TokenId>,
+ filter_keys: Option<Vec<RmrkPropertyKey>>,
+ mapper: Mapper,
+ ) -> Result<Vec<R>, DispatchError>
+ where
+ Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
+ Value: Decode + Default,
+ Mapper: Fn(Key, Value) -> R,
+ {
+ filter_keys
+ .map(|keys| {
+ let properties = keys
+ .into_iter()
+ .filter_map(|key| {
+ let key: Key = key.try_into().ok()?;
- let value = match token_id {
- Some(token_id) => Self::get_nft_property(
- collection_id,
- token_id,
- UserProperty(key.as_ref())
- ),
- None => Self::get_collection_property(
- collection_id,
- UserProperty(key.as_ref())
- )
- }.ok()?.decode_or_default();
+ let value = match token_id {
+ Some(token_id) => Self::get_nft_property(
+ collection_id,
+ token_id,
+ UserProperty(key.as_ref()),
+ ),
+ None => Self::get_collection_property(
+ collection_id,
+ UserProperty(key.as_ref()),
+ ),
+ }
+ .ok()?
+ .decode_or_default();
- Some(mapper(key, value))
- })
- .collect();
+ Some(mapper(key, value))
+ })
+ .collect();
- Ok(properties)
- }).unwrap_or_else(|| {
- let properties = Self::iterate_user_properties(collection_id, token_id, mapper)?
- .collect();
+ Ok(properties)
+ })
+ .unwrap_or_else(|| {
+ let properties =
+ Self::iterate_user_properties(collection_id, token_id, mapper)?.collect();
- Ok(properties)
- })
- }
+ Ok(properties)
+ })
+ }
- pub fn iterate_user_properties<Key, Value, R, Mapper>(
- collection_id: CollectionId,
- token_id: Option<TokenId>,
- mapper: Mapper,
- ) -> Result<impl Iterator<Item=R>, DispatchError>
- where
- Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
- Value: Decode + Default,
- Mapper: Fn(Key, Value) -> R
- {
- let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;
+ pub fn iterate_user_properties<Key, Value, R, Mapper>(
+ collection_id: CollectionId,
+ token_id: Option<TokenId>,
+ mapper: Mapper,
+ ) -> Result<impl Iterator<Item = R>, DispatchError>
+ where
+ Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
+ Value: Decode + Default,
+ Mapper: Fn(Key, Value) -> R,
+ {
+ let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;
- let properties = match token_id {
- Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),
- None => <PalletCommon<T>>::collection_properties(collection_id)
- };
+ let properties = match token_id {
+ Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),
+ None => <PalletCommon<T>>::collection_properties(collection_id),
+ };
- let properties = properties
- .into_iter()
- .filter_map(move |(key, value)| {
- let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;
+ let properties = properties.into_iter().filter_map(move |(key, value)| {
+ let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;
- let key: Key = key.to_vec().try_into().ok()?;
- let value: Value = value.decode_or_default();
+ let key: Key = key.to_vec().try_into().ok()?;
+ let value: Value = value.decode_or_default();
- Some(mapper(key, value))
- });
+ Some(mapper(key, value))
+ });
- Ok(properties)
- }
+ Ok(properties)
+ }
- pub fn get_typed_nft_collection(
- collection_id: CollectionId,
- collection_type: misc::CollectionType
- ) -> Result<NonfungibleHandle<T>, DispatchError> {
- Self::ensure_collection_type(collection_id, collection_type)?;
+ pub fn get_typed_nft_collection(
+ collection_id: CollectionId,
+ collection_type: misc::CollectionType,
+ ) -> Result<NonfungibleHandle<T>, DispatchError> {
+ Self::ensure_collection_type(collection_id, collection_type)?;
- Self::get_nft_collection(collection_id)
- }
+ Self::get_nft_collection(collection_id)
+ }
- fn map_common_err_to_proxy(err: DispatchError) -> DispatchError {
- map_common_err_to_proxy! {
- match err {
- NoPermission => NoPermission,
- CollectionTokenLimitExceeded => CollectionFullOrLocked,
- PublicMintingNotAllowed => NoPermission,
- TokenNotFound => NoAvailableNftId
- }
- }
- }
+ fn map_common_err_to_proxy(err: DispatchError) -> DispatchError {
+ map_common_err_to_proxy! {
+ match err {
+ NoPermission => NoPermission,
+ CollectionTokenLimitExceeded => CollectionFullOrLocked,
+ PublicMintingNotAllowed => NoPermission,
+ TokenNotFound => NoAvailableNftId
+ }
+ }
+ }
}
pallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/misc.rs
+++ b/pallets/proxy-rmrk-core/src/misc.rs
@@ -15,41 +15,42 @@
}
pub trait RmrkDecode<T: Decode + Default, S> {
- fn decode_or_default(&self) -> T;
+ fn decode_or_default(&self) -> T;
}
impl<T: Decode + Default, S> RmrkDecode<T, S> for BoundedVec<u8, S> {
- fn decode_or_default(&self) -> T {
- let mut value = self.as_slice();
+ fn decode_or_default(&self) -> T {
+ let mut value = self.as_slice();
- T::decode(&mut value).unwrap_or_default()
- }
+ T::decode(&mut value).unwrap_or_default()
+ }
}
pub trait RmrkRebind<T, S> {
- fn rebind(&self) -> BoundedVec<u8, S>;
+ fn rebind(&self) -> BoundedVec<u8, S>;
}
-impl<T, S> RmrkRebind<T, S> for BoundedVec<u8, T> where BoundedVec<u8, S>: TryFrom<Vec<u8>> {
- fn rebind(&self) -> BoundedVec<u8, S> {
- BoundedVec::<u8, S>::try_from(
- self.clone().into_inner()
- ).unwrap_or_default()
- }
+impl<T, S> RmrkRebind<T, S> for BoundedVec<u8, T>
+where
+ BoundedVec<u8, S>: TryFrom<Vec<u8>>,
+{
+ fn rebind(&self) -> BoundedVec<u8, S> {
+ BoundedVec::<u8, S>::try_from(self.clone().into_inner()).unwrap_or_default()
+ }
}
#[derive(Encode, Decode, PartialEq, Eq)]
pub enum CollectionType {
- Regular,
- Resource,
- Base,
+ Regular,
+ Resource,
+ Base,
}
#[derive(Encode, Decode, PartialEq, Eq)]
pub enum NftType {
- Regular,
- Resource,
- FixedPart,
- SlotPart,
- Theme
+ Regular,
+ Resource,
+ FixedPart,
+ SlotPart,
+ Theme,
}
pallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/property.rs
+++ b/pallets/proxy-rmrk-core/src/property.rs
@@ -2,38 +2,38 @@
use core::convert::AsRef;
pub enum RmrkProperty<'r> {
- Metadata,
- CollectionType,
- RoyaltyInfo,
- Equipped,
- ResourceCollection,
- ResourcePriorities,
- ResourceType,
- PendingResourceAccept,
- PendingResourceRemoval,
- Parts,
- Base,
- Src,
- Slot,
- License,
- Thumb,
- EquippedNft,
- BaseType,
- ExternalPartId,
- EquippableList,
- ZIndex,
- ThemeName,
- ThemeInherit,
- UserProperty(&'r [u8]),
+ Metadata,
+ CollectionType,
+ RoyaltyInfo,
+ Equipped,
+ ResourceCollection,
+ ResourcePriorities,
+ ResourceType,
+ PendingResourceAccept,
+ PendingResourceRemoval,
+ Parts,
+ Base,
+ Src,
+ Slot,
+ License,
+ Thumb,
+ EquippedNft,
+ BaseType,
+ ExternalPartId,
+ EquippableList,
+ ZIndex,
+ ThemeName,
+ ThemeInherit,
+ UserProperty(&'r [u8]),
}
impl<'r> RmrkProperty<'r> {
- pub fn to_key<T: Config>(self) -> Result<PropertyKey, Error<T>> {
- fn get_bytes<T: AsRef<[u8]>>(container: &T) -> &[u8] {
- container.as_ref()
- }
+ pub fn to_key<T: Config>(self) -> Result<PropertyKey, Error<T>> {
+ fn get_bytes<T: AsRef<[u8]>>(container: &T) -> &[u8] {
+ container.as_ref()
+ }
- macro_rules! key {
+ macro_rules! key {
($($component:expr),+) => {
PropertyKey::try_from([$(key!(@ &$component)),+].concat())
.map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)
@@ -44,30 +44,30 @@
};
}
- match self {
- Self::Metadata => key!("metadata"),
- Self::CollectionType => key!("collection-type"),
- Self::RoyaltyInfo => key!("royalty-info"),
- Self::Equipped => key!("equipped"),
- Self::ResourceCollection => key!("resource-collection"),
- Self::ResourcePriorities => key!("resource-priorities"),
- Self::ResourceType => key!("resource-type"),
- Self::PendingResourceAccept => key!("pending-accept"),
- Self::PendingResourceRemoval => key!("pending-removal"),
- Self::Parts => key!("parts"),
- Self::Base => key!("base"),
- Self::Src => key!("src"),
- Self::Slot => key!("slot"),
- Self::License => key!("license"),
- Self::Thumb => key!("thumb"),
- Self::EquippedNft => key!("equipped-nft"),
- Self::BaseType => key!("base-type"),
- Self::ExternalPartId => key!("ext-part-id"),
- Self::EquippableList => key!("equippable-list"),
- Self::ZIndex => key!("z-index"),
- Self::ThemeName => key!("theme-name"),
- Self::ThemeInherit => key!("theme-inherit"),
- Self::UserProperty(name) => key!("userprop-", name),
- }
- }
+ match self {
+ Self::Metadata => key!("metadata"),
+ Self::CollectionType => key!("collection-type"),
+ Self::RoyaltyInfo => key!("royalty-info"),
+ Self::Equipped => key!("equipped"),
+ Self::ResourceCollection => key!("resource-collection"),
+ Self::ResourcePriorities => key!("resource-priorities"),
+ Self::ResourceType => key!("resource-type"),
+ Self::PendingResourceAccept => key!("pending-accept"),
+ Self::PendingResourceRemoval => key!("pending-removal"),
+ Self::Parts => key!("parts"),
+ Self::Base => key!("base"),
+ Self::Src => key!("src"),
+ Self::Slot => key!("slot"),
+ Self::License => key!("license"),
+ Self::Thumb => key!("thumb"),
+ Self::EquippedNft => key!("equipped-nft"),
+ Self::BaseType => key!("base-type"),
+ Self::ExternalPartId => key!("ext-part-id"),
+ Self::EquippableList => key!("equippable-list"),
+ Self::ZIndex => key!("z-index"),
+ Self::ThemeName => key!("theme-name"),
+ Self::ThemeInherit => key!("theme-inherit"),
+ Self::UserProperty(name) => key!("userprop-", name),
+ }
+ }
}
pallets/proxy-rmrk-equip/src/lib.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-equip/src/lib.rs
+++ b/pallets/proxy-rmrk-equip/src/lib.rs
@@ -21,7 +21,11 @@
use sp_runtime::DispatchError;
use up_data_structs::*;
use pallet_common::{Pallet as PalletCommon, Error as CommonError};
-use pallet_rmrk_core::{Pallet as PalletCore, misc::{self, *}, property::RmrkProperty::*};
+use pallet_rmrk_core::{
+ Pallet as PalletCore,
+ misc::{self, *},
+ property::RmrkProperty::*,
+};
use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle};
use pallet_evm::account::CrossAccountId;
@@ -29,212 +33,206 @@
#[frame_support::pallet]
pub mod pallet {
- use super::*;
+ use super::*;
#[pallet::config]
- pub trait Config: frame_system::Config
- + pallet_rmrk_core::Config {
+ pub trait Config: frame_system::Config + pallet_rmrk_core::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
}
- #[pallet::storage]
+ #[pallet::storage]
#[pallet::getter(fn internal_part_id)]
- pub type InernalPartId<T: Config> = StorageDoubleMap<
- _,
- Twox64Concat,
- CollectionId,
- Twox64Concat,
- RmrkPartId,
- TokenId
- >;
+ pub type InernalPartId<T: Config> =
+ StorageDoubleMap<_, Twox64Concat, CollectionId, Twox64Concat, RmrkPartId, TokenId>;
- #[pallet::storage]
+ #[pallet::storage]
#[pallet::getter(fn base_has_default_theme)]
- pub type BaseHasDefaultTheme<T: Config> = StorageMap<
- _,
- Twox64Concat,
- CollectionId,
- bool,
- ValueQuery
- >;
+ pub type BaseHasDefaultTheme<T: Config> =
+ StorageMap<_, Twox64Concat, CollectionId, bool, ValueQuery>;
- #[pallet::pallet]
+ #[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
- BaseCreated {
+ BaseCreated {
issuer: T::AccountId,
base_id: RmrkBaseId,
},
- }
+ }
- #[pallet::error]
+ #[pallet::error]
pub enum Error<T> {
- PermissionError,
- NoAvailableBaseId,
- NoAvailablePartId,
- BaseDoesntExist,
- NeedsDefaultThemeFirst,
- }
+ PermissionError,
+ NoAvailableBaseId,
+ NoAvailablePartId,
+ BaseDoesntExist,
+ NeedsDefaultThemeFirst,
+ }
- #[pallet::call]
+ #[pallet::call]
impl<T: Config> Pallet<T> {
- #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
- #[transactional]
+ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ #[transactional]
pub fn create_base(
origin: OriginFor<T>,
base_type: RmrkString,
symbol: RmrkString,
parts: BoundedVec<RmrkPartType, RmrkPartsLimit>,
) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+ let sender = ensure_signed(origin)?;
+ let cross_sender = T::CrossAccountId::from_sub(sender.clone());
- let data = CreateCollectionData {
- limits: None,
- token_prefix: symbol.into_inner()
- .try_into()
- .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
- ..Default::default()
- };
+ let data = CreateCollectionData {
+ limits: None,
+ token_prefix: symbol
+ .into_inner()
+ .try_into()
+ .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
+ ..Default::default()
+ };
- let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);
+ let collection_id_res = <PalletNft<T>>::init_collection(sender.clone(), data);
- if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
- return Err(<Error<T>>::NoAvailableBaseId.into());
- }
+ if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
+ return Err(<Error<T>>::NoAvailableBaseId.into());
+ }
- let collection_id = collection_id_res?;
+ let collection_id = collection_id_res?;
- <PalletCommon<T>>::set_scoped_collection_properties(
- collection_id,
- PropertyScope::Rmrk,
- [
- <PalletCore<T>>::rmrk_property(CollectionType, &misc::CollectionType::Base)?,
- <PalletCore<T>>::rmrk_property(BaseType, &base_type)?,
- ].into_iter()
- )?;
+ <PalletCommon<T>>::set_scoped_collection_properties(
+ collection_id,
+ PropertyScope::Rmrk,
+ [
+ <PalletCore<T>>::rmrk_property(CollectionType, &misc::CollectionType::Base)?,
+ <PalletCore<T>>::rmrk_property(BaseType, &base_type)?,
+ ]
+ .into_iter(),
+ )?;
- let collection = <PalletCore<T>>::get_nft_collection(collection_id)?;
+ let collection = <PalletCore<T>>::get_nft_collection(collection_id)?;
- for part in parts {
- let part_id = part.id();
- let part_token_id = Self::create_part(
- &cross_sender,
- &collection,
- part
- )?;
+ for part in parts {
+ let part_id = part.id();
+ let part_token_id = Self::create_part(&cross_sender, &collection, part)?;
- <InernalPartId<T>>::insert(collection_id, part_id, part_token_id);
+ <InernalPartId<T>>::insert(collection_id, part_id, part_token_id);
- <PalletNft<T>>::set_scoped_token_property(
- collection_id,
- part_token_id,
- PropertyScope::Rmrk,
- <PalletCore<T>>::rmrk_property(ExternalPartId, &part_id)?
- )?;
- }
+ <PalletNft<T>>::set_scoped_token_property(
+ collection_id,
+ part_token_id,
+ PropertyScope::Rmrk,
+ <PalletCore<T>>::rmrk_property(ExternalPartId, &part_id)?,
+ )?;
+ }
- Self::deposit_event(Event::BaseCreated { issuer: sender, base_id: collection_id.0 });
+ Self::deposit_event(Event::BaseCreated {
+ issuer: sender,
+ base_id: collection_id.0,
+ });
- Ok(())
- }
+ Ok(())
+ }
- #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
- #[transactional]
+ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ #[transactional]
pub fn theme_add(
origin: OriginFor<T>,
base_id: RmrkBaseId,
theme: RmrkTheme,
) -> DispatchResult {
- let sender = ensure_signed(origin)?;
+ let sender = ensure_signed(origin)?;
- let sender = T::CrossAccountId::from_sub(sender);
- let owner = &sender;
+ let sender = T::CrossAccountId::from_sub(sender);
+ let owner = &sender;
- let collection_id: CollectionId = base_id.into();
+ let collection_id: CollectionId = base_id.into();
- let collection = <PalletCore<T>>::get_typed_nft_collection(
- collection_id,
- misc::CollectionType::Base
- ).map_err(|_| <Error<T>>::BaseDoesntExist)?;
+ let collection = <PalletCore<T>>::get_typed_nft_collection(
+ collection_id,
+ misc::CollectionType::Base,
+ )
+ .map_err(|_| <Error<T>>::BaseDoesntExist)?;
- if theme.name.as_slice() == b"default" {
- <BaseHasDefaultTheme<T>>::insert(collection_id, true);
- } else if !Self::base_has_default_theme(collection_id) {
- return Err(<Error<T>>::NeedsDefaultThemeFirst.into());
- }
+ if theme.name.as_slice() == b"default" {
+ <BaseHasDefaultTheme<T>>::insert(collection_id, true);
+ } else if !Self::base_has_default_theme(collection_id) {
+ return Err(<Error<T>>::NeedsDefaultThemeFirst.into());
+ }
- let token_id = <PalletCore<T>>::create_nft(
- &sender,
- owner,
- &collection,
- NftType::Theme,
- [
- <PalletCore<T>>::rmrk_property(ThemeName, &theme.name)?,
- <PalletCore<T>>::rmrk_property(ThemeInherit, &theme.inherit)?
- ].into_iter()
- ).map_err(|_| <Error<T>>::PermissionError)?;
+ let token_id = <PalletCore<T>>::create_nft(
+ &sender,
+ owner,
+ &collection,
+ NftType::Theme,
+ [
+ <PalletCore<T>>::rmrk_property(ThemeName, &theme.name)?,
+ <PalletCore<T>>::rmrk_property(ThemeInherit, &theme.inherit)?,
+ ]
+ .into_iter(),
+ )
+ .map_err(|_| <Error<T>>::PermissionError)?;
- for property in theme.properties {
- <PalletNft<T>>::set_scoped_token_property(
- collection_id,
- token_id,
- PropertyScope::Rmrk,
- <PalletCore<T>>::rmrk_property(
- UserProperty(property.key.as_slice()),
- &property.value
- )?
- )?;
- }
+ for property in theme.properties {
+ <PalletNft<T>>::set_scoped_token_property(
+ collection_id,
+ token_id,
+ PropertyScope::Rmrk,
+ <PalletCore<T>>::rmrk_property(
+ UserProperty(property.key.as_slice()),
+ &property.value,
+ )?,
+ )?;
+ }
- Ok(())
- }
- }
+ Ok(())
+ }
+ }
}
impl<T: Config> Pallet<T> {
- fn create_part(
- sender: &T::CrossAccountId,
- collection: &NonfungibleHandle<T>,
- part: RmrkPartType
- ) -> Result<TokenId, DispatchError> {
- let owner = sender;
+ fn create_part(
+ sender: &T::CrossAccountId,
+ collection: &NonfungibleHandle<T>,
+ part: RmrkPartType,
+ ) -> Result<TokenId, DispatchError> {
+ let owner = sender;
- let src = part.src();
- let z_index = part.z_index();
+ let src = part.src();
+ let z_index = part.z_index();
- let nft_type = match part {
- RmrkPartType::FixedPart(_) => NftType::FixedPart,
- RmrkPartType::SlotPart(_) => NftType::SlotPart,
- };
+ let nft_type = match part {
+ RmrkPartType::FixedPart(_) => NftType::FixedPart,
+ RmrkPartType::SlotPart(_) => NftType::SlotPart,
+ };
- let token_id = <PalletCore<T>>::create_nft(
- sender,
- owner,
- collection,
- nft_type,
- [
- <PalletCore<T>>::rmrk_property(Src, &src)?,
- <PalletCore<T>>::rmrk_property(ZIndex, &z_index)?
- ].into_iter()
- ).map_err(|err| match err {
- DispatchError::Arithmetic(_) => <Error<T>>::NoAvailablePartId.into(),
- err => err
- })?;
+ let token_id = <PalletCore<T>>::create_nft(
+ sender,
+ owner,
+ collection,
+ nft_type,
+ [
+ <PalletCore<T>>::rmrk_property(Src, &src)?,
+ <PalletCore<T>>::rmrk_property(ZIndex, &z_index)?,
+ ]
+ .into_iter(),
+ )
+ .map_err(|err| match err {
+ DispatchError::Arithmetic(_) => <Error<T>>::NoAvailablePartId.into(),
+ err => err,
+ })?;
- if let RmrkPartType::SlotPart(part) = part {
- <PalletNft<T>>::set_scoped_token_property(
- collection.id,
- token_id,
- PropertyScope::Rmrk,
- <PalletCore<T>>::rmrk_property(EquippableList, &part.equippable)?
- )?;
- }
+ if let RmrkPartType::SlotPart(part) = part {
+ <PalletNft<T>>::set_scoped_token_property(
+ collection.id,
+ token_id,
+ PropertyScope::Rmrk,
+ <PalletCore<T>>::rmrk_property(EquippableList, &part.equippable)?,
+ )?;
+ }
- Ok(token_id)
- }
+ Ok(token_id)
+ }
}
pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -313,17 +313,9 @@
fail!(<Error<T>>::RefungibleDisallowsNesting)
}
- fn nest(
- &self,
- _under: TokenId,
- _to_nest: (CollectionId, TokenId)
- ) {}
+ fn nest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}
- fn unnest(
- &self,
- _under: TokenId,
- _to_nest: (CollectionId, TokenId)
- ) {}
+ fn unnest(&self, _under: TokenId, _to_nest: (CollectionId, TokenId)) {}
fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId> {
<Owned<T>>::iter_prefix((self.id, account))
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -22,9 +22,7 @@
CreateCollectionData, CreateRefungibleExData, mapping::TokenAddressMapping, budget::Budget,
};
use pallet_evm::account::CrossAccountId;
-use pallet_common::{
- Error as CommonError, Event as CommonEvent, Pallet as PalletCommon,
-};
+use pallet_common::{Error as CommonError, Event as CommonEvent, Pallet as PalletCommon};
use pallet_structure::Pallet as PalletStructure;
use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
@@ -230,7 +228,9 @@
}
fn collection_has_tokens(collection_id: CollectionId) -> bool {
- <TokenData<T>>::iter_prefix((collection_id,)).next().is_some()
+ <TokenData<T>>::iter_prefix((collection_id,))
+ .next()
+ .is_some()
}
pub fn burn_token(collection: &RefungibleHandle<T>, token_id: TokenId) -> DispatchResult {
@@ -388,18 +388,14 @@
to,
collection.id,
token,
- nesting_budget
+ nesting_budget,
)?;
if let Some(balance_to) = balance_to {
// from != to
if balance_from == 0 {
<Balance<T>>::remove((collection.id, token, from));
- <PalletStructure<T>>::unnest_if_nested(
- from,
- collection.id,
- token
- );
+ <PalletStructure<T>>::unnest_if_nested(from, collection.id, token);
} else {
<Balance<T>>::insert((collection.id, token, from), balance_from);
}
@@ -497,7 +493,6 @@
for (i, token) in data.iter().enumerate() {
let token_id = TokenId(first_token_id + i as u32 + 1);
for (to, _) in token.users.iter() {
-
<PalletStructure<T>>::check_nesting(
sender.clone(),
to,
@@ -531,7 +526,11 @@
}
<Balance<T>>::insert((collection.id, token_id, &user), amount);
<Owned<T>>::insert((collection.id, &user, TokenId(token_id)), true);
- <PalletStructure<T>>::nest_if_sent_to_token_unchecked(&user, collection.id, TokenId(token_id));
+ <PalletStructure<T>>::nest_if_sent_to_token_unchecked(
+ &user,
+ collection.id,
+ TokenId(token_id),
+ );
// TODO: ERC20 transfer event
<PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(
pallets/structure/src/lib.rsdiffbeforeafterboth--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -189,17 +189,11 @@
under: &T::CrossAccountId,
collection_id: CollectionId,
token_id: TokenId,
- nesting_budget: &dyn Budget
+ nesting_budget: &dyn Budget,
) -> DispatchResult {
- Self::try_exec_if_owner_is_valid_nft(
- under,
- |d, parent_id| d.check_nesting(
- from,
- (collection_id, token_id),
- parent_id,
- nesting_budget
- )
- )
+ Self::try_exec_if_owner_is_valid_nft(under, |d, parent_id| {
+ d.check_nesting(from, (collection_id, token_id), parent_id, nesting_budget)
+ })
}
pub fn nest_if_sent_to_token(
@@ -207,69 +201,51 @@
under: &T::CrossAccountId,
collection_id: CollectionId,
token_id: TokenId,
- nesting_budget: &dyn Budget
+ nesting_budget: &dyn Budget,
) -> DispatchResult {
- Self::try_exec_if_owner_is_valid_nft(
- under,
- |d, parent_id| {
- d.check_nesting(
- from,
- (collection_id, token_id),
- parent_id,
- nesting_budget
- )?;
+ Self::try_exec_if_owner_is_valid_nft(under, |d, parent_id| {
+ d.check_nesting(from, (collection_id, token_id), parent_id, nesting_budget)?;
- d.nest(parent_id, (collection_id, token_id));
+ d.nest(parent_id, (collection_id, token_id));
- Ok(())
- }
- )
+ Ok(())
+ })
}
pub fn nest_if_sent_to_token_unchecked(
owner: &T::CrossAccountId,
collection_id: CollectionId,
- token_id: TokenId
+ token_id: TokenId,
) {
- Self::exec_if_owner_is_valid_nft(
- owner,
- |d, parent_id| d.nest(
- parent_id,
- (collection_id, token_id)
- )
- );
+ Self::exec_if_owner_is_valid_nft(owner, |d, parent_id| {
+ d.nest(parent_id, (collection_id, token_id))
+ });
}
pub fn unnest_if_nested(
owner: &T::CrossAccountId,
collection_id: CollectionId,
- token_id: TokenId
+ token_id: TokenId,
) {
- Self::exec_if_owner_is_valid_nft(
- owner,
- |d, parent_id| d.unnest(
- parent_id,
- (collection_id, token_id)
- )
- );
+ Self::exec_if_owner_is_valid_nft(owner, |d, parent_id| {
+ d.unnest(parent_id, (collection_id, token_id))
+ });
}
fn exec_if_owner_is_valid_nft(
account: &T::CrossAccountId,
- action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId)
+ action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId),
) {
- Self::try_exec_if_owner_is_valid_nft(
- account,
- |d, id| {
- action(d, id);
- Ok(())
- }
- ).unwrap();
+ Self::try_exec_if_owner_is_valid_nft(account, |d, id| {
+ action(d, id);
+ Ok(())
+ })
+ .unwrap();
}
fn try_exec_if_owner_is_valid_nft(
account: &T::CrossAccountId,
- action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId) -> DispatchResult
+ action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId) -> DispatchResult,
) -> DispatchResult {
let account = T::CrossTokenAddressMapping::address_to_token(account);
pallets/unique/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![recursion_limit = "1024"]18#![cfg_attr(not(feature = "std"), no_std)]19#![allow(20 clippy::too_many_arguments,21 clippy::unnecessary_mut_passed,22 clippy::unused_unit23)]2425extern crate alloc;2627use frame_support::{28 decl_module, decl_storage, decl_error, decl_event,29 dispatch::DispatchResult,30 ensure,31 weights::{Weight},32 transactional,33 pallet_prelude::{DispatchResultWithPostInfo, ConstU32},34 BoundedVec,35};36use scale_info::TypeInfo;37use frame_system::{self as system, ensure_signed};38use sp_runtime::{sp_std::prelude::Vec};39use up_data_structs::{40 MAX_COLLECTION_NAME_LENGTH,41 MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH, AccessMode, CreateItemData,42 CollectionLimits, CollectionPermissions, CollectionId, CollectionMode, TokenId, SponsorshipState,43 CreateCollectionData, CreateItemExData, budget, Property, PropertyKey,44 PropertyKeyPermission,45};46use pallet_evm::account::CrossAccountId;47use pallet_common::{48 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_call,49 dispatch::CollectionDispatch,50};51pub mod eth;5253#[cfg(feature = "runtime-benchmarks")]54mod benchmarking;55pub mod weights;56use weights::WeightInfo;5758const NESTING_BUDGET: u32 = 5;5960decl_error! {61 /// Error for non-fungible-token module.62 pub enum Error for Module<T: Config> {63 /// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.64 CollectionDecimalPointLimitExceeded,65 /// This address is not set as sponsor, use setCollectionSponsor first.66 ConfirmUnsetSponsorFail,67 /// Length of items properties must be greater than 0.68 EmptyArgument,69 }70}7172pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {73 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;7475 /// Weight information for extrinsics in this pallet.76 type WeightInfo: WeightInfo;77 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;78}7980decl_event! {81 pub enum Event<T>82 where83 <T as frame_system::Config>::AccountId,84 <T as pallet_evm::account::Config>::CrossAccountId,85 {86 /// Collection sponsor was removed87 ///88 /// # Arguments89 ///90 /// * collection_id: Globally unique collection identifier.91 CollectionSponsorRemoved(CollectionId),9293 /// Collection admin was added94 ///95 /// # Arguments96 ///97 /// * collection_id: Globally unique collection identifier.98 ///99 /// * admin: Admin address.100 CollectionAdminAdded(CollectionId, CrossAccountId),101102 /// Collection owned was change103 ///104 /// # Arguments105 ///106 /// * collection_id: Globally unique collection identifier.107 ///108 /// * owner: New owner address.109 CollectionOwnedChanged(CollectionId, AccountId),110111 /// Collection sponsor was set112 ///113 /// # Arguments114 ///115 /// * collection_id: Globally unique collection identifier.116 ///117 /// * owner: New sponsor address.118 CollectionSponsorSet(CollectionId, AccountId),119120 /// New sponsor was confirm121 ///122 /// # Arguments123 ///124 /// * collection_id: Globally unique collection identifier.125 ///126 /// * sponsor: New sponsor address.127 SponsorshipConfirmed(CollectionId, AccountId),128129 /// Collection admin was removed130 ///131 /// # Arguments132 ///133 /// * collection_id: Globally unique collection identifier.134 ///135 /// * admin: Admin address.136 CollectionAdminRemoved(CollectionId, CrossAccountId),137138 /// Address was remove from allow list139 ///140 /// # Arguments141 ///142 /// * collection_id: Globally unique collection identifier.143 ///144 /// * user: Address.145 AllowListAddressRemoved(CollectionId, CrossAccountId),146147 /// Address was add to allow list148 ///149 /// # Arguments150 ///151 /// * collection_id: Globally unique collection identifier.152 ///153 /// * user: Address.154 AllowListAddressAdded(CollectionId, CrossAccountId),155156 /// Collection limits was set157 ///158 /// # Arguments159 ///160 /// * collection_id: Globally unique collection identifier.161 CollectionLimitSet(CollectionId),162163 CollectionPermissionSet(CollectionId),164 }165}166167type SelfWeightOf<T> = <T as Config>::WeightInfo;168169// # Used definitions170//171// ## User control levels172//173// chain-controlled - key is uncontrolled by user174// i.e autoincrementing index175// can use non-cryptographic hash176// real - key is controlled by user177// but it is hard to generate enough colliding values, i.e owner of signed txs178// can use non-cryptographic hash179// controlled - key is completly controlled by users180// i.e maps with mutable keys181// should use cryptographic hash182//183// ## User control level downgrade reasons184//185// ?1 - chain-controlled -> controlled186// collections/tokens can be destroyed, resulting in massive holes187// ?2 - chain-controlled -> controlled188// same as ?1, but can be only added, resulting in easier exploitation189// ?3 - real -> controlled190// no confirmation required, so addresses can be easily generated191decl_storage! {192 trait Store for Module<T: Config> as Unique {193194 //#region Private members195 /// Used for migrations196 ChainVersion: u64;197 //#endregion198199 //#region Tokens transfer rate limit baskets200 /// (Collection id (controlled?2), who created (real))201 /// TODO: Off chain worker should remove from this map when collection gets removed202 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;203 /// Collection id (controlled?2), token id (controlled?2)204 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;205 /// Collection id (controlled?2), owning user (real)206 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;207 /// Collection id (controlled?2), token id (controlled?2)208 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;209 //#endregion210211 /// Variable metadata sponsoring212 /// Collection id (controlled?2), token id (controlled?2)213 #[deprecated]214 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;215 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;216217 /// Approval sponsoring218 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;219 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;220 pub RefungibleApproveBasket get(fn refungible_approve_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;221 }222}223224decl_module! {225 pub struct Module<T: Config> for enum Call226 where227 origin: T::Origin228 {229 type Error = Error<T>;230231 fn deposit_event() = default;232233 fn on_initialize(_now: T::BlockNumber) -> Weight {234 0235 }236237 fn on_runtime_upgrade() -> Weight {238 let limit = None;239240 <VariableMetaDataBasket<T>>::remove_all(limit);241242 0243 }244245 /// This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner of the collection is set to the address that signed the transaction and can be changed later.246 ///247 /// # Permissions248 ///249 /// * Anyone.250 ///251 /// # Arguments252 ///253 /// * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.254 ///255 /// * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.256 ///257 /// * token_prefix: UTF-8 string with token prefix.258 ///259 /// * mode: [CollectionMode] collection type and type dependent data.260 // returns collection ID261 #[weight = <SelfWeightOf<T>>::create_collection()]262 #[transactional]263 #[deprecated]264 pub fn create_collection(origin,265 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,266 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,267 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,268 mode: CollectionMode) -> DispatchResult {269 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {270 name: collection_name,271 description: collection_description,272 token_prefix,273 mode,274 ..Default::default()275 };276 Self::create_collection_ex(origin, data)277 }278279 /// This method creates a collection280 ///281 /// Prefer it to deprecated [`created_collection`] method282 #[weight = <SelfWeightOf<T>>::create_collection()]283 #[transactional]284 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {285 let sender = ensure_signed(origin)?;286287 // =========288289 T::CollectionDispatch::create(sender, data)?;290291 Ok(())292 }293294 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.295 ///296 /// # Permissions297 ///298 /// * Collection Owner.299 ///300 /// # Arguments301 ///302 /// * collection_id: collection to destroy.303 #[weight = <SelfWeightOf<T>>::destroy_collection()]304 #[transactional]305 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {306 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);307 let collection = <CollectionHandle<T>>::try_get(collection_id)?;308309 // =========310311 T::CollectionDispatch::destroy(sender, collection)?;312313 <NftTransferBasket<T>>::remove_prefix(collection_id, None);314 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);315 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);316317 <NftApproveBasket<T>>::remove_prefix(collection_id, None);318 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);319 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);320321 Ok(())322 }323324 /// Add an address to allow list.325 ///326 /// # Permissions327 ///328 /// * Collection Owner329 /// * Collection Admin330 ///331 /// # Arguments332 ///333 /// * collection_id.334 ///335 /// * address.336 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]337 #[transactional]338 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{339340 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);341 let collection = <CollectionHandle<T>>::try_get(collection_id)?;342343 <PalletCommon<T>>::toggle_allowlist(344 &collection,345 &sender,346 &address,347 true,348 )?;349350 Self::deposit_event(Event::<T>::AllowListAddressAdded(351 collection_id,352 address353 ));354355 Ok(())356 }357358 /// Remove an address from allow list.359 ///360 /// # Permissions361 ///362 /// * Collection Owner363 /// * Collection Admin364 ///365 /// # Arguments366 ///367 /// * collection_id.368 ///369 /// * address.370 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]371 #[transactional]372 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{373374 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);375 let collection = <CollectionHandle<T>>::try_get(collection_id)?;376377 <PalletCommon<T>>::toggle_allowlist(378 &collection,379 &sender,380 &address,381 false,382 )?;383384 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(385 collection_id,386 address387 ));388389 Ok(())390 }391392 /// Change the owner of the collection.393 ///394 /// # Permissions395 ///396 /// * Collection Owner.397 ///398 /// # Arguments399 ///400 /// * collection_id.401 ///402 /// * new_owner.403 #[weight = <SelfWeightOf<T>>::change_collection_owner()]404 #[transactional]405 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {406407 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);408409 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;410 target_collection.check_is_owner(&sender)?;411412 target_collection.owner = new_owner.clone();413 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(414 collection_id,415 new_owner416 ));417418 target_collection.save()419 }420421 /// Adds an admin of the Collection.422 /// NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.423 ///424 /// # Permissions425 ///426 /// * Collection Owner.427 /// * Collection Admin.428 ///429 /// # Arguments430 ///431 /// * collection_id: ID of the Collection to add admin for.432 ///433 /// * new_admin_id: Address of new admin to add.434 #[weight = <SelfWeightOf<T>>::add_collection_admin()]435 #[transactional]436 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {437 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);438 let collection = <CollectionHandle<T>>::try_get(collection_id)?;439440 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(441 collection_id,442 new_admin_id.clone()443 ));444445 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)446 }447448 /// Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.449 ///450 /// # Permissions451 ///452 /// * Collection Owner.453 /// * Collection Admin.454 ///455 /// # Arguments456 ///457 /// * collection_id: ID of the Collection to remove admin for.458 ///459 /// * account_id: Address of admin to remove.460 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]461 #[transactional]462 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {463 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);464 let collection = <CollectionHandle<T>>::try_get(collection_id)?;465466 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(467 collection_id,468 account_id.clone()469 ));470471 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)472 }473474 /// # Permissions475 ///476 /// * Collection Owner477 ///478 /// # Arguments479 ///480 /// * collection_id.481 ///482 /// * new_sponsor.483 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]484 #[transactional]485 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {486 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);487488 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;489 target_collection.check_is_owner(&sender)?;490491 target_collection.set_sponsor(new_sponsor.clone());492493 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(494 collection_id,495 new_sponsor496 ));497498 target_collection.save()499 }500501 /// # Permissions502 ///503 /// * Sponsor.504 ///505 /// # Arguments506 ///507 /// * collection_id.508 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]509 #[transactional]510 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {511 let sender = ensure_signed(origin)?;512513 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;514 ensure!(515 target_collection.confirm_sponsorship(&sender),516 Error::<T>::ConfirmUnsetSponsorFail517 );518519 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(520 collection_id,521 sender522 ));523524 target_collection.save()525 }526527 /// Switch back to pay-per-own-transaction model.528 ///529 /// # Permissions530 ///531 /// * Collection owner.532 ///533 /// # Arguments534 ///535 /// * collection_id.536 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]537 #[transactional]538 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {539 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);540541 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;542 target_collection.check_is_owner(&sender)?;543544 target_collection.sponsorship = SponsorshipState::Disabled;545546 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(547 collection_id548 ));549 target_collection.save()550 }551552 /// This method creates a concrete instance of NFT Collection created with CreateCollection method.553 ///554 /// # Permissions555 ///556 /// * Collection Owner.557 /// * Collection Admin.558 /// * Anyone if559 /// * Allow List is enabled, and560 /// * Address is added to allow list, and561 /// * MintPermission is enabled (see SetMintPermission method)562 ///563 /// # Arguments564 ///565 /// * collection_id: ID of the collection.566 ///567 /// * owner: Address, initial owner of the NFT.568 ///569 /// * data: Token data to store on chain.570 #[weight = T::CommonWeightInfo::create_item()]571 #[transactional]572 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {573 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);574 let budget = budget::Value::new(NESTING_BUDGET);575576 dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))577 }578579 /// This method creates multiple items in a collection created with CreateCollection method.580 ///581 /// # Permissions582 ///583 /// * Collection Owner.584 /// * Collection Admin.585 /// * Anyone if586 /// * Allow List is enabled, and587 /// * Address is added to allow list, and588 /// * MintPermission is enabled (see SetMintPermission method)589 ///590 /// # Arguments591 ///592 /// * collection_id: ID of the collection.593 ///594 /// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].595 ///596 /// * owner: Address, initial owner of the NFT.597 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]598 #[transactional]599 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {600 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);601 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);602 let budget = budget::Value::new(NESTING_BUDGET);603604 dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))605 }606607 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]608 #[transactional]609 pub fn set_collection_properties(610 origin,611 collection_id: CollectionId,612 properties: Vec<Property>613 ) -> DispatchResultWithPostInfo {614 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);615616 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);617618 dispatch_call::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))619 }620621 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]622 #[transactional]623 pub fn delete_collection_properties(624 origin,625 collection_id: CollectionId,626 property_keys: Vec<PropertyKey>,627 ) -> DispatchResultWithPostInfo {628 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);629630 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);631632 dispatch_call::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))633 }634635 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]636 #[transactional]637 pub fn set_token_properties(638 origin,639 collection_id: CollectionId,640 token_id: TokenId,641 properties: Vec<Property>642 ) -> DispatchResultWithPostInfo {643 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);644645 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);646647 dispatch_call::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties))648 }649650 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]651 #[transactional]652 pub fn delete_token_properties(653 origin,654 collection_id: CollectionId,655 token_id: TokenId,656 property_keys: Vec<PropertyKey>657 ) -> DispatchResultWithPostInfo {658 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);659660 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);661662 dispatch_call::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys))663 }664665 #[weight = T::CommonWeightInfo::set_property_permissions(property_permissions.len() as u32)]666 #[transactional]667 pub fn set_property_permissions(668 origin,669 collection_id: CollectionId,670 property_permissions: Vec<PropertyKeyPermission>,671 ) -> DispatchResultWithPostInfo {672 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);673674 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);675676 dispatch_call::<T, _>(collection_id, |d| d.set_property_permissions(&sender, property_permissions))677 }678679 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]680 #[transactional]681 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {682 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);683 let budget = budget::Value::new(NESTING_BUDGET);684685 dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))686 }687688 // TODO! transaction weight689690 /// Set transfers_enabled value for particular collection691 ///692 /// # Permissions693 ///694 /// * Collection Owner.695 ///696 /// # Arguments697 ///698 /// * collection_id: ID of the collection.699 ///700 /// * value: New flag value.701 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]702 #[transactional]703 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {704 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);705 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;706 target_collection.check_is_owner(&sender)?;707708 // =========709710 target_collection.limits.transfers_enabled = Some(value);711 target_collection.save()712 }713714 /// Destroys a concrete instance of NFT.715 ///716 /// # Permissions717 ///718 /// * Collection Owner.719 /// * Collection Admin.720 /// * Current NFT Owner.721 ///722 /// # Arguments723 ///724 /// * collection_id: ID of the collection.725 ///726 /// * item_id: ID of NFT to burn.727 #[weight = T::CommonWeightInfo::burn_item()]728 #[transactional]729 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {730 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);731732 let post_info = dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;733 if value == 1 {734 <NftTransferBasket<T>>::remove(collection_id, item_id);735 <NftApproveBasket<T>>::remove(collection_id, item_id);736 }737 // Those maps should be cleared only if token disappears completly, need to move this part of logic to pallets?738 // <FungibleApproveBasket<T>>::remove(collection_id, sender.as_sub());739 // <RefungibleApproveBasket<T>>::remove((collection_id, item_id, sender.as_sub()));740 Ok(post_info)741 }742743 /// Destroys a concrete instance of NFT on behalf of the owner744 /// See also: [`approve`]745 ///746 /// # Permissions747 ///748 /// * Collection Owner.749 /// * Collection Admin.750 /// * Current NFT Owner.751 ///752 /// # Arguments753 ///754 /// * collection_id: ID of the collection.755 ///756 /// * item_id: ID of NFT to burn.757 ///758 /// * from: owner of item759 #[weight = T::CommonWeightInfo::burn_from()]760 #[transactional]761 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {762 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);763 let budget = budget::Value::new(NESTING_BUDGET);764765 dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))766 }767768 /// Change ownership of the token.769 ///770 /// # Permissions771 ///772 /// * Collection Owner773 /// * Collection Admin774 /// * Current NFT owner775 ///776 /// # Arguments777 ///778 /// * recipient: Address of token recipient.779 ///780 /// * collection_id.781 ///782 /// * item_id: ID of the item783 /// * Non-Fungible Mode: Required.784 /// * Fungible Mode: Ignored.785 /// * Re-Fungible Mode: Required.786 ///787 /// * value: Amount to transfer.788 /// * Non-Fungible Mode: Ignored789 /// * Fungible Mode: Must specify transferred amount790 /// * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)791 #[weight = T::CommonWeightInfo::transfer()]792 #[transactional]793 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {794 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);795 let budget = budget::Value::new(NESTING_BUDGET);796797 dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))798 }799800 /// Set, change, or remove approved address to transfer the ownership of the NFT.801 ///802 /// # Permissions803 ///804 /// * Collection Owner805 /// * Collection Admin806 /// * Current NFT owner807 ///808 /// # Arguments809 ///810 /// * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).811 ///812 /// * collection_id.813 ///814 /// * item_id: ID of the item.815 #[weight = T::CommonWeightInfo::approve()]816 #[transactional]817 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {818 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);819820 dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))821 }822823 /// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.824 ///825 /// # Permissions826 /// * Collection Owner827 /// * Collection Admin828 /// * Current NFT owner829 /// * Address approved by current NFT owner830 ///831 /// # Arguments832 ///833 /// * from: Address that owns token.834 ///835 /// * recipient: Address of token recipient.836 ///837 /// * collection_id.838 ///839 /// * item_id: ID of the item.840 ///841 /// * value: Amount to transfer.842 #[weight = T::CommonWeightInfo::transfer_from()]843 #[transactional]844 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {845 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);846 let budget = budget::Value::new(NESTING_BUDGET);847848 dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))849 }850851 #[weight = <SelfWeightOf<T>>::set_collection_limits()]852 #[transactional]853 pub fn set_collection_limits(854 origin,855 collection_id: CollectionId,856 new_limit: CollectionLimits,857 ) -> DispatchResult {858 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);859 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;860 target_collection.check_is_owner(&sender)?;861 let old_limit = &target_collection.limits;862863 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;864865 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(866 collection_id867 ));868869 target_collection.save()870 }871872 #[weight = <SelfWeightOf<T>>::set_collection_limits()]873 #[transactional]874 pub fn set_collection_permissions(875 origin,876 collection_id: CollectionId,877 new_limit: CollectionPermissions,878 ) -> DispatchResult {879 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);880 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;881 target_collection.check_is_owner(&sender)?;882 let old_limit = &target_collection.permissions;883884 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_limit)?;885886 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(887 collection_id888 ));889890 target_collection.save()891 }892 }893}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617#![recursion_limit = "1024"]18#![cfg_attr(not(feature = "std"), no_std)]19#![allow(20 clippy::too_many_arguments,21 clippy::unnecessary_mut_passed,22 clippy::unused_unit23)]2425extern crate alloc;2627use frame_support::{28 decl_module, decl_storage, decl_error, decl_event,29 dispatch::DispatchResult,30 ensure,31 weights::{Weight},32 transactional,33 pallet_prelude::{DispatchResultWithPostInfo, ConstU32},34 BoundedVec,35};36use scale_info::TypeInfo;37use frame_system::{self as system, ensure_signed};38use sp_runtime::{sp_std::prelude::Vec};39use up_data_structs::{40 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,41 AccessMode, CreateItemData, CollectionLimits, CollectionPermissions, CollectionId,42 CollectionMode, TokenId, SponsorshipState, CreateCollectionData, CreateItemExData, budget,43 Property, PropertyKey, PropertyKeyPermission,44};45use pallet_evm::account::CrossAccountId;46use pallet_common::{47 CollectionHandle, Pallet as PalletCommon, CommonWeightInfo, dispatch::dispatch_call,48 dispatch::CollectionDispatch,49};50pub mod eth;5152#[cfg(feature = "runtime-benchmarks")]53mod benchmarking;54pub mod weights;55use weights::WeightInfo;5657const NESTING_BUDGET: u32 = 5;5859decl_error! {60 /// Error for non-fungible-token module.61 pub enum Error for Module<T: Config> {62 /// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.63 CollectionDecimalPointLimitExceeded,64 /// This address is not set as sponsor, use setCollectionSponsor first.65 ConfirmUnsetSponsorFail,66 /// Length of items properties must be greater than 0.67 EmptyArgument,68 }69}7071pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {72 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;7374 /// Weight information for extrinsics in this pallet.75 type WeightInfo: WeightInfo;76 type CommonWeightInfo: CommonWeightInfo<Self::CrossAccountId>;77}7879decl_event! {80 pub enum Event<T>81 where82 <T as frame_system::Config>::AccountId,83 <T as pallet_evm::account::Config>::CrossAccountId,84 {85 /// Collection sponsor was removed86 ///87 /// # Arguments88 ///89 /// * collection_id: Globally unique collection identifier.90 CollectionSponsorRemoved(CollectionId),9192 /// Collection admin was added93 ///94 /// # Arguments95 ///96 /// * collection_id: Globally unique collection identifier.97 ///98 /// * admin: Admin address.99 CollectionAdminAdded(CollectionId, CrossAccountId),100101 /// Collection owned was change102 ///103 /// # Arguments104 ///105 /// * collection_id: Globally unique collection identifier.106 ///107 /// * owner: New owner address.108 CollectionOwnedChanged(CollectionId, AccountId),109110 /// Collection sponsor was set111 ///112 /// # Arguments113 ///114 /// * collection_id: Globally unique collection identifier.115 ///116 /// * owner: New sponsor address.117 CollectionSponsorSet(CollectionId, AccountId),118119 /// New sponsor was confirm120 ///121 /// # Arguments122 ///123 /// * collection_id: Globally unique collection identifier.124 ///125 /// * sponsor: New sponsor address.126 SponsorshipConfirmed(CollectionId, AccountId),127128 /// Collection admin was removed129 ///130 /// # Arguments131 ///132 /// * collection_id: Globally unique collection identifier.133 ///134 /// * admin: Admin address.135 CollectionAdminRemoved(CollectionId, CrossAccountId),136137 /// Address was remove from allow list138 ///139 /// # Arguments140 ///141 /// * collection_id: Globally unique collection identifier.142 ///143 /// * user: Address.144 AllowListAddressRemoved(CollectionId, CrossAccountId),145146 /// Address was add to allow list147 ///148 /// # Arguments149 ///150 /// * collection_id: Globally unique collection identifier.151 ///152 /// * user: Address.153 AllowListAddressAdded(CollectionId, CrossAccountId),154155 /// Collection limits was set156 ///157 /// # Arguments158 ///159 /// * collection_id: Globally unique collection identifier.160 CollectionLimitSet(CollectionId),161162 CollectionPermissionSet(CollectionId),163 }164}165166type SelfWeightOf<T> = <T as Config>::WeightInfo;167168// # Used definitions169//170// ## User control levels171//172// chain-controlled - key is uncontrolled by user173// i.e autoincrementing index174// can use non-cryptographic hash175// real - key is controlled by user176// but it is hard to generate enough colliding values, i.e owner of signed txs177// can use non-cryptographic hash178// controlled - key is completly controlled by users179// i.e maps with mutable keys180// should use cryptographic hash181//182// ## User control level downgrade reasons183//184// ?1 - chain-controlled -> controlled185// collections/tokens can be destroyed, resulting in massive holes186// ?2 - chain-controlled -> controlled187// same as ?1, but can be only added, resulting in easier exploitation188// ?3 - real -> controlled189// no confirmation required, so addresses can be easily generated190decl_storage! {191 trait Store for Module<T: Config> as Unique {192193 //#region Private members194 /// Used for migrations195 ChainVersion: u64;196 //#endregion197198 //#region Tokens transfer rate limit baskets199 /// (Collection id (controlled?2), who created (real))200 /// TODO: Off chain worker should remove from this map when collection gets removed201 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;202 /// Collection id (controlled?2), token id (controlled?2)203 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;204 /// Collection id (controlled?2), owning user (real)205 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;206 /// Collection id (controlled?2), token id (controlled?2)207 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;208 //#endregion209210 /// Variable metadata sponsoring211 /// Collection id (controlled?2), token id (controlled?2)212 #[deprecated]213 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;214 pub TokenPropertyBasket get(fn token_property_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;215216 /// Approval sponsoring217 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;218 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;219 pub RefungibleApproveBasket get(fn refungible_approve_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;220 }221}222223decl_module! {224 pub struct Module<T: Config> for enum Call225 where226 origin: T::Origin227 {228 type Error = Error<T>;229230 fn deposit_event() = default;231232 fn on_initialize(_now: T::BlockNumber) -> Weight {233 0234 }235236 fn on_runtime_upgrade() -> Weight {237 let limit = None;238239 <VariableMetaDataBasket<T>>::remove_all(limit);240241 0242 }243244 /// This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner of the collection is set to the address that signed the transaction and can be changed later.245 ///246 /// # Permissions247 ///248 /// * Anyone.249 ///250 /// # Arguments251 ///252 /// * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.253 ///254 /// * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.255 ///256 /// * token_prefix: UTF-8 string with token prefix.257 ///258 /// * mode: [CollectionMode] collection type and type dependent data.259 // returns collection ID260 #[weight = <SelfWeightOf<T>>::create_collection()]261 #[transactional]262 #[deprecated]263 pub fn create_collection(origin,264 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,265 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,266 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,267 mode: CollectionMode) -> DispatchResult {268 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {269 name: collection_name,270 description: collection_description,271 token_prefix,272 mode,273 ..Default::default()274 };275 Self::create_collection_ex(origin, data)276 }277278 /// This method creates a collection279 ///280 /// Prefer it to deprecated [`created_collection`] method281 #[weight = <SelfWeightOf<T>>::create_collection()]282 #[transactional]283 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {284 let sender = ensure_signed(origin)?;285286 // =========287288 T::CollectionDispatch::create(sender, data)?;289290 Ok(())291 }292293 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.294 ///295 /// # Permissions296 ///297 /// * Collection Owner.298 ///299 /// # Arguments300 ///301 /// * collection_id: collection to destroy.302 #[weight = <SelfWeightOf<T>>::destroy_collection()]303 #[transactional]304 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {305 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);306 let collection = <CollectionHandle<T>>::try_get(collection_id)?;307308 // =========309310 T::CollectionDispatch::destroy(sender, collection)?;311312 <NftTransferBasket<T>>::remove_prefix(collection_id, None);313 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);314 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);315316 <NftApproveBasket<T>>::remove_prefix(collection_id, None);317 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);318 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);319320 Ok(())321 }322323 /// Add an address to allow list.324 ///325 /// # Permissions326 ///327 /// * Collection Owner328 /// * Collection Admin329 ///330 /// # Arguments331 ///332 /// * collection_id.333 ///334 /// * address.335 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]336 #[transactional]337 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{338339 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);340 let collection = <CollectionHandle<T>>::try_get(collection_id)?;341342 <PalletCommon<T>>::toggle_allowlist(343 &collection,344 &sender,345 &address,346 true,347 )?;348349 Self::deposit_event(Event::<T>::AllowListAddressAdded(350 collection_id,351 address352 ));353354 Ok(())355 }356357 /// Remove an address from allow list.358 ///359 /// # Permissions360 ///361 /// * Collection Owner362 /// * Collection Admin363 ///364 /// # Arguments365 ///366 /// * collection_id.367 ///368 /// * address.369 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]370 #[transactional]371 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{372373 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);374 let collection = <CollectionHandle<T>>::try_get(collection_id)?;375376 <PalletCommon<T>>::toggle_allowlist(377 &collection,378 &sender,379 &address,380 false,381 )?;382383 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(384 collection_id,385 address386 ));387388 Ok(())389 }390391 /// Change the owner of the collection.392 ///393 /// # Permissions394 ///395 /// * Collection Owner.396 ///397 /// # Arguments398 ///399 /// * collection_id.400 ///401 /// * new_owner.402 #[weight = <SelfWeightOf<T>>::change_collection_owner()]403 #[transactional]404 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {405406 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);407408 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;409 target_collection.check_is_owner(&sender)?;410411 target_collection.owner = new_owner.clone();412 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(413 collection_id,414 new_owner415 ));416417 target_collection.save()418 }419420 /// Adds an admin of the Collection.421 /// NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.422 ///423 /// # Permissions424 ///425 /// * Collection Owner.426 /// * Collection Admin.427 ///428 /// # Arguments429 ///430 /// * collection_id: ID of the Collection to add admin for.431 ///432 /// * new_admin_id: Address of new admin to add.433 #[weight = <SelfWeightOf<T>>::add_collection_admin()]434 #[transactional]435 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {436 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);437 let collection = <CollectionHandle<T>>::try_get(collection_id)?;438439 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(440 collection_id,441 new_admin_id.clone()442 ));443444 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)445 }446447 /// Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.448 ///449 /// # Permissions450 ///451 /// * Collection Owner.452 /// * Collection Admin.453 ///454 /// # Arguments455 ///456 /// * collection_id: ID of the Collection to remove admin for.457 ///458 /// * account_id: Address of admin to remove.459 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]460 #[transactional]461 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {462 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);463 let collection = <CollectionHandle<T>>::try_get(collection_id)?;464465 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(466 collection_id,467 account_id.clone()468 ));469470 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)471 }472473 /// # Permissions474 ///475 /// * Collection Owner476 ///477 /// # Arguments478 ///479 /// * collection_id.480 ///481 /// * new_sponsor.482 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]483 #[transactional]484 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {485 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);486487 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;488 target_collection.check_is_owner(&sender)?;489490 target_collection.set_sponsor(new_sponsor.clone());491492 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(493 collection_id,494 new_sponsor495 ));496497 target_collection.save()498 }499500 /// # Permissions501 ///502 /// * Sponsor.503 ///504 /// # Arguments505 ///506 /// * collection_id.507 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]508 #[transactional]509 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {510 let sender = ensure_signed(origin)?;511512 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;513 ensure!(514 target_collection.confirm_sponsorship(&sender),515 Error::<T>::ConfirmUnsetSponsorFail516 );517518 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(519 collection_id,520 sender521 ));522523 target_collection.save()524 }525526 /// Switch back to pay-per-own-transaction model.527 ///528 /// # Permissions529 ///530 /// * Collection owner.531 ///532 /// # Arguments533 ///534 /// * collection_id.535 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]536 #[transactional]537 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {538 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);539540 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;541 target_collection.check_is_owner(&sender)?;542543 target_collection.sponsorship = SponsorshipState::Disabled;544545 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(546 collection_id547 ));548 target_collection.save()549 }550551 /// This method creates a concrete instance of NFT Collection created with CreateCollection method.552 ///553 /// # Permissions554 ///555 /// * Collection Owner.556 /// * Collection Admin.557 /// * Anyone if558 /// * Allow List is enabled, and559 /// * Address is added to allow list, and560 /// * MintPermission is enabled (see SetMintPermission method)561 ///562 /// # Arguments563 ///564 /// * collection_id: ID of the collection.565 ///566 /// * owner: Address, initial owner of the NFT.567 ///568 /// * data: Token data to store on chain.569 #[weight = T::CommonWeightInfo::create_item()]570 #[transactional]571 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {572 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);573 let budget = budget::Value::new(NESTING_BUDGET);574575 dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data, &budget))576 }577578 /// This method creates multiple items in a collection created with CreateCollection method.579 ///580 /// # Permissions581 ///582 /// * Collection Owner.583 /// * Collection Admin.584 /// * Anyone if585 /// * Allow List is enabled, and586 /// * Address is added to allow list, and587 /// * MintPermission is enabled (see SetMintPermission method)588 ///589 /// # Arguments590 ///591 /// * collection_id: ID of the collection.592 ///593 /// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].594 ///595 /// * owner: Address, initial owner of the NFT.596 #[weight = T::CommonWeightInfo::create_multiple_items(&items_data)]597 #[transactional]598 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {599 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);600 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);601 let budget = budget::Value::new(NESTING_BUDGET);602603 dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))604 }605606 #[weight = T::CommonWeightInfo::set_collection_properties(properties.len() as u32)]607 #[transactional]608 pub fn set_collection_properties(609 origin,610 collection_id: CollectionId,611 properties: Vec<Property>612 ) -> DispatchResultWithPostInfo {613 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);614615 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);616617 dispatch_call::<T, _>(collection_id, |d| d.set_collection_properties(sender, properties))618 }619620 #[weight = T::CommonWeightInfo::delete_collection_properties(property_keys.len() as u32)]621 #[transactional]622 pub fn delete_collection_properties(623 origin,624 collection_id: CollectionId,625 property_keys: Vec<PropertyKey>,626 ) -> DispatchResultWithPostInfo {627 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);628629 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);630631 dispatch_call::<T, _>(collection_id, |d| d.delete_collection_properties(&sender, property_keys))632 }633634 #[weight = T::CommonWeightInfo::set_token_properties(properties.len() as u32)]635 #[transactional]636 pub fn set_token_properties(637 origin,638 collection_id: CollectionId,639 token_id: TokenId,640 properties: Vec<Property>641 ) -> DispatchResultWithPostInfo {642 ensure!(!properties.is_empty(), Error::<T>::EmptyArgument);643644 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);645646 dispatch_call::<T, _>(collection_id, |d| d.set_token_properties(sender, token_id, properties))647 }648649 #[weight = T::CommonWeightInfo::delete_token_properties(property_keys.len() as u32)]650 #[transactional]651 pub fn delete_token_properties(652 origin,653 collection_id: CollectionId,654 token_id: TokenId,655 property_keys: Vec<PropertyKey>656 ) -> DispatchResultWithPostInfo {657 ensure!(!property_keys.is_empty(), Error::<T>::EmptyArgument);658659 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);660661 dispatch_call::<T, _>(collection_id, |d| d.delete_token_properties(sender, token_id, property_keys))662 }663664 #[weight = T::CommonWeightInfo::set_property_permissions(property_permissions.len() as u32)]665 #[transactional]666 pub fn set_property_permissions(667 origin,668 collection_id: CollectionId,669 property_permissions: Vec<PropertyKeyPermission>,670 ) -> DispatchResultWithPostInfo {671 ensure!(!property_permissions.is_empty(), Error::<T>::EmptyArgument);672673 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);674675 dispatch_call::<T, _>(collection_id, |d| d.set_property_permissions(&sender, property_permissions))676 }677678 #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]679 #[transactional]680 pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData<T::CrossAccountId>) -> DispatchResultWithPostInfo {681 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);682 let budget = budget::Value::new(NESTING_BUDGET);683684 dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items_ex(sender, data, &budget))685 }686687 // TODO! transaction weight688689 /// Set transfers_enabled value for particular collection690 ///691 /// # Permissions692 ///693 /// * Collection Owner.694 ///695 /// # Arguments696 ///697 /// * collection_id: ID of the collection.698 ///699 /// * value: New flag value.700 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]701 #[transactional]702 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {703 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);704 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;705 target_collection.check_is_owner(&sender)?;706707 // =========708709 target_collection.limits.transfers_enabled = Some(value);710 target_collection.save()711 }712713 /// Destroys a concrete instance of NFT.714 ///715 /// # Permissions716 ///717 /// * Collection Owner.718 /// * Collection Admin.719 /// * Current NFT Owner.720 ///721 /// # Arguments722 ///723 /// * collection_id: ID of the collection.724 ///725 /// * item_id: ID of NFT to burn.726 #[weight = T::CommonWeightInfo::burn_item()]727 #[transactional]728 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {729 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);730731 let post_info = dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;732 if value == 1 {733 <NftTransferBasket<T>>::remove(collection_id, item_id);734 <NftApproveBasket<T>>::remove(collection_id, item_id);735 }736 // Those maps should be cleared only if token disappears completly, need to move this part of logic to pallets?737 // <FungibleApproveBasket<T>>::remove(collection_id, sender.as_sub());738 // <RefungibleApproveBasket<T>>::remove((collection_id, item_id, sender.as_sub()));739 Ok(post_info)740 }741742 /// Destroys a concrete instance of NFT on behalf of the owner743 /// See also: [`approve`]744 ///745 /// # Permissions746 ///747 /// * Collection Owner.748 /// * Collection Admin.749 /// * Current NFT Owner.750 ///751 /// # Arguments752 ///753 /// * collection_id: ID of the collection.754 ///755 /// * item_id: ID of NFT to burn.756 ///757 /// * from: owner of item758 #[weight = T::CommonWeightInfo::burn_from()]759 #[transactional]760 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {761 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);762 let budget = budget::Value::new(NESTING_BUDGET);763764 dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value, &budget))765 }766767 /// Change ownership of the token.768 ///769 /// # Permissions770 ///771 /// * Collection Owner772 /// * Collection Admin773 /// * Current NFT owner774 ///775 /// # Arguments776 ///777 /// * recipient: Address of token recipient.778 ///779 /// * collection_id.780 ///781 /// * item_id: ID of the item782 /// * Non-Fungible Mode: Required.783 /// * Fungible Mode: Ignored.784 /// * Re-Fungible Mode: Required.785 ///786 /// * value: Amount to transfer.787 /// * Non-Fungible Mode: Ignored788 /// * Fungible Mode: Must specify transferred amount789 /// * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)790 #[weight = T::CommonWeightInfo::transfer()]791 #[transactional]792 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {793 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);794 let budget = budget::Value::new(NESTING_BUDGET);795796 dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value, &budget))797 }798799 /// Set, change, or remove approved address to transfer the ownership of the NFT.800 ///801 /// # Permissions802 ///803 /// * Collection Owner804 /// * Collection Admin805 /// * Current NFT owner806 ///807 /// # Arguments808 ///809 /// * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).810 ///811 /// * collection_id.812 ///813 /// * item_id: ID of the item.814 #[weight = T::CommonWeightInfo::approve()]815 #[transactional]816 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {817 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);818819 dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))820 }821822 /// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.823 ///824 /// # Permissions825 /// * Collection Owner826 /// * Collection Admin827 /// * Current NFT owner828 /// * Address approved by current NFT owner829 ///830 /// # Arguments831 ///832 /// * from: Address that owns token.833 ///834 /// * recipient: Address of token recipient.835 ///836 /// * collection_id.837 ///838 /// * item_id: ID of the item.839 ///840 /// * value: Amount to transfer.841 #[weight = T::CommonWeightInfo::transfer_from()]842 #[transactional]843 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {844 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);845 let budget = budget::Value::new(NESTING_BUDGET);846847 dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value, &budget))848 }849850 #[weight = <SelfWeightOf<T>>::set_collection_limits()]851 #[transactional]852 pub fn set_collection_limits(853 origin,854 collection_id: CollectionId,855 new_limit: CollectionLimits,856 ) -> DispatchResult {857 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);858 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;859 target_collection.check_is_owner(&sender)?;860 let old_limit = &target_collection.limits;861862 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;863864 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(865 collection_id866 ));867868 target_collection.save()869 }870871 #[weight = <SelfWeightOf<T>>::set_collection_limits()]872 #[transactional]873 pub fn set_collection_permissions(874 origin,875 collection_id: CollectionId,876 new_limit: CollectionPermissions,877 ) -> DispatchResult {878 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);879 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;880 target_collection.check_is_owner(&sender)?;881 let old_limit = &target_collection.permissions;882883 target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_limit)?;884885 <Pallet<T>>::deposit_event(Event::<T>::CollectionPermissionSet(886 collection_id887 ));888889 target_collection.save()890 }891 }892}primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -49,7 +49,8 @@
},
NftChild as RmrkNftChild, AccountIdOrCollectionNftTuple as RmrkAccountIdOrCollectionNftTuple,
FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart, EquippableList as RmrkEquippableList,
- BasicResource as RmrkBasicResource, ComposableResource as RmrkComposableResource, SlotResource as RmrkSlotResource,
+ BasicResource as RmrkBasicResource, ComposableResource as RmrkComposableResource,
+ SlotResource as RmrkSlotResource,
};
mod bounded;
@@ -361,8 +362,7 @@
pub type CollectionPropertiesPermissionsVec =
BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;
-pub type CollectionPropertiesVec =
- BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;
+pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;
/// All fields are wrapped in `Option`s, where None means chain default
// When adding/removing fields from this struct - don't forget to also update clamp_limits
@@ -790,8 +790,8 @@
>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
- self.0.into_iter()
- }
+ self.0.into_iter()
+ }
}
impl<Value> TrySetProperty for PropertiesMap<Value> {
@@ -853,8 +853,8 @@
type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
- self.map.into_iter()
- }
+ self.map.into_iter()
+ }
}
impl TrySetProperty for Properties {
@@ -932,11 +932,7 @@
pub type RmrkCollectionInfo<AccountId> =
CollectionInfo<RmrkString, RmrkCollectionSymbol, AccountId>;
pub type RmrkInstanceInfo<AccountId> = NftInfo<AccountId, Permill, RmrkString>;
-pub type RmrkResourceInfo = ResourceInfo<
- RmrkBoundedResource,
- RmrkString,
- RmrkBoundedParts,
->;
+pub type RmrkResourceInfo = ResourceInfo<RmrkBoundedResource, RmrkString, RmrkBoundedParts>;
pub type RmrkPropertyInfo = PropertyInfo<RmrkKeyString, RmrkValueString>;
pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;
pub type RmrkPartType =
primitives/data-structs/src/rmrk.rsdiffbeforeafterboth--- a/primitives/data-structs/src/rmrk.rs
+++ b/primitives/data-structs/src/rmrk.rs
@@ -20,37 +20,37 @@
#[cfg(feature = "std")]
mod serialize {
- use core::convert::AsRef;
- use serde::ser::{self, Serialize};
+ use core::convert::AsRef;
+ use serde::ser::{self, Serialize};
- pub mod vec {
- use super::*;
+ pub mod vec {
+ use super::*;
- pub fn serialize<D, V, C>(value: &C, serializer: D) -> Result<D::Ok, D::Error>
- where
- D: ser::Serializer,
- V: Serialize,
- C: AsRef<[V]>,
- {
- value.as_ref().serialize(serializer)
- }
- }
+ pub fn serialize<D, V, C>(value: &C, serializer: D) -> Result<D::Ok, D::Error>
+ where
+ D: ser::Serializer,
+ V: Serialize,
+ C: AsRef<[V]>,
+ {
+ value.as_ref().serialize(serializer)
+ }
+ }
- pub mod opt_vec {
- use super::*;
+ pub mod opt_vec {
+ use super::*;
- pub fn serialize<D, V, C>(value: &Option<C>, serializer: D) -> Result<D::Ok, D::Error>
- where
- D: ser::Serializer,
- V: Serialize,
- C: AsRef<[V]>,
- {
- match value {
- Some(value) => super::vec::serialize(value, serializer),
- None => serializer.serialize_none()
- }
- }
- }
+ pub fn serialize<D, V, C>(value: &Option<C>, serializer: D) -> Result<D::Ok, D::Error>
+ where
+ D: ser::Serializer,
+ V: Serialize,
+ C: AsRef<[V]>,
+ {
+ match value {
+ Some(value) => super::vec::serialize(value, serializer),
+ None => serializer.serialize_none(),
+ }
+ }
+ }
}
/// Collection info.
@@ -58,13 +58,11 @@
#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
#[cfg_attr(
feature = "std",
- serde(
- bound = r#"
+ serde(bound = r#"
AccountId: Serialize,
BoundedString: AsRef<[u8]>,
BoundedSymbol: AsRef<[u8]>
- "#
- )
+ "#)
)]
pub struct CollectionInfo<BoundedString, BoundedSymbol, AccountId> {
/// Current bidder and bid price.
@@ -91,9 +89,9 @@
#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
pub struct RoyaltyInfo<AccountId, RoyaltyAmount> {
/// Recipient (AccountId) of the royalty
- pub recipient: AccountId,
+ pub recipient: AccountId,
/// Amount (Permill) of the royalty
- pub amount: RoyaltyAmount,
+ pub amount: RoyaltyAmount,
}
/// Nft info.
@@ -101,13 +99,11 @@
#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
#[cfg_attr(
feature = "std",
- serde(
- bound = r#"
+ serde(bound = r#"
AccountId: Serialize,
RoyaltyAmount: Serialize,
BoundedString: AsRef<[u8]>
- "#
- )
+ "#)
)]
pub struct NftInfo<AccountId, RoyaltyAmount, BoundedString> {
/// The owner of the NFT, can be either an Account or a tuple (CollectionId, NftId)
@@ -129,22 +125,19 @@
#[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]
pub struct NftChild {
pub collection_id: CollectionId,
- pub nft_id: NftId
+ pub nft_id: NftId,
}
#[cfg_attr(feature = "std", derive(Serialize))]
#[derive(Encode, Decode, PartialEq, TypeInfo)]
#[cfg_attr(
feature = "std",
- serde(
- bound = r#"
+ serde(bound = r#"
BoundedKey: AsRef<[u8]>,
BoundedValue: AsRef<[u8]>
- "#
- )
+ "#)
)]
-pub struct PropertyInfo<BoundedKey, BoundedValue>
-{
+pub struct PropertyInfo<BoundedKey, BoundedValue> {
/// Key of the property
#[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
pub key: BoundedKey,
@@ -156,10 +149,7 @@
#[derive(Encode, Decode, Default, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
#[cfg_attr(feature = "std", derive(Serialize))]
-#[cfg_attr(
- feature = "std",
- serde(bound = "BoundedString: AsRef<[u8]>")
-)]
+#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
pub struct BasicResource<BoundedString> {
/// If the resource is Media, the base property is absent. Media src should be a URI like an
/// IPFS hash.
@@ -188,12 +178,10 @@
#[cfg_attr(feature = "std", derive(Serialize))]
#[cfg_attr(
feature = "std",
- serde(
- bound = r#"
+ serde(bound = r#"
BoundedString: AsRef<[u8]>,
BoundedParts: AsRef<[PartId]>
- "#
- )
+ "#)
)]
pub struct ComposableResource<BoundedString, BoundedParts> {
/// If a resource is composed, it will have an array of parts that compose it
@@ -235,10 +223,7 @@
#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
#[cfg_attr(feature = "std", derive(Serialize))]
-#[cfg_attr(
- feature = "std",
- serde(bound = "BoundedString: AsRef<[u8]>")
-)]
+#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
pub struct SlotResource<BoundedString> {
/// A Base is uniquely identified by the combination of the word `base`, its minting block
/// number, and user provided symbol during Base creation, glued by dashes `-`, e.g.
@@ -279,14 +264,12 @@
#[cfg_attr(feature = "std", derive(Serialize))]
#[cfg_attr(
feature = "std",
- serde(
- bound = r#"
+ serde(bound = r#"
BoundedString: AsRef<[u8]>,
BoundedParts: AsRef<[PartId]>
- "#
- )
+ "#)
)]
-#[derivative(Default(bound=""))]
+#[derivative(Default(bound = ""))]
pub enum ResourceTypes<BoundedString: Default, BoundedParts> {
#[derivative(Default)]
Basic(BasicResource<BoundedString>),
@@ -294,18 +277,15 @@
Slot(SlotResource<BoundedString>),
}
-
#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
#[cfg_attr(feature = "std", derive(Serialize))]
#[cfg_attr(
feature = "std",
- serde(
- bound = r#"
+ serde(bound = r#"
BoundedResource: AsRef<[u8]>,
BoundedString: AsRef<[u8]>,
BoundedParts: AsRef<[PartId]>
- "#
- )
+ "#)
)]
pub struct ResourceInfo<BoundedResource, BoundedString: Default, BoundedParts> {
/// id is a 5-character string of reasonable uniqueness.
@@ -328,12 +308,10 @@
#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
#[cfg_attr(
feature = "std",
- serde(
- bound = r#"
+ serde(bound = r#"
AccountId: Serialize,
BoundedString: AsRef<[u8]>
- "#
- )
+ "#)
)]
pub struct BaseInfo<AccountId, BoundedString> {
/// Original creator of the Base
@@ -350,10 +328,7 @@
#[cfg_attr(feature = "std", derive(Serialize))]
#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]
-#[cfg_attr(
- feature = "std",
- serde(bound = "BoundedString: AsRef<[u8]>")
-)]
+#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
pub struct FixedPart<BoundedString> {
pub id: PartId,
pub z: ZIndex,
@@ -368,29 +343,24 @@
feature = "std",
serde(bound = "BoundedCollectionList: AsRef<[CollectionId]>")
)]
-#[derivative(Default(bound=""))]
+#[derivative(Default(bound = ""))]
pub enum EquippableList<BoundedCollectionList> {
All,
#[derivative(Default)]
Empty,
- Custom(
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- BoundedCollectionList
- ),
+ Custom(#[cfg_attr(feature = "std", serde(with = "serialize::vec"))] BoundedCollectionList),
}
#[cfg_attr(feature = "std", derive(Serialize))]
#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]
#[cfg_attr(
feature = "std",
- serde(
- bound = r#"
+ serde(bound = r#"
BoundedString: AsRef<[u8]>,
BoundedCollectionList: AsRef<[CollectionId]>
- "#
- )
+ "#)
)]
pub struct SlotPart<BoundedString, BoundedCollectionList> {
pub id: PartId,
@@ -406,12 +376,10 @@
#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]
#[cfg_attr(
feature = "std",
- serde(
- bound = r#"
+ serde(bound = r#"
BoundedString: AsRef<[u8]>,
BoundedCollectionList: AsRef<[CollectionId]>
- "#
- )
+ "#)
)]
pub enum PartType<BoundedString, BoundedCollectionList> {
FixedPart(FixedPart<BoundedString>),
@@ -422,21 +390,21 @@
pub fn id(&self) -> PartId {
match self {
Self::FixedPart(part) => part.id,
- Self::SlotPart(part) => part.id
+ Self::SlotPart(part) => part.id,
}
}
pub fn src(&self) -> &BoundedString {
match self {
Self::FixedPart(part) => &part.src,
- Self::SlotPart(part) => &part.src
+ Self::SlotPart(part) => &part.src,
}
}
pub fn z_index(&self) -> ZIndex {
match self {
Self::FixedPart(part) => part.z,
- Self::SlotPart(part) => part.z
+ Self::SlotPart(part) => part.z,
}
}
}
@@ -445,12 +413,10 @@
#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq)]
#[cfg_attr(
feature = "std",
- serde(
- bound = r#"
+ serde(bound = r#"
BoundedString: AsRef<[u8]>,
PropertyList: AsRef<[ThemeProperty<BoundedString>]>,
- "#
- )
+ "#)
)]
pub struct Theme<BoundedString, PropertyList> {
/// Name of the theme
@@ -466,10 +432,7 @@
#[cfg_attr(feature = "std", derive(Eq, Serialize))]
#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq)]
-#[cfg_attr(
- feature = "std",
- serde(bound = "BoundedString: AsRef<[u8]>")
-)]
+#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
pub struct ThemeProperty<BoundedString> {
/// Key of the property
#[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
runtime/tests/src/tests.rsdiffbeforeafterboth--- a/runtime/tests/src/tests.rs
+++ b/runtime/tests/src/tests.rs
@@ -19,9 +19,9 @@
use up_data_structs::{
COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,
CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, TokenId,
- MAX_TOKEN_OWNERSHIP, CreateCollectionData, CollectionMode,
- AccessMode, CollectionPermissions, PropertyKeyPermission, PropertyPermission,
- Property, CollectionPropertiesVec, CollectionPropertiesPermissionsVec,
+ MAX_TOKEN_OWNERSHIP, CreateCollectionData, CollectionMode, AccessMode, CollectionPermissions,
+ PropertyKeyPermission, PropertyPermission, Property, CollectionPropertiesVec,
+ CollectionPropertiesPermissionsVec,
};
use frame_support::{assert_noop, assert_ok, assert_err};
use sp_std::convert::TryInto;
@@ -47,12 +47,12 @@
fn default_nft_data() -> CreateNftData {
CreateNftData {
- properties: vec![
- Property {
- key: b"test-prop".to_vec().try_into().unwrap(),
- value: b"test-nft-prop".to_vec().try_into().unwrap(),
- },
- ].try_into().unwrap(),
+ properties: vec![Property {
+ key: b"test-prop".to_vec().try_into().unwrap(),
+ value: b"test-nft-prop".to_vec().try_into().unwrap(),
+ }]
+ .try_into()
+ .unwrap(),
}
}
@@ -77,22 +77,23 @@
let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
- let token_property_permissions: CollectionPropertiesPermissionsVec = vec![
- PropertyKeyPermission {
+ let token_property_permissions: CollectionPropertiesPermissionsVec =
+ vec![PropertyKeyPermission {
key: b"test-prop".to_vec().try_into().unwrap(),
permission: PropertyPermission {
mutable: true,
collection_admin: false,
token_owner: true,
},
- },
- ].try_into().unwrap();
- let properties: CollectionPropertiesVec = vec![
- Property {
- key: b"test-collection-prop".to_vec().try_into().unwrap(),
- value: b"test-collection-value".to_vec().try_into().unwrap(),
- }
- ].try_into().unwrap();
+ }]
+ .try_into()
+ .unwrap();
+ let properties: CollectionPropertiesVec = vec![Property {
+ key: b"test-collection-prop".to_vec().try_into().unwrap(),
+ value: b"test-collection-value".to_vec().try_into().unwrap(),
+ }]
+ .try_into()
+ .unwrap();
let data: CreateCollectionData<u64> = CreateCollectionData {
name: col_name1.try_into().unwrap(),
@@ -150,30 +151,21 @@
fn get_collection_property_permissions(collection_id: CollectionId) -> Vec<PropertyKeyPermission> {
<pallet_common::Pallet<Test>>::property_permissions(collection_id)
.into_iter()
- .map(|(key, permission)| PropertyKeyPermission {
- key,
- permission,
- })
+ .map(|(key, permission)| PropertyKeyPermission { key, permission })
.collect()
}
fn get_collection_properties(collection_id: CollectionId) -> Vec<Property> {
<pallet_common::Pallet<Test>>::collection_properties(collection_id)
.into_iter()
- .map(|(key, value)| Property {
- key,
- value,
- })
+ .map(|(key, value)| Property { key, value })
.collect()
}
fn get_token_properties(collection_id: CollectionId, token_id: TokenId) -> Vec<Property> {
<pallet_nonfungible::Pallet<Test>>::token_properties((collection_id, token_id))
.into_iter()
- .map(|(key, value)| Property {
- key,
- value,
- })
+ .map(|(key, value)| Property { key, value })
.collect()
}