git.delta.rocks / unique-network / refs/commits / 2e0d1a668d33

difftreelog

source

tests/src/eth/createNFTCollection.test.ts14.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 with properties', async ({helper}) => {32    const owner = await helper.eth.createAccountWithBalance(donor);3334    const name = 'CollectionEVM';35    const description = 'Some description';36    const prefix = 'token prefix';37    const baseUri = 'BaseURI';3839    const {collectionId, collectionAddress, events} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, name, description, prefix, baseUri);4041    expect(events).to.be.deep.equal([42      {43        address: '0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F',44        event: 'CollectionCreated',45        args: {46          owner: owner,47          collectionId: collectionAddress,48        },49      },50    ]);5152    const collection = helper.nft.getCollectionObject(collectionId);53    const data = (await collection.getData())!;54    55    expect(data.name).to.be.eq(name);56    expect(data.description).to.be.eq(description);57    expect(data.raw.tokenPrefix).to.be.eq(prefix);58    expect(data.raw.mode).to.be.eq('NFT');5960    const options = await collection.getOptions();61    expect(options.tokenPropertyPermissions).to.be.deep.equal([62      {63        key: 'URI',64        permission: {mutable: true, collectionAdmin: true, tokenOwner: false},65      },66      {67        key: 'URISuffix',68        permission: {mutable: true, collectionAdmin: true, tokenOwner: false},69      },70    ]);71  });7273  // Soft-deprecated74  itEth('[eth] Set sponsorship', async ({helper}) => {75    const owner = await helper.eth.createAccountWithBalance(donor);76    const sponsor = await helper.eth.createAccountWithBalance(donor);77    const ss58Format = helper.chain.getChainProperties().ss58Format;78    const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');7980    const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner, true);81    await collection.methods.setCollectionSponsor(sponsor).send();8283    let data = (await helper.nft.getData(collectionId))!;84    expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));8586    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');8788    const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);89    await sponsorCollection.methods.confirmCollectionSponsorship().send();9091    data = (await helper.nft.getData(collectionId))!;92    expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));93  });9495  itEth('[cross] Set sponsorship', async ({helper}) => {96    const owner = await helper.eth.createAccountWithBalance(donor);97    const sponsor = await helper.eth.createAccountWithBalance(donor);98    const ss58Format = helper.chain.getChainProperties().ss58Format;99    const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');100101    const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);102    const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);103    await collection.methods.setCollectionSponsorCross(sponsorCross).send();104105    let data = (await helper.nft.getData(collectionId))!;106    expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));107108    await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');109110    const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);111    await sponsorCollection.methods.confirmCollectionSponsorship().send();112113    data = (await helper.nft.getData(collectionId))!;114    expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));115  });116117  itEth('Set limits', async ({helper}) => {118    const owner = await helper.eth.createAccountWithBalance(donor);119    const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'FLO');120    const limits = {121      accountTokenOwnershipLimit: 1000,122      sponsoredDataSize: 1024,123      sponsoredDataRateLimit: 30,124      tokenLimit: 1000000,125      sponsorTransferTimeout: 6,126      sponsorApproveTimeout: 6,127      ownerCanTransfer: 0,128      ownerCanDestroy: 0,129      transfersEnabled: 0,130    };131    132    const expectedLimits = {133      accountTokenOwnershipLimit: 1000,134      sponsoredDataSize: 1024,135      sponsoredDataRateLimit: 30,136      tokenLimit: 1000000,137      sponsorTransferTimeout: 6,138      sponsorApproveTimeout: 6,139      ownerCanTransfer: false,140      ownerCanDestroy: false,141      transfersEnabled: false,142    };143144    const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);145    await collection.methods.setCollectionLimit('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();146    await collection.methods.setCollectionLimit('sponsoredDataSize', limits.sponsoredDataSize).send();147    await collection.methods.setCollectionLimit('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();148    await collection.methods.setCollectionLimit('tokenLimit', limits.tokenLimit).send();149    await collection.methods.setCollectionLimit('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();150    await collection.methods.setCollectionLimit('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();151    await collection.methods.setCollectionLimit('ownerCanTransfer', limits.ownerCanTransfer).send();152    await collection.methods.setCollectionLimit('ownerCanDestroy', limits.ownerCanDestroy).send();153    await collection.methods.setCollectionLimit('transfersEnabled', limits.transfersEnabled).send();154155    const data = (await helper.rft.getData(collectionId))!;156    expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(expectedLimits.accountTokenOwnershipLimit);157    expect(data.raw.limits.sponsoredDataSize).to.be.eq(expectedLimits.sponsoredDataSize);158    expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(expectedLimits.sponsoredDataRateLimit);159    expect(data.raw.limits.tokenLimit).to.be.eq(expectedLimits.tokenLimit);160    expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(expectedLimits.sponsorTransferTimeout);161    expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(expectedLimits.sponsorApproveTimeout);162    expect(data.raw.limits.ownerCanTransfer).to.be.eq(expectedLimits.ownerCanTransfer);163    expect(data.raw.limits.ownerCanDestroy).to.be.eq(expectedLimits.ownerCanDestroy);164    expect(data.raw.limits.transfersEnabled).to.be.eq(expectedLimits.transfersEnabled);165  });166167  itEth('Collection address exist', async ({helper}) => {168    const owner = await helper.eth.createAccountWithBalance(donor);169    const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';170    expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection)171      .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())172      .to.be.false;173174    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Exister', 'absolutely anything', 'EVC');175    expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)176      .methods.isCollectionExist(collectionAddress).call())177      .to.be.true;178  });179});180181describe('(!negative tests!) Create NFT collection from EVM', () => {182  let donor: IKeyringPair;183  let nominal: bigint;184185  before(async function () {186    await usingEthPlaygrounds(async (helper, privateKey) => {187      donor = await privateKey({filename: __filename});188      nominal = helper.balance.getOneTokenNominal();189    });190  });191192  itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {193    const owner = await helper.eth.createAccountWithBalance(donor);194    const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);195    {196      const MAX_NAME_LENGTH = 64;197      const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);198      const description = 'A';199      const tokenPrefix = 'A';200201      await expect(collectionHelper.methods202        .createNFTCollection(collectionName, description, tokenPrefix)203        .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);204205    }206    {207      const MAX_DESCRIPTION_LENGTH = 256;208      const collectionName = 'A';209      const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);210      const tokenPrefix = 'A';211      await expect(collectionHelper.methods212        .createNFTCollection(collectionName, description, tokenPrefix)213        .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);214    }215    {216      const MAX_TOKEN_PREFIX_LENGTH = 16;217      const collectionName = 'A';218      const description = 'A';219      const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);220      await expect(collectionHelper.methods221        .createNFTCollection(collectionName, description, tokenPrefix)222        .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);223    }224  });225226  itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {227    const owner = await helper.eth.createAccountWithBalance(donor);228    const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);229    await expect(collectionHelper.methods230      .createNFTCollection('Peasantry', 'absolutely anything', 'CVE')231      .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');232  });233234  // Soft-deprecated235  itEth('(!negative test!) [eth] Check owner', async ({helper}) => {236    const owner = await helper.eth.createAccountWithBalance(donor);237    const malfeasant = helper.eth.createAccount();238    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Transgressed', 'absolutely anything', 'COR');239    const malfeasantCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant, true);240    const EXPECTED_ERROR = 'NoPermission';241    {242      const sponsor = await helper.eth.createAccountWithBalance(donor);243      await expect(malfeasantCollection.methods244        .setCollectionSponsor(sponsor)245        .call()).to.be.rejectedWith(EXPECTED_ERROR);246247      const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor, true);248      await expect(sponsorCollection.methods249        .confirmCollectionSponsorship()250        .call()).to.be.rejectedWith('caller is not set as sponsor');251    }252    {253      await expect(malfeasantCollection.methods254        .setCollectionLimit('account_token_ownership_limit', '1000')255        .call()).to.be.rejectedWith(EXPECTED_ERROR);256    }257  });258259  itEth('(!negative test!) [cross] 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      const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);268      await expect(malfeasantCollection.methods269        .setCollectionSponsorCross(sponsorCross)270        .call()).to.be.rejectedWith(EXPECTED_ERROR);271272      const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);273      await expect(sponsorCollection.methods274        .confirmCollectionSponsorship()275        .call()).to.be.rejectedWith('caller is not set as sponsor');276    }277    {278      await expect(malfeasantCollection.methods279        .setCollectionLimit('account_token_ownership_limit', '1000')280        .call()).to.be.rejectedWith(EXPECTED_ERROR);281    }282  });283284  itEth('(!negative test!) Set limits', async ({helper}) => {285    const invalidLimits = {286      accountTokenOwnershipLimit: BigInt(Number.MAX_SAFE_INTEGER),287      transfersEnabled: 3,288    };289290    const owner = await helper.eth.createAccountWithBalance(donor);291    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');292    const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);293    294    await expect(collectionEvm.methods295      .setCollectionLimit(Object.keys(invalidLimits)[0], invalidLimits.accountTokenOwnershipLimit)296      .call()).to.be.rejectedWith(`can't convert value to u32 "${invalidLimits.accountTokenOwnershipLimit}"`);297    298    await expect(collectionEvm.methods299      .setCollectionLimit(Object.keys(invalidLimits)[1], invalidLimits.transfersEnabled)300      .call()).to.be.rejectedWith(`can't convert value to boolean "${invalidLimits.transfersEnabled}"`);301  });302303  itEth('destroyCollection', async ({helper}) => {304    const owner = await helper.eth.createAccountWithBalance(donor);305    const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');306    const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);307308309    const result = await collectionHelper.methods310      .destroyCollection(collectionAddress)311      .send({from: owner});312313    const events = helper.eth.normalizeEvents(result.events);314    315    expect(events).to.be.deep.equal([316      {317        address: collectionHelper.options.address,318        event: 'CollectionDestroyed',319        args: {320          collectionId: collectionAddress,321        },322      },323    ]);324325    expect(await collectionHelper.methods326      .isCollectionExist(collectionAddress)327      .call()).to.be.false;328  });329});