--- a/tests/src/change-collection-owner.test.ts +++ b/tests/src/change-collection-owner.test.ts @@ -7,7 +7,22 @@ import chaiAsPromised from 'chai-as-promised'; import privateKey from './substrate/privateKey'; import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api'; -import { createCollectionExpectSuccess, addCollectionAdminExpectSuccess } from './util/helpers'; +import { createCollectionExpectSuccess, + addCollectionAdminExpectSuccess, + setCollectionSponsorExpectSuccess, + confirmSponsorshipExpectSuccess, + removeCollectionSponsorExpectSuccess, + enableWhiteListExpectSuccess, + setMintPermissionExpectSuccess, + destroyCollectionExpectSuccess, + setCollectionSponsorExpectFailure, + confirmSponsorshipExpectFailure, + removeCollectionSponsorExpectFailure, + enableWhiteListExpectFail, + setMintPermissionExpectFailure, + destroyCollectionExpectFailure, + setPublicAccessModeExpectSuccess, +} from './util/helpers'; chai.use(chaiAsPromised); const expect = chai.expect; @@ -31,6 +46,97 @@ }); }); +describe('Integration Test changeCollectionOwner(collection_id, new_owner) special checks for exOwner:', () => { + it('Changing the owner of the collection is not allowed for the former owner', async () => { + await usingApi(async api => { + const collectionId = await createCollectionExpectSuccess(); + const alice = privateKey('//Alice'); + const bob = privateKey('//Bob'); + + const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON(); + expect(collection.Owner).to.be.deep.eq(alice.address); + + const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address); + await submitTransactionAsync(alice, changeOwnerTx); + + const badChangeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, alice.address); + await expect(submitTransactionExpectFailAsync(alice, badChangeOwnerTx)).to.be.rejected; + + const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON(); + expect(collectionAfterOwnerChange.Owner).to.be.deep.eq(bob.address); + }); + }); + + it('New collectionOwner has access to sponsorship management operations in the collection', async () => { + await usingApi(async api => { + const collectionId = await createCollectionExpectSuccess(); + const alice = privateKey('//Alice'); + const bob = privateKey('//Bob'); + const charlie = privateKey('//Charlie'); + + const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON(); + expect(collection.Owner).to.be.deep.eq(alice.address); + + const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address); + await submitTransactionAsync(alice, changeOwnerTx); + + const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON(); + expect(collectionAfterOwnerChange.Owner).to.be.deep.eq(bob.address); + + // After changing the owner of the collection, all privileged methods are available to the new owner + // The new owner of the collection has access to sponsorship management operations in the collection + await setCollectionSponsorExpectSuccess(collectionId, charlie.address, '//Bob'); + await confirmSponsorshipExpectSuccess(collectionId, '//Charlie'); + await removeCollectionSponsorExpectSuccess(collectionId, '//Bob'); + + // The new owner of the collection has access to operations for managing the collection parameters + const collectionLimits = { + AccountTokenOwnershipLimit: 1, + SponsoredMintSize: 1, + TokenLimit: 1, + SponsorTimeout: 1, + OwnerCanTransfer: true, + OwnerCanDestroy: true, + }; + const tx1 = api.tx.nft.setCollectionLimits( + collectionId, + collectionLimits, + ); + await submitTransactionAsync(bob, tx1); + + await setPublicAccessModeExpectSuccess(bob, collectionId, 'WhiteList'); + await enableWhiteListExpectSuccess(bob, collectionId); + await setMintPermissionExpectSuccess(bob, collectionId, true); + await destroyCollectionExpectSuccess(collectionId, '//Bob'); + }); + }); + + it('New collectionOwner has access to changeCollectionOwner', async () => { + await usingApi(async api => { + const collectionId = await createCollectionExpectSuccess(); + const alice = privateKey('//Alice'); + const bob = privateKey('//Bob'); + const charlie = privateKey('//Charlie'); + + const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON(); + expect(collection.Owner).to.be.deep.eq(alice.address); + + const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address); + await submitTransactionAsync(alice, changeOwnerTx); + + const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON(); + expect(collectionAfterOwnerChange.Owner).to.be.deep.eq(bob.address); + + const changeOwnerTx2 = api.tx.nft.changeCollectionOwner(collectionId, charlie.address); + await submitTransactionAsync(bob, changeOwnerTx2); + + // ownership lost + const collectionAfterOwnerChange2: any = (await api.query.nft.collectionById(collectionId)).toJSON(); + expect(collectionAfterOwnerChange2.Owner).to.be.deep.eq(charlie.address); + }); + }); +}); + describe('Negative Integration Test changeCollectionOwner(collection_id, new_owner):', () => { it('Not owner can\'t change owner.', async () => { await usingApi(async api => { @@ -81,4 +187,47 @@ await createCollectionExpectSuccess(); }); }); + + it('Former collectionOwner not allowed to sponsorship management operations in the collection', async () => { + await usingApi(async api => { + const collectionId = await createCollectionExpectSuccess(); + const alice = privateKey('//Alice'); + const bob = privateKey('//Bob'); + const charlie = privateKey('//Charlie'); + + const collection: any = (await api.query.nft.collectionById(collectionId)).toJSON(); + expect(collection.Owner).to.be.deep.eq(alice.address); + + const changeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, bob.address); + await submitTransactionAsync(alice, changeOwnerTx); + + const badChangeOwnerTx = api.tx.nft.changeCollectionOwner(collectionId, alice.address); + await expect(submitTransactionExpectFailAsync(alice, badChangeOwnerTx)).to.be.rejected; + + const collectionAfterOwnerChange: any = (await api.query.nft.collectionById(collectionId)).toJSON(); + expect(collectionAfterOwnerChange.Owner).to.be.deep.eq(bob.address); + + await setCollectionSponsorExpectFailure(collectionId, charlie.address, '//Alice'); + await confirmSponsorshipExpectFailure(collectionId, '//Alice'); + await removeCollectionSponsorExpectFailure(collectionId, '//Alice'); + + const collectionLimits = { + AccountTokenOwnershipLimit: 1, + SponsoredMintSize: 1, + TokenLimit: 1, + SponsorTimeout: 1, + OwnerCanTransfer: true, + OwnerCanDestroy: true, + }; + const tx1 = api.tx.nft.setCollectionLimits( + collectionId, + collectionLimits, + ); + await expect(submitTransactionExpectFailAsync(alice, tx1)).to.be.rejected; + + await enableWhiteListExpectFail(alice, collectionId); + await setMintPermissionExpectFailure(alice, collectionId, true); + await destroyCollectionExpectFailure(collectionId, '//Alice'); + }); + }); }); --- a/tests/src/util/helpers.ts +++ b/tests/src/util/helpers.ts @@ -431,13 +431,13 @@ }); } -export async function setCollectionSponsorExpectSuccess(collectionId: number, sponsor: string) { +export async function setCollectionSponsorExpectSuccess(collectionId: number, sponsor: string, sender = '//Alice') { await usingApi(async (api) => { // Run the transaction - const alicePrivateKey = privateKey('//Alice'); + const senderPrivateKey = privateKey(sender); const tx = api.tx.nft.setCollectionSponsor(collectionId, sponsor); - const events = await submitTransactionAsync(alicePrivateKey, tx); + const events = await submitTransactionAsync(senderPrivateKey, tx); const result = getGenericResult(events); // Get the collection @@ -451,11 +451,11 @@ }); } -export async function removeCollectionSponsorExpectSuccess(collectionId: number) { +export async function removeCollectionSponsorExpectSuccess(collectionId: number, sender = '//Alice') { await usingApi(async (api) => { // Run the transaction - const alicePrivateKey = privateKey('//Alice'); + const alicePrivateKey = privateKey(sender); const tx = api.tx.nft.removeCollectionSponsor(collectionId); const events = await submitTransactionAsync(alicePrivateKey, tx); const result = getGenericResult(events); @@ -1006,10 +1006,31 @@ }); } +export async function setPublicAccessModeExpectFail( + sender: IKeyringPair, collectionId: number, + accessMode: 'Normal' | 'WhiteList', +) { + await usingApi(async (api) => { + + // Run the transaction + const tx = api.tx.nft.setPublicAccessMode(collectionId, accessMode); + const events = await expect(submitTransactionExpectFailAsync(sender, tx)).to.be.rejected; + const result = getGenericResult(events); + + // What to expect + // tslint:disable-next-line:no-unused-expression + expect(result.success).to.be.false; + }); +} + export async function enableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) { await setPublicAccessModeExpectSuccess(sender, collectionId, 'WhiteList'); } +export async function enableWhiteListExpectFail(sender: IKeyringPair, collectionId: number) { + await setPublicAccessModeExpectFail(sender, collectionId, 'WhiteList'); +} + export async function disableWhiteListExpectSuccess(sender: IKeyringPair, collectionId: number) { await setPublicAccessModeExpectSuccess(sender, collectionId, 'Normal'); }