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 confirmSponsorshipExpectSuccess,14 confirmSponsorshipExpectFailure,15 createItemExpectSuccess,16 findUnusedAddress,17 getGenericResult,18 enableWhiteListExpectSuccess,19 enablePublicMintingExpectSuccess,20 addToWhiteListExpectSuccess,21 normalizeAccountId,22} from './util/helpers';23import { Keyring } from '@polkadot/api';24import { IKeyringPair } from '@polkadot/types/types';25import { BigNumber } from 'bignumber.js';2627chai.use(chaiAsPromised);28const expect = chai.expect;2930let alice: IKeyringPair;31let bob: IKeyringPair;32let charlie: IKeyringPair;3334describe('integration test: ext. confirmSponsorship():', () => {3536 before(async () => {37 await usingApi(async () => {38 const keyring = new Keyring({ type: 'sr25519' });39 alice = keyring.addFromUri('//Alice');40 bob = keyring.addFromUri('//Bob');41 charlie = keyring.addFromUri('//Charlie');42 });43 });4445 it('Confirm collection sponsorship', async () => {46 const collectionId = await createCollectionExpectSuccess();47 await setCollectionSponsorExpectSuccess(collectionId, bob.address);48 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');49 });50 it('Add sponsor to a collection after the same sponsor was already added and confirmed', async () => {51 const collectionId = await createCollectionExpectSuccess();52 await setCollectionSponsorExpectSuccess(collectionId, bob.address);53 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');54 await setCollectionSponsorExpectSuccess(collectionId, bob.address);55 });56 it('Add new sponsor to a collection after another sponsor was already added and confirmed', async () => {57 const collectionId = await createCollectionExpectSuccess();58 await setCollectionSponsorExpectSuccess(collectionId, bob.address);59 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');60 await setCollectionSponsorExpectSuccess(collectionId, charlie.address);61 });6263 it('NFT: Transfer fees are paid by the sponsor after confirmation', async () => {64 const collectionId = await createCollectionExpectSuccess();65 await setCollectionSponsorExpectSuccess(collectionId, bob.address);66 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');6768 await usingApi(async (api) => {69 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());7071 72 const zeroBalance = await findUnusedAddress(api);7374 75 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address);7677 78 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);79 const events = await submitTransactionAsync(zeroBalance, zeroToAlice);80 const result = getGenericResult(events);8182 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());8384 expect(result.success).to.be.true;85 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;86 });8788 });8990 it('Fungible: Transfer fees are paid by the sponsor after confirmation', async () => {91 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0 }});92 await setCollectionSponsorExpectSuccess(collectionId, bob.address);93 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');9495 await usingApi(async (api) => {96 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());9798 99 const zeroBalance = await findUnusedAddress(api);100101 102 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);103104 105 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);106 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);107 const result1 = getGenericResult(events1);108109 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());110111 expect(result1.success).to.be.true;112 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;113 });114 });115116 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {117 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});118 await setCollectionSponsorExpectSuccess(collectionId, bob.address);119 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');120121 await usingApi(async (api) => {122 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());123124 125 const zeroBalance = await findUnusedAddress(api);126127 128 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);129130 131 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);132 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);133 const result1 = getGenericResult(events1);134135 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());136137 expect(result1.success).to.be.true;138 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;139 });140 });141142 it('CreateItem fees are paid by the sponsor after confirmation', async () => {143 const collectionId = await createCollectionExpectSuccess();144 await setCollectionSponsorExpectSuccess(collectionId, bob.address);145 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');146147 148 await enableWhiteListExpectSuccess(alice, collectionId);149150 151 await enablePublicMintingExpectSuccess(alice, collectionId);152153 154 await usingApi(async (api) => {155 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());156157 158 const zeroBalance = await findUnusedAddress(api);159160 161 await addToWhiteListExpectSuccess(alice, collectionId, zeroBalance.address);162163 164 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);165166 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());167168 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;169 });170 });171172 it('NFT: Sponsoring of transfers is rate limited', async () => {173 const collectionId = await createCollectionExpectSuccess();174 await setCollectionSponsorExpectSuccess(collectionId, bob.address);175 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');176177 await usingApi(async (api) => {178 179 const zeroBalance = await findUnusedAddress(api);180181 182 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);183184 185 186 const aliceToZero = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 0);187 const events1 = await submitTransactionAsync(alice, aliceToZero);188 const result1 = getGenericResult(events1);189190 191 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());192 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(alice.address), collectionId, itemId, 0);193 const badTransaction = async function () { 194 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);195 };196 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');197 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());198199 200 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);201 await submitTransactionAsync(alice, balancetx);202 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);203 const result2 = getGenericResult(events2);204205 expect(result1.success).to.be.true;206 expect(result2.success).to.be.true;207 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;208 });209 });210211 it('Fungible: Sponsoring is rate limited', async () => {212 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0 }});213 await setCollectionSponsorExpectSuccess(collectionId, bob.address);214 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');215216 await usingApi(async (api) => {217 218 const zeroBalance = await findUnusedAddress(api);219220 221 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);222223 224 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);225 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);226 const result1 = getGenericResult(events1);227228 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());229 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);230 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());231232 233 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);234 await submitTransactionAsync(alice, balancetx);235 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);236 const result2 = getGenericResult(events2);237238 expect(result1.success).to.be.true;239 expect(result2.success).to.be.true;240 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;241 });242 });243244 it('ReFungible: Sponsoring is rate limited', async () => {245 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});246 await setCollectionSponsorExpectSuccess(collectionId, bob.address);247 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');248249 await usingApi(async (api) => {250 251 const zeroBalance = await findUnusedAddress(api);252253 254 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);255256 257 258 const aliceToZero = api.tx.nft.transfer(normalizeAccountId(zeroBalance.address), collectionId, itemId, 1);259 const events1 = await submitTransactionAsync(alice, aliceToZero);260 const result1 = getGenericResult(events1);261262 263 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());264 const zeroToAlice = api.tx.nft.transfer(normalizeAccountId(alice.address), collectionId, itemId, 1);265 const badTransaction = async function () { 266 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);267 };268 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');269 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());270271 272 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);273 await submitTransactionAsync(alice, balancetx);274 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);275 const result2 = getGenericResult(events2);276277 expect(result1.success).to.be.true;278 expect(result2.success).to.be.true;279 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;280 });281 });282283 it('NFT: Sponsoring of createItem is rate limited', async () => {284 const collectionId = await createCollectionExpectSuccess();285 await setCollectionSponsorExpectSuccess(collectionId, bob.address);286 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');287288 289 await enableWhiteListExpectSuccess(alice, collectionId);290291 292 await enablePublicMintingExpectSuccess(alice, collectionId);293294 await usingApi(async (api) => {295 296 const zeroBalance = await findUnusedAddress(api);297298 299 await addToWhiteListExpectSuccess(alice, collectionId, zeroBalance.address);300301 302 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);303304 305 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());306 307 const consoleError = console.error;308 const consoleLog = console.log;309 console.error = () => {};310 console.log = () => {};311 const badTransaction = async function () { 312 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);313 };314 await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees');315 console.error = consoleError;316 console.log = consoleLog;317 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());318319 320 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);321 await submitTransactionAsync(alice, balancetx);322 await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);323324 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;325 });326 });327328});329330describe('(!negative test!) integration test: ext. removeCollectionSponsor():', () => {331 before(async () => {332 await usingApi(async () => {333 const keyring = new Keyring({ type: 'sr25519' });334 alice = keyring.addFromUri('//Alice');335 bob = keyring.addFromUri('//Bob');336 charlie = keyring.addFromUri('//Charlie');337 });338 });339340 it('(!negative test!) Confirm sponsorship for a collection that never existed', async () => {341 342 let collectionId = 0;343 await usingApi(async (api) => {344 collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;345 });346347 await confirmSponsorshipExpectFailure(collectionId, '//Bob');348 });349350 it('(!negative test!) Confirm sponsorship using a non-sponsor address', async () => {351 const collectionId = await createCollectionExpectSuccess();352 await setCollectionSponsorExpectSuccess(collectionId, bob.address);353354 await usingApi(async (api) => {355 const transfer = api.tx.balances.transfer(charlie.address, 1e15);356 await submitTransactionAsync(alice, transfer);357 });358359 await confirmSponsorshipExpectFailure(collectionId, '//Charlie');360 });361362 it('(!negative test!) Confirm sponsorship using owner address', async () => {363 const collectionId = await createCollectionExpectSuccess();364 await setCollectionSponsorExpectSuccess(collectionId, bob.address);365 await confirmSponsorshipExpectFailure(collectionId, '//Alice');366 });367368 it('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async () => {369 const collectionId = await createCollectionExpectSuccess();370 await confirmSponsorshipExpectFailure(collectionId, '//Bob');371 });372 373 it('(!negative test!) Confirm sponsorship in a collection that was destroyed', async () => {374 const collectionId = await createCollectionExpectSuccess();375 await destroyCollectionExpectSuccess(collectionId);376 await confirmSponsorshipExpectFailure(collectionId, '//Bob');377 });378});