difftreelog
wip migrating confirmSponsorship
in: master
2 files changed
tests/package.jsondiffbeforeafterboth--- a/tests/package.json
+++ b/tests/package.json
@@ -44,6 +44,7 @@
"testAddCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/addCollectionAdmin.test.ts",
"testSetSchemaVersion": "mocha --timeout 9999999 -r ts-node/register ./**/setSchemaVersion.test.ts",
"testSetCollectionLimits": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionLimits.test.ts",
+ "testChangeCollectionOwner": "mocha --timeout 9999999 -r ts-node/register ./**/change-collection-owner.test.ts",
"testSetCollectionSponsor": "mocha --timeout 9999999 -r ts-node/register ./**/setCollectionSponsor.test.ts",
"testConfirmSponsorship": "mocha --timeout 9999999 -r ts-node/register ./**/confirmSponsorship.test.ts",
"testRemoveCollectionAdmin": "mocha --timeout 9999999 -r ts-node/register ./**/removeCollectionAdmin.test.ts",
tests/src/confirmSponsorship.test.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import chai from 'chai';18import chaiAsPromised from 'chai-as-promised';19import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';20import {21 createCollectionExpectSuccess,22 setCollectionSponsorExpectSuccess,23 destroyCollectionExpectSuccess,24 confirmSponsorshipExpectSuccess,25 confirmSponsorshipExpectFailure,26 createItemExpectSuccess,27 findUnusedAddress,28 getGenericResult,29 enableAllowListExpectSuccess,30 enablePublicMintingExpectSuccess,31 addToAllowListExpectSuccess,32 normalizeAccountId,33 addCollectionAdminExpectSuccess,34 getCreatedCollectionCount,35 UNIQUE,36 requirePallets,37 Pallets,38} from './util/helpers';39import {IKeyringPair} from '@polkadot/types/types';4041chai.use(chaiAsPromised);42const expect = chai.expect;4344let alice: IKeyringPair;45let bob: IKeyringPair;46let charlie: IKeyringPair;4748describe('integration test: ext. confirmSponsorship():', () => {4950 before(async () => {51 await usingApi(async (api, privateKeyWrapper) => {52 alice = privateKeyWrapper('//Alice');53 bob = privateKeyWrapper('//Bob');54 charlie = privateKeyWrapper('//Charlie');55 });56 });5758 it('Confirm collection sponsorship', async () => {59 const collectionId = await createCollectionExpectSuccess();60 await setCollectionSponsorExpectSuccess(collectionId, bob.address);61 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');62 });63 it('Add sponsor to a collection after the same sponsor was already added and confirmed', async () => {64 const collectionId = await createCollectionExpectSuccess();65 await setCollectionSponsorExpectSuccess(collectionId, bob.address);66 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');67 await setCollectionSponsorExpectSuccess(collectionId, bob.address);68 });69 it('Add new sponsor to a collection after another sponsor was already added and confirmed', async () => {70 const collectionId = await createCollectionExpectSuccess();71 await setCollectionSponsorExpectSuccess(collectionId, bob.address);72 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');73 await setCollectionSponsorExpectSuccess(collectionId, charlie.address);74 });7576 it('NFT: Transfer fees are paid by the sponsor after confirmation', async () => {77 const collectionId = await createCollectionExpectSuccess();78 await setCollectionSponsorExpectSuccess(collectionId, bob.address);79 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');8081 await usingApi(async (api, privateKeyWrapper) => {82 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();8384 // Find unused address85 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);8687 // Mint token for unused address88 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address);8990 // Transfer this tokens from unused address to Alice91 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);92 const events = await submitTransactionAsync(zeroBalance, zeroToAlice);93 const result = getGenericResult(events);94 expect(result.success).to.be.true;9596 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();9798 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;99 });100101 });102103 it('Fungible: Transfer fees are paid by the sponsor after confirmation', async () => {104 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});105 await setCollectionSponsorExpectSuccess(collectionId, bob.address);106 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');107108 await usingApi(async (api, privateKeyWrapper) => {109 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();110111 // Find unused address112 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);113114 // Mint token for unused address115 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);116117 // Transfer this tokens from unused address to Alice118 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);119 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);120 const result1 = getGenericResult(events1);121 expect(result1.success).to.be.true;122123 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();124125 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;126 });127 });128129 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async function() {130 await requirePallets(this, [Pallets.ReFungible]);131132 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});133 await setCollectionSponsorExpectSuccess(collectionId, bob.address);134 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');135136 await usingApi(async (api, privateKeyWrapper) => {137 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();138139 // Find unused address140 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);141142 // Mint token for unused address143 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);144145 // Transfer this tokens from unused address to Alice146 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);147 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);148 const result1 = getGenericResult(events1);149150 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();151152 expect(result1.success).to.be.true;153 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;154 });155 });156157 it('CreateItem fees are paid by the sponsor after confirmation', async () => {158 const collectionId = await createCollectionExpectSuccess();159 await setCollectionSponsorExpectSuccess(collectionId, bob.address);160 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');161162 // Enable collection allow list163 await enableAllowListExpectSuccess(alice, collectionId);164165 // Enable public minting166 await enablePublicMintingExpectSuccess(alice, collectionId);167168 // Create Item169 await usingApi(async (api, privateKeyWrapper) => {170 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();171172 // Find unused address173 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);174175 // Add zeroBalance address to allow list176 await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);177178 // Mint token using unused address as signer179 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);180181 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();182183 expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;184 });185 });186187 it('NFT: Sponsoring of transfers is rate limited', async () => {188 const collectionId = await createCollectionExpectSuccess();189 await setCollectionSponsorExpectSuccess(collectionId, bob.address);190 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');191192 await usingApi(async (api, privateKeyWrapper) => {193 // Find unused address194 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);195196 // Mint token for alice197 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);198199 // Transfer this token from Alice to unused address and back200 // Alice to Zero gets sponsored201 const aliceToZero = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);202 const events1 = await submitTransactionAsync(alice, aliceToZero);203 const result1 = getGenericResult(events1);204205 // Second transfer should fail206 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();207 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);208 const badTransaction = async function () {209 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);210 };211 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');212 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();213214 // Try again after Zero gets some balance - now it should succeed215 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);216 await submitTransactionAsync(alice, balancetx);217 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);218 const result2 = getGenericResult(events2);219220 expect(result1.success).to.be.true;221 expect(result2.success).to.be.true;222 expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);223 });224 });225226 it('Fungible: Sponsoring is rate limited', async () => {227 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});228 await setCollectionSponsorExpectSuccess(collectionId, bob.address);229 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');230231 await usingApi(async (api, privateKeyWrapper) => {232 // Find unused address233 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);234235 // Mint token for unused address236 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);237238 // Transfer this tokens in parts from unused address to Alice239 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);240 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);241 const result1 = getGenericResult(events1);242 expect(result1.success).to.be.true;243244 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();245 await expect(submitTransactionExpectFailAsync(zeroBalance, zeroToAlice)).to.be.rejected;246 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();247248 // Try again after Zero gets some balance - now it should succeed249 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);250 await submitTransactionAsync(alice, balancetx);251 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);252 const result2 = getGenericResult(events2);253 expect(result2.success).to.be.true;254255 expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);256 });257 });258259 it('ReFungible: Sponsoring is rate limited', async function() {260 await requirePallets(this, [Pallets.ReFungible]);261262 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});263 await setCollectionSponsorExpectSuccess(collectionId, bob.address);264 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');265266 await usingApi(async (api, privateKeyWrapper) => {267 // Find unused address268 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);269270 // Mint token for alice271 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);272273 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 1);274275 // Zero to alice gets sponsored276 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);277 const result1 = getGenericResult(events1);278 expect(result1.success).to.be.true;279280 // Second transfer should fail281 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();282 await expect(submitTransactionExpectFailAsync(zeroBalance, zeroToAlice)).to.be.rejectedWith('Inability to pay some fees');283 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();284 expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);285286 // Try again after Zero gets some balance - now it should succeed287 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);288 await submitTransactionAsync(alice, balancetx);289 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);290 const result2 = getGenericResult(events2);291 expect(result2.success).to.be.true;292 });293 });294295 it('NFT: Sponsoring of createItem is rate limited', async () => {296 const collectionId = await createCollectionExpectSuccess();297 await setCollectionSponsorExpectSuccess(collectionId, bob.address);298 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');299300 // Enable collection allow list301 await enableAllowListExpectSuccess(alice, collectionId);302303 // Enable public minting304 await enablePublicMintingExpectSuccess(alice, collectionId);305306 await usingApi(async (api, privateKeyWrapper) => {307 // Find unused address308 const zeroBalance = await findUnusedAddress(api, privateKeyWrapper);309310 // Add zeroBalance address to allow list311 await addToAllowListExpectSuccess(alice, collectionId, zeroBalance.address);312313 // Mint token using unused address as signer - gets sponsored314 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);315316 // Second mint should fail317 const sponsorBalanceBefore = (await api.query.system.account(bob.address)).data.free.toBigInt();318319 const badTransaction = async function () {320 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);321 };322 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');323 const sponsorBalanceAfter = (await api.query.system.account(bob.address)).data.free.toBigInt();324325 // Try again after Zero gets some balance - now it should succeed326 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1n * UNIQUE);327 await submitTransactionAsync(alice, balancetx);328 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);329330 expect(sponsorBalanceAfter).to.be.equal(sponsorBalanceBefore);331 });332 });333334});335336describe('(!negative test!) integration test: ext. confirmSponsorship():', () => {337 before(async () => {338 await usingApi(async (api, privateKeyWrapper) => {339 alice = privateKeyWrapper('//Alice');340 bob = privateKeyWrapper('//Bob');341 charlie = privateKeyWrapper('//Charlie');342 });343 });344345 it('(!negative test!) Confirm sponsorship for a collection that never existed', async () => {346 // Find the collection that never existed347 let collectionId = 0;348 await usingApi(async (api) => {349 collectionId = await getCreatedCollectionCount(api) + 1;350 });351352 await confirmSponsorshipExpectFailure(collectionId, '//Bob');353 });354355 it('(!negative test!) Confirm sponsorship using a non-sponsor address', async () => {356 const collectionId = await createCollectionExpectSuccess();357 await setCollectionSponsorExpectSuccess(collectionId, bob.address);358359 await usingApi(async (api) => {360 const transfer = api.tx.balances.transfer(charlie.address, 1e15);361 await submitTransactionAsync(alice, transfer);362 });363364 await confirmSponsorshipExpectFailure(collectionId, '//Charlie');365 });366367 it('(!negative test!) Confirm sponsorship using owner address', async () => {368 const collectionId = await createCollectionExpectSuccess();369 await setCollectionSponsorExpectSuccess(collectionId, bob.address);370 await confirmSponsorshipExpectFailure(collectionId, '//Alice');371 });372373 it('(!negative test!) Confirm sponsorship by collection admin', async () => {374 const collectionId = await createCollectionExpectSuccess();375 await setCollectionSponsorExpectSuccess(collectionId, bob.address);376 await addCollectionAdminExpectSuccess(alice, collectionId, charlie.address);377 await confirmSponsorshipExpectFailure(collectionId, '//Charlie');378 });379380 it('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async () => {381 const collectionId = await createCollectionExpectSuccess();382 await confirmSponsorshipExpectFailure(collectionId, '//Bob');383 });384385 it('(!negative test!) Confirm sponsorship in a collection that was destroyed', async () => {386 const collectionId = await createCollectionExpectSuccess();387 await destroyCollectionExpectSuccess(collectionId);388 await confirmSponsorshipExpectFailure(collectionId, '//Bob');389 });390391 it('(!negative test!) Transfer fees are not paid by the sponsor if the transfer failed', async () => {392 const collectionId = await createCollectionExpectSuccess();393 await setCollectionSponsorExpectSuccess(collectionId, bob.address);394 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');395396 await usingApi(async (api, privateKeyWrapper) => {397 // Find unused address398 const ownerZeroBalance = await findUnusedAddress(api, privateKeyWrapper);399400 // Find another unused address401 const senderZeroBalance = await findUnusedAddress(api, privateKeyWrapper);402403 // Mint token for an unused address404 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', ownerZeroBalance.address);405406 const sponsorBalanceBeforeTx = (await api.query.system.account(bob.address)).data.free.toBigInt();407408 // Try to transfer this token from an unsponsored unused adress to Alice409 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);410 await expect(submitTransactionExpectFailAsync(senderZeroBalance, zeroToAlice)).to.be.rejected;411412 const sponsorBalanceAfterTx = (await api.query.system.account(bob.address)).data.free.toBigInt();413414 expect(sponsorBalanceAfterTx).to.equal(sponsorBalanceBeforeTx);415 });416 });417});1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import chai from 'chai';18import chaiAsPromised from 'chai-as-promised';19import {default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync} from './substrate/substrate-api';20import {21 createCollectionExpectSuccess,22 setCollectionSponsorExpectSuccess,23 destroyCollectionExpectSuccess,24 confirmSponsorshipExpectSuccess,25 confirmSponsorshipExpectFailure,26 createItemExpectSuccess,27 findUnusedAddress,28 getGenericResult,29 enableAllowListExpectSuccess,30 enablePublicMintingExpectSuccess,31 addToAllowListExpectSuccess,32 normalizeAccountId,33 addCollectionAdminExpectSuccess,34 getCreatedCollectionCount,35 UNIQUE,36 requirePallets,37 Pallets,38} from './util/helpers';39import {IKeyringPair} from '@polkadot/types/types';40import {usingPlaygrounds} from './util/playgrounds';4142chai.use(chaiAsPromised);43const expect = chai.expect;4445let donor: IKeyringPair;4647before(async () => {48 await usingPlaygrounds(async (_, privateKey) => {49 donor = privateKey('//Alice');50 });51});5253let alice: IKeyringPair;54let bob: IKeyringPair;55let charlie: IKeyringPair;5657describe('integration test: ext. confirmSponsorship():', () => {5859 before(async () => {60 await usingPlaygrounds(async (helper) => {61 [alice, bob, charlie] = await helper.arrange.createAccounts([100n, 100n, 0n], donor);62 });63 });6465 it('Confirm collection sponsorship', async () => {66 await usingPlaygrounds(async (helper) => {67 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});68 await collection.setSponsor(alice, bob.address);69 await collection.confirmSponsorship(bob);70 });71 });7273 it('Add sponsor to a collection after the same sponsor was already added and confirmed', async () => {74 await usingPlaygrounds(async (helper) => {75 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});76 await collection.setSponsor(alice, bob.address);77 await collection.confirmSponsorship(bob);78 await collection.setSponsor(alice, bob.address);79 });80 });81 it('Add new sponsor to a collection after another sponsor was already added and confirmed', async () => {82 await usingPlaygrounds(async (helper) => {83 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});84 await collection.setSponsor(alice, bob.address);85 await collection.confirmSponsorship(charlie);86 });87 });8889 it('NFT: Transfer fees are paid by the sponsor after confirmation', async () => {90 await usingPlaygrounds(async (helper) => {91 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});92 await collection.setSponsor(alice, bob.address);93 await collection.confirmSponsorship(bob);94 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);95 const token = await collection.mintToken(alice, {Substrate: charlie.address});96 await token.transfer(charlie, {Substrate: alice.address});97 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);98 expect(bobBalanceAfter < bobBalanceBefore).to.be.true;99 });100 });101102 it('Fungible: Transfer fees are paid by the sponsor after confirmation', async () => {103 await usingPlaygrounds(async (helper) => {104 const collection = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'}, 0);105 await collection.setSponsor(alice, bob.address);106 await collection.confirmSponsorship(bob);107 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);108 await collection.mint(alice, {Substrate: charlie.address}, 100n);109 await collection.transfer(charlie, {Substrate: alice.address}, 1n);110 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);111 expect(bobBalanceAfter < bobBalanceBefore).to.be.true;112 });113 });114115 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async function() {116 await usingPlaygrounds(async (helper) => {117 const collection = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});118 await collection.setSponsor(alice, bob.address);119 await collection.confirmSponsorship(bob);120 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);121 const token = await collection.mintToken(alice, {Substrate: charlie.address}, 100n);122 await token.transfer(charlie, {Substrate: alice.address}, 1n);123 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);124 expect(bobBalanceAfter < bobBalanceBefore).to.be.true;125 });126 });127128 it('CreateItem fees are paid by the sponsor after confirmation', async () => {129 await usingPlaygrounds(async (helper) => {130 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});131 await collection.setSponsor(alice, bob.address);132 await collection.confirmSponsorship(bob);133 await collection.setPermissions(alice, {access: 'AllowList', mintMode: true});134 await collection.addToAllowList(alice, {Substrate: charlie.address});135136 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);137 await collection.mintToken(charlie, {Substrate: charlie.address});138 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);139140 expect(bobBalanceAfter < bobBalanceBefore).to.be.true;141 });142 });143144 it('NFT: Sponsoring of transfers is rate limited', async () => {145 await usingPlaygrounds(async (helper) => {146 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});147 await collection.setSponsor(alice, bob.address);148 await collection.confirmSponsorship(bob);149150 const token = await collection.mintToken(alice, {Substrate: alice.address});151 await token.transfer(alice, {Substrate: charlie.address});152 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);153154 const transferTx = async () => token.transfer(charlie, {Substrate: alice.address});155 await expect(transferTx()).to.be.rejectedWith('Inability to pay some fees');156 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);157158 expect(bobBalanceAfter === bobBalanceBefore).to.be.true;159 });160 });161162 it('Fungible: Sponsoring is rate limited', async () => {163 await usingPlaygrounds(async (helper) => {164 const collection = await helper.ft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});165 await collection.setSponsor(alice, bob.address);166 await collection.confirmSponsorship(bob);167168 await collection.mint(alice, {Substrate: charlie.address}, 100n);169 await collection.transfer(charlie, {Substrate: charlie.address}, 1n);170 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);171172 const transferTx = async () => collection.transfer(charlie, {Substrate: charlie.address});173 await expect(transferTx()).to.be.rejected;174 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);175176 expect(bobBalanceAfter === bobBalanceBefore).to.be.true;177 });178 });179180 it('ReFungible: Sponsoring is rate limited', async function() {181 await usingPlaygrounds(async (helper) => {182 const collection = await helper.rft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});183 await collection.setSponsor(alice, bob.address);184 await collection.confirmSponsorship(bob);185186 const token = await collection.mintToken(alice, {Substrate: charlie.address}, 100n);187 await token.transfer(charlie, {Substrate: alice.address});188189 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);190 const transferTx = async () => token.transfer(charlie, {Substrate: alice.address});191 await expect(transferTx()).to.be.rejectedWith('Inability to pay some fees');192 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);193194 expect(bobBalanceAfter === bobBalanceBefore).to.be.true;195 });196 });197198 it('NFT: Sponsoring of createItem is rate limited', async () => {199 await usingPlaygrounds(async (helper) => {200 const collection = await helper.nft.mintCollection(alice, {name: 'col', description: 'descr', tokenPrefix: 'COL'});201 await collection.setSponsor(alice, bob.address);202 await collection.confirmSponsorship(bob);203 await collection.setPermissions(alice, {mintMode: true, access: 'AllowList'});204 await collection.addToAllowList(alice, {Substrate: charlie.address});205206 await collection.mintToken(charlie, {Substrate: charlie.address});207208 const bobBalanceBefore = await helper.balance.getSubstrate(bob.address);209 const mintTx = async () => collection.mintToken(charlie, {Substrate: charlie.address});210 await expect(mintTx()).to.be.rejectedWith('Inability to pay some fees');211 const bobBalanceAfter = await helper.balance.getSubstrate(bob.address);212213 expect(bobBalanceAfter === bobBalanceBefore).to.be.true;214 });215 });216});217218describe('(!negative test!) integration test: ext. confirmSponsorship():', () => {219 before(async () => {220 await usingApi(async (api, privateKeyWrapper) => {221 alice = privateKeyWrapper('//Alice');222 bob = privateKeyWrapper('//Bob');223 charlie = privateKeyWrapper('//Charlie');224 });225 });226227 it('(!negative test!) Confirm sponsorship for a collection that never existed', async () => {228 // Find the collection that never existed229 let collectionId = 0;230 await usingApi(async (api) => {231 collectionId = await getCreatedCollectionCount(api) + 1;232 });233234 await confirmSponsorshipExpectFailure(collectionId, '//Bob');235 });236237 it('(!negative test!) Confirm sponsorship using a non-sponsor address', async () => {238 const collectionId = await createCollectionExpectSuccess();239 await setCollectionSponsorExpectSuccess(collectionId, bob.address);240241 await usingApi(async (api) => {242 const transfer = api.tx.balances.transfer(charlie.address, 1e15);243 await submitTransactionAsync(alice, transfer);244 });245246 await confirmSponsorshipExpectFailure(collectionId, '//Charlie');247 });248249 it('(!negative test!) Confirm sponsorship using owner address', async () => {250 const collectionId = await createCollectionExpectSuccess();251 await setCollectionSponsorExpectSuccess(collectionId, bob.address);252 await confirmSponsorshipExpectFailure(collectionId, '//Alice');253 });254255 it('(!negative test!) Confirm sponsorship by collection admin', async () => {256 const collectionId = await createCollectionExpectSuccess();257 await setCollectionSponsorExpectSuccess(collectionId, bob.address);258 await addCollectionAdminExpectSuccess(alice, collectionId, charlie.address);259 await confirmSponsorshipExpectFailure(collectionId, '//Charlie');260 });261262 it('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async () => {263 const collectionId = await createCollectionExpectSuccess();264 await confirmSponsorshipExpectFailure(collectionId, '//Bob');265 });266267 it('(!negative test!) Confirm sponsorship in a collection that was destroyed', async () => {268 const collectionId = await createCollectionExpectSuccess();269 await destroyCollectionExpectSuccess(collectionId);270 await confirmSponsorshipExpectFailure(collectionId, '//Bob');271 });272273 it('(!negative test!) Transfer fees are not paid by the sponsor if the transfer failed', async () => {274 const collectionId = await createCollectionExpectSuccess();275 await setCollectionSponsorExpectSuccess(collectionId, bob.address);276 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');277278 await usingApi(async (api, privateKeyWrapper) => {279 // Find unused address280 const ownerZeroBalance = await findUnusedAddress(api, privateKeyWrapper);281282 // Find another unused address283 const senderZeroBalance = await findUnusedAddress(api, privateKeyWrapper);284285 // Mint token for an unused address286 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', ownerZeroBalance.address);287288 const sponsorBalanceBeforeTx = (await api.query.system.account(bob.address)).data.free.toBigInt();289290 // Try to transfer this token from an unsponsored unused adress to Alice291 const zeroToAlice = api.tx.unique.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);292 await expect(submitTransactionExpectFailAsync(senderZeroBalance, zeroToAlice)).to.be.rejected;293294 const sponsorBalanceAfterTx = (await api.query.system.account(bob.address)).data.free.toBigInt();295296 expect(sponsorBalanceAfterTx).to.equal(sponsorBalanceBeforeTx);297 });298 });299});