difftreelog
Merge pull request #745 from UniqueNetwork/tests/eth-helpers
in: master
9 files changed
tests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth239 const owner = await helper.eth.createAccountWithBalance(donor);239 const owner = await helper.eth.createAccountWithBalance(donor);240 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');240 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');241241242 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);242 const [adminSub] = await helper.arrange.createAccounts([10n], donor);243 const adminEth = (await helper.eth.createAccountWithBalance(donor)).toLowerCase();243 const newAdminCross = helper.ethCrossAccount.fromKeyringPair(newAdmin);244 const adminCrossSub = helper.ethCrossAccount.fromKeyringPair(adminSub);245 const adminCrossEth = helper.ethCrossAccount.fromAddress(adminEth);246244 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);247 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);245 await collectionEvm.methods.addCollectionAdminCross(newAdminCross).send();248 await collectionEvm.methods.addCollectionAdminCross(adminCrossSub).send();249 await collectionEvm.methods.addCollectionAdminCross(adminCrossEth).send();250246 {251 {247 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);252 const adminList = await helper.collection.getAdmins(collectionId);248 expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())253 expect(adminList).to.deep.include({Substrate: adminSub.address});249 .to.be.eq(newAdmin.address.toLocaleLowerCase());254 expect(adminList).to.deep.include({Ethereum: adminEth});250 }255 }251256252 await collectionEvm.methods.removeCollectionAdminCross(newAdminCross).send();257 await collectionEvm.methods.removeCollectionAdminCross(adminCrossSub).send();258 await collectionEvm.methods.removeCollectionAdminCross(adminCrossEth).send();253 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);259 const adminList = await helper.collection.getAdmins(collectionId);254 expect(adminList.length).to.be.eq(0);260 expect(adminList.length).to.be.eq(0);261262 // Non admin cannot mint:263 await expect(helper.nft.mintToken(adminSub, {collectionId, owner: {Substrate: adminSub.address}})).to.be.rejectedWith(/common.PublicMintingNotAllowed/);264 await expect(collectionEvm.methods.mint(adminEth).send({from: adminEth})).to.be.rejected;255 });265 });256266257 // Soft-deprecated267 // Soft-deprecated395405396 itEth('Change owner [cross]', async ({helper}) => {406 itEth('Change owner [cross]', async ({helper}) => {397 const owner = await helper.eth.createAccountWithBalance(donor);407 const owner = await helper.eth.createAccountWithBalance(donor);408 const ownerEth = await helper.eth.createAccountWithBalance(donor);409 const ownerCrossEth = helper.ethCrossAccount.fromAddress(ownerEth);398 const [newOwner] = await helper.arrange.createAccounts([10n], donor);410 const [ownerSub] = await helper.arrange.createAccounts([10n], donor);399 const newOwnerCross = helper.ethCrossAccount.fromKeyringPair(newOwner);411 const ownerCrossSub = helper.ethCrossAccount.fromKeyringPair(ownerSub);412400 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');413 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');401 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);414 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);402415403 expect(await collectionEvm.methods.isOwnerOrAdminCross(newOwnerCross).call()).to.be.false;416 expect(await collectionEvm.methods.isOwnerOrAdminCross(ownerCrossSub).call()).to.be.false;404417418 // Can set ethereum owner:405 await collectionEvm.methods.changeCollectionOwnerCross(newOwnerCross).send();419 await collectionEvm.methods.changeCollectionOwnerCross(ownerCrossEth).send({from: owner});406407 expect(await collectionEvm.methods.isOwnerOrAdminCross(newOwnerCross).call()).to.be.true;420 expect(await collectionEvm.methods.isOwnerOrAdminCross(ownerCrossEth).call()).to.be.true;421 expect(await helper.collection.getData(collectionId))422 .to.have.property('normalizedOwner').that.is.eq(helper.address.ethToSubstrate(ownerEth));423 424 // Can set Substrate owner:425 await collectionEvm.methods.changeCollectionOwnerCross(ownerCrossSub).send({from: ownerEth});426 expect(await collectionEvm.methods.isOwnerOrAdminCross(ownerCrossSub).call()).to.be.true;427 expect(await helper.collection.getData(collectionId))428 .to.have.property('normalizedOwner').that.is.eq(helper.address.normalizeSubstrate(ownerSub.address));408 });429 });409430410 itEth.skip('change owner call fee', async ({helper}) => {431 itEth.skip('change owner call fee', async ({helper}) => {tests/src/eth/createFTCollection.test.tsdiffbeforeafterboth144 144 145 itEth('destroyCollection', async ({helper}) => {145 itEth('destroyCollection', async ({helper}) => {146 const owner = await helper.eth.createAccountWithBalance(donor);146 const owner = await helper.eth.createAccountWithBalance(donor);147 const {collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT');147 const {collectionAddress, collectionId} = await helper.eth.createFungibleCollection(owner, 'Exister', DECIMALS, 'absolutely anything', 'WIWT');148 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);148 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);149149150 const result = await collectionHelper.methods150 const result = await collectionHelper.methods166 expect(await collectionHelper.methods166 expect(await collectionHelper.methods167 .isCollectionExist(collectionAddress)167 .isCollectionExist(collectionAddress)168 .call()).to.be.false;168 .call()).to.be.false;169 expect(await helper.collection.getData(collectionId)).to.be.null;169 });170 });170});171});171172214 }215 }215 });216 });216 217 217 itEth('(!negative test!) Create collection (no funds)', async ({helper}) => {218 itEth('(!negative test!) cannot create collection if value !== 2', async ({helper}) => {218 const owner = await helper.eth.createAccountWithBalance(donor);219 const owner = await helper.eth.createAccountWithBalance(donor);219 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);220 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);221 const expects = [0n, 1n, 30n].map(async value => {220 await expect(collectionHelper.methods222 await expect(collectionHelper.methods221 .createFTCollection('Peasantry', DECIMALS, 'absolutely anything', 'TWIW')223 .createFTCollection('Peasantry', DECIMALS, 'absolutely anything', 'TWIW')222 .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');224 .call({value: Number(value * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');225 });226 await Promise.all(expects);223 });227 });224228225 // Soft-deprecated229 // Soft-deprecatedtests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth308308309 itEth('destroyCollection', async ({helper}) => {309 itEth('destroyCollection', async ({helper}) => {310 const owner = await helper.eth.createAccountWithBalance(donor);310 const owner = await helper.eth.createAccountWithBalance(donor);311 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');311 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');312 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);312 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);313313314314331 expect(await collectionHelper.methods331 expect(await collectionHelper.methods332 .isCollectionExist(collectionAddress)332 .isCollectionExist(collectionAddress)333 .call()).to.be.false;333 .call()).to.be.false;334 expect(await helper.collection.getData(collectionId)).to.be.null;334 });335 });335});336});tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth340 340 341 itEth('destroyCollection', async ({helper}) => {341 itEth('destroyCollection', async ({helper}) => {342 const owner = await helper.eth.createAccountWithBalance(donor);342 const owner = await helper.eth.createAccountWithBalance(donor);343 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');343 const {collectionAddress, collectionId} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');344 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);344 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);345 345 346 await expect(collectionHelper.methods346 await expect(collectionHelper.methods350 expect(await collectionHelper.methods350 expect(await collectionHelper.methods351 .isCollectionExist(collectionAddress)351 .isCollectionExist(collectionAddress)352 .call()).to.be.false; 352 .call()).to.be.false;353 expect(await helper.collection.getData(collectionId)).to.be.null;353 });354 });354});355});355356tests/src/eth/destroyCollection.test.tsdiffbeforeafterboth15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617import {IKeyringPair} from '@polkadot/types/types';17import {IKeyringPair} from '@polkadot/types/types';18import {Pallets, requirePalletsOrSkip} from '../util';18import {Pallets} from '../util';19import {expect, itEth, usingEthPlaygrounds} from './util';19import {expect, itEth, usingEthPlaygrounds} from './util';20212022describe('Destroy Collection from EVM', () => {21describe('Destroy Collection from EVM', function() {23 let donor: IKeyringPair;22 let donor: IKeyringPair;23 const testCases = [24 {method: 'createRFTCollection' as const, params: ['Limits', 'absolutely anything', 'OLF'], requiredPallets: [Pallets.ReFungible]},25 {method: 'createNFTCollection' as const, params: ['Limits', 'absolutely anything', 'OLF'], requiredPallets: [Pallets.NFT]},26 {method: 'createFTCollection' as const, params: ['Limits', 'absolutely anything', 'OLF', 18], requiredPallets: [Pallets.Fungible]},27 ];242825 before(async function() {29 before(async function() {26 await usingEthPlaygrounds(async (helper, privateKey) => {30 await usingEthPlaygrounds(async (_, privateKey) => {27 requirePalletsOrSkip(this, helper, [Pallets.ReFungible, Pallets.NFT]);28 donor = await privateKey({filename: __filename});31 donor = await privateKey({filename: __filename});29 });32 });30 });33 });313432 35 testCases.map((testCase) => 33 itEth('(!negative test!) RFT', async ({helper}) => {36 itEth.ifWithPallets(`Cannot burn non-owned or non-existing collection ${testCase.method}`, testCase.requiredPallets, async ({helper}) => {34 const owner = await helper.eth.createAccountWithBalance(donor);37 const owner = await helper.eth.createAccountWithBalance(donor);35 const signer = await helper.eth.createAccountWithBalance(donor);38 const signer = await helper.eth.createAccountWithBalance(donor);36 39 37 const unexistedCollection = helper.ethAddress.fromCollectionId(1000000);40 const unexistedCollection = helper.ethAddress.fromCollectionId(1000000);38 41 39 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');42 const collectionHelpers = helper.ethNativeContract.collectionHelpers(signer);40 const collectionHelper = helper.ethNativeContract.collectionHelpers(signer);43 const {collectionAddress} = await helper.eth.createCollecion(testCase.method, owner, ...testCase.params as [string, string, string, number?]);41 4445 // cannot burn collec42 await expect(collectionHelper.methods46 await expect(collectionHelpers.methods43 .destroyCollection(collectionAddress)47 .destroyCollection(collectionAddress)44 .send({from: signer})).to.be.rejected;48 .send({from: signer})).to.be.rejected;45 49 46 await expect(collectionHelper.methods50 await expect(collectionHelpers.methods47 .destroyCollection(unexistedCollection)51 .destroyCollection(unexistedCollection)48 .send({from: signer})).to.be.rejected;52 .send({from: signer})).to.be.rejected;49 53 50 expect(await collectionHelper.methods54 expect(await collectionHelpers.methods51 .isCollectionExist(unexistedCollection)55 .isCollectionExist(unexistedCollection)52 .call()).to.be.false;56 .call()).to.be.false;57 58 expect(await collectionHelpers.methods59 .isCollectionExist(collectionAddress)60 .call()).to.be.true;53 });61 }));54 55 itEth('(!negative test!) NFT', async ({helper}) => {56 const owner = await helper.eth.createAccountWithBalance(donor);57 const signer = await helper.eth.createAccountWithBalance(donor);58 59 const unexistedCollection = helper.ethAddress.fromCollectionId(1000000);60 61 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');62 const collectionHelper = helper.ethNativeContract.collectionHelpers(signer);63 64 await expect(collectionHelper.methods65 .destroyCollection(collectionAddress)66 .send({from: signer})).to.be.rejected;67 68 await expect(collectionHelper.methods69 .destroyCollection(unexistedCollection)70 .send({from: signer})).to.be.rejected;71 72 expect(await collectionHelper.methods73 .isCollectionExist(unexistedCollection)74 .call()).to.be.false;75 });76});62});7763tests/src/eth/fungible.test.tsdiffbeforeafterboth232 });232 });233233234 itEth('Can perform transferCross()', async ({helper}) => {234 itEth('Can perform transferCross()', async ({helper}) => {235 const owner = await helper.eth.createAccountWithBalance(donor);235 const sender = await helper.eth.createAccountWithBalance(donor);236 const receiver = await helper.eth.createAccountWithBalance(donor);236 const receiverEth = await helper.eth.createAccountWithBalance(donor);237 const to = helper.ethCrossAccount.fromAddress(receiver);237 const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth);238 const toSubstrate = helper.ethCrossAccount.fromKeyringPair(donor);238 const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(donor);239 const collection = await helper.ft.mintCollection(alice);239 const collection = await helper.ft.mintCollection(alice);240 await collection.mint(alice, 200n, {Ethereum: owner});240 await collection.mint(alice, 200n, {Ethereum: sender});241241242 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);242 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);243 const contract = helper.ethNativeContract.collection(collectionAddress, 'ft', owner);243 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', sender);244244245 {245 {246 // Can transferCross to ethereum address:246 const result = await contract.methods.transferCross(to, 50).send({from: owner});247 const result = await collectionEvm.methods.transferCross(receiverCrossEth, 50).send({from: sender});247 248 // Check events:248 const event = result.events.Transfer;249 const event = result.events.Transfer;249 expect(event.address).to.be.equal(collectionAddress);250 expect(event.address).to.be.equal(collectionAddress);250 expect(event.returnValues.from).to.be.equal(owner);251 expect(event.returnValues.from).to.be.equal(sender);251 expect(event.returnValues.to).to.be.equal(receiver);252 expect(event.returnValues.to).to.be.equal(receiverEth);252 expect(event.returnValues.value).to.be.equal('50');253 expect(event.returnValues.value).to.be.equal('50');254 // Sender's balance decreased:255 const ownerBalance = await collectionEvm.methods.balanceOf(sender).call();256 expect(+ownerBalance).to.equal(150);257 // Receiver's balance increased:258 const receiverBalance = await collectionEvm.methods.balanceOf(receiverEth).call();259 expect(+receiverBalance).to.equal(50);253 }260 }254261 255 {262 {256 const balance = await contract.methods.balanceOf(owner).call();263 // Can transferCross to substrate address:257 expect(+balance).to.equal(150);258 }259260 {264 const result = await collectionEvm.methods.transferCross(receiverCrossSub, 50).send({from: sender});261 const balance = await contract.methods.balanceOf(receiver).call();265 // Check events:262 expect(+balance).to.equal(50);263 }264 265 {266 const result = await contract.methods.transferCross(toSubstrate, 50).send({from: owner});267 268 const event = result.events.Transfer;266 const event = result.events.Transfer;269 expect(event.address).to.be.equal(collectionAddress);267 expect(event.address).to.be.equal(collectionAddress);270 expect(event.returnValues.from).to.be.equal(owner);268 expect(event.returnValues.from).to.be.equal(sender);271 expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(donor.address));269 expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(donor.address));272 expect(event.returnValues.value).to.be.equal('50');270 expect(event.returnValues.value).to.be.equal('50');273 }271 // Sender's balance decreased:274275 {276 const balance = await collection.getBalance({Ethereum: owner});272 const senderBalance = await collection.getBalance({Ethereum: sender});277 expect(balance).to.equal(100n);273 expect(senderBalance).to.equal(100n);278 }274 // Receiver's balance increased:279280 {281 const balance = await collection.getBalance({Substrate: donor.address});275 const balance = await collection.getBalance({Substrate: donor.address});282 expect(balance).to.equal(50n);276 expect(balance).to.equal(50n);283 }277 }284 285 });278 });286 279280 itEth('Cannot transferCross() more than have', async ({helper}) => {281 const sender = await helper.eth.createAccountWithBalance(donor);282 const receiverEth = await helper.eth.createAccountWithBalance(donor);283 const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth);284 const BALANCE = 200n;285 const BALANCE_TO_TRANSFER = BALANCE + 100n;286287 const collection = await helper.ft.mintCollection(alice);288 await collection.mint(alice, BALANCE, {Ethereum: sender});289 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);290 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'ft', sender);291292 await expect(collectionEvm.methods.transferCross(receiverCrossEth, BALANCE_TO_TRANSFER).send({from: sender})).to.be.rejected;293 });294 287 itEth('Can perform transfer()', async ({helper}) => {295 itEth('Can perform transfer()', async ({helper}) => {288 const owner = await helper.eth.createAccountWithBalance(donor);296 const owner = await helper.eth.createAccountWithBalance(donor);tests/src/eth/nonFungible.test.tsdiffbeforeafterboth252 itEth('Can perform burnFromCross()', async ({helper}) => {252 itEth('Can perform burnFromCross()', async ({helper}) => {253 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});253 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});254255 const owner = bob;254 const ownerSub = bob;255 const ownerCrossSub = helper.ethCrossAccount.fromKeyringPair(ownerSub);256 const spender = await helper.eth.createAccountWithBalance(donor, 100n);256 const ownerEth = await helper.eth.createAccountWithBalance(donor, 100n);257 const ownerCrossEth = helper.ethCrossAccount.fromAddress(ownerEth);258259 const burnerEth = await helper.eth.createAccountWithBalance(donor, 100n);260 const burnerCrossEth = helper.ethCrossAccount.fromAddress(burnerEth);257261258 const token = await collection.mintToken(minter, {Substrate: owner.address});262 const token1 = await collection.mintToken(minter, {Substrate: ownerSub.address});263 const token2 = await collection.mintToken(minter, {Ethereum: ownerEth});259264260 const address = helper.ethAddress.fromCollectionId(collection.collectionId);265 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);261 const contract = helper.ethNativeContract.collection(address, 'nft');266 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft');262267263 {268 // Approve tokens from substrate and ethereum:264 await token.approve(owner, {Ethereum: spender});269 await token1.approve(ownerSub, {Ethereum: burnerEth});270 await collectionEvm.methods.approveCross(burnerCrossEth, token2.tokenId).send({from: ownerEth});271272 // can burnFromCross:265 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);273 const result1 = await collectionEvm.methods.burnFromCross(ownerCrossSub, token1.tokenId).send({from: burnerEth});266 const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender});274 const result2 = await collectionEvm.methods.burnFromCross(ownerCrossEth, token2.tokenId).send({from: burnerEth});267 const events = result.events.Transfer;275 const events1 = result1.events.Transfer;268276 const events2 = result2.events.Transfer;277278 // Check events for burnFromCross (substrate and ethereum):279 [269 expect(events).to.be.like({280 [events1, token1, helper.address.substrateToEth(ownerSub.address)], 281 [events2, token2, ownerEth],282 ].map(burnData => {283 expect(burnData[0]).to.be.like({270 address,284 address: collectionAddress,271 event: 'Transfer',285 event: 'Transfer',272 returnValues: {286 returnValues: {273 from: helper.address.substrateToEth(owner.address),287 from: burnData[2],274 to: '0x0000000000000000000000000000000000000000',288 to: '0x0000000000000000000000000000000000000000',275 tokenId: token.tokenId.toString(),289 tokenId: burnData[1].tokenId.toString(),276 },290 },277 });291 });278 }292 });293294 expect(await token1.doesExist()).to.be.false;295 expect(await token2.doesExist()).to.be.false;279 });296 });280297281 itEth('Can perform approveCross()', async ({helper}) => {298 itEth('Can perform approveCross()', async ({helper}) => {326 expect(await helper.nft.getTokenOwner(collection.collectionId, token2.tokenId)).to.deep.eq({Ethereum: receiverEth.toLowerCase()});343 expect(await helper.nft.getTokenOwner(collection.collectionId, token2.tokenId)).to.deep.eq({Ethereum: receiverEth.toLowerCase()});327 });344 });345346 itEth('Can reaffirm approved address', async ({helper}) => {347 const owner = await helper.eth.createAccountWithBalance(donor, 100n);348 const ownerCrossEth = helper.ethCrossAccount.fromAddress(owner);349 const [receiver1, receiver2] = await helper.arrange.createAccounts([100n, 100n], donor);350 const receiver1Cross = helper.ethCrossAccount.fromKeyringPair(receiver1);351 const receiver2Cross = helper.ethCrossAccount.fromKeyringPair(receiver2);352 const collection = await helper.nft.mintCollection(minter, {name: 'A', description: 'B', tokenPrefix: 'C'});353 const token1 = await collection.mintToken(minter, {Ethereum: owner});354 const token2 = await collection.mintToken(minter, {Ethereum: owner});355 const collectionEvm = helper.ethNativeContract.collection(helper.ethAddress.fromCollectionId(collection.collectionId), 'nft');356357 // Can approve and reaffirm approved address:358 await collectionEvm.methods.approveCross(receiver1Cross, token1.tokenId).send({from: owner});359 await collectionEvm.methods.approveCross(receiver2Cross, token1.tokenId).send({from: owner});360361 // receiver1 cannot transferFrom:362 await expect(helper.nft.transferTokenFrom(receiver1, collection.collectionId, token1.tokenId, {Ethereum: owner}, {Substrate: receiver1.address})).to.be.rejected;363 // receiver2 can transferFrom:364 await helper.nft.transferTokenFrom(receiver2, collection.collectionId, token1.tokenId, {Ethereum: owner}, {Substrate: receiver2.address});365366 // can set approved address to self address to remove approval:367 await collectionEvm.methods.approveCross(receiver1Cross, token2.tokenId).send({from: owner});368 await collectionEvm.methods.approveCross(ownerCrossEth, token2.tokenId).send({from: owner});369370 // receiver1 cannot transfer token anymore:371 await expect(helper.nft.transferTokenFrom(receiver1, collection.collectionId, token2.tokenId, {Ethereum: owner}, {Substrate: receiver1.address})).to.be.rejected;372 });328373329 itEth('Can perform transferFrom()', async ({helper}) => {374 itEth('Can perform transferFrom()', async ({helper}) => {330 const owner = await helper.eth.createAccountWithBalance(donor);375 const owner = await helper.eth.createAccountWithBalance(donor);426 itEth('Can perform transferCross()', async ({helper}) => {471 itEth('Can perform transferCross()', async ({helper}) => {427 const collection = await helper.nft.mintCollection(minter, {});472 const collection = await helper.nft.mintCollection(minter, {});428 const owner = await helper.eth.createAccountWithBalance(donor);473 const owner = await helper.eth.createAccountWithBalance(donor);429 const receiver = await helper.eth.createAccountWithBalance(donor);474 const receiverEth = await helper.eth.createAccountWithBalance(donor);430 const to = helper.ethCrossAccount.fromAddress(receiver);475 const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth);431 const toSubstrate = helper.ethCrossAccount.fromKeyringPair(minter);476 const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(minter);432 477 433 const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});478 const {tokenId} = await collection.mintToken(minter, {Ethereum: owner});434479435 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);480 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);436 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);481 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);437482438 {483 {439 const result = await contract.methods.transferCross(to, tokenId).send({from: owner});484 // Can transferCross to ethereum address:440485 const result = await collectionEvm.methods.transferCross(receiverCrossEth, tokenId).send({from: owner});486 // Check events:441 const event = result.events.Transfer;487 const event = result.events.Transfer;442 expect(event.address).to.be.equal(collectionAddress);488 expect(event.address).to.be.equal(collectionAddress);443 expect(event.returnValues.from).to.be.equal(owner);489 expect(event.returnValues.from).to.be.equal(owner);444 expect(event.returnValues.to).to.be.equal(receiver);490 expect(event.returnValues.to).to.be.equal(receiverEth);445 expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);491 expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);446 }492 447493 // owner has balance = 0:448 {449 const balance = await contract.methods.balanceOf(owner).call();494 const ownerBalance = await collectionEvm.methods.balanceOf(owner).call();450 expect(+balance).to.equal(0);495 expect(+ownerBalance).to.equal(0);451 }496 // receiver owns token:452453 {454 const balance = await contract.methods.balanceOf(receiver).call();497 const receiverBalance = await collectionEvm.methods.balanceOf(receiverEth).call();455 expect(+balance).to.equal(1);498 expect(+receiverBalance).to.equal(1);456 }457 458 {459 const substrateResult = await contract.methods.transferCross(toSubstrate, tokenId).send({from: receiver});499 expect(await helper.nft.getTokenOwner(collection.collectionId, tokenId)).to.deep.eq({Ethereum: receiverEth.toLowerCase()});460 500 }461501 502 {503 // Can transferCross to substrate address:504 const substrateResult = await collectionEvm.methods.transferCross(receiverCrossSub, tokenId).send({from: receiverEth});505 // Check events:462 const event = substrateResult.events.Transfer;506 const event = substrateResult.events.Transfer;463 expect(event.address).to.be.equal(collectionAddress);507 expect(event.address).to.be.equal(collectionAddress);464 expect(event.returnValues.from).to.be.equal(receiver);508 expect(event.returnValues.from).to.be.equal(receiverEth);465 expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address));509 expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address));466 expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);510 expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);467 }511 468512 // owner has balance = 0:469 {470 const balance = await contract.methods.balanceOf(receiver).call();513 const ownerBalance = await collectionEvm.methods.balanceOf(receiverEth).call();471 expect(+balance).to.equal(0);514 expect(+ownerBalance).to.equal(0);472 }515 // receiver owns token:473474 {475 const balance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address});516 const receiverBalance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address});476 expect(balance).to.be.contain(tokenId);517 expect(receiverBalance).to.contain(tokenId);477 }518 }478 });519 });479});520});480521tests/src/eth/reFungible.test.tsdiffbeforeafterboth363 });363 });364 364 365 itEth('Can perform transferCross()', async ({helper}) => {365 itEth('Can perform transferCross()', async ({helper}) => {366 const caller = await helper.eth.createAccountWithBalance(donor);366 const sender = await helper.eth.createAccountWithBalance(donor);367 const receiver = await helper.eth.createAccountWithBalance(donor);367 const receiverEth = await helper.eth.createAccountWithBalance(donor);368 const to = helper.ethCrossAccount.fromAddress(receiver);368 const receiverCrossEth = helper.ethCrossAccount.fromAddress(receiverEth);369 const toSubstrate = helper.ethCrossAccount.fromKeyringPair(minter);369 const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(minter);370370 const collection = await helper.rft.mintCollection(minter, {});371 const collection = await helper.rft.mintCollection(minter, {});371 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);372 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);372 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);373 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', sender);373374374 const {tokenId} = await collection.mintToken(minter, 1n, {Ethereum: caller});375 const token = await collection.mintToken(minter, 50n, {Ethereum: sender});375376376 {377 {378 // Can transferCross to ethereum address:377 const result = await contract.methods.transferCross(to, tokenId).send({from: caller});379 const result = await collectionEvm.methods.transferCross(receiverCrossEth, token.tokenId).send({from: sender});378380 // Check events:379 const event = result.events.Transfer;381 const event = result.events.Transfer;380 expect(event.address).to.equal(collectionAddress);382 expect(event.address).to.equal(collectionAddress);381 expect(event.returnValues.from).to.equal(caller);383 expect(event.returnValues.from).to.equal(sender);382 expect(event.returnValues.to).to.equal(receiver);384 expect(event.returnValues.to).to.equal(receiverEth);383 expect(event.returnValues.tokenId).to.equal(tokenId.toString());385 expect(event.returnValues.tokenId).to.equal(token.tokenId.toString());386 // Sender's balance decreased:387 const senderBalance = await collectionEvm.methods.balanceOf(sender).call();388 expect(+senderBalance).to.equal(0);389 expect(await token.getBalance({Ethereum: sender})).to.eq(0n);390 // Receiver's balance increased:391 const receiverBalance = await collectionEvm.methods.balanceOf(receiverEth).call();392 expect(+receiverBalance).to.equal(1);393 expect(await token.getBalance({Ethereum: receiverEth})).to.eq(50n);384 }394 }385395 386 {396 {387 const balance = await contract.methods.balanceOf(caller).call();397 // Can transferCross to substrate address:388 expect(+balance).to.equal(0);389 }390391 {398 const substrateResult = await collectionEvm.methods.transferCross(receiverCrossSub, token.tokenId).send({from: receiverEth});392 const balance = await contract.methods.balanceOf(receiver).call();399 // Check events:393 expect(+balance).to.equal(1);394 }395 396 {397 const substrateResult = await contract.methods.transferCross(toSubstrate, tokenId).send({from: receiver});398 399400 const event = substrateResult.events.Transfer;400 const event = substrateResult.events.Transfer;401 expect(event.address).to.be.equal(collectionAddress);401 expect(event.address).to.be.equal(collectionAddress);402 expect(event.returnValues.from).to.be.equal(receiver);402 expect(event.returnValues.from).to.be.equal(receiverEth);403 expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address));403 expect(event.returnValues.to).to.be.equal(helper.address.substrateToEth(minter.address));404 expect(event.returnValues.tokenId).to.be.equal(`${tokenId}`);404 expect(event.returnValues.tokenId).to.be.equal(`${token.tokenId}`);405 }405 // Sender's balance decreased:406407 {408 const balance = await contract.methods.balanceOf(receiver).call();406 const senderBalance = await collectionEvm.methods.balanceOf(receiverEth).call();409 expect(+balance).to.equal(0);407 expect(+senderBalance).to.equal(0);410 }408 expect(await token.getBalance({Ethereum: receiverEth})).to.eq(0n);411409 // Receiver's balance increased:412 {413 const balance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address});410 const receiverBalance = await helper.nft.getTokensByAddress(collection.collectionId, {Substrate: minter.address});414 expect(balance).to.be.contain(tokenId);411 expect(receiverBalance).to.contain(token.tokenId);415 }412 expect(await token.getBalance({Substrate: minter.address})).to.eq(50n);413 }416 });414 });415416 itEth.skip('Cannot transferCross with invalid params', async ({helper}) => {417 const sender = await helper.eth.createAccountWithBalance(donor);418 const tokenOwner = await helper.eth.createAccountWithBalance(donor);419 const receiverCrossSub = helper.ethCrossAccount.fromKeyringPair(minter);420421 const collection = await helper.rft.mintCollection(minter, {});422 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);423 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', sender);424425 await collection.mintToken(minter, 50n, {Ethereum: sender});426 const notSendersToken = await collection.mintToken(minter, 50n, {Ethereum: tokenOwner});427 // Cannot transferCross someone else's token:428 await expect(collectionEvm.methods.transferCross(receiverCrossSub, notSendersToken.tokenId).send({from: sender})).to.be.rejected;429 // FIXME: (transaction successful): Cannot transfer token if it does not exist:430 await expect(collectionEvm.methods.transferCross(receiverCrossSub, 999999).send({from: sender})).to.be.rejected;431 });417432418 itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => {433 itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => {419 const caller = await helper.eth.createAccountWithBalance(donor);434 const caller = await helper.eth.createAccountWithBalance(donor);tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth186 return await this.helper.callRpc('api.rpc.eth.call', [{from: signer, to: contractAddress, data: abi}]);186 return await this.helper.callRpc('api.rpc.eth.call', [{from: signer, to: contractAddress, data: abi}]);187 }187 }188188189 async createCollecion(functionName: string, signer: string, name: string, description: string, tokenPrefix: string): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> {189 async createCollecion(functionName: 'createNFTCollection' | 'createRFTCollection' | 'createFTCollection', signer: string, name: string, description: string, tokenPrefix: string, decimals?: number): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> {190 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();190 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();191 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);191 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);192192193 const functionParams = functionName === 'createFTCollection' ? [name, decimals, description, tokenPrefix] : [name, description, tokenPrefix];193 const result = await collectionHelper.methods[functionName](name, description, tokenPrefix).send({value: Number(collectionCreationPrice)});194 const result = await collectionHelper.methods[functionName](...functionParams).send({value: Number(collectionCreationPrice)});194195195 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);196 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);196 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);197 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);217 return this.createCollecion('createRFTCollection', signer, name, description, tokenPrefix);218 return this.createCollecion('createRFTCollection', signer, name, description, tokenPrefix);218 }219 }219220220 async createFungibleCollection(signer: string, name: string, decimals: number, description: string, tokenPrefix: string): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[]}> {221 createFungibleCollection(signer: string, name: string, decimals: number, description: string, tokenPrefix: string): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[]}> {221 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();222 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);223224 const result = await collectionHelper.methods.createFTCollection(name, decimals, description, tokenPrefix).send({value: Number(collectionCreationPrice)});222 return this.createCollecion('createFTCollection', signer, name, description, tokenPrefix, decimals);225 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);226 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);227228 const events = this.helper.eth.normalizeEvents(result.events);229230 return {collectionId, collectionAddress, events};231 }223 }232224233 async createERC721MetadataCompatibleRFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> {225 async createERC721MetadataCompatibleRFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> {