git.delta.rocks / unique-network / refs/commits / 1f6cb5bfa45d

difftreelog

source

tests/src/transfer.test.ts17.3 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 {alicesPublicKey, bobsPublicKey} from './accounts';21import getBalance from './substrate/get-balance';22import privateKey from './substrate/privateKey';23import {default as usingApi, submitTransactionAsync} from './substrate/substrate-api';24import {25  burnItemExpectSuccess, createCollectionExpectSuccess, createItemExpectSuccess,26  destroyCollectionExpectSuccess,27  findUnusedAddress,28  getCreateCollectionResult,29  getCreateItemResult,30  transferExpectFailure,31  transferExpectSuccess,32  addCollectionAdminExpectSuccess,33  getCreatedCollectionCount,34  toSubstrateAddress,35  getTokenOwner,36  normalizeAccountId,37  getBalance as getTokenBalance,38  transferFromExpectSuccess,39  transferFromExpectFail,40} from './util/helpers';41import {42  subToEth,43  itWeb3, 44} from './eth/util/helpers';4546let alice: IKeyringPair;47let bob: IKeyringPair;48let charlie: IKeyringPair;4950describe('Integration Test Transfer(recipient, collection_id, item_id, value)', () => {51  it('Balance transfers and check balance', async () => {52    await usingApi(async (api: ApiPromise) => {53      const [alicesBalanceBefore, bobsBalanceBefore] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);5455      const alicePrivateKey = privateKey('//Alice');5657      const transfer = api.tx.balances.transfer(bobsPublicKey, 1n);58      const events = await submitTransactionAsync(alicePrivateKey, transfer);59      const result = getCreateItemResult(events);60      // tslint:disable-next-line:no-unused-expression61      expect(result.success).to.be.true;6263      const [alicesBalanceAfter, bobsBalanceAfter] = await getBalance(api, [alicesPublicKey, bobsPublicKey]);6465      // tslint:disable-next-line:no-unused-expression66      expect(alicesBalanceAfter < alicesBalanceBefore).to.be.true;67      // tslint:disable-next-line:no-unused-expression68      expect(bobsBalanceAfter > bobsBalanceBefore).to.be.true;69    });70  });7172  it('Inability to pay fees error message is correct', async () => {73    await usingApi(async (api) => {74      // Find unused address75      const pk = await findUnusedAddress(api);7677      const badTransfer = api.tx.balances.transfer(bobsPublicKey, 1n);78      // const events = await submitTransactionAsync(pk, badTransfer);79      const badTransaction = async () => {80        const events = await submitTransactionAsync(pk, badTransfer);81        const result = getCreateCollectionResult(events);82        // tslint:disable-next-line:no-unused-expression83        expect(result.success).to.be.false;84      };85      await expect(badTransaction()).to.be.rejectedWith('Inability to pay some fees , e.g. account balance too low');86    });87  });8889  it('User can transfer owned token', async () => {90    await usingApi(async () => {91      const alice = privateKey('//Alice');92      const bob = privateKey('//Bob');93      // nft94      const nftCollectionId = await createCollectionExpectSuccess();95      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');96      await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 1, 'NFT');97      // fungible98      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});99      const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');100      await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob, 1, 'Fungible');101      // reFungible102      const reFungibleCollectionId = await103      createCollectionExpectSuccess({mode: {type: 'ReFungible'}});104      const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');105      await transferExpectSuccess(106        reFungibleCollectionId,107        newReFungibleTokenId,108        alice,109        bob,110        100,111        'ReFungible',112      );113    });114  });115116  it('Collection admin can transfer owned token', async () => {117    await usingApi(async () => {118      const alice = privateKey('//Alice');119      const bob = privateKey('//Bob');120      // nft121      const nftCollectionId = await createCollectionExpectSuccess();122      await addCollectionAdminExpectSuccess(alice, nftCollectionId, bob.address);123      const newNftTokenId = await createItemExpectSuccess(bob, nftCollectionId, 'NFT', bob.address);124      await transferExpectSuccess(nftCollectionId, newNftTokenId, bob, alice, 1, 'NFT');125      // fungible126      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});127      await addCollectionAdminExpectSuccess(alice, fungibleCollectionId, bob.address);128      const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible', bob.address);129      await transferExpectSuccess(fungibleCollectionId, newFungibleTokenId, bob, alice, 1, 'Fungible');130      // reFungible131      const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});132      await addCollectionAdminExpectSuccess(alice, reFungibleCollectionId, bob.address);133      const newReFungibleTokenId = await createItemExpectSuccess(bob, reFungibleCollectionId, 'ReFungible', bob.address);134      await transferExpectSuccess(135        reFungibleCollectionId,136        newReFungibleTokenId,137        bob,138        alice,139        100,140        'ReFungible',141      );142    });143  });144});145146describe('Negative Integration Test Transfer(recipient, collection_id, item_id, value)', () => {147  before(async () => {148    await usingApi(async () => {149      alice = privateKey('//Alice');150      bob = privateKey('//Bob');151      charlie = privateKey('//Charlie');152    });153  });154  it('Transfer with not existed collection_id', async () => {155    await usingApi(async (api) => {156      // nft157      const nftCollectionCount = await getCreatedCollectionCount(api);158      await transferExpectFailure(nftCollectionCount + 1, 1, alice, bob, 1);159      // fungible160      const fungibleCollectionCount = await getCreatedCollectionCount(api);161      await transferExpectFailure(fungibleCollectionCount + 1, 0, alice, bob, 1);162      // reFungible163      const reFungibleCollectionCount = await getCreatedCollectionCount(api);164      await transferExpectFailure(reFungibleCollectionCount + 1, 1, alice, bob, 1);165    });166  });167  it('Transfer with deleted collection_id', async () => {168    // nft169    const nftCollectionId = await createCollectionExpectSuccess();170    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');171    await destroyCollectionExpectSuccess(nftCollectionId);172    await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);173    // fungible174    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});175    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');176    await destroyCollectionExpectSuccess(fungibleCollectionId);177    await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);178    // reFungible179    const reFungibleCollectionId = await180    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});181    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');182    await destroyCollectionExpectSuccess(reFungibleCollectionId);183    await transferExpectFailure(184      reFungibleCollectionId,185      newReFungibleTokenId,186      alice,187      bob,188      1,189    );190  });191  it('Transfer with not existed item_id', async () => {192    // nft193    const nftCollectionId = await createCollectionExpectSuccess();194    await transferExpectFailure(nftCollectionId, 2, alice, bob, 1);195    // fungible196    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});197    await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1);198    // reFungible199    const reFungibleCollectionId = await200    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});201    await transferExpectFailure(202      reFungibleCollectionId,203      2,204      alice,205      bob,206      1,207    );208  });209  it('Transfer with deleted item_id', async () => {210    // nft211    const nftCollectionId = await createCollectionExpectSuccess();212    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');213    await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);214    await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);215    // fungible216    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});217    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');218    await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);219    await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);220    // reFungible221    const reFungibleCollectionId = await222    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});223    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');224    await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100);225    await transferExpectFailure(226      reFungibleCollectionId,227      newReFungibleTokenId,228      alice,229      bob,230      1,231    );232  });233  it('Transfer with recipient that is not owner', async () => {234    // nft235    const nftCollectionId = await createCollectionExpectSuccess();236    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');237    await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1);238    // fungible239    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});240    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');241    await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1);242    // reFungible243    const reFungibleCollectionId = await244    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});245    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');246    await transferExpectFailure(247      reFungibleCollectionId,248      newReFungibleTokenId,249      charlie,250      bob,251      1,252    );253  });254});255256describe('Zero value transfer(From)', () => {257  before(async () => {258    await usingApi(async () => {259      alice = privateKey('//Alice');260      bob = privateKey('//Bob');261    });262  });263264  it('NFT', async () => {265    await usingApi(async (api: ApiPromise) => {266      const nftCollectionId = await createCollectionExpectSuccess();267      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');268269      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), nftCollectionId, newNftTokenId, 0);270      await submitTransactionAsync(alice, transferTx);271      const address = normalizeAccountId(await getTokenOwner(api, nftCollectionId, newNftTokenId));272273      expect(toSubstrateAddress(address)).to.be.equal(alice.address);274    });275  });276277  it('RFT', async () => {278    await usingApi(async (api: ApiPromise) => {279      const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});280      const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');281      const balanceBeforeAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId);282      const balanceBeforeBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId);283284      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), reFungibleCollectionId, newReFungibleTokenId, 0);285      await submitTransactionAsync(alice, transferTx);286287      const balanceAfterAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId);288      const balanceAfterBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId);289290      expect((balanceBeforeAlice)).to.be.equal(balanceAfterAlice);291      expect((balanceBeforeBob)).to.be.equal(balanceAfterBob);292    });293  });294295  it('Fungible', async () => {296    await usingApi(async (api: ApiPromise) => {297      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});298      const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');299      const balanceBeforeAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId);300      const balanceBeforeBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId);301302      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), fungibleCollectionId, newFungibleTokenId, 0);303      await submitTransactionAsync(alice, transferTx);304305      const balanceAfterAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId);306      const balanceAfterBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId);307308      expect((balanceBeforeAlice)).to.be.equal(balanceAfterAlice);309      expect((balanceBeforeBob)).to.be.equal(balanceAfterBob);310    });311  });312});313314describe('Transfers to self (potentially over substrate-evm boundary)', () => {315  itWeb3('Transfers to self. In case of same frontend', async ({api}) => {316    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});317    const alice = privateKey('//Alice');318    const aliceProxy = subToEth(alice.address);319    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});320    await transferExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, 10, 'Fungible');321    const balanceAliceBefore = await getTokenBalance(api, collectionId, {Ethereum: aliceProxy}, tokenId);322    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, {Ethereum: aliceProxy}, 10, 'Fungible');323    const balanceAliceAfter = await getTokenBalance(api, collectionId, {Ethereum: aliceProxy}, tokenId);324    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);325  });326327  itWeb3('Transfers to self. In case of substrate-evm boundary', async ({api}) => {328    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});329    const alice = privateKey('//Alice');330    const aliceProxy = subToEth(alice.address);331    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});332    const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);333    await transferExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy} , 10, 'Fungible');334    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, alice, 10, 'Fungible');335    const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);336    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);337  });338339  itWeb3('Transfers to self. In case of inside substrate-evm', async ({api}) => {340    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});341    const alice = privateKey('//Alice');342    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});343    const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);344    await transferExpectSuccess(collectionId, tokenId, alice, alice , 10, 'Fungible');345    await transferFromExpectSuccess(collectionId, tokenId, alice, alice, alice, 10, 'Fungible');346    const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);347    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);348  });349350  itWeb3('Transfers to self. In case of inside substrate-evm when not enought "Fungibles"', async ({api}) => {351    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});352    const alice = privateKey('//Alice');353    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});354    const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);355    await transferExpectFailure(collectionId, tokenId, alice, alice , 11);356    await transferFromExpectFail(collectionId, tokenId, alice, alice, alice, 11);357    const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);358    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);359  });360});