1import {expect} from 'chai';2import {tokenIdToAddress} from '../eth/util/helpers';3import privateKey from '../substrate/privateKey';4import usingApi, {executeTransaction} from '../substrate/substrate-api';5import {6 createCollectionExpectSuccess,7 createItemExpectFailure,8 createItemExpectSuccess,9 getTokenOwner,10 getTopmostTokenOwner,11 normalizeAccountId,12 setCollectionLimitsExpectSuccess,13 transferExpectSuccess,14} from '../util/helpers';15import {IKeyringPair} from '@polkadot/types/types';1617let alice: IKeyringPair;18let bob: IKeyringPair;1920describe('Integration Test: Unnesting', () => {21 before(async () => {22 await usingApi(async api => {23 alice = privateKey('//Alice');24 bob = privateKey('//Bob');25 });26 });2728 it('Allows the owner to successfully unnest a token', async () => {29 await usingApi(async api => {30 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});31 await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});32 const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');33 const targetAddress = {Ethereum: tokenIdToAddress(collection, targetToken)};3435 36 const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', targetAddress);3738 39 await expect(executeTransaction(40 api,41 alice,42 api.tx.unique.transferFrom(normalizeAccountId(targetAddress), normalizeAccountId(alice), collection, nestedToken, 1),43 )).to.not.be.rejected;44 expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Substrate: alice.address});4546 47 await transferExpectSuccess(collection, nestedToken, alice, targetAddress);48 await expect(executeTransaction(49 api,50 alice,51 api.tx.unique.burnFrom(collection, normalizeAccountId(alice.address), nestedToken, 1),52 )).to.not.be.rejected;53 await expect(getTokenOwner(api, collection, nestedToken)).to.be.rejected; 54 });55 });5657 58});5960describe('Negative Test: Unnesting', () => {61 before(async () => {62 await usingApi(async api => {63 alice = privateKey('//Alice');64 bob = privateKey('//Bob');65 });66 });6768 it('Disallows a non-owner to unnest/burn a token', async () => {69 await usingApi(async api => {70 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});71 await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});72 const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');73 const targetAddress = {Ethereum: tokenIdToAddress(collection, targetToken)};7475 76 const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', targetAddress);7778 79 await expect(executeTransaction(80 api,81 bob,82 api.tx.unique.transferFrom(normalizeAccountId(targetAddress), normalizeAccountId(bob), collection, nestedToken, 1),83 )).to.be.rejectedWith(/^common\.ApprovedValueTooLow$/);84 85 expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});8687 88 await expect(executeTransaction(89 api,90 bob,91 api.tx.unique.burnFrom(collection, normalizeAccountId(bob.address), nestedToken, 1),92 )).to.not.be.rejectedWith(/^common\.ApprovedValueTooLow$/);93 expect(await getTokenOwner(api, collection, nestedToken)).to.be.deep.equal({Ethereum: tokenIdToAddress(collection, targetToken).toLowerCase()});94 });95 });9697 it('Disallows excessive token nesting', async () => {98 await usingApi(async api => {99 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});100 await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});101 const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');102103 104 const nestedToken1 = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});105 const nestedToken2 = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, nestedToken1)});106 107 await createItemExpectFailure(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, nestedToken2)});108109 expect(await getTopmostTokenOwner(api, collection, nestedToken2)).to.be.deep.equal({Substrate: alice.address});110 });111 });112113 114115 116 it('Prevents ouroboros creation', async () => {117 const collection = await createCollectionExpectSuccess({mode: {type: 'NFT'}});118 await setCollectionLimitsExpectSuccess(alice, collection, {nestingRule: 'Owner'});119 const targetToken = await createItemExpectSuccess(alice, collection, 'NFT');120121 122 const nestedToken = await createItemExpectSuccess(alice, collection, 'NFT', {Ethereum: tokenIdToAddress(collection, targetToken)});123 expect(transferExpectSuccess(collection, targetToken, alice, {Ethereum: tokenIdToAddress(collection, nestedToken)})).to.be.rejectedWith(/^structure\.OuroborosDetected$/);124 });125});