difftreelog
Merge pull request #61 from usetech-llc/feature/NFTPAR-236_burn_item
in: master
Feature/nftpar 236 burn item
9 files changed
tests/src/burnItem.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/burnItem.test.ts
@@ -0,0 +1,237 @@
+import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from './substrate/substrate-api';
+import { Keyring } from "@polkadot/api";
+import { IKeyringPair } from "@polkadot/types/types";
+import {
+ createCollectionExpectSuccess,
+ createItemExpectSuccess,
+ getGenericResult,
+ destroyCollectionExpectSuccess
+} from './util/helpers';
+import { nullPublicKey } from "./accounts";
+
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+chai.use(chaiAsPromised);
+const expect = chai.expect;
+
+let alice: IKeyringPair;
+let bob: IKeyringPair;
+
+describe('integration test: ext. burnItem():', () => {
+ before(async () => {
+ await usingApi(async (api) => {
+ const keyring = new Keyring({ type: 'sr25519' });
+ alice = keyring.addFromUri(`//Alice`);
+ bob = keyring.addFromUri(`//Bob`);
+ });
+ });
+
+ it('Burn item in NFT collection', async () => {
+ const createMode = 'NFT';
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}});
+ const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
+
+ await usingApi(async (api) => {
+ const tx = api.tx.nft.burnItem(collectionId, tokenId, 0);
+ const events = await submitTransactionAsync(alice, tx);
+ const result = getGenericResult(events);
+
+ // Get the item
+ const item: any = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON();
+
+ // What to expect
+ expect(result.success).to.be.true;
+ expect(item).to.be.not.null;
+ expect(item.Owner).to.be.equal(nullPublicKey);
+ });
+
+ });
+ it('Burn item in Fungible collection', async () => {
+ const createMode = 'Fungible';
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0 }});
+ await createItemExpectSuccess(alice, collectionId, createMode); // Helper creates 10 fungible tokens
+ const tokenId = 0; // ignored
+
+ await usingApi(async (api) => {
+ // Destroy 1 of 10
+ const tx = api.tx.nft.burnItem(collectionId, tokenId, 1);
+ const events = await submitTransactionAsync(alice, tx);
+ const result = getGenericResult(events);
+
+ // Get alice balance
+ const balance: any = (await api.query.nft.fungibleItemList(collectionId, alice.address)).toJSON();
+
+ // What to expect
+ expect(result.success).to.be.true;
+ expect(balance).to.be.not.null;
+ expect(balance.Value).to.be.equal(9);
+ });
+
+ });
+ it('Burn item in ReFungible collection', async () => {
+ const createMode = 'ReFungible';
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 2 }});
+ const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
+
+ await usingApi(async (api) => {
+ const tx = api.tx.nft.burnItem(collectionId, tokenId, 1);
+ const events = await submitTransactionAsync(alice, tx);
+ const result = getGenericResult(events);
+
+ // Get alice balance
+ const balance: any = (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON();
+
+ // What to expect
+ expect(result.success).to.be.true;
+ expect(balance).to.be.not.null;
+ expect(balance.Owner.length).to.be.equal(0);
+ });
+
+ });
+
+ it('Burn owned portion of item in ReFungible collection', async () => {
+ const createMode = 'ReFungible';
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 2 }});
+ const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
+
+ await usingApi(async (api) => {
+ // Transfer 1/100 of the token to Bob
+ const transfertx = api.tx.nft.transfer(bob.address, collectionId, tokenId, 1);
+ const events1 = await submitTransactionAsync(alice, transfertx);
+ const result1 = getGenericResult(events1);
+
+ // Get balances
+ const balanceBefore: any = (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON();
+
+ // Bob burns his portion
+ const tx = api.tx.nft.burnItem(collectionId, tokenId, 0);
+ const events2 = await submitTransactionAsync(bob, tx);
+ const result2 = getGenericResult(events2);
+
+ // Get balances
+ const balance: any = (await api.query.nft.reFungibleItemList(collectionId, tokenId)).toJSON();
+ // console.log(balance);
+
+ // What to expect before burning
+ expect(result1.success).to.be.true;
+ expect(balanceBefore).to.be.not.null;
+ expect(balanceBefore.Owner.length).to.be.equal(2);
+ expect(balanceBefore.Owner[0].Owner).to.be.equal(alice.address);
+ expect(balanceBefore.Owner[0].Fraction).to.be.equal(99);
+ expect(balanceBefore.Owner[1].Owner).to.be.equal(bob.address);
+ expect(balanceBefore.Owner[1].Fraction).to.be.equal(1);
+
+ // What to expect after burning
+ expect(result2.success).to.be.true;
+ expect(balance).to.be.not.null;
+ expect(balance.Owner.length).to.be.equal(1);
+ expect(balance.Owner[0].Fraction).to.be.equal(99);
+ expect(balance.Owner[0].Owner).to.be.equal(alice.address);
+ });
+
+ });
+
+});
+
+describe('Negative integration test: ext. burnItem():', () => {
+ before(async () => {
+ await usingApi(async (api) => {
+ const keyring = new Keyring({ type: 'sr25519' });
+ alice = keyring.addFromUri(`//Alice`);
+ bob = keyring.addFromUri(`//Bob`);
+ });
+ });
+
+ it('Burn a token in a destroyed collection', async () => {
+ const createMode = 'NFT';
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode }});
+ const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
+ await destroyCollectionExpectSuccess(collectionId);
+
+ await usingApi(async (api) => {
+ const tx = api.tx.nft.burnItem(collectionId, tokenId, 0);
+ const badTransaction = async function () {
+ await submitTransactionExpectFailAsync(alice, tx);
+ };
+ await expect(badTransaction()).to.be.rejected;
+ });
+
+ });
+
+ it('Burn a token that was never created', async () => {
+ const createMode = 'NFT';
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode }});
+ const tokenId = 10;
+
+ await usingApi(async (api) => {
+ const tx = api.tx.nft.burnItem(collectionId, tokenId, 0);
+ const badTransaction = async function () {
+ await submitTransactionExpectFailAsync(alice, tx);
+ };
+ await expect(badTransaction()).to.be.rejected;
+ });
+
+ });
+
+ it('Burn a token using the address that does not own it', async () => {
+ const createMode = 'NFT';
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode }});
+ const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
+
+ await usingApi(async (api) => {
+ const tx = api.tx.nft.burnItem(collectionId, tokenId, 0);
+ const badTransaction = async function () {
+ await submitTransactionExpectFailAsync(bob, tx);
+ };
+ await expect(badTransaction()).to.be.rejected;
+ });
+
+ });
+
+ it('Transfer a burned a token', async () => {
+ const createMode = 'NFT';
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode }});
+ const tokenId = await createItemExpectSuccess(alice, collectionId, createMode);
+
+ await usingApi(async (api) => {
+
+ const burntx = api.tx.nft.burnItem(collectionId, tokenId, 0);
+ const events1 = await submitTransactionAsync(alice, burntx);
+ const result1 = getGenericResult(events1);
+ expect(result1.success).to.be.true;
+
+ const tx = api.tx.nft.transfer(bob.address, collectionId, tokenId, 0);
+ const badTransaction = async function () {
+ await submitTransactionExpectFailAsync(alice, tx);
+ };
+ await expect(badTransaction()).to.be.rejected;
+ });
+
+ });
+
+ it('Burn more than owned in Fungible collection', async () => {
+ const createMode = 'Fungible';
+ const collectionId = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0 }});
+ // Helper creates 10 fungible tokens
+ await createItemExpectSuccess(alice, collectionId, createMode);
+ const tokenId = 0; // ignored
+
+ await usingApi(async (api) => {
+ // Destroy 11 of 10
+ const tx = api.tx.nft.burnItem(collectionId, tokenId, 11);
+ const badTransaction = async function () {
+ await submitTransactionExpectFailAsync(alice, tx);
+ };
+ await expect(badTransaction()).to.be.rejected;
+
+ // Get alice balance
+ const balance: any = (await api.query.nft.fungibleItemList(collectionId, alice.address)).toJSON();
+
+ // What to expect
+ expect(balance).to.be.not.null;
+ expect(balance.Value).to.be.equal(10);
+ });
+
+ });
+
+});
tests/src/confirmSponsorship.test.tsdiffbeforeafterboth1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56import 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} from "./util/helpers";23import { Keyring } from "@polkadot/api";24import { IKeyringPair } from "@polkadot/types/types";25import type { AccountId } from '@polkadot/types/interfaces';26import { BigNumber } from 'bignumber.js';2728chai.use(chaiAsPromised);29const expect = chai.expect;3031let alice: IKeyringPair;32let bob: IKeyringPair;33let charlie: IKeyringPair;3435describe('integration test: ext. confirmSponsorship():', () => {3637 before(async () => {38 await usingApi(async (api) => {39 const keyring = new Keyring({ type: 'sr25519' });40 alice = keyring.addFromUri(`//Alice`);41 bob = keyring.addFromUri(`//Bob`);42 charlie = keyring.addFromUri(`//Charlie`);43 });44 });4546 it('Confirm collection sponsorship', async () => {47 const collectionId = await createCollectionExpectSuccess();48 await setCollectionSponsorExpectSuccess(collectionId, bob.address);49 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');50 });51 it('Add sponsor to a collection after the same sponsor was already added and confirmed', async () => {52 const collectionId = await createCollectionExpectSuccess();53 await setCollectionSponsorExpectSuccess(collectionId, bob.address);54 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');55 await setCollectionSponsorExpectSuccess(collectionId, bob.address);56 });57 it('Add new sponsor to a collection after another sponsor was already added and confirmed', async () => {58 const collectionId = await createCollectionExpectSuccess();59 await setCollectionSponsorExpectSuccess(collectionId, bob.address);60 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');61 await setCollectionSponsorExpectSuccess(collectionId, charlie.address);62 });6364 it('NFT: Transfer fees are paid by the sponsor after confirmation', async () => {65 const collectionId = await createCollectionExpectSuccess();66 await setCollectionSponsorExpectSuccess(collectionId, bob.address);67 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');6869 await usingApi(async (api) => {70 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());7172 // Find unused address73 const zeroBalance = await findUnusedAddress(api);7475 // Mint token for unused address76 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address);7778 // Transfer this tokens from unused address to Alice79 const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 0);80 const events = await submitTransactionAsync(zeroBalance, zeroToAlice);81 const result = getGenericResult(events);8283 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());8485 expect(result.success).to.be.true;86 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;87 });8889 });9091 it('Fungible: Transfer fees are paid by the sponsor after confirmation', async () => {92 const collectionId = await createCollectionExpectSuccess({mode: 'Fungible'});93 await setCollectionSponsorExpectSuccess(collectionId, bob.address);94 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');9596 await usingApi(async (api) => {97 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());9899 // Find unused address100 const zeroBalance = await findUnusedAddress(api);101102 // Mint token for unused address103 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);104105 // Transfer this tokens from unused address to Alice106 const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);107 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);108 const result1 = getGenericResult(events1);109110 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());111112 expect(result1.success).to.be.true;113 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;114 });115 });116117 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {118 const collectionId = await createCollectionExpectSuccess({mode: 'ReFungible'});119 await setCollectionSponsorExpectSuccess(collectionId, bob.address);120 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');121122 await usingApi(async (api) => {123 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());124125 // Find unused address126 const zeroBalance = await findUnusedAddress(api);127128 // Mint token for unused address129 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);130131 // Transfer this tokens from unused address to Alice132 const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);133 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);134 const result1 = getGenericResult(events1);135136 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());137138 expect(result1.success).to.be.true;139 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;140 });141 });142143 it('CreateItem fees are paid by the sponsor after confirmation', async () => {144 const collectionId = await createCollectionExpectSuccess();145 await setCollectionSponsorExpectSuccess(collectionId, bob.address);146 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');147148 // Enable collection white list 149 await enableWhiteListExpectSuccess(alice, collectionId);150151 // Enable public minting152 await enablePublicMintingExpectSuccess(alice, collectionId);153154 // Create Item 155 await usingApi(async (api) => {156 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());157158 // Find unused address159 const zeroBalance = await findUnusedAddress(api);160161 // Add zeroBalance address to white list162 await addToWhiteListExpectSuccess(alice, collectionId, zeroBalance.address);163164 // Mint token using unused address as signer165 const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);166167 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());168169 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;170 });171 });172173 it('NFT: Sponsoring is rate limited', async () => {174 const collectionId = await createCollectionExpectSuccess();175 await setCollectionSponsorExpectSuccess(collectionId, bob.address);176 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');177178 await usingApi(async (api) => {179 // Find unused address180 const zeroBalance = await findUnusedAddress(api);181182 // Mint token for alice183 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);184185 // Transfer this token from Alice to unused address and back186 // Alice to Zero gets sponsored187 const aliceToZero = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 0);188 const events1 = await submitTransactionAsync(alice, aliceToZero);189 const result1 = getGenericResult(events1);190191 // Second transfer should fail192 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());193 const zeroToAlice = api.tx.nft.transfer(alice.address, collectionId, itemId, 0);194 const badTransaction = async function () { 195 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);196 };197 await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");198 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());199200 // Try again after Zero gets some balance - now it should succeed201 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);202 await submitTransactionAsync(alice, balancetx);203 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);204 const result2 = getGenericResult(events2);205206 expect(result1.success).to.be.true;207 expect(result2.success).to.be.true;208 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;209 });210 });211212 it('Fungible: Sponsoring is rate limited', async () => {213 const collectionId = await createCollectionExpectSuccess({mode: 'Fungible'});214 await setCollectionSponsorExpectSuccess(collectionId, bob.address);215 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');216217 await usingApi(async (api) => {218 // Find unused address219 const zeroBalance = await findUnusedAddress(api);220221 // Mint token for unused address222 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);223224 // Transfer this tokens in parts from unused address to Alice225 const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);226 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);227 const result1 = getGenericResult(events1);228229 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());230231 const badTransaction = async function () { 232 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);233 };234235 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());236237 // Try again after Zero gets some balance - now it should succeed238 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);239 await submitTransactionAsync(alice, balancetx);240 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);241 const result2 = getGenericResult(events2);242243 expect(result1.success).to.be.true;244 expect(result2.success).to.be.true;245 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;246 });247 });248249 it('ReFungible: Sponsoring is rate limited', async () => {250 const collectionId = await createCollectionExpectSuccess({mode: 'ReFungible'});251 await setCollectionSponsorExpectSuccess(collectionId, bob.address);252 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');253254 await usingApi(async (api) => {255 // Find unused address256 const zeroBalance = await findUnusedAddress(api);257258 // Mint token for alice259 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);260261 // Transfer this token from Alice to unused address and back262 // Alice to Zero gets sponsored263 const aliceToZero = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);264 const events1 = await submitTransactionAsync(alice, aliceToZero);265 const result1 = getGenericResult(events1);266267 // Second transfer should fail268 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());269 const zeroToAlice = api.tx.nft.transfer(alice.address, collectionId, itemId, 1);270 const badTransaction = async function () { 271 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);272 };273 await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");274 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());275276 // Try again after Zero gets some balance - now it should succeed277 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);278 await submitTransactionAsync(alice, balancetx);279 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);280 const result2 = getGenericResult(events2);281282 expect(result1.success).to.be.true;283 expect(result2.success).to.be.true;284 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;285 });286 });287288});289290describe('(!negative test!) integration test: ext. removeCollectionSponsor():', () => {291 before(async () => {292 await usingApi(async (api) => {293 const keyring = new Keyring({ type: 'sr25519' });294 alice = keyring.addFromUri(`//Alice`);295 bob = keyring.addFromUri(`//Bob`);296 charlie = keyring.addFromUri(`//Charlie`);297 });298 });299300 it('(!negative test!) Confirm sponsorship for a collection that never existed', async () => {301 // Find the collection that never existed302 const collectionId = 0;303 await usingApi(async (api) => {304 const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;305 });306307 await confirmSponsorshipExpectFailure(collectionId, '//Bob');308 });309310 it('(!negative test!) Confirm sponsorship using a non-sponsor address', async () => {311 const collectionId = await createCollectionExpectSuccess();312 await setCollectionSponsorExpectSuccess(collectionId, bob.address);313314 await usingApi(async (api) => {315 const transfer = api.tx.balances.transfer(charlie.address, 1e15);316 await submitTransactionAsync(alice, transfer);317 });318319 await confirmSponsorshipExpectFailure(collectionId, '//Charlie');320 });321322 it('(!negative test!) Confirm sponsorship using owner address', async () => {323 const collectionId = await createCollectionExpectSuccess();324 await setCollectionSponsorExpectSuccess(collectionId, bob.address);325 await confirmSponsorshipExpectFailure(collectionId, '//Alice');326 });327328 it('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async () => {329 const collectionId = await createCollectionExpectSuccess();330 await confirmSponsorshipExpectFailure(collectionId, '//Bob');331 });332 333 it('(!negative test!) Confirm sponsorship in a collection that was destroyed', async () => {334 const collectionId = await createCollectionExpectSuccess();335 await destroyCollectionExpectSuccess(collectionId);336 await confirmSponsorshipExpectFailure(collectionId, '//Bob');337 });338});1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56import 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} from "./util/helpers";23import { Keyring } from "@polkadot/api";24import { IKeyringPair } from "@polkadot/types/types";25import type { AccountId } from '@polkadot/types/interfaces';26import { BigNumber } from 'bignumber.js';2728chai.use(chaiAsPromised);29const expect = chai.expect;3031let alice: IKeyringPair;32let bob: IKeyringPair;33let charlie: IKeyringPair;3435describe('integration test: ext. confirmSponsorship():', () => {3637 before(async () => {38 await usingApi(async (api) => {39 const keyring = new Keyring({ type: 'sr25519' });40 alice = keyring.addFromUri(`//Alice`);41 bob = keyring.addFromUri(`//Bob`);42 charlie = keyring.addFromUri(`//Charlie`);43 });44 });4546 it('Confirm collection sponsorship', async () => {47 const collectionId = await createCollectionExpectSuccess();48 await setCollectionSponsorExpectSuccess(collectionId, bob.address);49 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');50 });51 it('Add sponsor to a collection after the same sponsor was already added and confirmed', async () => {52 const collectionId = await createCollectionExpectSuccess();53 await setCollectionSponsorExpectSuccess(collectionId, bob.address);54 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');55 await setCollectionSponsorExpectSuccess(collectionId, bob.address);56 });57 it('Add new sponsor to a collection after another sponsor was already added and confirmed', async () => {58 const collectionId = await createCollectionExpectSuccess();59 await setCollectionSponsorExpectSuccess(collectionId, bob.address);60 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');61 await setCollectionSponsorExpectSuccess(collectionId, charlie.address);62 });6364 it('NFT: Transfer fees are paid by the sponsor after confirmation', async () => {65 const collectionId = await createCollectionExpectSuccess();66 await setCollectionSponsorExpectSuccess(collectionId, bob.address);67 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');6869 await usingApi(async (api) => {70 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());7172 // Find unused address73 const zeroBalance = await findUnusedAddress(api);7475 // Mint token for unused address76 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', zeroBalance.address);7778 // Transfer this tokens from unused address to Alice79 const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 0);80 const events = await submitTransactionAsync(zeroBalance, zeroToAlice);81 const result = getGenericResult(events);8283 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());8485 expect(result.success).to.be.true;86 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;87 });8889 });9091 it('Fungible: Transfer fees are paid by the sponsor after confirmation', async () => {92 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0 }});93 await setCollectionSponsorExpectSuccess(collectionId, bob.address);94 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');9596 await usingApi(async (api) => {97 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());9899 // Find unused address100 const zeroBalance = await findUnusedAddress(api);101102 // Mint token for unused address103 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);104105 // Transfer this tokens from unused address to Alice106 const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);107 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);108 const result1 = getGenericResult(events1);109110 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());111112 expect(result1.success).to.be.true;113 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;114 });115 });116117 it('ReFungible: Transfer fees are paid by the sponsor after confirmation', async () => {118 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0 }});119 await setCollectionSponsorExpectSuccess(collectionId, bob.address);120 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');121122 await usingApi(async (api) => {123 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());124125 // Find unused address126 const zeroBalance = await findUnusedAddress(api);127128 // Mint token for unused address129 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', zeroBalance.address);130131 // Transfer this tokens from unused address to Alice132 const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);133 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);134 const result1 = getGenericResult(events1);135136 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());137138 expect(result1.success).to.be.true;139 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;140 });141 });142143 it('CreateItem fees are paid by the sponsor after confirmation', async () => {144 const collectionId = await createCollectionExpectSuccess();145 await setCollectionSponsorExpectSuccess(collectionId, bob.address);146 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');147148 // Enable collection white list 149 await enableWhiteListExpectSuccess(alice, collectionId);150151 // Enable public minting152 await enablePublicMintingExpectSuccess(alice, collectionId);153154 // Create Item 155 await usingApi(async (api) => {156 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());157158 // Find unused address159 const zeroBalance = await findUnusedAddress(api);160161 // Add zeroBalance address to white list162 await addToWhiteListExpectSuccess(alice, collectionId, zeroBalance.address);163164 // Mint token using unused address as signer165 const tokenId = await createItemExpectSuccess(zeroBalance, collectionId, 'NFT', zeroBalance.address);166167 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());168169 expect(BsponsorBalance.lt(AsponsorBalance)).to.be.true;170 });171 });172173 it('NFT: Sponsoring is rate limited', async () => {174 const collectionId = await createCollectionExpectSuccess();175 await setCollectionSponsorExpectSuccess(collectionId, bob.address);176 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');177178 await usingApi(async (api) => {179 // Find unused address180 const zeroBalance = await findUnusedAddress(api);181182 // Mint token for alice183 const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);184185 // Transfer this token from Alice to unused address and back186 // Alice to Zero gets sponsored187 const aliceToZero = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 0);188 const events1 = await submitTransactionAsync(alice, aliceToZero);189 const result1 = getGenericResult(events1);190191 // Second transfer should fail192 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());193 const zeroToAlice = api.tx.nft.transfer(alice.address, collectionId, itemId, 0);194 const badTransaction = async function () { 195 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);196 };197 await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");198 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());199200 // Try again after Zero gets some balance - now it should succeed201 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);202 await submitTransactionAsync(alice, balancetx);203 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);204 const result2 = getGenericResult(events2);205206 expect(result1.success).to.be.true;207 expect(result2.success).to.be.true;208 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;209 });210 });211212 it('Fungible: Sponsoring is rate limited', async () => {213 const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0 }});214 await setCollectionSponsorExpectSuccess(collectionId, bob.address);215 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');216217 await usingApi(async (api) => {218 // Find unused address219 const zeroBalance = await findUnusedAddress(api);220221 // Mint token for unused address222 const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', zeroBalance.address);223224 // Transfer this tokens in parts from unused address to Alice225 const zeroToAlice = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);226 const events1 = await submitTransactionAsync(zeroBalance, zeroToAlice);227 const result1 = getGenericResult(events1);228229 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());230231 const badTransaction = async function () { 232 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);233 };234235 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());236237 // Try again after Zero gets some balance - now it should succeed238 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);239 await submitTransactionAsync(alice, balancetx);240 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);241 const result2 = getGenericResult(events2);242243 expect(result1.success).to.be.true;244 expect(result2.success).to.be.true;245 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;246 });247 });248249 it('ReFungible: Sponsoring is rate limited', async () => {250 const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0 }});251 await setCollectionSponsorExpectSuccess(collectionId, bob.address);252 await confirmSponsorshipExpectSuccess(collectionId, '//Bob');253254 await usingApi(async (api) => {255 // Find unused address256 const zeroBalance = await findUnusedAddress(api);257258 // Mint token for alice259 const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);260261 // Transfer this token from Alice to unused address and back262 // Alice to Zero gets sponsored263 const aliceToZero = api.tx.nft.transfer(zeroBalance.address, collectionId, itemId, 1);264 const events1 = await submitTransactionAsync(alice, aliceToZero);265 const result1 = getGenericResult(events1);266267 // Second transfer should fail268 const AsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());269 const zeroToAlice = api.tx.nft.transfer(alice.address, collectionId, itemId, 1);270 const badTransaction = async function () { 271 await submitTransactionExpectFailAsync(zeroBalance, zeroToAlice);272 };273 await expect(badTransaction()).to.be.rejectedWith("Inability to pay some fees");274 const BsponsorBalance = new BigNumber((await api.query.system.account(bob.address)).data.free.toString());275276 // Try again after Zero gets some balance - now it should succeed277 const balancetx = api.tx.balances.transfer(zeroBalance.address, 1e15);278 await submitTransactionAsync(alice, balancetx);279 const events2 = await submitTransactionAsync(zeroBalance, zeroToAlice);280 const result2 = getGenericResult(events2);281282 expect(result1.success).to.be.true;283 expect(result2.success).to.be.true;284 expect(BsponsorBalance.isEqualTo(AsponsorBalance)).to.be.true;285 });286 });287288});289290describe('(!negative test!) integration test: ext. removeCollectionSponsor():', () => {291 before(async () => {292 await usingApi(async (api) => {293 const keyring = new Keyring({ type: 'sr25519' });294 alice = keyring.addFromUri(`//Alice`);295 bob = keyring.addFromUri(`//Bob`);296 charlie = keyring.addFromUri(`//Charlie`);297 });298 });299300 it('(!negative test!) Confirm sponsorship for a collection that never existed', async () => {301 // Find the collection that never existed302 const collectionId = 0;303 await usingApi(async (api) => {304 const collectionId = parseInt((await api.query.nft.createdCollectionCount()).toString()) + 1;305 });306307 await confirmSponsorshipExpectFailure(collectionId, '//Bob');308 });309310 it('(!negative test!) Confirm sponsorship using a non-sponsor address', async () => {311 const collectionId = await createCollectionExpectSuccess();312 await setCollectionSponsorExpectSuccess(collectionId, bob.address);313314 await usingApi(async (api) => {315 const transfer = api.tx.balances.transfer(charlie.address, 1e15);316 await submitTransactionAsync(alice, transfer);317 });318319 await confirmSponsorshipExpectFailure(collectionId, '//Charlie');320 });321322 it('(!negative test!) Confirm sponsorship using owner address', async () => {323 const collectionId = await createCollectionExpectSuccess();324 await setCollectionSponsorExpectSuccess(collectionId, bob.address);325 await confirmSponsorshipExpectFailure(collectionId, '//Alice');326 });327328 it('(!negative test!) Confirm sponsorship without sponsor being set with setCollectionSponsor', async () => {329 const collectionId = await createCollectionExpectSuccess();330 await confirmSponsorshipExpectFailure(collectionId, '//Bob');331 });332 333 it('(!negative test!) Confirm sponsorship in a collection that was destroyed', async () => {334 const collectionId = await createCollectionExpectSuccess();335 await destroyCollectionExpectSuccess(collectionId);336 await confirmSponsorshipExpectFailure(collectionId, '//Bob');337 });338});tests/src/createCollection.test.tsdiffbeforeafterboth--- a/tests/src/createCollection.test.ts
+++ b/tests/src/createCollection.test.ts
@@ -6,14 +6,14 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { default as usingApi } from "./substrate/substrate-api";
-import { createCollectionExpectSuccess, createCollectionExpectFailure, CollectionMode } from "./util/helpers";
+import { createCollectionExpectSuccess, createCollectionExpectFailure } from "./util/helpers";
chai.use(chaiAsPromised);
const expect = chai.expect;
describe('integration test: ext. createCollection():', () => {
it('Create new NFT collection', async () => {
- await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: 'NFT'});
+ await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});
});
it('Create new NFT collection whith collection_name of maximum length (64 bytes)', async () => {
await createCollectionExpectSuccess({name: 'A'.repeat(64)});
@@ -25,10 +25,10 @@
await createCollectionExpectSuccess({tokenPrefix: 'A'.repeat(16)});
});
it('Create new Fungible collection', async () => {
- await createCollectionExpectSuccess({mode: 'Fungible'});
+ await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
});
it('Create new ReFungible collection', async () => {
- await createCollectionExpectSuccess({mode: 'ReFungible'});
+ await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
});
});
@@ -38,7 +38,7 @@
const AcollectionCount = parseInt((await api.query.nft.collectionCount()).toString());
const badTransaction = async function () {
- await createCollectionExpectSuccess({mode: 'BadMode' as CollectionMode});
+ await createCollectionExpectSuccess({mode: {type: 'Invalid'}});
};
expect(badTransaction()).to.be.rejected;
tests/src/createItem.test.tsdiffbeforeafterboth--- a/tests/src/createItem.test.ts
+++ b/tests/src/createItem.test.ts
@@ -18,17 +18,17 @@
it('Create new item in NFT collection', async () => {
const createMode = 'NFT';
- const newCollectionID = await createCollectionExpectSuccess({mode: createMode});
+ const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode}});
await createItemExpectSuccess(alice, newCollectionID, createMode);
});
it('Create new item in Fungible collection', async () => {
const createMode = 'Fungible';
- const newCollectionID = await createCollectionExpectSuccess({mode: createMode});
+ const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
await createItemExpectSuccess(alice, newCollectionID, createMode);
});
it('Create new item in ReFungible collection', async () => {
const createMode = 'ReFungible';
- const newCollectionID = await createCollectionExpectSuccess({mode: createMode});
+ const newCollectionID = await createCollectionExpectSuccess({mode: {type: createMode, decimalPoints: 0}});
await createItemExpectSuccess(alice, newCollectionID, createMode);
});
});
tests/src/destroyCollection.test.tsdiffbeforeafterboth--- a/tests/src/destroyCollection.test.ts
+++ b/tests/src/destroyCollection.test.ts
@@ -14,11 +14,11 @@
await destroyCollectionExpectSuccess(collectionId);
});
it('Fungible collection can be destroyed', async () => {
- const collectionId = await createCollectionExpectSuccess({ mode: 'Fungible' });
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});
await destroyCollectionExpectSuccess(collectionId);
});
it('ReFungible collection can be destroyed', async () => {
- const collectionId = await createCollectionExpectSuccess({ mode: 'ReFungible' });
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible', decimalPoints: 0}});
await destroyCollectionExpectSuccess(collectionId);
});
});
tests/src/setCollectionLimits.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionLimits.test.ts
+++ b/tests/src/setCollectionLimits.test.ts
@@ -32,7 +32,7 @@
});
it('choose or create collection for testing', async () => {
await usingApi(async () => {
- collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: 'NFT'});
+ collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});
});
});
});
tests/src/setCollectionSponsor.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionSponsor.test.ts
+++ b/tests/src/setCollectionSponsor.test.ts
@@ -30,11 +30,11 @@
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
});
it('Set Fungible collection sponsor', async () => {
- const collectionId = await createCollectionExpectSuccess({ mode: 'Fungible' });
+ const collectionId = await createCollectionExpectSuccess({ mode: {type: 'Fungible', decimalPoints: 0} });
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
});
it('Set ReFungible collection sponsor', async () => {
- const collectionId = await createCollectionExpectSuccess({ mode: 'ReFungible' });
+ const collectionId = await createCollectionExpectSuccess({ mode: {type: 'ReFungible', decimalPoints: 0} });
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
});
tests/src/setSchemaVersion.test.tsdiffbeforeafterboth--- a/tests/src/setSchemaVersion.test.ts
+++ b/tests/src/setSchemaVersion.test.ts
@@ -35,7 +35,7 @@
});
it('choose or create collection for testing', async () => {
await usingApi(async () => {
- collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: 'NFT'});
+ collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});
});
});
});
tests/src/util/helpers.tsdiffbeforeafterboth--- a/tests/src/util/helpers.ts
+++ b/tests/src/util/helpers.ts
@@ -88,7 +88,26 @@
return result;
}
-export type CollectionMode = 'NFT' | 'Fungible' | 'ReFungible';
+interface Invalid {
+ type: 'Invalid'
+}
+
+interface Nft {
+ type: 'NFT'
+}
+
+interface Fungible {
+ type: 'Fungible',
+ decimalPoints: number
+}
+
+interface ReFungible {
+ type: 'ReFungible',
+ decimalPoints: number
+}
+
+type CollectionMode = Nft | Fungible | ReFungible | Invalid;
+
export type CreateCollectionParams = {
mode: CollectionMode,
name: string,
@@ -99,7 +118,7 @@
const defaultCreateCollectionParams: CreateCollectionParams = {
name: 'name',
description: 'description',
- mode: 'NFT',
+ mode: { type: "NFT" },
tokenPrefix: 'prefix'
}
@@ -113,7 +132,22 @@
// Run the CreateCollection transaction
const alicePrivateKey = privateKey('//Alice');
- const tx = api.tx.nft.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), mode);
+
+ let modeprm = {};
+ if (mode.type == 'NFT') {
+ modeprm = {nft: null};
+ }
+ else if (mode.type == 'Fungible') {
+ modeprm = {fungible: mode.decimalPoints};
+ }
+ else if (mode.type == 'ReFungible') {
+ modeprm = {refungible: mode.decimalPoints};
+ }
+ else if (mode.type == 'Invalid') {
+ modeprm = {invalid: null};
+ }
+
+ const tx = api.tx.nft.createCollection(strToUTF16(name), strToUTF16(description), strToUTF16(tokenPrefix), modeprm);
const events = await submitTransactionAsync(alicePrivateKey, tx);
const result = getCreateCollectionResult(events);