git.delta.rocks / unique-network / refs/commits / 017fcbf7aa70

difftreelog

source

tests/src/eth/createNFTCollection.test.ts13.8 KiBsourcehistory
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.8//9// 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 {evmToAddress} from '@polkadot/util-crypto';18import {IKeyringPair} from '@polkadot/types/types';19import {expect, itEth, usingEthPlaygrounds} from './util';202122describe('Create NFT collection from EVM', () => {23  let donor: IKeyringPair;2425  before(async function () {26    await usingEthPlaygrounds(async (_helper, privateKey) => {27      donor = await privateKey({filename: __filename});28    });29  });3031  itEth('Create collection', async ({helper}) => {32    const owner = await helper.eth.createAccountWithBalance(donor);3334    const name = 'CollectionEVM';35    const description = 'Some description';36    const prefix = 'token prefix';3738    // todo:playgrounds this might fail when in async environment.39    const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;40    const {collectionId, collectionAddress, events} = await helper.eth.createNFTCollection(owner, name, description, prefix);41    42    expect(events).to.be.deep.equal([43      {44        address: '0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F',45        event: 'CollectionCreated',46        args: {47          owner: owner,48          collectionId: collectionAddress,49        },50      },51    ]);52    53    const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;5455    const collection = helper.nft.getCollectionObject(collectionId);56    const data = (await collection.getData())!;5758    expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);59    expect(collectionId).to.be.eq(collectionCountAfter);60    expect(data.name).to.be.eq(name);61    expect(data.description).to.be.eq(description);62    expect(data.raw.tokenPrefix).to.be.eq(prefix);63    expect(data.raw.mode).to.be.eq('NFT');6465    const options = await collection.getOptions();6667    expect(options.tokenPropertyPermissions).to.be.empty;68  });6970  itEth('Create collection with properties', async ({helper}) => {71    const owner = await helper.eth.createAccountWithBalance(donor);7273    const name = 'CollectionEVM';74    const description = 'Some description';75    const prefix = 'token prefix';76    const baseUri = 'BaseURI';7778    const {collectionId, collectionAddress, events} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, name, description, prefix, baseUri);7980    expect(events).to.be.deep.equal([81      {82        address: '0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F',83        event: 'CollectionCreated',84        args: {85          owner: owner,86          collectionId: collectionAddress,87        },88      },89    ]);9091    const collection = helper.nft.getCollectionObject(collectionId);92    const data = (await collection.getData())!;93    94    expect(data.name).to.be.eq(name);95    expect(data.description).to.be.eq(description);96    expect(data.raw.tokenPrefix).to.be.eq(prefix);97    expect(data.raw.mode).to.be.eq('NFT');9899    const options = await collection.getOptions();100    expect(options.tokenPropertyPermissions).to.be.deep.equal([101      {102        key: 'URI',103        permission: {mutable: true, collectionAdmin: true, tokenOwner: false},104      },105      {106        key: 'URISuffix',107        permission: {mutable: true, collectionAdmin: true, tokenOwner: false},108      },109    ]);110  });111112  // this test will occasionally fail when in async environment.113  itEth.skip('Check collection address exist', async ({helper}) => {114    const owner = await helper.eth.createAccountWithBalance(donor);115116    const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;117    const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);118    const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);119120    expect(await collectionHelpers.methods121      .isCollectionExist(expectedCollectionAddress)122      .call()).to.be.false;123124    await collectionHelpers.methods125      .createNFTCollection('A', 'A', 'A')126      .send({value: Number(2n * helper.balance.getOneTokenNominal())});127128    expect(await collectionHelpers.methods129      .isCollectionExist(expectedCollectionAddress)130      .call()).to.be.true;131  });132133  itEth('Set sponsorship', async ({helper}) => {134    const owner = await helper.eth.createAccountWithBalance(donor);135    const sponsor = await helper.eth.createAccountWithBalance(donor);136    const ss58Format = helper.chain.getChainProperties().ss58Format;137    const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');138139    const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);140    await collection.methods.setCollectionSponsor(sponsor).send();141142    let data = (await helper.nft.getData(collectionId))!;143    expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));144145    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');146147    const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);148    await sponsorCollection.methods.confirmCollectionSponsorship().send();149150    data = (await helper.nft.getData(collectionId))!;151    expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));152  });153154  itEth('Set limits', async ({helper}) => {155    const owner = await helper.eth.createAccountWithBalance(donor);156    const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'FLO');157    const limits = {158      accountTokenOwnershipLimit: 1000,159      sponsoredDataSize: 1024,160      sponsoredDataRateLimit: 30,161      tokenLimit: 1000000,162      sponsorTransferTimeout: 6,163      sponsorApproveTimeout: 6,164      ownerCanTransfer: false,165      ownerCanDestroy: false,166      transfersEnabled: false,167    };168169    const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);170    await collection.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();171    await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send();172    await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();173    await collection.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send();174    await collection.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();175    await collection.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();176    await collection.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send();177    await collection.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send();178    await collection.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send();179180    const data = (await helper.nft.getData(collectionId))!;181    expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(limits.accountTokenOwnershipLimit);182    expect(data.raw.limits.sponsoredDataSize).to.be.eq(limits.sponsoredDataSize);183    expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(limits.sponsoredDataRateLimit);184    expect(data.raw.limits.tokenLimit).to.be.eq(limits.tokenLimit);185    expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(limits.sponsorTransferTimeout);186    expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(limits.sponsorApproveTimeout);187    expect(data.raw.limits.ownerCanTransfer).to.be.eq(limits.ownerCanTransfer);188    expect(data.raw.limits.ownerCanDestroy).to.be.eq(limits.ownerCanDestroy);189    expect(data.raw.limits.transfersEnabled).to.be.eq(limits.transfersEnabled);190  });191192  itEth('Collection address exist', async ({helper}) => {193    const owner = await helper.eth.createAccountWithBalance(donor);194    const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';195    expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection)196      .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())197      .to.be.false;198199    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Exister', 'absolutely anything', 'EVC');200    expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)201      .methods.isCollectionExist(collectionAddress).call())202      .to.be.true;203  });204});205206describe('(!negative tests!) Create NFT collection from EVM', () => {207  let donor: IKeyringPair;208  let nominal: bigint;209210  before(async function () {211    await usingEthPlaygrounds(async (helper, privateKey) => {212      donor = await privateKey({filename: __filename});213      nominal = helper.balance.getOneTokenNominal();214    });215  });216217  itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {218    const owner = await helper.eth.createAccountWithBalance(donor);219    const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);220    {221      const MAX_NAME_LENGTH = 64;222      const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);223      const description = 'A';224      const tokenPrefix = 'A';225226      await expect(collectionHelper.methods227        .createNFTCollection(collectionName, description, tokenPrefix)228        .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);229230    }231    {232      const MAX_DESCRIPTION_LENGTH = 256;233      const collectionName = 'A';234      const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);235      const tokenPrefix = 'A';236      await expect(collectionHelper.methods237        .createNFTCollection(collectionName, description, tokenPrefix)238        .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);239    }240    {241      const MAX_TOKEN_PREFIX_LENGTH = 16;242      const collectionName = 'A';243      const description = 'A';244      const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);245      await expect(collectionHelper.methods246        .createNFTCollection(collectionName, description, tokenPrefix)247        .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);248    }249  });250251  itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {252    const owner = await helper.eth.createAccountWithBalance(donor);253    const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);254    await expect(collectionHelper.methods255      .createNFTCollection('Peasantry', 'absolutely anything', 'CVE')256      .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');257  });258259  itEth('(!negative test!) Check owner', async ({helper}) => {260    const owner = await helper.eth.createAccountWithBalance(donor);261    const malfeasant = helper.eth.createAccount();262    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Transgressed', 'absolutely anything', 'COR');263    const malfeasantCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant);264    const EXPECTED_ERROR = 'NoPermission';265    {266      const sponsor = await helper.eth.createAccountWithBalance(donor);267      await expect(malfeasantCollection.methods268        .setCollectionSponsor(sponsor)269        .call()).to.be.rejectedWith(EXPECTED_ERROR);270271      const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);272      await expect(sponsorCollection.methods273        .confirmCollectionSponsorship()274        .call()).to.be.rejectedWith('caller is not set as sponsor');275    }276    {277      await expect(malfeasantCollection.methods278        .setCollectionLimit('account_token_ownership_limit', '1000')279        .call()).to.be.rejectedWith(EXPECTED_ERROR);280    }281  });282283  itEth('(!negative test!) Set limits', async ({helper}) => {284    const owner = await helper.eth.createAccountWithBalance(donor);285    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');286    const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);287    await expect(collectionEvm.methods288      .setCollectionLimit('badLimit', 'true')289      .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');290  });291292  itEth('destroyCollection', async ({helper}) => {293    const owner = await helper.eth.createAccountWithBalance(donor);294    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');295    const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);296297298    const result = await collectionHelper.methods299      .destroyCollection(collectionAddress)300      .send({from: owner});301302    const events = helper.eth.normalizeEvents(result.events);303    304    expect(events).to.be.deep.equal([305      {306        address: collectionHelper.options.address,307        event: 'CollectionDestroyed',308        args: {309          collectionId: collectionAddress,310        },311      },312    ]);313314    expect(await collectionHelper.methods315      .isCollectionExist(collectionAddress)316      .call()).to.be.false;317  });318});