git.delta.rocks / unique-network / refs/commits / 0f7bb4adb180

difftreelog

source

tests/src/transfer.test.ts17.6 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 burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId);172    await destroyCollectionExpectSuccess(nftCollectionId);173    await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);174    // fungible175    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});176    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');177    await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);178    await destroyCollectionExpectSuccess(fungibleCollectionId);179    await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);180    // reFungible181    const reFungibleCollectionId = await182    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});183    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');184    await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100);185    await destroyCollectionExpectSuccess(reFungibleCollectionId);186    await transferExpectFailure(187      reFungibleCollectionId,188      newReFungibleTokenId,189      alice,190      bob,191      1,192    );193  });194  it('Transfer with not existed item_id', async () => {195    // nft196    const nftCollectionId = await createCollectionExpectSuccess();197    await transferExpectFailure(nftCollectionId, 2, alice, bob, 1);198    // fungible199    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});200    await transferExpectFailure(fungibleCollectionId, 2, alice, bob, 1);201    // reFungible202    const reFungibleCollectionId = await203    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});204    await transferExpectFailure(205      reFungibleCollectionId,206      2,207      alice,208      bob,209      1,210    );211  });212  it('Transfer with deleted item_id', async () => {213    // nft214    const nftCollectionId = await createCollectionExpectSuccess();215    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');216    await burnItemExpectSuccess(alice, nftCollectionId, newNftTokenId, 1);217    await transferExpectFailure(nftCollectionId, newNftTokenId, alice, bob, 1);218    // fungible219    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});220    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');221    await burnItemExpectSuccess(alice, fungibleCollectionId, newFungibleTokenId, 10);222    await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, alice, bob, 1);223    // reFungible224    const reFungibleCollectionId = await225    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});226    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');227    await burnItemExpectSuccess(alice, reFungibleCollectionId, newReFungibleTokenId, 100);228    await transferExpectFailure(229      reFungibleCollectionId,230      newReFungibleTokenId,231      alice,232      bob,233      1,234    );235  });236  it('Transfer with recipient that is not owner', async () => {237    // nft238    const nftCollectionId = await createCollectionExpectSuccess();239    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');240    await transferExpectFailure(nftCollectionId, newNftTokenId, charlie, bob, 1);241    // fungible242    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});243    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');244    await transferExpectFailure(fungibleCollectionId, newFungibleTokenId, charlie, bob, 1);245    // reFungible246    const reFungibleCollectionId = await247    createCollectionExpectSuccess({mode: {type: 'ReFungible'}});248    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');249    await transferExpectFailure(250      reFungibleCollectionId,251      newReFungibleTokenId,252      charlie,253      bob,254      1,255    );256  });257});258259describe('Zero value transfer(From)', () => {260  before(async () => {261    await usingApi(async () => {262      alice = privateKey('//Alice');263      bob = privateKey('//Bob');264    });265  });266267  it('NFT', async () => {268    await usingApi(async (api: ApiPromise) => {269      const nftCollectionId = await createCollectionExpectSuccess();270      const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');271272      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), nftCollectionId, newNftTokenId, 0);273      await submitTransactionAsync(alice, transferTx);274      const address = normalizeAccountId(await getTokenOwner(api, nftCollectionId, newNftTokenId));275276      expect(toSubstrateAddress(address)).to.be.equal(alice.address);277    });278  });279280  it('RFT', async () => {281    await usingApi(async (api: ApiPromise) => {282      const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});283      const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');284      const balanceBeforeAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId);285      const balanceBeforeBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId);286287      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), reFungibleCollectionId, newReFungibleTokenId, 0);288      await submitTransactionAsync(alice, transferTx);289290      const balanceAfterAlice = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(alice), newReFungibleTokenId);291      const balanceAfterBob = await getTokenBalance(api, reFungibleCollectionId, normalizeAccountId(bob), newReFungibleTokenId);292293      expect((balanceBeforeAlice)).to.be.equal(balanceAfterAlice);294      expect((balanceBeforeBob)).to.be.equal(balanceAfterBob);295    });296  });297298  it('Fungible', async () => {299    await usingApi(async (api: ApiPromise) => {300      const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});301      const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');302      const balanceBeforeAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId);303      const balanceBeforeBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId);304305      const transferTx = api.tx.unique.transfer(normalizeAccountId(bob), fungibleCollectionId, newFungibleTokenId, 0);306      await submitTransactionAsync(alice, transferTx);307308      const balanceAfterAlice = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(alice), newFungibleTokenId);309      const balanceAfterBob = await getTokenBalance(api, fungibleCollectionId, normalizeAccountId(bob), newFungibleTokenId);310311      expect((balanceBeforeAlice)).to.be.equal(balanceAfterAlice);312      expect((balanceBeforeBob)).to.be.equal(balanceAfterBob);313    });314  });315});316317describe('Transfers to self (potentially over substrate-evm boundary)', () => {318  itWeb3('Transfers to self. In case of same frontend', async ({api}) => {319    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});320    const alice = privateKey('//Alice');321    const aliceProxy = subToEth(alice.address);322    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});323    await transferExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, 10, 'Fungible');324    const balanceAliceBefore = await getTokenBalance(api, collectionId, {Ethereum: aliceProxy}, tokenId);325    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, {Ethereum: aliceProxy}, 10, 'Fungible');326    const balanceAliceAfter = await getTokenBalance(api, collectionId, {Ethereum: aliceProxy}, tokenId);327    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);328  });329330  itWeb3('Transfers to self. In case of substrate-evm boundary', async ({api}) => {331    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});332    const alice = privateKey('//Alice');333    const aliceProxy = subToEth(alice.address);334    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});335    const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);336    await transferExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy} , 10, 'Fungible');337    await transferFromExpectSuccess(collectionId, tokenId, alice, {Ethereum: aliceProxy}, alice, 10, 'Fungible');338    const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);339    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);340  });341342  itWeb3('Transfers to self. In case of inside substrate-evm', async ({api}) => {343    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});344    const alice = privateKey('//Alice');345    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});346    const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);347    await transferExpectSuccess(collectionId, tokenId, alice, alice , 10, 'Fungible');348    await transferFromExpectSuccess(collectionId, tokenId, alice, alice, alice, 10, 'Fungible');349    const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);350    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);351  });352353  itWeb3('Transfers to self. In case of inside substrate-evm when not enought "Fungibles"', async ({api}) => {354    const collectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});355    const alice = privateKey('//Alice');356    const tokenId = await createItemExpectSuccess(alice, collectionId, 'Fungible', {Substrate: alice.address});357    const balanceAliceBefore = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);358    await transferExpectFailure(collectionId, tokenId, alice, alice , 11);359    await transferFromExpectFail(collectionId, tokenId, alice, alice, alice, 11);360    const balanceAliceAfter = await getTokenBalance(api, collectionId, normalizeAccountId(alice), tokenId);361    expect(balanceAliceBefore).to.be.eq(balanceAliceAfter);362  });363});