git.delta.rocks / unique-network / refs/commits / 492b65108c16

difftreelog

Tests up

Maksandre2022-09-01parent: #d11ad96.patch.diff
in: master

4 files changed

modifiedtests/src/app-promotion.test.tsdiffbeforeafterboth
63});63});
6464
65describe('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);
7474
75 // 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 300
77 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 100
80 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 0
82 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
8687
87 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);
9899
99 // Can't stake full balance because Alice needs to pay some fee100 // Can't stake full balance because Alice needs to pay some fee
100 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);
102103
103 // 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});
124122
125describe('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);
130
131 // balance state still
132132
133 // 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);
141
142 // Wait for unstaking period. Balance now free ~600, and reserved, frozen, miscFrozeb 0n
143 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 });
143
144 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);
150
151 // Wait for unstaking period. Balance now free ~1000; reserved, frozen, miscFrozeb: 0n
152 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 });
148157
149 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 });
217
218 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 unlocked
225 expect.fail('Not implemented');
226 });
227 });
228226
229 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 });
382
383 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 existed
380 await expect(helper.signTransaction(palletAdmin, helper.api!.tx.promotion.sponsorCollection(999999999))).to.be.eventually.rejected;
381 // collection has been burned
386 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);
388384
406402
407 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');
413
414 // 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 });
418421
615});618});
616619
617describe('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 });
627
618 it('should credit 0.05% for staking period', async () => { 628 it('should credit 0.05% for staking period', async () => {
629 // TODO flaky test
619 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 637
627 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 });
631
632 it('can not be initialized by non admin', async () => {
633 await usingPlaygrounds(async (helper) => {
634 expect.fail('Test not implemented');
635 });
636 });
637642
638 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);
646
647 await helper.staking.stake(staker, 100n * nominal);
648 await helper.staking.stake(staker, 200n * nominal);
649
650 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));
655
656 const stakerFullBalance = await helper.balance.getSubstrateFull(staker.address);
657 const frozenBalanceShouldBe = calculateIncome(300n * nominal, 10n, 2);
658
640 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 test
651 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
modifiedtests/src/util/playgrounds/types.tsdiffbeforeafterboth
101 tokenId: number;101 tokenId: number;
102}102}
103
104export interface IBlock {
105 extrinsics: IExtrinsic[]
106 header: {
107 parentHash: string,
108 number: number,
109 };
110}
111
112export interface IExtrinsic {
113 isSigned: boolean,
114 method: {
115 method: string,
116 section: string,
117 args: any[]
118 }
119}
103120
104export interface ICollectionCreationOptions {121export interface ICollectionCreationOptions {
105 name: string | number[];122 name: string | number[];
modifiedtests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth

no syntactic changes

modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
9import {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';
1313
14const 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 }
1862
1863 // TODO add docs
1864 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 }
18621869
1863 /**1870 /**
1864 * Get account nonce1871 * Get account nonce