1234567891011121314151617import {evmToAddress} from '@polkadot/util-crypto';18import {IKeyringPair} from '@polkadot/types/types';19import {expect, itEth, usingEthPlaygrounds} from './util/playgrounds';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 const {collectionId} = await helper.eth.createNonfungibleCollection(owner, name, description, prefix);39 const data = (await helper.rft.getData(collectionId))!;40 41 expect(data.name).to.be.eq(name);42 expect(data.description).to.be.eq(description);43 expect(data.raw.tokenPrefix).to.be.eq(prefix);44 expect(data.raw.mode).to.be.eq('NFT');45 });4647 48 itEth.skip('Check collection address exist', async ({helper}) => {49 const owner = await helper.eth.createAccountWithBalance(donor);5051 const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;52 const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);53 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);5455 expect(await collectionHelpers.methods56 .isCollectionExist(expectedCollectionAddress)57 .call()).to.be.false;5859 await collectionHelpers.methods60 .createNonfungibleCollection('A', 'A', 'A')61 .send({value: Number(2n * helper.balance.getOneTokenNominal())});62 63 expect(await collectionHelpers.methods64 .isCollectionExist(expectedCollectionAddress)65 .call()).to.be.true;66 });67 68 itEth('Set sponsorship', async ({helper}) => {69 const owner = await helper.eth.createAccountWithBalance(donor);70 const sponsor = await helper.eth.createAccountWithBalance(donor);71 const ss58Format = helper.chain.getChainProperties().ss58Format;72 const {collectionId, collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');7374 const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);75 await collection.methods.setCollectionSponsor(sponsor).send();7677 let data = (await helper.nft.getData(collectionId))!;78 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));7980 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');8182 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);83 await sponsorCollection.methods.confirmCollectionSponsorship().send();8485 data = (await helper.nft.getData(collectionId))!;86 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));87 });8889 itEth('Set limits', async ({helper}) => {90 const owner = await helper.eth.createAccountWithBalance(donor);91 const {collectionId, collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Limits', 'absolutely anything', 'FLO');92 const limits = {93 accountTokenOwnershipLimit: 1000,94 sponsoredDataSize: 1024,95 sponsoredDataRateLimit: 30,96 tokenLimit: 1000000,97 sponsorTransferTimeout: 6,98 sponsorApproveTimeout: 6,99 ownerCanTransfer: false,100 ownerCanDestroy: false,101 transfersEnabled: false,102 };103104 const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);105 await collection.methods['setCollectionLimit(string,uint32)']('accountTokenOwnershipLimit', limits.accountTokenOwnershipLimit).send();106 await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataSize', limits.sponsoredDataSize).send();107 await collection.methods['setCollectionLimit(string,uint32)']('sponsoredDataRateLimit', limits.sponsoredDataRateLimit).send();108 await collection.methods['setCollectionLimit(string,uint32)']('tokenLimit', limits.tokenLimit).send();109 await collection.methods['setCollectionLimit(string,uint32)']('sponsorTransferTimeout', limits.sponsorTransferTimeout).send();110 await collection.methods['setCollectionLimit(string,uint32)']('sponsorApproveTimeout', limits.sponsorApproveTimeout).send();111 await collection.methods['setCollectionLimit(string,bool)']('ownerCanTransfer', limits.ownerCanTransfer).send();112 await collection.methods['setCollectionLimit(string,bool)']('ownerCanDestroy', limits.ownerCanDestroy).send();113 await collection.methods['setCollectionLimit(string,bool)']('transfersEnabled', limits.transfersEnabled).send();114 115 const data = (await helper.nft.getData(collectionId))!;116 expect(data.raw.limits.accountTokenOwnershipLimit).to.be.eq(limits.accountTokenOwnershipLimit);117 expect(data.raw.limits.sponsoredDataSize).to.be.eq(limits.sponsoredDataSize);118 expect(data.raw.limits.sponsoredDataRateLimit.blocks).to.be.eq(limits.sponsoredDataRateLimit);119 expect(data.raw.limits.tokenLimit).to.be.eq(limits.tokenLimit);120 expect(data.raw.limits.sponsorTransferTimeout).to.be.eq(limits.sponsorTransferTimeout);121 expect(data.raw.limits.sponsorApproveTimeout).to.be.eq(limits.sponsorApproveTimeout);122 expect(data.raw.limits.ownerCanTransfer).to.be.eq(limits.ownerCanTransfer);123 expect(data.raw.limits.ownerCanDestroy).to.be.eq(limits.ownerCanDestroy);124 expect(data.raw.limits.transfersEnabled).to.be.eq(limits.transfersEnabled);125 });126127 itEth('Collection address exist', async ({helper}) => {128 const owner = await helper.eth.createAccountWithBalance(donor);129 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';130 expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection)131 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())132 .to.be.false;133 134 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Exister', 'absolutely anything', 'EVC');135 expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)136 .methods.isCollectionExist(collectionAddress).call())137 .to.be.true;138 });139});140141describe('(!negative tests!) Create NFT collection from EVM', () => {142 let donor: IKeyringPair;143 let nominal: bigint;144145 before(async function() {146 await usingEthPlaygrounds(async (helper, privateKey) => {147 donor = await privateKey({filename: __filename});148 nominal = helper.balance.getOneTokenNominal();149 });150 });151152 itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {153 const owner = await helper.eth.createAccountWithBalance(donor);154 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);155 {156 const MAX_NAME_LENGTH = 64;157 const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);158 const description = 'A';159 const tokenPrefix = 'A';160161 await expect(collectionHelper.methods162 .createNonfungibleCollection(collectionName, description, tokenPrefix)163 .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);164 165 }166 {167 const MAX_DESCRIPTION_LENGTH = 256;168 const collectionName = 'A';169 const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);170 const tokenPrefix = 'A';171 await expect(collectionHelper.methods172 .createNonfungibleCollection(collectionName, description, tokenPrefix)173 .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);174 }175 {176 const MAX_TOKEN_PREFIX_LENGTH = 16;177 const collectionName = 'A';178 const description = 'A';179 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);180 await expect(collectionHelper.methods181 .createNonfungibleCollection(collectionName, description, tokenPrefix)182 .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);183 }184 });185 186 itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {187 const owner = await helper.eth.createAccountWithBalance(donor);188 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);189 await expect(collectionHelper.methods190 .createNonfungibleCollection('Peasantry', 'absolutely anything', 'CVE')191 .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');192 });193194 itEth('(!negative test!) Check owner', async ({helper}) => {195 const owner = await helper.eth.createAccountWithBalance(donor);196 const malfeasant = helper.eth.createAccount();197 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Transgressed', 'absolutely anything', 'COR');198 const malfeasantCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant);199 const EXPECTED_ERROR = 'NoPermission';200 {201 const sponsor = await helper.eth.createAccountWithBalance(donor);202 await expect(malfeasantCollection.methods203 .setCollectionSponsor(sponsor)204 .call()).to.be.rejectedWith(EXPECTED_ERROR);205 206 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', sponsor);207 await expect(sponsorCollection.methods208 .confirmCollectionSponsorship()209 .call()).to.be.rejectedWith('caller is not set as sponsor');210 }211 {212 await expect(malfeasantCollection.methods213 .setCollectionLimit('account_token_ownership_limit', '1000')214 .call()).to.be.rejectedWith(EXPECTED_ERROR);215 }216 });217218 itEth('(!negative test!) Set limits', async ({helper}) => {219 const owner = await helper.eth.createAccountWithBalance(donor);220 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Limits', 'absolutely anything', 'OLF');221 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);222 await expect(collectionEvm.methods223 .setCollectionLimit('badLimit', 'true')224 .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');225 });226});