1234567891011121314151617import 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 229 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 280 const ownerZeroBalance = await findUnusedAddress(api, privateKeyWrapper);281282 283 const senderZeroBalance = await findUnusedAddress(api, privateKeyWrapper);284285 286 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', ownerZeroBalance.address);287288 const sponsorBalanceBeforeTx = (await api.query.system.account(bob.address)).data.free.toBigInt();289290 291 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});