git.delta.rocks / unique-network / refs/commits / f59d814cf24d

difftreelog

source

tests/src/transfer.test.ts18.7 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617import {ApiPromise} from '@polkadot/api';18import {IKeyringPair} from '@polkadot/types/types';19import {expect} from 'chai';20import getBalance from './substrate/get-balance';21import {default as usingApi, submitTransactionAsync} from './substrate/substrate-api';22import {23  burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess,24  destroyCollectionExpectSuccess,25  findUnusedAddress,26  getCreateCollectionResult,27  getCreateItemResult,28  transferExpectFailure,29  transferExpectSuccess,30  addCollectionAdminExpectSuccess,31  getCreatedCollectionCount,32  toSubstrateAddress,33  getTokenOwner,34  normalizeAccountId,35  getBalance as getTokenBalance,36  transferFromExpectSuccess,37  transferFromExpectFail,38  requirePallets,39  Pallets,40} from './util/helpers';41import {42  subToEth,43  itWeb3, 44} from './eth/util/helpers';45import {request} from 'https';4647let alice: IKeyringPair;48let bob: IKeyringPair;49let charlie: IKeyringPair;5051describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => {52  before(async () => {53    await usingApi(async (api, privateKeyWrapper) => {54      alice = privateKeyWrapper('//Alice');55      bob = privateKeyWrapper('//Bob');56    });57  });58  59  it('Balance transfers and check balance', async () => {60    await usingApi(async (api, privateKeyWrapper) => {61      const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alice.address, bob.address]);6263      const transfer = api.tx.balances.transfer(bob.address, 1n);64      const events = await submitTransactionAsync(alice, transfer);65      const result = getCreateItemResult(events);66      // tslint:disable-next-line:no-unused-expression67      expect(result.success).to.be.true;6869      const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alice.address, bob.address]);7071      // tslint:disable-next-line:no-unused-expression72      expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;73      // tslint:disable-next-line:no-unused-expression74      expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true;75    });76  });7778  it('Inability to pay fees error message is correct', async () => {79    await usingApi(async (api, privateKeyWrapper) => {80      // Find unused address81      const pk = await findUnusedAddress(api, privateKeyWrapper);8283      const badTransfer = api.tx.balances.transfer(bob.address, 1n);84      // const events = await submitTransactionAsync(pk, badTransfer);85      const badTransaction = async () => {86        const events = await submitTransactionAsync(pk, badTransfer);87        const result = getCreateCollectionResult(events);88        // tslint:disable-next-line:no-unused-expression89        expect(result.success).to.be.false;90      };91      await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees , e.g. account balance too low');92    });93  });9495  it('[nft] User can transfer owned token', async () => {96    const nftCollectionId = await createCollectionExpectSuccess();97    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');98    await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');99  });100101  it('[fungible] User can transfer owned token', async () => {102    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});103    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');104    await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');105  });106107  it('[refungible] User can transfer owned token', async function() {108    await requirePallets(this, [Pallets.ReFungible]);109110    const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});111    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');112    await transferExpectSuccess(113      reFungibleCollectionId,114      newReFungibleTokenId,115      alice,116      bob,117      100,118      'ReFungible',119    );120  });121122  it('[nft] Collection admin can transfer owned token', async () => {123    const nftCollectionId = await createCollectionExpectSuccess();124    await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);125    const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);126    await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');127  });128129  it('[fungible] Collection admin can transfer owned token', async () => {130    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});131    await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);132    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);133    await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');134  });135136  it('[refungible] Collection admin can transfer owned token', async function() {137    await requirePallets(this, [Pallets.ReFungible]);138139    const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});140    await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);141    const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);142    await transferExpectSuccess(143      reFungibleCollectionId,144      newReFungibleTokenId,145      bob,146      alice,147      100,148      'ReFungible',149    );150  });151});152153describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {154  before(async () => {155    await usingApi(async (api, privateKeyWrapper) => {156      alice = privateKeyWrapper('//Alice');157      bob = privateKeyWrapper('//Bob');158      charlie = privateKeyWrapper('//Charlie');159    });160  });161162  it('[nft] Transfer with not existed collection_id', async () => {163    await usingApi(async (api) => {164      const nftCollectionCount = await getCreatedCollectionCount(api);165      await transferExpectFailure(nftCollectionCount + 1, 1, alice, bob, 1);166    });167  });168169  it('[fungible] Transfer with not existed collection_id', async () => {170    await usingApi(async (api) => {171      const fungibleCollectionCount = await getCreatedCollectionCount(api);172      await transferExpectFailure(fungibleCollectionCount + 1, 0, alice, bob, 1);173    });174  });175176  it('[refungible] Transfer with not existed collection_id', async function() {177    await requirePallets(this, [Pallets.ReFungible]);178179    await usingApi(async (api) => {180      const reFungibleCollectionCount = await getCreatedCollectionCount(api);181      await transferExpectFailure(reFungibleCollectionCount + 1, 1, alice, bob, 1);182    });183  });184185  it('[nft] Transfer with deleted collection_id', async () => {186    const nftCollectionId = await createCollectionExpectSuccess();187    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');188    await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId);189    await destroyCollectionExpectSuccess(nftCollectionId);190    await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);191  });192193  it('[fungible] Transfer with deleted collection_id', async () => {194    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});195    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');196    await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);197    await destroyCollectionExpectSuccess(fungibleCollectionId);198    await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);199  });200201  it('[refungible] Transfer with deleted collection_id', async function() {202    await requirePallets(this, [Pallets.ReFungible]);203204    const reFungibleCollectionId = await205    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});206    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');207    await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100);208    await destroyCollectionExpectSuccess(reFungibleCollectionId);209    await transferExpectFailure(210      reFungibleCollectionId,211      newReFungibleTokenId,212      alice,213      bob,214      1,215    );216  });217218  it('[nft] Transfer with not existed item_id', async () => {219    const nftCollectionId = await createCollectionExpectSuccess();220    await transferExpectFailure(nftCollectionId, 2, alice, bob, 1);221  });222223  it('[fungible] Transfer with not existed item_id', async () => {224    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});225    await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1);226  });227228  it('[refungible] Transfer with not existed item_id', async function() {229    await requirePallets(this, [Pallets.ReFungible]);230231    const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});232    await transferExpectFailure(233      reFungibleCollectionId,234      2,235      alice,236      bob,237      1,238    );239  });240241  it('[nft] Transfer with deleted item_id', async () => {242    const nftCollectionId = await createCollectionExpectSuccess();243    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');244    await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);245    await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);246  });247248  it('[fungible] Transfer with deleted item_id', async () => {249    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});250    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');251    await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);252    await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);253  });254255  it('[refungible] Transfer with deleted item_id', async function() {256    await requirePallets(this, [Pallets.ReFungible]);257258    const reFungibleCollectionId = await259    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});260    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');261    await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100);262    await transferExpectFailure(263      reFungibleCollectionId,264      newReFungibleTokenId,265      alice,266      bob,267      1,268    );269  });270271  it('[nft] Transfer with recipient that is not owner', async () => {272    const nftCollectionId = await createCollectionExpectSuccess();273    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');274    await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1);275  });276277  it('[fungible] Transfer with recipient that is not owner', async () => {278    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});279    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');280    await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1);281  });282283  it('[refungible] Transfer with recipient that is not owner', async function() {284    await requirePallets(this, [Pallets.ReFungible]);285286    const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});287    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');288    await transferExpectFailure(289      reFungibleCollectionId,290      newReFungibleTokenId,291      charlie,292      bob,293      1,294    );295  });296});297298describe('Zero value transfer(From)', () => {299  before(async () => {300    await usingApi(async (api, privateKeyWrapper) => {301      alice = privateKeyWrapper('//Alice');302      bob = privateKeyWrapper('//Bob');303    });304  });305306  it('NFT', async () => {307    await usingApi(async (api: ApiPromise) => {308      const nftCollectionId = await createCollectionExpectSuccess();309      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');310311      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), nftCollectionId, newNftTokenId, 0);312      await submitTransactionAsync(alice, transferTx);313      const address = normalizeAccountId(await getTokenOwner(api, nftCollectionId, newNftTokenId));314315      expect(toSubstrateAddress(address)).to.be.equal(alice.address);316    });317  });318319  it('RFT', async function() {320    await requirePallets(this, [Pallets.ReFungible]);321322    await usingApi(async (api: ApiPromise) => {323      const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});324      const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');325      const balanceBeforeAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId);326      const balanceBeforeBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId);327328      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), reFungibleCollectionId, newReFungibleTokenId, 0);329      await submitTransactionAsync(alice, transferTx);330331      const balanceAfterAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId);332      const balanceAfterBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId);333334      expect((balanceBeforeAlice)).to.be.equal(balanceAfterAlice);335      expect((balanceBeforeBob)).to.be.equal(balanceAfterBob);336    });337  });338339  it('Fungible', async () => {340    await usingApi(async (api: ApiPromise) => {341      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});342      const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');343      const balanceBeforeAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId);344      const balanceBeforeBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId);345346      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), fungibleCollectionId, newFungibleTokenId, 0);347      await submitTransactionAsync(alice, transferTx);348349      const balanceAfterAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId);350      const balanceAfterBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId);351352      expect((balanceBeforeAlice)).to.be.equal(balanceAfterAlice);353      expect((balanceBeforeBob)).to.be.equal(balanceAfterBob);354    });355  });356});357358describe('Transfers to self (potentially over substrate-evm boundary)', () => {359  itWeb3('Transfers to self. In case of same frontend', async ({api, privateKeyWrapper}) => {360    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});361    const aliceProxy = subToEth(alice.address);362    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});363    await transferExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, 10, 'Fungible');364    const balanceAliceBefore = await getTokenBalance(api, collectionId, {Ethereum: aliceProxy}, tokenId);365    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, {Ethereum: aliceProxy}, 10, 'Fungible');366    const balanceAliceAfter = await getTokenBalance(api, collectionId, {Ethereum: aliceProxy}, tokenId);367    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);368  });369370  itWeb3('Transfers to self. In case of substrate-evm boundary', async ({api, privateKeyWrapper}) => {371    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});372    const aliceProxy = subToEth(alice.address);373    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});374    const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);375    await transferExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy} , 10, 'Fungible');376    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, alice, 10, 'Fungible');377    const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);378    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);379  });380381  itWeb3('Transfers to self. In case of inside substrate-evm', async ({api, privateKeyWrapper}) => {382    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});383    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});384    const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);385    await transferExpectSuccess(collectionId, tokenId, alice, alice , 10, 'Fungible');386    await transferFromExpectSuccess(collectionId, tokenId, alice, alice, alice, 10, 'Fungible');387    const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);388    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);389  });390391  itWeb3('Transfers to self. In case of inside substrate-evm when not enought "Fungibles"', async ({api, privateKeyWrapper}) => {392    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});393    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});394    const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);395    await transferExpectFailure(collectionId, tokenId, alice, alice , 11);396    await transferFromExpectFail(collectionId, tokenId, alice, alice, alice, 11);397    const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);398    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);399  });400});