From 2986834a0c9e2cf5a62d80e4067b37c8518df6e6 Mon Sep 17 00:00:00 2001 From: Grigoriy Simonov Date: Thu, 23 Jun 2022 13:20:34 +0000 Subject: [PATCH] test refactoring. burn pieces for multiple users test. --- --- a/tests/src/refungible.test.ts +++ b/tests/src/refungible.test.ts @@ -18,17 +18,17 @@ import {IKeyringPair} from '@polkadot/types/types'; import { createCollectionExpectSuccess, - createItemExpectSuccess, - transferExpectSuccess, - transferExpectFailure, getBalance, - burnItemExpectSuccess, createMultipleItemsExpectSuccess, - approveExpectSuccess, - transferFromExpectSuccess, isTokenExists, getLastTokenId, getAllowance, + approve, + transferFrom, + createCollection, + createRefungibleToken, + transfer, + burnItem, } from './util/helpers'; import chai from 'chai'; @@ -47,24 +47,42 @@ }); }); - it('Create refungible collection and token. Token pieces transfer.', async () => { - const createMode = 'ReFungible'; - const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}}); - const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); + it('Create refungible collection and token', async () => { + await usingApi(async api => { + const createCollectionResult = await createCollection(api, alice, {mode: {type: 'ReFungible'}}); + expect(createCollectionResult.success).to.be.true; + const collectionId = createCollectionResult.collectionId; + + const itemCountBefore = await getLastTokenId(api, collectionId); + const result = await createRefungibleToken(api, alice, collectionId, 100n); + + const itemCountAfter = await getLastTokenId(api, collectionId); + + // What to expect + // tslint:disable-next-line:no-unused-expression + expect(result.success).to.be.true; + expect(itemCountAfter).to.be.equal(itemCountBefore + 1); + expect(collectionId).to.be.equal(result.collectionId); + expect(itemCountAfter.toString()).to.be.equal(result.itemId.toString()); + }); + }); - let aliceBalance = BigInt(0); + it('Transfer token pieces', async () => { await usingApi(async api => { - aliceBalance = await getBalance(api, collectionId, alice.address, tokenId); + const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; + const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId; + + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n); + expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true; + + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n); + expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n); + await expect(transfer(api, collectionId, tokenId, alice, bob, 41n)).to.eventually.be.rejected; }); - const transferAmount = BigInt(60); - await transferExpectSuccess(collectionId, tokenId, alice, bob, transferAmount, 'ReFungible'); - aliceBalance = aliceBalance - transferAmount; - await transferExpectFailure(collectionId, tokenId, alice, bob, aliceBalance + BigInt(1)); }); it('Create multiple tokens', async () => { - const createMode = 'ReFungible'; - const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}}); + const collectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const args = [ {ReFungible: {pieces: 1}}, {ReFungible: {pieces: 2}}, @@ -72,65 +90,76 @@ ]; await createMultipleItemsExpectSuccess(alice, collectionId, args); - let tokenId = 0; await usingApi(async api => { - tokenId = await getLastTokenId(api, collectionId); + const tokenId = await getLastTokenId(api, collectionId); expect(tokenId).to.be.equal(3); + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n); }); - - const transferAmount = BigInt(60); - await transferExpectSuccess(collectionId, tokenId, alice, bob, transferAmount, 'ReFungible'); }); it('Burn some pieces', async () => { - const createMode = 'ReFungible'; - const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}}); - const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); - - let aliceBalance = BigInt(0); - await usingApi(async api => { - aliceBalance = await getBalance(api, collectionId, alice.address, tokenId); + await usingApi(async api => { + const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; + const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId; + expect(await isTokenExists(api, collectionId, tokenId)).to.be.true; + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n); + expect(await burnItem(api, alice, collectionId, tokenId, 99n)).to.be.true; expect(await isTokenExists(api, collectionId, tokenId)).to.be.true; + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(1n); }); - await burnItemExpectSuccess(alice, collectionId, tokenId, aliceBalance - BigInt(1)); - await usingApi(async api => { + }); + + it('Burn all pieces', async () => { + await usingApi(async api => { + const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; + const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId; expect(await isTokenExists(api, collectionId, tokenId)).to.be.true; + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n); + expect(await burnItem(api, alice, collectionId, tokenId, 100n)).to.be.true; + expect(await isTokenExists(api, collectionId, tokenId)).to.be.false; }); }); - it('Burn all pieces', async () => { - const createMode = 'ReFungible'; - const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}}); - const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); + it('Burn some pieces for multiple users', async () => { + await usingApi(async api => { + const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; + const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId; + expect(await isTokenExists(api, collectionId, tokenId)).to.be.true; + + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n); + expect(await transfer(api, collectionId, tokenId, alice, bob, 60n)).to.be.true; + + + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(40n); + expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(60n); + expect(await burnItem(api, alice, collectionId, tokenId, 40n)).to.be.true; + + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(0n); + expect(await isTokenExists(api, collectionId, tokenId)).to.be.true; + expect(await burnItem(api, bob, collectionId, tokenId, 59n)).to.be.true; - let aliceBalance = BigInt(0); - await usingApi(async api => { - aliceBalance = await getBalance(api, collectionId, alice.address, tokenId); + expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(1n); expect(await isTokenExists(api, collectionId, tokenId)).to.be.true; - }); - await burnItemExpectSuccess(alice, collectionId, tokenId, aliceBalance); - await usingApi(async api => { + expect(await burnItem(api, bob, collectionId, tokenId, 1n)).to.be.true; + expect(await isTokenExists(api, collectionId, tokenId)).to.be.false; }); }); it('Set allowance for token', async () => { - const createMode = 'ReFungible'; - const collectionId = await createCollectionExpectSuccess({mode: {type: createMode}}); - const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); - - let aliceBalance = BigInt(0); await usingApi(async api => { - aliceBalance = await getBalance(api, collectionId, alice.address, tokenId); - }); - const allowedAmount = BigInt(60); - await approveExpectSuccess(collectionId, tokenId, alice, bob.address, allowedAmount); - const transferAmount = BigInt(20); - await transferFromExpectSuccess(collectionId, tokenId, bob, alice, bob, transferAmount, 'ReFungible'); + const collectionId = (await createCollection(api, alice, {mode: {type: 'ReFungible'}})).collectionId; + const tokenId = (await createRefungibleToken(api, alice, collectionId, 100n)).itemId; + + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(100n); - await usingApi(async api => { - expect(await getAllowance(api, collectionId, alice.address, bob.address, tokenId)).to.equal(allowedAmount - transferAmount); + expect(await approve(api, collectionId, tokenId, alice, bob, 60n)).to.be.true; + expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(60n); + + expect(await transferFrom(api, collectionId, tokenId, bob, alice, bob, 20n)).to.be.true; + expect(await getBalance(api, collectionId, alice, tokenId)).to.be.equal(80n); + expect(await getBalance(api, collectionId, bob, tokenId)).to.be.equal(20n); + expect(await getAllowance(api, collectionId, alice, bob, tokenId)).to.be.equal(40n); }); - }); }); --- a/tests/src/util/helpers.ts +++ b/tests/src/util/helpers.ts @@ -318,6 +318,33 @@ tokenPrefix: 'prefix', }; +export async function +createCollection( + api: ApiPromise, + sender: IKeyringPair, + params: Partial = {}, +): Promise { + const {name, description, mode, tokenPrefix} = {...defaultCreateCollectionParams, ...params}; + + 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: null}; + } + + const tx = api.tx.unique.createCollectionEx({ + name: strToUTF16(name), + description: strToUTF16(description), + tokenPrefix: strToUTF16(tokenPrefix), + mode: modeprm as any, + }); + const events = await submitTransactionAsync(sender, tx); + return getCreateCollectionResult(events); +} + export async function createCollectionExpectSuccess(params: Partial = {}): Promise { const {name, description, mode, tokenPrefix} = {...defaultCreateCollectionParams, ...params}; @@ -329,23 +356,7 @@ // Run the CreateCollection transaction const alicePrivateKey = privateKeyWrapper('//Alice'); - 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: null}; - } - - const tx = api.tx.unique.createCollectionEx({ - name: strToUTF16(name), - description: strToUTF16(description), - tokenPrefix: strToUTF16(tokenPrefix), - mode: modeprm as any, - }); - const events = await submitTransactionAsync(alicePrivateKey, tx); - const result = getCreateCollectionResult(events); + const result = await createCollection(api, alicePrivateKey, params); // Get number of collections after the transaction const collectionCountAfter = await getCreatedCollectionCount(api); @@ -490,7 +501,7 @@ return unused; } -export async function getAllowance(api: ApiPromise, collectionId: number, owner: CrossAccountId | string, approved: CrossAccountId | string, tokenId: number) { +export async function getAllowance(api: ApiPromise, collectionId: number, owner: CrossAccountId | string | IKeyringPair, approved: CrossAccountId | string | IKeyringPair, tokenId: number) { return (await api.rpc.unique.allowance(collectionId, normalizeAccountId(owner), normalizeAccountId(approved), tokenId)).toBigInt(); } @@ -800,16 +811,19 @@ ReFungible: CreateReFungibleData; }; +export async function burnItem(api: ApiPromise, sender: IKeyringPair, collectionId: number, tokenId: number, value: number | bigint) : Promise { + const tx = api.tx.unique.burnItem(collectionId, tokenId, value); + const events = await submitTransactionAsync(sender, tx); + return getGenericResult(events).success; +} + export async function burnItemExpectSuccess(sender: IKeyringPair, collectionId: number, tokenId: number, value: number | bigint = 1) { await usingApi(async (api) => { const balanceBefore = await getBalance(api, collectionId, normalizeAccountId(sender), tokenId); // if burning token by admin - use adminButnItemExpectSuccess expect(balanceBefore >= BigInt(value)).to.be.true; - const tx = api.tx.unique.burnItem(collectionId, tokenId, value); - const events = await submitTransactionAsync(sender, tx); - const result = getGenericResult(events); - expect(result.success).to.be.true; + expect(await burnItem(api, sender, collectionId, tokenId, value)).to.be.true; const balanceAfter = await getBalance(api, collectionId, normalizeAccountId(sender), tokenId); expect(balanceAfter + BigInt(value)).to.be.equal(balanceBefore); @@ -817,15 +831,24 @@ } export async function +approve( + api: ApiPromise, + collectionId: number, + tokenId: number, owner: IKeyringPair, approved: CrossAccountId | string | IKeyringPair, amount: number | bigint = 1, +) { + const approveUniqueTx = api.tx.unique.approve(normalizeAccountId(approved), collectionId, tokenId, amount); + const events = await submitTransactionAsync(owner, approveUniqueTx); + return getGenericResult(events).success; +} + +export async function approveExpectSuccess( collectionId: number, tokenId: number, owner: IKeyringPair, approved: CrossAccountId | string, amount: number | bigint = 1, ) { await usingApi(async (api: ApiPromise) => { - const approveUniqueTx = api.tx.unique.approve(normalizeAccountId(approved), collectionId, tokenId, amount); - const events = await submitTransactionAsync(owner, approveUniqueTx); - const result = getGenericResult(events); - expect(result.success).to.be.true; + const result = approve(api, collectionId, tokenId, owner, approved); + expect(result).to.be.true; expect(await getAllowance(api, collectionId, owner.address, approved, tokenId)).to.be.equal(BigInt(amount)); }); @@ -846,6 +869,23 @@ } export async function +transferFrom( + api: ApiPromise, + collectionId: number, + tokenId: number, + accountApproved: IKeyringPair, + accountFrom: IKeyringPair | CrossAccountId, + accountTo: IKeyringPair | CrossAccountId, + value: number | bigint, +) { + const from = normalizeAccountId(accountFrom); + const to = normalizeAccountId(accountTo); + const transferFromTx = api.tx.unique.transferFrom(from, to, collectionId, tokenId, value); + const events = await submitTransactionAsync(accountApproved, transferFromTx); + return getGenericResult(events).success; +} + +export async function transferFromExpectSuccess( collectionId: number, tokenId: number, @@ -862,11 +902,7 @@ if (type === 'Fungible' || type === 'ReFungible') { balanceBefore = await getBalance(api, collectionId, to, tokenId); } - const transferFromTx = api.tx.unique.transferFrom(normalizeAccountId(accountFrom), to, collectionId, tokenId, value); - const events = await submitTransactionAsync(accountApproved, transferFromTx); - const result = getGenericResult(events); - // tslint:disable-next-line:no-unused-expression - expect(result.success).to.be.true; + expect(transferFrom(api, collectionId, tokenId, accountApproved, accountFrom, accountTo, value)).to.be.true; if (type === 'NFT') { expect(await getTokenOwner(api, collectionId, tokenId)).to.be.deep.equal(to); } @@ -1071,6 +1107,20 @@ } export async function +transfer( + api: ApiPromise, + collectionId: number, + tokenId: number, + sender: IKeyringPair, + recipient: IKeyringPair | CrossAccountId, + value: number | bigint, +) : Promise { + const transferTx = api.tx.unique.transfer(normalizeAccountId(recipient), collectionId, tokenId, value); + const events = await executeTransaction(api, sender, transferTx); + return getGenericResult(events).success; +} + +export async function transferExpectSuccess( collectionId: number, tokenId: number, @@ -1087,10 +1137,11 @@ if (type === 'Fungible' || type === 'ReFungible') { balanceBefore = await getBalance(api, collectionId, to, tokenId); } - const transferTx = api.tx.unique.transfer(to, collectionId, tokenId, value); + + const transferTx = api.tx.unique.transfer(normalizeAccountId(recipient), collectionId, tokenId, value); const events = await executeTransaction(api, sender, transferTx); + const result = getTransferResult(api, events); - const result = getTransferResult(api, events); expect(result.collectionId).to.be.equal(collectionId); expect(result.itemId).to.be.equal(tokenId); expect(result.sender).to.be.deep.equal(normalizeAccountId(sender.address)); @@ -1148,7 +1199,7 @@ export async function getBalance( api: ApiPromise, collectionId: number, - owner: string | CrossAccountId, + owner: string | CrossAccountId | IKeyringPair, token: number, ): Promise { return (await api.rpc.unique.balance(collectionId, normalizeAccountId(owner), token)).toBigInt(); @@ -1229,7 +1280,7 @@ const tx = api.tx.unique.createMultipleItems(collectionId, to, itemsData); const events = await submitTransactionAsync(sender, tx); - const result = getCreateItemsResult(events); + expect(getGenericResult(events).success).to.be.true; }); } @@ -1366,6 +1417,14 @@ return newItemId; } +export async function createRefungibleToken(api: ApiPromise, sender: IKeyringPair, collectionId: number, amount: bigint, owner: CrossAccountId | IKeyringPair | string = sender.address) : Promise { + const createData = {refungible: {pieces: amount}}; + const tx = api.tx.unique.createItem(collectionId, normalizeAccountId(owner), createData as any); + + const events = await submitTransactionAsync(sender, tx); + return getCreateItemResult(events); +} + export async function createItemExpectFailure(sender: IKeyringPair, collectionId: number, createMode: string, owner: CrossAccountId | string = sender.address) { await usingApi(async (api) => { const tx = api.tx.unique.createItem(collectionId, normalizeAccountId(owner), createMode); -- gitstuff