difftreelog
CORE-410 Setup properties at creation items
in: master
4 files changed
pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -140,6 +140,7 @@
out.insert(to.clone(), data.pieces);
out.try_into().expect("limit > 0")
},
+ properties: data.properties,
}),
_ => fail!(<Error<T>>::NotRefungibleDataUsedToMintFungibleCollectionToken),
}
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -87,7 +87,7 @@
#![cfg_attr(not(feature = "std"), no_std)]
-use frame_support::{ensure, BoundedVec, transactional};
+use frame_support::{ensure, BoundedVec, transactional, storage::with_transaction};
use up_data_structs::{
AccessMode, CollectionId, CustomDataLimit, MAX_REFUNGIBLE_PIECES, TokenId,
CreateCollectionData, CreateRefungibleExData, mapping::TokenAddressMapping, budget::Budget,
@@ -96,7 +96,7 @@
use pallet_evm::account::CrossAccountId;
use pallet_common::{Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, CommonCollectionOperations as _};
use pallet_structure::Pallet as PalletStructure;
-use sp_runtime::{ArithmeticError, DispatchError, DispatchResult};
+use sp_runtime::{ArithmeticError, DispatchError, DispatchResult, TransactionOutcome};
use sp_std::{vec::Vec, vec, collections::btree_map::BTreeMap};
use core::ops::Deref;
use codec::{Encode, Decode, MaxEncodedLen};
@@ -804,32 +804,57 @@
// =========
+ with_transaction(|| {
+ for (i, data) in data.iter().enumerate() {
+ let token_id = first_token_id + i as u32 + 1;
+ <TotalSupply<T>>::insert((collection.id, token_id), totals[i]);
+
+ <TokenData<T>>::insert(
+ (collection.id, token_id),
+ ItemData {
+ const_data: data.const_data.clone(),
+ },
+ );
+
+ for (user, amount) in data.users.iter() {
+ if *amount == 0 {
+ continue;
+ }
+ <Balance<T>>::insert((collection.id, token_id, &user), amount);
+ <Owned<T>>::insert((collection.id, &user, TokenId(token_id)), true);
+ <PalletStructure<T>>::nest_if_sent_to_token_unchecked(
+ user,
+ collection.id,
+ TokenId(token_id),
+ );
+ }
+
+ if let Err(e) = Self::set_token_properties(
+ collection,
+ sender,
+ TokenId(token_id),
+ data.properties.clone().into_inner(),
+ true,
+ ) {
+ return TransactionOutcome::Rollback(Err(e));
+ }
+ }
+ TransactionOutcome::Commit(Ok(()))
+ })?;
+
<TokensMinted<T>>::insert(collection.id, tokens_minted);
+
for (account, balance) in balances {
<AccountBalance<T>>::insert((collection.id, account), balance);
}
+
for (i, token) in data.into_iter().enumerate() {
let token_id = first_token_id + i as u32 + 1;
- <TotalSupply<T>>::insert((collection.id, token_id), totals[i]);
-
- <TokenData<T>>::insert(
- (collection.id, token_id),
- ItemData {
- const_data: token.const_data,
- },
- );
for (user, amount) in token.users.into_iter() {
if amount == 0 {
continue;
- }
- <Balance<T>>::insert((collection.id, token_id, &user), amount);
- <Owned<T>>::insert((collection.id, &user, TokenId(token_id)), true);
- <PalletStructure<T>>::nest_if_sent_to_token_unchecked(
- &user,
- collection.id,
- TokenId(token_id),
- );
+ }
// TODO: ERC20 transfer event
<PalletCommon<T>>::deposit_event(CommonEvent::ItemCreated(
primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -534,7 +534,12 @@
#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
#[derivative(Debug(format_with = "bounded::vec_debug"))]
pub const_data: BoundedVec<u8, CustomDataLimit>,
+
pub pieces: u128,
+
+ #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
+ pub properties: CollectionPropertiesVec,
}
#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]
@@ -568,6 +573,8 @@
pub const_data: BoundedVec<u8, CustomDataLimit>,
#[derivative(Debug(format_with = "bounded::map_debug"))]
pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,
+ #[derivative(Debug(format_with = "bounded::vec_debug"))]
+ pub properties: CollectionPropertiesVec,
}
#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]
tests/src/createMultipleItems.test.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {ApiPromise} from '@polkadot/api';18import {IKeyringPair} from '@polkadot/types/types';19import chai from 'chai';20import chaiAsPromised from 'chai-as-promised';21import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync, executeTransaction} from './substrate/substrate-api';22import {23 createCollectionExpectSuccess,24 destroyCollectionExpectSuccess,25 getGenericResult,26 normalizeAccountId,27 setCollectionLimitsExpectSuccess,28 addCollectionAdminExpectSuccess,29 getBalance,30 getTokenOwner,31 getLastTokenId,32 getCreatedCollectionCount,33 createCollectionWithPropsExpectSuccess,34 createMultipleItemsWithPropsExpectSuccess,35 getTokenProperties,36} from './util/helpers';3738chai.use(chaiAsPromised);39const expect = chai.expect;4041describe('Integration Test createMultipleItems(collection_id, owner, items_data):', () => {42 it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {43 await usingApi(async (api, privateKeyWrapper) => {44 const collectionId = await createCollectionExpectSuccess();45 const itemsListIndexBefore = await getLastTokenId(api, collectionId);46 expect(itemsListIndexBefore).to.be.equal(0);4748 const alice = privateKeyWrapper('//Alice');49 await submitTransactionAsync(50 alice, 51 api.tx.unique.setTokenPropertyPermissions(collectionId, [{key: 'data', permission: {tokenOwner: true}}]),52 );53 54 const args = [55 {NFT: {properties: [{key: 'data', value: '1'}]}},56 {NFT: {properties: [{key: 'data', value: '2'}]}},57 {NFT: {properties: [{key: 'data', value: '3'}]}},58 ];59 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);60 await submitTransactionAsync(alice, createMultipleItemsTx);61 const itemsListIndexAfter = await getLastTokenId(api, collectionId);62 expect(itemsListIndexAfter).to.be.equal(3);6364 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));65 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));66 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));6768 expect((await getTokenProperties(api, collectionId, 1, ['data']))[0].value).to.be.equal('1');69 expect((await getTokenProperties(api, collectionId, 2, ['data']))[0].value).to.be.equal('2');70 expect((await getTokenProperties(api, collectionId, 3, ['data']))[0].value).to.be.equal('3');71 });72 });7374 it('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {75 await usingApi(async (api, privateKeyWrapper) => {76 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});77 const itemsListIndexBefore = await getLastTokenId(api, collectionId);78 expect(itemsListIndexBefore).to.be.equal(0);79 const alice = privateKeyWrapper('//Alice');80 const args = [81 {Fungible: {value: 1}},82 {Fungible: {value: 2}},83 {Fungible: {value: 3}},84 ];85 const createMultipleItemsTx = api.tx.unique86 .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);87 await submitTransactionAsync(alice, createMultipleItemsTx);88 const token1Data = await getBalance(api, collectionId, alice.address, 0);8990 expect(token1Data).to.be.equal(6n); // 1 + 2 + 391 });92 });9394 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {95 await usingApi(async (api, privateKeyWrapper) => {96 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});97 const itemsListIndexBefore = await getLastTokenId(api, collectionId);98 expect(itemsListIndexBefore).to.be.equal(0);99 const alice = privateKeyWrapper('//Alice');100 const args = [101 {ReFungible: {pieces: 1}},102 {ReFungible: {pieces: 2}},103 {ReFungible: {pieces: 3}},104 ];105 const createMultipleItemsTx = api.tx.unique106 .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);107 await submitTransactionAsync(alice, createMultipleItemsTx);108 const itemsListIndexAfter = await getLastTokenId(api, collectionId);109 expect(itemsListIndexAfter).to.be.equal(3);110111 expect(await getBalance(api, collectionId, alice.address, 1)).to.be.equal(1n);112 expect(await getBalance(api, collectionId, alice.address, 2)).to.be.equal(2n);113 expect(await getBalance(api, collectionId, alice.address, 3)).to.be.equal(3n);114 });115 });116117 it('Can mint amount of items equals to collection limits', async () => {118 await usingApi(async (api, privateKeyWrapper) => {119 const alice = privateKeyWrapper('//Alice');120121 const collectionId = await createCollectionExpectSuccess();122 await setCollectionLimitsExpectSuccess(alice, collectionId, {123 tokenLimit: 2,124 });125 const args = [126 {NFT: {}},127 {NFT: {}},128 ];129 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);130 const events = await submitTransactionAsync(alice, createMultipleItemsTx);131 const result = getGenericResult(events);132 expect(result.success).to.be.true;133 });134 });135136 it('Create 0x31, 0x32, 0x33 items in active NFT with property Admin', async () => {137 await usingApi(async (api, privateKeyWrapper) => {138 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]});139 const itemsListIndexBefore = await getLastTokenId(api, collectionId);140 expect(itemsListIndexBefore).to.be.equal(0);141 const alice = privateKeyWrapper('//Alice');142 const args = [143 {NFT: {properties: [{key: 'k', value: 'v1'}]}},144 {NFT: {properties: [{key: 'k', value: 'v2'}]}},145 {NFT: {properties: [{key: 'k', value: 'v3'}]}},146 ];147148 await createMultipleItemsWithPropsExpectSuccess(alice, collectionId, args);149 const itemsListIndexAfter = await getLastTokenId(api, collectionId);150 expect(itemsListIndexAfter).to.be.equal(3);151152 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));153 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));154 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));155156 expect((await getTokenProperties(api, collectionId, 1, ['k']))[0].value).to.be.equal('v1');157 expect((await getTokenProperties(api, collectionId, 2, ['k']))[0].value).to.be.equal('v2');158 expect((await getTokenProperties(api, collectionId, 3, ['k']))[0].value).to.be.equal('v3');159 });160 });161162 it('Create 0x31, 0x32, 0x33 items in active NFT with property AdminConst', async () => {163 await usingApi(async (api, privateKeyWrapper) => {164 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]});165 const itemsListIndexBefore = await getLastTokenId(api, collectionId);166 expect(itemsListIndexBefore).to.be.equal(0);167 const alice = privateKeyWrapper('//Alice');168 const bob = privateKeyWrapper('//Bob');169 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);170 const args = [171 {NFT: {properties: [{key: 'k', value: 'v1'}]}},172 {NFT: {properties: [{key: 'k', value: 'v2'}]}},173 {NFT: {properties: [{key: 'k', value: 'v3'}]}},174 ];175176 await createMultipleItemsWithPropsExpectSuccess(alice, collectionId, args);177 const itemsListIndexAfter = await getLastTokenId(api, collectionId);178 expect(itemsListIndexAfter).to.be.equal(3);179180 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));181 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));182 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));183184 expect((await getTokenProperties(api, collectionId, 1, ['k']))[0].value).to.be.equal('v1');185 expect((await getTokenProperties(api, collectionId, 2, ['k']))[0].value).to.be.equal('v2');186 expect((await getTokenProperties(api, collectionId, 3, ['k']))[0].value).to.be.equal('v3');187 });188 });189190 it('Create 0x31, 0x32, 0x33 items in active NFT with property itemOwnerOrAdmin', async () => {191 await usingApi(async (api, privateKeyWrapper) => {192 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]});193 const itemsListIndexBefore = await getLastTokenId(api, collectionId);194 expect(itemsListIndexBefore).to.be.equal(0);195 const alice = privateKeyWrapper('//Alice');196 const args = [197 {NFT: {properties: [{key: 'k', value: 'v1'}]}},198 {NFT: {properties: [{key: 'k', value: 'v2'}]}},199 {NFT: {properties: [{key: 'k', value: 'v3'}]}},200 ];201202 await createMultipleItemsWithPropsExpectSuccess(alice, collectionId, args);203 const itemsListIndexAfter = await getLastTokenId(api, collectionId);204 expect(itemsListIndexAfter).to.be.equal(3);205206 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));207 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));208 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));209210 expect((await getTokenProperties(api, collectionId, 1, ['k']))[0].value).to.be.equal('v1');211 expect((await getTokenProperties(api, collectionId, 2, ['k']))[0].value).to.be.equal('v2');212 expect((await getTokenProperties(api, collectionId, 3, ['k']))[0].value).to.be.equal('v3');213 });214 });215});216217describe('Integration Test createMultipleItems(collection_id, owner, items_data) with collection admin permissions:', () => {218 let alice: IKeyringPair;219 let bob: IKeyringPair;220221 before(async () => {222 await usingApi(async (api, privateKeyWrapper) => {223 alice = privateKeyWrapper('//Alice');224 bob = privateKeyWrapper('//Bob');225 });226 });227228 it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {229 await usingApi(async (api: ApiPromise) => {230 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'data', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]});231 const itemsListIndexBefore = await getLastTokenId(api, collectionId);232 expect(itemsListIndexBefore).to.be.equal(0);233 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);234 const args = [235 {NFT: {properties: [{key: 'data', value: 'v1'}]}},236 {NFT: {properties: [{key: 'data', value: 'v2'}]}},237 {NFT: {properties: [{key: 'data', value: 'v3'}]}},238 ];239 const createMultipleItemsTx = api.tx.unique240 .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);241 await submitTransactionAsync(bob, createMultipleItemsTx);242 const itemsListIndexAfter = await getLastTokenId(api, collectionId);243 expect(itemsListIndexAfter).to.be.equal(3);244245 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(bob.address));246 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(bob.address));247 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(bob.address));248249 expect((await getTokenProperties(api, collectionId, 1, ['data']))[0].value).to.be.equal('v1');250 expect((await getTokenProperties(api, collectionId, 2, ['data']))[0].value).to.be.equal('v2');251 expect((await getTokenProperties(api, collectionId, 3, ['data']))[0].value).to.be.equal('v3');252 });253 });254255 it('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {256 await usingApi(async (api: ApiPromise) => {257 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});258 const itemsListIndexBefore = await getLastTokenId(api, collectionId);259 expect(itemsListIndexBefore).to.be.equal(0);260 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);261 const args = [262 {Fungible: {value: 1}},263 {Fungible: {value: 2}},264 {Fungible: {value: 3}},265 ];266 const createMultipleItemsTx = api.tx.unique267 .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);268 await submitTransactionAsync(bob, createMultipleItemsTx);269 const token1Data = await getBalance(api, collectionId, bob.address, 0);270271 expect(token1Data).to.be.equal(6n); // 1 + 2 + 3272 });273 });274275 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {276 await usingApi(async (api: ApiPromise) => {277 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});278 const itemsListIndexBefore = await getLastTokenId(api, collectionId);279 expect(itemsListIndexBefore).to.be.equal(0);280 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);281 const args = [282 {ReFungible: {pieces: 1}},283 {ReFungible: {pieces: 2}},284 {ReFungible: {pieces: 3}},285 ];286 const createMultipleItemsTx = api.tx.unique287 .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);288 await submitTransactionAsync(bob, createMultipleItemsTx);289 const itemsListIndexAfter = await getLastTokenId(api, collectionId);290 expect(itemsListIndexAfter).to.be.equal(3);291292 expect(await getBalance(api, collectionId, bob.address, 1)).to.be.equal(1n);293 expect(await getBalance(api, collectionId, bob.address, 2)).to.be.equal(2n);294 expect(await getBalance(api, collectionId, bob.address, 3)).to.be.equal(3n);295 });296 });297});298299describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {300 let alice: IKeyringPair;301 let bob: IKeyringPair;302303 before(async () => {304 await usingApi(async (api, privateKeyWrapper) => {305 alice = privateKeyWrapper('//Alice');306 bob = privateKeyWrapper('//Bob');307 });308 });309310 it('Regular user cannot create items in active NFT collection', async () => {311 await usingApi(async (api: ApiPromise) => {312 const collectionId = await createCollectionExpectSuccess();313 const itemsListIndexBefore = await getLastTokenId(api, collectionId);314 expect(itemsListIndexBefore).to.be.equal(0);315 const args = [{NFT: {}},316 {NFT: {}},317 {NFT: {}}];318 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);319 await expect(executeTransaction(api, bob, createMultipleItemsTx)).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);320 });321 });322323 it('Regular user cannot create items in active Fungible collection', async () => {324 await usingApi(async (api: ApiPromise) => {325 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});326 const itemsListIndexBefore = await getLastTokenId(api, collectionId);327 expect(itemsListIndexBefore).to.be.equal(0);328 const args = [329 {Fungible: {value: 1}},330 {Fungible: {value: 2}},331 {Fungible: {value: 3}},332 ];333 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);334 await expect(executeTransaction(api, bob, createMultipleItemsTx)).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);335 });336 });337338 it('Regular user cannot create items in active ReFungible collection', async () => {339 await usingApi(async (api: ApiPromise) => {340 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});341 const itemsListIndexBefore = await getLastTokenId(api, collectionId);342 expect(itemsListIndexBefore).to.be.equal(0);343 const args = [344 {ReFungible: {pieces: 1}},345 {ReFungible: {pieces: 1}},346 {ReFungible: {pieces: 1}},347 ];348 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);349 await expect(executeTransaction(api, bob, createMultipleItemsTx)).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);350 });351 });352353 it('Create token in not existing collection', async () => {354 await usingApi(async (api: ApiPromise) => {355 const collectionId = await getCreatedCollectionCount(api) + 1;356 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'NFT', 'NFT']);357 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/common\.CollectionNotFound/);358 });359 });360361 it('Create NFT and Re-fungible tokens that has reached the maximum data limit', async () => {362 await usingApi(async (api, privateKeyWrapper) => {363 // NFT364 const collectionId = await createCollectionWithPropsExpectSuccess({365 propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],366 });367 const alice = privateKeyWrapper('//Alice');368 const args = [369 {NFT: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},370 {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},371 {NFT: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},372 ];373 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);374 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;375376 // ReFungible377 const collectionIdReFungible =378 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});379 const argsReFungible = [380 {ReFungible: ['1'.repeat(2049), 10]},381 {ReFungible: ['2'.repeat(2049), 10]},382 {ReFungible: ['3'.repeat(2049), 10]},383 ];384 const createMultipleItemsTxFungible = api.tx.unique385 .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);386 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;387 });388 });389390 it('Create tokens with different types', async () => {391 await usingApi(async (api: ApiPromise) => {392 const collectionId = await createCollectionExpectSuccess();393 const createMultipleItemsTx = api.tx.unique394 .createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'Fungible', 'ReFungible']);395 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);396 // garbage collection :-D // lol397 await destroyCollectionExpectSuccess(collectionId);398 });399 });400401 it('Create tokens with different data limits <> maximum data limit', async () => {402 await usingApi(async (api: ApiPromise) => {403 const collectionId = await createCollectionWithPropsExpectSuccess({404 propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],405 });406 const args = [407 {NFT: {properties: [{key: 'key', value: 'A'}]}},408 {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},409 ];410 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);411 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;412 });413 });414415 it('Fails when minting tokens exceeds collectionLimits amount', async () => {416 await usingApi(async (api) => {417 const collectionId = await createCollectionExpectSuccess();418 await setCollectionLimitsExpectSuccess(alice, collectionId, {419 tokenLimit: 1,420 });421 const args = [422 {NFT: {}},423 {NFT: {}},424 ];425 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);426 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/common\.CollectionTokenLimitExceeded/);427 });428 });429430 it('User doesnt have editing rights', async () => {431 await usingApi(async (api: ApiPromise) => {432 const collectionId = await createCollectionWithPropsExpectSuccess({433 propPerm: [{key: 'key1', permission: {mutable: true, collectionAdmin: false, tokenOwner: false}}],434 });435 const itemsListIndexBefore = await getLastTokenId(api, collectionId);436 expect(itemsListIndexBefore).to.be.equal(0);437 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);438 const args = [439 {NFT: {properties: [{key: 'key1', value: 'v2'}]}},440 {NFT: {}},441 {NFT: {}},442 ];443444 const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(bob.address), args);445 await expect(executeTransaction(api, bob, tx)).to.be.rejectedWith(/common\.NoPermission/);446 });447 });448449 it('Adding property without access rights', async () => {450 await usingApi(async (api: ApiPromise) => {451 const collectionId = await createCollectionWithPropsExpectSuccess({properties: [{key: 'k', value: 'v1'}]});452 const itemsListIndexBefore = await getLastTokenId(api, collectionId);453 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);454 expect(itemsListIndexBefore).to.be.equal(0);455 const args = [{NFT: {properties: [{key: 'k', value: 'v'}]}},456 {NFT: {}},457 {NFT: {}}];458459 const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(bob.address), args);460 await expect(executeTransaction(api, bob, tx)).to.be.rejectedWith(/common\.NoPermission/);461 });462 });463464 it('Adding more than 64 prps', async () => {465 await usingApi(async (api: ApiPromise) => {466 const propPerms = [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}];467 for (let i = 0; i < 65; i++) {468 propPerms.push({key: `key${i}`, permission: {mutable: true, collectionAdmin: true, tokenOwner: true}});469 }470471 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});472473 const tx1 = api.tx.unique.setTokenPropertyPermissions(collectionId, propPerms);474 await expect(executeTransaction(api, alice, tx1)).to.be.rejectedWith(/common\.PropertyLimitReached/);475476 const itemsListIndexBefore = await getLastTokenId(api, collectionId);477 expect(itemsListIndexBefore).to.be.equal(0);478 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);479480 const prps = [];481482 for (let i = 0; i < 65; i++) {483 prps.push({key: `key${i}`, value: `value${i}`});484 }485486 const args = [487 {NFT: {properties: prps}},488 {NFT: {properties: prps}},489 {NFT: {properties: prps}},490 ];491492 // there are no permissions, but will fail anyway because of too much weight for a block493 const tx2 = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);494 await expect(submitTransactionExpectFailAsync(alice, tx2)).to.be.rejected;495 });496 });497498 it('Trying to add bigger property than allowed', async () => {499 await usingApi(async (api: ApiPromise) => {500 const collectionId = await createCollectionWithPropsExpectSuccess({501 propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],502 });503 const itemsListIndexBefore = await getLastTokenId(api, collectionId);504 expect(itemsListIndexBefore).to.be.equal(0);505 const args = [{NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}},506 {NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}},507 {NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}}];508509 const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);510 await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/common\.NoPermission/);511 });512 });513});1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {ApiPromise} from '@polkadot/api';18import {IKeyringPair} from '@polkadot/types/types';19import chai from 'chai';20import chaiAsPromised from 'chai-as-promised';21import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync, executeTransaction} from './substrate/substrate-api';22import {23 createCollectionExpectSuccess,24 destroyCollectionExpectSuccess,25 getGenericResult,26 normalizeAccountId,27 setCollectionLimitsExpectSuccess,28 addCollectionAdminExpectSuccess,29 getBalance,30 getTokenOwner,31 getLastTokenId,32 getCreatedCollectionCount,33 createCollectionWithPropsExpectSuccess,34 createMultipleItemsWithPropsExpectSuccess,35 getTokenProperties,36} from './util/helpers';3738chai.use(chaiAsPromised);39const expect = chai.expect;4041describe('Integration Test createMultipleItems(collection_id, owner, items_data):', () => {42 it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {43 await usingApi(async (api, privateKeyWrapper) => {44 const collectionId = await createCollectionExpectSuccess();45 const itemsListIndexBefore = await getLastTokenId(api, collectionId);46 expect(itemsListIndexBefore).to.be.equal(0);4748 const alice = privateKeyWrapper('//Alice');49 await submitTransactionAsync(50 alice, 51 api.tx.unique.setTokenPropertyPermissions(collectionId, [{key: 'data', permission: {tokenOwner: true}}]),52 );53 54 const args = [55 {NFT: {properties: [{key: 'data', value: '1'}]}},56 {NFT: {properties: [{key: 'data', value: '2'}]}},57 {NFT: {properties: [{key: 'data', value: '3'}]}},58 ];59 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);60 await submitTransactionAsync(alice, createMultipleItemsTx);61 const itemsListIndexAfter = await getLastTokenId(api, collectionId);62 expect(itemsListIndexAfter).to.be.equal(3);6364 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));65 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));66 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));6768 expect((await getTokenProperties(api, collectionId, 1, ['data']))[0].value).to.be.equal('1');69 expect((await getTokenProperties(api, collectionId, 2, ['data']))[0].value).to.be.equal('2');70 expect((await getTokenProperties(api, collectionId, 3, ['data']))[0].value).to.be.equal('3');71 });72 });7374 it('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {75 await usingApi(async (api, privateKeyWrapper) => {76 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});77 const itemsListIndexBefore = await getLastTokenId(api, collectionId);78 expect(itemsListIndexBefore).to.be.equal(0);79 const alice = privateKeyWrapper('//Alice');80 const args = [81 {Fungible: {value: 1}},82 {Fungible: {value: 2}},83 {Fungible: {value: 3}},84 ];85 const createMultipleItemsTx = api.tx.unique86 .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);87 await submitTransactionAsync(alice, createMultipleItemsTx);88 const token1Data = await getBalance(api, collectionId, alice.address, 0);8990 expect(token1Data).to.be.equal(6n); // 1 + 2 + 391 });92 });9394 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {95 await usingApi(async (api, privateKeyWrapper) => {96 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});97 const itemsListIndexBefore = await getLastTokenId(api, collectionId);98 expect(itemsListIndexBefore).to.be.equal(0);99 const alice = privateKeyWrapper('//Alice');100 const args = [101 {ReFungible: {pieces: 1}},102 {ReFungible: {pieces: 2}},103 {ReFungible: {pieces: 3}},104 ];105 const createMultipleItemsTx = api.tx.unique106 .createMultipleItems(collectionId, normalizeAccountId(alice.address), args);107 await submitTransactionAsync(alice, createMultipleItemsTx);108 const itemsListIndexAfter = await getLastTokenId(api, collectionId);109 expect(itemsListIndexAfter).to.be.equal(3);110111 expect(await getBalance(api, collectionId, alice.address, 1)).to.be.equal(1n);112 expect(await getBalance(api, collectionId, alice.address, 2)).to.be.equal(2n);113 expect(await getBalance(api, collectionId, alice.address, 3)).to.be.equal(3n);114 });115 });116117 it('Can mint amount of items equals to collection limits', async () => {118 await usingApi(async (api, privateKeyWrapper) => {119 const alice = privateKeyWrapper('//Alice');120121 const collectionId = await createCollectionExpectSuccess();122 await setCollectionLimitsExpectSuccess(alice, collectionId, {123 tokenLimit: 2,124 });125 const args = [126 {NFT: {}},127 {NFT: {}},128 ];129 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);130 const events = await submitTransactionAsync(alice, createMultipleItemsTx);131 const result = getGenericResult(events);132 expect(result.success).to.be.true;133 });134 });135136 it('Create 0x31, 0x32, 0x33 items in active NFT with property Admin', async () => {137 await usingApi(async (api, privateKeyWrapper) => {138 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: false}}]});139 const itemsListIndexBefore = await getLastTokenId(api, collectionId);140 expect(itemsListIndexBefore).to.be.equal(0);141 const alice = privateKeyWrapper('//Alice');142 const args = [143 {NFT: {properties: [{key: 'k', value: 'v1'}]}},144 {NFT: {properties: [{key: 'k', value: 'v2'}]}},145 {NFT: {properties: [{key: 'k', value: 'v3'}]}},146 ];147148 await createMultipleItemsWithPropsExpectSuccess(alice, collectionId, args);149 const itemsListIndexAfter = await getLastTokenId(api, collectionId);150 expect(itemsListIndexAfter).to.be.equal(3);151152 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));153 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));154 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));155156 expect((await getTokenProperties(api, collectionId, 1, ['k']))[0].value).to.be.equal('v1');157 expect((await getTokenProperties(api, collectionId, 2, ['k']))[0].value).to.be.equal('v2');158 expect((await getTokenProperties(api, collectionId, 3, ['k']))[0].value).to.be.equal('v3');159 });160 });161162 it('Create 0x31, 0x32, 0x33 items in active NFT with property AdminConst', async () => {163 await usingApi(async (api, privateKeyWrapper) => {164 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'k', permission: {mutable: false, collectionAdmin: true, tokenOwner: false}}]});165 const itemsListIndexBefore = await getLastTokenId(api, collectionId);166 expect(itemsListIndexBefore).to.be.equal(0);167 const alice = privateKeyWrapper('//Alice');168 const bob = privateKeyWrapper('//Bob');169 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);170 const args = [171 {NFT: {properties: [{key: 'k', value: 'v1'}]}},172 {NFT: {properties: [{key: 'k', value: 'v2'}]}},173 {NFT: {properties: [{key: 'k', value: 'v3'}]}},174 ];175176 await createMultipleItemsWithPropsExpectSuccess(alice, collectionId, args);177 const itemsListIndexAfter = await getLastTokenId(api, collectionId);178 expect(itemsListIndexAfter).to.be.equal(3);179180 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));181 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));182 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));183184 expect((await getTokenProperties(api, collectionId, 1, ['k']))[0].value).to.be.equal('v1');185 expect((await getTokenProperties(api, collectionId, 2, ['k']))[0].value).to.be.equal('v2');186 expect((await getTokenProperties(api, collectionId, 3, ['k']))[0].value).to.be.equal('v3');187 });188 });189190 it('Create 0x31, 0x32, 0x33 items in active NFT with property itemOwnerOrAdmin', async () => {191 await usingApi(async (api, privateKeyWrapper) => {192 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]});193 const itemsListIndexBefore = await getLastTokenId(api, collectionId);194 expect(itemsListIndexBefore).to.be.equal(0);195 const alice = privateKeyWrapper('//Alice');196 const args = [197 {NFT: {properties: [{key: 'k', value: 'v1'}]}},198 {NFT: {properties: [{key: 'k', value: 'v2'}]}},199 {NFT: {properties: [{key: 'k', value: 'v3'}]}},200 ];201202 await createMultipleItemsWithPropsExpectSuccess(alice, collectionId, args);203 const itemsListIndexAfter = await getLastTokenId(api, collectionId);204 expect(itemsListIndexAfter).to.be.equal(3);205206 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(alice.address));207 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(alice.address));208 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(alice.address));209210 expect((await getTokenProperties(api, collectionId, 1, ['k']))[0].value).to.be.equal('v1');211 expect((await getTokenProperties(api, collectionId, 2, ['k']))[0].value).to.be.equal('v2');212 expect((await getTokenProperties(api, collectionId, 3, ['k']))[0].value).to.be.equal('v3');213 });214 });215});216217describe('Integration Test createMultipleItems(collection_id, owner, items_data) with collection admin permissions:', () => {218 let alice: IKeyringPair;219 let bob: IKeyringPair;220221 before(async () => {222 await usingApi(async (api, privateKeyWrapper) => {223 alice = privateKeyWrapper('//Alice');224 bob = privateKeyWrapper('//Bob');225 });226 });227228 it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {229 await usingApi(async (api: ApiPromise) => {230 const collectionId = await createCollectionWithPropsExpectSuccess({propPerm: [{key: 'data', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}]});231 const itemsListIndexBefore = await getLastTokenId(api, collectionId);232 expect(itemsListIndexBefore).to.be.equal(0);233 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);234 const args = [235 {NFT: {properties: [{key: 'data', value: 'v1'}]}},236 {NFT: {properties: [{key: 'data', value: 'v2'}]}},237 {NFT: {properties: [{key: 'data', value: 'v3'}]}},238 ];239 const createMultipleItemsTx = api.tx.unique240 .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);241 await submitTransactionAsync(bob, createMultipleItemsTx);242 const itemsListIndexAfter = await getLastTokenId(api, collectionId);243 expect(itemsListIndexAfter).to.be.equal(3);244245 expect(await getTokenOwner(api, collectionId, 1)).to.be.deep.equal(normalizeAccountId(bob.address));246 expect(await getTokenOwner(api, collectionId, 2)).to.be.deep.equal(normalizeAccountId(bob.address));247 expect(await getTokenOwner(api, collectionId, 3)).to.be.deep.equal(normalizeAccountId(bob.address));248249 expect((await getTokenProperties(api, collectionId, 1, ['data']))[0].value).to.be.equal('v1');250 expect((await getTokenProperties(api, collectionId, 2, ['data']))[0].value).to.be.equal('v2');251 expect((await getTokenProperties(api, collectionId, 3, ['data']))[0].value).to.be.equal('v3');252 });253 });254255 it('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {256 await usingApi(async (api: ApiPromise) => {257 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});258 const itemsListIndexBefore = await getLastTokenId(api, collectionId);259 expect(itemsListIndexBefore).to.be.equal(0);260 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);261 const args = [262 {Fungible: {value: 1}},263 {Fungible: {value: 2}},264 {Fungible: {value: 3}},265 ];266 const createMultipleItemsTx = api.tx.unique267 .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);268 await submitTransactionAsync(bob, createMultipleItemsTx);269 const token1Data = await getBalance(api, collectionId, bob.address, 0);270271 expect(token1Data).to.be.equal(6n); // 1 + 2 + 3272 });273 });274275 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {276 await usingApi(async (api: ApiPromise) => {277 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});278 const itemsListIndexBefore = await getLastTokenId(api, collectionId);279 expect(itemsListIndexBefore).to.be.equal(0);280 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);281 const args = [282 {ReFungible: {pieces: 1}},283 {ReFungible: {pieces: 2}},284 {ReFungible: {pieces: 3}},285 ];286 const createMultipleItemsTx = api.tx.unique287 .createMultipleItems(collectionId, normalizeAccountId(bob.address), args);288 await submitTransactionAsync(bob, createMultipleItemsTx);289 const itemsListIndexAfter = await getLastTokenId(api, collectionId);290 expect(itemsListIndexAfter).to.be.equal(3);291292 expect(await getBalance(api, collectionId, bob.address, 1)).to.be.equal(1n);293 expect(await getBalance(api, collectionId, bob.address, 2)).to.be.equal(2n);294 expect(await getBalance(api, collectionId, bob.address, 3)).to.be.equal(3n);295 });296 });297});298299describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {300 let alice: IKeyringPair;301 let bob: IKeyringPair;302303 before(async () => {304 await usingApi(async (api, privateKeyWrapper) => {305 alice = privateKeyWrapper('//Alice');306 bob = privateKeyWrapper('//Bob');307 });308 });309310 it('Regular user cannot create items in active NFT collection', async () => {311 await usingApi(async (api: ApiPromise) => {312 const collectionId = await createCollectionExpectSuccess();313 const itemsListIndexBefore = await getLastTokenId(api, collectionId);314 expect(itemsListIndexBefore).to.be.equal(0);315 const args = [{NFT: {}},316 {NFT: {}},317 {NFT: {}}];318 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);319 await expect(executeTransaction(api, bob, createMultipleItemsTx)).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);320 });321 });322323 it('Regular user cannot create items in active Fungible collection', async () => {324 await usingApi(async (api: ApiPromise) => {325 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});326 const itemsListIndexBefore = await getLastTokenId(api, collectionId);327 expect(itemsListIndexBefore).to.be.equal(0);328 const args = [329 {Fungible: {value: 1}},330 {Fungible: {value: 2}},331 {Fungible: {value: 3}},332 ];333 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);334 await expect(executeTransaction(api, bob, createMultipleItemsTx)).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);335 });336 });337338 it('Regular user cannot create items in active ReFungible collection', async () => {339 await usingApi(async (api: ApiPromise) => {340 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});341 const itemsListIndexBefore = await getLastTokenId(api, collectionId);342 expect(itemsListIndexBefore).to.be.equal(0);343 const args = [344 {ReFungible: {pieces: 1}},345 {ReFungible: {pieces: 1}},346 {ReFungible: {pieces: 1}},347 ];348 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);349 await expect(executeTransaction(api, bob, createMultipleItemsTx)).to.be.rejectedWith(/common\.PublicMintingNotAllowed/);350 });351 });352353 it('Create token in not existing collection', async () => {354 await usingApi(async (api: ApiPromise) => {355 const collectionId = await getCreatedCollectionCount(api) + 1;356 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'NFT', 'NFT']);357 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/common\.CollectionNotFound/);358 });359 });360361 it('Create NFT and Re-fungible tokens that has reached the maximum data limit', async () => {362 await usingApi(async (api, privateKeyWrapper) => {363 // NFT364 const collectionId = await createCollectionWithPropsExpectSuccess({365 propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],366 });367 const alice = privateKeyWrapper('//Alice');368 const args = [369 {NFT: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},370 {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},371 {NFT: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},372 ];373 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);374 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;375376 // ReFungible377 const collectionIdReFungible =378 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});379 {380 const argsReFungible = [381 {ReFungible: ['1'.repeat(2049), 10, []]},382 {ReFungible: ['2'.repeat(2049), 10, []]},383 {ReFungible: ['3'.repeat(2049), 10, []]},384 ];385 const createMultipleItemsTxFungible = api.tx.unique386 .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);387 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;388 }389 {390 const argsReFungible = [391 {ReFungible: {properties: [{key: 'key', value: 'A'.repeat(32769)}]}},392 {ReFungible: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},393 {ReFungible: {properties: [{key: 'key', value: 'C'.repeat(32769)}]}},394 ];395 const createMultipleItemsTxFungible = api.tx.unique396 .createMultipleItems(collectionIdReFungible, normalizeAccountId(alice.address), argsReFungible);397 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTxFungible)).to.be.rejected;398 }399 });400 });401402 it('Create tokens with different types', async () => {403 await usingApi(async (api: ApiPromise) => {404 const collectionId = await createCollectionExpectSuccess();405 const createMultipleItemsTx = api.tx.unique406 .createMultipleItems(collectionId, normalizeAccountId(alice.address), ['NFT', 'Fungible', 'ReFungible']);407 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/nonfungible\.NotNonfungibleDataUsedToMintFungibleCollectionToken/);408 // garbage collection :-D // lol409 await destroyCollectionExpectSuccess(collectionId);410 });411 });412413 it('Create tokens with different data limits <> maximum data limit', async () => {414 await usingApi(async (api: ApiPromise) => {415 const collectionId = await createCollectionWithPropsExpectSuccess({416 propPerm: [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],417 });418 const args = [419 {NFT: {properties: [{key: 'key', value: 'A'}]}},420 {NFT: {properties: [{key: 'key', value: 'B'.repeat(32769)}]}},421 ];422 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);423 await expect(submitTransactionExpectFailAsync(alice, createMultipleItemsTx)).to.be.rejected;424 });425 });426427 it('Fails when minting tokens exceeds collectionLimits amount', async () => {428 await usingApi(async (api) => {429 const collectionId = await createCollectionExpectSuccess();430 await setCollectionLimitsExpectSuccess(alice, collectionId, {431 tokenLimit: 1,432 });433 const args = [434 {NFT: {}},435 {NFT: {}},436 ];437 const createMultipleItemsTx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);438 await expect(executeTransaction(api, alice, createMultipleItemsTx)).to.be.rejectedWith(/common\.CollectionTokenLimitExceeded/);439 });440 });441442 it('User doesnt have editing rights', async () => {443 await usingApi(async (api: ApiPromise) => {444 const collectionId = await createCollectionWithPropsExpectSuccess({445 propPerm: [{key: 'key1', permission: {mutable: true, collectionAdmin: false, tokenOwner: false}}],446 });447 const itemsListIndexBefore = await getLastTokenId(api, collectionId);448 expect(itemsListIndexBefore).to.be.equal(0);449 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);450 const args = [451 {NFT: {properties: [{key: 'key1', value: 'v2'}]}},452 {NFT: {}},453 {NFT: {}},454 ];455456 const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(bob.address), args);457 await expect(executeTransaction(api, bob, tx)).to.be.rejectedWith(/common\.NoPermission/);458 });459 });460461 it('Adding property without access rights', async () => {462 await usingApi(async (api: ApiPromise) => {463 const collectionId = await createCollectionWithPropsExpectSuccess({properties: [{key: 'k', value: 'v1'}]});464 const itemsListIndexBefore = await getLastTokenId(api, collectionId);465 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);466 expect(itemsListIndexBefore).to.be.equal(0);467 const args = [{NFT: {properties: [{key: 'k', value: 'v'}]}},468 {NFT: {}},469 {NFT: {}}];470471 const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(bob.address), args);472 await expect(executeTransaction(api, bob, tx)).to.be.rejectedWith(/common\.NoPermission/);473 });474 });475476 it('Adding more than 64 prps', async () => {477 await usingApi(async (api: ApiPromise) => {478 const propPerms = [{key: 'key', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}];479 for (let i = 0; i < 65; i++) {480 propPerms.push({key: `key${i}`, permission: {mutable: true, collectionAdmin: true, tokenOwner: true}});481 }482483 const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});484485 const tx1 = api.tx.unique.setTokenPropertyPermissions(collectionId, propPerms);486 await expect(executeTransaction(api, alice, tx1)).to.be.rejectedWith(/common\.PropertyLimitReached/);487488 const itemsListIndexBefore = await getLastTokenId(api, collectionId);489 expect(itemsListIndexBefore).to.be.equal(0);490 await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);491492 const prps = [];493494 for (let i = 0; i < 65; i++) {495 prps.push({key: `key${i}`, value: `value${i}`});496 }497498 const args = [499 {NFT: {properties: prps}},500 {NFT: {properties: prps}},501 {NFT: {properties: prps}},502 ];503504 // there are no permissions, but will fail anyway because of too much weight for a block505 const tx2 = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);506 await expect(submitTransactionExpectFailAsync(alice, tx2)).to.be.rejected;507 });508 });509510 it('Trying to add bigger property than allowed', async () => {511 await usingApi(async (api: ApiPromise) => {512 const collectionId = await createCollectionWithPropsExpectSuccess({513 propPerm: [{key: 'k', permission: {mutable: true, collectionAdmin: true, tokenOwner: true}}],514 });515 const itemsListIndexBefore = await getLastTokenId(api, collectionId);516 expect(itemsListIndexBefore).to.be.equal(0);517 const args = [{NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}},518 {NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}},519 {NFT: {properties: [{key: 'k', value: 'vvvvvv'.repeat(5000)}, {key: 'k2', value: 'vvv'.repeat(5000)}]}}];520521 const tx = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);522 await expect(executeTransaction(api, alice, tx)).to.be.rejectedWith(/common\.NoPermission/);523 });524 });525});