--- a/tests/src/addCollectionAdmin.test.ts +++ b/tests/src/addCollectionAdmin.test.ts @@ -17,119 +17,114 @@ import {IKeyringPair} from '@polkadot/types/types'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import {usingPlaygrounds} from './util/playgrounds'; +import {itSub, usingPlaygrounds} from './util/playgrounds'; chai.use(chaiAsPromised); const expect = chai.expect; -let donor: IKeyringPair; +describe('Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => { + let donor: IKeyringPair; -before(async () => { - await usingPlaygrounds(async (_, privateKeyWrapper) => { - donor = privateKeyWrapper('//Alice'); + before(async () => { + await usingPlaygrounds(async (_, privateKeyWrapper) => { + donor = privateKeyWrapper('//Alice'); + }); }); -}); -describe('Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => { - it('Add collection admin.', async () => { - await usingPlaygrounds(async (helper) => { - const [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor); - const {collectionId} = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); + itSub('Add collection admin.', async ({helper}) => { + const [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor); + const {collectionId} = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); - const collection = await helper.collection.getData(collectionId); - expect(collection!.normalizedOwner!).to.be.equal(alice.address); + const collection = await helper.collection.getData(collectionId); + expect(collection!.normalizedOwner!).to.be.equal(helper.address.normalizeSubstrate(alice.address)); - await helper.nft.addAdmin(alice, collectionId, {Substrate: bob.address}); + await helper.nft.addAdmin(alice, collectionId, {Substrate: bob.address}); - const adminListAfterAddAdmin = await helper.collection.getAdmins(collectionId); - expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address}); - }); + const adminListAfterAddAdmin = await helper.collection.getAdmins(collectionId); + expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address}); }); }); describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => { - it("Not owner can't add collection admin.", async () => { - await usingPlaygrounds(async (helper) => { - const [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); - const {collectionId} = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); + let donor: IKeyringPair; + + before(async () => { + await usingPlaygrounds(async (_, privateKeyWrapper) => { + donor = privateKeyWrapper('//Alice'); + }); + }); - const collection = await helper.collection.getData(collectionId); - expect(collection?.normalizedOwner).to.be.equal(alice.address); + itSub("Not owner can't add collection admin.", async ({helper}) => { + const [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); + const {collectionId} = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); - const changeAdminTxBob = async () => helper.collection.addAdmin(bob, collectionId, {Substrate: bob.address}); - const changeAdminTxCharlie = async () => helper.collection.addAdmin(bob, collectionId, {Substrate: charlie.address}); - await expect(changeAdminTxCharlie()).to.be.rejected; - await expect(changeAdminTxBob()).to.be.rejected; + const collection = await helper.collection.getData(collectionId); + expect(collection?.normalizedOwner).to.be.equal(helper.address.normalizeSubstrate(alice.address)); + + const changeAdminTxBob = async () => helper.collection.addAdmin(bob, collectionId, {Substrate: bob.address}); + const changeAdminTxCharlie = async () => helper.collection.addAdmin(bob, collectionId, {Substrate: charlie.address}); + await expect(changeAdminTxCharlie()).to.be.rejectedWith(/common\.NoPermission/); + await expect(changeAdminTxBob()).to.be.rejectedWith(/common\.NoPermission/); - const adminListAfterAddAdmin = await helper.collection.getAdmins(collectionId); - expect(adminListAfterAddAdmin).to.be.not.deep.contains({Substrate: charlie.address}); - expect(adminListAfterAddAdmin).to.be.not.deep.contains({Substrate: bob.address}); - }); + const adminListAfterAddAdmin = await helper.collection.getAdmins(collectionId); + expect(adminListAfterAddAdmin).to.be.not.deep.contains({Substrate: charlie.address}); + expect(adminListAfterAddAdmin).to.be.not.deep.contains({Substrate: bob.address}); }); - it("Admin can't add collection admin.", async () => { - await usingPlaygrounds(async (helper) => { - const [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); - const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); + itSub("Admin can't add collection admin.", async ({helper}) => { + const [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); + const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); - await collection.addAdmin(alice, {Substrate: bob.address}); + await collection.addAdmin(alice, {Substrate: bob.address}); - const adminListAfterAddAdmin = await collection.getAdmins(); - expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address}); + const adminListAfterAddAdmin = await collection.getAdmins(); + expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address}); - const changeAdminTxCharlie = async () => collection.addAdmin(bob, {Substrate: charlie.address}); - await expect(changeAdminTxCharlie()).to.be.rejected; + const changeAdminTxCharlie = async () => collection.addAdmin(bob, {Substrate: charlie.address}); + await expect(changeAdminTxCharlie()).to.be.rejectedWith(/common\.NoPermission/); - const adminListAfterAddNewAdmin = await collection.getAdmins(); - expect(adminListAfterAddNewAdmin).to.be.deep.contains({Substrate: bob.address}); - expect(adminListAfterAddNewAdmin).to.be.not.deep.contains({Substrate: charlie.address}); - }); + const adminListAfterAddNewAdmin = await collection.getAdmins(); + expect(adminListAfterAddNewAdmin).to.be.deep.contains({Substrate: bob.address}); + expect(adminListAfterAddNewAdmin).to.be.not.deep.contains({Substrate: charlie.address}); }); - it("Can't add collection admin of not existing collection.", async () => { - await usingPlaygrounds(async (helper) => { - const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); - // tslint:disable-next-line: no-bitwise - const collectionId = (1 << 32) - 1; + itSub("Can't add collection admin of not existing collection.", async ({helper}) => { + const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); + const collectionId = (1 << 32) - 1; - const addAdminTx = async () => helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address}); - await expect(addAdminTx()).to.be.rejected; + const addAdminTx = async () => helper.collection.addAdmin(alice, collectionId, {Substrate: bob.address}); + await expect(addAdminTx()).to.be.rejectedWith(/common\.CollectionNotFound/); - // Verifying that nothing bad happened (network is live, new collections can be created, etc.) - await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); - }); + // Verifying that nothing bad happened (network is live, new collections can be created, etc.) + await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); }); - it("Can't add an admin to a destroyed collection.", async () => { - await usingPlaygrounds(async (helper) => { - const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); - const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); + itSub("Can't add an admin to a destroyed collection.", async ({helper}) => { + const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); + const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); - await collection.burn(alice); - const addAdminTx = async () => collection.addAdmin(alice, {Substrate: bob.address}); - await expect(addAdminTx()).to.be.rejected; + await collection.burn(alice); + const addAdminTx = async () => collection.addAdmin(alice, {Substrate: bob.address}); + await expect(addAdminTx()).to.be.rejectedWith(/common\.CollectionNotFound/); - // Verifying that nothing bad happened (network is live, new collections can be created, etc.) - await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); - }); + // Verifying that nothing bad happened (network is live, new collections can be created, etc.) + await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); }); - it('Add an admin to a collection that has reached the maximum number of admins limit', async () => { - await usingPlaygrounds(async (helper) => { - const [alice, ...accounts] = await helper.arrange.createAccounts([10n, 0n, 0n, 0n, 0n, 0n, 0n, 0n], donor); - const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); + itSub('Add an admin to a collection that has reached the maximum number of admins limit', async ({helper}) => { + const [alice, ...accounts] = await helper.arrange.createAccounts([10n, 0n, 0n, 0n, 0n, 0n, 0n, 0n], donor); + const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'}); - const chainAdminLimit = (helper.api!.consts.common.collectionAdminsLimit as any).toNumber(); - expect(chainAdminLimit).to.be.equal(5); + const chainAdminLimit = (helper.api!.consts.common.collectionAdminsLimit as any).toNumber(); + expect(chainAdminLimit).to.be.equal(5); - for (let i = 0; i < chainAdminLimit; i++) { - await collection.addAdmin(alice, {Substrate: accounts[i].address}); - const adminListAfterAddAdmin = await collection.getAdmins(); - expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: accounts[i].address}); - } + for (let i = 0; i < chainAdminLimit; i++) { + await collection.addAdmin(alice, {Substrate: accounts[i].address}); + const adminListAfterAddAdmin = await collection.getAdmins(); + expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: accounts[i].address}); + } - const addExtraAdminTx = async () => collection.addAdmin(alice, {Substrate: accounts[chainAdminLimit].address}); - await expect(addExtraAdminTx()).to.be.rejected; - }); + const addExtraAdminTx = async () => collection.addAdmin(alice, {Substrate: accounts[chainAdminLimit].address}); + await expect(addExtraAdminTx()).to.be.rejectedWith(/common\.CollectionAdminCountExceeded/); }); }); --- a/tests/src/eth/nesting/nest.test.ts +++ b/tests/src/eth/nesting/nest.test.ts @@ -20,7 +20,7 @@ let donor: IKeyringPair; before(async function() { - await usingEthPlaygrounds(async (helper, privateKey) => { + await usingEthPlaygrounds(async (_, privateKey) => { donor = privateKey('//Alice'); }); }); --- a/tests/src/eth/payable.test.ts +++ b/tests/src/eth/payable.test.ts @@ -22,7 +22,7 @@ let donor: IKeyringPair; before(async function() { - await usingEthPlaygrounds(async (helper, privateKey) => { + await usingEthPlaygrounds(async (_, privateKey) => { donor = privateKey('//Alice'); }); }); --- a/tests/src/fungible.test.ts +++ b/tests/src/fungible.test.ts @@ -16,11 +16,10 @@ import {IKeyringPair} from '@polkadot/types/types'; import {U128_MAX} from './util/helpers'; - -import {usingPlaygrounds} from './util/playgrounds'; - +import {itSub, usingPlaygrounds} from './util/playgrounds'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; + chai.use(chaiAsPromised); const expect = chai.expect; @@ -35,131 +34,117 @@ }); }); - it('Create fungible collection and token', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'trest'}); - const defaultTokenId = await collection.getLastTokenId(); - expect(defaultTokenId).to.be.equal(0); + itSub('Create fungible collection and token', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'trest'}); + const defaultTokenId = await collection.getLastTokenId(); + expect(defaultTokenId).to.be.equal(0); - await collection.mint(alice, {Substrate: alice.address}, U128_MAX); - const aliceBalance = await collection.getBalance({Substrate: alice.address}); - const itemCountAfter = await collection.getLastTokenId(); + await collection.mint(alice, {Substrate: alice.address}, U128_MAX); + const aliceBalance = await collection.getBalance({Substrate: alice.address}); + const itemCountAfter = await collection.getLastTokenId(); - expect(itemCountAfter).to.be.equal(defaultTokenId); - expect(aliceBalance).to.be.equal(U128_MAX); - }); + expect(itemCountAfter).to.be.equal(defaultTokenId); + expect(aliceBalance).to.be.equal(U128_MAX); }); - it('RPC method tokenOnewrs for fungible collection and token', async () => { - await usingPlaygrounds(async (helper, privateKey) => { - const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; - const facelessCrowd = Array(7).fill(0).map((_, i) => ({Substrate: privateKey(`//Alice+${i}`).address})); + itSub('RPC method tokenOnewrs for fungible collection and token', async ({helper, privateKey}) => { + const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; + const facelessCrowd = Array(7).fill(0).map((_, i) => ({Substrate: privateKey(`//Alice+${i}`).address})); - const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - await collection.mint(alice, {Substrate: alice.address}, U128_MAX); + await collection.mint(alice, {Substrate: alice.address}, U128_MAX); - await collection.transfer(alice, {Substrate: bob.address}, 1000n); - await collection.transfer(alice, ethAcc, 900n); - - for (let i = 0; i < 7; i++) { - await collection.transfer(alice, facelessCrowd[i], 1n); - } + await collection.transfer(alice, {Substrate: bob.address}, 1000n); + await collection.transfer(alice, ethAcc, 900n); + + for (let i = 0; i < 7; i++) { + await collection.transfer(alice, facelessCrowd[i], 1n); + } - const owners = await collection.getTop10Owners(); + const owners = await collection.getTop10Owners(); - // What to expect - expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]); - expect(owners.length).to.be.equal(10); - - const eleven = privateKey('//ALice+11'); - expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true; - expect((await collection.getTop10Owners()).length).to.be.equal(10); - }); + // What to expect + expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]); + expect(owners.length).to.be.equal(10); + + const eleven = privateKey('//ALice+11'); + expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true; + expect((await collection.getTop10Owners()).length).to.be.equal(10); }); - it('Transfer token', async () => { - await usingPlaygrounds(async helper => { - const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; - const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - await collection.mint(alice, {Substrate: alice.address}, 500n); + itSub('Transfer token', async ({helper}) => { + const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; + const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + await collection.mint(alice, {Substrate: alice.address}, 500n); - expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(500n); - expect(await collection.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true; - expect(await collection.transfer(alice, ethAcc, 140n)).to.be.true; + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(500n); + expect(await collection.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true; + expect(await collection.transfer(alice, ethAcc, 140n)).to.be.true; - expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(300n); - expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(60n); - expect(await collection.getBalance(ethAcc)).to.be.equal(140n); + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(300n); + expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(60n); + expect(await collection.getBalance(ethAcc)).to.be.equal(140n); - await expect(collection.transfer(alice, {Substrate: bob.address}, 350n)).to.eventually.be.rejected; - }); + await expect(collection.transfer(alice, {Substrate: bob.address}, 350n)).to.eventually.be.rejected; }); - it('Tokens multiple creation', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + itSub('Tokens multiple creation', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - await collection.mintWithOneOwner(alice, {Substrate: alice.address}, [ - {value: 500n}, - {value: 400n}, - {value: 300n}, - ]); + await collection.mintWithOneOwner(alice, {Substrate: alice.address}, [ + {value: 500n}, + {value: 400n}, + {value: 300n}, + ]); - expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1200n); - }); + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1200n); }); - it('Burn some tokens ', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - await collection.mint(alice, {Substrate: alice.address}, 500n); + itSub('Burn some tokens ', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + await collection.mint(alice, {Substrate: alice.address}, 500n); - expect(await collection.isTokenExists(0)).to.be.true; - expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(500n); - expect(await collection.burnTokens(alice, 499n)).to.be.true; - expect(await collection.isTokenExists(0)).to.be.true; - expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n); - }); + expect(await collection.isTokenExists(0)).to.be.true; + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(500n); + expect(await collection.burnTokens(alice, 499n)).to.be.true; + expect(await collection.isTokenExists(0)).to.be.true; + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n); }); - it('Burn all tokens ', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - await collection.mint(alice, {Substrate: alice.address}, 500n); + itSub('Burn all tokens ', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + await collection.mint(alice, {Substrate: alice.address}, 500n); - expect(await collection.isTokenExists(0)).to.be.true; - expect(await collection.burnTokens(alice, 500n)).to.be.true; - expect(await collection.isTokenExists(0)).to.be.true; + expect(await collection.isTokenExists(0)).to.be.true; + expect(await collection.burnTokens(alice, 500n)).to.be.true; + expect(await collection.isTokenExists(0)).to.be.true; - expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(0n); - expect(await collection.getTotalPieces()).to.be.equal(0n); - }); + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(0n); + expect(await collection.getTotalPieces()).to.be.equal(0n); }); - it('Set allowance for token', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; - await collection.mint(alice, {Substrate: alice.address}, 100n); + itSub('Set allowance for token', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; + await collection.mint(alice, {Substrate: alice.address}, 100n); - expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(100n); - - expect(await collection.approveTokens(alice, {Substrate: bob.address}, 60n)).to.be.true; - expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n); - expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n); + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(100n); + + expect(await collection.approveTokens(alice, {Substrate: bob.address}, 60n)).to.be.true; + expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n); + expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n); - expect(await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: bob.address}, 20n)).to.be.true; - expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(80n); - expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(20n); - expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(40n); + expect(await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: bob.address}, 20n)).to.be.true; + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(80n); + expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(20n); + expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(40n); - await collection.burnTokensFrom(bob, {Substrate: alice.address}, 10n); + await collection.burnTokensFrom(bob, {Substrate: alice.address}, 10n); - expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(70n); - expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(30n); - expect(await collection.transferFrom(bob, {Substrate: alice.address}, ethAcc, 10n)).to.be.true; - expect(await collection.getBalance(ethAcc)).to.be.equal(10n); - }); + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(70n); + expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(30n); + expect(await collection.transferFrom(bob, {Substrate: alice.address}, ethAcc, 10n)).to.be.true; + expect(await collection.getBalance(ethAcc)).to.be.equal(10n); }); }); --- a/tests/src/overflow.test.ts +++ b/tests/src/overflow.test.ts @@ -23,6 +23,7 @@ chai.use(chaiAsPromised); const expect = chai.expect; +// todo:playgrounds skipped ~ postponed describe.skip('Integration Test fungible overflows', () => { let alice: IKeyringPair; let bob: IKeyringPair; --- a/tests/src/pallet-presence.test.ts +++ b/tests/src/pallet-presence.test.ts @@ -14,13 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -import {ApiPromise} from '@polkadot/api'; import {expect} from 'chai'; -import usingApi from './substrate/substrate-api'; - -function getModuleNames(api: ApiPromise): string[] { - return api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase()); -} +import {itSub, usingPlaygrounds} from './util/playgrounds'; // Pallets that must always be present const requiredPallets = [ @@ -62,8 +57,8 @@ describe('Pallet presence', () => { before(async () => { - await usingApi(async api => { - const chain = await api.rpc.system.chain(); + await usingPlaygrounds(async helper => { + const chain = await helper.api!.rpc.system.chain(); const refungible = 'refungible'; const scheduler = 'scheduler'; @@ -80,23 +75,15 @@ }); }); - it('Required pallets are present', async () => { - await usingApi(async api => { - for (let i=0; i { + expect(helper.fetchAllPalletNames()).to.contain.members([...requiredPallets]); }); - it('Governance and consensus pallets are present', async () => { - await usingApi(async api => { - for (let i=0; i { + expect(helper.fetchAllPalletNames()).to.contain.members([...consensusPallets]); }); - it('No extra pallets are included', async () => { - await usingApi(async api => { - expect(getModuleNames(api).sort()).to.be.deep.equal([...requiredPallets, ...consensusPallets].sort()); - }); + + itSub('No extra pallets are included', async ({helper}) => { + expect(helper.fetchAllPalletNames().sort()).to.be.deep.equal([...requiredPallets, ...consensusPallets].sort()); }); }); --- a/tests/src/refungible.test.ts +++ b/tests/src/refungible.test.ts @@ -15,13 +15,7 @@ // along with Unique Network. If not, see . import {IKeyringPair} from '@polkadot/types/types'; - -import {usingPlaygrounds} from './util/playgrounds'; -import { - getModuleNames, - Pallets, - requirePallets, -} from './util/helpers'; +import {itSub, Pallets, requirePalletsOrSkip, usingPlaygrounds} from './util/playgrounds'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; @@ -34,255 +28,231 @@ describe('integration test: Refungible functionality:', async () => { before(async function() { - await requirePallets(this, [Pallets.ReFungible]); + await usingPlaygrounds(async (helper, privateKey) => { + requirePalletsOrSkip(this, helper, [Pallets.ReFungible]); - await usingPlaygrounds(async (helper, privateKey) => { alice = privateKey('//Alice'); bob = privateKey('//Bob'); - if (!getModuleNames(helper.api!).includes(Pallets.ReFungible)) this.skip(); }); }); - it('Create refungible collection and token', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + itSub('Create refungible collection and token', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const itemCountBefore = await collection.getLastTokenId(); - const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); - - const itemCountAfter = await collection.getLastTokenId(); - - // What to expect - expect(token?.tokenId).to.be.gte(itemCountBefore); - expect(itemCountAfter).to.be.equal(itemCountBefore + 1); - expect(itemCountAfter.toString()).to.be.equal(token?.tokenId.toString()); - }); + const itemCountBefore = await collection.getLastTokenId(); + const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); + + const itemCountAfter = await collection.getLastTokenId(); + + // What to expect + expect(token?.tokenId).to.be.gte(itemCountBefore); + expect(itemCountAfter).to.be.equal(itemCountBefore + 1); + expect(itemCountAfter.toString()).to.be.equal(token?.tokenId.toString()); }); - it('Checking RPC methods when interacting with maximum allowed values (MAX_REFUNGIBLE_PIECES)', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - - const token = await collection.mintToken(alice, {Substrate: alice.address}, MAX_REFUNGIBLE_PIECES); - - expect(await collection.getTokenBalance(token.tokenId, {Substrate: alice.address})).to.be.equal(MAX_REFUNGIBLE_PIECES); - - await collection.transferToken(alice, token.tokenId, {Substrate: bob.address}, MAX_REFUNGIBLE_PIECES); - expect(await collection.getTokenBalance(token.tokenId, {Substrate: bob.address})).to.be.equal(MAX_REFUNGIBLE_PIECES); - expect(await token.getTotalPieces()).to.be.equal(MAX_REFUNGIBLE_PIECES); - - await expect(collection.mintToken(alice, {Substrate: alice.address}, MAX_REFUNGIBLE_PIECES + 1n)).to.eventually.be.rejected; - }); + itSub('Checking RPC methods when interacting with maximum allowed values (MAX_REFUNGIBLE_PIECES)', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + + const token = await collection.mintToken(alice, {Substrate: alice.address}, MAX_REFUNGIBLE_PIECES); + + expect(await collection.getTokenBalance(token.tokenId, {Substrate: alice.address})).to.be.equal(MAX_REFUNGIBLE_PIECES); + + await collection.transferToken(alice, token.tokenId, {Substrate: bob.address}, MAX_REFUNGIBLE_PIECES); + expect(await collection.getTokenBalance(token.tokenId, {Substrate: bob.address})).to.be.equal(MAX_REFUNGIBLE_PIECES); + expect(await token.getTotalPieces()).to.be.equal(MAX_REFUNGIBLE_PIECES); + + await expect(collection.mintToken(alice, {Substrate: alice.address}, MAX_REFUNGIBLE_PIECES + 1n)) + .to.eventually.be.rejectedWith(/refungible\.WrongRefungiblePieces/); }); - it('RPC method tokenOnewrs for refungible collection and token', async () => { - await usingPlaygrounds(async (helper, privateKey) => { - const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; - const facelessCrowd = Array(7).fill(0).map((_, i) => ({Substrate: privateKey(`//Alice+${i}`).address})); + itSub('RPC method tokenOnewrs for refungible collection and token', async ({helper, privateKey}) => { + const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; + const facelessCrowd = Array(7).fill(0).map((_, i) => ({Substrate: privateKey(`//Alice+${i}`).address})); - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const token = await collection.mintToken(alice, {Substrate: alice.address}, 10_000n); + const token = await collection.mintToken(alice, {Substrate: alice.address}, 10_000n); - await token.transfer(alice, {Substrate: bob.address}, 1000n); - await token.transfer(alice, ethAcc, 900n); - - for (let i = 0; i < 7; i++) { - await token.transfer(alice, facelessCrowd[i], 50n * BigInt(i + 1)); - } + await token.transfer(alice, {Substrate: bob.address}, 1000n); + await token.transfer(alice, ethAcc, 900n); + + for (let i = 0; i < 7; i++) { + await token.transfer(alice, facelessCrowd[i], 50n * BigInt(i + 1)); + } - const owners = await token.getTop10Owners(); + const owners = await token.getTop10Owners(); - // What to expect - expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]); - expect(owners.length).to.be.equal(10); - - const eleven = privateKey('//ALice+11'); - expect(await token.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true; - expect((await token.getTop10Owners()).length).to.be.equal(10); - }); + // What to expect + expect(owners).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]); + expect(owners.length).to.be.equal(10); + + const eleven = privateKey('//ALice+11'); + expect(await token.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true; + expect((await token.getTop10Owners()).length).to.be.equal(10); }); - it('Transfer token pieces', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); + itSub('Transfer token pieces', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); - expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true; - - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n); - expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n); - - await expect(token.transfer(alice, {Substrate: bob.address}, 41n)).to.eventually.be.rejected; - }); + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); + expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true; + + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n); + expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n); + + await expect(token.transfer(alice, {Substrate: bob.address}, 41n)) + .to.eventually.be.rejectedWith(/common\.TokenValueTooLow/); }); - it('Create multiple tokens', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - // TODO: fix mintMultipleTokens - // await collection.mintMultipleTokens(alice, [ - // {owner: {Substrate: alice.address}, pieces: 1n}, - // {owner: {Substrate: alice.address}, pieces: 2n}, - // {owner: {Substrate: alice.address}, pieces: 100n}, - // ]); - await helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, [ - {pieces: 1n}, - {pieces: 2n}, - {pieces: 100n}, - ]); - const lastTokenId = await collection.getLastTokenId(); - expect(lastTokenId).to.be.equal(3); - expect(await collection.getTokenBalance(lastTokenId, {Substrate: alice.address})).to.be.equal(100n); - }); + itSub('Create multiple tokens', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + // TODO: fix mintMultipleTokens + // await collection.mintMultipleTokens(alice, [ + // {owner: {Substrate: alice.address}, pieces: 1n}, + // {owner: {Substrate: alice.address}, pieces: 2n}, + // {owner: {Substrate: alice.address}, pieces: 100n}, + // ]); + await helper.rft.mintMultipleTokensWithOneOwner(alice, collection.collectionId, {Substrate: alice.address}, [ + {pieces: 1n}, + {pieces: 2n}, + {pieces: 100n}, + ]); + const lastTokenId = await collection.getLastTokenId(); + expect(lastTokenId).to.be.equal(3); + expect(await collection.getTokenBalance(lastTokenId, {Substrate: alice.address})).to.be.equal(100n); }); - it('Burn some pieces', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); - expect(await collection.isTokenExists(token.tokenId)).to.be.true; - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); - expect((await token.burn(alice, 99n)).success).to.be.true; - expect(await collection.isTokenExists(token.tokenId)).to.be.true; - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(1n); - }); + itSub('Burn some pieces', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); + expect(await collection.isTokenExists(token.tokenId)).to.be.true; + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); + expect((await token.burn(alice, 99n)).success).to.be.true; + expect(await collection.isTokenExists(token.tokenId)).to.be.true; + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(1n); }); - it('Burn all pieces', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); - - expect(await collection.isTokenExists(token.tokenId)).to.be.true; - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); + itSub('Burn all pieces', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); + + expect(await collection.isTokenExists(token.tokenId)).to.be.true; + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); - expect((await token.burn(alice, 100n)).success).to.be.true; - expect(await collection.isTokenExists(token.tokenId)).to.be.false; - }); + expect((await token.burn(alice, 100n)).success).to.be.true; + expect(await collection.isTokenExists(token.tokenId)).to.be.false; }); - it('Burn some pieces for multiple users', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); + itSub('Burn some pieces for multiple users', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); - expect(await collection.isTokenExists(token.tokenId)).to.be.true; - - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); - expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true; + expect(await collection.isTokenExists(token.tokenId)).to.be.true; + + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); + expect(await token.transfer(alice, {Substrate: bob.address}, 60n)).to.be.true; - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n); - expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n); + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(40n); + expect(await token.getBalance({Substrate: bob.address})).to.be.equal(60n); - expect((await token.burn(alice, 40n)).success).to.be.true; + expect((await token.burn(alice, 40n)).success).to.be.true; - expect(await collection.isTokenExists(token.tokenId)).to.be.true; - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n); + expect(await collection.isTokenExists(token.tokenId)).to.be.true; + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n); - expect((await token.burn(bob, 59n)).success).to.be.true; + expect((await token.burn(bob, 59n)).success).to.be.true; - expect(await token.getBalance({Substrate: bob.address})).to.be.equal(1n); - expect(await collection.isTokenExists(token.tokenId)).to.be.true; + expect(await token.getBalance({Substrate: bob.address})).to.be.equal(1n); + expect(await collection.isTokenExists(token.tokenId)).to.be.true; - expect((await token.burn(bob, 1n)).success).to.be.true; + expect((await token.burn(bob, 1n)).success).to.be.true; - expect(await collection.isTokenExists(token.tokenId)).to.be.false; - }); + expect(await collection.isTokenExists(token.tokenId)).to.be.false; }); - it('Set allowance for token', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); - - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); + itSub('Set allowance for token', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); + + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(100n); - expect(await token.approve(alice, {Substrate: bob.address}, 60n)).to.be.true; - expect(await token.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n); + expect(await token.approve(alice, {Substrate: bob.address}, 60n)).to.be.true; + expect(await token.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(60n); - expect(await token.transferFrom(bob, {Substrate: alice.address}, {Substrate: bob.address}, 20n)).to.be.true; - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(80n); - expect(await token.getBalance({Substrate: bob.address})).to.be.equal(20n); - expect(await token.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(40n); - }); + expect(await token.transferFrom(bob, {Substrate: alice.address}, {Substrate: bob.address}, 20n)).to.be.true; + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(80n); + expect(await token.getBalance({Substrate: bob.address})).to.be.equal(20n); + expect(await token.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(40n); }); - it('Repartition', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); + itSub('Repartition', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); - expect(await token.repartition(alice, 200n)).to.be.true; - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(200n); - expect(await token.getTotalPieces()).to.be.equal(200n); - - expect(await token.transfer(alice, {Substrate: bob.address}, 110n)).to.be.true; - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(90n); - expect(await token.getBalance({Substrate: bob.address})).to.be.equal(110n); - - await expect(token.repartition(alice, 80n)).to.eventually.be.rejected; - - expect(await token.transfer(alice, {Substrate: bob.address}, 90n)).to.be.true; - expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n); - expect(await token.getBalance({Substrate: bob.address})).to.be.equal(200n); - - expect(await token.repartition(bob, 150n)).to.be.true; - await expect(token.transfer(bob, {Substrate: alice.address}, 160n)).to.eventually.be.rejected; + expect(await token.repartition(alice, 200n)).to.be.true; + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(200n); + expect(await token.getTotalPieces()).to.be.equal(200n); + + expect(await token.transfer(alice, {Substrate: bob.address}, 110n)).to.be.true; + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(90n); + expect(await token.getBalance({Substrate: bob.address})).to.be.equal(110n); + + await expect(token.repartition(alice, 80n)) + .to.eventually.be.rejectedWith(/refungible\.RepartitionWhileNotOwningAllPieces/); + + expect(await token.transfer(alice, {Substrate: bob.address}, 90n)).to.be.true; + expect(await token.getBalance({Substrate: alice.address})).to.be.equal(0n); + expect(await token.getBalance({Substrate: bob.address})).to.be.equal(200n); - }); + expect(await token.repartition(bob, 150n)).to.be.true; + await expect(token.transfer(bob, {Substrate: alice.address}, 160n)) + .to.eventually.be.rejectedWith(/common\.TokenValueTooLow/); }); - it('Repartition with increased amount', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); - await token.repartition(alice, 200n); - const chainEvents = helper.chainLog.slice(-1)[0].events.map((x: any) => x.event); - expect(chainEvents).to.include.deep.members([{ - method: 'ItemCreated', - section: 'common', - index: '0x4202', - data: [ - helper.api!.createType('u32', collection.collectionId).toHuman(), - helper.api!.createType('u32', token.tokenId).toHuman(), - {Substrate: alice.address}, - '100', - ], - }]); - }); + itSub('Repartition with increased amount', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); + await token.repartition(alice, 200n); + const chainEvents = helper.chainLog.slice(-1)[0].events.map((x: any) => x.event); + expect(chainEvents).to.include.deep.members([{ + method: 'ItemCreated', + section: 'common', + index: '0x4202', + data: [ + helper.api!.createType('u32', collection.collectionId).toHuman(), + helper.api!.createType('u32', token.tokenId).toHuman(), + {Substrate: alice.address}, + '100', + ], + }]); }); - it('Repartition with decreased amount', async () => { - await usingPlaygrounds(async helper => { - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); - await token.repartition(alice, 50n); - const chainEvents = helper.chainLog.slice(-1)[0].events.map((x: any) => x.event); - expect(chainEvents).to.include.deep.members([{ - method: 'ItemDestroyed', - section: 'common', - index: '0x4203', - data: [ - helper.api!.createType('u32', collection.collectionId).toHuman(), - helper.api!.createType('u32', token.tokenId).toHuman(), - {Substrate: alice.address}, - '50', - ], - }]); - }); + itSub('Repartition with decreased amount', async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + const token = await collection.mintToken(alice, {Substrate: alice.address}, 100n); + await token.repartition(alice, 50n); + const chainEvents = helper.chainLog.slice(-1)[0].events.map((x: any) => x.event); + expect(chainEvents).to.include.deep.members([{ + method: 'ItemDestroyed', + section: 'common', + index: '0x4203', + data: [ + helper.api!.createType('u32', collection.collectionId).toHuman(), + helper.api!.createType('u32', token.tokenId).toHuman(), + {Substrate: alice.address}, + '50', + ], + }]); }); - it('Create new collection with properties', async () => { - await usingPlaygrounds(async helper => { - const properties = [{key: 'key1', value: 'val1'}]; - const tokenPropertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}]; - const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test', properties, tokenPropertyPermissions}); - const info = await collection.getData(); - expect(info?.raw.properties).to.be.deep.equal(properties); - expect(info?.raw.tokenPropertyPermissions).to.be.deep.equal(tokenPropertyPermissions); - }); + itSub('Create new collection with properties', async ({helper}) => { + const properties = [{key: 'key1', value: 'val1'}]; + const tokenPropertyPermissions = [{key: 'key1', permission: {tokenOwner: true, mutable: false, collectionAdmin: true}}]; + const collection = await helper.rft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test', properties, tokenPropertyPermissions}); + const info = await collection.getData(); + expect(info?.raw.properties).to.be.deep.equal(properties); + expect(info?.raw.tokenPropertyPermissions).to.be.deep.equal(tokenPropertyPermissions); }); }); --- a/tests/src/removeCollectionAdmin.test.ts +++ b/tests/src/removeCollectionAdmin.test.ts @@ -16,113 +16,102 @@ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import {usingPlaygrounds} from './util/playgrounds'; +import {IKeyringPair} from '@polkadot/types/types'; +import {itSub, usingPlaygrounds} from './util/playgrounds'; chai.use(chaiAsPromised); const expect = chai.expect; describe('Integration Test removeCollectionAdmin(collection_id, account_id):', () => { - it('Remove collection admin.', async () => { + let alice: IKeyringPair; + let bob: IKeyringPair; + + before(async () => { await usingPlaygrounds(async (helper, privateKey) => { - const alice = privateKey('//Alice'); - const bob = privateKey('//Bob'); - const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - - const collectionInfo = await collection.getData(); - expect(collectionInfo?.raw.owner.toString()).to.be.deep.eq(alice.address); - // first - add collection admin Bob - await collection.addAdmin(alice, {Substrate: bob.address}); + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor); + }); + }); - const adminListAfterAddAdmin = await collection.getAdmins(); - expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)}); + itSub('Remove collection admin', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-1', tokenPrefix: 'RCA'}); + const collectionInfo = await collection.getData(); + expect(collectionInfo?.raw.owner.toString()).to.be.deep.eq(alice.address); + // first - add collection admin Bob + await collection.addAdmin(alice, {Substrate: bob.address}); + + const adminListAfterAddAdmin = await collection.getAdmins(); + expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address}); - // then remove bob from admins of collection - await collection.removeAdmin(alice, {Substrate: bob.address}); + // then remove bob from admins of collection + await collection.removeAdmin(alice, {Substrate: bob.address}); - const adminListAfterRemoveAdmin = await collection.getAdmins(); - expect(adminListAfterRemoveAdmin).not.to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)}); - }); + const adminListAfterRemoveAdmin = await collection.getAdmins(); + expect(adminListAfterRemoveAdmin).not.to.be.deep.contains({Substrate: bob.address}); }); - it('Remove admin from collection that has no admins', async () => { - await usingPlaygrounds(async (helper, privateKey) => { - const alice = privateKey('//Alice'); - const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + itSub('Remove admin from collection that has no admins', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-2', tokenPrefix: 'RCA'}); - const adminListBeforeAddAdmin = await collection.getAdmins(); - expect(adminListBeforeAddAdmin).to.have.lengthOf(0); + const adminListBeforeAddAdmin = await collection.getAdmins(); + expect(adminListBeforeAddAdmin).to.have.lengthOf(0); - // await expect(collection.removeAdmin(alice, {Substrate: alice.address})).to.be.rejectedWith('Unable to remove collection admin'); - await collection.removeAdmin(alice, {Substrate: alice.address}); - }); + await collection.removeAdmin(alice, {Substrate: alice.address}); }); }); describe('Negative Integration Test removeCollectionAdmin(collection_id, account_id):', () => { - it('Can\'t remove collection admin from not existing collection', async () => { - await usingPlaygrounds(async (helper, privateKey) => { - // tslint:disable-next-line: no-bitwise - const collectionId = (1 << 32) - 1; - const alice = privateKey('//Alice'); - const bob = privateKey('//Bob'); - - await expect(helper.collection.removeAdmin(alice, collectionId, {Substrate: bob.address})).to.be.rejected; + let alice: IKeyringPair; + let bob: IKeyringPair; + let charlie: IKeyringPair; - // Verifying that nothing bad happened (network is live, new collections can be created, etc.) - await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + before(async () => { + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob, charlie] = await helper.arrange.createAccounts([20n, 10n, 10n], donor); }); }); - it('Can\'t remove collection admin from deleted collection', async () => { - await usingPlaygrounds(async (helper, privateKey) => { - const alice = privateKey('//Alice'); - const bob = privateKey('//Bob'); - const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + itSub('Can\'t remove collection admin from not existing collection', async ({helper}) => { + const collectionId = (1 << 32) - 1; - expect(await collection.burn(alice)).to.be.true; + await expect(helper.collection.removeAdmin(alice, collectionId, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.CollectionNotFound/); + }); - await expect(helper.collection.removeAdmin(alice, collection.collectionId, {Substrate: bob.address})).to.be.rejected; + itSub('Can\'t remove collection admin from deleted collection', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-Neg-2', tokenPrefix: 'RCA'}); - // Verifying that nothing bad happened (network is live, new collections can be created, etc.) - await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - }); - }); + expect(await collection.burn(alice)).to.be.true; - it('Regular user can\'t remove collection admin', async () => { - await usingPlaygrounds(async (helper, privateKey) => { - const alice = privateKey('//Alice'); - const bob = privateKey('//Bob'); - const charlie = privateKey('//Charlie'); - const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); + await expect(helper.collection.removeAdmin(alice, collection.collectionId, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.CollectionNotFound/); + }); - await collection.addAdmin(alice, {Substrate: bob.address}); + itSub('Regular user can\'t remove collection admin', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-Neg-3', tokenPrefix: 'RCA'}); - await expect(collection.removeAdmin(charlie, {Substrate: bob.address})).to.be.rejected; + await collection.addAdmin(alice, {Substrate: bob.address}); - // Verifying that nothing bad happened (network is live, new collections can be created, etc.) - await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - }); + await expect(collection.removeAdmin(charlie, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.NoPermission/); }); - it('Admin can\'t remove collection admin.', async () => { - await usingPlaygrounds(async (helper, privateKey) => { - const alice = privateKey('//Alice'); - const bob = privateKey('//Bob'); - const charlie = privateKey('//Charlie'); - const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'}); - - await collection.addAdmin(alice, {Substrate: bob.address}); - await collection.addAdmin(alice, {Substrate: charlie.address}); + itSub('Admin can\'t remove collection admin.', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionAdmin-Neg-4', tokenPrefix: 'RCA'}); + + await collection.addAdmin(alice, {Substrate: bob.address}); + await collection.addAdmin(alice, {Substrate: charlie.address}); - const adminListAfterAddAdmin = await collection.getAdmins(); - expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)}); - expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(charlie.address)}); + const adminListAfterAddAdmin = await collection.getAdmins(); + expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: bob.address}); + expect(adminListAfterAddAdmin).to.be.deep.contains({Substrate: charlie.address}); - await expect(collection.removeAdmin(charlie, {Substrate: bob.address})).to.be.rejected; + await expect(collection.removeAdmin(charlie, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.NoPermission/); - const adminListAfterRemoveAdmin = await collection.getAdmins(); - expect(adminListAfterRemoveAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(bob.address)}); - expect(adminListAfterRemoveAdmin).to.be.deep.contains({Substrate: helper.address.normalizeSubstrate(charlie.address)}); - }); + const adminListAfterRemoveAdmin = await collection.getAdmins(); + expect(adminListAfterRemoveAdmin).to.be.deep.contains({Substrate: bob.address}); + expect(adminListAfterRemoveAdmin).to.be.deep.contains({Substrate: charlie.address}); }); }); --- a/tests/src/removeCollectionSponsor.test.ts +++ b/tests/src/removeCollectionSponsor.test.ts @@ -16,136 +16,115 @@ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import {default as usingApi, submitTransactionExpectFailAsync} from './substrate/substrate-api'; -import { - createCollectionExpectSuccess, - setCollectionSponsorExpectSuccess, - destroyCollectionExpectSuccess, - confirmSponsorshipExpectSuccess, - confirmSponsorshipExpectFailure, - createItemExpectSuccess, - findUnusedAddress, - removeCollectionSponsorExpectSuccess, - removeCollectionSponsorExpectFailure, - normalizeAccountId, - addCollectionAdminExpectSuccess, - getCreatedCollectionCount, -} from './util/helpers'; import {IKeyringPair} from '@polkadot/types/types'; +import {itSub, usingPlaygrounds} from './util/playgrounds'; chai.use(chaiAsPromised); const expect = chai.expect; -let alice: IKeyringPair; -let bob: IKeyringPair; - describe('integration test: ext. removeCollectionSponsor():', () => { + let donor: IKeyringPair; + let alice: IKeyringPair; + let bob: IKeyringPair; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); + await usingPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor); }); }); - it('Removing NFT collection sponsor stops sponsorship', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); - await removeCollectionSponsorExpectSuccess(collectionId); + itSub('Removing NFT collection sponsor stops sponsorship', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-1', tokenPrefix: 'RCS'}); + await collection.setSponsor(alice, bob.address); + await collection.confirmSponsorship(bob); + await collection.removeSponsor(alice); - await usingApi(async (api, privateKeyWrapper) => { - // Find unused address - const zeroBalance = await findUnusedAddress(api, privateKeyWrapper); + // Find unused address + const [zeroBalance] = await helper.arrange.createAccounts([0n], donor); - // Mint token for unused address - const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address); + // Mint token for unused address + const token = await collection.mintToken(alice, {Substrate: zeroBalance.address}); - // Transfer this tokens from unused address to Alice - should fail - const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt(); - const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0); - const badTransaction = async function () { - await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice); - }; - await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees'); - const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt(); + // Transfer this tokens from unused address to Alice - should fail + const sponsorBalanceBefore = await helper.balance.getSubstrate(bob.address); + await expect(token.transfer(zeroBalance, {Substrate: alice.address})) + .to.be.rejectedWith('Inability to pay some fees'); + const sponsorBalanceAfter = await helper.balance.getSubstrate(bob.address); - expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore); - }); + expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore); }); - it('Remove a sponsor after it was already removed', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); - await removeCollectionSponsorExpectSuccess(collectionId); - await removeCollectionSponsorExpectSuccess(collectionId); + itSub('Remove a sponsor after it was already removed', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-2', tokenPrefix: 'RCS'}); + await collection.setSponsor(alice, bob.address); + await collection.confirmSponsorship(bob); + await expect(collection.removeSponsor(alice)).to.not.be.rejected; + await expect(collection.removeSponsor(alice)).to.not.be.rejected; }); - it('Remove sponsor in a collection that never had the sponsor set', async () => { - const collectionId = await createCollectionExpectSuccess(); - await removeCollectionSponsorExpectSuccess(collectionId); + itSub('Remove sponsor in a collection that never had the sponsor set', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-3', tokenPrefix: 'RCS'}); + await expect(collection.removeSponsor(alice)).to.not.be.rejected; }); - it('Remove sponsor for a collection that had the sponsor set, but not confirmed', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await removeCollectionSponsorExpectSuccess(collectionId); + itSub('Remove sponsor for a collection that had the sponsor set, but not confirmed', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-4', tokenPrefix: 'RCS'}); + await collection.setSponsor(alice, bob.address); + await expect(collection.removeSponsor(alice)).to.not.be.rejected; }); }); describe('(!negative test!) integration test: ext. removeCollectionSponsor():', () => { + let alice: IKeyringPair; + let bob: IKeyringPair; + let charlie: IKeyringPair; + before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob, charlie] = await helper.arrange.createAccounts([20n, 10n, 10n], donor); }); }); - it('(!negative test!) Remove sponsor for a collection that never existed', async () => { - // Find the collection that never existed - let collectionId = 0; - await usingApi(async (api) => { - collectionId = await getCreatedCollectionCount(api) + 1; - }); - - await removeCollectionSponsorExpectFailure(collectionId); + itSub('(!negative test!) Remove sponsor for a collection that never existed', async ({helper}) => { + const collectionId = (1 << 32) - 1; + await expect(helper.collection.removeSponsor(alice, collectionId)).to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('(!negative test!) Remove sponsor for a collection with collection admin permissions', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await addCollectionAdminExpectSuccess(alice, collectionId, bob.address); - await removeCollectionSponsorExpectFailure(collectionId, '//Bob'); + itSub('(!negative test!) Remove sponsor for a collection with collection admin permissions', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-1', tokenPrefix: 'RCS'}); + await collection.setSponsor(alice, bob.address); + await collection.addAdmin(alice, {Substrate: charlie.address}); + await expect(collection.removeSponsor(charlie)).to.be.rejectedWith(/common\.NoPermission/); }); - it('(!negative test!) Remove sponsor for a collection by regular user', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await removeCollectionSponsorExpectFailure(collectionId, '//Bob'); + itSub('(!negative test!) Remove sponsor for a collection by regular user', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-2', tokenPrefix: 'RCS'}); + await collection.setSponsor(alice, bob.address); + await expect(collection.removeSponsor(charlie)).to.be.rejectedWith(/common\.NoPermission/); }); - it('(!negative test!) Remove sponsor in a destroyed collection', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await destroyCollectionExpectSuccess(collectionId); - await removeCollectionSponsorExpectFailure(collectionId); + itSub('(!negative test!) Remove sponsor in a destroyed collection', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-3', tokenPrefix: 'RCS'}); + await collection.setSponsor(alice, bob.address); + await collection.burn(alice); + await expect(collection.removeSponsor(alice)).to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('Set - remove - confirm: fails', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await removeCollectionSponsorExpectSuccess(collectionId); - await confirmSponsorshipExpectFailure(collectionId, '//Bob'); + itSub('Set - remove - confirm: fails', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-4', tokenPrefix: 'RCS'}); + await collection.setSponsor(alice, bob.address); + await collection.removeSponsor(alice); + await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/); }); - it('Set - confirm - remove - confirm: Sponsor cannot come back', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await confirmSponsorshipExpectSuccess(collectionId, '//Bob'); - await removeCollectionSponsorExpectSuccess(collectionId); - await confirmSponsorshipExpectFailure(collectionId, '//Bob'); + itSub('Set - confirm - remove - confirm: Sponsor cannot come back', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveCollectionSponsor-Neg-5', tokenPrefix: 'RCS'}); + await collection.setSponsor(alice, bob.address); + await collection.confirmSponsorship(bob); + await collection.removeSponsor(alice); + await expect(collection.confirmSponsorship(bob)).to.be.rejectedWith(/unique\.ConfirmUnsetSponsorFail/); }); - }); --- a/tests/src/removeFromAllowList.test.ts +++ b/tests/src/removeFromAllowList.test.ts @@ -16,21 +16,8 @@ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import {default as usingApi} from './substrate/substrate-api'; -import { - createCollectionExpectSuccess, - destroyCollectionExpectSuccess, - enableAllowListExpectSuccess, - addToAllowListExpectSuccess, - removeFromAllowListExpectSuccess, - isAllowlisted, - findNotExistingCollection, - removeFromAllowListExpectFailure, - disableAllowListExpectSuccess, - normalizeAccountId, - addCollectionAdminExpectSuccess, -} from './util/helpers'; import {IKeyringPair} from '@polkadot/types/types'; +import {itSub, usingPlaygrounds} from './util/playgrounds'; chai.use(chaiAsPromised); const expect = chai.expect; @@ -40,32 +27,37 @@ let bob: IKeyringPair; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor); }); }); - it('ensure bob is not in allowlist after removal', async () => { - await usingApi(async api => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await enableAllowListExpectSuccess(alice, collectionId); - await addToAllowListExpectSuccess(alice, collectionId, bob.address); + itSub('ensure bob is not in allowlist after removal', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-1', tokenPrefix: 'RFAL'}); - await removeFromAllowListExpectSuccess(alice, collectionId, normalizeAccountId(bob.address)); - expect(await isAllowlisted(api, collectionId, bob.address)).to.be.false; - }); + const collectionInfo = await collection.getData(); + expect(collectionInfo!.raw.permissions.access).to.not.equal('AllowList'); + + await collection.setPermissions(alice, {access: 'AllowList', mintMode: true}); + await collection.addToAllowList(alice, {Substrate: bob.address}); + expect(await collection.getAllowList()).to.deep.contains({Substrate: bob.address}); + + await collection.removeFromAllowList(alice, {Substrate: bob.address}); + expect(await collection.getAllowList()).to.be.empty; }); - it('allows removal from collection with unset allowlist status', async () => { - await usingApi(async () => { - const collectionWithoutAllowlistId = await createCollectionExpectSuccess(); - await enableAllowListExpectSuccess(alice, collectionWithoutAllowlistId); - await addToAllowListExpectSuccess(alice, collectionWithoutAllowlistId, bob.address); - await disableAllowListExpectSuccess(alice, collectionWithoutAllowlistId); + itSub('allows removal from collection with unset allowlist status', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-2', tokenPrefix: 'RFAL'}); - await removeFromAllowListExpectSuccess(alice, collectionWithoutAllowlistId, normalizeAccountId(bob.address)); - }); + await collection.setPermissions(alice, {access: 'AllowList', mintMode: true}); + await collection.addToAllowList(alice, {Substrate: bob.address}); + expect(await collection.getAllowList()).to.deep.contains({Substrate: bob.address}); + + await collection.setPermissions(alice, {access: 'Normal'}); + + await collection.removeFromAllowList(alice, {Substrate: bob.address}); + expect(await collection.getAllowList()).to.be.empty; }); }); @@ -74,29 +66,26 @@ let bob: IKeyringPair; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor); }); }); - it('fails on removal from not existing collection', async () => { - await usingApi(async (api) => { - const collectionId = await findNotExistingCollection(api); - - await removeFromAllowListExpectFailure(alice, collectionId, normalizeAccountId(bob.address)); - }); + itSub('fails on removal from not existing collection', async ({helper}) => { + const nonExistentCollectionId = (1 << 32) - 1; + await expect(helper.collection.removeFromAllowList(alice, nonExistentCollectionId, {Substrate: alice.address})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('fails on removal from removed collection', async () => { - await usingApi(async () => { - const collectionId = await createCollectionExpectSuccess(); - await enableAllowListExpectSuccess(alice, collectionId); - await addToAllowListExpectSuccess(alice, collectionId, bob.address); - await destroyCollectionExpectSuccess(collectionId); + itSub('fails on removal from removed collection', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-3', tokenPrefix: 'RFAL'}); + await collection.setPermissions(alice, {access: 'AllowList', mintMode: true}); + await collection.addToAllowList(alice, {Substrate: bob.address}); - await removeFromAllowListExpectFailure(alice, collectionId, normalizeAccountId(bob.address)); - }); + await collection.burn(alice); + await expect(collection.removeFromAllowList(alice, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); }); @@ -106,41 +95,45 @@ let charlie: IKeyringPair; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - charlie = privateKeyWrapper('//Charlie'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor); }); }); - it('ensure address is not in allowlist after removal', async () => { - await usingApi(async api => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await enableAllowListExpectSuccess(alice, collectionId); - await addCollectionAdminExpectSuccess(alice, collectionId, bob.address); - await addToAllowListExpectSuccess(alice, collectionId, charlie.address); - await removeFromAllowListExpectSuccess(bob, collectionId, normalizeAccountId(charlie.address)); - expect(await isAllowlisted(api, collectionId, charlie.address)).to.be.false; - }); + itSub('ensure address is not in allowlist after removal', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-4', tokenPrefix: 'RFAL'}); + + await collection.setPermissions(alice, {access: 'AllowList', mintMode: true}); + await collection.addAdmin(alice, {Substrate: bob.address}); + + await collection.addToAllowList(bob, {Substrate: charlie.address}); + await collection.removeFromAllowList(bob, {Substrate: charlie.address}); + + expect(await collection.getAllowList()).to.be.empty; }); - it('Collection admin allowed to remove from allowlist with unset allowlist status', async () => { - await usingApi(async () => { - const collectionWithoutAllowlistId = await createCollectionExpectSuccess(); - await enableAllowListExpectSuccess(alice, collectionWithoutAllowlistId); - await addCollectionAdminExpectSuccess(alice, collectionWithoutAllowlistId, bob.address); - await addToAllowListExpectSuccess(alice, collectionWithoutAllowlistId, charlie.address); - await disableAllowListExpectSuccess(alice, collectionWithoutAllowlistId); - await removeFromAllowListExpectSuccess(bob, collectionWithoutAllowlistId, normalizeAccountId(charlie.address)); - }); + itSub('Collection admin allowed to remove from allowlist with unset allowlist status', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-5', tokenPrefix: 'RFAL'}); + + await collection.setPermissions(alice, {access: 'AllowList', mintMode: true}); + await collection.addAdmin(alice, {Substrate: bob.address}); + await collection.addToAllowList(alice, {Substrate: charlie.address}); + + await collection.setPermissions(bob, {access: 'Normal'}); + await collection.removeFromAllowList(bob, {Substrate: charlie.address}); + + expect(await collection.getAllowList()).to.be.empty; }); - it('Regular user can`t remove from allowlist', async () => { - await usingApi(async () => { - const collectionWithoutAllowlistId = await createCollectionExpectSuccess(); - await enableAllowListExpectSuccess(alice, collectionWithoutAllowlistId); - await addToAllowListExpectSuccess(alice, collectionWithoutAllowlistId, charlie.address); - await removeFromAllowListExpectFailure(bob, collectionWithoutAllowlistId, normalizeAccountId(charlie.address)); - }); + itSub('Regular user can`t remove from allowlist', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'RemoveFromAllowList-6', tokenPrefix: 'RFAL'}); + + await collection.setPermissions(alice, {access: 'AllowList', mintMode: true}); + await collection.addToAllowList(alice, {Substrate: charlie.address}); + + await expect(collection.removeFromAllowList(bob, {Substrate: charlie.address})) + .to.be.rejectedWith(/common\.NoPermission/); + expect(await collection.getAllowList()).to.deep.contain({Substrate: charlie.address}); }); }); --- a/tests/src/removeFromContractAllowList.test.ts +++ b/tests/src/removeFromContractAllowList.test.ts @@ -20,6 +20,7 @@ import {IKeyringPair} from '@polkadot/types/types'; import {expect} from 'chai'; +// todo:playgrounds skipped again describe.skip('Integration Test removeFromContractAllowList', () => { let bob: IKeyringPair; --- a/tests/src/rpc.test.ts +++ b/tests/src/rpc.test.ts @@ -1,57 +1,57 @@ import {IKeyringPair} from '@polkadot/types/types'; -import {expect} from 'chai'; -import usingApi from './substrate/substrate-api'; -import {createCollection, createCollectionExpectSuccess, createFungibleItemExpectSuccess, CrossAccountId, getTokenOwner, normalizeAccountId, transfer, U128_MAX} from './util/helpers'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import {usingPlaygrounds, itSub} from './util/playgrounds'; +import {crossAccountIdFromLower} from './util/playgrounds/unique'; -let alice: IKeyringPair; -let bob: IKeyringPair; +chai.use(chaiAsPromised); +const expect = chai.expect; +describe('integration test: RPC methods', () => { + let donor: IKeyringPair; + let alice: IKeyringPair; + let bob: IKeyringPair; -describe('integration test: RPC methods', () => { before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); + await usingPlaygrounds(async (helper, privateKey) => { + donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor); }); }); - - it('returns None for fungible collection', async () => { - await usingApi(async api => { - const collection = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - await expect(getTokenOwner(api, collection, 0)).to.be.rejectedWith(/^owner == null$/); - }); + itSub('returns None for fungible collection', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'RPC-1', tokenPrefix: 'RPC'}); + const owner = (await helper.callRpc('api.rpc.unique.tokenOwner', [collection.collectionId, 0])).toJSON() as any; + expect(owner).to.be.null; }); - it('RPC method tokenOwners for fungible collection and token', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; - const facelessCrowd = Array.from(Array(7).keys()).map(i => normalizeAccountId(privateKeyWrapper(i.toString()))); - - const createCollectionResult = await createCollection(api, alice, {mode: {type: 'Fungible', decimalPoints: 0}}); - const collectionId = createCollectionResult.collectionId; - const aliceTokenId = await createFungibleItemExpectSuccess(alice, collectionId, {Value: U128_MAX}, alice.address); - - await transfer(api, collectionId, aliceTokenId, alice, bob, 1000n); - await transfer(api, collectionId, aliceTokenId, alice, ethAcc, 900n); - - for (let i = 0; i < 7; i++) { - await transfer(api, collectionId, aliceTokenId, alice, facelessCrowd[i], 1); - } - - const owners = await api.rpc.unique.tokenOwners(collectionId, aliceTokenId); - const ids = (owners.toJSON() as CrossAccountId[]).map(s => normalizeAccountId(s)); - const aliceID = normalizeAccountId(alice); - const bobId = normalizeAccountId(bob); + itSub('RPC method tokenOwners for fungible collection and token', async ({helper}) => { + // Set-up a few token owners of all stripes + const ethAcc = {Ethereum: '0x67fb3503a61b284dc83fa96dceec4192db47dc7c'}; + const facelessCrowd = (await helper.arrange.createAccounts([0n, 0n, 0n, 0n, 0n, 0n, 0n], donor)) + .map(i => {return {Substrate: i.address};}); + + const collection = await helper.ft.mintCollection(alice, {name: 'RPC-2', tokenPrefix: 'RPC'}); + // mint some maximum (u128) amounts of tokens possible + await collection.mint(alice, {Substrate: alice.address}, (1n << 128n) - 1n); + + await collection.transfer(alice, {Substrate: bob.address}, 1000n); + await collection.transfer(alice, ethAcc, 900n); + + for (let i = 0; i < facelessCrowd.length; i++) { + await collection.transfer(alice, facelessCrowd[i], 1n); + } + // Set-up over + + const owners = await helper.callRpc('api.rpc.unique.tokenOwners', [collection.collectionId, 0]); + const ids = (owners.toJSON() as any[]).map(crossAccountIdFromLower); - // What to expect - // tslint:disable-next-line:no-unused-expression - expect(ids).to.deep.include.members([aliceID, ethAcc, bobId, ...facelessCrowd]); - expect(owners.length == 10).to.be.true; - - const eleven = privateKeyWrapper('11'); - expect(await transfer(api, collectionId, aliceTokenId, alice, eleven, 10n)).to.be.true; - expect((await api.rpc.unique.tokenOwners(collectionId, aliceTokenId)).length).to.be.equal(10); - }); + expect(ids).to.deep.include.members([{Substrate: alice.address}, ethAcc, {Substrate: bob.address}, ...facelessCrowd]); + expect(owners.length == 10).to.be.true; + + // Make sure only 10 results are returned with this RPC + const [eleven] = await helper.arrange.createAccounts([0n], donor); + expect(await collection.transfer(alice, {Substrate: eleven.address}, 10n)).to.be.true; + expect((await helper.callRpc('api.rpc.unique.tokenOwners', [collection.collectionId, 0])).length).to.be.equal(10); }); }); \ No newline at end of file --- a/tests/src/scheduler.test.ts +++ b/tests/src/scheduler.test.ts @@ -44,6 +44,7 @@ chai.use(chaiAsPromised); +// todo:playgrounds skipped ~ postponed describe.skip('Scheduling token and balance transfers', () => { let alice: IKeyringPair; let bob: IKeyringPair; --- a/tests/src/setChainLimits.test.ts +++ b/tests/src/setChainLimits.test.ts @@ -23,6 +23,7 @@ IChainLimits, } from './util/helpers'; +// todo:playgrounds skipped ~ postponed describe.skip('Negative Integration Test setChainLimits', () => { let alice: IKeyringPair; let bob: IKeyringPair; --- a/tests/src/setCollectionLimits.test.ts +++ b/tests/src/setCollectionLimits.test.ts @@ -15,26 +15,13 @@ // along with Unique Network. If not, see . // https://unique-network.readthedocs.io/en/latest/jsapi.html#setchainlimits -import {ApiPromise} from '@polkadot/api'; import {IKeyringPair} from '@polkadot/types/types'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import usingApi, {submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api'; -import { - createCollectionExpectSuccess, getCreatedCollectionCount, - getCreateItemResult, - setCollectionLimitsExpectFailure, - setCollectionLimitsExpectSuccess, - addCollectionAdminExpectSuccess, - queryCollectionExpectSuccess, -} from './util/helpers'; +import {itSub, usingPlaygrounds} from './util/playgrounds'; chai.use(chaiAsPromised); const expect = chai.expect; - -let alice: IKeyringPair; -let bob: IKeyringPair; -let collectionIdForTesting: number; const accountTokenOwnershipLimit = 0; const sponsoredDataSize = 0; @@ -42,197 +29,177 @@ const tokenLimit = 10; describe('setCollectionLimits positive', () => { - let tx; + let alice: IKeyringPair; + let bob: IKeyringPair; + before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}}); - }); - }); - it('execute setCollectionLimits with predefined params ', async () => { - await usingApi(async (api: ApiPromise) => { - tx = api.tx.unique.setCollectionLimits( - collectionIdForTesting, - { - accountTokenOwnershipLimit: accountTokenOwnershipLimit, - sponsoredDataSize: sponsoredDataSize, - tokenLimit: tokenLimit, - sponsorTransferTimeout, - ownerCanTransfer: true, - ownerCanDestroy: true, - }, - ); - const events = await submitTransactionAsync(alice, tx); - const result = getCreateItemResult(events); - - // get collection limits defined previously - const collectionInfo = await queryCollectionExpectSuccess(api, collectionIdForTesting); - - // tslint:disable-next-line:no-unused-expression - expect(result.success).to.be.true; - expect(collectionInfo.limits.accountTokenOwnershipLimit.unwrap().toNumber()).to.be.equal(accountTokenOwnershipLimit); - expect(collectionInfo.limits.sponsoredDataSize.unwrap().toNumber()).to.be.equal(sponsoredDataSize); - expect(collectionInfo.limits.tokenLimit.unwrap().toNumber()).to.be.equal(tokenLimit); - expect(collectionInfo.limits.sponsorTransferTimeout.unwrap().toNumber()).to.be.equal(sponsorTransferTimeout); - expect(collectionInfo.limits.ownerCanTransfer.unwrap().toJSON()).to.be.true; - expect(collectionInfo.limits.ownerCanDestroy.unwrap().toJSON()).to.be.true; + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor); }); }); - it('Set the same token limit twice', async () => { - await usingApi(async (api: ApiPromise) => { + itSub('execute setCollectionLimits with predefined params', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-1', tokenPrefix: 'SCL'}); - const collectionLimits = { - accountTokenOwnershipLimit: accountTokenOwnershipLimit, - sponsoredMintSize: sponsoredDataSize, - tokenLimit: tokenLimit, + await collection.setLimits( + alice, + { + accountTokenOwnershipLimit, + sponsoredDataSize, + tokenLimit, sponsorTransferTimeout, ownerCanTransfer: true, ownerCanDestroy: true, - }; + }, + ); - // The first time - const tx1 = api.tx.unique.setCollectionLimits( - collectionIdForTesting, - collectionLimits, - ); - const events1 = await submitTransactionAsync(alice, tx1); - const result1 = getCreateItemResult(events1); - expect(result1.success).to.be.true; - const collectionInfo1 = await queryCollectionExpectSuccess(api, collectionIdForTesting); - expect(collectionInfo1.limits.tokenLimit.unwrap().toNumber()).to.be.equal(tokenLimit); + // get collection limits defined previously + const collectionInfo = await collection.getEffectiveLimits(); - // The second time - const tx2 = api.tx.unique.setCollectionLimits( - collectionIdForTesting, - collectionLimits, - ); - const events2 = await submitTransactionAsync(alice, tx2); - const result2 = getCreateItemResult(events2); - expect(result2.success).to.be.true; - const collectionInfo2 = await queryCollectionExpectSuccess(api, collectionIdForTesting); - expect(collectionInfo2.limits.tokenLimit.unwrap().toNumber()).to.be.equal(tokenLimit); - }); + expect(collectionInfo.accountTokenOwnershipLimit).to.be.equal(accountTokenOwnershipLimit); + expect(collectionInfo.sponsoredDataSize).to.be.equal(sponsoredDataSize); + expect(collectionInfo.tokenLimit).to.be.equal(tokenLimit); + expect(collectionInfo.sponsorTransferTimeout).to.be.equal(sponsorTransferTimeout); + expect(collectionInfo.ownerCanTransfer).to.be.true; + expect(collectionInfo.ownerCanDestroy).to.be.true; }); - it('execute setCollectionLimits from admin collection', async () => { - await addCollectionAdminExpectSuccess(alice, collectionIdForTesting, bob.address); - await usingApi(async (api: ApiPromise) => { - tx = api.tx.unique.setCollectionLimits( - collectionIdForTesting, - { - accountTokenOwnershipLimit, - sponsoredDataSize, - // sponsoredMintSize, - tokenLimit, - }, - ); - await expect(submitTransactionAsync(bob, tx)).to.be.not.rejected; - }); + itSub('Set the same token limit twice', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-2', tokenPrefix: 'SCL'}); + + const collectionLimits = { + accountTokenOwnershipLimit, + sponsoredDataSize, + tokenLimit, + sponsorTransferTimeout, + ownerCanTransfer: true, + ownerCanDestroy: true, + }; + + await collection.setLimits(alice, collectionLimits); + + const collectionInfo1 = await collection.getEffectiveLimits(); + + expect(collectionInfo1.tokenLimit).to.be.equal(tokenLimit); + + await collection.setLimits(alice, collectionLimits); + const collectionInfo2 = await collection.getEffectiveLimits(); + expect(collectionInfo2.tokenLimit).to.be.equal(tokenLimit); }); + + itSub('execute setCollectionLimits from admin collection', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-3', tokenPrefix: 'SCL'}); + await collection.addAdmin(alice, {Substrate: bob.address}); + + const collectionLimits = { + accountTokenOwnershipLimit, + sponsoredDataSize, + // sponsoredMintSize, + tokenLimit, + }; + + await expect(collection.setLimits(alice, collectionLimits)).to.not.be.rejected; + }); }); describe('setCollectionLimits negative', () => { - let tx; + let alice: IKeyringPair; + let bob: IKeyringPair; + before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}}); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([20n, 10n], donor); }); }); - it('execute setCollectionLimits for not exists collection', async () => { - await usingApi(async (api: ApiPromise) => { - const collectionCount = await getCreatedCollectionCount(api); - const nonExistedCollectionId = collectionCount + 1; - tx = api.tx.unique.setCollectionLimits( - nonExistedCollectionId, - { - accountTokenOwnershipLimit, - sponsoredDataSize, - // sponsoredMintSize, - tokenLimit, - }, - ); - await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected; - }); + + itSub('execute setCollectionLimits for not exists collection', async ({helper}) => { + const nonExistentCollectionId = (1 << 32) - 1; + await expect(helper.collection.setLimits( + alice, + nonExistentCollectionId, + { + accountTokenOwnershipLimit, + sponsoredDataSize, + // sponsoredMintSize, + tokenLimit, + }, + )).to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('execute setCollectionLimits from user who is not owner of this collection', async () => { - await usingApi(async (api: ApiPromise) => { - tx = api.tx.unique.setCollectionLimits( - collectionIdForTesting, - { - accountTokenOwnershipLimit, - sponsoredDataSize, - // sponsoredMintSize, - tokenLimit, - }, - ); - await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected; - }); + + itSub('execute setCollectionLimits from user who is not owner of this collection', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-Neg-1', tokenPrefix: 'SCL'}); + + await expect(collection.setLimits(bob, { + accountTokenOwnershipLimit, + sponsoredDataSize, + // sponsoredMintSize, + tokenLimit, + })).to.be.rejectedWith(/common\.NoPermission/); }); - it('fails when trying to enable OwnerCanTransfer after it was disabled', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionLimitsExpectSuccess(alice, collectionId, { - accountTokenOwnershipLimit: accountTokenOwnershipLimit, - sponsoredMintSize: sponsoredDataSize, - tokenLimit: tokenLimit, + itSub('fails when trying to enable OwnerCanTransfer after it was disabled', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-Neg-2', tokenPrefix: 'SCL'}); + + await collection.setLimits(alice, { + accountTokenOwnershipLimit, + sponsoredDataSize, + tokenLimit, sponsorTransferTimeout, ownerCanTransfer: false, ownerCanDestroy: true, }); - await setCollectionLimitsExpectFailure(alice, collectionId, { - accountTokenOwnershipLimit: accountTokenOwnershipLimit, - sponsoredMintSize: sponsoredDataSize, - tokenLimit: tokenLimit, + + await expect(collection.setLimits(alice, { + accountTokenOwnershipLimit, + sponsoredDataSize, + tokenLimit, sponsorTransferTimeout, ownerCanTransfer: true, ownerCanDestroy: true, - }); + })).to.be.rejectedWith(/common\.OwnerPermissionsCantBeReverted/); }); - it('fails when trying to enable OwnerCanDestroy after it was disabled', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionLimitsExpectSuccess(alice, collectionId, { - accountTokenOwnershipLimit: accountTokenOwnershipLimit, - sponsoredMintSize: sponsoredDataSize, - tokenLimit: tokenLimit, + itSub('fails when trying to enable OwnerCanDestroy after it was disabled', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-Neg-3', tokenPrefix: 'SCL'}); + + await collection.setLimits(alice, { + accountTokenOwnershipLimit, + sponsoredDataSize, + tokenLimit, sponsorTransferTimeout, ownerCanTransfer: true, ownerCanDestroy: false, }); - await setCollectionLimitsExpectFailure(alice, collectionId, { + + await expect(collection.setLimits(alice, { + accountTokenOwnershipLimit, + sponsoredDataSize, + tokenLimit, + sponsorTransferTimeout, + ownerCanTransfer: true, + ownerCanDestroy: true, + })).to.be.rejectedWith(/common\.OwnerPermissionsCantBeReverted/); + }); + + itSub('Setting the higher token limit fails', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionLimits-Neg-4', tokenPrefix: 'SCL'}); + + const collectionLimits = { accountTokenOwnershipLimit: accountTokenOwnershipLimit, sponsoredMintSize: sponsoredDataSize, tokenLimit: tokenLimit, sponsorTransferTimeout, ownerCanTransfer: true, ownerCanDestroy: true, - }); - }); + }; - it('Setting the higher token limit fails', async () => { - await usingApi(async () => { + // The first time + await collection.setLimits(alice, collectionLimits); - const collectionId = await createCollectionExpectSuccess(); - const collectionLimits = { - accountTokenOwnershipLimit: accountTokenOwnershipLimit, - sponsoredMintSize: sponsoredDataSize, - tokenLimit: tokenLimit, - sponsorTransferTimeout, - ownerCanTransfer: true, - ownerCanDestroy: true, - }; - - // The first time - await setCollectionLimitsExpectSuccess(alice, collectionId, collectionLimits); - - // The second time - higher token limit - collectionLimits.tokenLimit += 1; - await setCollectionLimitsExpectFailure(alice, collectionId, collectionLimits); - }); + // The second time - higher token limit + collectionLimits.tokenLimit += 1; + await expect(collection.setLimits(alice, collectionLimits)).to.be.rejectedWith(/common\.CollectionTokenLimitExceeded/); }); - }); --- a/tests/src/setCollectionSponsor.test.ts +++ b/tests/src/setCollectionSponsor.test.ts @@ -16,91 +16,109 @@ import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import {default as usingApi} from './substrate/substrate-api'; -import {createCollectionExpectSuccess, - setCollectionSponsorExpectSuccess, - destroyCollectionExpectSuccess, - setCollectionSponsorExpectFailure, - addCollectionAdminExpectSuccess, - getCreatedCollectionCount, - requirePallets, - Pallets, -} from './util/helpers'; import {IKeyringPair} from '@polkadot/types/types'; +import {itSub, usingPlaygrounds, Pallets} from './util/playgrounds'; chai.use(chaiAsPromised); - -let alice: IKeyringPair; -let bob: IKeyringPair; -let charlie: IKeyringPair; +const expect = chai.expect; describe('integration test: ext. setCollectionSponsor():', () => { + 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'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob, charlie] = await helper.arrange.createAccounts([20n, 10n, 10n], donor); }); }); - it('Set NFT collection sponsor', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); + itSub('Set NFT collection sponsor', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-1-NFT', tokenPrefix: 'SCS'}); + await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected; + + expect((await collection.getData())?.raw.sponsorship).to.deep.equal({ + Unconfirmed: bob.address, + }); }); - it('Set Fungible collection sponsor', async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); + + itSub('Set Fungible collection sponsor', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'SetCollectionSponsor-1-FT', tokenPrefix: 'SCS'}); + await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected; + + expect((await collection.getData())?.raw.sponsorship).to.deep.equal({ + Unconfirmed: bob.address, + }); }); - it('Set ReFungible collection sponsor', async function() { - await requirePallets(this, [Pallets.ReFungible]); - const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); + itSub.ifWithPallets('Set ReFungible collection sponsor', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'SetCollectionSponsor-1-RFT', tokenPrefix: 'SCS'}); + await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected; + + expect((await collection.getData())?.raw.sponsorship).to.deep.equal({ + Unconfirmed: bob.address, + }); }); - it('Set the same sponsor repeatedly', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); + itSub('Set the same sponsor repeatedly', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-2', tokenPrefix: 'SCS'}); + await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected; + await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected; + + expect((await collection.getData())?.raw.sponsorship).to.deep.equal({ + Unconfirmed: bob.address, + }); }); - it('Replace collection sponsor', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectSuccess(collectionId, bob.address); - await setCollectionSponsorExpectSuccess(collectionId, charlie.address); + + itSub('Replace collection sponsor', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-3', tokenPrefix: 'SCS'}); + await expect(collection.setSponsor(alice, bob.address)).to.be.not.rejected; + await expect(collection.setSponsor(alice, charlie.address)).to.be.not.rejected; + + expect((await collection.getData())?.raw.sponsorship).to.deep.equal({ + Unconfirmed: charlie.address, + }); }); - it('Collection admin add sponsor', async () => { - const collectionId = await createCollectionExpectSuccess(); - await addCollectionAdminExpectSuccess(alice, collectionId, bob.address); - await setCollectionSponsorExpectSuccess(collectionId, charlie.address, '//Bob'); + + itSub('Collection admin add sponsor', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-4', tokenPrefix: 'SCS'}); + await collection.addAdmin(alice, {Substrate: bob.address}); + await expect(collection.setSponsor(bob, charlie.address)).to.be.not.rejected; + + expect((await collection.getData())?.raw.sponsorship).to.deep.equal({ + Unconfirmed: charlie.address, + }); }); }); describe('(!negative test!) integration test: ext. setCollectionSponsor():', () => { + let alice: IKeyringPair; + let bob: IKeyringPair; + before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - charlie = privateKeyWrapper('//Charlie'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([10n, 5n], donor); }); }); - it('(!negative test!) Add sponsor with a non-owner', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionSponsorExpectFailure(collectionId, bob.address, '//Bob'); + itSub('(!negative test!) Add sponsor with a non-owner', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-Neg-1', tokenPrefix: 'SCS'}); + await expect(collection.setSponsor(bob, bob.address)) + .to.be.rejectedWith(/common\.NoPermission/); }); - it('(!negative test!) Add sponsor to a collection that never existed', async () => { - // Find the collection that never existed - let collectionId = 0; - await usingApi(async (api) => { - collectionId = await getCreatedCollectionCount(api) + 1; - }); - await setCollectionSponsorExpectFailure(collectionId, bob.address); + itSub('(!negative test!) Add sponsor to a collection that never existed', async ({helper}) => { + const collectionId = (1 << 32) - 1; + await expect(helper.collection.setSponsor(alice, collectionId, bob.address)) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('(!negative test!) Add sponsor to a collection that was destroyed', async () => { - const collectionId = await createCollectionExpectSuccess(); - await destroyCollectionExpectSuccess(collectionId); - await setCollectionSponsorExpectFailure(collectionId, bob.address); + + itSub('(!negative test!) Add sponsor to a collection that was destroyed', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetCollectionSponsor-Neg-2', tokenPrefix: 'SCS'}); + await collection.burn(alice); + await expect(collection.setSponsor(alice, bob.address)) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); }); --- a/tests/src/setContractSponsoringRateLimit.test.ts +++ b/tests/src/setContractSponsoringRateLimit.test.ts @@ -25,6 +25,7 @@ setContractSponsoringRateLimitExpectSuccess, } from './util/helpers'; +// todo:playgrounds postponed skipped 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) => { --- a/tests/src/setMintPermission.test.ts +++ b/tests/src/setMintPermission.test.ts @@ -15,65 +15,62 @@ // along with Unique Network. If not, see . import {IKeyringPair} from '@polkadot/types/types'; -import usingApi from './substrate/substrate-api'; -import { - addToAllowListExpectSuccess, - createCollectionExpectSuccess, - createItemExpectFailure, - createItemExpectSuccess, - destroyCollectionExpectSuccess, - enableAllowListExpectSuccess, - findNotExistingCollection, - setMintPermissionExpectFailure, - setMintPermissionExpectSuccess, - addCollectionAdminExpectSuccess, -} from './util/helpers'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import {itSub, usingPlaygrounds} from './util/playgrounds'; +chai.use(chaiAsPromised); +const expect = chai.expect; + describe('Integration Test setMintPermission', () => { let alice: IKeyringPair; let bob: IKeyringPair; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor); }); }); - it('ensure allow-listed non-privileged address can mint tokens', async () => { - await usingApi(async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await enableAllowListExpectSuccess(alice, collectionId); - await setMintPermissionExpectSuccess(alice, collectionId, true); - await addToAllowListExpectSuccess(alice, collectionId, bob.address); + itSub('ensure allow-listed non-privileged address can mint tokens', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-1', description: '', tokenPrefix: 'SMP'}); + await collection.setPermissions(alice, {access: 'AllowList', mintMode: true}); + await collection.addToAllowList(alice, {Substrate: bob.address}); - await createItemExpectSuccess(bob, collectionId, 'NFT'); - }); + await expect(collection.mintToken(bob, {Substrate: bob.address})).to.not.be.rejected; }); - it('can be enabled twice', async () => { - await usingApi(async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await setMintPermissionExpectSuccess(alice, collectionId, true); - await setMintPermissionExpectSuccess(alice, collectionId, true); - }); + itSub('can be enabled twice', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-2', description: '', tokenPrefix: 'SMP'}); + expect((await collection.getData())?.raw.permissions.access).to.not.equal('AllowList'); + + await collection.setPermissions(alice, {mintMode: true}); + await collection.setPermissions(alice, {mintMode: true}); + expect((await collection.getData())?.raw.permissions.mintMode).to.be.true; }); - it('can be disabled twice', async () => { - await usingApi(async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await setMintPermissionExpectSuccess(alice, collectionId, true); - await setMintPermissionExpectSuccess(alice, collectionId, false); - await setMintPermissionExpectSuccess(alice, collectionId, false); - }); + itSub('can be disabled twice', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-3', description: '', tokenPrefix: 'SMP'}); + expect((await collection.getData())?.raw.permissions.access).to.equal('Normal'); + + await collection.setPermissions(alice, {access: 'AllowList', mintMode: true}); + expect((await collection.getData())?.raw.permissions.access).to.equal('AllowList'); + expect((await collection.getData())?.raw.permissions.mintMode).to.equal(true); + + await collection.setPermissions(alice, {access: 'Normal', mintMode: false}); + await collection.setPermissions(alice, {access: 'Normal', mintMode: false}); + expect((await collection.getData())?.raw.permissions.access).to.equal('Normal'); + expect((await collection.getData())?.raw.permissions.mintMode).to.equal(false); }); - it('Collection admin success on set', async () => { - await usingApi(async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await addCollectionAdminExpectSuccess(alice, collectionId, bob.address); - await setMintPermissionExpectSuccess(bob, collectionId, true); - }); + itSub('Collection admin success on set', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-4', description: '', tokenPrefix: 'SMP'}); + await collection.addAdmin(alice, {Substrate: bob.address}); + await collection.setPermissions(bob, {access: 'AllowList', mintMode: true}); + + expect((await collection.getData())?.raw.permissions.access).to.equal('AllowList'); + expect((await collection.getData())?.raw.permissions.mintMode).to.equal(true); }); }); @@ -82,41 +79,38 @@ let bob: IKeyringPair; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor); }); }); - it('fails on not existing collection', async () => { - await usingApi(async (api) => { - const nonExistingCollection = await findNotExistingCollection(api); - await setMintPermissionExpectFailure(alice, nonExistingCollection, true); - }); + itSub('fails on not existing collection', async ({helper}) => { + const collectionId = (1 << 32) - 1; + await expect(helper.collection.setPermissions(alice, collectionId, {mintMode: true})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('fails on removed collection', async () => { - await usingApi(async () => { - const removedCollectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await destroyCollectionExpectSuccess(removedCollectionId); + itSub('fails on removed collection', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-Neg-1', tokenPrefix: 'SMP'}); + await collection.burn(alice); - await setMintPermissionExpectFailure(alice, removedCollectionId, true); - }); + await expect(collection.setPermissions(alice, {mintMode: true})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('fails when not collection owner tries to set mint status', async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await enableAllowListExpectSuccess(alice, collectionId); - await setMintPermissionExpectFailure(bob, collectionId, true); + itSub('fails when non-owner tries to set mint status', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-Neg-2', tokenPrefix: 'SMP'}); + + await expect(collection.setPermissions(bob, {mintMode: true})) + .to.be.rejectedWith(/common\.NoPermission/); }); - it('ensure non-allow-listed non-privileged address can\'t mint tokens', async () => { - await usingApi(async () => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}}); - await enableAllowListExpectSuccess(alice, collectionId); - await setMintPermissionExpectSuccess(alice, collectionId, true); + itSub('ensure non-allow-listed non-privileged address can\'t mint tokens', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'SetMintPermission-Neg-3', tokenPrefix: 'SMP'}); + await collection.setPermissions(alice, {mintMode: true}); - await createItemExpectFailure(bob, collectionId, 'NFT'); - }); + await expect(collection.mintToken(bob, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.AddressNotInAllowlist/); }); }); --- a/tests/src/setPublicAccessMode.test.ts +++ b/tests/src/setPublicAccessMode.test.ts @@ -15,111 +15,84 @@ // along with Unique Network. If not, see . // https://unique-network.readthedocs.io/en/latest/jsapi.html#setschemaversion -import {ApiPromise} from '@polkadot/api'; import {IKeyringPair} from '@polkadot/types/types'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import usingApi, {submitTransactionExpectFailAsync} from './substrate/substrate-api'; -import { - addToAllowListExpectSuccess, - createCollectionExpectSuccess, - createItemExpectSuccess, - destroyCollectionExpectSuccess, - enablePublicMintingExpectSuccess, - enableAllowListExpectSuccess, - normalizeAccountId, - addCollectionAdminExpectSuccess, - getCreatedCollectionCount, -} from './util/helpers'; +import {itSub, usingPlaygrounds} from './util/playgrounds'; chai.use(chaiAsPromised); const expect = chai.expect; - -let alice: IKeyringPair; -let bob: IKeyringPair; describe('Integration Test setPublicAccessMode(): ', () => { + let alice: IKeyringPair; + let bob: IKeyringPair; + before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor); }); }); - it('Run extrinsic with collection id parameters, set the allowlist mode for the collection', async () => { - await usingApi(async () => { - const collectionId: number = await createCollectionExpectSuccess(); - await enableAllowListExpectSuccess(alice, collectionId); - await enablePublicMintingExpectSuccess(alice, collectionId); - await addToAllowListExpectSuccess(alice, collectionId, bob.address); - await createItemExpectSuccess(bob, collectionId, 'NFT', bob.address); - }); + itSub('Runs extrinsic with collection id parameters, sets the allowlist mode for the collection', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-1', tokenPrefix: 'TF'}); + await collection.setPermissions(alice, {access: 'AllowList', mintMode: true}); + await collection.addToAllowList(alice, {Substrate: bob.address}); + + await expect(collection.mintToken(bob, {Substrate: bob.address})).to.be.not.rejected; + }); + + itSub('Allowlisted collection limits', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-2', tokenPrefix: 'TF'}); + await collection.setPermissions(alice, {access: 'AllowList', mintMode: true}); + + await expect(collection.mintToken(bob, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.AddressNotInAllowlist/); }); - it('Allowlisted collection limits', async () => { - await usingApi(async (api: ApiPromise) => { - const collectionId = await createCollectionExpectSuccess(); - await enableAllowListExpectSuccess(alice, collectionId); - await enablePublicMintingExpectSuccess(alice, collectionId); - const tx = api.tx.unique.createItem(collectionId, normalizeAccountId(bob.address), 'NFT'); - await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected; - }); + itSub('setPublicAccessMode by collection admin', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-Neg-4', tokenPrefix: 'TF'}); + await collection.addAdmin(alice, {Substrate: bob.address}); + + await expect(collection.setPermissions(bob, {access: 'AllowList'})).to.be.not.rejected; }); }); describe('Negative Integration Test ext. setPublicAccessMode(): ', () => { - it('Set a non-existent collection', async () => { - await usingApi(async (api: ApiPromise) => { - // tslint:disable-next-line: radix - const collectionId = await getCreatedCollectionCount(api) + 1; - const tx = api.tx.unique.setCollectionPermissions(collectionId, {access: 'AllowList'}); - await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected; + let alice: IKeyringPair; + let bob: IKeyringPair; + + before(async () => { + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor); }); }); - it('Set the collection that has been deleted', async () => { - await usingApi(async (api: ApiPromise) => { - // tslint:disable-next-line: no-bitwise - const collectionId = await createCollectionExpectSuccess(); - await destroyCollectionExpectSuccess(collectionId); - const tx = api.tx.unique.setCollectionPermissions(collectionId, {access: 'AllowList'}); - await expect(submitTransactionExpectFailAsync(alice, tx)).to.be.rejected; - }); + itSub('Sets a non-existent collection', async ({helper}) => { + const collectionId = (1 << 32) - 1; + await expect(helper.collection.setPermissions(alice, collectionId, {access: 'AllowList'})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('Re-set the list mode already set in quantity', async () => { - await usingApi(async () => { - const collectionId: number = await createCollectionExpectSuccess(); - await enableAllowListExpectSuccess(alice, collectionId); - await enableAllowListExpectSuccess(alice, collectionId); - }); + itSub('Sets the collection that has been deleted', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-Neg-1', tokenPrefix: 'TF'}); + await collection.burn(alice); + + await expect(collection.setPermissions(alice, {access: 'AllowList'})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('Execute method not on behalf of the collection owner', async () => { - await usingApi(async (api: ApiPromise) => { - // tslint:disable-next-line: no-bitwise - const collectionId = await createCollectionExpectSuccess(); - const tx = api.tx.unique.setCollectionPermissions(collectionId, {access: 'AllowList'}); - await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected; - }); + itSub('Re-sets the list mode already set in quantity', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-Neg-2', tokenPrefix: 'TF'}); + await collection.setPermissions(alice, {access: 'AllowList'}); + await collection.setPermissions(alice, {access: 'AllowList'}); }); - it('setPublicAccessMode by collection admin', async () => { - await usingApi(async (api: ApiPromise) => { - // tslint:disable-next-line: no-bitwise - const collectionId = await createCollectionExpectSuccess(); - await addCollectionAdminExpectSuccess(alice, collectionId, bob.address); - const tx = api.tx.unique.setCollectionPermissions(collectionId, {access: 'AllowList'}); - await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.not.rejected; - }); - }); -}); + itSub('Executes method as a malefactor', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'PublicAccess-Neg-3', tokenPrefix: 'TF'}); -describe('Negative Integration Test ext. collection admin setPublicAccessMode(): ', () => { - before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - }); + await expect(collection.setPermissions(bob, {access: 'AllowList'})) + .to.be.rejectedWith(/common\.NoPermission/); }); }); --- a/tests/src/toggleContractAllowList.test.ts +++ b/tests/src/toggleContractAllowList.test.ts @@ -31,6 +31,7 @@ const value = 0; const gasLimit = 3000n * 1000000n; +// todo:playgrounds skipped ~ postpone describe.skip('Integration Test toggleContractAllowList', () => { it('Enable allow list contract mode', async () => { --- a/tests/src/transfer.test.ts +++ b/tests/src/transfer.test.ts @@ -14,387 +14,319 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -import {ApiPromise} from '@polkadot/api'; import {IKeyringPair} from '@polkadot/types/types'; -import {expect} from 'chai'; -import getBalance from './substrate/get-balance'; -import {default as usingApi, submitTransactionAsync} from './substrate/substrate-api'; -import { - burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess, - destroyCollectionExpectSuccess, - findUnusedAddress, - getCreateCollectionResult, - getCreateItemResult, - transferExpectFailure, - transferExpectSuccess, - addCollectionAdminExpectSuccess, - getCreatedCollectionCount, - toSubstrateAddress, - getTokenOwner, - normalizeAccountId, - getBalance as getTokenBalance, - transferFromExpectSuccess, - transferFromExpectFail, - requirePallets, - Pallets, -} from './util/helpers'; -import { - subToEth, - itWeb3, -} from './eth/util/helpers'; -import {request} from 'https'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import {itEth, usingEthPlaygrounds} from './eth/util/playgrounds'; +import {itSub, Pallets, usingPlaygrounds} from './util/playgrounds'; + +chai.use(chaiAsPromised); +const expect = chai.expect; -let alice: IKeyringPair; -let bob: IKeyringPair; -let charlie: IKeyringPair; +describe.skip('Integration Test Transfer(recipient, collection_id, item_id, value)', () => { + let alice: IKeyringPair; + let bob: IKeyringPair; -describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => { before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor); }); }); - it('Balance transfers and check balance', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alice.address, bob.address]); + itSub('Balance transfers and check balance', async ({helper}) => { + const alicesBalanceBefore = await helper.balance.getSubstrate(alice.address); + const bobsBalanceBefore = await helper.balance.getSubstrate(bob.address); - const transfer = api.tx.balances.transfer(bob.address, 1n); - const events = await submitTransactionAsync(alice, transfer); - const result = getCreateItemResult(events); - // tslint:disable-next-line:no-unused-expression - expect(result.success).to.be.true; + expect(await helper.balance.transferToSubstrate(alice, bob.address, 1n)).to.be.true; - const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alice.address, bob.address]); + const alicesBalanceAfter = await helper.balance.getSubstrate(alice.address); + const bobsBalanceAfter = await helper.balance.getSubstrate(bob.address); - // 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; - }); + expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true; + expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true; }); - it('Inability to pay fees error message is correct', async () => { - await usingApi(async (api, privateKeyWrapper) => { - // Find unused address - const pk = await findUnusedAddress(api, privateKeyWrapper); + itSub('Inability to pay fees error message is correct', async ({helper, privateKey}) => { + const donor = privateKey('//Alice'); + const [zero] = await helper.arrange.createAccounts([0n], donor); - const badTransfer = api.tx.balances.transfer(bob.address, 1n); - // const events = await submitTransactionAsync(pk, badTransfer); - const badTransaction = async () => { - const events = await submitTransactionAsync(pk, badTransfer); - const result = getCreateCollectionResult(events); - // tslint:disable-next-line:no-unused-expression - expect(result.success).to.be.false; - }; - await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees , e.g. account balance too low'); - }); + // console.error = () => {}; + // The following operation throws an error into the console and the logs. Pay it no heed as long as the test succeeds. + await expect(helper.balance.transferToSubstrate(zero, donor.address, 1n)) + .to.be.rejectedWith('Inability to pay some fees , e.g. account balance too low'); }); - it('[nft] User can transfer owned token', async () => { - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); - await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT'); + itSub('[nft] User can transfer owned token', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-1-NFT', description: '', tokenPrefix: 'T'}); + const nft = await collection.mintToken(alice, {Substrate: alice.address}); + + await nft.transfer(alice, {Substrate: bob.address}); + expect(await nft.getOwner()).to.be.deep.equal({Substrate: bob.address}); }); - it('[fungible] User can transfer owned token', async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible'); + itSub('[fungible] User can transfer owned token', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-1-FT', description: '', tokenPrefix: 'T'}); + await collection.mint(alice, {Substrate: alice.address}, 10n); + + await collection.transfer(alice, {Substrate: bob.address}, 9n); + expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(9n); + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n); }); - it('[refungible] User can transfer owned token', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itSub.ifWithPallets('[refungible] User can transfer owned token', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-1-RFT', description: '', tokenPrefix: 'T'}); + const rft = await collection.mintToken(alice, {Substrate: alice.address}, 10n); - const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - await transferExpectSuccess( - reFungibleCollectionId, - newReFungibleTokenId, - alice, - bob, - 100, - 'ReFungible', - ); + await rft.transfer(alice, {Substrate: bob.address}, 9n); + expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(9n); + expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(1n); }); - it('[nft] Collection admin can transfer owned token', async () => { - const nftCollectionId = await createCollectionExpectSuccess(); - await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address); - const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address); - await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT'); + itSub('[nft] Collection admin can transfer owned token', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-2-NFT', description: '', tokenPrefix: 'T'}); + await collection.addAdmin(alice, {Substrate: bob.address}); + + const nft = await collection.mintToken(bob, {Substrate: bob.address}); + await nft.transfer(bob, {Substrate: alice.address}); + + expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address}); }); - it('[fungible] Collection admin can transfer owned token', async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address); - await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible'); + itSub('[fungible] Collection admin can transfer owned token', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-2-FT', description: '', tokenPrefix: 'T'}); + await collection.addAdmin(alice, {Substrate: bob.address}); + + await collection.mint(bob, {Substrate: bob.address}, 10n); + await collection.transfer(bob, {Substrate: alice.address}, 1n); + + expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(9n); + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(1n); }); - it('[refungible] Collection admin can transfer owned token', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itSub.ifWithPallets('[refungible] Collection admin can transfer owned token', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-2-RFT', description: '', tokenPrefix: 'T'}); + await collection.addAdmin(alice, {Substrate: bob.address}); + + const rft = await collection.mintToken(bob, {Substrate: bob.address}, 10n); + await rft.transfer(bob, {Substrate: alice.address}, 1n); - const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address); - const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address); - await transferExpectSuccess( - reFungibleCollectionId, - newReFungibleTokenId, - bob, - alice, - 100, - 'ReFungible', - ); + expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(9n); + expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(1n); }); }); -describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => { +describe.skip('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => { + let alice: IKeyringPair; + let bob: IKeyringPair; + before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - charlie = privateKeyWrapper('//Charlie'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob] = await helper.arrange.createAccounts([50n, 10n], donor); }); }); - it('[nft] Transfer with not existed collection_id', async () => { - await usingApi(async (api) => { - const nftCollectionCount = await getCreatedCollectionCount(api); - await transferExpectFailure(nftCollectionCount + 1, 1, alice, bob, 1); - }); + itSub('[nft] Transfer with not existed collection_id', async ({helper}) => { + const collectionId = (1 << 32) - 1; + await expect(helper.nft.transferToken(alice, collectionId, 1, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('[fungible] Transfer with not existed collection_id', async () => { - await usingApi(async (api) => { - const fungibleCollectionCount = await getCreatedCollectionCount(api); - await transferExpectFailure(fungibleCollectionCount + 1, 0, alice, bob, 1); - }); + itSub('[fungible] Transfer with not existed collection_id', async ({helper}) => { + const collectionId = (1 << 32) - 1; + await expect(helper.ft.transfer(alice, collectionId, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('[refungible] Transfer with not existed collection_id', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itSub.ifWithPallets('[refungible] Transfer with not existed collection_id', [Pallets.ReFungible], async ({helper}) => { + const collectionId = (1 << 32) - 1; + await expect(helper.rft.transferToken(alice, collectionId, 1, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.CollectionNotFound/); + }); + + itSub('[nft] Transfer with deleted collection_id', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-1-NFT', description: '', tokenPrefix: 'T'}); + const nft = await collection.mintToken(alice, {Substrate: alice.address}); + + await nft.burn(alice); + await collection.burn(alice); - await usingApi(async (api) => { - const reFungibleCollectionCount = await getCreatedCollectionCount(api); - await transferExpectFailure(reFungibleCollectionCount + 1, 1, alice, bob, 1); - }); + await expect(nft.transfer(alice, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('[nft] Transfer with deleted collection_id', async () => { - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); - await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId); - await destroyCollectionExpectSuccess(nftCollectionId); - await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1); + itSub('[fungible] Transfer with deleted collection_id', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-1-FT', description: '', tokenPrefix: 'T'}); + await collection.mint(alice, {Substrate: alice.address}, 10n); + + await collection.burnTokens(alice, 10n); + await collection.burn(alice); + + await expect(collection.transfer(alice, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); + + itSub.ifWithPallets('[refungible] Transfer with deleted collection_id', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-1-RFT', description: '', tokenPrefix: 'T'}); + const rft = await collection.mintToken(alice, {Substrate: alice.address}, 10n); + + await rft.burn(alice, 10n); + await collection.burn(alice); - it('[fungible] Transfer with deleted collection_id', async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10); - await destroyCollectionExpectSuccess(fungibleCollectionId); - await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1); + await expect(rft.transfer(alice, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.CollectionNotFound/); }); - it('[refungible] Transfer with deleted collection_id', async function() { - await requirePallets(this, [Pallets.ReFungible]); - - const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100); - await destroyCollectionExpectSuccess(reFungibleCollectionId); - await transferExpectFailure( - reFungibleCollectionId, - newReFungibleTokenId, - alice, - bob, - 1, - ); + itSub('[nft] Transfer with not existed item_id', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-2-NFT', description: '', tokenPrefix: 'T'}); + await expect(collection.transferToken(alice, 1, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.TokenNotFound/); }); - it('[nft] Transfer with not existed item_id', async () => { - const nftCollectionId = await createCollectionExpectSuccess(); - await transferExpectFailure(nftCollectionId, 2, alice, bob, 1); + itSub('[fungible] Transfer with not existed item_id', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-2-FT', description: '', tokenPrefix: 'T'}); + await expect(collection.transfer(alice, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.TokenValueTooLow/); }); - it('[fungible] Transfer with not existed item_id', async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1); + itSub.ifWithPallets('[refungible] Transfer with not existed item_id', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-2-RFT', description: '', tokenPrefix: 'T'}); + await expect(collection.transferToken(alice, 1, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.TokenValueTooLow/); }); - it('[refungible] Transfer with not existed item_id', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itSub('[nft] Transfer with deleted item_id', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-3-NFT', description: '', tokenPrefix: 'T'}); + const nft = await collection.mintToken(alice, {Substrate: alice.address}); + + await nft.burn(alice); - const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - await transferExpectFailure( - reFungibleCollectionId, - 2, - alice, - bob, - 1, - ); + await expect(nft.transfer(alice, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.TokenNotFound/); }); - it('[nft] Transfer with deleted item_id', async () => { - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); - await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1); - await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1); - }); + itSub('[fungible] Transfer with deleted item_id', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-3-FT', description: '', tokenPrefix: 'T'}); + await collection.mint(alice, {Substrate: alice.address}, 10n); + + await collection.burnTokens(alice, 10n); - it('[fungible] Transfer with deleted item_id', async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10); - await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1); + await expect(collection.transfer(alice, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.TokenValueTooLow/); }); - it('[refungible] Transfer with deleted item_id', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itSub.ifWithPallets('[refungible] Transfer with deleted item_id', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-Neg-3-RFT', description: '', tokenPrefix: 'T'}); + const rft = await collection.mintToken(alice, {Substrate: alice.address}, 10n); + + await rft.burn(alice, 10n); - const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100); - await transferExpectFailure( - reFungibleCollectionId, - newReFungibleTokenId, - alice, - bob, - 1, - ); + await expect(rft.transfer(alice, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.TokenValueTooLow/); }); - it('[nft] Transfer with recipient that is not owner', async () => { - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); - await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1); + itSub('[nft] Transfer with recipient that is not owner', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'Transfer-Neg-4-NFT', description: '', tokenPrefix: 'T'}); + const nft = await collection.mintToken(alice, {Substrate: alice.address}); + + await expect(nft.transfer(bob, {Substrate: bob.address})) + .to.be.rejectedWith(/common\.NoPermission/); + expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address}); }); - it('[fungible] Transfer with recipient that is not owner', async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1); + itSub('[fungible] Transfer with recipient that is not owner', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'Transfer-Neg-4-FT', description: '', tokenPrefix: 'T'}); + await collection.mint(alice, {Substrate: alice.address}, 10n); + + await expect(collection.transfer(bob, {Substrate: bob.address}, 9n)) + .to.be.rejectedWith(/common\.TokenValueTooLow/); + expect(await collection.getBalance({Substrate: bob.address})).to.be.equal(0n); + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(10n); }); - it('[refungible] Transfer with recipient that is not owner', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itSub.ifWithPallets('[refungible] Transfer with recipient that is not owner', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'Transfer-1-RFT', description: '', tokenPrefix: 'T'}); + const rft = await collection.mintToken(alice, {Substrate: alice.address}, 10n); - const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - await transferExpectFailure( - reFungibleCollectionId, - newReFungibleTokenId, - charlie, - bob, - 1, - ); + await expect(rft.transfer(bob, {Substrate: bob.address}, 9n)) + .to.be.rejectedWith(/common\.TokenValueTooLow/); + expect(await rft.getBalance({Substrate: bob.address})).to.be.equal(0n); + expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(10n); }); }); -describe('Zero value transfer(From)', () => { - before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); +describe('Transfers to self (potentially over substrate-evm boundary)', () => { + let donor: IKeyringPair; + + before(async function() { + await usingEthPlaygrounds(async (_, privateKey) => { + donor = privateKey('//Alice'); }); }); + + itEth('Transfers to self. In case of same frontend', async ({helper}) => { + const [owner] = await helper.arrange.createAccounts([10n], donor); + const collection = await helper.ft.mintCollection(owner, {}); + await collection.mint(owner, {Substrate: owner.address}, 100n); - it('NFT', async () => { - await usingApi(async (api: ApiPromise) => { - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); + const ownerProxy = helper.address.substrateToEth(owner.address); - const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), nftCollectionId, newNftTokenId, 0); - await submitTransactionAsync(alice, transferTx); - const address = normalizeAccountId(await getTokenOwner(api, nftCollectionId, newNftTokenId)); + // transfer to own proxy + await collection.transfer(owner, {Ethereum: ownerProxy}, 10n); + expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n); + expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n); - expect(toSubstrateAddress(address)).to.be.equal(alice.address); - }); + // transfer-from own proxy to own proxy again + await collection.transferFrom(owner, {Ethereum: ownerProxy}, {Ethereum: ownerProxy}, 5n); + expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n); + expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n); }); - it('RFT', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itEth('Transfers to self. In case of substrate-evm boundary', async ({helper}) => { + const [owner] = await helper.arrange.createAccounts([10n], donor); + const collection = await helper.ft.mintCollection(owner, {}); + await collection.mint(owner, {Substrate: owner.address}, 100n); - await usingApi(async (api: ApiPromise) => { - const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - const balanceBeforeAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId); - const balanceBeforeBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId); - - const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), reFungibleCollectionId, newReFungibleTokenId, 0); - await submitTransactionAsync(alice, transferTx); + const ownerProxy = helper.address.substrateToEth(owner.address); - const balanceAfterAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId); - const balanceAfterBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId); + // transfer to own proxy + await collection.transfer(owner, {Ethereum: ownerProxy}, 10n); + expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(90n); + expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(10n); - expect((balanceBeforeAlice)).to.be.equal(balanceAfterAlice); - expect((balanceBeforeBob)).to.be.equal(balanceAfterBob); - }); + // transfer-from own proxy to self + await collection.transferFrom(owner, {Ethereum: ownerProxy}, {Substrate: owner.address}, 5n); + expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(95n); + expect(await collection.getBalance({Ethereum: ownerProxy})).to.be.equal(5n); }); - - it('Fungible', async () => { - await usingApi(async (api: ApiPromise) => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - const balanceBeforeAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId); - const balanceBeforeBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId); - - const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), fungibleCollectionId, newFungibleTokenId, 0); - await submitTransactionAsync(alice, transferTx); - const balanceAfterAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId); - const balanceAfterBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId); + itEth('Transfers to self. In case of inside substrate-evm', async ({helper}) => { + const [owner] = await helper.arrange.createAccounts([10n], donor); + const collection = await helper.ft.mintCollection(owner, {}); + await collection.mint(owner, {Substrate: owner.address}, 100n); - expect((balanceBeforeAlice)).to.be.equal(balanceAfterAlice); - expect((balanceBeforeBob)).to.be.equal(balanceAfterBob); - }); - }); -}); + // transfer to self again + await collection.transfer(owner, {Substrate: owner.address}, 10n); + expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(100n); -describe('Transfers to self (potentially over substrate-evm boundary)', () => { - itWeb3('Transfers to self. In case of same frontend', async ({api, privateKeyWrapper}) => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const aliceProxy = subToEth(alice.address); - const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address}); - await transferExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, 10, 'Fungible'); - const balanceAliceBefore = await getTokenBalance(api, collectionId, {Ethereum: aliceProxy}, tokenId); - await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, {Ethereum: aliceProxy}, 10, 'Fungible'); - const balanceAliceAfter = await getTokenBalance(api, collectionId, {Ethereum: aliceProxy}, tokenId); - expect(balanceAliceBefore).to.be.eq(balanceAliceAfter); + // transfer-from self to self again + await collection.transferFrom(owner, {Substrate: owner.address}, {Substrate: owner.address}, 5n); + expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(100n); }); - itWeb3('Transfers to self. In case of substrate-evm boundary', async ({api, privateKeyWrapper}) => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const aliceProxy = subToEth(alice.address); - const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address}); - const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId); - await transferExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy} , 10, 'Fungible'); - await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, alice, 10, 'Fungible'); - const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId); - expect(balanceAliceBefore).to.be.eq(balanceAliceAfter); - }); + itEth('Transfers to self. In case of inside substrate-evm when not enought "Fungibles"', async ({helper}) => { + const [owner] = await helper.arrange.createAccounts([10n], donor); + const collection = await helper.ft.mintCollection(owner, {}); + await collection.mint(owner, {Substrate: owner.address}, 10n); - itWeb3('Transfers to self. In case of inside substrate-evm', async ({api, privateKeyWrapper}) => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address}); - const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId); - await transferExpectSuccess(collectionId, tokenId, alice, alice , 10, 'Fungible'); - await transferFromExpectSuccess(collectionId, tokenId, alice, alice, alice, 10, 'Fungible'); - const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId); - expect(balanceAliceBefore).to.be.eq(balanceAliceAfter); - }); + // transfer to self again + await expect(collection.transfer(owner, {Substrate: owner.address}, 11n)) + .to.be.rejectedWith(/common\.TokenValueTooLow/); - itWeb3('Transfers to self. In case of inside substrate-evm when not enought "Fungibles"', async ({api, privateKeyWrapper}) => { - const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address}); - const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId); - await transferExpectFailure(collectionId, tokenId, alice, alice , 11); - await transferFromExpectFail(collectionId, tokenId, alice, alice, alice, 11); - const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId); - expect(balanceAliceBefore).to.be.eq(balanceAliceAfter); + // transfer-from self to self again + await expect(collection.transferFrom(owner, {Substrate: owner.address}, {Substrate: owner.address}, 12n)) + .to.be.rejectedWith(/common\.TokenValueTooLow/); + expect(await collection.getBalance({Substrate: owner.address})).to.be.equal(10n); }); }); --- a/tests/src/transferFrom.test.ts +++ b/tests/src/transferFrom.test.ts @@ -14,26 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Unique Network. If not, see . -import {ApiPromise} from '@polkadot/api'; import {IKeyringPair} from '@polkadot/types/types'; import chai from 'chai'; import chaiAsPromised from 'chai-as-promised'; -import {default as usingApi} from './substrate/substrate-api'; -import { - approveExpectFail, - approveExpectSuccess, - createCollectionExpectSuccess, - createFungibleItemExpectSuccess, - createItemExpectSuccess, - getAllowance, - transferFromExpectFail, - transferFromExpectSuccess, - burnItemExpectSuccess, - setCollectionLimitsExpectSuccess, - getCreatedCollectionCount, - requirePallets, - Pallets, -} from './util/helpers'; +import {itSub, Pallets, usingPlaygrounds} from './util/playgrounds'; chai.use(chaiAsPromised); const expect = chai.expect; @@ -44,67 +28,64 @@ let charlie: IKeyringPair; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - charlie = privateKeyWrapper('//Charlie'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob, charlie] = await helper.arrange.createAccounts([20n, 10n, 10n], donor); }); }); - it('[nft] Execute the extrinsic and check nftItemList - owner of token', async () => { - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); - await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address); + itSub('[nft] Execute the extrinsic and check nftItemList - owner of token', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-1', description: '', tokenPrefix: 'TF'}); + const nft = await collection.mintToken(alice, {Substrate: alice.address}); + await nft.approve(alice, {Substrate: bob.address}); + expect(await nft.isApproved({Substrate: bob.address})).to.be.true; - await transferFromExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, charlie, 1, 'NFT'); + await nft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}); + expect(await nft.getOwner()).to.be.deep.equal({Substrate: charlie.address}); }); - it('[fungible] Execute the extrinsic and check nftItemList - owner of token', async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address); - await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1, 'Fungible'); + itSub('[fungible] Execute the extrinsic and check nftItemList - owner of token', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-2', description: '', tokenPrefix: 'TF'}); + await collection.mint(alice, {Substrate: alice.address}, 10n); + await collection.approveTokens(alice, {Substrate: bob.address}, 7n); + expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(7n); + + await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 6n); + expect(await collection.getBalance({Substrate: charlie.address})).to.be.equal(6n); + expect(await collection.getBalance({Substrate: alice.address})).to.be.equal(4n); + expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(1n); }); - it('[refungible] Execute the extrinsic and check nftItemList - owner of token', async function() { - await requirePallets(this, [Pallets.ReFungible]); - - const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 100); - await transferFromExpectSuccess( - reFungibleCollectionId, - newReFungibleTokenId, - bob, - alice, - charlie, - 100, - 'ReFungible', - ); + itSub.ifWithPallets('[refungible] Execute the extrinsic and check nftItemList - owner of token', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-3', description: '', tokenPrefix: 'TF'}); + const rft = await collection.mintToken(alice, {Substrate: alice.address}, 10n); + await rft.approve(alice, {Substrate: bob.address}, 7n); + expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(7n); + + await rft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 6n); + expect(await rft.getBalance({Substrate: charlie.address})).to.be.equal(6n); + expect(await rft.getBalance({Substrate: alice.address})).to.be.equal(4n); + expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(1n); }); - it('Should reduce allowance if value is big', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const alice = privateKeyWrapper('//Alice'); - const bob = privateKeyWrapper('//Bob'); - const charlie = privateKeyWrapper('//Charlie'); + itSub('Should reduce allowance if value is big', async ({helper}) => { + // fungible + const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-4', description: '', tokenPrefix: 'TF'}); + await collection.mint(alice, {Substrate: alice.address}, 500000n); - // fungible - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createFungibleItemExpectSuccess(alice, fungibleCollectionId, {Value: 500000n}); - - await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 500000n); - await transferFromExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 500000n, 'Fungible'); - expect(await getAllowance(api, fungibleCollectionId, alice.address, bob.address, newFungibleTokenId)).to.equal(0n); - }); + await collection.approveTokens(alice, {Substrate: bob.address}, 500000n); + expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(500000n); + await collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 500000n); + expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.equal(0n); }); - it('can be called by collection owner on non-owned item when OwnerCanTransfer == true', async () => { - const collectionId = await createCollectionExpectSuccess(); - await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: true}); - const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address); + itSub('can be called by collection owner on non-owned item when OwnerCanTransfer == true', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-5', description: '', tokenPrefix: 'TF'}); + await collection.setLimits(alice, {ownerCanTransfer: true}); - await transferFromExpectSuccess(collectionId, itemId, alice, bob, charlie); + const nft = await collection.mintToken(alice, {Substrate: bob.address}); + await nft.transferFrom(alice, {Substrate: bob.address}, {Substrate: charlie.address}); + expect(await nft.getOwner()).to.be.deep.equal({Substrate: charlie.address}); }); }); @@ -114,245 +95,263 @@ let charlie: IKeyringPair; before(async () => { - await usingApi(async (api, privateKeyWrapper) => { - alice = privateKeyWrapper('//Alice'); - bob = privateKeyWrapper('//Bob'); - charlie = privateKeyWrapper('//Charlie'); + await usingPlaygrounds(async (helper, privateKey) => { + const donor = privateKey('//Alice'); + [alice, bob, charlie] = await helper.arrange.createAccounts([50n, 10n, 10n], donor); }); }); - it('[nft] transferFrom for a collection that does not exist', async () => { - await usingApi(async (api: ApiPromise) => { - const nftCollectionCount = await getCreatedCollectionCount(api); - await approveExpectFail(nftCollectionCount + 1, 1, alice, bob); + itSub('transferFrom for a collection that does not exist', async ({helper}) => { + const collectionId = (1 << 32) - 1; + await expect(helper.collection.approveToken(alice, collectionId, 0, {Substrate: bob.address}, 1n)) + .to.be.rejectedWith(/common\.CollectionNotFound/); + await expect(helper.collection.transferTokenFrom(bob, collectionId, 0, {Substrate: alice.address}, {Substrate: bob.address}, 1n)) + .to.be.rejectedWith(/common\.CollectionNotFound/); + }); + + /* itSub('transferFrom for a collection that was destroyed', async ({helper}) => { + this test copies approve negative test + }); */ + + /* itSub('transferFrom a token that does not exist', async ({helper}) => { + this test copies approve negative test + }); */ + + /* itSub('transferFrom a token that was deleted', async ({helper}) => { + this test copies approve negative test + }); */ + + itSub('[nft] transferFrom for not approved address', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-1', description: '', tokenPrefix: 'TF'}); + const nft = await collection.mintToken(alice, {Substrate: alice.address}); + + await expect(nft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address})) + .to.be.rejectedWith(/common\.ApprovedValueTooLow/); + expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address}); + }); + + itSub('[fungible] transferFrom for not approved address', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-Neg-1', description: '', tokenPrefix: 'TF'}); + await collection.mint(alice, {Substrate: alice.address}, 10n); - await transferFromExpectFail(nftCollectionCount + 1, 1, bob, alice, charlie, 1); - }); + await expect(collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 5n)) + .to.be.rejectedWith(/common\.ApprovedValueTooLow/); + expect(await collection.getBalance({Substrate: alice.address})).to.be.deep.equal(10n); + expect(await collection.getBalance({Substrate: bob.address})).to.be.deep.equal(0n); + expect(await collection.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n); }); - it('[fungible] transferFrom for a collection that does not exist', async () => { - await usingApi(async (api: ApiPromise) => { - const fungibleCollectionCount = await getCreatedCollectionCount(api); - await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob); + itSub.ifWithPallets('[refungible] transferFrom for not approved address', [Pallets.ReFungible], async({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-Neg-3', description: '', tokenPrefix: 'TF'}); + const rft = await collection.mintToken(alice, {Substrate: alice.address}, 10n); - await transferFromExpectFail(fungibleCollectionCount + 1, 0, bob, alice, charlie, 1); - }); + await expect(rft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address})) + .to.be.rejectedWith(/common\.ApprovedValueTooLow/); + expect(await rft.getBalance({Substrate: alice.address})).to.be.deep.equal(10n); + expect(await rft.getBalance({Substrate: bob.address})).to.be.deep.equal(0n); + expect(await rft.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n); }); - it('[refungible] transferFrom for a collection that does not exist', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itSub('[nft] transferFrom incorrect token count', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-4', description: '', tokenPrefix: 'TF'}); + const nft = await collection.mintToken(alice, {Substrate: alice.address}); - await usingApi(async (api: ApiPromise) => { - const reFungibleCollectionCount = await getCreatedCollectionCount(api); - await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob); + await nft.approve(alice, {Substrate: bob.address}); + expect(await nft.isApproved({Substrate: bob.address})).to.be.true; - await transferFromExpectFail(reFungibleCollectionCount + 1, 1, bob, alice, charlie, 1); - }); + await expect(helper.collection.transferTokenFrom( + bob, + collection.collectionId, + nft.tokenId, + {Substrate: alice.address}, + {Substrate: charlie.address}, + 2n, + )).to.be.rejectedWith(/nonfungible\.NonfungibleItemsHaveNoAmount/); + expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address}); }); - /* it('transferFrom for a collection that was destroyed', async () => { - await usingApi(async (api: ApiPromise) => { - this test copies approve negative test - }); - }); */ + itSub('[fungible] transferFrom incorrect token count', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-Neg-5', description: '', tokenPrefix: 'TF'}); + await collection.mint(alice, {Substrate: alice.address}, 10n); - /* it('transferFrom a token that does not exist', async () => { - await usingApi(async (api: ApiPromise) => { - this test copies approve negative test - }); - }); */ + await collection.approveTokens(alice, {Substrate: bob.address}, 2n); + expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(2n); - /* it('transferFrom a token that was deleted', async () => { - await usingApi(async (api: ApiPromise) => { - this test copies approve negative test - }); - }); */ + await expect(collection.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 5n)) + .to.be.rejectedWith(/common\.ApprovedValueTooLow/); + expect(await collection.getBalance({Substrate: alice.address})).to.be.deep.equal(10n); + expect(await collection.getBalance({Substrate: bob.address})).to.be.deep.equal(0n); + expect(await collection.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n); + }); - it('[nft] transferFrom for not approved address', async () => { - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); + itSub.ifWithPallets('[refungible] transferFrom incorrect token count', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-Neg-6', description: '', tokenPrefix: 'TF'}); + const rft = await collection.mintToken(alice, {Substrate: alice.address}, 10n); - await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1); - }); + await rft.approve(alice, {Substrate: bob.address}, 5n); + expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(5n); - it('[fungible] transferFrom for not approved address', async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1); + await expect(rft.transferFrom(bob, {Substrate: alice.address}, {Substrate: charlie.address}, 7n)) + .to.be.rejectedWith(/common\.ApprovedValueTooLow/); + expect(await rft.getBalance({Substrate: alice.address})).to.be.deep.equal(10n); + expect(await rft.getBalance({Substrate: bob.address})).to.be.deep.equal(0n); + expect(await rft.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n); }); - it('[refungible] transferFrom for not approved address', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itSub('[nft] execute transferFrom from account that is not owner of collection', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-7', description: '', tokenPrefix: 'TF'}); + const nft = await collection.mintToken(alice, {Substrate: alice.address}); - const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - await transferFromExpectFail( - reFungibleCollectionId, - newReFungibleTokenId, - bob, - alice, + await expect(nft.approve(charlie, {Substrate: bob.address})).to.be.rejectedWith(/common\.CantApproveMoreThanOwned/); + expect(await nft.isApproved({Substrate: bob.address})).to.be.false; + + await expect(nft.transferFrom( charlie, - 1, - ); + {Substrate: alice.address}, + {Substrate: charlie.address}, + )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); + expect(await nft.getOwner()).to.be.deep.equal({Substrate: alice.address}); }); - it('[nft] transferFrom incorrect token count', async () => { - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); - await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address); + itSub('[fungible] execute transferFrom from account that is not owner of collection', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-Neg-8', description: '', tokenPrefix: 'TF'}); + await collection.mint(alice, {Substrate: alice.address}, 10000n); - await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 2); - }); + await expect(collection.approveTokens(charlie, {Substrate: bob.address}, 1n)).to.be.rejectedWith(/common\.CantApproveMoreThanOwned/); + expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(0n); + expect(await collection.getApprovedTokens({Substrate: charlie.address}, {Substrate: bob.address})).to.be.eq(0n); - it('[fungible] transferFrom incorrect token count', async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address); - await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 2); + await expect(collection.transferFrom( + charlie, + {Substrate: alice.address}, + {Substrate: charlie.address}, + )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); + expect(await collection.getBalance({Substrate: alice.address})).to.be.deep.equal(10000n); + expect(await collection.getBalance({Substrate: bob.address})).to.be.deep.equal(0n); + expect(await collection.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n); }); - it('[refungible] transferFrom incorrect token count', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itSub.ifWithPallets('[refungible] execute transferFrom from account that is not owner of collection', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-Neg-9', description: '', tokenPrefix: 'TF'}); + const rft = await collection.mintToken(alice, {Substrate: alice.address}, 10000n); + + await expect(rft.approve(charlie, {Substrate: bob.address}, 1n)).to.be.rejectedWith(/common\.CantApproveMoreThanOwned/); + expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(0n); + expect(await rft.getApprovedPieces({Substrate: charlie.address}, {Substrate: bob.address})).to.be.eq(0n); - const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address); - await transferFromExpectFail( - reFungibleCollectionId, - newReFungibleTokenId, - bob, - alice, + await expect(rft.transferFrom( charlie, - 2, - ); + {Substrate: alice.address}, + {Substrate: charlie.address}, + )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); + expect(await rft.getBalance({Substrate: alice.address})).to.be.deep.equal(10000n); + expect(await rft.getBalance({Substrate: bob.address})).to.be.deep.equal(0n); + expect(await rft.getBalance({Substrate: charlie.address})).to.be.deep.equal(0n); }); - it('[nft] execute transferFrom from account that is not owner of collection', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const dave = privateKeyWrapper('//Dave'); - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); - try { - await approveExpectFail(nftCollectionId, newNftTokenId, dave, bob); - await transferFromExpectFail(nftCollectionId, newNftTokenId, dave, alice, charlie, 1); - } catch (e) { - // tslint:disable-next-line:no-unused-expression - expect(e).to.be.exist; - } + itSub('transferFrom burnt token before approve NFT', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-10', description: '', tokenPrefix: 'TF'}); + await collection.setLimits(alice, {ownerCanTransfer: true}); + const nft = await collection.mintToken(alice, {Substrate: alice.address}); + + await nft.burn(alice); + await expect(nft.approve(alice, {Substrate: bob.address})).to.be.rejectedWith(/common\.TokenNotFound/); - // await transferFromExpectFail(nftCollectionId, newNftTokenId, Dave, Alice, Charlie, 1); - }); + await expect(nft.transferFrom( + bob, + {Substrate: alice.address}, + {Substrate: charlie.address}, + )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); }); - it('[fungible] execute transferFrom from account that is not owner of collection', async () => { - await usingApi(async (api, privateKeyWrapper) => { - const dave = privateKeyWrapper('//Dave'); + itSub('transferFrom burnt token before approve Fungible', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-Neg-11', description: '', tokenPrefix: 'TF'}); + await collection.setLimits(alice, {ownerCanTransfer: true}); + await collection.mint(alice, {Substrate: alice.address}, 10n); - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - try { - await approveExpectFail(fungibleCollectionId, newFungibleTokenId, dave, bob); - await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, dave, alice, charlie, 1); - } catch (e) { - // tslint:disable-next-line:no-unused-expression - expect(e).to.be.exist; - } - }); + await collection.burnTokens(alice, 10n); + await expect(collection.approveTokens(alice, {Substrate: bob.address})).to.be.not.rejected; + + await expect(collection.transferFrom( + alice, + {Substrate: alice.address}, + {Substrate: charlie.address}, + )).to.be.rejectedWith(/common\.TokenValueTooLow/); }); - it('[refungible] execute transferFrom from account that is not owner of collection', async function() { - await requirePallets(this, [Pallets.ReFungible]); + itSub.ifWithPallets('transferFrom burnt token before approve ReFungible', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-Neg-12', description: '', tokenPrefix: 'TF'}); + await collection.setLimits(alice, {ownerCanTransfer: true}); + const rft = await collection.mintToken(alice, {Substrate: alice.address}, 10n); - await usingApi(async (api, privateKeyWrapper) => { - const dave = privateKeyWrapper('//Dave'); - const reFungibleCollectionId = await - createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - try { - await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, bob); - await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, dave, alice, charlie, 1); - } catch (e) { - // tslint:disable-next-line:no-unused-expression - expect(e).to.be.exist; - } - }); - }); - it('transferFrom burnt token before approve NFT', async () => { - await usingApi(async () => { - // nft - const nftCollectionId = await createCollectionExpectSuccess(); - await setCollectionLimitsExpectSuccess(alice, nftCollectionId, {ownerCanTransfer: true}); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); - await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1); - await approveExpectFail(nftCollectionId, newNftTokenId, alice, bob); - await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1); - }); - }); - it('transferFrom burnt token before approve Fungible', async () => { - await usingApi(async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - await setCollectionLimitsExpectSuccess(alice, fungibleCollectionId, {ownerCanTransfer: true}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10); - await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address); - await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1); + await rft.burn(alice, 10n); + await expect(rft.approve(alice, {Substrate: bob.address})).to.be.rejectedWith(/common\.CantApproveMoreThanOwned/); - }); + await expect(rft.transferFrom( + alice, + {Substrate: alice.address}, + {Substrate: charlie.address}, + )).to.be.rejectedWith(/common\.TokenValueTooLow/); }); - it('transferFrom burnt token before approve ReFungible', async function() { - await requirePallets(this, [Pallets.ReFungible]); - await usingApi(async () => { - const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - await setCollectionLimitsExpectSuccess(alice, reFungibleCollectionId, {ownerCanTransfer: true}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100); - await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, alice, bob); - await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice, charlie, 1); + itSub('transferFrom burnt token after approve NFT', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-13', description: '', tokenPrefix: 'TF'}); + const nft = await collection.mintToken(alice, {Substrate: alice.address}); - }); - }); + await nft.approve(alice, {Substrate: bob.address}); + expect(await nft.isApproved({Substrate: bob.address})).to.be.true; - it('transferFrom burnt token after approve NFT', async () => { - await usingApi(async () => { - // nft - const nftCollectionId = await createCollectionExpectSuccess(); - const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT'); - await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address); - await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1); - await transferFromExpectFail(nftCollectionId, newNftTokenId, bob, alice, charlie, 1); - }); + await nft.burn(alice); + + await expect(nft.transferFrom( + bob, + {Substrate: alice.address}, + {Substrate: charlie.address}, + )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); }); - it('transferFrom burnt token after approve Fungible', async () => { - await usingApi(async () => { - const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); - const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible'); - await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address); - await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10); - await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice, charlie, 1); - }); + itSub('transferFrom burnt token after approve Fungible', async ({helper}) => { + const collection = await helper.ft.mintCollection(alice, {name: 'TransferFrom-Neg-14', description: '', tokenPrefix: 'TF'}); + await collection.mint(alice, {Substrate: alice.address}, 10n); + + await collection.approveTokens(alice, {Substrate: bob.address}); + expect(await collection.getApprovedTokens({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(1n); + + await collection.burnTokens(alice, 10n); + + await expect(collection.transferFrom( + bob, + {Substrate: alice.address}, + {Substrate: charlie.address}, + )).to.be.rejectedWith(/common\.TokenValueTooLow/); }); - it('transferFrom burnt token after approve ReFungible', async function() { - await requirePallets(this, [Pallets.ReFungible]); - await usingApi(async () => { - const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); - const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible'); - await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address); - await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100); - await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice, charlie, 1); + itSub.ifWithPallets('transferFrom burnt token after approve ReFungible', [Pallets.ReFungible], async ({helper}) => { + const collection = await helper.rft.mintCollection(alice, {name: 'TransferFrom-Neg-15', description: '', tokenPrefix: 'TF'}); + const rft = await collection.mintToken(alice, {Substrate: alice.address}, 10n); + + await rft.approve(alice, {Substrate: bob.address}, 10n); + expect(await rft.getApprovedPieces({Substrate: alice.address}, {Substrate: bob.address})).to.be.eq(10n); + + await rft.burn(alice, 10n); - }); + await expect(rft.transferFrom( + bob, + {Substrate: alice.address}, + {Substrate: charlie.address}, + )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); }); - it('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async () => { - const collectionId = await createCollectionExpectSuccess(); - const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address); - await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: false}); + itSub('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async ({helper}) => { + const collection = await helper.nft.mintCollection(alice, {name: 'TransferFrom-Neg-16', description: '', tokenPrefix: 'TF'}); + const nft = await collection.mintToken(alice, {Substrate: bob.address}); - await transferFromExpectFail(collectionId, itemId, alice, bob, charlie); + await collection.setLimits(alice, {ownerCanTransfer: false}); + + await expect(nft.transferFrom( + alice, + {Substrate: bob.address}, + {Substrate: charlie.address}, + )).to.be.rejectedWith(/common\.ApprovedValueTooLow/); }); }); --- a/tests/src/util/playgrounds/unique.ts +++ b/tests/src/util/playgrounds/unique.ts @@ -2128,10 +2128,6 @@ return await this.helper.collection.addAdmin(signer, this.collectionId, adminAddressObj); } - async enableCertainPermissions(signer: TSigner, accessMode: 'AllowList' | 'Normal' | undefined = 'AllowList', mintMode: boolean | undefined = true) { - return await this.setPermissions(signer, {access: accessMode, mintMode: mintMode}); - } - async addToAllowList(signer: TSigner, addressObj: ICrossAccountId) { return await this.helper.collection.addToAllowList(signer, this.collectionId, addressObj); } --- a/tests/src/xcmTransfer.test.ts +++ b/tests/src/xcmTransfer.test.ts @@ -33,6 +33,7 @@ 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;