difftreelog
Tests up
in: master
4 files changed
tests/src/app-promotion.test.tsdiffbeforeafterboth63});63});646465describe('app-promotions.stake extrinsic', () => {65describe('app-promotions.stake extrinsic', () => {66 it('should "lock" some balance in system.account, add it to "staked" map, and increase "totalStaked" amount', async () => {66 it('should "lock" staking balance, add it to "staked" map, and increase "totalStaked" amount', async () => {67 await usingPlaygrounds(async (helper) => {67 await usingPlaygrounds(async (helper) => {68 const totalStakedBefore = await helper.staking.getTotalStaked();68 const totalStakedBefore = await helper.staking.getTotalStaked();69 const [staker, recepient] = await helper.arrange.createAccounts([400n, 0n], alice);69 const [staker, recepient] = await helper.arrange.createAccounts([400n, 0n], alice);72 await expect(helper.staking.stake(staker, 100n * nominal - 1n)).to.be.eventually.rejected;72 await expect(helper.staking.stake(staker, 100n * nominal - 1n)).to.be.eventually.rejected;73 await helper.staking.stake(staker, 100n * nominal);73 await helper.staking.stake(staker, 100n * nominal);747475 // Staker balance is: miscFrozen: 100, feeFrozen: 100, reserved: 0n, free less than 300...75 // Staker balance is: miscFrozen: 100, feeFrozen: 100, reserved: 0n...76 // ...so he can not transfer 30076 // ...so he can not transfer 30077 expect (await helper.balance.getSubstrateFull(staker.address)).to.contain({miscFrozen: 100n * nominal, feeFrozen: 100n * nominal, reserved: 0n});77 expect (await helper.balance.getSubstrateFull(staker.address)).to.contain({miscFrozen: 100n * nominal, feeFrozen: 100n * nominal, reserved: 0n});78 await expect(helper.balance.transferToSubstrate(staker, recepient.address, 300n * nominal)).to.be.rejected;78 await expect(helper.balance.transferToSubstrate(staker, recepient.address, 300n * nominal)).to.be.rejected;79 79 80 // 100 -> 24 locked 100; staked 0; 24 => locked 100 staked 10080 expect(await helper.staking.getTotalStakingLocked({Substrate: staker.address})).to.be.equal(100n * nominal);81 expect(await helper.staking.getTotalStakingLocked({Substrate: staker.address})).to.be.equal(100n * nominal);81 // TODO add helpers to assert bigints. Check balance close to 10082 // TODO should be 082 expect(await helper.balance.getSubstrate(staker.address) - 99n * nominal >= (nominal / 2n)).to.be.true;83 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(100n * nominal);83 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(100n * nominal);84 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(399n);84 // it is potentially flaky test. Promotion can credited some tokens. Maybe we need to use closeTo? 85 // it is potentially flaky test. Promotion can credited some tokens. Maybe we need to use closeTo? 85 expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore + 100n * nominal); // total tokens amount staked in app-promotion increased 86 expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore + 100n * nominal); // total tokens amount staked in app-promotion increased 868787 await helper.staking.stake(staker, 200n * nominal);88 await helper.staking.stake(staker, 200n * nominal);89 88 expect(await helper.staking.getTotalStakingLocked({Substrate: staker.address})).to.be.equal(300n * nominal);90 expect(await helper.staking.getTotalStakingLocked({Substrate: staker.address})).to.be.equal(300n * nominal);89 90 const stakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map((x) => x[1]);91 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(300n * nominal);91 expect(stakedPerBlock).to.be.deep.equal([100n * nominal, 200n * nominal]);92 expect((await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map((x) => x[1])).to.be.deep.equal([100n * nominal, 200n * nominal]);92 });93 });93 });94 });94 95 95 it('should reject transaction if stake amount is more than total free balance', async () => {96 it('should reject transaction if stake amount is more than total free balance minus frozen', async () => {96 await usingPlaygrounds(async helper => { 97 await usingPlaygrounds(async helper => { 97 const [staker] = await helper.arrange.createAccounts([300n], alice);98 const [staker] = await helper.arrange.createAccounts([300n], alice);989999 // Can't stake full balance because Alice needs to pay some fee100 // Can't stake full balance because Alice needs to pay some fee100 await expect(helper.staking.stake(staker, 300n * nominal)).to.be.eventually.rejected;101 await expect(helper.staking.stake(staker, 300n * nominal)).to.be.eventually.rejected;101 await helper.staking.stake(staker, 150n * nominal);102 await helper.staking.stake(staker, 150n * nominal);102103103 // Can't stake 4 tkn because Alice has ~3 free tkn, and 7 locked104 // Can't stake 150 tkn because Alice has Less than 150 free - frozen tokens;104 await expect(helper.staking.stake(staker, 150n * nominal)).to.be.eventually.rejected; 105 await expect(helper.staking.stake(staker, 150n * nominal)).to.be.eventually.rejected; 105 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(150n * nominal);106 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(150n * nominal);106 });107 });117 expect(crowdStakes).to.deep.equal([100n * nominal, 100n * nominal, 100n * nominal, 100n * nominal]);118 expect(crowdStakes).to.deep.equal([100n * nominal, 100n * nominal, 100n * nominal, 100n * nominal]);118 });119 });119 });120 });120 // TODO it('Staker stakes 5 times in one block with nonce');121 // TODO it('Staked balance appears as locked in the balance pallet');122 // TODO it('Alice stakes huge amount of tokens');123});121});124122125describe('unstake balance extrinsic', () => { 123describe('unstake balance extrinsic', () => { 130 await helper.staking.stake(staker, 500n * nominal);128 await helper.staking.stake(staker, 500n * nominal);131 await helper.staking.unstake(staker);129 await helper.staking.unstake(staker);130131 // balance state still132132133 // Stakers balance now: {free: <100n, reserved: 500n, miscFrozen: 0, feeFrozen: 0};133 // Stakers balance now: {free: <100n, reserved: 500n, miscFrozen: 0, feeFrozen: 0};134 // Staker can not transfer 134 // Staker can not transfer 139 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n);139 expect(await helper.staking.getTotalStaked({Substrate: staker.address})).to.be.equal(0n);140 expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore);140 expect(await helper.staking.getTotalStaked()).to.be.equal(totalStakedBefore);141142 // Wait for unstaking period. Balance now free ~600, and reserved, frozen, miscFrozeb 0n143 await waitForRelayBlock(helper.api!, 20);144 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n * nominal, miscFrozen: 0n, feeFrozen: 0n});145 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(599n);146 });141 });147 });142 });143144 it('should unlock balance after unlocking period ends and subtract it from "pendingUnstake"', async () => {145 await usingPlaygrounds(async (helper) => {146 const [staker] = await helper.arrange.createAccounts([1000n], alice);147 await helper.staking.stake(staker, 100n * nominal);148 await helper.staking.unstake(staker);149 await waitForRelayBlock(helper.api!, 20);150151 // Wait for unstaking period. Balance now free ~1000; reserved, frozen, miscFrozeb: 0n152 await waitForRelayBlock(helper.api!, 20);153 expect(await helper.balance.getSubstrateFull(staker.address)).to.deep.contain({reserved: 0n * nominal, miscFrozen: 0n, feeFrozen: 0n});154 expect(await helper.balance.getSubstrate(staker.address) / nominal).to.be.equal(999n);155 });156 });148157149 it('should successfully unstake multiple stakes', async () => {158 it('should successfully unstake multiple stakes', async () => {150 await usingPlaygrounds(async helper => {159 await usingPlaygrounds(async helper => {215 });224 });216 });225 });217218 it('should unlock balance after unlocking period ends and subtract it from "pendingUnstake"', async () => {219 await usingPlaygrounds(async (helper) => {220 const [staker] = await helper.arrange.createAccounts([1000n], alice);221 await helper.staking.stake(staker, 100n * nominal);222 await helper.staking.unstake(staker);223 await waitForRelayBlock(helper.api!, 20);224 // expect balance unlocked225 expect.fail('Not implemented');226 });227 });228226229 it('should be possible for different accounts in one block', async () => {227 it('should be possible for different accounts in one block', async () => {230 await usingPlaygrounds(async (helper) => {228 await usingPlaygrounds(async (helper) => {374 });372 });375 });373 });376 374 377 it('should reject transaction if collection doesn\'t exist', async () => {378 await usingPlaygrounds(async (helper) => {379 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.promotion.sponsorCollection(999999999))).to.be.eventually.rejected;380 });381 });382383 it('should reject transaction if collection was burnt', async () => {375 it('should reject transaction if collection doesn\'t exist', async () => {384 await usingPlaygrounds(async (helper) => {376 await usingPlaygrounds(async (helper) => {385 const [collectionOwner] = await helper.arrange.createAccounts([10n], alice);377 const [collectionOwner] = await helper.arrange.createAccounts([10n], alice);378 379 // collection has never existed380 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.promotion.sponsorCollection(999999999))).to.be.eventually.rejected;381 // collection has been burned386 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});382 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});387 await collection.burn(collectionOwner);383 await collection.burn(collectionOwner);388384406402407 it('should set sponsoring as disabled', async () => {403 it('should set sponsoring as disabled', async () => {408 await usingPlaygrounds(async (helper) => {404 await usingPlaygrounds(async (helper) => {409 const [collectionOwner] = await helper.arrange.createAccounts([10n, 10n], alice);405 const [collectionOwner, recepient] = await helper.arrange.createAccounts([10n, 0n], alice);410 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});406 const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', limits: {sponsorTransferTimeout: 0}});411 407 const token = await collection.mintToken(collectionOwner, {Substrate: collectionOwner.address});408 412 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.promotion.sponsorCollection(collection.collectionId))).to.be.eventually.fulfilled;409 await helper.signTransaction(palletAdmin, helper.api!.tx.promotion.sponsorCollection(collection.collectionId));413 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.promotion.stopSponsoringCollection(collection.collectionId))).to.be.eventually.fulfilled;410 await helper.signTransaction(palletAdmin, helper.api!.tx.promotion.stopSponsoringCollection(collection.collectionId));414 411 415 expect((await collection.getData())?.raw.sponsorship).to.be.equal('Disabled');412 expect((await collection.getData())?.raw.sponsorship).to.be.equal('Disabled');413414 // Transactions are not sponsored anymore:415 const ownerBalanceBefore = await helper.balance.getSubstrate(collectionOwner.address);416 await token.transfer(collectionOwner, {Substrate: recepient.address});417 const ownerBalanceAfter = await helper.balance.getSubstrate(collectionOwner.address);418 expect(ownerBalanceAfter < ownerBalanceBefore).to.be.equal(true);416 });419 });417 });420 });418421615});618});616619617describe('app-promotion rewards', () => {620describe('app-promotion rewards', () => {621 it('can not be called by non admin', async () => {622 await usingPlaygrounds(async (helper) => {623 const [nonAdmin] = await helper.arrange.createAccounts([10n], alice);624 await expect(helper.signTransaction(nonAdmin, helper.api!.tx.promotion.payoutStakers(50))).to.be.rejected;625 });626 });627618 it('should credit 0.05% for staking period', async () => { 628 it('should credit 0.05% for staking period', async () => { 629 // TODO flaky test619 await usingPlaygrounds(async helper => {630 await usingPlaygrounds(async helper => {620 const [staker] = await helper.arrange.createAccounts([5000n], alice);631 const [staker] = await helper.arrange.createAccounts([5000n], alice);621 632 622 await helper.staking.stake(staker, 100n * nominal);633 await helper.staking.stake(staker, 100n * nominal);623 await helper.staking.stake(staker, 200n * nominal);634 await helper.staking.stake(staker, 200n * nominal);624 await waitForRelayBlock(helper.api!, 40);635 await waitForRelayBlock(helper.api!, 30);625 await helper.signTransaction(palletAdmin, helper.api!.tx.promotion.payoutStakers(50));636 await helper.signTransaction(palletAdmin, helper.api!.tx.promotion.payoutStakers(50));626 637627 const totalStakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(s => s[1]);638 const totalStakedPerBlock = (await helper.staking.getTotalStakedPerBlock({Substrate: staker.address})).map(s => s[1]);628 expect(totalStakedPerBlock).to.be.deep.equal([calculateIncome(100n * nominal, 10n), calculateIncome(200n * nominal, 10n)]);639 expect(totalStakedPerBlock).to.be.deep.equal([calculateIncome(100n * nominal, 10n), calculateIncome(200n * nominal, 10n)]);629 });640 });630 });641 });631632 it('can not be initialized by non admin', async () => {633 await usingPlaygrounds(async (helper) => {634 expect.fail('Test not implemented');635 });636 });637642638 it('shoud be paid for more than one period if payments was missed', async () => {643 it('shoud be paid for more than one period if payments was missed', async () => {639 await usingPlaygrounds(async (helper) => {644 await usingPlaygrounds(async (helper) => {645 const [staker] = await helper.arrange.createAccounts([400n], alice);646647 await helper.staking.stake(staker, 100n * nominal);648 await helper.staking.stake(staker, 200n * nominal);649650 await waitForRelayBlock(helper.api!, 55);651 await helper.signTransaction(palletAdmin, helper.api!.tx.promotion.payoutStakers(50));652 const stakedPerBlock = await helper.staking.getTotalStakedPerBlock({Substrate: staker.address});653 expect(stakedPerBlock[0][1]).to.be.equal(calculateIncome(100n * nominal, 10n, 2));654 expect(stakedPerBlock[1][1]).to.be.equal(calculateIncome(200n * nominal, 10n, 2));655656 const stakerFullBalance = await helper.balance.getSubstrateFull(staker.address);657 const frozenBalanceShouldBe = calculateIncome(300n * nominal, 10n, 2);658640 expect.fail('Test not implemented');659 expect(stakerFullBalance).to.contain({reserved: 0n, feeFrozen: frozenBalanceShouldBe, miscFrozen: frozenBalanceShouldBe});641 });660 });642 });661 });643 662 644 it('should not be credited for unstaked (reserved) balance', async () => {663 it('should not be credited for unstaked (reserved) balance', async () => {664 expect.fail('Test not implemented');645 await usingPlaygrounds(async helper => {665 await usingPlaygrounds(async helper => {646 expect.fail('Implement me after unstake method will be fixed');666 const staker = await helper.arrange.createAccounts([1000n], alice);647 });667 });648 });668 });649 669 650 it('should bring compound interest', async () => {670 it('should bring compound interest', async () => {671 // TODO flaky test651 await usingPlaygrounds(async helper => {672 await usingPlaygrounds(async helper => {652 const [staker] = await helper.arrange.createAccounts([800n], alice);673 const [staker] = await helper.arrange.createAccounts([800n], alice);653 674 tests/src/util/playgrounds/types.tsdiffbeforeafterboth101 tokenId: number;101 tokenId: number;102}102}103104export interface IBlock {105 extrinsics: IExtrinsic[]106 header: {107 parentHash: string,108 number: number,109 };110}111112export interface IExtrinsic {113 isSigned: boolean,114 method: {115 method: string,116 section: string,117 args: any[]118 }119}103120104export interface ICollectionCreationOptions {121export interface ICollectionCreationOptions {105 name: string | number[];122 name: string | number[];tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterbothno syntactic changes
tests/src/util/playgrounds/unique.tsdiffbeforeafterboth9import {ApiInterfaceEvents} from '@polkadot/api/types';9import {ApiInterfaceEvents} from '@polkadot/api/types';10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';11import {IKeyringPair} from '@polkadot/types/types';11import {IKeyringPair} from '@polkadot/types/types';12import {IApiListeners, IChainEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types';12import {IApiListeners, IBlock, IChainEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, TUniqueNetworks} from './types';131314const crossAccountIdFromLower = (lowerAddress: ICrossAccountIdLower): ICrossAccountId => {14const crossAccountIdFromLower = (lowerAddress: ICrossAccountIdLower): ICrossAccountId => {15 const address = {} as ICrossAccountId;15 const address = {} as ICrossAccountId;1860 return blockHash;1860 return blockHash;1861 }1861 }18621863 // TODO add docs1864 async getBlock(blockHashOrNumber: string | number): Promise<IBlock | null> {1865 const blockHash = typeof blockHashOrNumber === 'string' ? blockHashOrNumber : await this.getBlockHashByNumber(blockHashOrNumber);1866 if (!blockHash) return null;1867 return (await this.helper.callRpc('api.rpc.chain.getBlock', [blockHash])).toHuman().block;1868 }186218691863 /**1870 /**1864 * Get account nonce1871 * Get account nonce