From 570880cf1d2e3e3e4a900300bddbafd9abb8e33c Mon Sep 17 00:00:00 2001 From: str-mv Date: Tue, 03 Aug 2021 07:37:01 +0000 Subject: [PATCH] CORE-180. burnItem --- --- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -987,12 +987,12 @@ /// * item_id: ID of NFT to burn. #[weight = >::burn_item()] #[transactional] - pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResult { + pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, item_owner: T::CrossAccountId, value: u128) -> DispatchResult { let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?); let target_collection = Self::get_collection(collection_id)?; - Self::burn_item_internal(&sender, &target_collection, item_id, value)?; + Self::burn_item_internal(&sender, &target_collection, item_id, &item_owner, value)?; target_collection.submit_logs() } @@ -1596,6 +1596,7 @@ sender: &T::CrossAccountId, collection: &CollectionHandle, item_id: TokenId, + item_owner: &T::CrossAccountId, value: u128, ) -> DispatchResult { ensure!( @@ -1611,8 +1612,11 @@ match collection.mode { CollectionMode::NFT => Self::burn_nft_item(collection, item_id)?, - CollectionMode::Fungible(_) => Self::burn_fungible_item(sender, collection, value)?, - CollectionMode::ReFungible => Self::burn_refungible_item(collection, item_id, sender)?, + CollectionMode::Fungible(_) => Self::burn_fungible_item(collection, item_owner, value)?, + CollectionMode::ReFungible => { + Self::burn_refungible_item(collection, item_id, item_owner)? + } + _ => (), }; Ok(()) @@ -1947,8 +1951,8 @@ } fn burn_fungible_item( - owner: &T::CrossAccountId, collection: &CollectionHandle, + owner: &T::CrossAccountId, value: u128, ) -> DispatchResult { let collection_id = collection.id; --- a/pallets/nft/src/tests.rs +++ b/pallets/nft/src/tests.rs @@ -707,9 +707,15 @@ assert_eq!(TemplateModule::balance_count(1, 1), 1); // burn item - assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5)); + assert_ok!(TemplateModule::burn_item( + origin1.clone(), + 1, + 1, + account(1), + 5 + )); assert_noop!( - TemplateModule::burn_item(origin1, 1, 1, 5), + TemplateModule::burn_item(origin1, 1, 1, account(1), 5), Error::::TokenNotFound ); @@ -736,9 +742,15 @@ assert_eq!(TemplateModule::balance_count(1, 1), 5); // burn item - assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 5)); + assert_ok!(TemplateModule::burn_item( + origin1.clone(), + 1, + 1, + account(1), + 5 + )); assert_noop!( - TemplateModule::burn_item(origin1, 1, 1, 5), + TemplateModule::burn_item(origin1, 1, 1, account(1), 5), Error::::TokenValueNotEnough ); @@ -781,9 +793,15 @@ assert_eq!(TemplateModule::balance_count(1, 1), 1023); // burn item - assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1, 1023)); + assert_ok!(TemplateModule::burn_item( + origin1.clone(), + 1, + 1, + account(1), + 1023 + )); assert_noop!( - TemplateModule::burn_item(origin1, 1, 1, 1023), + TemplateModule::burn_item(origin1, 1, 1, account(1), 1023), Error::::TokenNotFound ); @@ -1378,7 +1396,7 @@ AccessMode::WhiteList )); assert_noop!( - TemplateModule::burn_item(origin1, 1, 1, 5), + TemplateModule::burn_item(origin1.clone(), 1, 1, account(1), 5), Error::::AddresNotInWhiteList ); }); --- a/tests/src/burnItem.test.ts +++ b/tests/src/burnItem.test.ts @@ -38,7 +38,7 @@ const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); await usingApi(async (api) => { - const tx = api.tx.nft.burnItem(collectionId, tokenId, 0); + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 0); const events = await submitTransactionAsync(alice, tx); const result = getGenericResult(events); // Get the item @@ -59,7 +59,7 @@ await usingApi(async (api) => { // Destroy 1 of 10 - const tx = api.tx.nft.burnItem(collectionId, tokenId, 1); + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 1); const events = await submitTransactionAsync(alice, tx); const result = getGenericResult(events); @@ -79,7 +79,7 @@ const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); await usingApi(async (api) => { - const tx = api.tx.nft.burnItem(collectionId, tokenId, 1); + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 1); const events = await submitTransactionAsync(alice, tx); const result = getGenericResult(events); @@ -107,7 +107,7 @@ 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 tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(bob.address), 0); const events2 = await submitTransactionAsync(bob, tx); const result2 = getGenericResult(events2); @@ -152,7 +152,7 @@ await addCollectionAdminExpectSuccess(alice, collectionId, bob); await usingApi(async (api) => { - const tx = api.tx.nft.burnItem(collectionId, tokenId, 0); + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 0); const events = await submitTransactionAsync(bob, tx); const result = getGenericResult(events); // Get the item @@ -164,6 +164,49 @@ expect(item).to.be.null; }); }); + + + 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 + await addCollectionAdminExpectSuccess(alice, collectionId, bob); + const tokenId = 0; // ignored + + await usingApi(async (api) => { + // Destroy 1 of 10 + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 1); + const events = await submitTransactionAsync(bob, 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 }}); + const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); + await addCollectionAdminExpectSuccess(alice, collectionId, bob); + + await usingApi(async (api) => { + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 1); + const events = await submitTransactionAsync(bob, 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.null; + }); + }); }); describe('Negative integration test: ext. burnItem():', () => { @@ -182,7 +225,7 @@ await destroyCollectionExpectSuccess(collectionId); await usingApi(async (api) => { - const tx = api.tx.nft.burnItem(collectionId, tokenId, 0); + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 0); const badTransaction = async function () { await submitTransactionExpectFailAsync(alice, tx); }; @@ -197,7 +240,7 @@ const tokenId = 10; await usingApi(async (api) => { - const tx = api.tx.nft.burnItem(collectionId, tokenId, 0); + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 0); const badTransaction = async function () { await submitTransactionExpectFailAsync(alice, tx); }; @@ -212,7 +255,7 @@ const tokenId = await createItemExpectSuccess(alice, collectionId, createMode); await usingApi(async (api) => { - const tx = api.tx.nft.burnItem(collectionId, tokenId, 0); + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 0); const badTransaction = async function () { await submitTransactionExpectFailAsync(bob, tx); }; @@ -228,7 +271,7 @@ await usingApi(async (api) => { - const burntx = api.tx.nft.burnItem(collectionId, tokenId, 0); + const burntx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 0); const events1 = await submitTransactionAsync(alice, burntx); const result1 = getGenericResult(events1); expect(result1.success).to.be.true; @@ -251,7 +294,7 @@ await usingApi(async (api) => { // Destroy 11 of 10 - const tx = api.tx.nft.burnItem(collectionId, tokenId, 11); + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(alice.address), 11); const badTransaction = async function () { await submitTransactionExpectFailAsync(alice, tx); }; --- a/tests/src/check-event/burnItemEvent.test.ts +++ b/tests/src/check-event/burnItemEvent.test.ts @@ -10,7 +10,7 @@ import chaiAsPromised from 'chai-as-promised'; import privateKey from '../substrate/privateKey'; import usingApi, {submitTransactionAsync} from '../substrate/substrate-api'; -import { createCollectionExpectSuccess, createItemExpectSuccess, nftEventMessage } from '../util/helpers'; +import { createCollectionExpectSuccess, createItemExpectSuccess, nftEventMessage, normalizeAccountId } from '../util/helpers'; chai.use(chaiAsPromised); const expect = chai.expect; @@ -29,7 +29,7 @@ await usingApi(async (api: ApiPromise) => { const collectionID = await createCollectionExpectSuccess(); const itemID = await createItemExpectSuccess(Alice, collectionID, 'NFT'); - const burnItem = api.tx.nft.burnItem(collectionID, itemID, 1); + const burnItem = api.tx.nft.burnItem(collectionID, itemID, normalizeAccountId(Alice.address), 1); const events = await submitTransactionAsync(Alice, burnItem); const msg = JSON.stringify(nftEventMessage(events)); expect(msg).to.be.contain(checkSection); --- a/tests/src/collision-tests/admVsOwnerTake.test.ts +++ b/tests/src/collision-tests/admVsOwnerTake.test.ts @@ -34,7 +34,7 @@ const itemId = await createItemExpectSuccess(Bob, collectionId, 'NFT'); // const sendItem = api.tx.nft.transfer(normalizeAccountId(Ferdie.address), collectionId, itemId, 1); - const burnItem = api.tx.nft.burnItem(collectionId, itemId, 1); + const burnItem = api.tx.nft.burnItem(collectionId, itemId, normalizeAccountId(Alice.address), 1); await Promise.all([ sendItem.signAndSend(Bob), burnItem.signAndSend(Alice), --- a/tests/src/setVariableMetaData.test.ts +++ b/tests/src/setVariableMetaData.test.ts @@ -116,7 +116,7 @@ it('fails on removed token', async () => { const removedTokenCollectionId = await createCollectionExpectSuccess({ mode: { type: 'NFT' } }); const removedTokenId = await createItemExpectSuccess(alice, removedTokenCollectionId, 'NFT'); - await burnItemExpectSuccess(alice, removedTokenCollectionId, removedTokenId); + await burnItemExpectSuccess(alice, removedTokenCollectionId, removedTokenId, alice); await setVariableMetaDataExpectFailure(alice, removedTokenCollectionId, removedTokenId, data); }); --- a/tests/src/transfer.test.ts +++ b/tests/src/transfer.test.ts @@ -188,18 +188,18 @@ // nft const nftCollectionId = await createCollectionExpectSuccess(); const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT'); - await burnItemExpectSuccess(Alice, nftCollectionId, newNftTokenId, 1); + await burnItemExpectSuccess(Alice, nftCollectionId, newNftTokenId, Alice, 1); await transferExpectFailure(nftCollectionId, newNftTokenId, Alice, Bob, 1); // fungible const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); const newFungibleTokenId = await createItemExpectSuccess(Alice, fungibleCollectionId, 'Fungible'); - await burnItemExpectSuccess(Alice, fungibleCollectionId, newFungibleTokenId, 10); + await burnItemExpectSuccess(Alice, fungibleCollectionId, newFungibleTokenId, Alice, 10); await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, Alice, Bob, 1); // reFungible const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); - await burnItemExpectSuccess(Alice, reFungibleCollectionId, newReFungibleTokenId, 1); + await burnItemExpectSuccess(Alice, reFungibleCollectionId, newReFungibleTokenId, Alice, 1); await transferExpectFailure( reFungibleCollectionId, newReFungibleTokenId, --- a/tests/src/transferFrom.test.ts +++ b/tests/src/transferFrom.test.ts @@ -246,7 +246,7 @@ // nft const nftCollectionId = await createCollectionExpectSuccess(); const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT'); - await burnItemExpectSuccess(Alice, nftCollectionId, newNftTokenId, 1); + await burnItemExpectSuccess(Alice, nftCollectionId, newNftTokenId, Alice, 1); await approveExpectFail(nftCollectionId, newNftTokenId, Alice, Bob); await transferFromExpectFail(nftCollectionId, newNftTokenId, Bob, Alice, Charlie, 1); }); @@ -255,7 +255,7 @@ await usingApi(async () => { const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); const newFungibleTokenId = await createItemExpectSuccess(Alice, fungibleCollectionId, 'Fungible'); - await burnItemExpectSuccess(Alice, fungibleCollectionId, 1, 10); + await burnItemExpectSuccess(Alice, fungibleCollectionId, 1, Alice, 10); await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob); await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 1); @@ -265,7 +265,7 @@ await usingApi(async () => { const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); - await burnItemExpectSuccess(Alice, reFungibleCollectionId, newReFungibleTokenId, 1); + await burnItemExpectSuccess(Alice, reFungibleCollectionId, newReFungibleTokenId, Alice, 1); await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob); await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, Bob, Alice, Charlie, 1); @@ -278,7 +278,7 @@ const nftCollectionId = await createCollectionExpectSuccess(); const newNftTokenId = await createItemExpectSuccess(Alice, nftCollectionId, 'NFT'); await approveExpectSuccess(nftCollectionId, newNftTokenId, Alice, Bob); - await burnItemExpectSuccess(Alice, nftCollectionId, newNftTokenId, 1); + await burnItemExpectSuccess(Alice, nftCollectionId, newNftTokenId, Alice, 1); await transferFromExpectFail(nftCollectionId, newNftTokenId, Bob, Alice, Charlie, 1); }); }); @@ -287,7 +287,7 @@ const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}}); const newFungibleTokenId = await createItemExpectSuccess(Alice, fungibleCollectionId, 'Fungible'); await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, Alice, Bob); - await burnItemExpectSuccess(Alice, fungibleCollectionId, 1, 10); + await burnItemExpectSuccess(Alice, fungibleCollectionId, 1, Alice, 10); await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, Bob, Alice, Charlie, 1); }); @@ -297,7 +297,7 @@ const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}}); const newReFungibleTokenId = await createItemExpectSuccess(Alice, reFungibleCollectionId, 'ReFungible'); await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, Alice, Bob); - await burnItemExpectSuccess(Alice, reFungibleCollectionId, newReFungibleTokenId, 1); + await burnItemExpectSuccess(Alice, reFungibleCollectionId, newReFungibleTokenId, Alice, 1); await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, Bob, Alice, Charlie, 1); }); --- a/tests/src/util/helpers.ts +++ b/tests/src/util/helpers.ts @@ -700,10 +700,10 @@ ReFungible: CreateReFungibleData; }; -export async function burnItemExpectSuccess(owner: IKeyringPair, collectionId: number, tokenId: number, value = 0) { +export async function burnItemExpectSuccess(sender: IKeyringPair, collectionId: number, tokenId: number, owner: IKeyringPair, value = 0) { await usingApi(async (api) => { - const tx = api.tx.nft.burnItem(collectionId, tokenId, value); - const events = await submitTransactionAsync(owner, tx); + const tx = api.tx.nft.burnItem(collectionId, tokenId, normalizeAccountId(owner.address), value); + const events = await submitTransactionAsync(sender, tx); const result = getGenericResult(events); // Get the item const item: any = (await api.query.nft.nftItemList(collectionId, tokenId)).toJSON(); -- gitstuff