12345import { ApiPromise } from '@polkadot/api';6import { IKeyringPair } from '@polkadot/types/types';7import BN from 'bn.js';8import chai from 'chai';9import chaiAsPromised from 'chai-as-promised';10import privateKey from './substrate/privateKey';11import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';12import {13 createCollectionExpectSuccess,14 destroyCollectionExpectSuccess,15 getGenericResult,16 IFungibleTokenDataType,17 IReFungibleTokenDataType,18 normalizeAccountId,19 setCollectionLimitsExpectSuccess,20 addCollectionAdminExpectSuccess,21} from './util/helpers';2223chai.use(chaiAsPromised);24const expect = chai.expect;2526interface ITokenDataType {27 Owner: number[];28 ConstData: number[];29 VariableData: number[];30}3132describe('Integration Test createMultipleItems(collection_id, owner, items_data):', () => {33 it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {34 await usingApi(async (api: ApiPromise) => {35 const collectionId = await createCollectionExpectSuccess();36 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;37 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);38 const Alice = privateKey('//Alice');39 const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }];40 const createMultipleItemsTx = api.tx.nft41 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);42 await submitTransactionAsync(Alice, createMultipleItemsTx);43 const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;44 expect(itemsListIndexAfter.toNumber()).to.be.equal(3);45 const token1Data = (await api.query.nft.nftItemList(collectionId, 1)).toJSON() as unknown as ITokenDataType;46 const token2Data = (await api.query.nft.nftItemList(collectionId, 2)).toJSON() as unknown as ITokenDataType;47 const token3Data = (await api.query.nft.nftItemList(collectionId, 3)).toJSON() as unknown as ITokenDataType;4849 expect(token1Data.Owner).to.be.deep.equal(normalizeAccountId(Alice.address));50 expect(token2Data.Owner).to.be.deep.equal(normalizeAccountId(Alice.address));51 expect(token3Data.Owner).to.be.deep.equal(normalizeAccountId(Alice.address));5253 expect(token1Data.ConstData.toString()).to.be.equal('0x31');54 expect(token2Data.ConstData.toString()).to.be.equal('0x32');55 expect(token3Data.ConstData.toString()).to.be.equal('0x33');5657 expect(token1Data.VariableData.toString()).to.be.equal('0x31');58 expect(token2Data.VariableData.toString()).to.be.equal('0x32');59 expect(token3Data.VariableData.toString()).to.be.equal('0x33');60 });61 });6263 it('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {64 await usingApi(async (api: ApiPromise) => {65 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});66 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;67 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);68 const Alice = privateKey('//Alice');69 const args = [70 {fungible: { value: 1 }},71 {fungible: { value: 2 }},72 {fungible: { value: 3 }},73 ];74 const createMultipleItemsTx = api.tx.nft75 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);76 await submitTransactionAsync(Alice, createMultipleItemsTx);77 const token1Data = (await api.query.nft.fungibleItemList(collectionId, Alice.address) as any).toJSON() as unknown as IFungibleTokenDataType;7879 expect(token1Data.Value).to.be.equal(6); 80 });81 });8283 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {84 await usingApi(async (api: ApiPromise) => {85 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});86 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;87 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);88 const Alice = privateKey('//Alice');89 const args = [90 {refungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}},91 {refungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},92 {refungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},93 ];94 const createMultipleItemsTx = api.tx.nft95 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);96 await submitTransactionAsync(Alice, createMultipleItemsTx);97 const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;98 expect(itemsListIndexAfter.toNumber()).to.be.equal(3);99 const token1Data = (await api.query.nft.reFungibleItemList(collectionId, 1) as any).toJSON() as unknown as IReFungibleTokenDataType;100 const token2Data = (await api.query.nft.reFungibleItemList(collectionId, 2) as any).toJSON() as unknown as IReFungibleTokenDataType;101 const token3Data = (await api.query.nft.reFungibleItemList(collectionId, 3) as any).toJSON() as unknown as IReFungibleTokenDataType;102103 expect(token1Data.Owner[0].Owner).to.be.deep.equal(normalizeAccountId(Alice.address));104 expect(token1Data.Owner[0].Fraction).to.be.equal(1);105106 expect(token2Data.Owner[0].Owner).to.be.deep.equal(normalizeAccountId(Alice.address));107 expect(token2Data.Owner[0].Fraction).to.be.equal(1);108109 expect(token3Data.Owner[0].Owner).to.be.deep.equal(normalizeAccountId(Alice.address));110 expect(token3Data.Owner[0].Fraction).to.be.equal(1);111112 expect(token1Data.ConstData.toString()).to.be.equal('0x31');113 expect(token2Data.ConstData.toString()).to.be.equal('0x32');114 expect(token3Data.ConstData.toString()).to.be.equal('0x33');115116 expect(token1Data.VariableData.toString()).to.be.equal('0x31');117 expect(token2Data.VariableData.toString()).to.be.equal('0x32');118 expect(token3Data.VariableData.toString()).to.be.equal('0x33');119 });120 });121122 it('Can mint amount of items equals to collection limits', async () => {123 await usingApi(async (api) => {124 const alice = privateKey('//Alice');125126 const collectionId = await createCollectionExpectSuccess();127 await setCollectionLimitsExpectSuccess(alice, collectionId, {128 TokenLimit: 2,129 });130 const args = [131 { nft: ['A', 'A'] },132 { nft: ['B', 'B'] },133 ];134 const createMultipleItemsTx = api.tx.nft.createMultipleItems(collectionId, normalizeAccountId(alice.address), args);135 const events = await submitTransactionAsync(alice, createMultipleItemsTx);136 const result = getGenericResult(events);137 expect(result.success).to.be.true;138 });139 });140});141142describe('Integration Test createMultipleItems(collection_id, owner, items_data) with collection admin permissions:', () => {143144 let Alice: IKeyringPair;145 let Bob: IKeyringPair;146147 before(async () => {148 await usingApi(async () => {149 Alice = privateKey('//Alice');150 Bob = privateKey('//Bob');151 });152 });153154 it('Create 0x31, 0x32, 0x33 items in active NFT collection and verify tokens data in chain', async () => {155 await usingApi(async (api: ApiPromise) => {156 const collectionId = await createCollectionExpectSuccess();157 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;158 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);159 await addCollectionAdminExpectSuccess(Alice, collectionId, Bob); 160 const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }];161 const createMultipleItemsTx = api.tx.nft162 .createMultipleItems(collectionId, normalizeAccountId(Bob.address), args);163 await submitTransactionAsync(Bob, createMultipleItemsTx);164 const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;165 expect(itemsListIndexAfter.toNumber()).to.be.equal(3);166 const token1Data = (await api.query.nft.nftItemList(collectionId, 1)).toJSON() as unknown as ITokenDataType;167 const token2Data = (await api.query.nft.nftItemList(collectionId, 2)).toJSON() as unknown as ITokenDataType;168 const token3Data = (await api.query.nft.nftItemList(collectionId, 3)).toJSON() as unknown as ITokenDataType;169170 expect(token1Data.Owner).to.be.deep.equal(normalizeAccountId(Bob.address));171 expect(token2Data.Owner).to.be.deep.equal(normalizeAccountId(Bob.address));172 expect(token3Data.Owner).to.be.deep.equal(normalizeAccountId(Bob.address));173174 expect(token1Data.ConstData.toString()).to.be.equal('0x31');175 expect(token2Data.ConstData.toString()).to.be.equal('0x32');176 expect(token3Data.ConstData.toString()).to.be.equal('0x33');177178 expect(token1Data.VariableData.toString()).to.be.equal('0x31');179 expect(token2Data.VariableData.toString()).to.be.equal('0x32');180 expect(token3Data.VariableData.toString()).to.be.equal('0x33');181 });182 });183184 it('Create 0x01, 0x02, 0x03 items in active Fungible collection and verify tokens data in chain', async () => {185 await usingApi(async (api: ApiPromise) => {186 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});187 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;188 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);189 await addCollectionAdminExpectSuccess(Alice, collectionId, Bob); 190 const args = [191 {fungible: { value: 1 }},192 {fungible: { value: 2 }},193 {fungible: { value: 3 }},194 ];195 const createMultipleItemsTx = api.tx.nft196 .createMultipleItems(collectionId, normalizeAccountId(Bob.address), args);197 await submitTransactionAsync(Bob, createMultipleItemsTx);198 const token1Data = (await api.query.nft.fungibleItemList(collectionId, Bob.address) as any).toJSON() as unknown as IFungibleTokenDataType;199200 expect(token1Data.Value).to.be.equal(6); 201 });202 });203204 it('Create 0x31, 0x32, 0x33 items in active ReFungible collection and verify tokens data in chain', async () => {205 await usingApi(async (api: ApiPromise) => {206 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});207 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;208 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);209 await addCollectionAdminExpectSuccess(Alice, collectionId, Bob); 210 const args = [211 {refungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}},212 {refungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},213 {refungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},214 ];215 const createMultipleItemsTx = api.tx.nft216 .createMultipleItems(collectionId, normalizeAccountId(Bob.address), args);217 await submitTransactionAsync(Bob, createMultipleItemsTx);218 const itemsListIndexAfter = await api.query.nft.itemListIndex(collectionId) as unknown as BN;219 expect(itemsListIndexAfter.toNumber()).to.be.equal(3);220 const token1Data = (await api.query.nft.reFungibleItemList(collectionId, 1) as any).toJSON() as unknown as IReFungibleTokenDataType;221 const token2Data = (await api.query.nft.reFungibleItemList(collectionId, 2) as any).toJSON() as unknown as IReFungibleTokenDataType;222 const token3Data = (await api.query.nft.reFungibleItemList(collectionId, 3) as any).toJSON() as unknown as IReFungibleTokenDataType;223224 expect(token1Data.Owner[0].Owner).to.be.deep.equal(normalizeAccountId(Bob.address));225 expect(token1Data.Owner[0].Fraction).to.be.equal(1);226227 expect(token2Data.Owner[0].Owner).to.be.deep.equal(normalizeAccountId(Bob.address));228 expect(token2Data.Owner[0].Fraction).to.be.equal(1);229230 expect(token3Data.Owner[0].Owner).to.be.deep.equal(normalizeAccountId(Bob.address));231 expect(token3Data.Owner[0].Fraction).to.be.equal(1);232233 expect(token1Data.ConstData.toString()).to.be.equal('0x31');234 expect(token2Data.ConstData.toString()).to.be.equal('0x32');235 expect(token3Data.ConstData.toString()).to.be.equal('0x33');236237 expect(token1Data.VariableData.toString()).to.be.equal('0x31');238 expect(token2Data.VariableData.toString()).to.be.equal('0x32');239 expect(token3Data.VariableData.toString()).to.be.equal('0x33');240 });241 });242});243244describe('Negative Integration Test createMultipleItems(collection_id, owner, items_data):', () => {245246 let Alice: IKeyringPair;247 let Bob: IKeyringPair;248249 before(async () => {250 await usingApi(async () => {251 Alice = privateKey('//Alice');252 Bob = privateKey('//Bob');253 });254 });255256 it('Regular user cannot create items in active NFT collection', async () => {257 await usingApi(async (api: ApiPromise) => {258 const collectionId = await createCollectionExpectSuccess();259 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;260 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);261 const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }];262 const createMultipleItemsTx = api.tx.nft263 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);264 await expect(submitTransactionAsync(Bob, createMultipleItemsTx)).to.be.rejected;265 });266 });267268 it('Regular user cannot create items in active Fungible collection', async () => {269 await usingApi(async (api: ApiPromise) => {270 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});271 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;272 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);273 const args = [274 {fungible: { value: 1 }},275 {fungible: { value: 2 }},276 {fungible: { value: 3 }},277 ];278 const createMultipleItemsTx = api.tx.nft279 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);280 await expect(submitTransactionAsync(Bob, createMultipleItemsTx)).to.be.rejected;281 });282 });283284 it('Regular user cannot create items in active ReFungible collection', async () => {285 await usingApi(async (api: ApiPromise) => {286 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});287 const itemsListIndexBefore = await api.query.nft.itemListIndex(collectionId) as unknown as BN;288 expect(itemsListIndexBefore.toNumber()).to.be.equal(0);289 const args = [290 {refungible: {const_data: [0x31], variable_data: [0x31], pieces: 1}},291 {refungible: {const_data: [0x32], variable_data: [0x32], pieces: 1}},292 {refungible: {const_data: [0x33], variable_data: [0x33], pieces: 1}},293 ];294 const createMultipleItemsTx = api.tx.nft295 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);296 await expect(submitTransactionAsync(Bob, createMultipleItemsTx)).to.be.rejected;297 });298 });299300 it('Create token with not existing type', async () => {301 await usingApi(async (api: ApiPromise) => {302 const collectionId = await createCollectionExpectSuccess();303 try {304 const args = [{ invalid: null }, { invalid: null }, { invalid: null }];305 const createMultipleItemsTx = await api.tx.nft306 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);307 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;308 } catch (e) {309 310 expect(e).to.be.exist;311 }312 });313 });314315 it('Create token in not existing collection', async () => {316 await usingApi(async (api: ApiPromise) => {317 const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;318 const createMultipleItemsTx = api.tx.nft319 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), ['NFT', 'NFT', 'NFT']);320 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;321 });322 });323324 it('Create NFT and Re-fungible tokens that has reached the maximum data limit', async () => {325 await usingApi(async (api: ApiPromise) => {326 327 const collectionId = await createCollectionExpectSuccess();328 const Alice = privateKey('//Alice');329 const args = [330 { nft: ['A'.repeat(2049), 'A'.repeat(2049)] },331 { nft: ['B'.repeat(2049), 'B'.repeat(2049)] },332 { nft: ['C'.repeat(2049), 'C'.repeat(2049)] },333 ];334 const createMultipleItemsTx = api.tx.nft335 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);336 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;337338 339 const collectionIdReFungible =340 await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});341 const argsReFungible = [342 { ReFungible: ['1'.repeat(2049), '1'.repeat(2049), 10] },343 { ReFungible: ['2'.repeat(2049), '2'.repeat(2049), 10] },344 { ReFungible: ['3'.repeat(2049), '3'.repeat(2049), 10] },345 ];346 const createMultipleItemsTxFungible = api.tx.nft347 .createMultipleItems(collectionIdReFungible, normalizeAccountId(Alice.address), argsReFungible);348 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTxFungible)).to.be.rejected;349 });350 });351352 it('Create tokens with different types', async () => {353 await usingApi(async (api: ApiPromise) => {354 const collectionId = await createCollectionExpectSuccess();355 const createMultipleItemsTx = api.tx.nft356 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), ['NFT', 'Fungible', 'ReFungible']);357 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;358 359 await destroyCollectionExpectSuccess(collectionId);360 });361 });362363 it('Create tokens with different data limits <> maximum data limit', async () => {364 await usingApi(async (api: ApiPromise) => {365 const collectionId = await createCollectionExpectSuccess();366 const args = [367 { nft: ['A', 'A'] },368 { nft: ['B', 'B'.repeat(2049)] },369 { nft: ['C'.repeat(2049), 'C'] },370 ];371 const createMultipleItemsTx = await api.tx.nft372 .createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);373 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;374 });375 });376377 it('Fails when minting tokens exceeds collectionLimits amount', async () => {378 await usingApi(async (api) => {379380 const collectionId = await createCollectionExpectSuccess();381 await setCollectionLimitsExpectSuccess(Alice, collectionId, {382 TokenLimit: 1,383 });384 const args = [385 { nft: ['A', 'A'] },386 { nft: ['B', 'B'] },387 ];388 const createMultipleItemsTx = api.tx.nft.createMultipleItems(collectionId, normalizeAccountId(Alice.address), args);389 await expect(submitTransactionExpectFailAsync(Alice, createMultipleItemsTx)).to.be.rejected;390 });391 });392});