difftreelog
Merge pull request #113 from usetech-llc/feature/NFTPAR-196_sponsor_setVariableMetadata
in: master
Sponsored setVariableMetadata
19 files changed
node/src/chain_spec.rsdiffbeforeafterboth--- a/node/src/chain_spec.rs
+++ b/node/src/chain_spec.rs
@@ -180,9 +180,9 @@
.collect(),
}),
pallet_nft: Some(NftConfig {
- collection: vec![(
+ collection_id: vec![(
1,
- CollectionType {
+ Collection {
owner: get_account_id_from_seed::<sr25519::Public>("Alice"),
mode: CollectionMode::NFT,
access: AccessMode::Normal,
pallets/nft/src/default_weights.rsdiffbeforeafterboth--- a/pallets/nft/src/default_weights.rs
+++ b/pallets/nft/src/default_weights.rs
@@ -127,6 +127,11 @@
.saturating_add(DbWeight::get().reads(0 as Weight))
.saturating_add(DbWeight::get().writes(2 as Weight))
}
+ fn set_variable_meta_data_sponsoring_rate_limit() -> Weight {
+ (3_500_000 as Weight)
+ .saturating_add(DbWeight::get().reads(2 as Weight))
+ .saturating_add(DbWeight::get().writes(1 as Weight))
+ }
fn toggle_contract_white_list() -> Weight {
(3_000_000 as Weight)
.saturating_add(DbWeight::get().reads(0 as Weight))
pallets/nft/src/lib.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -13,6 +13,7 @@
#[cfg(feature = "std")]
pub use serde::*;
+use core::ops::{Deref, DerefMut};
use codec::{Decode, Encode};
pub use frame_support::{
construct_runtime, decl_event, decl_module, decl_storage, decl_error,
@@ -160,10 +161,10 @@
}
}
-#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+#[derive(Encode, Decode, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub struct CollectionType<AccountId> {
- pub owner: AccountId,
+pub struct Collection<T: Config> {
+ pub owner: T::AccountId,
pub mode: CollectionMode,
pub access: AccessMode,
pub decimal_points: DecimalPoints,
@@ -174,11 +175,30 @@
pub offchain_schema: Vec<u8>,
pub schema_version: SchemaVersion,
pub sponsorship: SponsorshipState<AccountId>,
- pub limits: CollectionLimits, // Collection private restrictions
+ pub limits: CollectionLimits<T::BlockNumber>, // Collection private restrictions
pub variable_on_chain_schema: Vec<u8>, //
pub const_on_chain_schema: Vec<u8>, //
}
+pub struct CollectionHandle<T: Config> {
+ pub id: CollectionId,
+ collection: Collection<T>,
+}
+
+impl<T: Config> Deref for CollectionHandle<T> {
+ type Target = Collection<T>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.collection
+ }
+}
+
+impl<T: Config> DerefMut for CollectionHandle<T> {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.collection
+ }
+}
+
#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct NftItemType<AccountId> {
@@ -214,9 +234,13 @@
#[derive(Encode, Decode, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
-pub struct CollectionLimits {
+pub struct CollectionLimits<BlockNumber: Encode + Decode> {
pub account_token_ownership_limit: u32,
pub sponsored_data_size: u32,
+ /// None - setVariableMetadata is not sponsored
+ /// Some(v) - setVariableMetadata is sponsored
+ /// if there is v block between txs
+ pub sponsored_data_rate_limit: Option<BlockNumber>,
pub token_limit: u32,
// Timeouts for item types in passed blocks
@@ -225,12 +249,13 @@
pub owner_can_destroy: bool,
}
-impl Default for CollectionLimits {
- fn default() -> CollectionLimits {
- CollectionLimits {
+impl<BlockNumber: Encode + Decode> Default for CollectionLimits<BlockNumber> {
+ fn default() -> Self {
+ Self {
account_token_ownership_limit: 10_000_000,
token_limit: u32::max_value(),
- sponsored_data_size: u32::MAX,
+ sponsored_data_size: u32::MAX,
+ sponsored_data_rate_limit: None,
sponsor_transfer_timeout: 14400,
owner_can_transfer: true,
owner_can_destroy: true
@@ -283,6 +308,7 @@
fn set_schema_version() -> Weight;
fn set_chain_limits() -> Weight;
fn set_contract_sponsoring_rate_limit() -> Weight;
+ fn set_variable_meta_data_sponsoring_rate_limit() -> Weight;
fn toggle_contract_white_list() -> Weight;
fn add_to_contract_white_list() -> Weight;
fn remove_from_contract_white_list() -> Weight;
@@ -496,7 +522,7 @@
//#region Basic collections
/// Collection info
/// Collection id (controlled?1)
- pub Collection get(fn collection) config(): map hasher(blake2_128_concat) CollectionId => CollectionType<T::AccountId>;
+ pub CollectionById get(fn collection_id) config(): map hasher(blake2_128_concat) CollectionId => Option<Collection<T>> = None;
/// List of collection admins
/// Collection id (controlled?2)
pub AdminList get(fn admin_list_collection): map hasher(blake2_128_concat) CollectionId => Vec<T::AccountId>;
@@ -538,6 +564,10 @@
pub ReFungibleTransferBasket get(fn refungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => T::BlockNumber;
//#endregion
+ /// Variable metadata sponsoring
+ /// Collection id (controlled?2), token id (controlled?2)
+ pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber> = None;
+
//#region Contract Sponsorship and Ownership
/// Contract address (real)
pub ContractOwner get(fn contract_owner): map hasher(twox_64_concat) T::AccountId => T::AccountId;
@@ -556,7 +586,7 @@
add_extra_genesis {
build(|config: &GenesisConfig<T>| {
// Modification of storage
- for (_num, _c) in &config.collection {
+ for (_num, _c) in &config.collection_id {
<Module<T>>::init_collection(_c);
}
@@ -710,7 +740,7 @@
};
// Create new collection
- let new_collection = CollectionType {
+ let new_collection = Collection {
owner: who.clone(),
name: collection_name,
mode: mode.clone(),
@@ -728,7 +758,7 @@
};
// Add new collection to map
- <Collection<T>>::insert(next_id, new_collection);
+ <CollectionById<T>>::insert(next_id, new_collection);
// call event
Self::deposit_event(RawEvent::Created(next_id, mode.into(), who.clone()));
@@ -750,10 +780,9 @@
pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::check_owner_permissions(collection_id, sender)?;
-
- let target_collection = <Collection<T>>::get(collection_id);
- if !target_collection.limits.owner_can_destroy {
+ let collection = Self::get_collection(collection_id)?;
+ Self::check_owner_permissions(&collection, sender)?;
+ if !collection.limits.owner_can_destroy {
fail!(Error::<T>::NoPermission);
}
@@ -762,7 +791,7 @@
<Balance<T>>::remove_prefix(collection_id);
<ItemListIndex>::remove(collection_id);
<AdminList<T>>::remove(collection_id);
- <Collection<T>>::remove(collection_id);
+ <CollectionById<T>>::remove(collection_id);
<WhiteList<T>>::remove_prefix(collection_id);
<NftItemList<T>>::remove_prefix(collection_id);
@@ -773,6 +802,8 @@
<FungibleTransferBasket<T>>::remove_prefix(collection_id);
<ReFungibleTransferBasket<T>>::remove_prefix(collection_id);
+ <VariableMetaDataBasket<T>>::remove_prefix(collection_id);
+
DestroyedCollectionCount::put(DestroyedCollectionCount::get()
.checked_add(1)
.ok_or(Error::<T>::NumOverflow)?);
@@ -797,7 +828,8 @@
pub fn add_to_white_list(origin, collection_id: CollectionId, address: T::AccountId) -> DispatchResult{
let sender = ensure_signed(origin)?;
- Self::check_owner_or_admin_permissions(collection_id, sender)?;
+ let collection = Self::get_collection(collection_id)?;
+ Self::check_owner_or_admin_permissions(&collection, sender)?;
<WhiteList<T>>::insert(collection_id, address, true);
@@ -821,7 +853,8 @@
pub fn remove_from_white_list(origin, collection_id: CollectionId, address: T::AccountId) -> DispatchResult{
let sender = ensure_signed(origin)?;
- Self::check_owner_or_admin_permissions(collection_id, sender)?;
+ let collection = Self::get_collection(collection_id)?;
+ Self::check_owner_or_admin_permissions(&collection, sender)?;
<WhiteList<T>>::remove(collection_id, address);
@@ -845,10 +878,10 @@
{
let sender = ensure_signed(origin)?;
- Self::check_owner_permissions(collection_id, sender)?;
- let mut target_collection = <Collection<T>>::get(collection_id);
+ let mut target_collection = Self::get_collection(collection_id)?;
+ Self::check_owner_permissions(&target_collection, sender)?;
target_collection.access = mode;
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -872,10 +905,10 @@
{
let sender = ensure_signed(origin)?;
- Self::check_owner_permissions(collection_id, sender)?;
- let mut target_collection = <Collection<T>>::get(collection_id);
+ let mut target_collection = Self::get_collection(collection_id)?;
+ Self::check_owner_permissions(&target_collection, sender)?;
target_collection.mint_mode = mint_permission;
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -896,10 +929,10 @@
pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::check_owner_permissions(collection_id, sender)?;
- let mut target_collection = <Collection<T>>::get(collection_id);
+ let mut target_collection = Self::get_collection(collection_id)?;
+ Self::check_owner_permissions(&target_collection, sender)?;
target_collection.owner = new_owner;
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -922,7 +955,8 @@
pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::AccountId) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::check_owner_or_admin_permissions(collection_id, sender)?;
+ let collection = Self::get_collection(collection_id)?;
+ Self::check_owner_or_admin_permissions(&collection, sender)?;
let mut admin_arr: Vec<T::AccountId> = Vec::new();
if <AdminList<T>>::contains_key(collection_id)
@@ -957,7 +991,8 @@
pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::AccountId) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::check_owner_or_admin_permissions(collection_id, sender)?;
+ let collection = Self::get_collection(collection_id)?;
+ Self::check_owner_or_admin_permissions(&collection, sender)?;
ensure!(<AdminList<T>>::contains_key(collection_id), Error::<T>::AdminNotFound);
let mut admin_arr = <AdminList<T>>::get(collection_id);
@@ -981,13 +1016,11 @@
pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {
let sender = ensure_signed(origin)?;
- ensure!(<Collection<T>>::contains_key(collection_id), Error::<T>::CollectionNotFound);
-
- let mut target_collection = <Collection<T>>::get(collection_id);
- ensure!(sender == target_collection.owner, Error::<T>::NoPermission);
+ let mut target_collection = Self::get_collection(collection_id)?;
+ Self::check_owner_permissions(&target_collection, sender)?;
target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor);
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -1004,16 +1037,15 @@
pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {
let sender = ensure_signed(origin)?;
- ensure!(<Collection<T>>::contains_key(collection_id), Error::<T>::CollectionNotFound);
- let mut target_collection = <Collection<T>>::get(collection_id);
+ let mut target_collection = Self::get_collection(collection_id)?;
ensure!(
target_collection.sponsorship.pending_sponsor() == Some(&sender),
Error::<T>::ConfirmUnsetSponsorFail
);
target_collection.sponsorship = SponsorshipState::Confirmed(sender);
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -1032,13 +1064,12 @@
pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {
let sender = ensure_signed(origin)?;
- ensure!(<Collection<T>>::contains_key(collection_id), Error::<T>::CollectionNotFound);
- let mut target_collection = <Collection<T>>::get(collection_id);
- ensure!(sender == target_collection.owner, Error::<T>::NoPermission);
+ let mut target_collection = Self::get_collection(collection_id)?;
+ Self::check_owner_permissions(&target_collection, sender)?;
target_collection.sponsorship = SponsorshipState::Disabled;
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -1072,14 +1103,12 @@
pub fn create_item(origin, collection_id: CollectionId, owner: T::AccountId, data: CreateItemData) -> DispatchResult {
let sender = ensure_signed(origin)?;
-
- Self::collection_exists(collection_id)?;
- let target_collection = <Collection<T>>::get(collection_id);
+ let target_collection = Self::get_collection(collection_id)?;
- Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner, 1)?;
+ Self::can_create_items_in_collection(&target_collection, &sender, &owner, 1)?;
Self::validate_create_item_args(&target_collection, &data)?;
- Self::create_item_no_validation(collection_id, owner, data)?;
+ Self::create_item_no_validation(&target_collection, owner, data)?;
Ok(())
}
@@ -1111,16 +1140,15 @@
ensure!(items_data.len() > 0, Error::<T>::EmptyArgument);
let sender = ensure_signed(origin)?;
- Self::collection_exists(collection_id)?;
- let target_collection = <Collection<T>>::get(collection_id);
+ let target_collection = Self::get_collection(collection_id)?;
- Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner, items_data.len() as u32)?;
+ Self::can_create_items_in_collection(&target_collection, &sender, &owner, items_data.len() as u32)?;
for data in &items_data {
Self::validate_create_item_args(&target_collection, data)?;
}
for data in &items_data {
- Self::create_item_no_validation(collection_id, owner.clone(), data.clone())?;
+ Self::create_item_no_validation(&target_collection, owner.clone(), data.clone())?;
}
Ok(())
@@ -1144,33 +1172,32 @@
pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::collection_exists(collection_id)?;
// Transfer permissions check
- let target_collection = <Collection<T>>::get(collection_id);
+ let target_collection = Self::get_collection(collection_id)?;
ensure!(
- Self::is_item_owner(sender.clone(), collection_id, item_id) ||
+ Self::is_item_owner(sender.clone(), &target_collection, item_id) ||
(
target_collection.limits.owner_can_transfer &&
- Self::is_owner_or_admin_permissions(collection_id, sender.clone())
+ Self::is_owner_or_admin_permissions(&target_collection, sender.clone())
),
Error::<T>::NoPermission
);
if target_collection.access == AccessMode::WhiteList {
- Self::check_white_list(collection_id, &sender)?;
+ Self::check_white_list(&target_collection, &sender)?;
}
match target_collection.mode
{
- CollectionMode::NFT => Self::burn_nft_item(collection_id, item_id)?,
- CollectionMode::Fungible(_) => Self::burn_fungible_item(&sender, collection_id, value)?,
- CollectionMode::ReFungible => Self::burn_refungible_item(collection_id, item_id, &sender)?,
+ CollectionMode::NFT => Self::burn_nft_item(&target_collection, item_id)?,
+ CollectionMode::Fungible(_) => Self::burn_fungible_item(&sender, &target_collection, value)?,
+ CollectionMode::ReFungible => Self::burn_refungible_item(&target_collection, item_id, &sender)?,
_ => ()
};
// call event
- Self::deposit_event(RawEvent::ItemDestroyed(collection_id, item_id));
+ Self::deposit_event(RawEvent::ItemDestroyed(target_collection.id, item_id));
Ok(())
}
@@ -1202,7 +1229,9 @@
#[transactional]
pub fn transfer(origin, recipient: T::AccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::transfer_internal(sender, recipient, collection_id, item_id, value)
+ let collection = Self::get_collection(collection_id)?;
+
+ Self::transfer_internal(sender, recipient, &collection, item_id, value)
}
/// Set, change, or remove approved address to transfer the ownership of the NFT.
@@ -1225,16 +1254,14 @@
pub fn approve(origin, spender: T::AccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResult {
let sender = ensure_signed(origin)?;
+ let target_collection = Self::get_collection(collection_id)?;
- Self::collection_exists(collection_id)?;
- Self::token_exists(collection_id, item_id, &sender)?;
+ Self::token_exists(&target_collection, item_id, &sender)?;
// Transfer permissions check
- let target_collection = <Collection<T>>::get(collection_id);
-
let bypasses_limits = target_collection.limits.owner_can_transfer &&
Self::is_owner_or_admin_permissions(
- collection_id,
+ &target_collection,
sender.clone(),
);
@@ -1242,7 +1269,7 @@
None
} else if let Some(amount) = Self::owned_amount(
sender.clone(),
- collection_id,
+ &target_collection,
item_id,
) {
Some(amount)
@@ -1251,8 +1278,8 @@
};
if target_collection.access == AccessMode::WhiteList {
- Self::check_white_list(collection_id, &sender)?;
- Self::check_white_list(collection_id, &spender)?;
+ Self::check_white_list(&target_collection, &sender)?;
+ Self::check_white_list(&target_collection, &spender)?;
}
let allowance_exists = <Allowances<T>>::contains_key(collection_id, (item_id, &sender, &spender));
@@ -1292,6 +1319,8 @@
pub fn transfer_from(origin, from: T::AccountId, recipient: T::AccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResult {
let sender = ensure_signed(origin)?;
+ let target_collection = Self::get_collection(collection_id)?;
+
let mut appoved_transfer = false;
// Check approval
@@ -1302,24 +1331,22 @@
appoved_transfer = true;
}
- let target_collection = <Collection<T>>::get(collection_id);
-
// Limits check
- Self::is_correct_transfer(collection_id, &target_collection, &recipient)?;
+ Self::is_correct_transfer(&target_collection, &recipient)?;
// Transfer permissions check
ensure!(
appoved_transfer ||
(
target_collection.limits.owner_can_transfer &&
- Self::is_owner_or_admin_permissions(collection_id, sender.clone())
+ Self::is_owner_or_admin_permissions(&target_collection, sender.clone())
),
Error::<T>::NoPermission
);
if target_collection.access == AccessMode::WhiteList {
- Self::check_white_list(collection_id, &sender)?;
- Self::check_white_list(collection_id, &recipient)?;
+ Self::check_white_list(&target_collection, &sender)?;
+ Self::check_white_list(&target_collection, &recipient)?;
}
// Reduce approval by transferred amount or remove if remaining approval drops to 0
@@ -1332,9 +1359,9 @@
match target_collection.mode
{
- CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, from, recipient)?,
- CollectionMode::Fungible(_) => Self::transfer_fungible(collection_id, value, &from, &recipient)?,
- CollectionMode::ReFungible => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?,
+ CollectionMode::NFT => Self::transfer_nft(&target_collection, item_id, from, recipient)?,
+ CollectionMode::Fungible(_) => Self::transfer_fungible(&target_collection, value, &from, &recipient)?,
+ CollectionMode::ReFungible => Self::transfer_refungible(&target_collection, item_id, value, from.clone(), recipient)?,
_ => ()
};
@@ -1378,21 +1405,20 @@
) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::collection_exists(collection_id)?;
- Self::token_exists(collection_id, item_id, &sender)?;
+ let target_collection = Self::get_collection(collection_id)?;
+ Self::token_exists(&target_collection, item_id, &sender)?;
ensure!(ChainLimit::get().custom_data_limit >= data.len() as u32, Error::<T>::TokenVariableDataLimitExceeded);
// Modify permissions check
- let target_collection = <Collection<T>>::get(collection_id);
- ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) ||
- Self::is_owner_or_admin_permissions(collection_id, sender.clone()),
+ ensure!(Self::is_item_owner(sender.clone(), &target_collection, item_id) ||
+ Self::is_owner_or_admin_permissions(&target_collection, sender.clone()),
Error::<T>::NoPermission);
match target_collection.mode
{
- CollectionMode::NFT => Self::set_nft_variable_data(collection_id, item_id, data)?,
- CollectionMode::ReFungible => Self::set_re_fungible_variable_data(collection_id, item_id, data)?,
+ CollectionMode::NFT => Self::set_nft_variable_data(&target_collection, item_id, data)?,
+ CollectionMode::ReFungible => Self::set_re_fungible_variable_data(&target_collection, item_id, data)?,
CollectionMode::Fungible(_) => fail!(Error::<T>::CantStoreMetadataInFungibleTokens),
_ => fail!(Error::<T>::UnexpectedCollectionType)
};
@@ -1422,10 +1448,10 @@
version: SchemaVersion
) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
- let mut target_collection = <Collection<T>>::get(collection_id);
+ let mut target_collection = Self::get_collection(collection_id)?;
+ Self::check_owner_or_admin_permissions(&target_collection, sender.clone())?;
target_collection.schema_version = version;
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -1450,14 +1476,14 @@
schema: Vec<u8>
) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+ let mut target_collection = Self::get_collection(collection_id)?;
+ Self::check_owner_or_admin_permissions(&target_collection, sender.clone())?;
// check schema limit
ensure!(schema.len() as u32 <= ChainLimit::get().offchain_schema_limit, "");
- let mut target_collection = <Collection<T>>::get(collection_id);
target_collection.offchain_schema = schema;
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -1482,14 +1508,14 @@
schema: Vec<u8>
) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+ let mut target_collection = Self::get_collection(collection_id)?;
+ Self::check_owner_or_admin_permissions(&target_collection, sender.clone())?;
// check schema limit
ensure!(schema.len() as u32 <= ChainLimit::get().const_on_chain_schema_limit, "");
- let mut target_collection = <Collection<T>>::get(collection_id);
target_collection.const_on_chain_schema = schema;
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -1514,14 +1540,14 @@
schema: Vec<u8>
) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
+ let mut target_collection = Self::get_collection(collection_id)?;
+ Self::check_owner_or_admin_permissions(&target_collection, sender.clone())?;
// check schema limit
ensure!(schema.len() as u32 <= ChainLimit::get().variable_on_chain_schema_limit, "");
- let mut target_collection = <Collection<T>>::get(collection_id);
target_collection.variable_on_chain_schema = schema;
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -1694,12 +1720,12 @@
pub fn set_collection_limits(
origin,
collection_id: u32,
- new_limits: CollectionLimits,
+ new_limits: CollectionLimits<T::BlockNumber>,
) -> DispatchResult {
let sender = ensure_signed(origin)?;
- Self::check_owner_permissions(collection_id, sender.clone())?;
- let mut target_collection = <Collection<T>>::get(collection_id);
- let old_limits = target_collection.limits;
+ let mut target_collection = Self::get_collection(collection_id)?;
+ Self::check_owner_permissions(&target_collection, sender.clone())?;
+ let old_limits = &target_collection.limits;
let chain_limits = ChainLimit::get();
// collection bounds
@@ -1719,7 +1745,7 @@
);
target_collection.limits = new_limits;
- <Collection<T>>::insert(collection_id, target_collection);
+ Self::save_collection(target_collection);
Ok(())
}
@@ -1728,38 +1754,36 @@
impl<T: Config> Module<T> {
- pub fn transfer_internal(sender: T::AccountId, recipient: T::AccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult {
-
- let target_collection = <Collection<T>>::get(collection_id);
-
+ pub fn transfer_internal(sender: T::AccountId, recipient: T::AccountId, target_collection: &CollectionHandle<T>, item_id: TokenId, value: u128) -> DispatchResult {
// Limits check
- Self::is_correct_transfer(collection_id, &target_collection, &recipient)?;
+ Self::is_correct_transfer(target_collection, &recipient)?;
// Transfer permissions check
- ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id) ||
- Self::is_owner_or_admin_permissions(collection_id, sender.clone()),
+ ensure!(Self::is_item_owner(sender.clone(), target_collection, item_id) ||
+ Self::is_owner_or_admin_permissions(target_collection, sender.clone()),
Error::<T>::NoPermission);
if target_collection.access == AccessMode::WhiteList {
- Self::check_white_list(collection_id, &sender)?;
- Self::check_white_list(collection_id, &recipient)?;
+ Self::check_white_list(target_collection, &sender)?;
+ Self::check_white_list(target_collection, &recipient)?;
}
match target_collection.mode
{
- CollectionMode::NFT => Self::transfer_nft(collection_id, item_id, sender.clone(), recipient.clone())?,
- CollectionMode::Fungible(_) => Self::transfer_fungible(collection_id, value, &sender, &recipient)?,
- CollectionMode::ReFungible => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient.clone())?,
+ CollectionMode::NFT => Self::transfer_nft(target_collection, item_id, sender.clone(), recipient.clone())?,
+ CollectionMode::Fungible(_) => Self::transfer_fungible(target_collection, value, &sender, &recipient)?,
+ CollectionMode::ReFungible => Self::transfer_refungible(target_collection, item_id, value, sender.clone(), recipient.clone())?,
_ => ()
};
- Self::deposit_event(RawEvent::Transfer(collection_id, item_id, sender, recipient, value));
+ Self::deposit_event(RawEvent::Transfer(target_collection.id, item_id, sender, recipient, value));
Ok(())
}
- fn is_correct_transfer(collection_id: CollectionId, collection: &CollectionType<T::AccountId>, recipient: &T::AccountId) -> DispatchResult {
+ fn is_correct_transfer(collection: &CollectionHandle<T>, recipient: &T::AccountId) -> DispatchResult {
+ let collection_id = collection.id;
// check token limit and account token limit
let account_items: u32 = <AddressTokens<T>>::get(collection_id, recipient).len() as u32;
@@ -1768,7 +1792,8 @@
Ok(())
}
- fn can_create_items_in_collection(collection_id: CollectionId, collection: &CollectionType<T::AccountId>, sender: &T::AccountId, owner: &T::AccountId, amount: u32) -> DispatchResult {
+ fn can_create_items_in_collection(collection: &CollectionHandle<T>, sender: &T::AccountId, owner: &T::AccountId, amount: u32) -> DispatchResult {
+ let collection_id = collection.id;
// check token limit and account token limit
let total_items: u32 = ItemListIndex::get(collection_id)
@@ -1780,16 +1805,16 @@
ensure!(collection.limits.token_limit >= total_items, Error::<T>::CollectionTokenLimitExceeded);
ensure!(collection.limits.account_token_ownership_limit >= account_items, Error::<T>::AccountTokenLimitExceeded);
- if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {
+ if !Self::is_owner_or_admin_permissions(collection, sender.clone()) {
ensure!(collection.mint_mode == true, Error::<T>::PublicMintingNotAllowed);
- Self::check_white_list(collection_id, owner)?;
- Self::check_white_list(collection_id, sender)?;
+ Self::check_white_list(collection, owner)?;
+ Self::check_white_list(collection, sender)?;
}
Ok(())
}
- fn validate_create_item_args(target_collection: &CollectionType<T::AccountId>, data: &CreateItemData) -> DispatchResult {
+ fn validate_create_item_args(target_collection: &CollectionHandle<T>, data: &CreateItemData) -> DispatchResult {
match target_collection.mode
{
CollectionMode::NFT => {
@@ -1827,7 +1852,9 @@
Ok(())
}
- fn create_item_no_validation(collection_id: CollectionId, owner: T::AccountId, data: CreateItemData) -> DispatchResult {
+ fn create_item_no_validation(collection: &CollectionHandle<T>, owner: T::AccountId, data: CreateItemData) -> DispatchResult {
+ let collection_id = collection.id;
+
match data
{
CreateItemData::NFT(data) => {
@@ -1837,10 +1864,10 @@
variable_data: data.variable_data
};
- Self::add_nft_item(collection_id, item)?;
+ Self::add_nft_item(collection, item)?;
},
CreateItemData::Fungible(data) => {
- Self::add_fungible_item(collection_id, &owner, data.value)?;
+ Self::add_fungible_item(collection, &owner, data.value)?;
},
CreateItemData::ReFungible(data) => {
let mut owner_list = Vec::new();
@@ -1852,14 +1879,15 @@
variable_data: data.variable_data
};
- Self::add_refungible_item(collection_id, item)?;
+ Self::add_refungible_item(collection, item)?;
}
};
Ok(())
}
- fn add_fungible_item(collection_id: CollectionId, owner: &T::AccountId, value: u128) -> DispatchResult {
+ fn add_fungible_item(collection: &CollectionHandle<T>, owner: &T::AccountId, value: u128) -> DispatchResult {
+ let collection_id = collection.id;
// Does new owner already have an account?
let mut balance: u128 = 0;
@@ -1883,7 +1911,9 @@
Ok(())
}
- fn add_refungible_item(collection_id: CollectionId, item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
+ fn add_refungible_item(collection: &CollectionHandle<T>, item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
+ let collection_id = collection.id;
+
let current_index = <ItemListIndex>::get(collection_id)
.checked_add(1)
.ok_or(Error::<T>::NumOverflow)?;
@@ -1913,7 +1943,9 @@
Ok(())
}
- fn add_nft_item(collection_id: CollectionId, item: NftItemType<T::AccountId>) -> DispatchResult {
+ fn add_nft_item(collection: &CollectionHandle<T>, item: NftItemType<T::AccountId>) -> DispatchResult {
+ let collection_id = collection.id;
+
let current_index = <ItemListIndex>::get(collection_id)
.checked_add(1)
.ok_or(Error::<T>::NumOverflow)?;
@@ -1935,10 +1967,12 @@
}
fn burn_refungible_item(
- collection_id: CollectionId,
+ collection: &CollectionHandle<T>,
item_id: TokenId,
owner: &T::AccountId,
) -> DispatchResult {
+ let collection_id = collection.id;
+
ensure!(
<ReFungibleItemList<T>>::contains_key(collection_id, item_id),
Error::<T>::TokenNotFound
@@ -1969,6 +2003,7 @@
// Burn the token completely if this was the last (only) owner
if owner_count == 0 {
<ReFungibleItemList<T>>::remove(collection_id, item_id);
+ <VariableMetaDataBasket<T>>::remove(collection_id, item_id);
}
else {
<ReFungibleItemList<T>>::insert(collection_id, item_id, token);
@@ -1977,7 +2012,9 @@
Ok(())
}
- fn burn_nft_item(collection_id: CollectionId, item_id: TokenId) -> DispatchResult {
+ fn burn_nft_item(collection: &CollectionHandle<T>, item_id: TokenId) -> DispatchResult {
+ let collection_id = collection.id;
+
ensure!(
<NftItemList<T>>::contains_key(collection_id, item_id),
Error::<T>::TokenNotFound
@@ -1991,11 +2028,14 @@
.ok_or(Error::<T>::NumOverflow)?;
<Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
<NftItemList<T>>::remove(collection_id, item_id);
+ <VariableMetaDataBasket<T>>::remove(collection_id, item_id);
Ok(())
}
- fn burn_fungible_item(owner: &T::AccountId, collection_id: CollectionId, value: u128) -> DispatchResult {
+ fn burn_fungible_item(owner: &T::AccountId, collection: &CollectionHandle<T>, value: u128) -> DispatchResult {
+ let collection_id = collection.id;
+
ensure!(
<FungibleItemList<T>>::contains_key(collection_id, owner),
Error::<T>::TokenNotFound
@@ -2020,18 +2060,20 @@
Ok(())
}
- fn collection_exists(collection_id: CollectionId) -> DispatchResult {
- ensure!(
- <Collection<T>>::contains_key(collection_id),
- Error::<T>::CollectionNotFound
- );
- Ok(())
+ pub fn get_collection(collection_id: CollectionId) -> Result<CollectionHandle<T>, sp_runtime::DispatchError> {
+ Ok(<CollectionById<T>>::get(collection_id)
+ .map(|collection| CollectionHandle {
+ id: collection_id,
+ collection
+ })
+ .ok_or(Error::<T>::CollectionNotFound)?)
}
- fn check_owner_permissions(collection_id: CollectionId, subject: T::AccountId) -> DispatchResult {
- Self::collection_exists(collection_id)?;
+ fn save_collection(collection: CollectionHandle<T>) {
+ <CollectionById<T>>::insert(collection.id, collection.collection);
+ }
- let target_collection = <Collection<T>>::get(collection_id);
+ fn check_owner_permissions(target_collection: &CollectionHandle<T>, subject: T::AccountId) -> DispatchResult {
ensure!(
subject == target_collection.owner,
Error::<T>::NoPermission
@@ -2040,13 +2082,12 @@
Ok(())
}
- fn is_owner_or_admin_permissions(collection_id: CollectionId, subject: T::AccountId) -> bool {
- let target_collection = <Collection<T>>::get(collection_id);
- let mut result: bool = subject == target_collection.owner;
- let exists = <AdminList<T>>::contains_key(collection_id);
+ fn is_owner_or_admin_permissions(collection: &CollectionHandle<T>, subject: T::AccountId) -> bool {
+ let mut result: bool = subject == collection.owner;
+ let exists = <AdminList<T>>::contains_key(collection.id);
if !result & exists {
- if <AdminList<T>>::get(collection_id).contains(&subject) {
+ if <AdminList<T>>::get(collection.id).contains(&subject) {
result = true
}
}
@@ -2055,11 +2096,10 @@
}
fn check_owner_or_admin_permissions(
- collection_id: CollectionId,
+ collection: &CollectionHandle<T>,
subject: T::AccountId,
) -> DispatchResult {
- Self::collection_exists(collection_id)?;
- let result = Self::is_owner_or_admin_permissions(collection_id, subject.clone());
+ let result = Self::is_owner_or_admin_permissions(collection, subject.clone());
ensure!(
result,
@@ -2070,10 +2110,10 @@
fn owned_amount(
subject: T::AccountId,
- collection_id: CollectionId,
+ target_collection: &CollectionHandle<T>,
item_id: TokenId,
) -> Option<u128> {
- let target_collection = <Collection<T>>::get(collection_id);
+ let collection_id = target_collection.id;
match target_collection.mode {
CollectionMode::NFT => {
@@ -2098,8 +2138,8 @@
}
}
- fn is_item_owner(subject: T::AccountId, collection_id: CollectionId, item_id: TokenId) -> bool {
- let target_collection = <Collection<T>>::get(collection_id);
+ fn is_item_owner(subject: T::AccountId, target_collection: &CollectionHandle<T>, item_id: TokenId) -> bool {
+ let collection_id = target_collection.id;
match target_collection.mode {
CollectionMode::NFT => {
@@ -2118,7 +2158,9 @@
}
}
- fn check_white_list(collection_id: CollectionId, address: &T::AccountId) -> DispatchResult {
+ fn check_white_list(collection: &CollectionHandle<T>, address: &T::AccountId) -> DispatchResult {
+ let collection_id = collection.id;
+
let mes = Error::<T>::AddresNotInWhiteList;
ensure!(<WhiteList<T>>::contains_key(collection_id, address), mes);
@@ -2128,11 +2170,11 @@
/// Check if token exists. In case of Fungible, check if there is an entry for
/// the owner in fungible balances double map
fn token_exists(
- collection_id: CollectionId,
+ target_collection: &CollectionHandle<T>,
item_id: TokenId,
owner: &T::AccountId
) -> DispatchResult {
- let target_collection = <Collection<T>>::get(collection_id);
+ let collection_id = target_collection.id;
let exists = match target_collection.mode
{
CollectionMode::NFT => <NftItemList<T>>::contains_key(collection_id, item_id),
@@ -2146,18 +2188,19 @@
}
fn transfer_fungible(
- collection_id: CollectionId,
+ collection: &CollectionHandle<T>,
value: u128,
owner: &T::AccountId,
recipient: &T::AccountId,
) -> DispatchResult {
- Self::token_exists(collection_id, 0, owner)?;
+ let collection_id = collection.id;
+ Self::token_exists(&collection, 0, owner)?;
let mut balance = <FungibleItemList<T>>::get(collection_id, owner);
ensure!(balance.value >= value, Error::<T>::TokenValueTooLow);
// Send balance to recipient (updates balanceOf of recipient)
- Self::add_fungible_item(collection_id, recipient, value)?;
+ Self::add_fungible_item(collection, recipient, value)?;
// update balanceOf of sender
<Balance<T>>::insert(collection_id, (*owner).clone(), balance.value - value);
@@ -2175,13 +2218,14 @@
}
fn transfer_refungible(
- collection_id: CollectionId,
+ collection: &CollectionHandle<T>,
item_id: TokenId,
value: u128,
owner: T::AccountId,
new_owner: T::AccountId,
) -> DispatchResult {
- Self::token_exists(collection_id, item_id, &owner)?;
+ let collection_id = collection.id;
+ Self::token_exists(collection, item_id, &owner)?;
let full_item = <ReFungibleItemList<T>>::get(collection_id, item_id);
let item = full_item
@@ -2257,12 +2301,13 @@
}
fn transfer_nft(
- collection_id: CollectionId,
+ collection: &CollectionHandle<T>,
item_id: TokenId,
sender: T::AccountId,
new_owner: T::AccountId,
) -> DispatchResult {
- Self::token_exists(collection_id, item_id, &sender)?;
+ let collection_id = collection.id;
+ Self::token_exists(&collection, item_id, &sender)?;
let mut item = <NftItemList<T>>::get(collection_id, item_id);
@@ -2294,10 +2339,11 @@
}
fn set_re_fungible_variable_data(
- collection_id: CollectionId,
+ collection: &CollectionHandle<T>,
item_id: TokenId,
data: Vec<u8>
) -> DispatchResult {
+ let collection_id = collection.id;
let mut item = <ReFungibleItemList<T>>::get(collection_id, item_id);
item.variable_data = data;
@@ -2308,10 +2354,11 @@
}
fn set_nft_variable_data(
- collection_id: CollectionId,
+ collection: &CollectionHandle<T>,
item_id: TokenId,
data: Vec<u8>
) -> DispatchResult {
+ let collection_id = collection.id;
let mut item = <NftItemList<T>>::get(collection_id, item_id);
item.variable_data = data;
@@ -2321,7 +2368,7 @@
Ok(())
}
- fn init_collection(item: &CollectionType<T::AccountId>) {
+ fn init_collection(item: &Collection<T>) {
// check params
assert!(
item.decimal_points <= MAX_DECIMAL_POINTS,
@@ -2401,7 +2448,6 @@
}
fn add_token_index(collection_id: CollectionId, item_index: TokenId, owner: &T::AccountId) -> DispatchResult {
-
// add to account limit
if <AccountItemCount<T>>::contains_key(owner) {
@@ -2569,8 +2615,9 @@
// Determine who is paying transaction fee based on ecnomic model
// Parse call to extract collection ID and access collection sponsor
- let mut sponsor: T::AccountId = match IsSubType::<Call<T>>::is_sub_type(call) {
+ let mut sponsor: Option<T::AccountId> = (|| match IsSubType::<Call<T>>::is_sub_type(call) {
Some(Call::create_item(collection_id, _owner, _properties)) => {
+ let collection = <CollectionById<T>>::get(collection_id)?;
// sponsor timeout
let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
@@ -2583,12 +2630,10 @@
let last_tx_block = <CreateItemBasket<T>>::get((collection_id, &who));
let limit_time = last_tx_block + limit.into();
if block_number <= limit_time {
- sponsored = false;
+ return None;
}
}
- if sponsored {
- <CreateItemBasket<T>>::insert((collection_id, who.clone()), block_number);
- }
+ <CreateItemBasket<T>>::insert((collection_id, who.clone()), block_number);
// check free create limit
if (collection.limits.sponsored_data_size >= (_properties.len() as u32)) &&
@@ -2596,18 +2641,18 @@
{
collection.sponsorship.sponsor()
.cloned()
- .unwrap_or_default()
} else {
- T::AccountId::default()
+ None
}
}
Some(Call::transfer(_new_owner, collection_id, item_id, _value)) => {
+ let collection = <CollectionById<T>>::get(collection_id)?;
let mut sponsor_transfer = false;
- if <Collection<T>>::get(collection_id).sponsorship.confirmed() {
+ if collection.sponsorship.confirmed() {
- let collection_limits = <Collection<T>>::get(collection_id).limits;
- let collection_mode = <Collection<T>>::get(collection_id).mode;
+ let collection_limits = collection.limits;
+ let collection_mode = collection.mode;
// sponsor timeout
let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
@@ -2689,19 +2734,68 @@
}
if !sponsor_transfer {
- T::AccountId::default()
+ None
} else {
- <Collection<T>>::get(collection_id).sponsorship.sponsor()
+ collection.sponsorship.sponsor()
.cloned()
- .unwrap_or_default()
}
}
- _ => T::AccountId::default(),
- };
+ Some(Call::set_variable_meta_data(collection_id, item_id, data)) => {
+ let mut sponsor_metadata_changes = false;
+
+ let collection = <CollectionById<T>>::get(collection_id)?;
+
+ if
+ collection.sponsor_confirmed &&
+ // Can't sponsor fungible collection, this tx will be rejected
+ // as invalid
+ !matches!(collection.mode, CollectionMode::Fungible(_)) &&
+ data.len() <= collection.limits.sponsored_data_size as usize
+ {
+ if let Some(rate_limit) = collection.limits.sponsored_data_rate_limit {
+ let block_number = <system::Module<T>>::block_number() as T::BlockNumber;
+
+ if <VariableMetaDataBasket<T>>::get(collection_id, item_id)
+ .map(|last_block| block_number - last_block > rate_limit)
+ .unwrap_or(true)
+ {
+ sponsor_metadata_changes = true;
+ <VariableMetaDataBasket<T>>::insert(collection_id, item_id, block_number);
+ }
+ }
+ }
+
+ if !sponsor_metadata_changes {
+ None
+ } else {
+ Some(collection.sponsor)
+ }
+ }
+
+ _ => None,
+ })();
+
+ match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
+ Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => {
+ let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default());
+
+ let owned_contract = <ContractOwner<T>>::contains_key(called_contract.clone())
+ && <ContractOwner<T>>::get(called_contract.clone()) == *who;
+ let white_list_enabled = <ContractWhiteListEnabled<T>>::contains_key(called_contract.clone()) && <ContractWhiteListEnabled<T>>::get(called_contract.clone());
+
+ if !owned_contract && white_list_enabled {
+ if !<ContractWhiteList<T>>::contains_key(called_contract.clone(), who) {
+ return Err(InvalidTransaction::Call.into());
+ }
+ }
+ },
+ _ => {},
+ }
+
// Sponsor smart contracts
- sponsor = match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
+ sponsor = sponsor.or_else(|| match IsSubType::<pallet_contracts::Call<T>>::is_sub_type(call) {
// On instantiation: set the contract owner
Some(pallet_contracts::Call::instantiate(_endowment, _gas_limit, code_hash, _data, salt)) => {
@@ -2713,7 +2807,7 @@
);
<ContractOwner<T>>::insert(new_contract_address.clone(), who.clone());
- T::AccountId::default()
+ None
},
// On instantiation with code: set the contract owner
@@ -2727,23 +2821,13 @@
<ContractOwner<T>>::insert(new_contract_address.clone(), who.clone());
- T::AccountId::default()
+ None
}
// When the contract is called, check if the sponsoring is enabled and pay fees from contract endowment if it is
Some(pallet_contracts::Call::call(dest, _value, _gas_limit, _data)) => {
let called_contract: T::AccountId = T::Lookup::lookup((*dest).clone()).unwrap_or(T::AccountId::default());
-
- let owned_contract = <ContractOwner<T>>::contains_key(called_contract.clone())
- && <ContractOwner<T>>::get(called_contract.clone()) == *who;
- let white_list_enabled = <ContractWhiteListEnabled<T>>::contains_key(called_contract.clone()) && <ContractWhiteListEnabled<T>>::get(called_contract.clone());
-
- if !owned_contract && white_list_enabled {
- if !<ContractWhiteList<T>>::contains_key(called_contract.clone(), who) {
- return Err(InvalidTransaction::Call.into());
- }
- }
let mut sponsor_transfer = false;
if <ContractSponsoringRateLimit<T>>::contains_key(called_contract.clone()) {
@@ -2760,26 +2844,21 @@
sponsor_transfer = false;
}
-
- let mut sp = T::AccountId::default();
if sponsor_transfer {
if <ContractSelfSponsoring<T>>::contains_key(called_contract.clone()) {
if <ContractSelfSponsoring<T>>::get(called_contract.clone()) {
- sp = called_contract;
+ return Some(called_contract);
}
}
}
- sp
+ None
},
- _ => sponsor,
- };
+ _ => None,
+ });
- let mut who_pays_fee: T::AccountId = sponsor.clone();
- if sponsor == T::AccountId::default() {
- who_pays_fee = who.clone();
- }
+ let who_pays_fee = sponsor.unwrap_or_else(|| who.clone());
<<T as pallet_transaction_payment::Config>::OnChargeTransaction as pallet_transaction_payment::OnChargeTransaction<T>>::withdraw_fee(&who_pays_fee, call, info, fee, tip)
.map(|i| (fee, i))
pallets/nft/src/tests.rsdiffbeforeafterboth1// Tests to be written here2use super::*;3use crate::mock::*;4use crate::{AccessMode, CollectionMode,5 Ownership, ChainLimits, CreateItemData, CreateNftData, CreateFungibleData, CreateReFungibleData,6 CollectionId, TokenId, MAX_DECIMAL_POINTS};7use frame_support::{assert_noop, assert_ok};8use frame_system::{ RawOrigin };910fn default_collection_numbers_limit() -> u32 {11 1012}1314fn default_limits() {15 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits {16 collection_numbers_limit: default_collection_numbers_limit(),17 account_token_ownership_limit: 10,18 collections_admins_limit: 5,19 custom_data_limit: 2048,20 nft_sponsor_transfer_timeout: 15,21 fungible_sponsor_transfer_timeout: 15,22 refungible_sponsor_transfer_timeout: 15,23 const_on_chain_schema_limit: 1024,24 offchain_schema_limit: 1024,25 variable_on_chain_schema_limit: 1024,26 }));27}2829fn default_nft_data() -> CreateNftData {30 CreateNftData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] }31}3233fn default_fungible_data () -> CreateFungibleData {34 CreateFungibleData { value: 5 }35}3637fn default_re_fungible_data () -> CreateReFungibleData {38 CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1], pieces: 1023 }39}4041fn create_test_collection_for_owner(mode: &CollectionMode, owner: u64, id: CollectionId) -> CollectionId {42 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();43 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();44 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();4546 let origin1 = Origin::signed(owner);47 assert_ok!(TemplateModule::create_collection(48 origin1.clone(),49 col_name1.clone(),50 col_desc1.clone(),51 token_prefix1.clone(),52 mode.clone()53 ));5455 let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();56 let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();57 let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();58 assert_eq!(TemplateModule::collection(id).owner, owner);59 assert_eq!(TemplateModule::collection(id).name, saved_col_name);60 assert_eq!(TemplateModule::collection(id).mode, *mode);61 assert_eq!(TemplateModule::collection(id).description, saved_description);62 assert_eq!(TemplateModule::collection(id).token_prefix, saved_prefix);63 id64}6566fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {67 create_test_collection_for_owner(&mode, 1, id)68}6970fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {71 let origin1 = Origin::signed(1);72 assert_ok!(TemplateModule::create_item(73 origin1.clone(),74 collection_id,75 1,76 data.clone()77 ));7879}8081// Use cases tests region82// #region8384#[test]85fn set_version_schema() {86 new_test_ext().execute_with(|| {87 default_limits();88 let origin1 = Origin::signed(1);89 let collection_id = create_test_collection(&CollectionMode::NFT, 1);90 91 assert_ok!(TemplateModule::set_schema_version(origin1, collection_id, SchemaVersion::Unique));92 assert_eq!(TemplateModule::collection(collection_id).schema_version, SchemaVersion::Unique);93 });94}9596#[test]97fn create_fungible_collection_fails_with_large_decimal_numbers() {98 new_test_ext().execute_with(|| {99 default_limits();100101 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();102 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();103 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();104105 let origin1 = Origin::signed(1);106 assert_noop!(TemplateModule::create_collection(107 origin1,108 col_name1,109 col_desc1,110 token_prefix1,111 CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1)112 ), Error::<Test>::CollectionDecimalPointLimitExceeded);113 }); 114}115116#[test]117fn create_nft_item() {118 new_test_ext().execute_with(|| {119 default_limits();120 let collection_id = create_test_collection(&CollectionMode::NFT, 1);121 122 let data = default_nft_data();123 create_test_item(collection_id, &data.clone().into());124 assert_eq!(TemplateModule::nft_item_id(collection_id, 1).const_data, data.const_data);125 assert_eq!(TemplateModule::nft_item_id(collection_id, 1).variable_data, data.variable_data);126 });127}128129// Use cases tests region130// #region131#[test]132fn create_nft_multiple_items() {133 new_test_ext().execute_with(|| {134 default_limits();135 136 create_test_collection(&CollectionMode::NFT, 1);137138 let origin1 = Origin::signed(1);139140 let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];141142 assert_ok!(TemplateModule::create_multiple_items(143 origin1.clone(),144 1,145 1,146 items_data.clone().into_iter().map(|d| { d.into() }).collect()147 ));148 for (index, data) in items_data.iter().enumerate() {149 assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as TokenId).const_data.to_vec(), data.const_data);150 assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as TokenId).variable_data.to_vec(), data.variable_data);151 }152 });153}154155#[test]156fn create_refungible_item() {157 new_test_ext().execute_with(|| {158 default_limits();159 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);160161 let data = default_re_fungible_data();162 create_test_item(collection_id, &data.clone().into());163 assert_eq!(164 TemplateModule::refungible_item_id(collection_id, 1).const_data,165 data.const_data166 );167 assert_eq!(168 TemplateModule::refungible_item_id(collection_id, 1).variable_data,169 data.variable_data170 );171 assert_eq!(172 TemplateModule::refungible_item_id(collection_id, 1).owner[0],173 Ownership {174 owner: 1,175 fraction: 1023176 }177 );178 });179}180181#[test]182fn create_multiple_refungible_items() {183 new_test_ext().execute_with(|| {184 default_limits();185 186 create_test_collection(&CollectionMode::ReFungible, 1);187188 let origin1 = Origin::signed(1);189190 let items_data = vec![default_re_fungible_data(), default_re_fungible_data(), default_re_fungible_data()];191192 assert_ok!(TemplateModule::create_multiple_items(193 origin1.clone(),194 1,195 1,196 items_data.clone().into_iter().map(|d| { d.into() }).collect()197 ));198 for (index, data) in items_data.iter().enumerate() {199200 let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId);201 assert_eq!(item.const_data.to_vec(), data.const_data);202 assert_eq!(item.variable_data.to_vec(), data.variable_data);203 assert_eq!(204 item.owner[0],205 Ownership {206 owner: 1,207 fraction: 1023208 }209 );210 }211 });212}213214#[test]215fn create_fungible_item() {216 new_test_ext().execute_with(|| {217 default_limits();218 219 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);220221 let data = default_fungible_data();222 create_test_item(collection_id, &data.into());223224 assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).value, 5);225 });226}227228//#[test]229// fn create_multiple_fungible_items() {230// new_test_ext().execute_with(|| {231// default_limits();232233// create_test_collection(&CollectionMode::Fungible(3), 1);234235// let origin1 = Origin::signed(1);236237// let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];238239// assert_ok!(TemplateModule::create_multiple_items(240// origin1.clone(),241// 1,242// 1,243// items_data.clone().into_iter().map(|d| { d.into() }).collect()244// ));245 246// for (index, _) in items_data.iter().enumerate() {247// assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).value, 5);248// }249// assert_eq!(TemplateModule::balance_count(1, 1), 3000);250// assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);251// });252// }253254#[test]255fn transfer_fungible_item() {256 new_test_ext().execute_with(|| {257 default_limits();258 259 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);260261 let origin1 = Origin::signed(1);262 let origin2 = Origin::signed(2);263264 let data = default_fungible_data();265 create_test_item(collection_id, &data.into());266267 assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 5);268 assert_eq!(TemplateModule::balance_count(1, 1), 5);269270 // change owner scenario271 assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 5));272 assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 0);273 assert_eq!(TemplateModule::balance_count(1, 1), 0);274 assert_eq!(TemplateModule::balance_count(1, 2), 5);275276 // split item scenario277 assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 3));278 assert_eq!(TemplateModule::balance_count(1, 2), 2);279 assert_eq!(TemplateModule::balance_count(1, 3), 3);280281 // split item and new owner has account scenario282 assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 1));283 assert_eq!(TemplateModule::fungible_item_id(1, 2).value, 1);284 assert_eq!(TemplateModule::fungible_item_id(1, 3).value, 4);285 assert_eq!(TemplateModule::balance_count(1, 2), 1);286 assert_eq!(TemplateModule::balance_count(1, 3), 4);287 });288}289290#[test]291fn transfer_refungible_item() {292 new_test_ext().execute_with(|| {293 default_limits();294 295 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);296297 let data = default_re_fungible_data();298 create_test_item(collection_id, &data.clone().into());299300 let origin1 = Origin::signed(1);301 let origin2 = Origin::signed(2);302 assert_eq!(303 TemplateModule::refungible_item_id(collection_id, 1).const_data,304 data.const_data305 );306 assert_eq!(307 TemplateModule::refungible_item_id(collection_id, 1).variable_data,308 data.variable_data309 );310 assert_eq!(311 TemplateModule::refungible_item_id(collection_id, 1).owner[0],312 Ownership {313 owner: 1,314 fraction: 1023315 }316 );317 assert_eq!(TemplateModule::balance_count(1, 1), 1023);318 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);319320 // change owner scenario321 assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1023));322 assert_eq!(323 TemplateModule::refungible_item_id(1, 1).owner[0],324 Ownership {325 owner: 2,326 fraction: 1023327 }328 );329 assert_eq!(TemplateModule::balance_count(1, 1), 0);330 assert_eq!(TemplateModule::balance_count(1, 2), 1023);331 // assert_eq!(TemplateModule::address_tokens(1, 1), []);332 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);333334 // split item scenario335 assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 500));336 assert_eq!(337 TemplateModule::refungible_item_id(1, 1).owner[0],338 Ownership {339 owner: 2,340 fraction: 523341 }342 );343 assert_eq!(344 TemplateModule::refungible_item_id(1, 1).owner[1],345 Ownership {346 owner: 3,347 fraction: 500348 }349 );350 assert_eq!(TemplateModule::balance_count(1, 2), 523);351 assert_eq!(TemplateModule::balance_count(1, 3), 500);352 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);353 assert_eq!(TemplateModule::address_tokens(1, 3), [1]);354355 // split item and new owner has account scenario356 assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 200));357 assert_eq!(358 TemplateModule::refungible_item_id(1, 1).owner[0],359 Ownership {360 owner: 2,361 fraction: 323362 }363 );364 assert_eq!(365 TemplateModule::refungible_item_id(1, 1).owner[1],366 Ownership {367 owner: 3,368 fraction: 700369 }370 );371 assert_eq!(TemplateModule::balance_count(1, 2), 323);372 assert_eq!(TemplateModule::balance_count(1, 3), 700);373 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);374 assert_eq!(TemplateModule::address_tokens(1, 3), [1]);375 });376}377378#[test]379fn transfer_nft_item() {380 new_test_ext().execute_with(|| {381 default_limits();382 383 let collection_id = create_test_collection(&CollectionMode::NFT, 1);384385 let data = default_nft_data();386 create_test_item(collection_id, &data.into());387 assert_eq!(TemplateModule::balance_count(1, 1), 1);388 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);389390 let origin1 = Origin::signed(1);391 // default scenario392 assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000));393 assert_eq!(TemplateModule::nft_item_id(1, 1).owner, 2);394 assert_eq!(TemplateModule::balance_count(1, 1), 0);395 assert_eq!(TemplateModule::balance_count(1, 2), 1);396 // assert_eq!(TemplateModule::address_tokens(1, 1), []);397 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);398 });399}400401#[test]402fn nft_approve_and_transfer_from() {403 new_test_ext().execute_with(|| {404 default_limits();405 406 let collection_id = create_test_collection(&CollectionMode::NFT, 1);407408 let data = default_nft_data();409 create_test_item(collection_id, &data.into());410411 let origin1 = Origin::signed(1);412 let origin2 = Origin::signed(2);413414 assert_eq!(TemplateModule::balance_count(1, 1), 1);415 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);416417 // neg transfer418 assert_noop!(TemplateModule::transfer_from(419 origin2.clone(),420 1,421 2,422 1,423 1,424 1), Error::<Test>::NoPermission);425426 // do approve427 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));428 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);429 assert_eq!(430 TemplateModule::approved(1, (1, 1, 2)),431 5432 );433434 assert_ok!(TemplateModule::transfer_from(435 origin2.clone(),436 1,437 3,438 1,439 1,440 1441 ));442 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);443 });444}445446#[test]447fn nft_approve_and_transfer_from_white_list() {448 new_test_ext().execute_with(|| {449 default_limits();450 451 let collection_id = create_test_collection(&CollectionMode::NFT, 1);452453 let origin1 = Origin::signed(1);454 let origin2 = Origin::signed(2);455456 let data = default_nft_data();457 create_test_item(collection_id, &data.clone().into());458459 assert_eq!(TemplateModule::nft_item_id(1, 1).const_data, data.const_data);460 assert_eq!(TemplateModule::balance_count(1, 1), 1);461 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);462463 assert_ok!(TemplateModule::set_mint_permission(464 origin1.clone(),465 1,466 true467 ));468 assert_ok!(TemplateModule::set_public_access_mode(469 origin1.clone(),470 1,471 AccessMode::WhiteList472 ));473 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));474 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));475 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));476477 // do approve478 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));479 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);480 assert_ok!(TemplateModule::approve(origin1.clone(), 3, 1, 1, 5));481 assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);482483 assert_ok!(TemplateModule::transfer_from(484 origin2.clone(),485 1,486 3,487 1,488 1,489 1490 ));491 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);492 });493}494495#[test]496fn refungible_approve_and_transfer_from() {497 new_test_ext().execute_with(|| {498 default_limits();499 500 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);501 502 let origin1 = Origin::signed(1);503 let origin2 = Origin::signed(2);504505 let data = default_re_fungible_data();506 create_test_item(collection_id, &data.into());507508 assert_eq!(TemplateModule::balance_count(1, 1), 1023);509 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);510511 assert_ok!(TemplateModule::set_mint_permission(512 origin1.clone(),513 1,514 true515 ));516 assert_ok!(TemplateModule::set_public_access_mode(517 origin1.clone(),518 1,519 AccessMode::WhiteList520 ));521 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));522 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));523 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));524525 // do approve526 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1023));527 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1023);528529 assert_ok!(TemplateModule::transfer_from(530 origin2.clone(),531 1,532 3,533 1,534 1,535 100536 ));537 assert_eq!(TemplateModule::balance_count(1, 1), 923);538 assert_eq!(TemplateModule::balance_count(1, 3), 100);539 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);540 assert_eq!(TemplateModule::address_tokens(1, 3), [1]);541542 assert_eq!(543 TemplateModule::approved(1, (1, 1, 2)),544 923545 );546 });547}548549#[test]550fn fungible_approve_and_transfer_from() {551 new_test_ext().execute_with(|| {552 default_limits();553 554 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);555 556 let data = default_fungible_data();557 create_test_item(collection_id, &data.into());558559 let origin1 = Origin::signed(1);560 let origin2 = Origin::signed(2);561562 assert_eq!(TemplateModule::balance_count(1, 1), 5);563564 assert_ok!(TemplateModule::set_mint_permission(565 origin1.clone(),566 1,567 true568 ));569 assert_ok!(TemplateModule::set_public_access_mode(570 origin1.clone(),571 1,572 AccessMode::WhiteList573 ));574 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));575 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));576 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));577578 // do approve579 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));580 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);581 assert_ok!(TemplateModule::approve(origin1.clone(), 3, 1, 1, 5));582 assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);583 assert_eq!(584 TemplateModule::approved(1, (1, 1, 2)),585 5586 );587588 assert_ok!(TemplateModule::transfer_from(589 origin2.clone(),590 1,591 3,592 1,593 1,594 4595 ));596 assert_eq!(TemplateModule::balance_count(1, 1), 1);597 assert_eq!(TemplateModule::balance_count(1, 3), 4);598599 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);600601 assert_noop!(TemplateModule::transfer_from(602 origin2.clone(),603 1,604 3,605 1,606 1,607 4608 ), Error::<Test>::TokenValueNotEnough);609 });610}611612#[test]613fn change_collection_owner() {614 new_test_ext().execute_with(|| {615 default_limits();616 617 let collection_id = create_test_collection(&CollectionMode::NFT, 1);618 619 let origin1 = Origin::signed(1);620 assert_ok!(TemplateModule::change_collection_owner(621 origin1.clone(),622 collection_id,623 2624 ));625 assert_eq!(TemplateModule::collection(collection_id).owner, 2);626 });627}628629#[test]630fn destroy_collection() {631 new_test_ext().execute_with(|| {632 default_limits();633 634 let collection_id = create_test_collection(&CollectionMode::NFT, 1);635 636 let origin1 = Origin::signed(1);637 assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));638 });639}640641#[test]642fn burn_nft_item() {643 new_test_ext().execute_with(|| {644 default_limits();645 646 let collection_id = create_test_collection(&CollectionMode::NFT, 1);647648 let origin1 = Origin::signed(1);649 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));650 651 let data = default_nft_data();652 create_test_item(collection_id, &data.into());653654 // check balance (collection with id = 1, user id = 1)655 assert_eq!(TemplateModule::balance_count(1, 1), 1);656657 // burn item658 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));659 assert_noop!(660 TemplateModule::burn_item(origin1.clone(), 1, 1, 5),661 Error::<Test>::TokenNotFound662 );663664 assert_eq!(TemplateModule::balance_count(1, 1), 0);665 });666}667668#[test]669fn burn_fungible_item() {670 new_test_ext().execute_with(|| {671 default_limits();672 673 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);674 675 let origin1 = Origin::signed(1);676 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));677 678 let data = default_fungible_data();679 create_test_item(collection_id, &data.into());680681 // check balance (collection with id = 1, user id = 1)682 assert_eq!(TemplateModule::balance_count(1, 1), 5);683684 // burn item685 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));686 assert_noop!(687 TemplateModule::burn_item(origin1.clone(), 1, 1, 5),688 Error::<Test>::TokenNotFound689 );690691 assert_eq!(TemplateModule::balance_count(1, 1), 0);692 });693}694695#[test]696fn burn_refungible_item() {697 new_test_ext().execute_with(|| {698 default_limits();699 700 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);701 let origin1 = Origin::signed(1);702703 assert_ok!(TemplateModule::set_mint_permission(704 origin1.clone(),705 collection_id,706 true707 ));708 assert_ok!(TemplateModule::set_public_access_mode(709 origin1.clone(),710 collection_id,711 AccessMode::WhiteList712 ));713 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));714715 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));716 717 let data = default_re_fungible_data();718 create_test_item(collection_id, &data.into());719720 // check balance (collection with id = 1, user id = 2)721 assert_eq!(TemplateModule::balance_count(1, 1), 1023);722723 // burn item724 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1023));725 assert_noop!(726 TemplateModule::burn_item(origin1.clone(), 1, 1, 1023),727 Error::<Test>::TokenNotFound728 );729730 assert_eq!(TemplateModule::balance_count(1, 1), 0);731 });732}733734#[test]735fn add_collection_admin() {736 new_test_ext().execute_with(|| {737 default_limits();738 739 let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);740 create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);741 create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);742 743 let origin1 = Origin::signed(1);744745 // collection admin746 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 2));747 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 3));748749 assert_eq!(TemplateModule::admin_list_collection(collection1_id).contains(&2), true);750 assert_eq!(TemplateModule::admin_list_collection(collection1_id).contains(&3), true);751 });752}753754#[test]755fn remove_collection_admin() {756 new_test_ext().execute_with(|| {757 default_limits();758 759 let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);760 create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);761 create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);762763 let origin1 = Origin::signed(1);764 let origin2 = Origin::signed(2);765766 // collection admin767 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 2));768 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 3));769770 assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true);771 assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true);772773 // remove admin774 assert_ok!(TemplateModule::remove_collection_admin(775 origin2.clone(),776 1,777 3778 ));779 assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), false);780 });781}782783#[test]784fn balance_of() {785 new_test_ext().execute_with(|| {786 default_limits();787 788 let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);789 let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);790 let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3);791 792 // check balance before793 assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 0);794 assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 0);795 assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 0);796797 let nft_data = default_nft_data();798 create_test_item(nft_collection_id, &nft_data.into());799 800 let fungible_data = default_fungible_data();801 create_test_item(fungible_collection_id, &fungible_data.into());802 803 let re_fungible_data = default_re_fungible_data();804 create_test_item(re_fungible_collection_id, &re_fungible_data.into());805806 // check balance (collection with id = 1, user id = 1)807 assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 1);808 assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 5);809 assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 1023);810 assert_eq!(TemplateModule::nft_item_id(nft_collection_id, 1).owner, 1);811 assert_eq!(TemplateModule::fungible_item_id(fungible_collection_id, 1).value, 5);812 assert_eq!(TemplateModule::refungible_item_id(re_fungible_collection_id, 1).owner[0].owner, 1);813 });814}815816#[test]817fn approve() {818 new_test_ext().execute_with(|| {819 default_limits();820 821 let collection_id = create_test_collection(&CollectionMode::NFT, 1);822 823 let data = default_nft_data();824 create_test_item(collection_id, &data.into());825826 let origin1 = Origin::signed(1);827 828 // approve829 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1));830 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);831 });832}833834#[test]835fn transfer_from() {836 new_test_ext().execute_with(|| {837 default_limits();838 839 let collection_id = create_test_collection(&CollectionMode::NFT, 1);840 let origin1 = Origin::signed(1);841 let origin2 = Origin::signed(2);842843 let data = default_nft_data();844 create_test_item(collection_id, &data.into());845846 // approve847 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1));848 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);849850 assert_ok!(TemplateModule::set_mint_permission(851 origin1.clone(),852 1,853 true854 ));855 assert_ok!(TemplateModule::set_public_access_mode(856 origin1.clone(),857 1,858 AccessMode::WhiteList859 ));860 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));861 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));862 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));863864 assert_ok!(TemplateModule::transfer_from(865 origin2.clone(),866 1,867 2,868 1,869 1,870 1871 ));872873 // after transfer874 assert_eq!(TemplateModule::balance_count(1, 1), 0);875 assert_eq!(TemplateModule::balance_count(1, 2), 1);876 });877}878879// #endregion880881// Coverage tests region882// #region883884#[test]885fn owner_can_add_address_to_white_list() {886 new_test_ext().execute_with(|| {887 default_limits();888 889 let collection_id = create_test_collection(&CollectionMode::NFT, 1);890891 let origin1 = Origin::signed(1);892 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));893 assert_eq!(TemplateModule::white_list(collection_id, 2), true);894 });895}896897#[test]898fn admin_can_add_address_to_white_list() {899 new_test_ext().execute_with(|| {900 default_limits();901 902 let collection_id = create_test_collection(&CollectionMode::NFT, 1);903 let origin1 = Origin::signed(1);904 let origin2 = Origin::signed(2);905906 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));907 assert_ok!(TemplateModule::add_to_white_list(origin2.clone(), collection_id, 3));908 assert_eq!(TemplateModule::white_list(collection_id, 3), true);909 });910}911912#[test]913fn nonprivileged_user_cannot_add_address_to_white_list() {914 new_test_ext().execute_with(|| {915 default_limits();916 917 let collection_id = create_test_collection(&CollectionMode::NFT, 1);918919 let origin2 = Origin::signed(2);920 assert_noop!(921 TemplateModule::add_to_white_list(origin2.clone(), collection_id, 3),922 Error::<Test>::NoPermission923 );924 });925}926927#[test]928fn nobody_can_add_address_to_white_list_of_nonexisting_collection() {929 new_test_ext().execute_with(|| {930 default_limits();931932 let origin1 = Origin::signed(1);933934 assert_noop!(935 TemplateModule::add_to_white_list(origin1.clone(), 1, 2),936 Error::<Test>::CollectionNotFound937 );938 });939}940941#[test]942fn nobody_can_add_address_to_white_list_of_deleted_collection() {943 new_test_ext().execute_with(|| {944 default_limits();945 946 let collection_id = create_test_collection(&CollectionMode::NFT, 1);947948 let origin1 = Origin::signed(1);949 assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));950 assert_noop!(951 TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2),952 Error::<Test>::CollectionNotFound953 );954 });955}956957// If address is already added to white list, nothing happens958#[test]959fn address_is_already_added_to_white_list() {960 new_test_ext().execute_with(|| {961 default_limits();962 963 let collection_id = create_test_collection(&CollectionMode::NFT, 1);964 let origin1 = Origin::signed(1);965 966 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));967 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));968 assert_eq!(TemplateModule::white_list(collection_id, 2), true);969 });970}971972#[test]973fn owner_can_remove_address_from_white_list() {974 new_test_ext().execute_with(|| {975 default_limits();976 977 let collection_id = create_test_collection(&CollectionMode::NFT, 1);978979 let origin1 = Origin::signed(1);980 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));981 assert_ok!(TemplateModule::remove_from_white_list(982 origin1.clone(),983 collection_id,984 2985 ));986 assert_eq!(TemplateModule::white_list(collection_id, 2), false);987 });988}989990#[test]991fn admin_can_remove_address_from_white_list() {992 new_test_ext().execute_with(|| {993 default_limits();994 995 let collection_id = create_test_collection(&CollectionMode::NFT, 1);996 let origin1 = Origin::signed(1);997 let origin2 = Origin::signed(2);998999 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));10001001 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 3));1002 assert_ok!(TemplateModule::remove_from_white_list(1003 origin2.clone(),1004 collection_id,1005 31006 ));1007 assert_eq!(TemplateModule::white_list(collection_id, 3), false);1008 });1009}10101011#[test]1012fn nonprivileged_user_cannot_remove_address_from_white_list() {1013 new_test_ext().execute_with(|| {1014 default_limits();1015 1016 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1017 let origin1 = Origin::signed(1);1018 let origin2 = Origin::signed(2);10191020 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1021 assert_noop!(1022 TemplateModule::remove_from_white_list(origin2.clone(), collection_id, 2),1023 Error::<Test>::NoPermission1024 );1025 assert_eq!(TemplateModule::white_list(collection_id, 2), true);1026 });1027}10281029#[test]1030fn nobody_can_remove_address_from_white_list_of_nonexisting_collection() {1031 new_test_ext().execute_with(|| {1032 default_limits();1033 let origin1 = Origin::signed(1);10341035 assert_noop!(1036 TemplateModule::remove_from_white_list(origin1.clone(), 1, 2),1037 Error::<Test>::CollectionNotFound1038 );1039 });1040}10411042#[test]1043fn nobody_can_remove_address_from_white_list_of_deleted_collection() {1044 new_test_ext().execute_with(|| {1045 default_limits();1046 1047 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1048 let origin1 = Origin::signed(1);1049 let origin2 = Origin::signed(2);10501051 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1052 assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));1053 assert_noop!(1054 TemplateModule::remove_from_white_list(origin2.clone(), collection_id, 2),1055 Error::<Test>::CollectionNotFound1056 );1057 assert_eq!(TemplateModule::white_list(collection_id, 2), false);1058 });1059}10601061// If address is already removed from white list, nothing happens1062#[test]1063fn address_is_already_removed_from_white_list() {1064 new_test_ext().execute_with(|| {1065 default_limits();1066 1067 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1068 let origin1 = Origin::signed(1);10691070 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1071 assert_ok!(TemplateModule::remove_from_white_list(1072 origin1.clone(),1073 collection_id,1074 21075 ));1076 assert_ok!(TemplateModule::remove_from_white_list(1077 origin1.clone(),1078 collection_id,1079 21080 ));1081 assert_eq!(TemplateModule::white_list(collection_id, 2), false);1082 });1083}10841085// If Public Access mode is set to WhiteList, tokens can’t be transferred from a non-whitelisted address with transfer or transferFrom (2 tests)1086#[test]1087fn white_list_test_1() {1088 new_test_ext().execute_with(|| {1089 default_limits();1090 1091 let collection_id = create_test_collection(&CollectionMode::NFT, 1);10921093 let origin1 = Origin::signed(1);1094 1095 let data = default_nft_data();1096 create_test_item(collection_id, &data.into());10971098 assert_ok!(TemplateModule::set_public_access_mode(1099 origin1.clone(),1100 collection_id,1101 AccessMode::WhiteList1102 ));1103 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));11041105 assert_noop!(1106 TemplateModule::transfer(origin1.clone(), 3, 1, 1, 1),1107 Error::<Test>::AddresNotInWhiteList1108 );1109 });1110}11111112#[test]1113fn white_list_test_2() {1114 new_test_ext().execute_with(|| {1115 default_limits();1116 1117 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1118 let origin1 = Origin::signed(1);1119 1120 let data = default_nft_data();1121 create_test_item(collection_id, &data.into());11221123 assert_ok!(TemplateModule::set_public_access_mode(1124 origin1.clone(),1125 collection_id,1126 AccessMode::WhiteList1127 ));1128 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));1129 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));11301131 // do approve1132 assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1, 1));1133 assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);11341135 assert_ok!(TemplateModule::remove_from_white_list(1136 origin1.clone(),1137 1,1138 11139 ));11401141 assert_noop!(1142 TemplateModule::transfer_from(origin1.clone(), 1, 3, 1, 1, 1),1143 Error::<Test>::AddresNotInWhiteList1144 );1145 });1146}11471148// If Public Access mode is set to WhiteList, tokens can’t be transferred to a non-whitelisted address with transfer or transferFrom (2 tests)1149#[test]1150fn white_list_test_3() {1151 new_test_ext().execute_with(|| {1152 default_limits();1153 1154 let collection_id = create_test_collection(&CollectionMode::NFT, 1);11551156 let origin1 = Origin::signed(1);1157 1158 let data = default_nft_data();1159 create_test_item(collection_id, &data.into());11601161 assert_ok!(TemplateModule::set_public_access_mode(1162 origin1.clone(),1163 collection_id,1164 AccessMode::WhiteList1165 ));1166 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));11671168 assert_noop!(1169 TemplateModule::transfer(origin1.clone(), 3, 1, 1, 1),1170 Error::<Test>::AddresNotInWhiteList1171 );1172 });1173}11741175#[test]1176fn white_list_test_4() {1177 new_test_ext().execute_with(|| {1178 default_limits();1179 1180 let collection_id = create_test_collection(&CollectionMode::NFT, 1);11811182 let origin1 = Origin::signed(1);11831184 let data = default_nft_data();1185 create_test_item(collection_id, &data.into());11861187 assert_ok!(TemplateModule::set_public_access_mode(1188 origin1.clone(),1189 collection_id,1190 AccessMode::WhiteList1191 ));1192 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1193 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));11941195 // do approve1196 assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1, 1));1197 assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);11981199 assert_ok!(TemplateModule::remove_from_white_list(1200 origin1.clone(),1201 collection_id,1202 21203 ));12041205 assert_noop!(1206 TemplateModule::transfer_from(origin1.clone(), 1, 3, 1, 1, 1),1207 Error::<Test>::AddresNotInWhiteList1208 );1209 });1210}12111212// If Public Access mode is set to WhiteList, tokens can’t be destroyed by a non-whitelisted address (even if it owned them before enabling WhiteList mode)1213#[test]1214fn white_list_test_5() {1215 new_test_ext().execute_with(|| {1216 default_limits();1217 1218 let collection_id = create_test_collection(&CollectionMode::NFT, 1);12191220 let origin1 = Origin::signed(1);12211222 let data = default_nft_data();1223 create_test_item(collection_id, &data.into());12241225 assert_ok!(TemplateModule::set_public_access_mode(1226 origin1.clone(),1227 collection_id,1228 AccessMode::WhiteList1229 ));1230 assert_noop!(1231 TemplateModule::burn_item(origin1.clone(), 1, 1, 5),1232 Error::<Test>::AddresNotInWhiteList1233 );1234 });1235}12361237// If Public Access mode is set to WhiteList, token transfers can’t be Approved by a non-whitelisted address (see Approve method).1238#[test]1239fn white_list_test_6() {1240 new_test_ext().execute_with(|| {1241 default_limits();1242 1243 let collection_id = create_test_collection(&CollectionMode::NFT, 1);12441245 let origin1 = Origin::signed(1);12461247 let data = default_nft_data();1248 create_test_item(collection_id, &data.into());12491250 assert_ok!(TemplateModule::set_public_access_mode(1251 origin1.clone(),1252 collection_id,1253 AccessMode::WhiteList1254 ));12551256 // do approve1257 assert_noop!(1258 TemplateModule::approve(origin1.clone(), 1, 1, 1, 5),1259 Error::<Test>::AddresNotInWhiteList1260 );1261 });1262}12631264// If Public Access mode is set to WhiteList, tokens can be transferred from a whitelisted address with transfer or transferFrom (2 tests) and1265// tokens can be transferred from a whitelisted address with transfer or transferFrom (2 tests)1266#[test]1267fn white_list_test_7() {1268 new_test_ext().execute_with(|| {1269 default_limits();1270 1271 let collection_id = create_test_collection(&CollectionMode::NFT, 1);12721273 let data = default_nft_data();1274 create_test_item(collection_id, &data.into());1275 1276 let origin1 = Origin::signed(1);12771278 assert_ok!(TemplateModule::set_public_access_mode(1279 origin1.clone(),1280 collection_id,1281 AccessMode::WhiteList1282 ));1283 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1284 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));12851286 assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1));1287 });1288}12891290#[test]1291fn white_list_test_8() {1292 new_test_ext().execute_with(|| {1293 default_limits();1294 1295 let collection_id = create_test_collection(&CollectionMode::NFT, 1);12961297 let data = default_nft_data();1298 create_test_item(collection_id, &data.into());1299 1300 let origin1 = Origin::signed(1);13011302 assert_ok!(TemplateModule::set_public_access_mode(1303 origin1.clone(),1304 collection_id,1305 AccessMode::WhiteList1306 ));1307 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1308 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));13091310 // do approve1311 assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1, 5));1312 assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 5);13131314 assert_ok!(TemplateModule::transfer_from(1315 origin1.clone(),1316 1,1317 2,1318 1,1319 1,1320 11321 ));1322 });1323}13241325// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens can be created by owner.1326#[test]1327fn white_list_test_9() {1328 new_test_ext().execute_with(|| {1329 default_limits();1330 1331 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1332 let origin1 = Origin::signed(1);13331334 assert_ok!(TemplateModule::set_public_access_mode(1335 origin1.clone(),1336 collection_id,1337 AccessMode::WhiteList1338 ));1339 assert_ok!(TemplateModule::set_mint_permission(1340 origin1.clone(),1341 collection_id,1342 false1343 ));13441345 let data = default_nft_data();1346 create_test_item(collection_id, &data.into());1347 });1348}13491350// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens can be created by admin.1351#[test]1352fn white_list_test_10() {1353 new_test_ext().execute_with(|| {1354 default_limits();1355 1356 let collection_id = create_test_collection(&CollectionMode::NFT, 1);13571358 let origin1 = Origin::signed(1);1359 let origin2 = Origin::signed(2);13601361 assert_ok!(TemplateModule::set_public_access_mode(1362 origin1.clone(),1363 collection_id,1364 AccessMode::WhiteList1365 ));1366 assert_ok!(TemplateModule::set_mint_permission(1367 origin1.clone(),1368 collection_id,1369 false1370 ));13711372 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));13731374 assert_ok!(TemplateModule::create_item(1375 origin2.clone(),1376 collection_id,1377 2,1378 default_nft_data().into()1379 ));1380 });1381}13821383// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens cannot be created by non-privileged and white listed address.1384#[test]1385fn white_list_test_11() {1386 new_test_ext().execute_with(|| {1387 default_limits();1388 1389 let collection_id = create_test_collection(&CollectionMode::NFT, 1);13901391 let origin1 = Origin::signed(1);1392 let origin2 = Origin::signed(2);13931394 assert_ok!(TemplateModule::set_public_access_mode(1395 origin1.clone(),1396 collection_id,1397 AccessMode::WhiteList1398 ));1399 assert_ok!(TemplateModule::set_mint_permission(1400 origin1.clone(),1401 collection_id,1402 false1403 ));1404 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));14051406 assert_noop!(1407 TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1408 Error::<Test>::PublicMintingNotAllowed1409 );1410 });1411}14121413// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-white listed address.1414#[test]1415fn white_list_test_12() {1416 new_test_ext().execute_with(|| {1417 default_limits();1418 1419 let collection_id = create_test_collection(&CollectionMode::NFT, 1);14201421 let origin1 = Origin::signed(1);1422 let origin2 = Origin::signed(2);14231424 assert_ok!(TemplateModule::set_public_access_mode(1425 origin1.clone(),1426 collection_id,1427 AccessMode::WhiteList1428 ));1429 assert_ok!(TemplateModule::set_mint_permission(1430 origin1.clone(),1431 collection_id,1432 false1433 ));14341435 assert_noop!(1436 TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1437 Error::<Test>::PublicMintingNotAllowed1438 );1439 });1440}14411442// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by owner.1443#[test]1444fn white_list_test_13() {1445 new_test_ext().execute_with(|| {1446 default_limits();1447 1448 let collection_id = create_test_collection(&CollectionMode::NFT, 1);14491450 let origin1 = Origin::signed(1);14511452 assert_ok!(TemplateModule::set_public_access_mode(1453 origin1.clone(),1454 collection_id,1455 AccessMode::WhiteList1456 ));1457 assert_ok!(TemplateModule::set_mint_permission(1458 origin1.clone(),1459 collection_id,1460 true1461 ));14621463 let data = default_nft_data();1464 create_test_item(collection_id, &data.into());1465 });1466}14671468// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by admin.1469#[test]1470fn white_list_test_14() {1471 new_test_ext().execute_with(|| {1472 default_limits();1473 1474 let collection_id = create_test_collection(&CollectionMode::NFT, 1);14751476 let origin1 = Origin::signed(1);1477 let origin2 = Origin::signed(2);14781479 assert_ok!(TemplateModule::set_public_access_mode(1480 origin1.clone(),1481 collection_id,1482 AccessMode::WhiteList1483 ));1484 assert_ok!(TemplateModule::set_mint_permission(1485 origin1.clone(),1486 collection_id,1487 true1488 ));14891490 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));14911492 assert_ok!(TemplateModule::create_item(1493 origin2.clone(),1494 1,1495 2,1496 default_nft_data().into()1497 ));1498 });1499}15001501// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-white listed address.1502#[test]1503fn white_list_test_15() {1504 new_test_ext().execute_with(|| {1505 default_limits();1506 1507 let collection_id = create_test_collection(&CollectionMode::NFT, 1);15081509 let origin1 = Origin::signed(1);1510 let origin2 = Origin::signed(2);15111512 assert_ok!(TemplateModule::set_public_access_mode(1513 origin1.clone(),1514 collection_id,1515 AccessMode::WhiteList1516 ));1517 assert_ok!(TemplateModule::set_mint_permission(1518 origin1.clone(),1519 collection_id,1520 true1521 ));15221523 assert_noop!(1524 TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1525 Error::<Test>::AddresNotInWhiteList1526 );1527 });1528}15291530// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by non-privileged and white listed address.1531#[test]1532fn white_list_test_16() {1533 new_test_ext().execute_with(|| {1534 default_limits();1535 1536 let collection_id = create_test_collection(&CollectionMode::NFT, 1);15371538 let origin1 = Origin::signed(1);1539 let origin2 = Origin::signed(2);15401541 assert_ok!(TemplateModule::set_public_access_mode(1542 origin1.clone(),1543 collection_id,1544 AccessMode::WhiteList1545 ));1546 assert_ok!(TemplateModule::set_mint_permission(1547 origin1.clone(),1548 collection_id,1549 true1550 ));1551 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));15521553 assert_ok!(TemplateModule::create_item(1554 origin2.clone(),1555 1,1556 2,1557 default_nft_data().into()1558 ));1559 });1560}15611562// Total number of collections. Positive test1563#[test]1564fn total_number_collections_bound() {1565 new_test_ext().execute_with(|| {1566 default_limits();1567 1568 create_test_collection(&CollectionMode::NFT, 1);1569 });1570}15711572// Total number of collections. Negotive test1573#[test]1574fn total_number_collections_bound_neg() {1575 new_test_ext().execute_with(|| {1576 default_limits();15771578 let origin1 = Origin::signed(1);15791580 for i in 0..default_collection_numbers_limit() {1581 create_test_collection(&CollectionMode::NFT, i + 1);1582 }15831584 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();1585 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();1586 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();15871588 // 11-th collection in chain. Expects error1589 assert_noop!(TemplateModule::create_collection(1590 origin1.clone(),1591 col_name1.clone(),1592 col_desc1.clone(),1593 token_prefix1.clone(),1594 CollectionMode::NFT1595 ), Error::<Test>::TotalCollectionsLimitExceeded);1596 });1597}15981599// Owned tokens by a single address. Positive test1600#[test]1601fn owned_tokens_bound() {1602 new_test_ext().execute_with(|| {1603 default_limits();1604 1605 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16061607 let data = default_nft_data();1608 create_test_item(collection_id, &data.clone().into());1609 create_test_item(collection_id, &data.into());1610 });1611}16121613// Owned tokens by a single address. Negotive test1614#[test]1615fn owned_tokens_bound_neg() {1616 new_test_ext().execute_with(|| {1617 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1618 collection_numbers_limit: 10,1619 account_token_ownership_limit: 1,1620 collections_admins_limit: 5,1621 custom_data_limit: 2048,1622 nft_sponsor_transfer_timeout: 15,1623 fungible_sponsor_transfer_timeout: 15,1624 refungible_sponsor_transfer_timeout: 15,1625 const_on_chain_schema_limit: 1024,1626 offchain_schema_limit: 1024,1627 variable_on_chain_schema_limit: 1024,1628 }));1629 1630 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16311632 let origin1 = Origin::signed(1);1633 let data = default_nft_data();1634 create_test_item(collection_id, &data.clone().into());16351636 assert_noop!(TemplateModule::create_item(1637 origin1.clone(),1638 1,1639 1,1640 data.into()1641 ), Error::<Test>::AddressOwnershipLimitExceeded);1642 });1643}16441645// Number of collection admins. Positive test1646#[test]1647fn collection_admins_bound() {1648 new_test_ext().execute_with(|| {1649 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1650 collection_numbers_limit: 10,1651 account_token_ownership_limit: 10,1652 collections_admins_limit: 2,1653 custom_data_limit: 2048,1654 nft_sponsor_transfer_timeout: 15,1655 fungible_sponsor_transfer_timeout: 15,1656 refungible_sponsor_transfer_timeout: 15,1657 const_on_chain_schema_limit: 1024,1658 offchain_schema_limit: 1024,1659 variable_on_chain_schema_limit: 1024,1660 }));1661 1662 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16631664 let origin1 = Origin::signed(1);1665 1666 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));1667 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 3));1668 });1669}16701671// Number of collection admins. Negotive test1672#[test]1673fn collection_admins_bound_neg() {1674 new_test_ext().execute_with(|| {1675 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1676 collection_numbers_limit: 10,1677 account_token_ownership_limit: 1,1678 collections_admins_limit: 1,1679 custom_data_limit: 2048,1680 nft_sponsor_transfer_timeout: 15,1681 fungible_sponsor_transfer_timeout: 15,1682 refungible_sponsor_transfer_timeout: 15,1683 const_on_chain_schema_limit: 1024,1684 offchain_schema_limit: 1024,1685 variable_on_chain_schema_limit: 1024,1686 }));1687 1688 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16891690 let origin1 = Origin::signed(1);16911692 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));1693 assert_noop!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 3), Error::<Test>::CollectionAdminsLimitExceeded);1694 });1695}16961697// NFT custom data size. Negative test const_data.1698#[test]1699fn custom_data_size_nft_const_data_bound_neg() {1700 new_test_ext().execute_with(|| {1701 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1702 collection_numbers_limit: 10,1703 account_token_ownership_limit: 10,1704 collections_admins_limit: 5,1705 custom_data_limit: 2,1706 nft_sponsor_transfer_timeout: 15,1707 fungible_sponsor_transfer_timeout: 15,1708 refungible_sponsor_transfer_timeout: 15,1709 const_on_chain_schema_limit: 1024,1710 offchain_schema_limit: 1024,1711 variable_on_chain_schema_limit: 1024,1712 }));1713 1714 let collection_id = create_test_collection(&CollectionMode::NFT, 1);17151716 let origin1 = Origin::signed(1);1717 let too_big_const_data = CreateItemData::NFT(CreateNftData{1718 const_data: vec![1, 2, 3, 4],1719 variable_data: vec![]1720 });17211722 assert_noop!(TemplateModule::create_item(1723 origin1.clone(),1724 collection_id,1725 1,1726 too_big_const_data1727 ), Error::<Test>::TokenConstDataLimitExceeded);1728 });1729}17301731// NFT custom data size. Negative test variable_data.1732#[test]1733fn custom_data_size_nft_variable_data_bound_neg() {1734 new_test_ext().execute_with(|| {1735 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1736 collection_numbers_limit: 10,1737 account_token_ownership_limit: 10,1738 collections_admins_limit: 5,1739 custom_data_limit: 2,1740 nft_sponsor_transfer_timeout: 15,1741 fungible_sponsor_transfer_timeout: 15,1742 refungible_sponsor_transfer_timeout: 15,1743 const_on_chain_schema_limit: 1024,1744 offchain_schema_limit: 1024,1745 variable_on_chain_schema_limit: 1024,1746 }));17471748 let collection_id = create_test_collection(&CollectionMode::NFT, 1);17491750 let origin1 = Origin::signed(1);1751 let too_big_const_data = CreateItemData::NFT(CreateNftData{1752 const_data: vec![],1753 variable_data: vec![1, 2, 3, 4]1754 });17551756 assert_noop!(TemplateModule::create_item(1757 origin1.clone(),1758 collection_id,1759 1,1760 too_big_const_data1761 ), Error::<Test>::TokenVariableDataLimitExceeded);1762 });1763}17641765// Re fungible custom data size. Negative test const_data.1766#[test]1767fn custom_data_size_re_fungible_const_data_bound_neg() {1768 new_test_ext().execute_with(|| {1769 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1770 collection_numbers_limit: 10,1771 account_token_ownership_limit: 10,1772 collections_admins_limit: 5,1773 custom_data_limit: 2,1774 nft_sponsor_transfer_timeout: 15,1775 fungible_sponsor_transfer_timeout: 15,1776 refungible_sponsor_transfer_timeout: 15,1777 const_on_chain_schema_limit: 1024,1778 offchain_schema_limit: 1024,1779 variable_on_chain_schema_limit: 1024,1780 }));17811782 let collection_id = create_test_collection(&CollectionMode::NFT, 1);17831784 let origin1 = Origin::signed(1);1785 let too_big_const_data = CreateItemData::NFT(CreateNftData{1786 const_data: vec![1, 2, 3, 4],1787 variable_data: vec![]1788 });17891790 assert_noop!(TemplateModule::create_item(1791 origin1.clone(),1792 collection_id,1793 1,1794 too_big_const_data1795 ), Error::<Test>::TokenConstDataLimitExceeded);1796 });1797}17981799// Re fungible custom data size. Negative test variable_data.1800#[test]1801fn custom_data_size_re_fungible_variable_data_bound_neg() {1802 new_test_ext().execute_with(|| {1803 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1804 collection_numbers_limit: 10,1805 account_token_ownership_limit: 10,1806 collections_admins_limit: 5,1807 custom_data_limit: 2,1808 nft_sponsor_transfer_timeout: 15,1809 fungible_sponsor_transfer_timeout: 15,1810 refungible_sponsor_transfer_timeout: 15,1811 const_on_chain_schema_limit: 1024,1812 offchain_schema_limit: 1024,1813 variable_on_chain_schema_limit: 1024,1814 }));18151816 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18171818 let origin1 = Origin::signed(1);1819 let too_big_const_data = CreateItemData::NFT(CreateNftData{1820 const_data: vec![],1821 variable_data: vec![1, 2, 3, 4]1822 });18231824 assert_noop!(TemplateModule::create_item(1825 origin1.clone(),1826 collection_id,1827 1,1828 too_big_const_data1829 ), Error::<Test>::TokenVariableDataLimitExceeded);1830 });1831}1832// #endregion18331834#[test]1835fn set_const_on_chain_schema() {1836 new_test_ext().execute_with(|| {1837 default_limits();18381839 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18401841 let origin1 = Origin::signed(1);1842 assert_ok!(TemplateModule::set_const_on_chain_schema(origin1, collection_id, b"test const on chain schema".to_vec()));18431844 assert_eq!(TemplateModule::collection(collection_id).const_on_chain_schema, b"test const on chain schema".to_vec());1845 assert_eq!(TemplateModule::collection(collection_id).variable_on_chain_schema, b"".to_vec());1846 });1847}18481849#[test]1850fn set_variable_on_chain_schema() {1851 new_test_ext().execute_with(|| {1852 default_limits();1853 1854 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18551856 let origin1 = Origin::signed(1);1857 assert_ok!(TemplateModule::set_variable_on_chain_schema(origin1, collection_id, b"test variable on chain schema".to_vec()));18581859 assert_eq!(TemplateModule::collection(collection_id).const_on_chain_schema, b"".to_vec());1860 assert_eq!(TemplateModule::collection(collection_id).variable_on_chain_schema, b"test variable on chain schema".to_vec());1861 });1862}18631864#[test]1865fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {1866 new_test_ext().execute_with(|| {1867 default_limits();18681869 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18701871 let origin1 = Origin::signed(1);1872 1873 let data = default_nft_data();1874 create_test_item(1, &data.into());1875 1876 let variable_data = b"test set_variable_meta_data method.".to_vec();1877 assert_ok!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()));18781879 assert_eq!(TemplateModule::nft_item_id(collection_id, 1).variable_data, variable_data);1880 });1881}18821883#[test]1884fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {1885 new_test_ext().execute_with(|| {1886 default_limits();18871888 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);18891890 let origin1 = Origin::signed(1);18911892 let data = default_re_fungible_data();1893 create_test_item(1, &data.into());18941895 let variable_data = b"test set_variable_meta_data method.".to_vec();1896 assert_ok!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()));18971898 assert_eq!(TemplateModule::refungible_item_id(collection_id, 1).variable_data, variable_data);1899 });1900}190119021903#[test]1904fn set_variable_meta_data_on_fungible_token_fails() {1905 new_test_ext().execute_with(|| {1906 default_limits();19071908 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);19091910 let origin1 = Origin::signed(1);19111912 let data = default_fungible_data();1913 create_test_item(1, &data.into());19141915 let variable_data = b"test set_variable_meta_data method.".to_vec();1916 assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()), Error::<Test>::CantStoreMetadataInFungibleTokens);1917 });1918}19191920#[test]1921fn set_variable_meta_data_on_nft_token_fails_for_big_data() {1922 new_test_ext().execute_with(|| {1923 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1924 collection_numbers_limit: default_collection_numbers_limit(),1925 account_token_ownership_limit: 10,1926 collections_admins_limit: 5,1927 custom_data_limit: 10,1928 nft_sponsor_transfer_timeout: 15,1929 fungible_sponsor_transfer_timeout: 15,1930 refungible_sponsor_transfer_timeout: 15,1931 const_on_chain_schema_limit: 1024,1932 offchain_schema_limit: 1024,1933 variable_on_chain_schema_limit: 1024,1934 }));19351936 let collection_id = create_test_collection(&CollectionMode::NFT, 1);19371938 let origin1 = Origin::signed(1);19391940 let data = default_nft_data();1941 create_test_item(1, &data.into());19421943 let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();1944 assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data), Error::<Test>::TokenVariableDataLimitExceeded);1945 });1946}19471948#[test]1949fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() {1950 new_test_ext().execute_with(|| {1951 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1952 collection_numbers_limit: default_collection_numbers_limit(),1953 account_token_ownership_limit: 10,1954 collections_admins_limit: 5,1955 custom_data_limit: 10,1956 nft_sponsor_transfer_timeout: 15,1957 fungible_sponsor_transfer_timeout: 15,1958 refungible_sponsor_transfer_timeout: 15,1959 const_on_chain_schema_limit: 1024,1960 offchain_schema_limit: 1024,1961 variable_on_chain_schema_limit: 1024,1962 }));196319641965 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);19661967 let origin1 = Origin::signed(1);19681969 let data = default_re_fungible_data();1970 create_test_item(1, &data.into());19711972 let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();1973 assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data), Error::<Test>::TokenVariableDataLimitExceeded);1974 });1975}1// Tests to be written here2use super::*;3use crate::mock::*;4use crate::{AccessMode, CollectionMode,5 Ownership, ChainLimits, CreateItemData, CreateNftData, CreateFungibleData, CreateReFungibleData,6 CollectionId, TokenId, MAX_DECIMAL_POINTS};7use frame_support::{assert_noop, assert_ok};8use frame_system::{ RawOrigin };910fn default_collection_numbers_limit() -> u32 {11 1012}1314fn default_limits() {15 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits {16 collection_numbers_limit: default_collection_numbers_limit(),17 account_token_ownership_limit: 10,18 collections_admins_limit: 5,19 custom_data_limit: 2048,20 nft_sponsor_transfer_timeout: 15,21 fungible_sponsor_transfer_timeout: 15,22 refungible_sponsor_transfer_timeout: 15,23 const_on_chain_schema_limit: 1024,24 offchain_schema_limit: 1024,25 variable_on_chain_schema_limit: 1024,26 }));27}2829fn default_nft_data() -> CreateNftData {30 CreateNftData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1] }31}3233fn default_fungible_data () -> CreateFungibleData {34 CreateFungibleData { value: 5 }35}3637fn default_re_fungible_data () -> CreateReFungibleData {38 CreateReFungibleData { const_data: vec![1, 2, 3], variable_data: vec![3, 2, 1], pieces: 1023 }39}4041fn create_test_collection_for_owner(mode: &CollectionMode, owner: u64, id: CollectionId) -> CollectionId {42 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();43 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();44 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();4546 let origin1 = Origin::signed(owner);47 assert_ok!(TemplateModule::create_collection(48 origin1.clone(),49 col_name1.clone(),50 col_desc1.clone(),51 token_prefix1.clone(),52 mode.clone()53 ));5455 let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();56 let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();57 let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();58 assert_eq!(TemplateModule::collection_id(id).unwrap().owner, owner);59 assert_eq!(TemplateModule::collection_id(id).unwrap().name, saved_col_name);60 assert_eq!(TemplateModule::collection_id(id).unwrap().mode, *mode);61 assert_eq!(TemplateModule::collection_id(id).unwrap().description, saved_description);62 assert_eq!(TemplateModule::collection_id(id).unwrap().token_prefix, saved_prefix);63 id64}6566fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {67 create_test_collection_for_owner(&mode, 1, id)68}6970fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {71 let origin1 = Origin::signed(1);72 assert_ok!(TemplateModule::create_item(73 origin1.clone(),74 collection_id,75 1,76 data.clone()77 ));7879}8081// Use cases tests region82// #region8384#[test]85fn set_version_schema() {86 new_test_ext().execute_with(|| {87 default_limits();88 let origin1 = Origin::signed(1);89 let collection_id = create_test_collection(&CollectionMode::NFT, 1);90 91 assert_ok!(TemplateModule::set_schema_version(origin1, collection_id, SchemaVersion::Unique));92 assert_eq!(TemplateModule::collection_id(collection_id).unwrap().schema_version, SchemaVersion::Unique);93 });94}9596#[test]97fn create_fungible_collection_fails_with_large_decimal_numbers() {98 new_test_ext().execute_with(|| {99 default_limits();100101 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();102 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();103 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();104105 let origin1 = Origin::signed(1);106 assert_noop!(TemplateModule::create_collection(107 origin1,108 col_name1,109 col_desc1,110 token_prefix1,111 CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1)112 ), Error::<Test>::CollectionDecimalPointLimitExceeded);113 }); 114}115116#[test]117fn create_nft_item() {118 new_test_ext().execute_with(|| {119 default_limits();120 let collection_id = create_test_collection(&CollectionMode::NFT, 1);121 122 let data = default_nft_data();123 create_test_item(collection_id, &data.clone().into());124 assert_eq!(TemplateModule::nft_item_id(collection_id, 1).const_data, data.const_data);125 assert_eq!(TemplateModule::nft_item_id(collection_id, 1).variable_data, data.variable_data);126 });127}128129// Use cases tests region130// #region131#[test]132fn create_nft_multiple_items() {133 new_test_ext().execute_with(|| {134 default_limits();135 136 create_test_collection(&CollectionMode::NFT, 1);137138 let origin1 = Origin::signed(1);139140 let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];141142 assert_ok!(TemplateModule::create_multiple_items(143 origin1.clone(),144 1,145 1,146 items_data.clone().into_iter().map(|d| { d.into() }).collect()147 ));148 for (index, data) in items_data.iter().enumerate() {149 assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as TokenId).const_data.to_vec(), data.const_data);150 assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as TokenId).variable_data.to_vec(), data.variable_data);151 }152 });153}154155#[test]156fn create_refungible_item() {157 new_test_ext().execute_with(|| {158 default_limits();159 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);160161 let data = default_re_fungible_data();162 create_test_item(collection_id, &data.clone().into());163 assert_eq!(164 TemplateModule::refungible_item_id(collection_id, 1).const_data,165 data.const_data166 );167 assert_eq!(168 TemplateModule::refungible_item_id(collection_id, 1).variable_data,169 data.variable_data170 );171 assert_eq!(172 TemplateModule::refungible_item_id(collection_id, 1).owner[0],173 Ownership {174 owner: 1,175 fraction: 1023176 }177 );178 });179}180181#[test]182fn create_multiple_refungible_items() {183 new_test_ext().execute_with(|| {184 default_limits();185 186 create_test_collection(&CollectionMode::ReFungible, 1);187188 let origin1 = Origin::signed(1);189190 let items_data = vec![default_re_fungible_data(), default_re_fungible_data(), default_re_fungible_data()];191192 assert_ok!(TemplateModule::create_multiple_items(193 origin1.clone(),194 1,195 1,196 items_data.clone().into_iter().map(|d| { d.into() }).collect()197 ));198 for (index, data) in items_data.iter().enumerate() {199200 let item = TemplateModule::refungible_item_id(1, (index + 1) as TokenId);201 assert_eq!(item.const_data.to_vec(), data.const_data);202 assert_eq!(item.variable_data.to_vec(), data.variable_data);203 assert_eq!(204 item.owner[0],205 Ownership {206 owner: 1,207 fraction: 1023208 }209 );210 }211 });212}213214#[test]215fn create_fungible_item() {216 new_test_ext().execute_with(|| {217 default_limits();218 219 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);220221 let data = default_fungible_data();222 create_test_item(collection_id, &data.into());223224 assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).value, 5);225 });226}227228//#[test]229// fn create_multiple_fungible_items() {230// new_test_ext().execute_with(|| {231// default_limits();232233// create_test_collection(&CollectionMode::Fungible(3), 1);234235// let origin1 = Origin::signed(1);236237// let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];238239// assert_ok!(TemplateModule::create_multiple_items(240// origin1.clone(),241// 1,242// 1,243// items_data.clone().into_iter().map(|d| { d.into() }).collect()244// ));245 246// for (index, _) in items_data.iter().enumerate() {247// assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).value, 5);248// }249// assert_eq!(TemplateModule::balance_count(1, 1), 3000);250// assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);251// });252// }253254#[test]255fn transfer_fungible_item() {256 new_test_ext().execute_with(|| {257 default_limits();258 259 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);260261 let origin1 = Origin::signed(1);262 let origin2 = Origin::signed(2);263264 let data = default_fungible_data();265 create_test_item(collection_id, &data.into());266267 assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 5);268 assert_eq!(TemplateModule::balance_count(1, 1), 5);269270 // change owner scenario271 assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 5));272 assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 0);273 assert_eq!(TemplateModule::balance_count(1, 1), 0);274 assert_eq!(TemplateModule::balance_count(1, 2), 5);275276 // split item scenario277 assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 3));278 assert_eq!(TemplateModule::balance_count(1, 2), 2);279 assert_eq!(TemplateModule::balance_count(1, 3), 3);280281 // split item and new owner has account scenario282 assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 1));283 assert_eq!(TemplateModule::fungible_item_id(1, 2).value, 1);284 assert_eq!(TemplateModule::fungible_item_id(1, 3).value, 4);285 assert_eq!(TemplateModule::balance_count(1, 2), 1);286 assert_eq!(TemplateModule::balance_count(1, 3), 4);287 });288}289290#[test]291fn transfer_refungible_item() {292 new_test_ext().execute_with(|| {293 default_limits();294 295 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);296297 let data = default_re_fungible_data();298 create_test_item(collection_id, &data.clone().into());299300 let origin1 = Origin::signed(1);301 let origin2 = Origin::signed(2);302 assert_eq!(303 TemplateModule::refungible_item_id(collection_id, 1).const_data,304 data.const_data305 );306 assert_eq!(307 TemplateModule::refungible_item_id(collection_id, 1).variable_data,308 data.variable_data309 );310 assert_eq!(311 TemplateModule::refungible_item_id(collection_id, 1).owner[0],312 Ownership {313 owner: 1,314 fraction: 1023315 }316 );317 assert_eq!(TemplateModule::balance_count(1, 1), 1023);318 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);319320 // change owner scenario321 assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1023));322 assert_eq!(323 TemplateModule::refungible_item_id(1, 1).owner[0],324 Ownership {325 owner: 2,326 fraction: 1023327 }328 );329 assert_eq!(TemplateModule::balance_count(1, 1), 0);330 assert_eq!(TemplateModule::balance_count(1, 2), 1023);331 // assert_eq!(TemplateModule::address_tokens(1, 1), []);332 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);333334 // split item scenario335 assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 500));336 assert_eq!(337 TemplateModule::refungible_item_id(1, 1).owner[0],338 Ownership {339 owner: 2,340 fraction: 523341 }342 );343 assert_eq!(344 TemplateModule::refungible_item_id(1, 1).owner[1],345 Ownership {346 owner: 3,347 fraction: 500348 }349 );350 assert_eq!(TemplateModule::balance_count(1, 2), 523);351 assert_eq!(TemplateModule::balance_count(1, 3), 500);352 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);353 assert_eq!(TemplateModule::address_tokens(1, 3), [1]);354355 // split item and new owner has account scenario356 assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 200));357 assert_eq!(358 TemplateModule::refungible_item_id(1, 1).owner[0],359 Ownership {360 owner: 2,361 fraction: 323362 }363 );364 assert_eq!(365 TemplateModule::refungible_item_id(1, 1).owner[1],366 Ownership {367 owner: 3,368 fraction: 700369 }370 );371 assert_eq!(TemplateModule::balance_count(1, 2), 323);372 assert_eq!(TemplateModule::balance_count(1, 3), 700);373 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);374 assert_eq!(TemplateModule::address_tokens(1, 3), [1]);375 });376}377378#[test]379fn transfer_nft_item() {380 new_test_ext().execute_with(|| {381 default_limits();382 383 let collection_id = create_test_collection(&CollectionMode::NFT, 1);384385 let data = default_nft_data();386 create_test_item(collection_id, &data.into());387 assert_eq!(TemplateModule::balance_count(1, 1), 1);388 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);389390 let origin1 = Origin::signed(1);391 // default scenario392 assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000));393 assert_eq!(TemplateModule::nft_item_id(1, 1).owner, 2);394 assert_eq!(TemplateModule::balance_count(1, 1), 0);395 assert_eq!(TemplateModule::balance_count(1, 2), 1);396 // assert_eq!(TemplateModule::address_tokens(1, 1), []);397 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);398 });399}400401#[test]402fn nft_approve_and_transfer_from() {403 new_test_ext().execute_with(|| {404 default_limits();405 406 let collection_id = create_test_collection(&CollectionMode::NFT, 1);407408 let data = default_nft_data();409 create_test_item(collection_id, &data.into());410411 let origin1 = Origin::signed(1);412 let origin2 = Origin::signed(2);413414 assert_eq!(TemplateModule::balance_count(1, 1), 1);415 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);416417 // neg transfer418 assert_noop!(TemplateModule::transfer_from(419 origin2.clone(),420 1,421 2,422 1,423 1,424 1), Error::<Test>::NoPermission);425426 // do approve427 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));428 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);429 assert_eq!(430 TemplateModule::approved(1, (1, 1, 2)),431 5432 );433434 assert_ok!(TemplateModule::transfer_from(435 origin2.clone(),436 1,437 3,438 1,439 1,440 1441 ));442 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);443 });444}445446#[test]447fn nft_approve_and_transfer_from_white_list() {448 new_test_ext().execute_with(|| {449 default_limits();450 451 let collection_id = create_test_collection(&CollectionMode::NFT, 1);452453 let origin1 = Origin::signed(1);454 let origin2 = Origin::signed(2);455456 let data = default_nft_data();457 create_test_item(collection_id, &data.clone().into());458459 assert_eq!(TemplateModule::nft_item_id(1, 1).const_data, data.const_data);460 assert_eq!(TemplateModule::balance_count(1, 1), 1);461 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);462463 assert_ok!(TemplateModule::set_mint_permission(464 origin1.clone(),465 1,466 true467 ));468 assert_ok!(TemplateModule::set_public_access_mode(469 origin1.clone(),470 1,471 AccessMode::WhiteList472 ));473 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));474 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));475 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));476477 // do approve478 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));479 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);480 assert_ok!(TemplateModule::approve(origin1.clone(), 3, 1, 1, 5));481 assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);482483 assert_ok!(TemplateModule::transfer_from(484 origin2.clone(),485 1,486 3,487 1,488 1,489 1490 ));491 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 4);492 });493}494495#[test]496fn refungible_approve_and_transfer_from() {497 new_test_ext().execute_with(|| {498 default_limits();499 500 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);501 502 let origin1 = Origin::signed(1);503 let origin2 = Origin::signed(2);504505 let data = default_re_fungible_data();506 create_test_item(collection_id, &data.into());507508 assert_eq!(TemplateModule::balance_count(1, 1), 1023);509 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);510511 assert_ok!(TemplateModule::set_mint_permission(512 origin1.clone(),513 1,514 true515 ));516 assert_ok!(TemplateModule::set_public_access_mode(517 origin1.clone(),518 1,519 AccessMode::WhiteList520 ));521 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));522 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));523 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));524525 // do approve526 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1023));527 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1023);528529 assert_ok!(TemplateModule::transfer_from(530 origin2.clone(),531 1,532 3,533 1,534 1,535 100536 ));537 assert_eq!(TemplateModule::balance_count(1, 1), 923);538 assert_eq!(TemplateModule::balance_count(1, 3), 100);539 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);540 assert_eq!(TemplateModule::address_tokens(1, 3), [1]);541542 assert_eq!(543 TemplateModule::approved(1, (1, 1, 2)),544 923545 );546 });547}548549#[test]550fn fungible_approve_and_transfer_from() {551 new_test_ext().execute_with(|| {552 default_limits();553 554 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);555 556 let data = default_fungible_data();557 create_test_item(collection_id, &data.into());558559 let origin1 = Origin::signed(1);560 let origin2 = Origin::signed(2);561562 assert_eq!(TemplateModule::balance_count(1, 1), 5);563564 assert_ok!(TemplateModule::set_mint_permission(565 origin1.clone(),566 1,567 true568 ));569 assert_ok!(TemplateModule::set_public_access_mode(570 origin1.clone(),571 1,572 AccessMode::WhiteList573 ));574 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));575 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));576 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));577578 // do approve579 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 5));580 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 5);581 assert_ok!(TemplateModule::approve(origin1.clone(), 3, 1, 1, 5));582 assert_eq!(TemplateModule::approved(1, (1, 1, 3)), 5);583 assert_eq!(584 TemplateModule::approved(1, (1, 1, 2)),585 5586 );587588 assert_ok!(TemplateModule::transfer_from(589 origin2.clone(),590 1,591 3,592 1,593 1,594 4595 ));596 assert_eq!(TemplateModule::balance_count(1, 1), 1);597 assert_eq!(TemplateModule::balance_count(1, 3), 4);598599 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);600601 assert_noop!(TemplateModule::transfer_from(602 origin2.clone(),603 1,604 3,605 1,606 1,607 4608 ), Error::<Test>::TokenValueNotEnough);609 });610}611612#[test]613fn change_collection_owner() {614 new_test_ext().execute_with(|| {615 default_limits();616 617 let collection_id = create_test_collection(&CollectionMode::NFT, 1);618 619 let origin1 = Origin::signed(1);620 assert_ok!(TemplateModule::change_collection_owner(621 origin1.clone(),622 collection_id,623 2624 ));625 assert_eq!(TemplateModule::collection_id(collection_id).unwrap().owner, 2);626 });627}628629#[test]630fn destroy_collection() {631 new_test_ext().execute_with(|| {632 default_limits();633 634 let collection_id = create_test_collection(&CollectionMode::NFT, 1);635 636 let origin1 = Origin::signed(1);637 assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));638 });639}640641#[test]642fn burn_nft_item() {643 new_test_ext().execute_with(|| {644 default_limits();645 646 let collection_id = create_test_collection(&CollectionMode::NFT, 1);647648 let origin1 = Origin::signed(1);649 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));650 651 let data = default_nft_data();652 create_test_item(collection_id, &data.into());653654 // check balance (collection with id = 1, user id = 1)655 assert_eq!(TemplateModule::balance_count(1, 1), 1);656657 // burn item658 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));659 assert_noop!(660 TemplateModule::burn_item(origin1.clone(), 1, 1, 5),661 Error::<Test>::TokenNotFound662 );663664 assert_eq!(TemplateModule::balance_count(1, 1), 0);665 });666}667668#[test]669fn burn_fungible_item() {670 new_test_ext().execute_with(|| {671 default_limits();672 673 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);674 675 let origin1 = Origin::signed(1);676 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));677 678 let data = default_fungible_data();679 create_test_item(collection_id, &data.into());680681 // check balance (collection with id = 1, user id = 1)682 assert_eq!(TemplateModule::balance_count(1, 1), 5);683684 // burn item685 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5));686 assert_noop!(687 TemplateModule::burn_item(origin1.clone(), 1, 1, 5),688 Error::<Test>::TokenNotFound689 );690691 assert_eq!(TemplateModule::balance_count(1, 1), 0);692 });693}694695#[test]696fn burn_refungible_item() {697 new_test_ext().execute_with(|| {698 default_limits();699 700 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);701 let origin1 = Origin::signed(1);702703 assert_ok!(TemplateModule::set_mint_permission(704 origin1.clone(),705 collection_id,706 true707 ));708 assert_ok!(TemplateModule::set_public_access_mode(709 origin1.clone(),710 collection_id,711 AccessMode::WhiteList712 ));713 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));714715 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));716 717 let data = default_re_fungible_data();718 create_test_item(collection_id, &data.into());719720 // check balance (collection with id = 1, user id = 2)721 assert_eq!(TemplateModule::balance_count(1, 1), 1023);722723 // burn item724 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1023));725 assert_noop!(726 TemplateModule::burn_item(origin1.clone(), 1, 1, 1023),727 Error::<Test>::TokenNotFound728 );729730 assert_eq!(TemplateModule::balance_count(1, 1), 0);731 });732}733734#[test]735fn add_collection_admin() {736 new_test_ext().execute_with(|| {737 default_limits();738 739 let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);740 create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);741 create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);742 743 let origin1 = Origin::signed(1);744745 // collection admin746 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 2));747 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 3));748749 assert_eq!(TemplateModule::admin_list_collection(collection1_id).contains(&2), true);750 assert_eq!(TemplateModule::admin_list_collection(collection1_id).contains(&3), true);751 });752}753754#[test]755fn remove_collection_admin() {756 new_test_ext().execute_with(|| {757 default_limits();758 759 let collection1_id = create_test_collection_for_owner(&CollectionMode::NFT, 1, 1);760 create_test_collection_for_owner(&CollectionMode::NFT, 2, 2);761 create_test_collection_for_owner(&CollectionMode::NFT, 3, 3);762763 let origin1 = Origin::signed(1);764 let origin2 = Origin::signed(2);765766 // collection admin767 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 2));768 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection1_id, 3));769770 assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true);771 assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true);772773 // remove admin774 assert_ok!(TemplateModule::remove_collection_admin(775 origin2.clone(),776 1,777 3778 ));779 assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), false);780 });781}782783#[test]784fn balance_of() {785 new_test_ext().execute_with(|| {786 default_limits();787 788 let nft_collection_id = create_test_collection(&CollectionMode::NFT, 1);789 let fungible_collection_id = create_test_collection(&CollectionMode::Fungible(3), 2);790 let re_fungible_collection_id = create_test_collection(&CollectionMode::ReFungible, 3);791 792 // check balance before793 assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 0);794 assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 0);795 assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 0);796797 let nft_data = default_nft_data();798 create_test_item(nft_collection_id, &nft_data.into());799 800 let fungible_data = default_fungible_data();801 create_test_item(fungible_collection_id, &fungible_data.into());802 803 let re_fungible_data = default_re_fungible_data();804 create_test_item(re_fungible_collection_id, &re_fungible_data.into());805806 // check balance (collection with id = 1, user id = 1)807 assert_eq!(TemplateModule::balance_count(nft_collection_id, 1), 1);808 assert_eq!(TemplateModule::balance_count(fungible_collection_id, 1), 5);809 assert_eq!(TemplateModule::balance_count(re_fungible_collection_id, 1), 1023);810 assert_eq!(TemplateModule::nft_item_id(nft_collection_id, 1).owner, 1);811 assert_eq!(TemplateModule::fungible_item_id(fungible_collection_id, 1).value, 5);812 assert_eq!(TemplateModule::refungible_item_id(re_fungible_collection_id, 1).owner[0].owner, 1);813 });814}815816#[test]817fn approve() {818 new_test_ext().execute_with(|| {819 default_limits();820 821 let collection_id = create_test_collection(&CollectionMode::NFT, 1);822 823 let data = default_nft_data();824 create_test_item(collection_id, &data.into());825826 let origin1 = Origin::signed(1);827 828 // approve829 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1));830 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);831 });832}833834#[test]835fn transfer_from() {836 new_test_ext().execute_with(|| {837 default_limits();838 839 let collection_id = create_test_collection(&CollectionMode::NFT, 1);840 let origin1 = Origin::signed(1);841 let origin2 = Origin::signed(2);842843 let data = default_nft_data();844 create_test_item(collection_id, &data.into());845846 // approve847 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1, 1));848 assert_eq!(TemplateModule::approved(1, (1, 1, 2)), 1);849850 assert_ok!(TemplateModule::set_mint_permission(851 origin1.clone(),852 1,853 true854 ));855 assert_ok!(TemplateModule::set_public_access_mode(856 origin1.clone(),857 1,858 AccessMode::WhiteList859 ));860 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));861 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));862 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 3));863864 assert_ok!(TemplateModule::transfer_from(865 origin2.clone(),866 1,867 2,868 1,869 1,870 1871 ));872873 // after transfer874 assert_eq!(TemplateModule::balance_count(1, 1), 0);875 assert_eq!(TemplateModule::balance_count(1, 2), 1);876 });877}878879// #endregion880881// Coverage tests region882// #region883884#[test]885fn owner_can_add_address_to_white_list() {886 new_test_ext().execute_with(|| {887 default_limits();888 889 let collection_id = create_test_collection(&CollectionMode::NFT, 1);890891 let origin1 = Origin::signed(1);892 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));893 assert_eq!(TemplateModule::white_list(collection_id, 2), true);894 });895}896897#[test]898fn admin_can_add_address_to_white_list() {899 new_test_ext().execute_with(|| {900 default_limits();901 902 let collection_id = create_test_collection(&CollectionMode::NFT, 1);903 let origin1 = Origin::signed(1);904 let origin2 = Origin::signed(2);905906 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));907 assert_ok!(TemplateModule::add_to_white_list(origin2.clone(), collection_id, 3));908 assert_eq!(TemplateModule::white_list(collection_id, 3), true);909 });910}911912#[test]913fn nonprivileged_user_cannot_add_address_to_white_list() {914 new_test_ext().execute_with(|| {915 default_limits();916 917 let collection_id = create_test_collection(&CollectionMode::NFT, 1);918919 let origin2 = Origin::signed(2);920 assert_noop!(921 TemplateModule::add_to_white_list(origin2.clone(), collection_id, 3),922 Error::<Test>::NoPermission923 );924 });925}926927#[test]928fn nobody_can_add_address_to_white_list_of_nonexisting_collection() {929 new_test_ext().execute_with(|| {930 default_limits();931932 let origin1 = Origin::signed(1);933934 assert_noop!(935 TemplateModule::add_to_white_list(origin1.clone(), 1, 2),936 Error::<Test>::CollectionNotFound937 );938 });939}940941#[test]942fn nobody_can_add_address_to_white_list_of_deleted_collection() {943 new_test_ext().execute_with(|| {944 default_limits();945 946 let collection_id = create_test_collection(&CollectionMode::NFT, 1);947948 let origin1 = Origin::signed(1);949 assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));950 assert_noop!(951 TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2),952 Error::<Test>::CollectionNotFound953 );954 });955}956957// If address is already added to white list, nothing happens958#[test]959fn address_is_already_added_to_white_list() {960 new_test_ext().execute_with(|| {961 default_limits();962 963 let collection_id = create_test_collection(&CollectionMode::NFT, 1);964 let origin1 = Origin::signed(1);965 966 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));967 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));968 assert_eq!(TemplateModule::white_list(collection_id, 2), true);969 });970}971972#[test]973fn owner_can_remove_address_from_white_list() {974 new_test_ext().execute_with(|| {975 default_limits();976 977 let collection_id = create_test_collection(&CollectionMode::NFT, 1);978979 let origin1 = Origin::signed(1);980 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));981 assert_ok!(TemplateModule::remove_from_white_list(982 origin1.clone(),983 collection_id,984 2985 ));986 assert_eq!(TemplateModule::white_list(collection_id, 2), false);987 });988}989990#[test]991fn admin_can_remove_address_from_white_list() {992 new_test_ext().execute_with(|| {993 default_limits();994 995 let collection_id = create_test_collection(&CollectionMode::NFT, 1);996 let origin1 = Origin::signed(1);997 let origin2 = Origin::signed(2);998999 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));10001001 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 3));1002 assert_ok!(TemplateModule::remove_from_white_list(1003 origin2.clone(),1004 collection_id,1005 31006 ));1007 assert_eq!(TemplateModule::white_list(collection_id, 3), false);1008 });1009}10101011#[test]1012fn nonprivileged_user_cannot_remove_address_from_white_list() {1013 new_test_ext().execute_with(|| {1014 default_limits();1015 1016 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1017 let origin1 = Origin::signed(1);1018 let origin2 = Origin::signed(2);10191020 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1021 assert_noop!(1022 TemplateModule::remove_from_white_list(origin2.clone(), collection_id, 2),1023 Error::<Test>::NoPermission1024 );1025 assert_eq!(TemplateModule::white_list(collection_id, 2), true);1026 });1027}10281029#[test]1030fn nobody_can_remove_address_from_white_list_of_nonexisting_collection() {1031 new_test_ext().execute_with(|| {1032 default_limits();1033 let origin1 = Origin::signed(1);10341035 assert_noop!(1036 TemplateModule::remove_from_white_list(origin1.clone(), 1, 2),1037 Error::<Test>::CollectionNotFound1038 );1039 });1040}10411042#[test]1043fn nobody_can_remove_address_from_white_list_of_deleted_collection() {1044 new_test_ext().execute_with(|| {1045 default_limits();1046 1047 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1048 let origin1 = Origin::signed(1);1049 let origin2 = Origin::signed(2);10501051 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1052 assert_ok!(TemplateModule::destroy_collection(origin1.clone(), collection_id));1053 assert_noop!(1054 TemplateModule::remove_from_white_list(origin2.clone(), collection_id, 2),1055 Error::<Test>::CollectionNotFound1056 );1057 assert_eq!(TemplateModule::white_list(collection_id, 2), false);1058 });1059}10601061// If address is already removed from white list, nothing happens1062#[test]1063fn address_is_already_removed_from_white_list() {1064 new_test_ext().execute_with(|| {1065 default_limits();1066 1067 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1068 let origin1 = Origin::signed(1);10691070 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));1071 assert_ok!(TemplateModule::remove_from_white_list(1072 origin1.clone(),1073 collection_id,1074 21075 ));1076 assert_ok!(TemplateModule::remove_from_white_list(1077 origin1.clone(),1078 collection_id,1079 21080 ));1081 assert_eq!(TemplateModule::white_list(collection_id, 2), false);1082 });1083}10841085// If Public Access mode is set to WhiteList, tokens can’t be transferred from a non-whitelisted address with transfer or transferFrom (2 tests)1086#[test]1087fn white_list_test_1() {1088 new_test_ext().execute_with(|| {1089 default_limits();1090 1091 let collection_id = create_test_collection(&CollectionMode::NFT, 1);10921093 let origin1 = Origin::signed(1);1094 1095 let data = default_nft_data();1096 create_test_item(collection_id, &data.into());10971098 assert_ok!(TemplateModule::set_public_access_mode(1099 origin1.clone(),1100 collection_id,1101 AccessMode::WhiteList1102 ));1103 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));11041105 assert_noop!(1106 TemplateModule::transfer(origin1.clone(), 3, 1, 1, 1),1107 Error::<Test>::AddresNotInWhiteList1108 );1109 });1110}11111112#[test]1113fn white_list_test_2() {1114 new_test_ext().execute_with(|| {1115 default_limits();1116 1117 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1118 let origin1 = Origin::signed(1);1119 1120 let data = default_nft_data();1121 create_test_item(collection_id, &data.into());11221123 assert_ok!(TemplateModule::set_public_access_mode(1124 origin1.clone(),1125 collection_id,1126 AccessMode::WhiteList1127 ));1128 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));1129 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 2));11301131 // do approve1132 assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1, 1));1133 assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);11341135 assert_ok!(TemplateModule::remove_from_white_list(1136 origin1.clone(),1137 1,1138 11139 ));11401141 assert_noop!(1142 TemplateModule::transfer_from(origin1.clone(), 1, 3, 1, 1, 1),1143 Error::<Test>::AddresNotInWhiteList1144 );1145 });1146}11471148// If Public Access mode is set to WhiteList, tokens can’t be transferred to a non-whitelisted address with transfer or transferFrom (2 tests)1149#[test]1150fn white_list_test_3() {1151 new_test_ext().execute_with(|| {1152 default_limits();1153 1154 let collection_id = create_test_collection(&CollectionMode::NFT, 1);11551156 let origin1 = Origin::signed(1);1157 1158 let data = default_nft_data();1159 create_test_item(collection_id, &data.into());11601161 assert_ok!(TemplateModule::set_public_access_mode(1162 origin1.clone(),1163 collection_id,1164 AccessMode::WhiteList1165 ));1166 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), 1, 1));11671168 assert_noop!(1169 TemplateModule::transfer(origin1.clone(), 3, 1, 1, 1),1170 Error::<Test>::AddresNotInWhiteList1171 );1172 });1173}11741175#[test]1176fn white_list_test_4() {1177 new_test_ext().execute_with(|| {1178 default_limits();1179 1180 let collection_id = create_test_collection(&CollectionMode::NFT, 1);11811182 let origin1 = Origin::signed(1);11831184 let data = default_nft_data();1185 create_test_item(collection_id, &data.into());11861187 assert_ok!(TemplateModule::set_public_access_mode(1188 origin1.clone(),1189 collection_id,1190 AccessMode::WhiteList1191 ));1192 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1193 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));11941195 // do approve1196 assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1, 1));1197 assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 1);11981199 assert_ok!(TemplateModule::remove_from_white_list(1200 origin1.clone(),1201 collection_id,1202 21203 ));12041205 assert_noop!(1206 TemplateModule::transfer_from(origin1.clone(), 1, 3, 1, 1, 1),1207 Error::<Test>::AddresNotInWhiteList1208 );1209 });1210}12111212// If Public Access mode is set to WhiteList, tokens can’t be destroyed by a non-whitelisted address (even if it owned them before enabling WhiteList mode)1213#[test]1214fn white_list_test_5() {1215 new_test_ext().execute_with(|| {1216 default_limits();1217 1218 let collection_id = create_test_collection(&CollectionMode::NFT, 1);12191220 let origin1 = Origin::signed(1);12211222 let data = default_nft_data();1223 create_test_item(collection_id, &data.into());12241225 assert_ok!(TemplateModule::set_public_access_mode(1226 origin1.clone(),1227 collection_id,1228 AccessMode::WhiteList1229 ));1230 assert_noop!(1231 TemplateModule::burn_item(origin1.clone(), 1, 1, 5),1232 Error::<Test>::AddresNotInWhiteList1233 );1234 });1235}12361237// If Public Access mode is set to WhiteList, token transfers can’t be Approved by a non-whitelisted address (see Approve method).1238#[test]1239fn white_list_test_6() {1240 new_test_ext().execute_with(|| {1241 default_limits();1242 1243 let collection_id = create_test_collection(&CollectionMode::NFT, 1);12441245 let origin1 = Origin::signed(1);12461247 let data = default_nft_data();1248 create_test_item(collection_id, &data.into());12491250 assert_ok!(TemplateModule::set_public_access_mode(1251 origin1.clone(),1252 collection_id,1253 AccessMode::WhiteList1254 ));12551256 // do approve1257 assert_noop!(1258 TemplateModule::approve(origin1.clone(), 1, 1, 1, 5),1259 Error::<Test>::AddresNotInWhiteList1260 );1261 });1262}12631264// If Public Access mode is set to WhiteList, tokens can be transferred from a whitelisted address with transfer or transferFrom (2 tests) and1265// tokens can be transferred from a whitelisted address with transfer or transferFrom (2 tests)1266#[test]1267fn white_list_test_7() {1268 new_test_ext().execute_with(|| {1269 default_limits();1270 1271 let collection_id = create_test_collection(&CollectionMode::NFT, 1);12721273 let data = default_nft_data();1274 create_test_item(collection_id, &data.into());1275 1276 let origin1 = Origin::signed(1);12771278 assert_ok!(TemplateModule::set_public_access_mode(1279 origin1.clone(),1280 collection_id,1281 AccessMode::WhiteList1282 ));1283 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1284 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));12851286 assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1));1287 });1288}12891290#[test]1291fn white_list_test_8() {1292 new_test_ext().execute_with(|| {1293 default_limits();1294 1295 let collection_id = create_test_collection(&CollectionMode::NFT, 1);12961297 let data = default_nft_data();1298 create_test_item(collection_id, &data.into());1299 1300 let origin1 = Origin::signed(1);13011302 assert_ok!(TemplateModule::set_public_access_mode(1303 origin1.clone(),1304 collection_id,1305 AccessMode::WhiteList1306 ));1307 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 1));1308 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));13091310 // do approve1311 assert_ok!(TemplateModule::approve(origin1.clone(), 1, 1, 1, 5));1312 assert_eq!(TemplateModule::approved(1, (1, 1, 1)), 5);13131314 assert_ok!(TemplateModule::transfer_from(1315 origin1.clone(),1316 1,1317 2,1318 1,1319 1,1320 11321 ));1322 });1323}13241325// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens can be created by owner.1326#[test]1327fn white_list_test_9() {1328 new_test_ext().execute_with(|| {1329 default_limits();1330 1331 let collection_id = create_test_collection(&CollectionMode::NFT, 1);1332 let origin1 = Origin::signed(1);13331334 assert_ok!(TemplateModule::set_public_access_mode(1335 origin1.clone(),1336 collection_id,1337 AccessMode::WhiteList1338 ));1339 assert_ok!(TemplateModule::set_mint_permission(1340 origin1.clone(),1341 collection_id,1342 false1343 ));13441345 let data = default_nft_data();1346 create_test_item(collection_id, &data.into());1347 });1348}13491350// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens can be created by admin.1351#[test]1352fn white_list_test_10() {1353 new_test_ext().execute_with(|| {1354 default_limits();1355 1356 let collection_id = create_test_collection(&CollectionMode::NFT, 1);13571358 let origin1 = Origin::signed(1);1359 let origin2 = Origin::signed(2);13601361 assert_ok!(TemplateModule::set_public_access_mode(1362 origin1.clone(),1363 collection_id,1364 AccessMode::WhiteList1365 ));1366 assert_ok!(TemplateModule::set_mint_permission(1367 origin1.clone(),1368 collection_id,1369 false1370 ));13711372 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));13731374 assert_ok!(TemplateModule::create_item(1375 origin2.clone(),1376 collection_id,1377 2,1378 default_nft_data().into()1379 ));1380 });1381}13821383// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens cannot be created by non-privileged and white listed address.1384#[test]1385fn white_list_test_11() {1386 new_test_ext().execute_with(|| {1387 default_limits();1388 1389 let collection_id = create_test_collection(&CollectionMode::NFT, 1);13901391 let origin1 = Origin::signed(1);1392 let origin2 = Origin::signed(2);13931394 assert_ok!(TemplateModule::set_public_access_mode(1395 origin1.clone(),1396 collection_id,1397 AccessMode::WhiteList1398 ));1399 assert_ok!(TemplateModule::set_mint_permission(1400 origin1.clone(),1401 collection_id,1402 false1403 ));1404 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));14051406 assert_noop!(1407 TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1408 Error::<Test>::PublicMintingNotAllowed1409 );1410 });1411}14121413// If Public Access mode is set to WhiteList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-white listed address.1414#[test]1415fn white_list_test_12() {1416 new_test_ext().execute_with(|| {1417 default_limits();1418 1419 let collection_id = create_test_collection(&CollectionMode::NFT, 1);14201421 let origin1 = Origin::signed(1);1422 let origin2 = Origin::signed(2);14231424 assert_ok!(TemplateModule::set_public_access_mode(1425 origin1.clone(),1426 collection_id,1427 AccessMode::WhiteList1428 ));1429 assert_ok!(TemplateModule::set_mint_permission(1430 origin1.clone(),1431 collection_id,1432 false1433 ));14341435 assert_noop!(1436 TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1437 Error::<Test>::PublicMintingNotAllowed1438 );1439 });1440}14411442// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by owner.1443#[test]1444fn white_list_test_13() {1445 new_test_ext().execute_with(|| {1446 default_limits();1447 1448 let collection_id = create_test_collection(&CollectionMode::NFT, 1);14491450 let origin1 = Origin::signed(1);14511452 assert_ok!(TemplateModule::set_public_access_mode(1453 origin1.clone(),1454 collection_id,1455 AccessMode::WhiteList1456 ));1457 assert_ok!(TemplateModule::set_mint_permission(1458 origin1.clone(),1459 collection_id,1460 true1461 ));14621463 let data = default_nft_data();1464 create_test_item(collection_id, &data.into());1465 });1466}14671468// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by admin.1469#[test]1470fn white_list_test_14() {1471 new_test_ext().execute_with(|| {1472 default_limits();1473 1474 let collection_id = create_test_collection(&CollectionMode::NFT, 1);14751476 let origin1 = Origin::signed(1);1477 let origin2 = Origin::signed(2);14781479 assert_ok!(TemplateModule::set_public_access_mode(1480 origin1.clone(),1481 collection_id,1482 AccessMode::WhiteList1483 ));1484 assert_ok!(TemplateModule::set_mint_permission(1485 origin1.clone(),1486 collection_id,1487 true1488 ));14891490 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));14911492 assert_ok!(TemplateModule::create_item(1493 origin2.clone(),1494 1,1495 2,1496 default_nft_data().into()1497 ));1498 });1499}15001501// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-white listed address.1502#[test]1503fn white_list_test_15() {1504 new_test_ext().execute_with(|| {1505 default_limits();1506 1507 let collection_id = create_test_collection(&CollectionMode::NFT, 1);15081509 let origin1 = Origin::signed(1);1510 let origin2 = Origin::signed(2);15111512 assert_ok!(TemplateModule::set_public_access_mode(1513 origin1.clone(),1514 collection_id,1515 AccessMode::WhiteList1516 ));1517 assert_ok!(TemplateModule::set_mint_permission(1518 origin1.clone(),1519 collection_id,1520 true1521 ));15221523 assert_noop!(1524 TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1525 Error::<Test>::AddresNotInWhiteList1526 );1527 });1528}15291530// If Public Access mode is set to WhiteList, and Mint Permission is set to true, tokens can be created by non-privileged and white listed address.1531#[test]1532fn white_list_test_16() {1533 new_test_ext().execute_with(|| {1534 default_limits();1535 1536 let collection_id = create_test_collection(&CollectionMode::NFT, 1);15371538 let origin1 = Origin::signed(1);1539 let origin2 = Origin::signed(2);15401541 assert_ok!(TemplateModule::set_public_access_mode(1542 origin1.clone(),1543 collection_id,1544 AccessMode::WhiteList1545 ));1546 assert_ok!(TemplateModule::set_mint_permission(1547 origin1.clone(),1548 collection_id,1549 true1550 ));1551 assert_ok!(TemplateModule::add_to_white_list(origin1.clone(), collection_id, 2));15521553 assert_ok!(TemplateModule::create_item(1554 origin2.clone(),1555 1,1556 2,1557 default_nft_data().into()1558 ));1559 });1560}15611562// Total number of collections. Positive test1563#[test]1564fn total_number_collections_bound() {1565 new_test_ext().execute_with(|| {1566 default_limits();1567 1568 create_test_collection(&CollectionMode::NFT, 1);1569 });1570}15711572// Total number of collections. Negotive test1573#[test]1574fn total_number_collections_bound_neg() {1575 new_test_ext().execute_with(|| {1576 default_limits();15771578 let origin1 = Origin::signed(1);15791580 for i in 0..default_collection_numbers_limit() {1581 create_test_collection(&CollectionMode::NFT, i + 1);1582 }15831584 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();1585 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();1586 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();15871588 // 11-th collection in chain. Expects error1589 assert_noop!(TemplateModule::create_collection(1590 origin1.clone(),1591 col_name1.clone(),1592 col_desc1.clone(),1593 token_prefix1.clone(),1594 CollectionMode::NFT1595 ), Error::<Test>::TotalCollectionsLimitExceeded);1596 });1597}15981599// Owned tokens by a single address. Positive test1600#[test]1601fn owned_tokens_bound() {1602 new_test_ext().execute_with(|| {1603 default_limits();1604 1605 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16061607 let data = default_nft_data();1608 create_test_item(collection_id, &data.clone().into());1609 create_test_item(collection_id, &data.into());1610 });1611}16121613// Owned tokens by a single address. Negotive test1614#[test]1615fn owned_tokens_bound_neg() {1616 new_test_ext().execute_with(|| {1617 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1618 collection_numbers_limit: 10,1619 account_token_ownership_limit: 1,1620 collections_admins_limit: 5,1621 custom_data_limit: 2048,1622 nft_sponsor_transfer_timeout: 15,1623 fungible_sponsor_transfer_timeout: 15,1624 refungible_sponsor_transfer_timeout: 15,1625 const_on_chain_schema_limit: 1024,1626 offchain_schema_limit: 1024,1627 variable_on_chain_schema_limit: 1024,1628 }));1629 1630 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16311632 let origin1 = Origin::signed(1);1633 let data = default_nft_data();1634 create_test_item(collection_id, &data.clone().into());16351636 assert_noop!(TemplateModule::create_item(1637 origin1.clone(),1638 1,1639 1,1640 data.into()1641 ), Error::<Test>::AddressOwnershipLimitExceeded);1642 });1643}16441645// Number of collection admins. Positive test1646#[test]1647fn collection_admins_bound() {1648 new_test_ext().execute_with(|| {1649 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1650 collection_numbers_limit: 10,1651 account_token_ownership_limit: 10,1652 collections_admins_limit: 2,1653 custom_data_limit: 2048,1654 nft_sponsor_transfer_timeout: 15,1655 fungible_sponsor_transfer_timeout: 15,1656 refungible_sponsor_transfer_timeout: 15,1657 const_on_chain_schema_limit: 1024,1658 offchain_schema_limit: 1024,1659 variable_on_chain_schema_limit: 1024,1660 }));1661 1662 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16631664 let origin1 = Origin::signed(1);1665 1666 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));1667 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 3));1668 });1669}16701671// Number of collection admins. Negotive test1672#[test]1673fn collection_admins_bound_neg() {1674 new_test_ext().execute_with(|| {1675 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1676 collection_numbers_limit: 10,1677 account_token_ownership_limit: 1,1678 collections_admins_limit: 1,1679 custom_data_limit: 2048,1680 nft_sponsor_transfer_timeout: 15,1681 fungible_sponsor_transfer_timeout: 15,1682 refungible_sponsor_transfer_timeout: 15,1683 const_on_chain_schema_limit: 1024,1684 offchain_schema_limit: 1024,1685 variable_on_chain_schema_limit: 1024,1686 }));1687 1688 let collection_id = create_test_collection(&CollectionMode::NFT, 1);16891690 let origin1 = Origin::signed(1);16911692 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 2));1693 assert_noop!(TemplateModule::add_collection_admin(origin1.clone(), collection_id, 3), Error::<Test>::CollectionAdminsLimitExceeded);1694 });1695}16961697// NFT custom data size. Negative test const_data.1698#[test]1699fn custom_data_size_nft_const_data_bound_neg() {1700 new_test_ext().execute_with(|| {1701 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1702 collection_numbers_limit: 10,1703 account_token_ownership_limit: 10,1704 collections_admins_limit: 5,1705 custom_data_limit: 2,1706 nft_sponsor_transfer_timeout: 15,1707 fungible_sponsor_transfer_timeout: 15,1708 refungible_sponsor_transfer_timeout: 15,1709 const_on_chain_schema_limit: 1024,1710 offchain_schema_limit: 1024,1711 variable_on_chain_schema_limit: 1024,1712 }));1713 1714 let collection_id = create_test_collection(&CollectionMode::NFT, 1);17151716 let origin1 = Origin::signed(1);1717 let too_big_const_data = CreateItemData::NFT(CreateNftData{1718 const_data: vec![1, 2, 3, 4],1719 variable_data: vec![]1720 });17211722 assert_noop!(TemplateModule::create_item(1723 origin1.clone(),1724 collection_id,1725 1,1726 too_big_const_data1727 ), Error::<Test>::TokenConstDataLimitExceeded);1728 });1729}17301731// NFT custom data size. Negative test variable_data.1732#[test]1733fn custom_data_size_nft_variable_data_bound_neg() {1734 new_test_ext().execute_with(|| {1735 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1736 collection_numbers_limit: 10,1737 account_token_ownership_limit: 10,1738 collections_admins_limit: 5,1739 custom_data_limit: 2,1740 nft_sponsor_transfer_timeout: 15,1741 fungible_sponsor_transfer_timeout: 15,1742 refungible_sponsor_transfer_timeout: 15,1743 const_on_chain_schema_limit: 1024,1744 offchain_schema_limit: 1024,1745 variable_on_chain_schema_limit: 1024,1746 }));17471748 let collection_id = create_test_collection(&CollectionMode::NFT, 1);17491750 let origin1 = Origin::signed(1);1751 let too_big_const_data = CreateItemData::NFT(CreateNftData{1752 const_data: vec![],1753 variable_data: vec![1, 2, 3, 4]1754 });17551756 assert_noop!(TemplateModule::create_item(1757 origin1.clone(),1758 collection_id,1759 1,1760 too_big_const_data1761 ), Error::<Test>::TokenVariableDataLimitExceeded);1762 });1763}17641765// Re fungible custom data size. Negative test const_data.1766#[test]1767fn custom_data_size_re_fungible_const_data_bound_neg() {1768 new_test_ext().execute_with(|| {1769 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1770 collection_numbers_limit: 10,1771 account_token_ownership_limit: 10,1772 collections_admins_limit: 5,1773 custom_data_limit: 2,1774 nft_sponsor_transfer_timeout: 15,1775 fungible_sponsor_transfer_timeout: 15,1776 refungible_sponsor_transfer_timeout: 15,1777 const_on_chain_schema_limit: 1024,1778 offchain_schema_limit: 1024,1779 variable_on_chain_schema_limit: 1024,1780 }));17811782 let collection_id = create_test_collection(&CollectionMode::NFT, 1);17831784 let origin1 = Origin::signed(1);1785 let too_big_const_data = CreateItemData::NFT(CreateNftData{1786 const_data: vec![1, 2, 3, 4],1787 variable_data: vec![]1788 });17891790 assert_noop!(TemplateModule::create_item(1791 origin1.clone(),1792 collection_id,1793 1,1794 too_big_const_data1795 ), Error::<Test>::TokenConstDataLimitExceeded);1796 });1797}17981799// Re fungible custom data size. Negative test variable_data.1800#[test]1801fn custom_data_size_re_fungible_variable_data_bound_neg() {1802 new_test_ext().execute_with(|| {1803 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1804 collection_numbers_limit: 10,1805 account_token_ownership_limit: 10,1806 collections_admins_limit: 5,1807 custom_data_limit: 2,1808 nft_sponsor_transfer_timeout: 15,1809 fungible_sponsor_transfer_timeout: 15,1810 refungible_sponsor_transfer_timeout: 15,1811 const_on_chain_schema_limit: 1024,1812 offchain_schema_limit: 1024,1813 variable_on_chain_schema_limit: 1024,1814 }));18151816 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18171818 let origin1 = Origin::signed(1);1819 let too_big_const_data = CreateItemData::NFT(CreateNftData{1820 const_data: vec![],1821 variable_data: vec![1, 2, 3, 4]1822 });18231824 assert_noop!(TemplateModule::create_item(1825 origin1.clone(),1826 collection_id,1827 1,1828 too_big_const_data1829 ), Error::<Test>::TokenVariableDataLimitExceeded);1830 });1831}1832// #endregion18331834#[test]1835fn set_const_on_chain_schema() {1836 new_test_ext().execute_with(|| {1837 default_limits();18381839 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18401841 let origin1 = Origin::signed(1);1842 assert_ok!(TemplateModule::set_const_on_chain_schema(origin1, collection_id, b"test const on chain schema".to_vec()));18431844 assert_eq!(TemplateModule::collection_id(collection_id).unwrap().const_on_chain_schema, b"test const on chain schema".to_vec());1845 assert_eq!(TemplateModule::collection_id(collection_id).unwrap().variable_on_chain_schema, b"".to_vec());1846 });1847}18481849#[test]1850fn set_variable_on_chain_schema() {1851 new_test_ext().execute_with(|| {1852 default_limits();1853 1854 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18551856 let origin1 = Origin::signed(1);1857 assert_ok!(TemplateModule::set_variable_on_chain_schema(origin1, collection_id, b"test variable on chain schema".to_vec()));18581859 assert_eq!(TemplateModule::collection_id(collection_id).unwrap().const_on_chain_schema, b"".to_vec());1860 assert_eq!(TemplateModule::collection_id(collection_id).unwrap().variable_on_chain_schema, b"test variable on chain schema".to_vec());1861 });1862}18631864#[test]1865fn set_variable_meta_data_on_nft_token_stores_variable_meta_data() {1866 new_test_ext().execute_with(|| {1867 default_limits();18681869 let collection_id = create_test_collection(&CollectionMode::NFT, 1);18701871 let origin1 = Origin::signed(1);1872 1873 let data = default_nft_data();1874 create_test_item(1, &data.into());1875 1876 let variable_data = b"test set_variable_meta_data method.".to_vec();1877 assert_ok!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()));18781879 assert_eq!(TemplateModule::nft_item_id(collection_id, 1).variable_data, variable_data);1880 });1881}18821883#[test]1884fn set_variable_meta_data_on_re_fungible_token_stores_variable_meta_data() {1885 new_test_ext().execute_with(|| {1886 default_limits();18871888 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);18891890 let origin1 = Origin::signed(1);18911892 let data = default_re_fungible_data();1893 create_test_item(1, &data.into());18941895 let variable_data = b"test set_variable_meta_data method.".to_vec();1896 assert_ok!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()));18971898 assert_eq!(TemplateModule::refungible_item_id(collection_id, 1).variable_data, variable_data);1899 });1900}190119021903#[test]1904fn set_variable_meta_data_on_fungible_token_fails() {1905 new_test_ext().execute_with(|| {1906 default_limits();19071908 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);19091910 let origin1 = Origin::signed(1);19111912 let data = default_fungible_data();1913 create_test_item(1, &data.into());19141915 let variable_data = b"test set_variable_meta_data method.".to_vec();1916 assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data.clone()), Error::<Test>::CantStoreMetadataInFungibleTokens);1917 });1918}19191920#[test]1921fn set_variable_meta_data_on_nft_token_fails_for_big_data() {1922 new_test_ext().execute_with(|| {1923 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1924 collection_numbers_limit: default_collection_numbers_limit(),1925 account_token_ownership_limit: 10,1926 collections_admins_limit: 5,1927 custom_data_limit: 10,1928 nft_sponsor_transfer_timeout: 15,1929 fungible_sponsor_transfer_timeout: 15,1930 refungible_sponsor_transfer_timeout: 15,1931 const_on_chain_schema_limit: 1024,1932 offchain_schema_limit: 1024,1933 variable_on_chain_schema_limit: 1024,1934 }));19351936 let collection_id = create_test_collection(&CollectionMode::NFT, 1);19371938 let origin1 = Origin::signed(1);19391940 let data = default_nft_data();1941 create_test_item(1, &data.into());19421943 let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();1944 assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data), Error::<Test>::TokenVariableDataLimitExceeded);1945 });1946}19471948#[test]1949fn set_variable_meta_data_on_re_fungible_token_fails_for_big_data() {1950 new_test_ext().execute_with(|| {1951 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 1952 collection_numbers_limit: default_collection_numbers_limit(),1953 account_token_ownership_limit: 10,1954 collections_admins_limit: 5,1955 custom_data_limit: 10,1956 nft_sponsor_transfer_timeout: 15,1957 fungible_sponsor_transfer_timeout: 15,1958 refungible_sponsor_transfer_timeout: 15,1959 const_on_chain_schema_limit: 1024,1960 offchain_schema_limit: 1024,1961 variable_on_chain_schema_limit: 1024,1962 }));196319641965 let collection_id = create_test_collection(&CollectionMode::ReFungible, 1);19661967 let origin1 = Origin::signed(1);19681969 let data = default_re_fungible_data();1970 create_test_item(1, &data.into());19711972 let variable_data = b"test set_variable_meta_data method, bigger than limits.".to_vec();1973 assert_noop!(TemplateModule::set_variable_meta_data(origin1, collection_id, 1, variable_data), Error::<Test>::TokenVariableDataLimitExceeded);1974 });1975}runtime/src/chain_extension.rsdiffbeforeafterboth--- a/runtime/src/chain_extension.rs
+++ b/runtime/src/chain_extension.rs
@@ -60,7 +60,9 @@
}
let recipient = AccountId32::from(bytes_rec);
- match pallet_nft::Module::<Runtime>::transfer_internal(sender, recipient, input.collection_id, input.token_id, input.amount) {
+ let collection = pallet_nft::Module::<Runtime>::get_collection(input.collection_id)?;
+
+ match pallet_nft::Module::<Runtime>::transfer_internal(sender, recipient, &collection, input.token_id, input.amount) {
Ok(_) => Ok(RetVal::Converging(func_id)),
_ => Err(DispatchError::Other("Transfer error"))
}
runtime/src/nft_weights.rsdiffbeforeafterboth--- a/runtime/src/nft_weights.rs
+++ b/runtime/src/nft_weights.rs
@@ -133,6 +133,11 @@
.saturating_add(DbWeight::get().reads(0 as Weight))
.saturating_add(DbWeight::get().writes(2 as Weight))
}
+ fn set_variable_meta_data_sponsoring_rate_limit() -> Weight {
+ (3_500_000 as Weight)
+ .saturating_add(DbWeight::get().reads(1 as Weight))
+ .saturating_add(DbWeight::get().writes(2 as Weight))
+ }
fn toggle_contract_white_list() -> Weight {
(3_000_000 as Weight)
.saturating_add(DbWeight::get().reads(0 as Weight))
runtime_types.jsondiffbeforeafterboth--- a/runtime_types.json
+++ b/runtime_types.json
@@ -38,7 +38,7 @@
"Confirmed": "AccountId"
}
},
- "CollectionType": {
+ "Collection": {
"Owner": "AccountId",
"Mode": "CollectionMode",
"Access": "AccessMode",
@@ -99,7 +99,8 @@
},
"CollectionLimits": {
"AccountTokenOwnershipLimit": "u32",
- "SponsoredMintSize": "u32",
+ "SponsoredDataSize": "u32",
+ "SponsoredDataRateLimit": "Option<BlockNumber>",
"TokenLimit": "u32",
"SponsorTimeout": "u32",
"OwnerCanTransfer": "bool",
tests/package.jsondiffbeforeafterboth--- a/tests/package.json
+++ b/tests/package.json
@@ -46,7 +46,8 @@
"testEnableContractSponsoring": "mocha --timeout 9999999 -r ts-node/register ./**/enableContractSponsoring.test.ts",
"testSetContractSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setContractSponsoringRateLimit.test.ts",
"testSetOffchainSchema": "mocha --timeout 9999999 -r ts-node/register ./**/setOffchainSchema.test.ts",
- "testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts"
+ "testOverflow": "mocha --timeout 9999999 -r ts-node/register ./**/overflow.test.ts",
+ "testSetVariableMetadataSponsoringRateLimit": "mocha --timeout 9999999 -r ts-node/register ./**/setVariableMetadataSponsoringRateLimit.test.ts"
},
"author": "",
"license": "SEE LICENSE IN ../LICENSE",
tests/src/addCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/addCollectionAdmin.test.ts
+++ b/tests/src/addCollectionAdmin.test.ts
@@ -1,135 +1,135 @@
-//
-// This file is subject to the terms and conditions defined in
-// file 'LICENSE', which is part of this source code package.
-//
-
-import { ApiPromise } from '@polkadot/api';
-import BN from 'bn.js';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import privateKey from './substrate/privateKey';
-import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
-import {createCollectionExpectSuccess, destroyCollectionExpectSuccess} from './util/helpers';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
-describe('Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
- it('Add collection admin.', async () => {
- await usingApi(async (api) => {
- const collectionId = await createCollectionExpectSuccess();
- const alice = privateKey('//Alice');
- const bob = privateKey('//Bob');
-
- const collection: any = (await api.query.nft.collection(collectionId));
- expect(collection.Owner.toString()).to.be.eq(alice.address);
-
- const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, bob.address);
- await submitTransactionAsync(alice, changeAdminTx);
-
- const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
- expect(adminListAfterAddAdmin).to.be.contains(bob.address);
- });
- });
-
- it('Add admin using added collection admin.', async () => {
- await usingApi(async (api) => {
- const collectionId = await createCollectionExpectSuccess();
- const Alice = privateKey('//Alice');
- const Bob = privateKey('//Bob');
- const Charlie = privateKey('//CHARLIE');
-
- const collection: any = (await api.query.nft.collection(collectionId));
- expect(collection.Owner.toString()).to.be.eq(Alice.address);
-
- const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, Bob.address);
- await submitTransactionAsync(Alice, changeAdminTx);
-
- const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
- expect(adminListAfterAddAdmin).to.be.contains(Bob.address);
-
- const changeAdminTxCharlie = api.tx.nft.addCollectionAdmin(collectionId, Charlie.address);
- await submitTransactionAsync(Bob, changeAdminTxCharlie);
- const adminListAfterAddNewAdmin: any = (await api.query.nft.adminList(collectionId));
- expect(adminListAfterAddNewAdmin).to.be.contains(Bob.address);
- expect(adminListAfterAddNewAdmin).to.be.contains(Charlie.address);
- });
- });
-});
-
-describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
- it("Not owner can't add collection admin.", async () => {
- await usingApi(async (api) => {
- const collectionId = await createCollectionExpectSuccess();
- const alice = privateKey('//Alice');
- const nonOwner = privateKey('//Bob_stash');
-
- const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, alice.address);
- await expect(submitTransactionExpectFailAsync(nonOwner, changeAdminTx)).to.be.rejected;
-
- const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
- expect(adminListAfterAddAdmin).not.to.be.contains(alice.address);
-
- // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
- await createCollectionExpectSuccess();
- });
- });
- it("Can't add collection admin of not existing collection.", async () => {
- await usingApi(async (api) => {
- // tslint:disable-next-line: no-bitwise
- const collectionId = (1 << 32) - 1;
- const alice = privateKey('//Alice');
- const bob = privateKey('//Bob');
-
- const changeOwnerTx = api.tx.nft.addCollectionAdmin(collectionId, bob.address);
- await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;
-
- // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
- await createCollectionExpectSuccess();
- });
- });
-
- it("Can't add an admin to a destroyed collection.", async () => {
- await usingApi(async (api) => {
- const collectionId = await createCollectionExpectSuccess();
- const Alice = privateKey('//Alice');
- const Bob = privateKey('//Bob');
- await destroyCollectionExpectSuccess(collectionId);
- const changeOwnerTx = api.tx.nft.addCollectionAdmin(collectionId, Bob.address);
- await expect(submitTransactionExpectFailAsync(Alice, changeOwnerTx)).to.be.rejected;
-
- // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
- await createCollectionExpectSuccess();
- });
- });
-
- it('Add an admin to a collection that has reached the maximum number of admins limit', async () => {
- await usingApi(async (api: ApiPromise) => {
- const Alice = privateKey('//Alice');
- const accounts = [
- 'GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz',
- 'FoQJpPyadYccjavVdTWxpxU7rUEaYhfLCPwXgkfD6Zat9QP',
- 'JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5',
- 'Fr4NzY1udSFFLzb2R3qxVQkwz9cZraWkyfH4h3mVVk7BK7P',
- 'DfnTB4z7eUvYRqcGtTpFsLC69o6tvBSC1pEv8vWPZFtCkaK',
- 'HnMAUz7r2G8G3hB27SYNyit5aJmh2a5P4eMdDtACtMFDbam',
- 'DE14BzQ1bDXWPKeLoAqdLAm1GpyAWaWF1knF74cEZeomTBM',
- ];
- const collectionId = await createCollectionExpectSuccess();
-
- const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN };
- const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber();
- expect(chainAdminLimit).to.be.equal(5);
-
- for (let i = 0; i < chainAdminLimit; i++) {
- const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, accounts[i]);
- await submitTransactionAsync(Alice, changeAdminTx);
- const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
- expect(adminListAfterAddAdmin).to.be.contains(accounts[i]);
- }
-
- const tx = api.tx.nft.addCollectionAdmin(collectionId, accounts[chainAdminLimit]);
- await expect(submitTransactionExpectFailAsync(Alice, tx)).to.be.rejected;
- });
- });
-});
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { ApiPromise } from '@polkadot/api';
+import BN from 'bn.js';
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import privateKey from './substrate/privateKey';
+import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
+import {createCollectionExpectSuccess, destroyCollectionExpectSuccess} from './util/helpers';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+describe('Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
+ it('Add collection admin.', async () => {
+ await usingApi(async (api) => {
+ const collectionId = await createCollectionExpectSuccess();
+ const alice = privateKey('//Alice');
+ const bob = privateKey('//Bob');
+
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+ expect(collection.Owner.toString()).to.be.eq(alice.address);
+
+ const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, bob.address);
+ await submitTransactionAsync(alice, changeAdminTx);
+
+ const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
+ expect(adminListAfterAddAdmin).to.be.contains(bob.address);
+ });
+ });
+
+ it('Add admin using added collection admin.', async () => {
+ await usingApi(async (api) => {
+ const collectionId = await createCollectionExpectSuccess();
+ const Alice = privateKey('//Alice');
+ const Bob = privateKey('//Bob');
+ const Charlie = privateKey('//CHARLIE');
+
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+ expect(collection.Owner.toString()).to.be.eq(Alice.address);
+
+ const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, Bob.address);
+ await submitTransactionAsync(Alice, changeAdminTx);
+
+ const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
+ expect(adminListAfterAddAdmin).to.be.contains(Bob.address);
+
+ const changeAdminTxCharlie = api.tx.nft.addCollectionAdmin(collectionId, Charlie.address);
+ await submitTransactionAsync(Bob, changeAdminTxCharlie);
+ const adminListAfterAddNewAdmin: any = (await api.query.nft.adminList(collectionId));
+ expect(adminListAfterAddNewAdmin).to.be.contains(Bob.address);
+ expect(adminListAfterAddNewAdmin).to.be.contains(Charlie.address);
+ });
+ });
+});
+
+describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
+ it("Not owner can't add collection admin.", async () => {
+ await usingApi(async (api) => {
+ const collectionId = await createCollectionExpectSuccess();
+ const alice = privateKey('//Alice');
+ const nonOwner = privateKey('//Bob_stash');
+
+ const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, alice.address);
+ await expect(submitTransactionExpectFailAsync(nonOwner, changeAdminTx)).to.be.rejected;
+
+ const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
+ expect(adminListAfterAddAdmin).not.to.be.contains(alice.address);
+
+ // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
+ await createCollectionExpectSuccess();
+ });
+ });
+ it("Can't add collection admin of not existing collection.", async () => {
+ await usingApi(async (api) => {
+ // tslint:disable-next-line: no-bitwise
+ const collectionId = (1 << 32) - 1;
+ const alice = privateKey('//Alice');
+ const bob = privateKey('//Bob');
+
+ const changeOwnerTx = api.tx.nft.addCollectionAdmin(collectionId, bob.address);
+ await expect(submitTransactionExpectFailAsync(alice, changeOwnerTx)).to.be.rejected;
+
+ // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
+ await createCollectionExpectSuccess();
+ });
+ });
+
+ it("Can't add an admin to a destroyed collection.", async () => {
+ await usingApi(async (api) => {
+ const collectionId = await createCollectionExpectSuccess();
+ const Alice = privateKey('//Alice');
+ const Bob = privateKey('//Bob');
+ await destroyCollectionExpectSuccess(collectionId);
+ const changeOwnerTx = api.tx.nft.addCollectionAdmin(collectionId, Bob.address);
+ await expect(submitTransactionExpectFailAsync(Alice, changeOwnerTx)).to.be.rejected;
+
+ // Verifying that nothing bad happened (network is live, new collections can be created, etc.)
+ await createCollectionExpectSuccess();
+ });
+ });
+
+ it('Add an admin to a collection that has reached the maximum number of admins limit', async () => {
+ await usingApi(async (api: ApiPromise) => {
+ const Alice = privateKey('//Alice');
+ const accounts = [
+ 'GsvVmjr1CBHwQHw84pPHMDxgNY3iBLz6Qn7qS3CH8qPhrHz',
+ 'FoQJpPyadYccjavVdTWxpxU7rUEaYhfLCPwXgkfD6Zat9QP',
+ 'JKspFU6ohf1Grg3Phdzj2pSgWvsYWzSfKghhfzMbdhNBWs5',
+ 'Fr4NzY1udSFFLzb2R3qxVQkwz9cZraWkyfH4h3mVVk7BK7P',
+ 'DfnTB4z7eUvYRqcGtTpFsLC69o6tvBSC1pEv8vWPZFtCkaK',
+ 'HnMAUz7r2G8G3hB27SYNyit5aJmh2a5P4eMdDtACtMFDbam',
+ 'DE14BzQ1bDXWPKeLoAqdLAm1GpyAWaWF1knF74cEZeomTBM',
+ ];
+ const collectionId = await createCollectionExpectSuccess();
+
+ const chainLimit = await api.query.nft.chainLimit() as unknown as { CollectionAdminsLimit: BN };
+ const chainAdminLimit = chainLimit.CollectionAdminsLimit.toNumber();
+ expect(chainAdminLimit).to.be.equal(5);
+
+ for (let i = 0; i < chainAdminLimit; i++) {
+ const changeAdminTx = api.tx.nft.addCollectionAdmin(collectionId, accounts[i]);
+ await submitTransactionAsync(Alice, changeAdminTx);
+ const adminListAfterAddAdmin: any = (await api.query.nft.adminList(collectionId));
+ expect(adminListAfterAddAdmin).to.be.contains(accounts[i]);
+ }
+
+ const tx = api.tx.nft.addCollectionAdmin(collectionId, accounts[chainAdminLimit]);
+ await expect(submitTransactionExpectFailAsync(Alice, tx)).to.be.rejected;
+ });
+ });
+});
tests/src/change-collection-owner.test.tsdiffbeforeafterboth--- a/tests/src/change-collection-owner.test.ts
+++ b/tests/src/change-collection-owner.test.ts
@@ -19,13 +19,13 @@
const alice = privateKey('//Alice');
const bob = privateKey('//Bob');
- const collection: any = (await api.query.nft.collection(collectionId));
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
expect(collection.Owner.toString()).to.be.eq(alice.address);
const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
await submitTransactionAsync(alice, changeOwnerTx);
- const collectionAfterOwnerChange: any = (await api.query.nft.collection(collectionId));
+ const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON();
expect(collectionAfterOwnerChange.Owner.toString()).to.be.eq(bob.address);
});
});
@@ -41,7 +41,7 @@
const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address);
await expect(submitTransactionExpectFailAsync(bob, changeOwnerTx)).to.be.rejected;
- const collectionAfterOwnerChange: any = (await api.query.nft.collection(collectionId));
+ const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON();
expect(collectionAfterOwnerChange.Owner.toString()).to.be.eq(alice.address);
// Verifying that nothing bad happened (network is live, new collections can be created, etc.)
tests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -19,7 +19,7 @@
const collectionId = await createCollectionExpectSuccess();
const Alice = privateKey('//Alice');
const Bob = privateKey('//Bob');
- const collection: any = (await api.query.nft.collection(collectionId));
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
expect(collection.Owner.toString()).to.be.eq(Alice.address);
// first - add collection admin Bob
const addAdminTx = api.tx.nft.addCollectionAdmin(collectionId, Bob.address);
tests/src/setCollectionLimits.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionLimits.test.ts
+++ b/tests/src/setCollectionLimits.test.ts
@@ -61,12 +61,12 @@
// tslint:disable-next-line:no-unused-expression
expect(result.success).to.be.true;
- expect(collectionInfo.Limits.AccountTokenOwnershipLimit.toNumber()).to.be.equal(accountTokenOwnershipLimit);
- expect(collectionInfo.Limits.SponsoredMintSize.toNumber()).to.be.equal(sponsoredDataSize);
- expect(collectionInfo.Limits.TokenLimit.toNumber()).to.be.equal(tokenLimit);
- expect(collectionInfo.Limits.SponsorTimeout.toNumber()).to.be.equal(sponsorTimeout);
- expect(collectionInfo.Limits.OwnerCanTransfer.valueOf()).to.be.true;
- expect(collectionInfo.Limits.OwnerCanDestroy.valueOf()).to.be.true;
+ expect(collectionInfo.Limits.AccountTokenOwnershipLimit).to.be.equal(accountTokenOwnershipLimit);
+ expect(collectionInfo.Limits.SponsoredDataSize).to.be.equal(sponsoredDataSize);
+ expect(collectionInfo.Limits.TokenLimit).to.be.equal(tokenLimit);
+ expect(collectionInfo.Limits.SponsorTimeout).to.be.equal(sponsorTimeout);
+ expect(collectionInfo.Limits.OwnerCanTransfer).to.be.true;
+ expect(collectionInfo.Limits.OwnerCanDestroy).to.be.true;
});
});
});
tests/src/setConstOnChainSchema.test.tsdiffbeforeafterboth--- a/tests/src/setConstOnChainSchema.test.ts
+++ b/tests/src/setConstOnChainSchema.test.ts
@@ -36,7 +36,7 @@
it('Run extrinsic with parameters of the collection id, set the scheme', async () => {
await usingApi(async (api) => {
const collectionId = await createCollectionExpectSuccess();
- const collection: any = (await api.query.nft.collection(collectionId));
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
expect(collection.Owner.toString()).to.be.eq(Alice.address);
const setShema = api.tx.nft.setConstOnChainSchema(collectionId, Shema);
await submitTransactionAsync(Alice, setShema);
@@ -48,7 +48,7 @@
const collectionId = await createCollectionExpectSuccess();
const setShema = api.tx.nft.setConstOnChainSchema(collectionId, Shema);
await submitTransactionAsync(Alice, setShema);
- const collection: any = (await api.query.nft.collection(collectionId));
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
expect(collection.ConstOnChainSchema.toString()).to.be.eq(Shema);
});
@@ -86,7 +86,7 @@
it('Execute method not on behalf of the collection owner', async () => {
await usingApi(async (api) => {
const collectionId = await createCollectionExpectSuccess();
- const collection: any = (await api.query.nft.collection(collectionId));
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
expect(collection.Owner.toString()).to.be.eq(Alice.address);
const setShema = api.tx.nft.setConstOnChainSchema(collectionId, Shema);
await expect(submitTransactionExpectFailAsync(Bob, setShema)).to.be.rejected;
tests/src/setOffchainSchema.test.tsdiffbeforeafterboth--- a/tests/src/setOffchainSchema.test.ts
+++ b/tests/src/setOffchainSchema.test.ts
@@ -36,7 +36,7 @@
await setOffchainSchemaExpectSuccess(alice, collectionId, DATA);
const collection = await queryCollectionExpectSuccess(collectionId);
- expect(Array.from(collection.OffchainSchema)).to.be.deep.equal(DATA);
+ expect(collection.OffchainSchema).to.be.equal('0x' + Buffer.from(DATA).toString('hex'));
});
});
tests/src/setVariableMetadataSponsoringRateLimit.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/setVariableMetadataSponsoringRateLimit.test.ts
@@ -0,0 +1,80 @@
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { IKeyringPair } from '@polkadot/types/types';
+import privateKey from './substrate/privateKey';
+import usingApi from './substrate/substrate-api';
+import {
+ confirmSponsorshipExpectSuccess,
+ createCollectionExpectSuccess,
+ createItemExpectSuccess,
+ findUnusedAddress,
+ setCollectionLimitsExpectSuccess,
+ setCollectionSponsorExpectSuccess,
+ setVariableMetaDataExpectFailure,
+ setVariableMetaDataExpectSuccess,
+} from './util/helpers';
+
+describe('Integration Test setVariableMetadataSponsoringRateLimit', () => {
+ let alice: IKeyringPair;
+ let userWithNoBalance: IKeyringPair;
+
+ before(async () => {
+ await usingApi(async (api) => {
+ alice = privateKey('//Alice');
+ userWithNoBalance = await findUnusedAddress(api);
+ });
+ });
+
+ it('sponsored setVariableMetaData can be called twice with pause for free', async () => {
+ const collectionId = await createCollectionExpectSuccess();
+ await setCollectionSponsorExpectSuccess(collectionId, alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId);
+ await setCollectionLimitsExpectSuccess(alice, collectionId, {
+ SponsoredDataRateLimit: 0,
+ });
+
+ const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', userWithNoBalance.address);
+ await setVariableMetaDataExpectSuccess(userWithNoBalance, collectionId, itemId, [1, 2, 3]);
+ await setVariableMetaDataExpectSuccess(userWithNoBalance, collectionId, itemId, [1, 2, 3]);
+ });
+
+ it('sponsored setVariableMetaData can\'t be called twice without pause for free', async () => {
+ const collectionId = await createCollectionExpectSuccess();
+ await setCollectionSponsorExpectSuccess(collectionId, alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId);
+ await setCollectionLimitsExpectSuccess(alice, collectionId, {
+ SponsoredDataRateLimit: 10,
+ });
+
+ const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', userWithNoBalance.address);
+ await setVariableMetaDataExpectSuccess(userWithNoBalance, collectionId, itemId, [1, 2, 3]);
+ await setVariableMetaDataExpectFailure(userWithNoBalance, collectionId, itemId, [1, 2, 3]);
+ });
+
+ it('sponsored setVariableMetaData can\'t be called for free with variable metadata above collection limits', async () => {
+ const collectionId = await createCollectionExpectSuccess();
+ await setCollectionSponsorExpectSuccess(collectionId, alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId);
+ await setCollectionLimitsExpectSuccess(alice, collectionId, {
+ SponsoredDataRateLimit: 0,
+ SponsoredDataSize: 1,
+ });
+ const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', userWithNoBalance.address);
+
+ await setVariableMetaDataExpectSuccess(userWithNoBalance, collectionId, itemId, [1]);
+ await setVariableMetaDataExpectFailure(userWithNoBalance, collectionId, itemId, [1, 2]);
+ });
+
+ it.only('Default value of rate limit does not sponsor setting variable metadata', async () => {
+ const collectionId = await createCollectionExpectSuccess();
+ await setCollectionSponsorExpectSuccess(collectionId, alice.address);
+ await confirmSponsorshipExpectSuccess(collectionId);
+
+ const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', userWithNoBalance.address);
+ await setVariableMetaDataExpectFailure(userWithNoBalance, collectionId, itemId, [1]);
+ });
+
+});
tests/src/setVariableOnChainSchema.test.tsdiffbeforeafterboth--- a/tests/src/setVariableOnChainSchema.test.ts
+++ b/tests/src/setVariableOnChainSchema.test.ts
@@ -1,96 +1,96 @@
-//
-// This file is subject to the terms and conditions defined in
-// file 'LICENSE', which is part of this source code package.
-//
-
-import { Keyring } from '@polkadot/api';
-import { IKeyringPair } from '@polkadot/types/types';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
-import {
- createCollectionExpectSuccess,
- destroyCollectionExpectSuccess,
-} from './util/helpers';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
-let Alice: IKeyringPair;
-let Bob: IKeyringPair;
-let Schema: any;
-let largeSchema: any;
-
-before(async () => {
- await usingApi(async (api) => {
- const keyring = new Keyring({ type: 'sr25519' });
- Alice = keyring.addFromUri('//Alice');
- Bob = keyring.addFromUri('//Bob');
- Schema = '0x31';
- largeSchema = new Array(4097).fill(0xff);
-
- });
-});
-describe('Integration Test ext. setVariableOnChainSchema()', () => {
-
- it('Run extrinsic with parameters of the collection id, set the scheme', async () => {
- await usingApi(async (api) => {
- const collectionId = await createCollectionExpectSuccess();
- const collection: any = (await api.query.nft.collection(collectionId));
- expect(collection.Owner.toString()).to.be.eq(Alice.address);
- const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
- await submitTransactionAsync(Alice, setSchema);
- });
- });
-
- it('Checking collection data using the setVariableOnChainSchema parameter', async () => {
- await usingApi(async (api) => {
- const collectionId = await createCollectionExpectSuccess();
- const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
- await submitTransactionAsync(Alice, setSchema);
- const collection: any = (await api.query.nft.collection(collectionId));
- expect(collection.VariableOnChainSchema.toString()).to.be.eq(Schema);
-
- });
- });
-});
-
-describe('Negative Integration Test ext. setVariableOnChainSchema()', () => {
-
- it('Set a non-existent collection', async () => {
- await usingApi(async (api) => {
- // tslint:disable-next-line: radix
- const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;
- const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
- await expect(submitTransactionExpectFailAsync(Alice, setSchema)).to.be.rejected;
- });
- });
-
- it('Set a previously deleted collection', async () => {
- await usingApi(async (api) => {
- const collectionId = await createCollectionExpectSuccess();
- await destroyCollectionExpectSuccess(collectionId);
- const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
- await expect(submitTransactionExpectFailAsync(Alice, setSchema)).to.be.rejected;
- });
- });
-
- it('Set invalid data in schema (size too large:> 1024b)', async () => {
- await usingApi(async (api) => {
- const collectionId = await createCollectionExpectSuccess();
- const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, largeSchema);
- await expect(submitTransactionExpectFailAsync(Alice, setSchema)).to.be.rejected;
- });
- });
-
- it('Execute method not on behalf of the collection owner', async () => {
- await usingApi(async (api) => {
- const collectionId = await createCollectionExpectSuccess();
- const collection: any = (await api.query.nft.collection(collectionId));
- expect(collection.Owner.toString()).to.be.eq(Alice.address);
- const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
- await expect(submitTransactionExpectFailAsync(Bob, setSchema)).to.be.rejected;
- });
- });
-
-});
+//
+// This file is subject to the terms and conditions defined in
+// file 'LICENSE', which is part of this source code package.
+//
+
+import { Keyring } from '@polkadot/api';
+import { IKeyringPair } from '@polkadot/types/types';
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
+import {
+ createCollectionExpectSuccess,
+ destroyCollectionExpectSuccess,
+} from './util/helpers';
+
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+let Alice: IKeyringPair;
+let Bob: IKeyringPair;
+let Schema: any;
+let largeSchema: any;
+
+before(async () => {
+ await usingApi(async (api) => {
+ const keyring = new Keyring({ type: 'sr25519' });
+ Alice = keyring.addFromUri('//Alice');
+ Bob = keyring.addFromUri('//Bob');
+ Schema = '0x31';
+ largeSchema = new Array(4097).fill(0xff);
+
+ });
+});
+describe('Integration Test ext. setVariableOnChainSchema()', () => {
+
+ it('Run extrinsic with parameters of the collection id, set the scheme', async () => {
+ await usingApi(async (api) => {
+ const collectionId = await createCollectionExpectSuccess();
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+ expect(collection.Owner.toString()).to.be.eq(Alice.address);
+ const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+ await submitTransactionAsync(Alice, setSchema);
+ });
+ });
+
+ it('Checking collection data using the setVariableOnChainSchema parameter', async () => {
+ await usingApi(async (api) => {
+ const collectionId = await createCollectionExpectSuccess();
+ const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+ await submitTransactionAsync(Alice, setSchema);
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+ expect(collection.VariableOnChainSchema.toString()).to.be.eq(Schema);
+
+ });
+ });
+});
+
+describe('Negative Integration Test ext. setVariableOnChainSchema()', () => {
+
+ it('Set a non-existent collection', async () => {
+ await usingApi(async (api) => {
+ // tslint:disable-next-line: radix
+ const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;
+ const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+ await expect(submitTransactionExpectFailAsync(Alice, setSchema)).to.be.rejected;
+ });
+ });
+
+ it('Set a previously deleted collection', async () => {
+ await usingApi(async (api) => {
+ const collectionId = await createCollectionExpectSuccess();
+ await destroyCollectionExpectSuccess(collectionId);
+ const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+ await expect(submitTransactionExpectFailAsync(Alice, setSchema)).to.be.rejected;
+ });
+ });
+
+ it('Set invalid data in schema (size too large:> 1024b)', async () => {
+ await usingApi(async (api) => {
+ const collectionId = await createCollectionExpectSuccess();
+ const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, largeSchema);
+ await expect(submitTransactionExpectFailAsync(Alice, setSchema)).to.be.rejected;
+ });
+ });
+
+ it('Execute method not on behalf of the collection owner', async () => {
+ await usingApi(async (api) => {
+ const collectionId = await createCollectionExpectSuccess();
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
+ expect(collection.Owner.toString()).to.be.eq(Alice.address);
+ const setSchema = api.tx.nft.setVariableOnChainSchema(collectionId, Schema);
+ await expect(submitTransactionExpectFailAsync(Bob, setSchema)).to.be.rejected;
+ });
+ });
+
+});
tests/src/types.tsdiffbeforeafterboth--- a/tests/src/types.ts
+++ b/tests/src/types.ts
@@ -13,10 +13,11 @@
Description: [BN, BN]; // utf16
isReFungible: boolean;
Limits: {
- AccountTokenOwnershipLimit: BN;
- SponsoredMintSize: BN;
- TokenLimit: BN;
- SponsorTimeout: BN;
+ AccountTokenOwnershipLimit: number;
+ SponsoredDataSize: number;
+ SponsoredDataRateLimit?: number,
+ TokenLimit: number;
+ SponsorTimeout: number;
OwnerCanTransfer: boolean;
OwnerCanDestroy: boolean;
};
tests/src/util/contracthelpers.tsdiffbeforeafterboth--- a/tests/src/util/contracthelpers.ts
+++ b/tests/src/util/contracthelpers.ts
@@ -22,9 +22,9 @@
function deployContract(alice: IKeyringPair, code: CodePromise, constructor: string = 'default', ...args: any[]): Promise<Contract> {
return new Promise<Contract>(async (resolve, reject) => {
- const unsub = await code
+ const unsub = await (code as any)
.tx[constructor]({value: endowment, gasLimit}, ...args)
- .signAndSend(alice, (result) => {
+ .signAndSend(alice, (result: any) => {
if (result.status.isInBlock || result.status.isFinalized) {
// here we have an additional field in the result, containing the blueprint
resolve((result as any).contract);
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -212,7 +212,7 @@
const BcollectionCount = parseInt((await api.query.nft.createdCollectionCount()).toString(), 10);
// Get the collection
- const collection: any = (await api.query.nft.collection(result.collectionId)).toJSON();
+ const collection: any = (await api.query.nft.collectionById(result.collectionId)).toJSON();
// What to expect
// tslint:disable-next-line:no-unused-expression
@@ -324,18 +324,17 @@
const result = getDestroyResult(events);
// Get the collection
- const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
// What to expect
expect(result).to.be.true;
- expect(collection).to.be.not.null;
- expect(collection.Owner).to.be.equal(nullPublicKey);
+ expect(collection).to.be.null;
});
}
export async function queryCollectionLimits(collectionId: number) {
return await usingApi(async (api) => {
- return ((await api.query.nft.collection(collectionId)).toJSON() as any).Limits;
+ return ((await api.query.nft.collectionById(collectionId)).toJSON() as any).Limits;
});
}
@@ -373,7 +372,7 @@
const result = getGenericResult(events);
// Get the collection
- const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
// What to expect
expect(result.success).to.be.true;
@@ -393,7 +392,7 @@
const result = getGenericResult(events);
// Get the collection
- const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
// What to expect
expect(result.success).to.be.true;
@@ -431,7 +430,7 @@
const result = getGenericResult(events);
// Get the collection
- const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
// What to expect
expect(result.success).to.be.true;
@@ -839,7 +838,7 @@
const result = getGenericResult(events);
// Get the collection
- const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
// What to expect
// tslint:disable-next-line:no-unused-expression
@@ -865,7 +864,7 @@
const result = getGenericResult(events);
// Get the collection
- const collection: any = (await api.query.nft.collection(collectionId)).toJSON();
+ const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON();
// What to expect
// tslint:disable-next-line:no-unused-expression
@@ -947,7 +946,7 @@
export const getDetailedCollectionInfo = async (api: ApiPromise, collectionId: number)
: Promise<ICollectionInterface | null> => {
- return await api.query.nft.collection(collectionId) as unknown as ICollectionInterface;
+ return (await api.query.nft.collectionById(collectionId)).toJSON() as unknown as ICollectionInterface;
};
export const getCreatedCollectionCount = async (api: ApiPromise): Promise<number> => {
@@ -957,6 +956,6 @@
export async function queryCollectionExpectSuccess(collectionId: number): Promise<ICollectionInterface> {
return await usingApi(async (api) => {
- return (await api.query.nft.collection(collectionId)) as unknown as ICollectionInterface;
+ return (await api.query.nft.collectionById(collectionId)).toJSON() as unknown as ICollectionInterface;
});
}