123456import chai from 'chai';7import chaiAsPromised from 'chai-as-promised';8import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";9import { 10 createCollectionExpectSuccess, 11 setCollectionSponsorExpectSuccess, 12 destroyCollectionExpectSuccess, 13 setCollectionSponsorExpectFailure,14 confirmSponsorshipExpectSuccess,15 confirmSponsorshipExpectFailure,16 createItemExpectSuccess,17 findUnusedAddress,18 getGenericResult,19 enableWhiteListExpectSuccess,20 enablePublicMintingExpectSuccess,21 addToWhiteListExpectSuccess,22 normalizeAccountId,23} from "./util/helpers";24import { Keyring } from "@polkadot/api";25import { IKeyringPair } from "@polkadot/types/types";26import type { AccountId } from '@polkadot/types/interfaces';27import { BigNumber } from 'bignumber.js';2829chai.use(chaiAsPromised);30const expect = chai.expect;3132let alice: IKeyringPair;33let bob: IKeyringPair;34let charlie: IKeyringPair;3536describe('integration test: ext. confirmSponsorship():', () => {3738 before(async () => {39 await usingApi(async (api) => {40 const keyring = new Keyring({ type: 'sr25519' });41 alice = keyring.addFromUri(`//Alice`);42 bob = keyring.addFromUri(`//Bob`);43 charlie = keyring.addFromUri(`//Charlie`);44 });45 });4647 it('Confirm collection sponsorship', async () => {48 const collectionId = await createCollectionExpectSuccess();49 await setCollectionSponsorExpectSuccess(collectionId, bob.address);50 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');51 });52 it('Add sponsor to a collection after the same sponsor was already added and confirmed', async () => {53 const collectionId = await createCollectionExpectSuccess();54 await setCollectionSponsorExpectSuccess(collectionId, bob.address);55 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');56 await setCollectionSponsorExpectSuccess(collectionId, bob.address);57 });58 it('Add new sponsor to a collection after another sponsor was already added and confirmed', async () => {59 const collectionId = await createCollectionExpectSuccess();60 await setCollectionSponsorExpectSuccess(collectionId, bob.address);61 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');62 await setCollectionSponsorExpectSuccess(collectionId, charlie.address);63 });6465 it('NFT: Transfer fees are paid by the sponsor after confirmation', async () => {66 const collectionId = await createCollectionExpectSuccess();67 await setCollectionSponsorExpectSuccess(collectionId, bob.address);68 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');6970 await usingApi(async (api) => {71 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());7273 74 const zeroBalance = await findUnusedAddress(api);7576 77 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address);7879 80 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);81 const events = await submitTransactionAsync(zeroBalance, zeroToAlice);82 const result = getGenericResult(events);8384 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());8586 expect(result.success).to.be.true;87 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;88 });8990 });9192 it('Fungible: Transfer fees are paid by the sponsor after confirmation', async () => {93 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0 }});94 await setCollectionSponsorExpectSuccess(collectionId, bob.address);95 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');9697 await usingApi(async (api) => {98 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());99100 101 const zeroBalance = await findUnusedAddress(api);102103 104 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);105106 107 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);108 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);109 const result1 = getGenericResult(events1);110111 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());112113 expect(result1.success).to.be.true;114 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;115 });116 });117118 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {119 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});120 await setCollectionSponsorExpectSuccess(collectionId, bob.address);121 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');122123 await usingApi(async (api) => {124 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());125126 127 const zeroBalance = await findUnusedAddress(api);128129 130 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);131132 133 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);134 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);135 const result1 = getGenericResult(events1);136137 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());138139 expect(result1.success).to.be.true;140 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;141 });142 });143144 it('CreateItem fees are paid by the sponsor after confirmation', async () => {145 const collectionId = await createCollectionExpectSuccess();146 await setCollectionSponsorExpectSuccess(collectionId, bob.address);147 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');148149 150 await enableWhiteListExpectSuccess(alice, collectionId);151152 153 await enablePublicMintingExpectSuccess(alice, collectionId);154155 156 await usingApi(async (api) => {157 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());158159 160 const zeroBalance = await findUnusedAddress(api);161162 163 await addToWhiteListExpectSuccess(alice, collectionId, zeroBalance.address);164165 166 const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);167168 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());169170 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;171 });172 });173174 it('NFT: Sponsoring of transfers is rate limited', async () => {175 const collectionId = await createCollectionExpectSuccess();176 await setCollectionSponsorExpectSuccess(collectionId, bob.address);177 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');178179 await usingApi(async (api) => {180 181 const zeroBalance = await findUnusedAddress(api);182183 184 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);185186 187 188 const aliceToZero = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);189 const events1 = await submitTransactionAsync(alice, aliceToZero);190 const result1 = getGenericResult(events1);191192 193 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());194 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);195 const badTransaction = async function () { 196 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);197 };198 await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");199 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());200201 202 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);203 await submitTransactionAsync(alice, balancetx);204 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);205 const result2 = getGenericResult(events2);206207 expect(result1.success).to.be.true;208 expect(result2.success).to.be.true;209 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;210 });211 });212213 it('Fungible: Sponsoring is rate limited', async () => {214 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0 }});215 await setCollectionSponsorExpectSuccess(collectionId, bob.address);216 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');217218 await usingApi(async (api) => {219 220 const zeroBalance = await findUnusedAddress(api);221222 223 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);224225 226 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);227 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);228 const result1 = getGenericResult(events1);229230 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());231232 const badTransaction = async function () { 233 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);234 };235236 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());237238 239 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);240 await submitTransactionAsync(alice, balancetx);241 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);242 const result2 = getGenericResult(events2);243244 expect(result1.success).to.be.true;245 expect(result2.success).to.be.true;246 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;247 });248 });249250 it('ReFungible: Sponsoring is rate limited', async () => {251 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});252 await setCollectionSponsorExpectSuccess(collectionId, bob.address);253 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');254255 await usingApi(async (api) => {256 257 const zeroBalance = await findUnusedAddress(api);258259 260 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);261262 263 264 const aliceToZero = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);265 const events1 = await submitTransactionAsync(alice, aliceToZero);266 const result1 = getGenericResult(events1);267268 269 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());270 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(alice.address), collectionId, itemId, 1);271 const badTransaction = async function () { 272 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);273 };274 await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");275 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());276277 278 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);279 await submitTransactionAsync(alice, balancetx);280 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);281 const result2 = getGenericResult(events2);282283 expect(result1.success).to.be.true;284 expect(result2.success).to.be.true;285 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;286 });287 });288289 it('NFT: Sponsoring of createItem is rate limited', async () => {290 const collectionId = await createCollectionExpectSuccess();291 await setCollectionSponsorExpectSuccess(collectionId, bob.address);292 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');293294 295 await enableWhiteListExpectSuccess(alice, collectionId);296297 298 await enablePublicMintingExpectSuccess(alice, collectionId);299300 await usingApi(async (api) => {301 302 const zeroBalance = await findUnusedAddress(api);303304 305 await addToWhiteListExpectSuccess(alice, collectionId, zeroBalance.address);306307 308 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);309310 311 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());312 313 const consoleError = console.error;314 const consoleLog = console.log;315 console.error = () => {};316 console.log = () => {};317 const badTransaction = async function () { 318 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);319 };320 await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");321 console.error = consoleError;322 console.log = consoleLog;323 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());324325 326 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);327 await submitTransactionAsync(alice, balancetx);328 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);329330 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;331 });332 });333334});335336describe('(!negative test!) integration test: ext. removeCollectionSponsor():', () => {337 before(async () => {338 await usingApi(async (api) => {339 const keyring = new Keyring({ type: 'sr25519' });340 alice = keyring.addFromUri(`//Alice`);341 bob = keyring.addFromUri(`//Bob`);342 charlie = keyring.addFromUri(`//Charlie`);343 });344 });345346 it('(!negative test!) Confirm sponsorship for a collection that never existed', async () => {347 348 const collectionId = 0;349 await usingApi(async (api) => {350 const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;351 });352353 await confirmSponsorshipExpectFailure(collectionId, '//Bob');354 });355356 it('(!negative test!) Confirm sponsorship using a non-sponsor address', async () => {357 const collectionId = await createCollectionExpectSuccess();358 await setCollectionSponsorExpectSuccess(collectionId, bob.address);359360 await usingApi(async (api) => {361 const transfer = api.tx.balances.transfer(charlie.address, 1e15);362 await submitTransactionAsync(alice, transfer);363 });364365 await confirmSponsorshipExpectFailure(collectionId, '//Charlie');366 });367368 it('(!negative test!) Confirm sponsorship using owner address', async () => {369 const collectionId = await createCollectionExpectSuccess();370 await setCollectionSponsorExpectSuccess(collectionId, bob.address);371 await confirmSponsorshipExpectFailure(collectionId, '//Alice');372 });373374 it('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async () => {375 const collectionId = await createCollectionExpectSuccess();376 await confirmSponsorshipExpectFailure(collectionId, '//Bob');377 });378 379 it('(!negative test!) Confirm sponsorship in a collection that was destroyed', async () => {380 const collectionId = await createCollectionExpectSuccess();381 await destroyCollectionExpectSuccess(collectionId);382 await confirmSponsorshipExpectFailure(collectionId, '//Bob');383 });384});