1234567891011121314151617import {evmToAddress} from '@polkadot/util-crypto';18import {IKeyringPair} from '@polkadot/types/types';19import {Pallets, requirePalletsOrSkip} from '../util';20import {expect, itEth, usingEthPlaygrounds} from './util';21import {CollectionLimitField} from './util/playgrounds/types';222324describe('Create RFT collection from EVM', () => {25 let donor: IKeyringPair;2627 before(async function() {28 await usingEthPlaygrounds(async (helper, privateKey) => {29 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);30 donor = await privateKey({filename: __filename});31 });32 });3334 itEth('Create collection', async ({helper}) => {35 const owner = await helper.eth.createAccountWithBalance(donor);36 37 const name = 'CollectionEVM';38 const description = 'Some description';39 const prefix = 'token prefix';40 41 const {collectionId} = await helper.eth.createRFTCollection(owner, name, description, prefix);42 const data = (await helper.rft.getData(collectionId))!;43 const collection = helper.rft.getCollectionObject(collectionId);4445 expect(data.name).to.be.eq(name);46 expect(data.description).to.be.eq(description);47 expect(data.raw.tokenPrefix).to.be.eq(prefix);48 expect(data.raw.mode).to.be.eq('ReFungible');4950 const options = await collection.getOptions();5152 expect(options.tokenPropertyPermissions).to.be.empty;53 });5455 5657 itEth('Create collection with properties & get description', async ({helper}) => {58 const owner = await helper.eth.createAccountWithBalance(donor);5960 const name = 'CollectionEVM';61 const description = 'Some description';62 const prefix = 'token prefix';63 const baseUri = 'BaseURI';6465 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, name, description, prefix, baseUri);66 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');6768 const collection = helper.rft.getCollectionObject(collectionId);69 const data = (await collection.getData())!;70 71 expect(data.name).to.be.eq(name);72 expect(data.description).to.be.eq(description);73 expect(data.raw.tokenPrefix).to.be.eq(prefix);74 expect(data.raw.mode).to.be.eq('ReFungible');7576 expect(await contract.methods.description().call()).to.deep.equal(description);7778 const options = await collection.getOptions();79 expect(options.tokenPropertyPermissions).to.be.deep.equal([80 {81 key: 'URI',82 permission: {mutable: true, collectionAdmin: true, tokenOwner: false},83 },84 {85 key: 'URISuffix',86 permission: {mutable: true, collectionAdmin: true, tokenOwner: false},87 },88 ]);89 });90 91 92 itEth.skip('Check collection address exist', async ({helper}) => {93 const owner = await helper.eth.createAccountWithBalance(donor);9495 const expectedCollectionId = +(await helper.callRpc('api.rpc.unique.collectionStats')).created + 1;96 const expectedCollectionAddress = helper.ethAddress.fromCollectionId(expectedCollectionId);97 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);9899 expect(await collectionHelpers.methods100 .isCollectionExist(expectedCollectionAddress)101 .call()).to.be.false;102103 await collectionHelpers.methods104 .createRFTCollection('A', 'A', 'A')105 .send({value: Number(2n * helper.balance.getOneTokenNominal())});106 107 expect(await collectionHelpers.methods108 .isCollectionExist(expectedCollectionAddress)109 .call()).to.be.true;110 });111 112 113 itEth('[eth] Set sponsorship', async ({helper}) => {114 const owner = await helper.eth.createAccountWithBalance(donor);115 const sponsor = await helper.eth.createAccountWithBalance(donor);116 const ss58Format = helper.chain.getChainProperties().ss58Format;117 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');118119 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true);120 await collection.methods.setCollectionSponsor(sponsor).send();121122 let data = (await helper.rft.getData(collectionId))!;123 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));124125 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');126127 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);128 await sponsorCollection.methods.confirmCollectionSponsorship().send();129130 data = (await helper.rft.getData(collectionId))!;131 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));132 });133134 itEth('[cross] Set sponsorship', async ({helper}) => {135 const owner = await helper.eth.createAccountWithBalance(donor);136 const sponsor = await helper.eth.createAccountWithBalance(donor);137 const ss58Format = helper.chain.getChainProperties().ss58Format;138 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');139140 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);141 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);142 await collection.methods.setCollectionSponsorCross(sponsorCross).send();143144 let data = (await helper.rft.getData(collectionId))!;145 expect(data.raw.sponsorship.Unconfirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));146147 await expect(collection.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('ConfirmSponsorshipFail');148149 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);150 await sponsorCollection.methods.confirmCollectionSponsorship().send();151152 data = (await helper.rft.getData(collectionId))!;153 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));154 });155156 itEth('Collection address exist', async ({helper}) => {157 const owner = await helper.eth.createAccountWithBalance(donor);158 const collectionAddressForNonexistentCollection = '0x17C4E6453CC49AAAAEACA894E6D9683E00112233';159 expect(await helper.ethNativeContract.collectionHelpers(collectionAddressForNonexistentCollection)160 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())161 .to.be.false;162 163 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Exister', 'absolutely anything', 'WIWT');164 expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)165 .methods.isCollectionExist(collectionAddress).call())166 .to.be.true;167 });168});169170describe('(!negative tests!) Create RFT collection from EVM', () => {171 let donor: IKeyringPair;172 let nominal: bigint;173174 before(async function() {175 await usingEthPlaygrounds(async (helper, privateKey) => {176 requirePalletsOrSkip(this, helper, [Pallets.ReFungible]);177 donor = await privateKey({filename: __filename});178 nominal = helper.balance.getOneTokenNominal();179 });180 });181182 itEth('(!negative test!) Create collection (bad lengths)', async ({helper}) => {183 const owner = await helper.eth.createAccountWithBalance(donor);184 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);185 {186 const MAX_NAME_LENGTH = 64;187 const collectionName = 'A'.repeat(MAX_NAME_LENGTH + 1);188 const description = 'A';189 const tokenPrefix = 'A';190191 await expect(collectionHelper.methods192 .createRFTCollection(collectionName, description, tokenPrefix)193 .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);194 }195 {196 const MAX_DESCRIPTION_LENGTH = 256;197 const collectionName = 'A';198 const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);199 const tokenPrefix = 'A';200 await expect(collectionHelper.methods201 .createRFTCollection(collectionName, description, tokenPrefix)202 .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);203 }204 {205 const MAX_TOKEN_PREFIX_LENGTH = 16;206 const collectionName = 'A';207 const description = 'A';208 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);209 await expect(collectionHelper.methods210 .createRFTCollection(collectionName, description, tokenPrefix)211 .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);212 }213 });214 215 itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {216 const owner = await helper.eth.createAccountWithBalance(donor);217 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);218 await expect(collectionHelper.methods219 .createRFTCollection('Peasantry', 'absolutely anything', 'TWIW')220 .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');221 });222223 224 itEth('(!negative test!) [eth] Check owner', async ({helper}) => {225 const owner = await helper.eth.createAccountWithBalance(donor);226 const peasant = helper.eth.createAccount();227 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');228 const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant, true);229 const EXPECTED_ERROR = 'NoPermission';230 {231 const sponsor = await helper.eth.createAccountWithBalance(donor);232 await expect(peasantCollection.methods233 .setCollectionSponsor(sponsor)234 .call()).to.be.rejectedWith(EXPECTED_ERROR);235 236 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor, true);237 await expect(sponsorCollection.methods238 .confirmCollectionSponsorship()239 .call()).to.be.rejectedWith('ConfirmSponsorshipFail');240 }241 {242 await expect(peasantCollection.methods243 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})244 .call()).to.be.rejectedWith(EXPECTED_ERROR);245 }246 });247248 itEth('(!negative test!) [cross] Check owner', async ({helper}) => {249 const owner = await helper.eth.createAccountWithBalance(donor);250 const peasant = helper.eth.createAccount();251 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');252 const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant);253 const EXPECTED_ERROR = 'NoPermission';254 {255 const sponsor = await helper.eth.createAccountWithBalance(donor);256 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);257 await expect(peasantCollection.methods258 .setCollectionSponsorCross(sponsorCross)259 .call()).to.be.rejectedWith(EXPECTED_ERROR);260 261 const sponsorCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', sponsor);262 await expect(sponsorCollection.methods263 .confirmCollectionSponsorship()264 .call()).to.be.rejectedWith('ConfirmSponsorshipFail');265 }266 {267 await expect(peasantCollection.methods268 .setCollectionLimit({field: CollectionLimitField.AccountTokenOwnership, value: {status: true, value: 1000}})269 .call()).to.be.rejectedWith(EXPECTED_ERROR);270 }271 });272 273 itEth('destroyCollection', async ({helper}) => {274 const owner = await helper.eth.createAccountWithBalance(donor);275 const {collectionAddress, collectionId} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');276 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);277 278 await expect(collectionHelper.methods279 .destroyCollection(collectionAddress)280 .send({from: owner})).to.be.fulfilled;281 282 expect(await collectionHelper.methods283 .isCollectionExist(collectionAddress)284 .call()).to.be.false;285 expect(await helper.collection.getData(collectionId)).to.be.null;286 });287});