From 1e8c54cb6ea68509fa55595c2dbf4b03830401a2 Mon Sep 17 00:00:00 2001 From: Maksandre Date: Wed, 05 Oct 2022 09:09:16 +0000 Subject: [PATCH] Tests: move outdated tests to .oudated dir --- --- /dev/null +++ b/tests/src/.outdated/addToContractAllowList.test.ts @@ -0,0 +1,103 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import usingApi, {submitTransactionAsync, submitTransactionExpectFailAsync} from '../substrate/substrate-api'; +import { + deployFlipper, +} from '../util/contracthelpers'; +import { + getGenericResult, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + +// todo:playgrounds skipped ~ postponed +describe.skip('Integration Test addToContractAllowList', () => { + + it('Add an address to a contract allow list', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const bob = privateKeyWrapper('//Bob'); + const [contract, deployer] = await deployFlipper(api, privateKeyWrapper); + + const allowListedBefore = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); + const addTx = api.tx.unique.addToContractAllowList(contract.address, bob.address); + const addEvents = await submitTransactionAsync(deployer, addTx); + const allowListedAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); + + expect(getGenericResult(addEvents).success).to.be.true; + expect(allowListedBefore).to.be.false; + expect(allowListedAfter).to.be.true; + }); + }); + + it('Adding same address to allow list repeatedly should not produce errors', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const bob = privateKeyWrapper('//Bob'); + const [contract, deployer] = await deployFlipper(api, privateKeyWrapper); + + const allowListedBefore = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); + const addTx = api.tx.unique.addToContractAllowList(contract.address, bob.address); + const addEvents = await submitTransactionAsync(deployer, addTx); + const allowListedAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); + const addAgainEvents = await submitTransactionAsync(deployer, addTx); + const allowListedAgainAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); + + expect(getGenericResult(addEvents).success).to.be.true; + expect(allowListedBefore).to.be.false; + expect(allowListedAfter).to.be.true; + expect(getGenericResult(addAgainEvents).success).to.be.true; + expect(allowListedAgainAfter).to.be.true; + }); + }); +}); + +describe.skip('Negative Integration Test addToContractAllowList', () => { + + it('Add an address to a allow list of a non-contract', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const alice = privateKeyWrapper('//Bob'); + const bob = privateKeyWrapper('//Bob'); + const charlieGuineaPig = privateKeyWrapper('//Charlie'); + + const allowListedBefore = (await api.query.unique.contractAllowList(charlieGuineaPig.address, bob.address)).toJSON(); + const addTx = api.tx.unique.addToContractAllowList(charlieGuineaPig.address, bob.address); + await expect(submitTransactionExpectFailAsync(alice, addTx)).to.be.rejected; + const allowListedAfter = (await api.query.unique.contractAllowList(charlieGuineaPig.address, bob.address)).toJSON(); + + expect(allowListedBefore).to.be.false; + expect(allowListedAfter).to.be.false; + }); + }); + + it('Add to a contract allow list using a non-owner address', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const bob = privateKeyWrapper('//Bob'); + const [contract] = await deployFlipper(api, privateKeyWrapper); + + const allowListedBefore = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); + const addTx = api.tx.unique.addToContractAllowList(contract.address, bob.address); + await expect(submitTransactionExpectFailAsync(bob, addTx)).to.be.rejected; + const allowListedAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); + + expect(allowListedBefore).to.be.false; + expect(allowListedAfter).to.be.false; + }); + }); + +}); --- /dev/null +++ b/tests/src/.outdated/collision-tests/admVsOwnerChanges.test.ts @@ -0,0 +1,73 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +/* broken by design +// substrate transactions are sequential, not parallel +// the order of execution is indeterminate + +import { IKeyringPair } from '@polkadot/types/types'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import privateKey from '../substrate/privateKey'; +import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; +import { + createCollectionExpectSuccess, + createItemExpectSuccess, + normalizeAccountId, + waitNewBlocks, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +let Alice: IKeyringPair; +let Bob: IKeyringPair; +let Ferdie: IKeyringPair; + +before(async () => { + await usingApi(async () => { + Alice = privateKey('//Alice'); + Bob = privateKey('//Bob'); + Ferdie = privateKey('//Ferdie'); + }); +}); + +describe('Admin vs Owner changes token: ', () => { + // tslint:disable-next-line: max-line-length + it('The collection admin changes the owner of the token and in the same block the current owner transfers the token to another address ', async () => { + + await usingApi(async (api) => { + const collectionId = await createCollectionExpectSuccess(); + const changeAdminTxBob = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); + await submitTransactionAsync(Alice, changeAdminTxBob); + const changeAdminTxFerdie = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Ferdie.address)); + await submitTransactionAsync(Bob, changeAdminTxFerdie); + const itemId = await createItemExpectSuccess(Ferdie, collectionId, 'NFT'); + + const changeOwner = api.tx.unique.transferFrom(normalizeAccountId(Ferdie.address), normalizeAccountId(Bob.address), collectionId, itemId, 1); + const approve = api.tx.unique.approve(normalizeAccountId(Bob.address), collectionId, itemId, 1); + const sendItem = api.tx.unique.transfer(normalizeAccountId(Alice.address), collectionId, itemId, 1); + await Promise.all([ + changeOwner.signAndSend(Alice), + approve.signAndSend(Bob), + sendItem.signAndSend(Ferdie), + ]); + const itemBefore: any = await api.query.unique.nftItemList(collectionId, itemId); + expect(itemBefore.owner).not.to.be.eq(Bob.address); + await waitNewBlocks(2); + }); + }); +}); +*/ \ No newline at end of file --- /dev/null +++ b/tests/src/.outdated/collision-tests/admVsOwnerData.test.ts @@ -0,0 +1,69 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +/* broken by design +// substrate transactions are sequential, not parallel +// the order of execution is indeterminate + +import { IKeyringPair } from '@polkadot/types/types'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import privateKey from '../substrate/privateKey'; +import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; +import { + createCollectionExpectSuccess, + createItemExpectSuccess, + normalizeAccountId, + waitNewBlocks, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +let Alice: IKeyringPair; +let Bob: IKeyringPair; + +before(async () => { + await usingApi(async () => { + Alice = privateKey('//Alice'); + Bob = privateKey('//Bob'); + }); +}); + +describe('Admin vs Owner changes the data in the token: ', () => { + it('The collection admin changes the data in the token and in the same block the token owner also changes the data in it ', async () => { + await usingApi(async (api) => { + const AliceData = 1; + const BobData = 2; + const collectionId = await createCollectionExpectSuccess(); + const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); + await submitTransactionAsync(Alice, changeAdminTx); + const itemId = await createItemExpectSuccess(Bob, collectionId, 'NFT'); + // + // tslint:disable-next-line: max-line-length + const AliceTx = api.tx.unique.setVariableMetaData(collectionId, itemId, AliceData.toString()); + // tslint:disable-next-line: max-line-length + const BobTx = api.tx.unique.setVariableMetaData(collectionId, itemId, BobData.toString()); + await Promise.all([ + AliceTx.signAndSend(Alice), + BobTx.signAndSend(Bob), + ]); + const item: any = await api.query.unique.nftItemList(collectionId, itemId); + expect(item.variableData).not.to.be.eq(null); // Pseudo-random selection of one of two values + await waitNewBlocks(2); + }); + }); +}); +*/ \ No newline at end of file --- /dev/null +++ b/tests/src/.outdated/collision-tests/admVsOwnerTake.test.ts @@ -0,0 +1,71 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +/* broken by design +// substrate transactions are sequential, not parallel +// the order of execution is indeterminate + +import { IKeyringPair } from '@polkadot/types/types'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import privateKey from '../substrate/privateKey'; +import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; +import { + createCollectionExpectSuccess, + createItemExpectSuccess, + normalizeAccountId, + waitNewBlocks, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +let Alice: IKeyringPair; +let Bob: IKeyringPair; +let Ferdie: IKeyringPair; + +before(async () => { + await usingApi(async () => { + Alice = privateKey('//Alice'); + Bob = privateKey('//Bob'); + Ferdie = privateKey('//Ferdie'); + }); +}); + +describe('Admin vs Owner take token: ', () => { + // tslint:disable-next-line: max-line-length + it('The collection admin burns the token and in the same block the token owner performs a transaction on it ', async () => { + await usingApi(async (api) => { + const collectionId = await createCollectionExpectSuccess(); + const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); + await submitTransactionAsync(Alice, changeAdminTx); + const itemId = await createItemExpectSuccess(Bob, collectionId, 'NFT'); + // + const sendItem = api.tx.unique.transfer(normalizeAccountId(Ferdie.address), collectionId, itemId, 1); + const burnItem = api.tx.unique.burnItem(collectionId, itemId, 1); + await Promise.all([ + sendItem.signAndSend(Bob), + burnItem.signAndSend(Alice), + ]); + await waitNewBlocks(2); + let itemBurn = false; + itemBurn = (await (api.query.unique.nftItemList(collectionId, itemId))).toJSON() as boolean; + // tslint:disable-next-line: no-unused-expression + expect(itemBurn).to.be.null; + await waitNewBlocks(2); + }); + }); +}); +*/ \ No newline at end of file --- /dev/null +++ b/tests/src/.outdated/collision-tests/adminDestroyCollection.test.ts @@ -0,0 +1,70 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +/* broken by design +// substrate transactions are sequential, not parallel +// the order of execution is indeterminate + +import { IKeyringPair } from '@polkadot/types/types'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import privateKey from '../substrate/privateKey'; +import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; +import { + createCollectionExpectSuccess, + normalizeAccountId, + waitNewBlocks, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +let Alice: IKeyringPair; +let Bob: IKeyringPair; +let Ferdie: IKeyringPair; + +before(async () => { + await usingApi(async () => { + Alice = privateKey('//Alice'); + Bob = privateKey('//Bob'); + Ferdie = privateKey('//Ferdie'); + }); +}); + +describe('Deleting a collection while add address to allowlist: ', () => { + // tslint:disable-next-line: max-line-length + it('Adding an address to the collection allowlist in a block by the admin, and deleting the collection by the owner ', async () => { + await usingApi(async (api) => { + const collectionId = await createCollectionExpectSuccess(); + const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); + await submitTransactionAsync(Alice, changeAdminTx); + await waitNewBlocks(1); + // + const addAllowlistAdm = api.tx.unique.addToAllowList(collectionId, normalizeAccountId(Ferdie.address)); + const destroyCollection = api.tx.unique.destroyCollection(collectionId); + await Promise.all([ + addAllowlistAdm.signAndSend(Bob), + destroyCollection.signAndSend(Alice), + ]); + await waitNewBlocks(1); + let allowList = false; + allowList = (await api.query.unique.allowList(collectionId, Ferdie.address)).toJSON() as boolean; + // tslint:disable-next-line: no-unused-expression + expect(allowList).to.be.false; + await waitNewBlocks(2); + }); + }); +}); +*/ \ No newline at end of file --- /dev/null +++ b/tests/src/.outdated/collision-tests/adminLimitsOff.test.ts @@ -0,0 +1,86 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +/* broken by design +// substrate transactions are sequential, not parallel +// the order of execution is indeterminate + +import { IKeyringPair } from '@polkadot/types/types'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import privateKey from '../substrate/privateKey'; +import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from '../substrate/substrate-api'; +import { + createCollectionExpectSuccess, + normalizeAccountId, + waitNewBlocks, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +let Alice: IKeyringPair; +let Bob: IKeyringPair; +let Ferdie: IKeyringPair; +let Charlie: IKeyringPair; +let Eve: IKeyringPair; +let Dave: IKeyringPair; + +before(async () => { + await usingApi(async () => { + Alice = privateKey('//Alice'); + Bob = privateKey('//Bob'); + Ferdie = privateKey('//Ferdie'); + Charlie = privateKey('//Charlie'); + Eve = privateKey('//Eve'); + Dave = privateKey('//Dave'); + }); +}); + +describe('Admin limit exceeded collection: ', () => { + // tslint:disable-next-line: max-line-length + it('In one block, the owner and admin add new admins to the collection more than the limit ', async () => { + await usingApi(async (api) => { + const collectionId = await createCollectionExpectSuccess(); + + const chainAdminLimit = (api.consts.unique.collectionAdminsLimit as any).toNumber(); + expect(chainAdminLimit).to.be.equal(5); + + const changeAdminTx1 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Eve.address)); + await submitTransactionAsync(Alice, changeAdminTx1); + const changeAdminTx2 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Dave.address)); + await submitTransactionAsync(Alice, changeAdminTx2); + const changeAdminTx3 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); + await submitTransactionAsync(Alice, changeAdminTx3); + + const addAdmOne = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Ferdie.address)); + const addAdmTwo = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Charlie.address)); + await Promise.all([ + addAdmOne.signAndSend(Bob), + addAdmTwo.signAndSend(Alice), + ]); + await waitNewBlocks(2); + const changeAdminTx4 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Alice.address)); + await expect(submitTransactionExpectFailAsync(Alice, changeAdminTx4)).to.be.rejected; + + const adminListAfterAddAdmin: any = (await api.query.unique.adminList(collectionId)); + expect(adminListAfterAddAdmin).to.be.contains(normalizeAccountId(Eve.address)); + expect(adminListAfterAddAdmin).to.be.contains(normalizeAccountId(Ferdie.address)); + expect(adminListAfterAddAdmin).not.to.be.contains(normalizeAccountId(Alice.address)); + await waitNewBlocks(2); + }); + }); +}); +*/ \ No newline at end of file --- /dev/null +++ b/tests/src/.outdated/collision-tests/adminRightsOff.test.ts @@ -0,0 +1,69 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +/* broken by design +// substrate transactions are sequential, not parallel +// the order of execution is indeterminate + +import { IKeyringPair } from '@polkadot/types/types'; +import BN from 'bn.js'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import privateKey from '../substrate/privateKey'; +import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; +import { + createCollectionExpectSuccess, + normalizeAccountId, + waitNewBlocks, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +let Alice: IKeyringPair; +let Bob: IKeyringPair; + +before(async () => { + await usingApi(async () => { + Alice = privateKey('//Alice'); + Bob = privateKey('//Bob'); + }); +}); + +describe('Deprivation of admin rights: ', () => { + // tslint:disable-next-line: max-line-length + it('In the block, the collection admin adds a token or changes data, and the collection owner deprives the admin of rights ', async () => { + await usingApi(async (api) => { + const collectionId = await createCollectionExpectSuccess(); + const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); + await submitTransactionAsync(Alice, changeAdminTx); + await waitNewBlocks(1); + const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }]; + const addItemAdm = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(Bob.address), args); + const removeAdm = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); + await Promise.all([ + addItemAdm.signAndSend(Bob), + removeAdm.signAndSend(Alice), + ]); + await waitNewBlocks(2); + const itemsListIndex = await api.query.unique.itemListIndex(collectionId) as unknown as BN; + expect(itemsListIndex.toNumber()).to.be.equal(0); + const adminList: any = (await api.query.unique.adminList(collectionId)); + expect(adminList).not.to.be.contains(normalizeAccountId(Bob.address)); + await waitNewBlocks(2); + }); + }); +}); +*/ \ No newline at end of file --- /dev/null +++ b/tests/src/.outdated/collision-tests/setSponsorNewOwner.test.ts @@ -0,0 +1,67 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +/* broken by design +// substrate transactions are sequential, not parallel +// the order of execution is indeterminate + +import { IKeyringPair } from '@polkadot/types/types'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import privateKey from '../substrate/privateKey'; +import usingApi from '../substrate/substrate-api'; +import { + createCollectionExpectSuccess, + setCollectionSponsorExpectSuccess, + waitNewBlocks, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +let Alice: IKeyringPair; +let Bob: IKeyringPair; +let Ferdie: IKeyringPair; + +before(async () => { + await usingApi(async () => { + Alice = privateKey('//Alice'); + Bob = privateKey('//Bob'); + Ferdie = privateKey('//Ferdie'); + }); +}); + +describe('Sponsored with new owner ', () => { + // tslint:disable-next-line: max-line-length + it('Confirmation of sponsorship of a collection in a block with a change in the owner of the collection: ', async () => { + await usingApi(async (api) => { + const collectionId = await createCollectionExpectSuccess(); + await setCollectionSponsorExpectSuccess(collectionId, Bob.address); + await waitNewBlocks(2); + const confirmSponsorship = api.tx.unique.confirmSponsorship(collectionId); + const changeCollectionOwner = api.tx.unique.changeCollectionOwner(collectionId, Ferdie.address); + await Promise.all([ + confirmSponsorship.signAndSend(Bob), + changeCollectionOwner.signAndSend(Alice), + ]); + await waitNewBlocks(2); + const collection: any = (await api.query.unique.collectionById(collectionId)).toJSON(); + expect(collection.sponsorship.confirmed).to.be.eq(Bob.address); + expect(collection.owner).to.be.eq(Ferdie.address); + await waitNewBlocks(2); + }); + }); +}); +*/ \ No newline at end of file --- /dev/null +++ b/tests/src/.outdated/collision-tests/sponsorPayments.test.ts @@ -0,0 +1,76 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +/* broken by design +// substrate transactions are sequential, not parallel +// the order of execution is indeterminate + +import { IKeyringPair } from '@polkadot/types/types'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import { alicesPublicKey, bobsPublicKey } from '../accounts'; +import getBalance from '../substrate/get-balance'; +import privateKey from '../substrate/privateKey'; +import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; +import { + confirmSponsorshipExpectSuccess, + createCollectionExpectSuccess, + createItemExpectSuccess, + setCollectionSponsorExpectSuccess, + normalizeAccountId, + waitNewBlocks, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +let Alice: IKeyringPair; +let Bob: IKeyringPair; + +before(async () => { + await usingApi(async () => { + Alice = privateKey('//Alice'); + Bob = privateKey('//Bob'); + }); +}); + +describe('Payment of commission if one block: ', () => { + // tslint:disable-next-line: max-line-length + it('Payment of commission if one block contains transactions for payment from the sponsor\'s balance and his (sponsor\'s) exclusion from the collection ', async () => { + await usingApi(async (api) => { + const collectionId = await createCollectionExpectSuccess(); + const changeAdminTxBob = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); + await submitTransactionAsync(Alice, changeAdminTxBob); + const itemId = await createItemExpectSuccess(Bob, collectionId, 'NFT'); + await setCollectionSponsorExpectSuccess(collectionId, Bob.address); + await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); + + const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alicesPublicKey, bobsPublicKey]); + const sendItem = api.tx.unique.transfer(normalizeAccountId(Alice.address), collectionId, itemId, 1); + const revokeSponsor = api.tx.unique.removeCollectionSponsor(collectionId); + await Promise.all([ + sendItem.signAndSend(Bob), + revokeSponsor.signAndSend(Alice), + ]); + const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]); + // tslint:disable-next-line:no-unused-expression + expect(alicesBalanceAfter === alicesBalanceBefore).to.be.true; + // tslint:disable-next-line:no-unused-expression + expect(bobsBalanceAfter === bobsBalanceBefore).to.be.true; + await waitNewBlocks(2); + }); + }); +}); +*/ \ No newline at end of file --- /dev/null +++ b/tests/src/.outdated/collision-tests/tokenLimitsOff.test.ts @@ -0,0 +1,100 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +/* broken by design +// substrate transactions are sequential, not parallel +// the order of execution is indeterminate + +import { IKeyringPair } from '@polkadot/types/types'; +import BN from 'bn.js'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import privateKey from '../substrate/privateKey'; +import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; +import { + addToAllowListExpectSuccess, + createCollectionExpectSuccess, + getCreateItemResult, + setMintPermissionExpectSuccess, + normalizeAccountId, + waitNewBlocks, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +let Alice: IKeyringPair; +let Bob: IKeyringPair; +let Ferdie: IKeyringPair; + +const accountTokenOwnershipLimit = 4; +const sponsoredMintSize = 4294967295; +const tokenLimit = 4; +const sponsorTimeout = 14400; +const ownerCanTransfer = false; +const ownerCanDestroy = false; + +before(async () => { + await usingApi(async () => { + Alice = privateKey('//Alice'); + Bob = privateKey('//Bob'); + Ferdie = privateKey('//Ferdie'); + }); +}); + +describe('Token limit exceeded collection: ', () => { + // tslint:disable-next-line: max-line-length + it('The number of tokens created in the collection from different addresses exceeds the allowed collection limit ', async () => { + await usingApi(async (api) => { + const collectionId = await createCollectionExpectSuccess(); + await setMintPermissionExpectSuccess(Alice, collectionId, true); + await addToAllowListExpectSuccess(Alice, collectionId, Ferdie.address); + await addToAllowListExpectSuccess(Alice, collectionId, Bob.address); + const setCollectionLim = api.tx.unique.setCollectionLimits( + collectionId, + { + accountTokenOwnershipLimit, + sponsoredMintSize, + tokenLimit, + // tslint:disable-next-line: object-literal-sort-keys + sponsorTimeout, + ownerCanTransfer, + ownerCanDestroy, + }, + ); + const subTx = await submitTransactionAsync(Alice, setCollectionLim); + const subTxTesult = getCreateItemResult(subTx); + // tslint:disable-next-line:no-unused-expression + expect(subTxTesult.success).to.be.true; + await waitNewBlocks(2); + + const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }]; + const mintItemOne = api.tx.unique + .createMultipleItems(collectionId, normalizeAccountId(Ferdie.address), args); + const mintItemTwo = api.tx.unique + .createMultipleItems(collectionId, normalizeAccountId(Bob.address), args); + await Promise.all([ + mintItemOne.signAndSend(Ferdie), + mintItemTwo.signAndSend(Bob), + ]); + await waitNewBlocks(2); + const itemsListIndexAfter = await api.query.unique.itemListIndex(collectionId) as unknown as BN; + expect(itemsListIndexAfter.toNumber()).to.be.equal(3); + // TokenLimit = 4. The first transaction is successful. The second should fail. + await waitNewBlocks(2); + }); + }); +}); +*/ --- /dev/null +++ b/tests/src/.outdated/collision-tests/turnsOffMinting.test.ts @@ -0,0 +1,68 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +/* broken by design +// substrate transactions are sequential, not parallel +// the order of execution is indeterminate + +import { IKeyringPair } from '@polkadot/types/types'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import privateKey from '../substrate/privateKey'; +import usingApi from '../substrate/substrate-api'; +import { + addToAllowListExpectSuccess, + createCollectionExpectSuccess, + setMintPermissionExpectSuccess, + normalizeAccountId, + waitNewBlocks, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; +let Alice: IKeyringPair; +let Ferdie: IKeyringPair; + +before(async () => { + await usingApi(async () => { + Alice = privateKey('//Alice'); + Ferdie = privateKey('//Ferdie'); + }); +}); + +describe('Turns off minting mode: ', () => { + // tslint:disable-next-line: max-line-length + it('The collection owner turns off minting mode and there are minting transactions in the same block ', async () => { + await usingApi(async (api) => { + const collectionId = await createCollectionExpectSuccess(); + await setMintPermissionExpectSuccess(Alice, collectionId, true); + await addToAllowListExpectSuccess(Alice, collectionId, Ferdie.address); + + const mintItem = api.tx.unique.createItem(collectionId, normalizeAccountId(Ferdie.address), 'NFT'); + const offMinting = api.tx.unique.setMintPermission(collectionId, false); + await Promise.all([ + mintItem.signAndSend(Ferdie), + offMinting.signAndSend(Alice), + ]); + let itemList = false; + itemList = (await (api.query.unique.nftItemList(collectionId, mintItem))).toJSON() as boolean; + // tslint:disable-next-line: no-unused-expression + expect(itemList).to.be.null; + await waitNewBlocks(2); + }); + }); +}); +*/ \ No newline at end of file --- /dev/null +++ b/tests/src/.outdated/contracts.test.ts @@ -0,0 +1,240 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import usingApi, {submitTransactionAsync} from '../substrate/substrate-api'; +import fs from 'fs'; +import {Abi, ContractPromise as Contract} from '@polkadot/api-contract'; +import { + deployFlipper, + getFlipValue, + deployTransferContract, +} from '../util/contracthelpers'; + +import { + addToAllowListExpectSuccess, + approveExpectSuccess, + createCollectionExpectSuccess, + createItemExpectSuccess, + enablePublicMintingExpectSuccess, + enableAllowListExpectSuccess, + getGenericResult, + normalizeAccountId, + isAllowlisted, + transferFromExpectSuccess, + getTokenOwner, +} from '../util/helpers'; + + +chai.use(chaiAsPromised); +const expect = chai.expect; + +const value = 0; +const gasLimit = 9000n * 1000000n; +const marketContractAddress = '5CYN9j3YvRkqxewoxeSvRbhAym4465C57uMmX5j4yz99L5H6'; + +// todo:playgrounds skipped ~ postponed +describe.skip('Contracts', () => { + it('Can deploy smart contract Flipper, instantiate it and call it\'s get and flip messages.', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const [contract, deployer] = await deployFlipper(api, privateKeyWrapper); + const initialGetResponse = await getFlipValue(contract, deployer); + + const bob = privateKeyWrapper('//Bob'); + const flip = contract.tx.flip({value, gasLimit}); + await submitTransactionAsync(bob, flip); + + const afterFlipGetResponse = await getFlipValue(contract, deployer); + expect(afterFlipGetResponse).not.to.be.eq(initialGetResponse, 'Flipping should change value.'); + }); + }); + + it('Can initialize contract instance', async () => { + await usingApi(async (api) => { + const metadata = JSON.parse(fs.readFileSync('./src/flipper/metadata.json').toString('utf-8')); + const abi = new Abi(metadata); + const newContractInstance = new Contract(api, abi, marketContractAddress); + expect(newContractInstance).to.have.property('address'); + expect(newContractInstance.address.toString()).to.equal(marketContractAddress); + }); + }); +}); + +describe.skip('Chain extensions', () => { + it('Transfer CE', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const alice = privateKeyWrapper('//Alice'); + const bob = privateKeyWrapper('//Bob'); + + // Prep work + const collectionId = await createCollectionExpectSuccess(); + const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT'); + const [contract] = await deployTransferContract(api, privateKeyWrapper); + const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, contract.address); + await submitTransactionAsync(alice, changeAdminTx); + + expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address)); + + // Transfer + const transferTx = contract.tx.transfer({value, gasLimit}, bob.address, collectionId, tokenId, 1); + const events = await submitTransactionAsync(alice, transferTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(bob.address)); + }); + }); + + it('Mint CE', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const alice = privateKeyWrapper('//Alice'); + const bob = privateKeyWrapper('//Bob'); + + const collectionId = await createCollectionExpectSuccess(); + const [contract] = await deployTransferContract(api, privateKeyWrapper); + await enablePublicMintingExpectSuccess(alice, collectionId); + await enableAllowListExpectSuccess(alice, collectionId); + await addToAllowListExpectSuccess(alice, collectionId, contract.address); + await addToAllowListExpectSuccess(alice, collectionId, bob.address); + + const transferTx = contract.tx.createItem({value, gasLimit}, bob.address, collectionId, {Nft: {const_data: '0x010203'}}); + const events = await submitTransactionAsync(alice, transferTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + const tokensAfter = (await api.query.unique.nftItemList.entries(collectionId)).map((kv: any) => kv[1].toJSON()); + expect(tokensAfter).to.be.deep.equal([ + { + owner: bob.address, + constData: '0x010203', + }, + ]); + }); + }); + + it('Bulk mint CE', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const alice = privateKeyWrapper('//Alice'); + const bob = privateKeyWrapper('//Bob'); + + const collectionId = await createCollectionExpectSuccess(); + const [contract] = await deployTransferContract(api, privateKeyWrapper); + await enablePublicMintingExpectSuccess(alice, collectionId); + await enableAllowListExpectSuccess(alice, collectionId); + await addToAllowListExpectSuccess(alice, collectionId, contract.address); + await addToAllowListExpectSuccess(alice, collectionId, bob.address); + + const transferTx = contract.tx.createMultipleItems({value, gasLimit}, bob.address, collectionId, [ + {NFT: {/*const_data: '0x010203'*/}}, + {NFT: {/*const_data: '0x010204'*/}}, + {NFT: {/*const_data: '0x010205'*/}}, + ]); + const events = await submitTransactionAsync(alice, transferTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + const tokensAfter: any = (await api.query.unique.nftItemList.entries(collectionId) as any) + .map((kv: any) => kv[1].toJSON()) + .sort((a: any, b: any) => a.constData.localeCompare(b.constData)); + expect(tokensAfter).to.be.deep.equal([ + { + Owner: bob.address, + //ConstData: '0x010203', + }, + { + Owner: bob.address, + //ConstData: '0x010204', + }, + { + Owner: bob.address, + //ConstData: '0x010205', + }, + ]); + }); + }); + + it('Approve CE', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const alice = privateKeyWrapper('//Alice'); + const bob = privateKeyWrapper('//Bob'); + const charlie = privateKeyWrapper('//Charlie'); + + const collectionId = await createCollectionExpectSuccess(); + const [contract] = await deployTransferContract(api, privateKeyWrapper); + const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', contract.address.toString()); + + const transferTx = contract.tx.approve({value, gasLimit}, bob.address, collectionId, tokenId, 1); + const events = await submitTransactionAsync(alice, transferTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + await transferFromExpectSuccess(collectionId, tokenId, bob, normalizeAccountId(contract.address.toString()), charlie, 1, 'NFT'); + }); + }); + + it('TransferFrom CE', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const alice = privateKeyWrapper('//Alice'); + const bob = privateKeyWrapper('//Bob'); + const charlie = privateKeyWrapper('//Charlie'); + + const collectionId = await createCollectionExpectSuccess(); + const [contract] = await deployTransferContract(api, privateKeyWrapper); + const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address); + await approveExpectSuccess(collectionId, tokenId, bob, contract.address.toString(), 1); + + const transferTx = contract.tx.transferFrom({value, gasLimit}, bob.address, charlie.address, collectionId, tokenId, 1); + const events = await submitTransactionAsync(alice, transferTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + const token: any = (await api.query.unique.nftItemList(collectionId, tokenId) as any).unwrap(); + expect(token.owner.toString()).to.be.equal(charlie.address); + }); + }); + + it('ToggleAllowList CE', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const alice = privateKeyWrapper('//Alice'); + const bob = privateKeyWrapper('//Bob'); + + const collectionId = await createCollectionExpectSuccess(); + const [contract] = await deployTransferContract(api, privateKeyWrapper); + const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, contract.address); + await submitTransactionAsync(alice, changeAdminTx); + + expect(await isAllowlisted(api, collectionId, bob.address)).to.be.false; + + { + const transferTx = contract.tx.toggleAllowList({value, gasLimit}, collectionId, bob.address, true); + const events = await submitTransactionAsync(alice, transferTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + expect(await isAllowlisted(api, collectionId, bob.address)).to.be.true; + } + { + const transferTx = contract.tx.toggleAllowList({value, gasLimit}, collectionId, bob.address, false); + const events = await submitTransactionAsync(alice, transferTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + + expect(await isAllowlisted(api, collectionId, bob.address)).to.be.false; + } + }); + }); +}); --- /dev/null +++ b/tests/src/.outdated/enableContractSponsoring.test.ts @@ -0,0 +1,102 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import {IKeyringPair} from '@polkadot/types/types'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import usingApi from '../substrate/substrate-api'; +import {deployFlipper, getFlipValue, toggleFlipValueExpectSuccess} from '../util/contracthelpers'; +import { + enableContractSponsoringExpectFailure, + enableContractSponsoringExpectSuccess, + findUnusedAddress, + setContractSponsoringRateLimitExpectSuccess, +} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + +// todo:playgrounds skipped ~ postponed +describe.skip('Integration Test enableContractSponsoring', () => { + it('ensure tx fee is paid from endowment', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const user = await findUnusedAddress(api, privateKeyWrapper); + + const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); + await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); + await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 1); + await toggleFlipValueExpectSuccess(user, flipper); + + expect(await getFlipValue(flipper, deployer)).to.be.false; + }); + }); + + it('ensure it can be enabled twice', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); + + await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); + await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); + }); + }); + + it('ensure it can be disabled twice', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); + + await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); + await enableContractSponsoringExpectSuccess(deployer, flipper.address, false); + await enableContractSponsoringExpectSuccess(deployer, flipper.address, false); + }); + }); + + it('ensure it can be re-enabled', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); + + await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); + await enableContractSponsoringExpectSuccess(deployer, flipper.address, false); + await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); + }); + }); + +}); + +describe.skip('Negative Integration Test enableContractSponsoring', () => { + let alice: IKeyringPair; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + }); + }); + + it('fails when called for non-contract address', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const user = await findUnusedAddress(api, privateKeyWrapper); + + await enableContractSponsoringExpectFailure(alice, user.address, true); + }); + }); + + it('fails when called by non-owning user', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const [flipper] = await deployFlipper(api, privateKeyWrapper); + + await enableContractSponsoringExpectFailure(alice, flipper.address, true); + }); + }); +}); --- /dev/null +++ b/tests/src/.outdated/inflation.test.ts @@ -0,0 +1,58 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import {IKeyringPair} from '@polkadot/types/types'; +import {expect, itSub, usingPlaygrounds} from '../util/playgrounds'; + +// todo:playgrounds requires sudo, look into on the later stage +describe('integration test: Inflation', () => { + let superuser: IKeyringPair; + + before(async () => { + await usingPlaygrounds(async (_, privateKey) => { + superuser = privateKey('//Alice'); + }); + }); + + itSub('First year inflation is 10%', async ({helper}) => { + // Make sure non-sudo can't start inflation + const [bob] = await helper.arrange.createAccounts([10n], superuser); + + await expect(helper.executeExtrinsic(bob, 'api.tx.inflation.startInflation', [1])).to.be.rejectedWith(/BadOrigin/); + + // Make sure superuser can't start inflation without explicit sudo + await expect(helper.executeExtrinsic(superuser, 'api.tx.inflation.startInflation', [1])).to.be.rejectedWith(/BadOrigin/); + + // Start inflation on relay block 1 (Alice is sudo) + const tx = helper.constructApiCall('api.tx.inflation.startInflation', [1]); + await expect(helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [tx])).to.not.be.rejected; + + const blockInterval = (helper.api!.consts.inflation.inflationBlockInterval as any).toBigInt(); + const totalIssuanceStart = ((await helper.api!.query.inflation.startingYearTotalIssuance()) as any).toBigInt(); + const blockInflation = (await helper.api!.query.inflation.blockInflation() as any).toBigInt(); + + const YEAR = 5259600n; // 6-second block. Blocks in one year + // const YEAR = 2629800n; // 12-second block. Blocks in one year + + const totalExpectedInflation = totalIssuanceStart / 10n; + const totalActualInflation = blockInflation * YEAR / blockInterval; + + const tolerance = 0.00001; // Relative difference per year between theoretical and actual inflation + const expectedInflation = totalExpectedInflation / totalActualInflation - 1n; + + expect(Math.abs(Number(expectedInflation))).to.be.lessThanOrEqual(tolerance); + }); +}); --- /dev/null +++ b/tests/src/.outdated/overflow.test.ts @@ -0,0 +1,73 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import {IKeyringPair} from '@polkadot/types/types'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import usingApi from '../substrate/substrate-api'; +import {approveExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, getAllowance, getBalance, transferExpectFailure, transferExpectSuccess, transferFromExpectFail, transferFromExpectSuccess, U128_MAX} from '../util/helpers'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + +// todo:playgrounds skipped ~ postponed +describe.skip('Integration Test fungible overflows', () => { + let alice: IKeyringPair; + let bob: IKeyringPair; + let charlie: IKeyringPair; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + bob = privateKeyWrapper('//Bob'); + charlie = privateKeyWrapper('//Charlie'); + }); + }); + + it('fails when overflows on transfer', async () => { + await usingApi(async api => { + const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); + + await createFungibleItemExpectSuccess(alice, fungibleCollectionId, {Value: U128_MAX}); + await transferExpectSuccess(fungibleCollectionId, 0, alice, bob, U128_MAX, 'Fungible'); + + await createFungibleItemExpectSuccess(alice, fungibleCollectionId, {Value: 1n}); + await transferExpectFailure(fungibleCollectionId, 0, alice, bob, 1); + + expect(await getBalance(api, fungibleCollectionId, alice.address, 0)).to.equal(1n); + expect(await getBalance(api, fungibleCollectionId, bob.address, 0)).to.equal(U128_MAX); + }); + }); + + it('fails when overflows on transferFrom', async () => { + await usingApi(async api => { + const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); + await createFungibleItemExpectSuccess(alice, fungibleCollectionId, {Value: U128_MAX}); + await approveExpectSuccess(fungibleCollectionId, 0, alice, bob.address, U128_MAX); + await transferFromExpectSuccess(fungibleCollectionId, 0, bob, alice, charlie, U128_MAX, 'Fungible'); + + expect(await getBalance(api, fungibleCollectionId, charlie.address, 0)).to.equal(U128_MAX); + expect(await getAllowance(api, fungibleCollectionId, alice.address, bob.address, 0)).to.equal(0n); + + await createFungibleItemExpectSuccess(alice, fungibleCollectionId, {Value: U128_MAX}); + await approveExpectSuccess(fungibleCollectionId, 0, alice, bob.address, 1n); + await transferFromExpectFail(fungibleCollectionId, 0, bob, alice, charlie, 1); + + expect(await getBalance(api, fungibleCollectionId, charlie.address, 0)).to.equal(U128_MAX); + expect(await getAllowance(api, fungibleCollectionId, alice.address, bob.address, 0)).to.equal(1n); + }); + }); +}); --- /dev/null +++ b/tests/src/.outdated/removeFromContractAllowList.test.ts @@ -0,0 +1,92 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import usingApi from '../substrate/substrate-api'; +import {deployFlipper, toggleFlipValueExpectFailure, toggleFlipValueExpectSuccess} from '../util/contracthelpers'; +import {addToContractAllowListExpectSuccess, isAllowlistedInContract, removeFromContractAllowListExpectFailure, removeFromContractAllowListExpectSuccess, toggleContractAllowlistExpectSuccess} from '../util/helpers'; +import {IKeyringPair} from '@polkadot/types/types'; +import {expect} from 'chai'; + +// todo:playgrounds skipped again +describe.skip('Integration Test removeFromContractAllowList', () => { + let bob: IKeyringPair; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + bob = privateKeyWrapper('//Bob'); + }); + }); + + it('user is no longer allowlisted after removal', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); + + await addToContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); + await removeFromContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); + + expect(await isAllowlistedInContract(flipper.address, bob.address)).to.be.false; + }); + }); + + it('user can\'t execute contract after removal', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); + await toggleContractAllowlistExpectSuccess(deployer, flipper.address.toString(), true); + + await addToContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); + await toggleFlipValueExpectSuccess(bob, flipper); + + await removeFromContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); + await toggleFlipValueExpectFailure(bob, flipper); + }); + }); + + it('can be called twice', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); + + await addToContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); + await removeFromContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); + await removeFromContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); + }); + }); +}); + +describe.skip('Negative Integration Test removeFromContractAllowList', () => { + let alice: IKeyringPair; + let bob: IKeyringPair; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + bob = privateKeyWrapper('//Bob'); + }); + }); + + it('fails when called with non-contract address', async () => { + await usingApi(async () => { + await removeFromContractAllowListExpectFailure(alice, alice.address, bob.address); + }); + }); + + it('fails when executed by non owner', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const [flipper] = await deployFlipper(api, privateKeyWrapper); + + await removeFromContractAllowListExpectFailure(alice, flipper.address.toString(), bob.address); + }); + }); +}); --- /dev/null +++ b/tests/src/.outdated/scheduler.test.ts @@ -0,0 +1,210 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import chai, {expect} from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import { + default as usingApi, + submitTransactionAsync, +} from '../substrate/substrate-api'; +import { + createItemExpectSuccess, + createCollectionExpectSuccess, + scheduleTransferExpectSuccess, + scheduleTransferAndWaitExpectSuccess, + setCollectionSponsorExpectSuccess, + confirmSponsorshipExpectSuccess, + findUnusedAddress, + UNIQUE, + enablePublicMintingExpectSuccess, + addToAllowListExpectSuccess, + waitNewBlocks, + normalizeAccountId, + getTokenOwner, + getGenericResult, + scheduleTransferFundsPeriodicExpectSuccess, + getFreeBalance, + confirmSponsorshipByKeyExpectSuccess, + scheduleExpectFailure, +} from '../util/helpers'; +import {IKeyringPair} from '@polkadot/types/types'; + +chai.use(chaiAsPromised); + +// todo:playgrounds skipped ~ postponed +describe.skip('Scheduling token and balance transfers', () => { + let alice: IKeyringPair; + let bob: IKeyringPair; + let scheduledIdBase: string; + let scheduledIdSlider: number; + + before(async() => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + bob = privateKeyWrapper('//Bob'); + }); + + scheduledIdBase = '0x' + '0'.repeat(31); + scheduledIdSlider = 0; + }); + + // Loop scheduledId around 10. Unless there are concurrent tasks with long periods/repetitions, tests' tasks' ids shouldn't ovelap. + function makeScheduledId(): string { + return scheduledIdBase + ((scheduledIdSlider++) % 10); + } + + it('Can schedule a transfer of an owned token with delay', async () => { + await usingApi(async () => { + const nftCollectionId = await createCollectionExpectSuccess(); + const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); + await setCollectionSponsorExpectSuccess(nftCollectionId, alice.address); + await confirmSponsorshipExpectSuccess(nftCollectionId); + + await scheduleTransferAndWaitExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 4, makeScheduledId()); + }); + }); + + it('Can transfer funds periodically', async () => { + await usingApi(async () => { + const waitForBlocks = 4; + const period = 2; + await scheduleTransferFundsPeriodicExpectSuccess(1n * UNIQUE, alice, bob, waitForBlocks, makeScheduledId(), period, 2); + const bobsBalanceBefore = await getFreeBalance(bob); + + // discounting already waited-for operations + await waitNewBlocks(waitForBlocks - 2); + const bobsBalanceAfterFirst = await getFreeBalance(bob); + expect(bobsBalanceAfterFirst > bobsBalanceBefore).to.be.true; + + await waitNewBlocks(period); + const bobsBalanceAfterSecond = await getFreeBalance(bob); + expect(bobsBalanceAfterSecond > bobsBalanceAfterFirst).to.be.true; + }); + }); + + it('Can sponsor scheduling a transaction', async () => { + const collectionId = await createCollectionExpectSuccess(); + await setCollectionSponsorExpectSuccess(collectionId, bob.address); + await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); + + await usingApi(async () => { + const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address); + + const bobBalanceBefore = await getFreeBalance(bob); + const waitForBlocks = 4; + // no need to wait to check, fees must be deducted on scheduling, immediately + await scheduleTransferExpectSuccess(collectionId, tokenId, alice, bob, 0, waitForBlocks, makeScheduledId()); + const bobBalanceAfter = await getFreeBalance(bob); + // expect(aliceBalanceAfter == aliceBalanceBefore).to.be.true; + expect(bobBalanceAfter < bobBalanceBefore).to.be.true; + // wait for sequentiality matters + await waitNewBlocks(waitForBlocks - 1); + }); + }); + + it('Schedules and dispatches a transaction even if the caller has no funds at the time of the dispatch', async () => { + await usingApi(async (api, privateKeyWrapper) => { + // Find an empty, unused account + const zeroBalance = await findUnusedAddress(api, privateKeyWrapper); + + const collectionId = await createCollectionExpectSuccess(); + + // Add zeroBalance address to allow list + await enablePublicMintingExpectSuccess(alice, collectionId); + await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address); + + // Grace zeroBalance with money, enough to cover future transactions + const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE); + await submitTransactionAsync(alice, balanceTx); + + // Mint a fresh NFT + const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT'); + + // Schedule transfer of the NFT a few blocks ahead + const waitForBlocks = 5; + await scheduleTransferExpectSuccess(collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks, makeScheduledId()); + + // Get rid of the account's funds before the scheduled transaction takes place + const balanceTx2 = api.tx.balances.transfer(alice.address, UNIQUE * 68n / 100n); + const events = await submitTransactionAsync(zeroBalance, balanceTx2); + expect(getGenericResult(events).success).to.be.true; + /*const emptyBalanceTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0); // do not null reserved? + const sudoTx = api.tx.sudo.sudo(emptyBalanceTx as any); + const events = await submitTransactionAsync(alice, sudoTx); + expect(getGenericResult(events).success).to.be.true;*/ + + // Wait for a certain number of blocks, discarding the ones that already happened while accepting the late transactions + await waitNewBlocks(waitForBlocks - 3); + + expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address)); + }); + }); + + it('Sponsor going bankrupt does not impact a scheduled transaction', async () => { + const collectionId = await createCollectionExpectSuccess(); + + await usingApi(async (api, privateKeyWrapper) => { + const zeroBalance = await findUnusedAddress(api, privateKeyWrapper); + const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE); + await submitTransactionAsync(alice, balanceTx); + + await setCollectionSponsorExpectSuccess(collectionId, zeroBalance.address); + await confirmSponsorshipByKeyExpectSuccess(collectionId, zeroBalance); + + const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address); + + const waitForBlocks = 5; + await scheduleTransferExpectSuccess(collectionId, tokenId, alice, zeroBalance, 1, waitForBlocks, makeScheduledId()); + + const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0); + const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any); + const events = await submitTransactionAsync(alice, sudoTx); + expect(getGenericResult(events).success).to.be.true; + + // Wait for a certain number of blocks, save for the ones that already happened while accepting the late transactions + await waitNewBlocks(waitForBlocks - 3); + + expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(zeroBalance.address)); + }); + }); + + it.skip('Exceeding sponsor rate limit without having enough funds prevents scheduling a periodic transaction', async () => { + const collectionId = await createCollectionExpectSuccess(); + await setCollectionSponsorExpectSuccess(collectionId, bob.address); + await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); + + await usingApi(async (api, privateKeyWrapper) => { + const zeroBalance = await findUnusedAddress(api, privateKeyWrapper); + + await enablePublicMintingExpectSuccess(alice, collectionId); + await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address); + + const bobBalanceBefore = await getFreeBalance(bob); + + const createData = {nft: {const_data: [], variable_data: []}}; + const creationTx = api.tx.unique.createItem(collectionId, normalizeAccountId(zeroBalance), createData as any); + + /*const badTransaction = async function () { + await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice); + }; + await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');*/ + + await scheduleExpectFailure(creationTx, zeroBalance, 3, makeScheduledId(), 1, 3); + + expect(await getFreeBalance(bob)).to.be.equal(bobBalanceBefore); + }); + }); +}); --- /dev/null +++ b/tests/src/.outdated/setChainLimits.test.ts @@ -0,0 +1,64 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import {IKeyringPair} from '@polkadot/types/types'; +import usingApi from '../substrate/substrate-api'; +import { + createCollectionExpectSuccess, + addCollectionAdminExpectSuccess, + setChainLimitsExpectFailure, + IChainLimits, +} from '../util/helpers'; + +// todo:playgrounds skipped ~ postponed +describe.skip('Negative Integration Test setChainLimits', () => { + let alice: IKeyringPair; + let bob: IKeyringPair; + let dave: IKeyringPair; + let limits: IChainLimits; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + bob = privateKeyWrapper('//Bob'); + dave = privateKeyWrapper('//Dave'); + limits = { + collectionNumbersLimit : 1, + accountTokenOwnershipLimit: 1, + collectionsAdminsLimit: 1, + customDataLimit: 1, + nftSponsorTransferTimeout: 1, + fungibleSponsorTransferTimeout: 1, + refungibleSponsorTransferTimeout: 1, + }; + }); + }); + + it('Collection owner cannot set chain limits', async () => { + await createCollectionExpectSuccess({mode: {type: 'NFT'}}); + await setChainLimitsExpectFailure(alice, limits); + }); + + it('Collection admin cannot set chain limits', async () => { + const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); + await addCollectionAdminExpectSuccess(alice, collectionId, bob.address); + await setChainLimitsExpectFailure(bob, limits); + }); + + it('Regular user cannot set chain limits', async () => { + await setChainLimitsExpectFailure(dave, limits); + }); +}); --- /dev/null +++ b/tests/src/.outdated/setContractSponsoringRateLimit.test.ts @@ -0,0 +1,80 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import {IKeyringPair} from '@polkadot/types/types'; +import usingApi from '../substrate/substrate-api'; +import waitNewBlocks from '../substrate/wait-new-blocks'; +import {deployFlipper, toggleFlipValueExpectFailure, toggleFlipValueExpectSuccess} from '../util/contracthelpers'; +import { + enableContractSponsoringExpectSuccess, + findUnusedAddress, + setContractSponsoringRateLimitExpectFailure, + setContractSponsoringRateLimitExpectSuccess, +} from '../util/helpers'; + +// todo:playgrounds skipped~postponed test +describe.skip('Integration Test setContractSponsoringRateLimit', () => { + it('ensure sponsored contract can\'t be called twice without pause for free', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const user = await findUnusedAddress(api, privateKeyWrapper); + + const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); + await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); + await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 10); + await toggleFlipValueExpectSuccess(user, flipper); + await toggleFlipValueExpectFailure(user, flipper); + }); + }); + + it('ensure sponsored contract can be called twice with pause for free', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const user = await findUnusedAddress(api, privateKeyWrapper); + + const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); + await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); + await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 1); + await toggleFlipValueExpectSuccess(user, flipper); + await waitNewBlocks(api, 1); + await toggleFlipValueExpectSuccess(user, flipper); + }); + }); +}); + +describe.skip('Negative Integration Test setContractSponsoringRateLimit', () => { + let alice: IKeyringPair; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + }); + }); + + it('fails when called for non-contract address', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const user = await findUnusedAddress(api, privateKeyWrapper); + + await setContractSponsoringRateLimitExpectFailure(alice, user.address, 1); + }); + }); + + it('fails when called by non-owning user', async () => { + await usingApi(async (api, privateKeyWrapper) => { + const [flipper] = await deployFlipper(api, privateKeyWrapper); + + await setContractSponsoringRateLimitExpectFailure(alice, flipper.address, 1); + }); + }); +}); --- /dev/null +++ b/tests/src/.outdated/xcmTransfer.test.ts @@ -0,0 +1,187 @@ +// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. +// This file is part of Unique Network. + +// Unique Network is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Unique Network is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Unique Network. If not, see . + +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; + +import {WsProvider} from '@polkadot/api'; +import {ApiOptions} from '@polkadot/api/types'; +import {IKeyringPair} from '@polkadot/types/types'; +import usingApi, {submitTransactionAsync} from '../substrate/substrate-api'; +import {getGenericResult} from '../util/helpers'; +import waitNewBlocks from '../substrate/wait-new-blocks'; +import getBalance from '../substrate/get-balance'; + +chai.use(chaiAsPromised); +const expect = chai.expect; + +const UNIQUE_CHAIN = 1000; +const KARURA_CHAIN = 2000; +const KARURA_PORT = '9946'; +const TRANSFER_AMOUNT = 2000000000000000000000000n; + +// todo:playgrounds refit when XCM drops +describe.skip('Integration test: Exchanging QTZ with Karura', () => { + let alice: IKeyringPair; + + before(async () => { + await usingApi(async (api, privateKeyWrapper) => { + alice = privateKeyWrapper('//Alice'); + }); + + const karuraApiOptions: ApiOptions = { + provider: new WsProvider('ws://127.0.0.1:' + KARURA_PORT), + }; + + await usingApi(async (api) => { + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: UNIQUE_CHAIN, + }, + ], + }, + }; + + const metadata = + { + name: 'QTZ', + symbol: 'QTZ', + decimals: 18, + minimalBalance: 1, + }; + + const tx = api.tx.assetRegistry.registerForeignAsset(destination, metadata); + const sudoTx = api.tx.sudo.sudo(tx as any); + const events = await submitTransactionAsync(alice, sudoTx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + }, karuraApiOptions); + }); + + it('Should connect and send QTZ to Karura', async () => { + let balanceOnKaruraBefore: bigint; + + await usingApi(async (api) => { + const {free} = (await api.query.tokens.accounts(alice.addressRaw, {ForeignAssetId: 0})).toJSON() as any; + balanceOnKaruraBefore = free; + }, {provider: new WsProvider('ws://127.0.0.1:' + KARURA_PORT)}); + + await usingApi(async (api) => { + const destination = { + V0: { + X2: [ + 'Parent', + { + Parachain: KARURA_CHAIN, + }, + ], + }, + }; + + const beneficiary = { + V0: { + X1: { + AccountId32: { + network: 'Any', + id: alice.addressRaw, + }, + }, + }, + }; + + const assets = { + V1: [ + { + id: { + Concrete: { + parents: 0, + interior: 'Here', + }, + }, + fun: { + Fungible: TRANSFER_AMOUNT, + }, + }, + ], + }; + + const feeAssetItem = 0; + + const weightLimit = { + Limited: 5000000000, + }; + + const tx = api.tx.polkadotXcm.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); + const events = await submitTransactionAsync(alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + }); + + await usingApi(async (api) => { + // todo do something about instant sealing, where there might not be any new blocks + await waitNewBlocks(api, 3); + const {free} = (await api.query.tokens.accounts(alice.addressRaw, {ForeignAssetId: 0})).toJSON() as any; + expect(free > balanceOnKaruraBefore).to.be.true; + }, {provider: new WsProvider('ws://127.0.0.1:' + KARURA_PORT)}); + }); + + it('Should connect to Karura and send QTZ back', async () => { + let balanceBefore: bigint; + + await usingApi(async (api) => { + [balanceBefore] = await getBalance(api, [alice.address]); + }); + + await usingApi(async (api) => { + const destination = { + V1: { + parents: 1, + interior: { + X2: [ + {Parachain: UNIQUE_CHAIN}, + {AccountId32: { + network: 'Any', + id: alice.addressRaw, + }}, + ], + }, + }, + }; + + const id = { + ForeignAssetId: 0, + }; + + const amount = TRANSFER_AMOUNT; + const destWeight = 50000000; + + const tx = api.tx.xTokens.transfer(id, amount, destination, destWeight); + const events = await submitTransactionAsync(alice, tx); + const result = getGenericResult(events); + expect(result.success).to.be.true; + }, {provider: new WsProvider('ws://127.0.0.1:' + KARURA_PORT)}); + + await usingApi(async (api) => { + // todo do something about instant sealing, where there might not be any new blocks + await waitNewBlocks(api, 3); + const [balanceAfter] = await getBalance(api, [alice.address]); + expect(balanceAfter > balanceBefore).to.be.true; + }); + }); +}); --- a/tests/src/addToContractAllowList.test.ts +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import usingApi, {submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api'; -import { - deployFlipper, -} from './util/contracthelpers'; -import { - getGenericResult, -} from './util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; - -// todo:playgrounds skipped ~ postponed -describe.skip('Integration Test addToContractAllowList', () => { - - it('Add an address to a contract allow list', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const bob = privateKeyWrapper('//Bob'); - const [contract, deployer] = await deployFlipper(api, privateKeyWrapper); - - const allowListedBefore = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); - const addTx = api.tx.unique.addToContractAllowList(contract.address, bob.address); - const addEvents = await submitTransactionAsync(deployer, addTx); - const allowListedAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); - - expect(getGenericResult(addEvents).success).to.be.true; - expect(allowListedBefore).to.be.false; - expect(allowListedAfter).to.be.true; - }); - }); - - it('Adding same address to allow list repeatedly should not produce errors', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const bob = privateKeyWrapper('//Bob'); - const [contract, deployer] = await deployFlipper(api, privateKeyWrapper); - - const allowListedBefore = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); - const addTx = api.tx.unique.addToContractAllowList(contract.address, bob.address); - const addEvents = await submitTransactionAsync(deployer, addTx); - const allowListedAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); - const addAgainEvents = await submitTransactionAsync(deployer, addTx); - const allowListedAgainAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); - - expect(getGenericResult(addEvents).success).to.be.true; - expect(allowListedBefore).to.be.false; - expect(allowListedAfter).to.be.true; - expect(getGenericResult(addAgainEvents).success).to.be.true; - expect(allowListedAgainAfter).to.be.true; - }); - }); -}); - -describe.skip('Negative Integration Test addToContractAllowList', () => { - - it('Add an address to a allow list of a non-contract', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const alice = privateKeyWrapper('//Bob'); - const bob = privateKeyWrapper('//Bob'); - const charlieGuineaPig = privateKeyWrapper('//Charlie'); - - const allowListedBefore = (await api.query.unique.contractAllowList(charlieGuineaPig.address, bob.address)).toJSON(); - const addTx = api.tx.unique.addToContractAllowList(charlieGuineaPig.address, bob.address); - await expect(submitTransactionExpectFailAsync(alice, addTx)).to.be.rejected; - const allowListedAfter = (await api.query.unique.contractAllowList(charlieGuineaPig.address, bob.address)).toJSON(); - - expect(allowListedBefore).to.be.false; - expect(allowListedAfter).to.be.false; - }); - }); - - it('Add to a contract allow list using a non-owner address', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const bob = privateKeyWrapper('//Bob'); - const [contract] = await deployFlipper(api, privateKeyWrapper); - - const allowListedBefore = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); - const addTx = api.tx.unique.addToContractAllowList(contract.address, bob.address); - await expect(submitTransactionExpectFailAsync(bob, addTx)).to.be.rejected; - const allowListedAfter = (await api.query.unique.contractAllowList(contract.address, bob.address)).toJSON(); - - expect(allowListedBefore).to.be.false; - expect(allowListedAfter).to.be.false; - }); - }); - -}); --- a/tests/src/collision-tests/admVsOwnerChanges.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -/* broken by design -// substrate transactions are sequential, not parallel -// the order of execution is indeterminate - -import { IKeyringPair } from '@polkadot/types/types'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import privateKey from '../substrate/privateKey'; -import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; -import { - createCollectionExpectSuccess, - createItemExpectSuccess, - normalizeAccountId, - waitNewBlocks, -} from '../util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; -let Alice: IKeyringPair; -let Bob: IKeyringPair; -let Ferdie: IKeyringPair; - -before(async () => { - await usingApi(async () => { - Alice = privateKey('//Alice'); - Bob = privateKey('//Bob'); - Ferdie = privateKey('//Ferdie'); - }); -}); - -describe('Admin vs Owner changes token: ', () => { - // tslint:disable-next-line: max-line-length - it('The collection admin changes the owner of the token and in the same block the current owner transfers the token to another address ', async () => { - - await usingApi(async (api) => { - const collectionId = await createCollectionExpectSuccess(); - const changeAdminTxBob = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); - await submitTransactionAsync(Alice, changeAdminTxBob); - const changeAdminTxFerdie = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Ferdie.address)); - await submitTransactionAsync(Bob, changeAdminTxFerdie); - const itemId = await createItemExpectSuccess(Ferdie, collectionId, 'NFT'); - - const changeOwner = api.tx.unique.transferFrom(normalizeAccountId(Ferdie.address), normalizeAccountId(Bob.address), collectionId, itemId, 1); - const approve = api.tx.unique.approve(normalizeAccountId(Bob.address), collectionId, itemId, 1); - const sendItem = api.tx.unique.transfer(normalizeAccountId(Alice.address), collectionId, itemId, 1); - await Promise.all([ - changeOwner.signAndSend(Alice), - approve.signAndSend(Bob), - sendItem.signAndSend(Ferdie), - ]); - const itemBefore: any = await api.query.unique.nftItemList(collectionId, itemId); - expect(itemBefore.owner).not.to.be.eq(Bob.address); - await waitNewBlocks(2); - }); - }); -}); -*/ \ No newline at end of file --- a/tests/src/collision-tests/admVsOwnerData.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -/* broken by design -// substrate transactions are sequential, not parallel -// the order of execution is indeterminate - -import { IKeyringPair } from '@polkadot/types/types'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import privateKey from '../substrate/privateKey'; -import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; -import { - createCollectionExpectSuccess, - createItemExpectSuccess, - normalizeAccountId, - waitNewBlocks, -} from '../util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; -let Alice: IKeyringPair; -let Bob: IKeyringPair; - -before(async () => { - await usingApi(async () => { - Alice = privateKey('//Alice'); - Bob = privateKey('//Bob'); - }); -}); - -describe('Admin vs Owner changes the data in the token: ', () => { - it('The collection admin changes the data in the token and in the same block the token owner also changes the data in it ', async () => { - await usingApi(async (api) => { - const AliceData = 1; - const BobData = 2; - const collectionId = await createCollectionExpectSuccess(); - const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); - await submitTransactionAsync(Alice, changeAdminTx); - const itemId = await createItemExpectSuccess(Bob, collectionId, 'NFT'); - // - // tslint:disable-next-line: max-line-length - const AliceTx = api.tx.unique.setVariableMetaData(collectionId, itemId, AliceData.toString()); - // tslint:disable-next-line: max-line-length - const BobTx = api.tx.unique.setVariableMetaData(collectionId, itemId, BobData.toString()); - await Promise.all([ - AliceTx.signAndSend(Alice), - BobTx.signAndSend(Bob), - ]); - const item: any = await api.query.unique.nftItemList(collectionId, itemId); - expect(item.variableData).not.to.be.eq(null); // Pseudo-random selection of one of two values - await waitNewBlocks(2); - }); - }); -}); -*/ \ No newline at end of file --- a/tests/src/collision-tests/admVsOwnerTake.test.ts +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -/* broken by design -// substrate transactions are sequential, not parallel -// the order of execution is indeterminate - -import { IKeyringPair } from '@polkadot/types/types'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import privateKey from '../substrate/privateKey'; -import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; -import { - createCollectionExpectSuccess, - createItemExpectSuccess, - normalizeAccountId, - waitNewBlocks, -} from '../util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; -let Alice: IKeyringPair; -let Bob: IKeyringPair; -let Ferdie: IKeyringPair; - -before(async () => { - await usingApi(async () => { - Alice = privateKey('//Alice'); - Bob = privateKey('//Bob'); - Ferdie = privateKey('//Ferdie'); - }); -}); - -describe('Admin vs Owner take token: ', () => { - // tslint:disable-next-line: max-line-length - it('The collection admin burns the token and in the same block the token owner performs a transaction on it ', async () => { - await usingApi(async (api) => { - const collectionId = await createCollectionExpectSuccess(); - const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); - await submitTransactionAsync(Alice, changeAdminTx); - const itemId = await createItemExpectSuccess(Bob, collectionId, 'NFT'); - // - const sendItem = api.tx.unique.transfer(normalizeAccountId(Ferdie.address), collectionId, itemId, 1); - const burnItem = api.tx.unique.burnItem(collectionId, itemId, 1); - await Promise.all([ - sendItem.signAndSend(Bob), - burnItem.signAndSend(Alice), - ]); - await waitNewBlocks(2); - let itemBurn = false; - itemBurn = (await (api.query.unique.nftItemList(collectionId, itemId))).toJSON() as boolean; - // tslint:disable-next-line: no-unused-expression - expect(itemBurn).to.be.null; - await waitNewBlocks(2); - }); - }); -}); -*/ \ No newline at end of file --- a/tests/src/collision-tests/adminDestroyCollection.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -/* broken by design -// substrate transactions are sequential, not parallel -// the order of execution is indeterminate - -import { IKeyringPair } from '@polkadot/types/types'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import privateKey from '../substrate/privateKey'; -import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; -import { - createCollectionExpectSuccess, - normalizeAccountId, - waitNewBlocks, -} from '../util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; -let Alice: IKeyringPair; -let Bob: IKeyringPair; -let Ferdie: IKeyringPair; - -before(async () => { - await usingApi(async () => { - Alice = privateKey('//Alice'); - Bob = privateKey('//Bob'); - Ferdie = privateKey('//Ferdie'); - }); -}); - -describe('Deleting a collection while add address to allowlist: ', () => { - // tslint:disable-next-line: max-line-length - it('Adding an address to the collection allowlist in a block by the admin, and deleting the collection by the owner ', async () => { - await usingApi(async (api) => { - const collectionId = await createCollectionExpectSuccess(); - const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); - await submitTransactionAsync(Alice, changeAdminTx); - await waitNewBlocks(1); - // - const addAllowlistAdm = api.tx.unique.addToAllowList(collectionId, normalizeAccountId(Ferdie.address)); - const destroyCollection = api.tx.unique.destroyCollection(collectionId); - await Promise.all([ - addAllowlistAdm.signAndSend(Bob), - destroyCollection.signAndSend(Alice), - ]); - await waitNewBlocks(1); - let allowList = false; - allowList = (await api.query.unique.allowList(collectionId, Ferdie.address)).toJSON() as boolean; - // tslint:disable-next-line: no-unused-expression - expect(allowList).to.be.false; - await waitNewBlocks(2); - }); - }); -}); -*/ \ No newline at end of file --- a/tests/src/collision-tests/adminLimitsOff.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -/* broken by design -// substrate transactions are sequential, not parallel -// the order of execution is indeterminate - -import { IKeyringPair } from '@polkadot/types/types'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import privateKey from '../substrate/privateKey'; -import usingApi, { submitTransactionAsync, submitTransactionExpectFailAsync } from '../substrate/substrate-api'; -import { - createCollectionExpectSuccess, - normalizeAccountId, - waitNewBlocks, -} from '../util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; -let Alice: IKeyringPair; -let Bob: IKeyringPair; -let Ferdie: IKeyringPair; -let Charlie: IKeyringPair; -let Eve: IKeyringPair; -let Dave: IKeyringPair; - -before(async () => { - await usingApi(async () => { - Alice = privateKey('//Alice'); - Bob = privateKey('//Bob'); - Ferdie = privateKey('//Ferdie'); - Charlie = privateKey('//Charlie'); - Eve = privateKey('//Eve'); - Dave = privateKey('//Dave'); - }); -}); - -describe('Admin limit exceeded collection: ', () => { - // tslint:disable-next-line: max-line-length - it('In one block, the owner and admin add new admins to the collection more than the limit ', async () => { - await usingApi(async (api) => { - const collectionId = await createCollectionExpectSuccess(); - - const chainAdminLimit = (api.consts.unique.collectionAdminsLimit as any).toNumber(); - expect(chainAdminLimit).to.be.equal(5); - - const changeAdminTx1 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Eve.address)); - await submitTransactionAsync(Alice, changeAdminTx1); - const changeAdminTx2 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Dave.address)); - await submitTransactionAsync(Alice, changeAdminTx2); - const changeAdminTx3 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); - await submitTransactionAsync(Alice, changeAdminTx3); - - const addAdmOne = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Ferdie.address)); - const addAdmTwo = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Charlie.address)); - await Promise.all([ - addAdmOne.signAndSend(Bob), - addAdmTwo.signAndSend(Alice), - ]); - await waitNewBlocks(2); - const changeAdminTx4 = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Alice.address)); - await expect(submitTransactionExpectFailAsync(Alice, changeAdminTx4)).to.be.rejected; - - const adminListAfterAddAdmin: any = (await api.query.unique.adminList(collectionId)); - expect(adminListAfterAddAdmin).to.be.contains(normalizeAccountId(Eve.address)); - expect(adminListAfterAddAdmin).to.be.contains(normalizeAccountId(Ferdie.address)); - expect(adminListAfterAddAdmin).not.to.be.contains(normalizeAccountId(Alice.address)); - await waitNewBlocks(2); - }); - }); -}); -*/ \ No newline at end of file --- a/tests/src/collision-tests/adminRightsOff.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -/* broken by design -// substrate transactions are sequential, not parallel -// the order of execution is indeterminate - -import { IKeyringPair } from '@polkadot/types/types'; -import BN from 'bn.js'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import privateKey from '../substrate/privateKey'; -import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; -import { - createCollectionExpectSuccess, - normalizeAccountId, - waitNewBlocks, -} from '../util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; -let Alice: IKeyringPair; -let Bob: IKeyringPair; - -before(async () => { - await usingApi(async () => { - Alice = privateKey('//Alice'); - Bob = privateKey('//Bob'); - }); -}); - -describe('Deprivation of admin rights: ', () => { - // tslint:disable-next-line: max-line-length - it('In the block, the collection admin adds a token or changes data, and the collection owner deprives the admin of rights ', async () => { - await usingApi(async (api) => { - const collectionId = await createCollectionExpectSuccess(); - const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); - await submitTransactionAsync(Alice, changeAdminTx); - await waitNewBlocks(1); - const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }]; - const addItemAdm = api.tx.unique.createMultipleItems(collectionId, normalizeAccountId(Bob.address), args); - const removeAdm = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); - await Promise.all([ - addItemAdm.signAndSend(Bob), - removeAdm.signAndSend(Alice), - ]); - await waitNewBlocks(2); - const itemsListIndex = await api.query.unique.itemListIndex(collectionId) as unknown as BN; - expect(itemsListIndex.toNumber()).to.be.equal(0); - const adminList: any = (await api.query.unique.adminList(collectionId)); - expect(adminList).not.to.be.contains(normalizeAccountId(Bob.address)); - await waitNewBlocks(2); - }); - }); -}); -*/ \ No newline at end of file --- a/tests/src/collision-tests/setSponsorNewOwner.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -/* broken by design -// substrate transactions are sequential, not parallel -// the order of execution is indeterminate - -import { IKeyringPair } from '@polkadot/types/types'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import privateKey from '../substrate/privateKey'; -import usingApi from '../substrate/substrate-api'; -import { - createCollectionExpectSuccess, - setCollectionSponsorExpectSuccess, - waitNewBlocks, -} from '../util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; -let Alice: IKeyringPair; -let Bob: IKeyringPair; -let Ferdie: IKeyringPair; - -before(async () => { - await usingApi(async () => { - Alice = privateKey('//Alice'); - Bob = privateKey('//Bob'); - Ferdie = privateKey('//Ferdie'); - }); -}); - -describe('Sponsored with new owner ', () => { - // tslint:disable-next-line: max-line-length - it('Confirmation of sponsorship of a collection in a block with a change in the owner of the collection: ', async () => { - await usingApi(async (api) => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, Bob.address); - await waitNewBlocks(2); - const confirmSponsorship = api.tx.unique.confirmSponsorship(collectionId); - const changeCollectionOwner = api.tx.unique.changeCollectionOwner(collectionId, Ferdie.address); - await Promise.all([ - confirmSponsorship.signAndSend(Bob), - changeCollectionOwner.signAndSend(Alice), - ]); - await waitNewBlocks(2); - const collection: any = (await api.query.unique.collectionById(collectionId)).toJSON(); - expect(collection.sponsorship.confirmed).to.be.eq(Bob.address); - expect(collection.owner).to.be.eq(Ferdie.address); - await waitNewBlocks(2); - }); - }); -}); -*/ \ No newline at end of file --- a/tests/src/collision-tests/sponsorPayments.test.ts +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -/* broken by design -// substrate transactions are sequential, not parallel -// the order of execution is indeterminate - -import { IKeyringPair } from '@polkadot/types/types'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import { alicesPublicKey, bobsPublicKey } from '../accounts'; -import getBalance from '../substrate/get-balance'; -import privateKey from '../substrate/privateKey'; -import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; -import { - confirmSponsorshipExpectSuccess, - createCollectionExpectSuccess, - createItemExpectSuccess, - setCollectionSponsorExpectSuccess, - normalizeAccountId, - waitNewBlocks, -} from '../util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; -let Alice: IKeyringPair; -let Bob: IKeyringPair; - -before(async () => { - await usingApi(async () => { - Alice = privateKey('//Alice'); - Bob = privateKey('//Bob'); - }); -}); - -describe('Payment of commission if one block: ', () => { - // tslint:disable-next-line: max-line-length - it('Payment of commission if one block contains transactions for payment from the sponsor\'s balance and his (sponsor\'s) exclusion from the collection ', async () => { - await usingApi(async (api) => { - const collectionId = await createCollectionExpectSuccess(); - const changeAdminTxBob = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(Bob.address)); - await submitTransactionAsync(Alice, changeAdminTxBob); - const itemId = await createItemExpectSuccess(Bob, collectionId, 'NFT'); - await setCollectionSponsorExpectSuccess(collectionId, Bob.address); - await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); - - const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alicesPublicKey, bobsPublicKey]); - const sendItem = api.tx.unique.transfer(normalizeAccountId(Alice.address), collectionId, itemId, 1); - const revokeSponsor = api.tx.unique.removeCollectionSponsor(collectionId); - await Promise.all([ - sendItem.signAndSend(Bob), - revokeSponsor.signAndSend(Alice), - ]); - const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]); - // tslint:disable-next-line:no-unused-expression - expect(alicesBalanceAfter === alicesBalanceBefore).to.be.true; - // tslint:disable-next-line:no-unused-expression - expect(bobsBalanceAfter === bobsBalanceBefore).to.be.true; - await waitNewBlocks(2); - }); - }); -}); -*/ \ No newline at end of file --- a/tests/src/collision-tests/tokenLimitsOff.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -/* broken by design -// substrate transactions are sequential, not parallel -// the order of execution is indeterminate - -import { IKeyringPair } from '@polkadot/types/types'; -import BN from 'bn.js'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import privateKey from '../substrate/privateKey'; -import usingApi, { submitTransactionAsync } from '../substrate/substrate-api'; -import { - addToAllowListExpectSuccess, - createCollectionExpectSuccess, - getCreateItemResult, - setMintPermissionExpectSuccess, - normalizeAccountId, - waitNewBlocks, -} from '../util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; -let Alice: IKeyringPair; -let Bob: IKeyringPair; -let Ferdie: IKeyringPair; - -const accountTokenOwnershipLimit = 4; -const sponsoredMintSize = 4294967295; -const tokenLimit = 4; -const sponsorTimeout = 14400; -const ownerCanTransfer = false; -const ownerCanDestroy = false; - -before(async () => { - await usingApi(async () => { - Alice = privateKey('//Alice'); - Bob = privateKey('//Bob'); - Ferdie = privateKey('//Ferdie'); - }); -}); - -describe('Token limit exceeded collection: ', () => { - // tslint:disable-next-line: max-line-length - it('The number of tokens created in the collection from different addresses exceeds the allowed collection limit ', async () => { - await usingApi(async (api) => { - const collectionId = await createCollectionExpectSuccess(); - await setMintPermissionExpectSuccess(Alice, collectionId, true); - await addToAllowListExpectSuccess(Alice, collectionId, Ferdie.address); - await addToAllowListExpectSuccess(Alice, collectionId, Bob.address); - const setCollectionLim = api.tx.unique.setCollectionLimits( - collectionId, - { - accountTokenOwnershipLimit, - sponsoredMintSize, - tokenLimit, - // tslint:disable-next-line: object-literal-sort-keys - sponsorTimeout, - ownerCanTransfer, - ownerCanDestroy, - }, - ); - const subTx = await submitTransactionAsync(Alice, setCollectionLim); - const subTxTesult = getCreateItemResult(subTx); - // tslint:disable-next-line:no-unused-expression - expect(subTxTesult.success).to.be.true; - await waitNewBlocks(2); - - const args = [{ nft: ['0x31', '0x31'] }, { nft: ['0x32', '0x32'] }, { nft: ['0x33', '0x33'] }]; - const mintItemOne = api.tx.unique - .createMultipleItems(collectionId, normalizeAccountId(Ferdie.address), args); - const mintItemTwo = api.tx.unique - .createMultipleItems(collectionId, normalizeAccountId(Bob.address), args); - await Promise.all([ - mintItemOne.signAndSend(Ferdie), - mintItemTwo.signAndSend(Bob), - ]); - await waitNewBlocks(2); - const itemsListIndexAfter = await api.query.unique.itemListIndex(collectionId) as unknown as BN; - expect(itemsListIndexAfter.toNumber()).to.be.equal(3); - // TokenLimit = 4. The first transaction is successful. The second should fail. - await waitNewBlocks(2); - }); - }); -}); -*/ --- a/tests/src/collision-tests/turnsOffMinting.test.ts +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -/* broken by design -// substrate transactions are sequential, not parallel -// the order of execution is indeterminate - -import { IKeyringPair } from '@polkadot/types/types'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import privateKey from '../substrate/privateKey'; -import usingApi from '../substrate/substrate-api'; -import { - addToAllowListExpectSuccess, - createCollectionExpectSuccess, - setMintPermissionExpectSuccess, - normalizeAccountId, - waitNewBlocks, -} from '../util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; -let Alice: IKeyringPair; -let Ferdie: IKeyringPair; - -before(async () => { - await usingApi(async () => { - Alice = privateKey('//Alice'); - Ferdie = privateKey('//Ferdie'); - }); -}); - -describe('Turns off minting mode: ', () => { - // tslint:disable-next-line: max-line-length - it('The collection owner turns off minting mode and there are minting transactions in the same block ', async () => { - await usingApi(async (api) => { - const collectionId = await createCollectionExpectSuccess(); - await setMintPermissionExpectSuccess(Alice, collectionId, true); - await addToAllowListExpectSuccess(Alice, collectionId, Ferdie.address); - - const mintItem = api.tx.unique.createItem(collectionId, normalizeAccountId(Ferdie.address), 'NFT'); - const offMinting = api.tx.unique.setMintPermission(collectionId, false); - await Promise.all([ - mintItem.signAndSend(Ferdie), - offMinting.signAndSend(Alice), - ]); - let itemList = false; - itemList = (await (api.query.unique.nftItemList(collectionId, mintItem))).toJSON() as boolean; - // tslint:disable-next-line: no-unused-expression - expect(itemList).to.be.null; - await waitNewBlocks(2); - }); - }); -}); -*/ \ No newline at end of file --- a/tests/src/contracts.test.ts +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import usingApi, {submitTransactionAsync} from './substrate/substrate-api'; -import fs from 'fs'; -import {Abi, ContractPromise as Contract} from '@polkadot/api-contract'; -import { - deployFlipper, - getFlipValue, - deployTransferContract, -} from './util/contracthelpers'; - -import { - addToAllowListExpectSuccess, - approveExpectSuccess, - createCollectionExpectSuccess, - createItemExpectSuccess, - enablePublicMintingExpectSuccess, - enableAllowListExpectSuccess, - getGenericResult, - normalizeAccountId, - isAllowlisted, - transferFromExpectSuccess, - getTokenOwner, -} from './util/helpers'; - - -chai.use(chaiAsPromised); -const expect = chai.expect; - -const value = 0; -const gasLimit = 9000n * 1000000n; -const marketContractAddress = '5CYN9j3YvRkqxewoxeSvRbhAym4465C57uMmX5j4yz99L5H6'; - -// todo:playgrounds skipped ~ postponed -describe.skip('Contracts', () => { - it('Can deploy smart contract Flipper, instantiate it and call it\'s get and flip messages.', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [contract, deployer] = await deployFlipper(api, privateKeyWrapper); - const initialGetResponse = await getFlipValue(contract, deployer); - - const bob = privateKeyWrapper('//Bob'); - const flip = contract.tx.flip({value, gasLimit}); - await submitTransactionAsync(bob, flip); - - const afterFlipGetResponse = await getFlipValue(contract, deployer); - expect(afterFlipGetResponse).not.to.be.eq(initialGetResponse, 'Flipping should change value.'); - }); - }); - - it('Can initialize contract instance', async () => { - await usingApi(async (api) => { - const metadata = JSON.parse(fs.readFileSync('./src/flipper/metadata.json').toString('utf-8')); - const abi = new Abi(metadata); - const newContractInstance = new Contract(api, abi, marketContractAddress); - expect(newContractInstance).to.have.property('address'); - expect(newContractInstance.address.toString()).to.equal(marketContractAddress); - }); - }); -}); - -describe.skip('Chain extensions', () => { - it('Transfer CE', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const alice = privateKeyWrapper('//Alice'); - const bob = privateKeyWrapper('//Bob'); - - // Prep work - const collectionId = await createCollectionExpectSuccess(); - const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT'); - const [contract] = await deployTransferContract(api, privateKeyWrapper); - const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, contract.address); - await submitTransactionAsync(alice, changeAdminTx); - - expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address)); - - // Transfer - const transferTx = contract.tx.transfer({value, gasLimit}, bob.address, collectionId, tokenId, 1); - const events = await submitTransactionAsync(alice, transferTx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - - expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(bob.address)); - }); - }); - - it('Mint CE', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const alice = privateKeyWrapper('//Alice'); - const bob = privateKeyWrapper('//Bob'); - - const collectionId = await createCollectionExpectSuccess(); - const [contract] = await deployTransferContract(api, privateKeyWrapper); - await enablePublicMintingExpectSuccess(alice, collectionId); - await enableAllowListExpectSuccess(alice, collectionId); - await addToAllowListExpectSuccess(alice, collectionId, contract.address); - await addToAllowListExpectSuccess(alice, collectionId, bob.address); - - const transferTx = contract.tx.createItem({value, gasLimit}, bob.address, collectionId, {Nft: {const_data: '0x010203'}}); - const events = await submitTransactionAsync(alice, transferTx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - - const tokensAfter = (await api.query.unique.nftItemList.entries(collectionId)).map((kv: any) => kv[1].toJSON()); - expect(tokensAfter).to.be.deep.equal([ - { - owner: bob.address, - constData: '0x010203', - }, - ]); - }); - }); - - it('Bulk mint CE', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const alice = privateKeyWrapper('//Alice'); - const bob = privateKeyWrapper('//Bob'); - - const collectionId = await createCollectionExpectSuccess(); - const [contract] = await deployTransferContract(api, privateKeyWrapper); - await enablePublicMintingExpectSuccess(alice, collectionId); - await enableAllowListExpectSuccess(alice, collectionId); - await addToAllowListExpectSuccess(alice, collectionId, contract.address); - await addToAllowListExpectSuccess(alice, collectionId, bob.address); - - const transferTx = contract.tx.createMultipleItems({value, gasLimit}, bob.address, collectionId, [ - {NFT: {/*const_data: '0x010203'*/}}, - {NFT: {/*const_data: '0x010204'*/}}, - {NFT: {/*const_data: '0x010205'*/}}, - ]); - const events = await submitTransactionAsync(alice, transferTx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - - const tokensAfter: any = (await api.query.unique.nftItemList.entries(collectionId) as any) - .map((kv: any) => kv[1].toJSON()) - .sort((a: any, b: any) => a.constData.localeCompare(b.constData)); - expect(tokensAfter).to.be.deep.equal([ - { - Owner: bob.address, - //ConstData: '0x010203', - }, - { - Owner: bob.address, - //ConstData: '0x010204', - }, - { - Owner: bob.address, - //ConstData: '0x010205', - }, - ]); - }); - }); - - it('Approve CE', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const alice = privateKeyWrapper('//Alice'); - const bob = privateKeyWrapper('//Bob'); - const charlie = privateKeyWrapper('//Charlie'); - - const collectionId = await createCollectionExpectSuccess(); - const [contract] = await deployTransferContract(api, privateKeyWrapper); - const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', contract.address.toString()); - - const transferTx = contract.tx.approve({value, gasLimit}, bob.address, collectionId, tokenId, 1); - const events = await submitTransactionAsync(alice, transferTx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - - await transferFromExpectSuccess(collectionId, tokenId, bob, normalizeAccountId(contract.address.toString()), charlie, 1, 'NFT'); - }); - }); - - it('TransferFrom CE', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const alice = privateKeyWrapper('//Alice'); - const bob = privateKeyWrapper('//Bob'); - const charlie = privateKeyWrapper('//Charlie'); - - const collectionId = await createCollectionExpectSuccess(); - const [contract] = await deployTransferContract(api, privateKeyWrapper); - const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address); - await approveExpectSuccess(collectionId, tokenId, bob, contract.address.toString(), 1); - - const transferTx = contract.tx.transferFrom({value, gasLimit}, bob.address, charlie.address, collectionId, tokenId, 1); - const events = await submitTransactionAsync(alice, transferTx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - - const token: any = (await api.query.unique.nftItemList(collectionId, tokenId) as any).unwrap(); - expect(token.owner.toString()).to.be.equal(charlie.address); - }); - }); - - it('ToggleAllowList CE', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const alice = privateKeyWrapper('//Alice'); - const bob = privateKeyWrapper('//Bob'); - - const collectionId = await createCollectionExpectSuccess(); - const [contract] = await deployTransferContract(api, privateKeyWrapper); - const changeAdminTx = api.tx.unique.addCollectionAdmin(collectionId, contract.address); - await submitTransactionAsync(alice, changeAdminTx); - - expect(await isAllowlisted(api, collectionId, bob.address)).to.be.false; - - { - const transferTx = contract.tx.toggleAllowList({value, gasLimit}, collectionId, bob.address, true); - const events = await submitTransactionAsync(alice, transferTx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - - expect(await isAllowlisted(api, collectionId, bob.address)).to.be.true; - } - { - const transferTx = contract.tx.toggleAllowList({value, gasLimit}, collectionId, bob.address, false); - const events = await submitTransactionAsync(alice, transferTx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - - expect(await isAllowlisted(api, collectionId, bob.address)).to.be.false; - } - }); - }); -}); --- a/tests/src/enableContractSponsoring.test.ts +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -import {IKeyringPair} from '@polkadot/types/types'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import usingApi from './substrate/substrate-api'; -import {deployFlipper, getFlipValue, toggleFlipValueExpectSuccess} from './util/contracthelpers'; -import { - enableContractSponsoringExpectFailure, - enableContractSponsoringExpectSuccess, - findUnusedAddress, - setContractSponsoringRateLimitExpectSuccess, -} from './util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; - -// todo:playgrounds skipped ~ postponed -describe.skip('Integration Test enableContractSponsoring', () => { - it('ensure tx fee is paid from endowment', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const user = await findUnusedAddress(api, privateKeyWrapper); - - const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); - await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); - await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 1); - await toggleFlipValueExpectSuccess(user, flipper); - - expect(await getFlipValue(flipper, deployer)).to.be.false; - }); - }); - - it('ensure it can be enabled twice', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); - - await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); - await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); - }); - }); - - it('ensure it can be disabled twice', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); - - await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); - await enableContractSponsoringExpectSuccess(deployer, flipper.address, false); - await enableContractSponsoringExpectSuccess(deployer, flipper.address, false); - }); - }); - - it('ensure it can be re-enabled', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); - - await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); - await enableContractSponsoringExpectSuccess(deployer, flipper.address, false); - await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); - }); - }); - -}); - -describe.skip('Negative Integration Test enableContractSponsoring', () => { - let alice: IKeyringPair; - - before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - }); - }); - - it('fails when called for non-contract address', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const user = await findUnusedAddress(api, privateKeyWrapper); - - await enableContractSponsoringExpectFailure(alice, user.address, true); - }); - }); - - it('fails when called by non-owning user', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [flipper] = await deployFlipper(api, privateKeyWrapper); - - await enableContractSponsoringExpectFailure(alice, flipper.address, true); - }); - }); -}); --- a/tests/src/inflation.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -import {IKeyringPair} from '@polkadot/types/types'; -import {expect, itSub, usingPlaygrounds} from './util/playgrounds'; - -// todo:playgrounds requires sudo, look into on the later stage -describe('integration test: Inflation', () => { - let superuser: IKeyringPair; - - before(async () => { - await usingPlaygrounds(async (_, privateKey) => { - superuser = privateKey('//Alice'); - }); - }); - - itSub('First year inflation is 10%', async ({helper}) => { - // Make sure non-sudo can't start inflation - const [bob] = await helper.arrange.createAccounts([10n], superuser); - - await expect(helper.executeExtrinsic(bob, 'api.tx.inflation.startInflation', [1])).to.be.rejectedWith(/BadOrigin/); - - // Make sure superuser can't start inflation without explicit sudo - await expect(helper.executeExtrinsic(superuser, 'api.tx.inflation.startInflation', [1])).to.be.rejectedWith(/BadOrigin/); - - // Start inflation on relay block 1 (Alice is sudo) - const tx = helper.constructApiCall('api.tx.inflation.startInflation', [1]); - await expect(helper.executeExtrinsic(superuser, 'api.tx.sudo.sudo', [tx])).to.not.be.rejected; - - const blockInterval = (helper.api!.consts.inflation.inflationBlockInterval as any).toBigInt(); - const totalIssuanceStart = ((await helper.api!.query.inflation.startingYearTotalIssuance()) as any).toBigInt(); - const blockInflation = (await helper.api!.query.inflation.blockInflation() as any).toBigInt(); - - const YEAR = 5259600n; // 6-second block. Blocks in one year - // const YEAR = 2629800n; // 12-second block. Blocks in one year - - const totalExpectedInflation = totalIssuanceStart / 10n; - const totalActualInflation = blockInflation * YEAR / blockInterval; - - const tolerance = 0.00001; // Relative difference per year between theoretical and actual inflation - const expectedInflation = totalExpectedInflation / totalActualInflation - 1n; - - expect(Math.abs(Number(expectedInflation))).to.be.lessThanOrEqual(tolerance); - }); -}); --- a/tests/src/nesting/migration-check.test.ts +++ /dev/null @@ -1,173 +0,0 @@ -import {expect} from 'chai'; -import usingApi, {executeTransaction, submitTransactionAsync} from '../substrate/substrate-api'; -import {getCreateCollectionResult, getCreateItemResult, normalizeAccountId} from '../util/helpers'; -import {IKeyringPair} from '@polkadot/types/types'; -import {strToUTF16} from '../util/util'; -import waitNewBlocks from '../substrate/wait-new-blocks'; -// Used for polkadot-launch signalling -import find from 'find-process'; - -// todo un-skip for migrations -// todo:playgrounds skipped, this one is outdated. Probably to be deleted/replaced. -describe.skip('Migration testing: Properties', () => { - let alice: IKeyringPair; - - before(async() => { - await usingApi(async (_, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - }); - }); - - it('Preserves collection settings after migration', async () => { - let oldVersion: number; - let collectionId: number; - let collectionOld: any; - let nftId: number; - let nftOld: any; - - await usingApi(async api => { - // ----------- Collection pre-upgrade ------------ - const txCollection = api.tx.unique.createCollectionEx({ - mode: 'NFT', - access: 'AllowList', - name: strToUTF16('Mojave Pictures'), - description: strToUTF16('$2.2 billion power plant!'), - tokenPrefix: '0x0002030', - offchainSchema: '0x111111', - schemaVersion: 'Unique', - limits: { - accountTokenOwnershipLimit: 3, - }, - constOnChainSchema: '0x333333', - variableOnChainSchema: '0x22222', - }); - const events0 = await submitTransactionAsync(alice, txCollection); - const result0 = getCreateCollectionResult(events0); - collectionId = result0.collectionId; - - // Get the pre-upgrade collection info - collectionOld = (await api.query.common.collectionById(collectionId)).toJSON(); - - // ---------- NFT pre-upgrade ------------ - const txNft = api.tx.unique.createItem( - collectionId, - normalizeAccountId(alice), - { - NFT: { - owner: {substrate: alice.address}, - constData: '0x0000', - variableData: '0x1111', - }, - }, - ); - const events1 = await executeTransaction(api, alice, txNft); - const result1 = getCreateItemResult(events1); - nftId = result1.itemId; - - // Get the pre-upgrade NFT data - nftOld = (await api.query.nonfungible.tokenData(collectionId, nftId)).toJSON(); - - // Get the pre-upgrade spec version - oldVersion = (api.consts.system.version.toJSON() as any).specVersion; - }); - - console.log(`Now waiting for the parachain upgrade from ${oldVersion!}...`); - - let newVersion = oldVersion!; - let connectionFailCounter = 0; - - // Cooperate with polkadot-launch if it's running (assuming custom name change to 'polkadot-launch'), and send a custom signal - find('name', 'polkadot-launch', true).then((list) => { - for (const proc of list) { - process.kill(proc.pid, 'SIGUSR1'); - } - }); - - // And wait for the parachain upgrade - { - // Catch warnings like 'RPC methods not decorated' and keep the 'waiting' message in front - const stdlog = console.warn.bind(console); - let warnCount = 0; - console.warn = function(...args){ - if (arguments.length <= 2 || !args[2].includes('RPC methods not decorated')) { - warnCount++; - stdlog.apply(console, args as any); - } - }; - - let oldWarnCount = 0; - while (newVersion == oldVersion! && connectionFailCounter < 5) { - await new Promise(resolve => setTimeout(resolve, 12000)); - try { - await usingApi(async api => { - await waitNewBlocks(api); - newVersion = (api.consts.system.version.toJSON() as any).specVersion; - if (warnCount > oldWarnCount) { - console.log(`Still waiting for the parachain upgrade from ${oldVersion!}...`); - oldWarnCount = warnCount; - } - }); - } catch (_) { - connectionFailCounter++; - } - } - } - - await usingApi(async api => { - // ---------- Collection comparison ----------- - const collectionNew = (await api.query.common.collectionById(collectionId)).toJSON() as any; - - // Make sure the extra fields are what they should be - expect(( - await api.rpc.unique.collectionProperties(collectionId, ['_old_constOnChainSchema']) - )[0].value.toHex()).to.be.equal(collectionOld.constOnChainSchema); - - expect(( - await api.rpc.unique.collectionProperties(collectionId, ['_old_variableOnChainSchema']) - )[0].value.toHex()).to.be.equal(collectionOld.variableOnChainSchema); - - expect(( - await api.rpc.unique.collectionProperties(collectionId, ['_old_offchainSchema']) - )[0].value.toHex()).to.be.equal(collectionOld.offchainSchema); - - expect(( - await api.rpc.unique.collectionProperties(collectionId, ['_old_schemaVersion']) - )[0].value.toHuman()).to.be.equal(collectionOld.schemaVersion); - - expect(collectionNew.permissions).to.be.deep.equal({ - access: collectionOld.access, - mintMode: collectionOld.mintMode, - nesting: null, - }); - - expect(collectionNew.externalCollection).to.be.equal(false); - - // Get rid of extra fields to perform comparison on the rest of the collection - delete collectionNew.permissions; - delete collectionNew.externalCollection; - delete collectionOld.schemaVersion; - delete collectionOld.constOnChainSchema; - delete collectionOld.variableOnChainSchema; - delete collectionOld.offchainSchema; - delete collectionOld.mintMode; - delete collectionOld.access; - delete collectionOld.metaUpdatePermission; // todo look into, doesn't migrate - - expect(collectionNew).to.be.deep.equal(collectionOld); - - // ---------- NFT comparison ----------- - const nftNew = (await api.query.nonfungible.tokenData(collectionId, nftId)).toJSON() as any; - - // Make sure the extra fields are what they should be - expect((await api.rpc.unique.tokenProperties(collectionId, nftId, ['_old_constData']))[0].value.toHex()).to.be.equal(nftOld.constData); - - expect((await api.rpc.unique.tokenProperties(collectionId, nftId, ['_old_variableData']))[0].value.toHex()).to.be.equal(nftOld.variableData); - - // Get rid of extra fields to perform comparison on the rest of the NFT - delete nftOld.constData; - delete nftOld.variableData; - - expect(nftNew).to.be.deep.equal(nftOld); - }); - }); -}); --- a/tests/src/overflow.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -import {IKeyringPair} from '@polkadot/types/types'; -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import usingApi from './substrate/substrate-api'; -import {approveExpectSuccess, createCollectionExpectSuccess, createFungibleItemExpectSuccess, getAllowance, getBalance, transferExpectFailure, transferExpectSuccess, transferFromExpectFail, transferFromExpectSuccess, U128_MAX} from './util/helpers'; - -chai.use(chaiAsPromised); -const expect = chai.expect; - -// todo:playgrounds skipped ~ postponed -describe.skip('Integration Test fungible overflows', () => { - let alice: IKeyringPair; - let bob: IKeyringPair; - let charlie: IKeyringPair; - - before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - charlie = privateKeyWrapper('//Charlie'); - }); - }); - - it('fails when overflows on transfer', async () => { - await usingApi(async api => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - - await createFungibleItemExpectSuccess(alice, fungibleCollectionId, {Value: U128_MAX}); - await transferExpectSuccess(fungibleCollectionId, 0, alice, bob, U128_MAX, 'Fungible'); - - await createFungibleItemExpectSuccess(alice, fungibleCollectionId, {Value: 1n}); - await transferExpectFailure(fungibleCollectionId, 0, alice, bob, 1); - - expect(await getBalance(api, fungibleCollectionId, alice.address, 0)).to.equal(1n); - expect(await getBalance(api, fungibleCollectionId, bob.address, 0)).to.equal(U128_MAX); - }); - }); - - it('fails when overflows on transferFrom', async () => { - await usingApi(async api => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - await createFungibleItemExpectSuccess(alice, fungibleCollectionId, {Value: U128_MAX}); - await approveExpectSuccess(fungibleCollectionId, 0, alice, bob.address, U128_MAX); - await transferFromExpectSuccess(fungibleCollectionId, 0, bob, alice, charlie, U128_MAX, 'Fungible'); - - expect(await getBalance(api, fungibleCollectionId, charlie.address, 0)).to.equal(U128_MAX); - expect(await getAllowance(api, fungibleCollectionId, alice.address, bob.address, 0)).to.equal(0n); - - await createFungibleItemExpectSuccess(alice, fungibleCollectionId, {Value: U128_MAX}); - await approveExpectSuccess(fungibleCollectionId, 0, alice, bob.address, 1n); - await transferFromExpectFail(fungibleCollectionId, 0, bob, alice, charlie, 1); - - expect(await getBalance(api, fungibleCollectionId, charlie.address, 0)).to.equal(U128_MAX); - expect(await getAllowance(api, fungibleCollectionId, alice.address, bob.address, 0)).to.equal(1n); - }); - }); -}); --- a/tests/src/removeFromContractAllowList.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -import usingApi from './substrate/substrate-api'; -import {deployFlipper, toggleFlipValueExpectFailure, toggleFlipValueExpectSuccess} from './util/contracthelpers'; -import {addToContractAllowListExpectSuccess, isAllowlistedInContract, removeFromContractAllowListExpectFailure, removeFromContractAllowListExpectSuccess, toggleContractAllowlistExpectSuccess} from './util/helpers'; -import {IKeyringPair} from '@polkadot/types/types'; -import {expect} from 'chai'; - -// todo:playgrounds skipped again -describe.skip('Integration Test removeFromContractAllowList', () => { - let bob: IKeyringPair; - - before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - bob = privateKeyWrapper('//Bob'); - }); - }); - - it('user is no longer allowlisted after removal', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); - - await addToContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); - await removeFromContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); - - expect(await isAllowlistedInContract(flipper.address, bob.address)).to.be.false; - }); - }); - - it('user can\'t execute contract after removal', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); - await toggleContractAllowlistExpectSuccess(deployer, flipper.address.toString(), true); - - await addToContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); - await toggleFlipValueExpectSuccess(bob, flipper); - - await removeFromContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); - await toggleFlipValueExpectFailure(bob, flipper); - }); - }); - - it('can be called twice', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); - - await addToContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); - await removeFromContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); - await removeFromContractAllowListExpectSuccess(deployer, flipper.address.toString(), bob.address); - }); - }); -}); - -describe.skip('Negative Integration Test removeFromContractAllowList', () => { - let alice: IKeyringPair; - let bob: IKeyringPair; - - before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - }); - }); - - it('fails when called with non-contract address', async () => { - await usingApi(async () => { - await removeFromContractAllowListExpectFailure(alice, alice.address, bob.address); - }); - }); - - it('fails when executed by non owner', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [flipper] = await deployFlipper(api, privateKeyWrapper); - - await removeFromContractAllowListExpectFailure(alice, flipper.address.toString(), bob.address); - }); - }); -}); --- a/tests/src/scheduler.test.ts +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -import chai, {expect} from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import { - default as usingApi, - submitTransactionAsync, -} from './substrate/substrate-api'; -import { - createItemExpectSuccess, - createCollectionExpectSuccess, - scheduleTransferExpectSuccess, - scheduleTransferAndWaitExpectSuccess, - setCollectionSponsorExpectSuccess, - confirmSponsorshipExpectSuccess, - findUnusedAddress, - UNIQUE, - enablePublicMintingExpectSuccess, - addToAllowListExpectSuccess, - waitNewBlocks, - normalizeAccountId, - getTokenOwner, - getGenericResult, - scheduleTransferFundsPeriodicExpectSuccess, - getFreeBalance, - confirmSponsorshipByKeyExpectSuccess, - scheduleExpectFailure, -} from './util/helpers'; -import {IKeyringPair} from '@polkadot/types/types'; - -chai.use(chaiAsPromised); - -// todo:playgrounds skipped ~ postponed -describe.skip('Scheduling token and balance transfers', () => { - let alice: IKeyringPair; - let bob: IKeyringPair; - let scheduledIdBase: string; - let scheduledIdSlider: number; - - before(async() => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - }); - - scheduledIdBase = '0x' + '0'.repeat(31); - scheduledIdSlider = 0; - }); - - // Loop scheduledId around 10. Unless there are concurrent tasks with long periods/repetitions, tests' tasks' ids shouldn't ovelap. - function makeScheduledId(): string { - return scheduledIdBase + ((scheduledIdSlider++) % 10); - } - - it('Can schedule a transfer of an owned token with delay', async () => { - await usingApi(async () => { - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); - await setCollectionSponsorExpectSuccess(nftCollectionId, alice.address); - await confirmSponsorshipExpectSuccess(nftCollectionId); - - await scheduleTransferAndWaitExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 4, makeScheduledId()); - }); - }); - - it('Can transfer funds periodically', async () => { - await usingApi(async () => { - const waitForBlocks = 4; - const period = 2; - await scheduleTransferFundsPeriodicExpectSuccess(1n * UNIQUE, alice, bob, waitForBlocks, makeScheduledId(), period, 2); - const bobsBalanceBefore = await getFreeBalance(bob); - - // discounting already waited-for operations - await waitNewBlocks(waitForBlocks - 2); - const bobsBalanceAfterFirst = await getFreeBalance(bob); - expect(bobsBalanceAfterFirst > bobsBalanceBefore).to.be.true; - - await waitNewBlocks(period); - const bobsBalanceAfterSecond = await getFreeBalance(bob); - expect(bobsBalanceAfterSecond > bobsBalanceAfterFirst).to.be.true; - }); - }); - - it('Can sponsor scheduling a transaction', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); - - await usingApi(async () => { - const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address); - - const bobBalanceBefore = await getFreeBalance(bob); - const waitForBlocks = 4; - // no need to wait to check, fees must be deducted on scheduling, immediately - await scheduleTransferExpectSuccess(collectionId, tokenId, alice, bob, 0, waitForBlocks, makeScheduledId()); - const bobBalanceAfter = await getFreeBalance(bob); - // expect(aliceBalanceAfter == aliceBalanceBefore).to.be.true; - expect(bobBalanceAfter < bobBalanceBefore).to.be.true; - // wait for sequentiality matters - await waitNewBlocks(waitForBlocks - 1); - }); - }); - - it('Schedules and dispatches a transaction even if the caller has no funds at the time of the dispatch', async () => { - await usingApi(async (api, privateKeyWrapper) => { - // Find an empty, unused account - const zeroBalance = await findUnusedAddress(api, privateKeyWrapper); - - const collectionId = await createCollectionExpectSuccess(); - - // Add zeroBalance address to allow list - await enablePublicMintingExpectSuccess(alice, collectionId); - await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address); - - // Grace zeroBalance with money, enough to cover future transactions - const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE); - await submitTransactionAsync(alice, balanceTx); - - // Mint a fresh NFT - const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT'); - - // Schedule transfer of the NFT a few blocks ahead - const waitForBlocks = 5; - await scheduleTransferExpectSuccess(collectionId, tokenId, zeroBalance, alice, 1, waitForBlocks, makeScheduledId()); - - // Get rid of the account's funds before the scheduled transaction takes place - const balanceTx2 = api.tx.balances.transfer(alice.address, UNIQUE * 68n / 100n); - const events = await submitTransactionAsync(zeroBalance, balanceTx2); - expect(getGenericResult(events).success).to.be.true; - /*const emptyBalanceTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0); // do not null reserved? - const sudoTx = api.tx.sudo.sudo(emptyBalanceTx as any); - const events = await submitTransactionAsync(alice, sudoTx); - expect(getGenericResult(events).success).to.be.true;*/ - - // Wait for a certain number of blocks, discarding the ones that already happened while accepting the late transactions - await waitNewBlocks(waitForBlocks - 3); - - expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(alice.address)); - }); - }); - - it('Sponsor going bankrupt does not impact a scheduled transaction', async () => { - const collectionId = await createCollectionExpectSuccess(); - - await usingApi(async (api, privateKeyWrapper) => { - const zeroBalance = await findUnusedAddress(api, privateKeyWrapper); - const balanceTx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE); - await submitTransactionAsync(alice, balanceTx); - - await setCollectionSponsorExpectSuccess(collectionId, zeroBalance.address); - await confirmSponsorshipByKeyExpectSuccess(collectionId, zeroBalance); - - const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address); - - const waitForBlocks = 5; - await scheduleTransferExpectSuccess(collectionId, tokenId, alice, zeroBalance, 1, waitForBlocks, makeScheduledId()); - - const emptyBalanceSponsorTx = api.tx.balances.setBalance(zeroBalance.address, 0, 0); - const sudoTx = api.tx.sudo.sudo(emptyBalanceSponsorTx as any); - const events = await submitTransactionAsync(alice, sudoTx); - expect(getGenericResult(events).success).to.be.true; - - // Wait for a certain number of blocks, save for the ones that already happened while accepting the late transactions - await waitNewBlocks(waitForBlocks - 3); - - expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(normalizeAccountId(zeroBalance.address)); - }); - }); - - it.skip('Exceeding sponsor rate limit without having enough funds prevents scheduling a periodic transaction', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); - - await usingApi(async (api, privateKeyWrapper) => { - const zeroBalance = await findUnusedAddress(api, privateKeyWrapper); - - await enablePublicMintingExpectSuccess(alice, collectionId); - await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address); - - const bobBalanceBefore = await getFreeBalance(bob); - - const createData = {nft: {const_data: [], variable_data: []}}; - const creationTx = api.tx.unique.createItem(collectionId, normalizeAccountId(zeroBalance), createData as any); - - /*const badTransaction = async function () { - await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice); - }; - await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');*/ - - await scheduleExpectFailure(creationTx, zeroBalance, 3, makeScheduledId(), 1, 3); - - expect(await getFreeBalance(bob)).to.be.equal(bobBalanceBefore); - }); - }); -}); --- a/tests/src/setChainLimits.test.ts +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -import {IKeyringPair} from '@polkadot/types/types'; -import usingApi from './substrate/substrate-api'; -import { - createCollectionExpectSuccess, - addCollectionAdminExpectSuccess, - setChainLimitsExpectFailure, - IChainLimits, -} from './util/helpers'; - -// todo:playgrounds skipped ~ postponed -describe.skip('Negative Integration Test setChainLimits', () => { - let alice: IKeyringPair; - let bob: IKeyringPair; - let dave: IKeyringPair; - let limits: IChainLimits; - - before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - dave = privateKeyWrapper('//Dave'); - limits = { - collectionNumbersLimit : 1, - accountTokenOwnershipLimit: 1, - collectionsAdminsLimit: 1, - customDataLimit: 1, - nftSponsorTransferTimeout: 1, - fungibleSponsorTransferTimeout: 1, - refungibleSponsorTransferTimeout: 1, - }; - }); - }); - - it('Collection owner cannot set chain limits', async () => { - await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await setChainLimitsExpectFailure(alice, limits); - }); - - it('Collection admin cannot set chain limits', async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await addCollectionAdminExpectSuccess(alice, collectionId, bob.address); - await setChainLimitsExpectFailure(bob, limits); - }); - - it('Regular user cannot set chain limits', async () => { - await setChainLimitsExpectFailure(dave, limits); - }); -}); --- a/tests/src/setContractSponsoringRateLimit.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -import {IKeyringPair} from '@polkadot/types/types'; -import usingApi from './substrate/substrate-api'; -import waitNewBlocks from './substrate/wait-new-blocks'; -import {deployFlipper, toggleFlipValueExpectFailure, toggleFlipValueExpectSuccess} from './util/contracthelpers'; -import { - enableContractSponsoringExpectSuccess, - findUnusedAddress, - setContractSponsoringRateLimitExpectFailure, - setContractSponsoringRateLimitExpectSuccess, -} from './util/helpers'; - -// todo:playgrounds skipped~postponed test -describe.skip('Integration Test setContractSponsoringRateLimit', () => { - it('ensure sponsored contract can\'t be called twice without pause for free', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const user = await findUnusedAddress(api, privateKeyWrapper); - - const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); - await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); - await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 10); - await toggleFlipValueExpectSuccess(user, flipper); - await toggleFlipValueExpectFailure(user, flipper); - }); - }); - - it('ensure sponsored contract can be called twice with pause for free', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const user = await findUnusedAddress(api, privateKeyWrapper); - - const [flipper, deployer] = await deployFlipper(api, privateKeyWrapper); - await enableContractSponsoringExpectSuccess(deployer, flipper.address, true); - await setContractSponsoringRateLimitExpectSuccess(deployer, flipper.address, 1); - await toggleFlipValueExpectSuccess(user, flipper); - await waitNewBlocks(api, 1); - await toggleFlipValueExpectSuccess(user, flipper); - }); - }); -}); - -describe.skip('Negative Integration Test setContractSponsoringRateLimit', () => { - let alice: IKeyringPair; - - before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - }); - }); - - it('fails when called for non-contract address', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const user = await findUnusedAddress(api, privateKeyWrapper); - - await setContractSponsoringRateLimitExpectFailure(alice, user.address, 1); - }); - }); - - it('fails when called by non-owning user', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [flipper] = await deployFlipper(api, privateKeyWrapper); - - await setContractSponsoringRateLimitExpectFailure(alice, flipper.address, 1); - }); - }); -}); --- a/tests/src/xcmTransfer.test.ts +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright 2019-2022 Unique Network (Gibraltar) Ltd. -// This file is part of Unique Network. - -// Unique Network is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Unique Network is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Unique Network. If not, see . - -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; - -import {WsProvider} from '@polkadot/api'; -import {ApiOptions} from '@polkadot/api/types'; -import {IKeyringPair} from '@polkadot/types/types'; -import usingApi, {submitTransactionAsync} from './substrate/substrate-api'; -import {getGenericResult} from './util/helpers'; -import waitNewBlocks from './substrate/wait-new-blocks'; -import getBalance from './substrate/get-balance'; - -chai.use(chaiAsPromised); -const expect = chai.expect; - -const UNIQUE_CHAIN = 1000; -const KARURA_CHAIN = 2000; -const KARURA_PORT = '9946'; -const TRANSFER_AMOUNT = 2000000000000000000000000n; - -// todo:playgrounds refit when XCM drops -describe.skip('Integration test: Exchanging QTZ with Karura', () => { - let alice: IKeyringPair; - - before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - }); - - const karuraApiOptions: ApiOptions = { - provider: new WsProvider('ws://127.0.0.1:' + KARURA_PORT), - }; - - await usingApi(async (api) => { - const destination = { - V0: { - X2: [ - 'Parent', - { - Parachain: UNIQUE_CHAIN, - }, - ], - }, - }; - - const metadata = - { - name: 'QTZ', - symbol: 'QTZ', - decimals: 18, - minimalBalance: 1, - }; - - const tx = api.tx.assetRegistry.registerForeignAsset(destination, metadata); - const sudoTx = api.tx.sudo.sudo(tx as any); - const events = await submitTransactionAsync(alice, sudoTx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - }, karuraApiOptions); - }); - - it('Should connect and send QTZ to Karura', async () => { - let balanceOnKaruraBefore: bigint; - - await usingApi(async (api) => { - const {free} = (await api.query.tokens.accounts(alice.addressRaw, {ForeignAssetId: 0})).toJSON() as any; - balanceOnKaruraBefore = free; - }, {provider: new WsProvider('ws://127.0.0.1:' + KARURA_PORT)}); - - await usingApi(async (api) => { - const destination = { - V0: { - X2: [ - 'Parent', - { - Parachain: KARURA_CHAIN, - }, - ], - }, - }; - - const beneficiary = { - V0: { - X1: { - AccountId32: { - network: 'Any', - id: alice.addressRaw, - }, - }, - }, - }; - - const assets = { - V1: [ - { - id: { - Concrete: { - parents: 0, - interior: 'Here', - }, - }, - fun: { - Fungible: TRANSFER_AMOUNT, - }, - }, - ], - }; - - const feeAssetItem = 0; - - const weightLimit = { - Limited: 5000000000, - }; - - const tx = api.tx.polkadotXcm.limitedReserveTransferAssets(destination, beneficiary, assets, feeAssetItem, weightLimit); - const events = await submitTransactionAsync(alice, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - }); - - await usingApi(async (api) => { - // todo do something about instant sealing, where there might not be any new blocks - await waitNewBlocks(api, 3); - const {free} = (await api.query.tokens.accounts(alice.addressRaw, {ForeignAssetId: 0})).toJSON() as any; - expect(free > balanceOnKaruraBefore).to.be.true; - }, {provider: new WsProvider('ws://127.0.0.1:' + KARURA_PORT)}); - }); - - it('Should connect to Karura and send QTZ back', async () => { - let balanceBefore: bigint; - - await usingApi(async (api) => { - [balanceBefore] = await getBalance(api, [alice.address]); - }); - - await usingApi(async (api) => { - const destination = { - V1: { - parents: 1, - interior: { - X2: [ - {Parachain: UNIQUE_CHAIN}, - {AccountId32: { - network: 'Any', - id: alice.addressRaw, - }}, - ], - }, - }, - }; - - const id = { - ForeignAssetId: 0, - }; - - const amount = TRANSFER_AMOUNT; - const destWeight = 50000000; - - const tx = api.tx.xTokens.transfer(id, amount, destination, destWeight); - const events = await submitTransactionAsync(alice, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; - }, {provider: new WsProvider('ws://127.0.0.1:' + KARURA_PORT)}); - - await usingApi(async (api) => { - // todo do something about instant sealing, where there might not be any new blocks - await waitNewBlocks(api, 3); - const [balanceAfter] = await getBalance(api, [alice.address]); - expect(balanceAfter > balanceBefore).to.be.true; - }); - }); -}); --- a/tests/tsconfig.json +++ b/tests/tsconfig.json @@ -20,6 +20,9 @@ "include": [ "./src/**/*", "./src/interfaces/*.ts" +, "src/.outdated/collision-tests" ], + "exclude": [ + "./src/.outdated" ], "lib": [ "es2017" -- gitstuff