git.delta.rocks / unique-network / refs/commits / 6bbb9b831975

difftreelog

source

tests/src/approve.test.ts23.1 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 {IKeyringPair} from '@polkadot/types/types';18import {ApiPromise} from '@polkadot/api';19import chai from 'chai';20import chaiAsPromised from 'chai-as-promised';21import privateKey from './substrate/privateKey';22import {default as usingApi} from './substrate/substrate-api';23import {24  approveExpectFail,25  approveExpectSuccess,26  createCollectionExpectSuccess,27  createItemExpectSuccess,28  destroyCollectionExpectSuccess,29  setCollectionLimitsExpectSuccess,30  transferExpectSuccess,31  addCollectionAdminExpectSuccess,32  adminApproveFromExpectSuccess,33  getCreatedCollectionCount,34  transferFromExpectSuccess,35  transferFromExpectFail,36} from './util/helpers';3738chai.use(chaiAsPromised);3940describe('Integration Test approve(spender, collection_id, item_id, amount):', () => {41  let alice: IKeyringPair;42  let bob: IKeyringPair;43  let charlie: IKeyringPair;4445  before(async () => {46    await usingApi(async () => {47      alice = privateKey('//Alice');48      bob = privateKey('//Bob');49      charlie = privateKey('//Charlie');50    });51  });5253  it('Execute the extrinsic and check approvedList', async () => {54    const nftCollectionId = await createCollectionExpectSuccess();55    // nft56    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');57    await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address);58    // fungible59    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});60    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');61    await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address);62    // reFungible63    const reFungibleCollectionId =64      await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});65    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');66    await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address);67  });6869  it('Remove approval by using 0 amount', async () => {70    const nftCollectionId = await createCollectionExpectSuccess();71    // nft72    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');73    await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 1);74    await approveExpectSuccess(nftCollectionId, newNftTokenId, alice, bob.address, 0);75    // fungible76    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});77    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');78    await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 1);79    await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 0);80    // reFungible81    const reFungibleCollectionId =82      await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});83    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');84    await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 1);85    await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 0);86  });8788  it('can be called by collection owner on non-owned item when OwnerCanTransfer == true', async () => {89    const collectionId = await createCollectionExpectSuccess();90    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);9192    await adminApproveFromExpectSuccess(collectionId, itemId, alice, bob.address, charlie.address);93  });94});9596describe('Normal user can approve other users to transfer:', () => {97  let alice: IKeyringPair;98  let bob: IKeyringPair;99  let charlie: IKeyringPair;100101  before(async () => {102    await usingApi(async () => {103      alice = privateKey('//Alice');104      bob = privateKey('//Bob');105      charlie = privateKey('//Charlie');106    });107  });  108109  it('NFT', async () => {110    const collectionId = await createCollectionExpectSuccess();111    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);112    await approveExpectSuccess(collectionId, itemId, bob, charlie.address);113  });114115  it('Fungible up to an approved amount', async () => {116    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});117    const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', bob.address); 118    await approveExpectSuccess(collectionId, itemId, bob, charlie.address);119  });120121  it('ReFungible up to an approved amount', async () => {122    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});123    const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);124    await approveExpectSuccess(collectionId, itemId, bob, charlie.address);125  });126});127128describe('Approved users can transferFrom up to approved amount:', () => {129  let alice: IKeyringPair;130  let bob: IKeyringPair;131  let charlie: IKeyringPair;132133  before(async () => {134    await usingApi(async () => {135      alice = privateKey('//Alice');136      bob = privateKey('//Bob');137      charlie = privateKey('//Charlie');138    });139  });  140141  it('NFT', async () => {142    const collectionId = await createCollectionExpectSuccess();143    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);144    await approveExpectSuccess(collectionId, itemId, bob, charlie.address);145    await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'NFT');146  });147148  it('Fungible up to an approved amount', async () => {149    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});150    const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', bob.address); 151    await approveExpectSuccess(collectionId, itemId, bob, charlie.address);152    await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');153  });154155  it('ReFungible up to an approved amount', async () => {156    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});157    const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);158    await approveExpectSuccess(collectionId, itemId, bob, charlie.address);159    await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'ReFungible');160  });161});162163describe('Approved users cannot use transferFrom to repeat transfers if approved amount was already transferred:', () => {164  let alice: IKeyringPair;165  let bob: IKeyringPair;166  let charlie: IKeyringPair;167168  before(async () => {169    await usingApi(async () => {170      alice = privateKey('//Alice');171      bob = privateKey('//Bob');172      charlie = privateKey('//Charlie');173    });174  });  175176  it('NFT', async () => {177    const collectionId = await createCollectionExpectSuccess();178    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);179    await approveExpectSuccess(collectionId, itemId, bob, charlie.address);180    await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'NFT');181    await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);182  });183184  it('Fungible up to an approved amount', async () => {185    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});186    const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', bob.address); 187    await approveExpectSuccess(collectionId, itemId, bob, charlie.address);188    await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'Fungible');189    await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);190  });191192  it('ReFungible up to an approved amount', async () => {193    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});194    const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', bob.address);195    await approveExpectSuccess(collectionId, itemId, bob, charlie.address);196    await transferFromExpectSuccess(collectionId, itemId, charlie, bob, alice, 1, 'ReFungible');197    await transferFromExpectFail(collectionId, itemId, charlie, bob, alice, 1);198  });199});200201describe('Approved amount decreases by the transferred amount.:', () => {202  let alice: IKeyringPair;203  let bob: IKeyringPair;204  let charlie: IKeyringPair;205  let dave: IKeyringPair;206207  before(async () => {208    await usingApi(async () => {209      alice = privateKey('//Alice');210      bob = privateKey('//Bob');211      charlie = privateKey('//Charlie');212      dave = privateKey('//Dave');213    });214  });  215216  it('If a user B is approved to transfer 10 Fungible tokens from user A, they can transfer 2 tokens to user C, which will result in decreasing approval from 10 to 8. Then user B can transfer 8 tokens to user D.', async () => {217    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});218    const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', alice.address); 219    await approveExpectSuccess(collectionId, itemId, alice, bob.address, 10);220    await transferFromExpectSuccess(collectionId, itemId, bob, alice, charlie, 2, 'Fungible');221    await transferFromExpectSuccess(collectionId, itemId, bob, alice, dave, 8, 'Fungible');222  });223});224225describe('User may clear the approvals to approving for 0 amount:', () => {226  let alice: IKeyringPair;227  let bob: IKeyringPair;228  let charlie: IKeyringPair;229230  before(async () => {231    await usingApi(async () => {232      alice = privateKey('//Alice');233      bob = privateKey('//Bob');234      charlie = privateKey('//Charlie');235    });236  });237238  it('NFT', async () => {239    const collectionId = await createCollectionExpectSuccess();240    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT');241    await approveExpectSuccess(collectionId, itemId, alice, bob.address, 1);242    await approveExpectSuccess(collectionId, itemId, alice, bob.address, 0);243    await transferFromExpectFail(collectionId, itemId, bob, bob, charlie, 1);244  });245246  it('Fungible', async () => {247    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});248    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');249    await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 1);250    await approveExpectSuccess(fungibleCollectionId, newFungibleTokenId, alice, bob.address, 0);251    await transferFromExpectFail(fungibleCollectionId, newFungibleTokenId, bob, bob, charlie, 1);252  });253254  it('ReFungible', async () => {255    const reFungibleCollectionId =256      await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});257    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');258    await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 1);259    await approveExpectSuccess(reFungibleCollectionId, newReFungibleTokenId, alice, bob.address, 0);260    await transferFromExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, bob, charlie, 1);261  });262});263264describe('User cannot approve for the amount greater than they own:', () => {265  let alice: IKeyringPair;266  let bob: IKeyringPair;267  let charlie: IKeyringPair;268269  before(async () => {270    await usingApi(async () => {271      alice = privateKey('//Alice');272      bob = privateKey('//Bob');273      charlie = privateKey('//Charlie');274    });275  });276277  it('1 for NFT', async () => {278    const collectionId = await createCollectionExpectSuccess();279    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);280    await approveExpectFail(collectionId, itemId, bob, charlie, 2);281  });282283  it('Fungible', async () => {284    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});285    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');286    await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, charlie, 11);287  });288289  it('ReFungible', async () => {290    const reFungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});291    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');292    await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, charlie, 101);293  });294});295296describe('Administrator and collection owner do not need approval in order to execute TransferFrom:', () => {297  let alice: IKeyringPair;298  let bob: IKeyringPair;299  let charlie: IKeyringPair;300  let dave: IKeyringPair;301302  before(async () => {303    await usingApi(async () => {304      alice = privateKey('//Alice');305      bob = privateKey('//Bob');306      charlie = privateKey('//Charlie');307      dave = privateKey('//Dave');308    });309  });  310311  it('NFT', async () => {312    const collectionId = await createCollectionExpectSuccess();313    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', charlie.address);314    await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'NFT');315    await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);316    await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'NFT');317  });318319  it('Fungible up to an approved amount', async () => {320    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});321    const itemId = await createItemExpectSuccess(alice, collectionId, 'Fungible', charlie.address); 322    await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'Fungible');323    await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);324    await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'Fungible');325  });326327  it('ReFungible up to an approved amount', async () => {328    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});329    const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', charlie.address);330    await transferFromExpectSuccess(collectionId, itemId, alice, charlie, dave, 1, 'ReFungible');331    await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);332    await transferFromExpectSuccess(collectionId, itemId, bob, dave, alice, 1, 'ReFungible');333  });334});335336describe('Repeated approvals add up', () => {337  let alice: IKeyringPair;338  let bob: IKeyringPair;339  let charlie: IKeyringPair;340  let dave: IKeyringPair;341342  before(async () => {343    await usingApi(async () => {344      alice = privateKey('//Alice');345      bob = privateKey('//Bob');346      charlie = privateKey('//Charlie');347      dave = privateKey('//Dave');348    });349  });  350351  it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. Fungible', async () => {352    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});353    await createItemExpectSuccess(alice, collectionId, 'Fungible', alice.address);354    await approveExpectSuccess(collectionId, 0, alice, bob.address, 1);355    await approveExpectSuccess(collectionId, 0, alice, charlie.address, 1);356    // const allowances1 = await getAllowance(collectionId, 0, Alice.address, Bob.address);357    // const allowances2 = await getAllowance(collectionId, 0, Alice.address, Charlie.address);358    // expect(allowances1 + allowances2).to.be.eq(BigInt(2));359  });360361  it.skip('Owned 10, approval 1: 1, approval 2: 1, resulting approved value: 2. ReFungible', async () => {362    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});363    const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', alice.address);364    await approveExpectSuccess(collectionId, itemId, alice, bob.address, 1);365    await approveExpectSuccess(collectionId, itemId, alice, charlie.address, 1);366    // const allowances1 = await getAllowance(collectionId, itemId, Alice.address, Bob.address);367    // const allowances2 = await getAllowance(collectionId, itemId, Alice.address, Charlie.address);368    // expect(allowances1 + allowances2).to.be.eq(BigInt(2));369  });370371  // Canceled by changing approve logic372  it.skip('Cannot approve for more than total user`s amount (owned: 10, approval 1: 5 - should succeed, approval 2: 6 - should fail). Fungible', async () => {373    const collectionId = await createCollectionExpectSuccess({mode:{type: 'Fungible', decimalPoints: 0}});374    await createItemExpectSuccess(alice, collectionId, 'Fungible', dave.address);375    await approveExpectSuccess(collectionId, 0, dave, bob.address, 5);376    await approveExpectFail(collectionId, 0, dave, charlie, 6);377  });378379  // Canceled by changing approve logic380  it.skip('Cannot approve for more than total users amount (owned: 100, approval 1: 50 - should succeed, approval 2: 51 - should fail). ReFungible', async () => {381    const collectionId = await createCollectionExpectSuccess({mode:{type: 'ReFungible'}});382    const itemId = await createItemExpectSuccess(alice, collectionId, 'ReFungible', dave.address);383    await approveExpectSuccess(collectionId, itemId, dave, bob.address, 50);384    await approveExpectFail(collectionId, itemId, dave, charlie, 51);385  });386});387388describe('Integration Test approve(spender, collection_id, item_id, amount) with collection admin permissions:', () => {389  let alice: IKeyringPair;390  let bob: IKeyringPair;391  let charlie: IKeyringPair;392393  before(async () => {394    await usingApi(async () => {395      alice = privateKey('//Alice');396      bob = privateKey('//Bob');397      charlie = privateKey('//Charlie');398    });399  });400401  it('can be called by collection admin on non-owned item', async () => {402    const collectionId = await createCollectionExpectSuccess();403    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', alice.address);404405    await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);406    await adminApproveFromExpectSuccess(collectionId, itemId, bob, alice.address, charlie.address);407  });408});409410describe('Negative Integration Test approve(spender, collection_id, item_id, amount):', () => {411  let alice: IKeyringPair;412  let bob: IKeyringPair;413  let charlie: IKeyringPair;414415  before(async () => {416    await usingApi(async () => {417      alice = privateKey('//Alice');418      bob = privateKey('//Bob');419      charlie = privateKey('//Charlie');420    });421  });422423  it('Approve for a collection that does not exist', async () => {424    await usingApi(async (api: ApiPromise) => {425      // nft426      const nftCollectionCount = await getCreatedCollectionCount(api);427      await approveExpectFail(nftCollectionCount + 1, 1, alice, bob);428      // fungible429      const fungibleCollectionCount = await getCreatedCollectionCount(api);430      await approveExpectFail(fungibleCollectionCount + 1, 0, alice, bob);431      // reFungible432      const reFungibleCollectionCount = await getCreatedCollectionCount(api);433      await approveExpectFail(reFungibleCollectionCount + 1, 1, alice, bob);434    });435  });436437  it('Approve for a collection that was destroyed', async () => {438    // nft439    const nftCollectionId = await createCollectionExpectSuccess();440    await destroyCollectionExpectSuccess(nftCollectionId);441    await approveExpectFail(nftCollectionId, 1, alice, bob);442    // fungible443    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});444    await destroyCollectionExpectSuccess(fungibleCollectionId);445    await approveExpectFail(fungibleCollectionId, 0, alice, bob);446    // reFungible447    const reFungibleCollectionId =448      await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});449    await destroyCollectionExpectSuccess(reFungibleCollectionId);450    await approveExpectFail(reFungibleCollectionId, 1, alice, bob);451  });452453  it('Approve transfer of a token that does not exist', async () => {454    // nft455    const nftCollectionId = await createCollectionExpectSuccess();456    await approveExpectFail(nftCollectionId, 2, alice, bob);457    // reFungible458    const reFungibleCollectionId =459      await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});460    await approveExpectFail(reFungibleCollectionId, 2, alice, bob);461  });462463  it('Approve using the address that does not own the approved token', async () => {464    const nftCollectionId = await createCollectionExpectSuccess();465    // nft466    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'NFT');467    await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice);468    // fungible469    const fungibleCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});470    const newFungibleTokenId = await createItemExpectSuccess(alice, fungibleCollectionId, 'Fungible');471    await approveExpectFail(fungibleCollectionId, newFungibleTokenId, bob, alice);472    // reFungible473    const reFungibleCollectionId =474      await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});475    const newReFungibleTokenId = await createItemExpectSuccess(alice, reFungibleCollectionId, 'ReFungible');476    await approveExpectFail(reFungibleCollectionId, newReFungibleTokenId, bob, alice);477  });478479  it('should fail if approved more ReFungibles than owned', async () => {480    const nftCollectionId = await createCollectionExpectSuccess({mode: {type: 'ReFungible'}});481    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'ReFungible');482    await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 100, 'ReFungible');483    await approveExpectSuccess(nftCollectionId, newNftTokenId, bob, alice.address, 100);484    await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice, 101);485  });486487  it('should fail if approved more Fungibles than owned', async () => {488    const nftCollectionId = await createCollectionExpectSuccess({mode: {type: 'Fungible', decimalPoints: 0}});489    const newNftTokenId = await createItemExpectSuccess(alice, nftCollectionId, 'Fungible');490    await transferExpectSuccess(nftCollectionId, newNftTokenId, alice, bob, 10, 'Fungible');491    await approveExpectSuccess(nftCollectionId, newNftTokenId, bob, alice.address, 10);492    await approveExpectFail(nftCollectionId, newNftTokenId, bob, alice, 11);493  });494495  it('fails when called by collection owner on non-owned item when OwnerCanTransfer == false', async () => {496    const collectionId = await createCollectionExpectSuccess();497    const itemId = await createItemExpectSuccess(alice, collectionId, 'NFT', bob.address);498    await setCollectionLimitsExpectSuccess(alice, collectionId, {ownerCanTransfer: false});499500    await approveExpectFail(collectionId, itemId, alice, charlie);501  });502});