difftreelog
Merge branch 'feature/app-staking' of https://github.com/UniqueNetwork/unique-chain into feature/app-staking
in: master
4 files changed
tests/src/addCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/addCollectionAdmin.test.ts
+++ b/tests/src/addCollectionAdmin.test.ts
@@ -33,7 +33,7 @@
describe('Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
it('Add collection admin.', async () => {
await usingPlaygrounds(async (helper) => {
- const [alice, bob] = await helper.arrange.creteAccounts([10n, 10n], donor);
+ const [alice, bob] = await helper.arrange.createAccounts([10n, 10n], donor);
const {collectionId} = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
const collection = await helper.collection.getData(collectionId);
@@ -50,7 +50,7 @@
describe('Negative Integration Test addCollectionAdmin(collection_id, new_admin_id):', () => {
it("Not owner can't add collection admin.", async () => {
await usingPlaygrounds(async (helper) => {
- const [alice, bob, charlie] = await helper.arrange.creteAccounts([10n, 10n, 10n], donor);
+ const [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
const {collectionId} = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
const collection = await helper.collection.getData(collectionId);
@@ -69,7 +69,7 @@
it("Admin can't add collection admin.", async () => {
await usingPlaygrounds(async (helper) => {
- const [alice, bob, charlie] = await helper.arrange.creteAccounts([10n, 10n, 10n], donor);
+ const [alice, bob, charlie] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
await collection.addAdmin(alice, {Substrate: bob.address});
@@ -88,7 +88,7 @@
it("Can't add collection admin of not existing collection.", async () => {
await usingPlaygrounds(async (helper) => {
- const [alice, bob] = await helper.arrange.creteAccounts([10n, 10n, 10n], donor);
+ const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
// tslint:disable-next-line: no-bitwise
const collectionId = (1 << 32) - 1;
@@ -102,7 +102,7 @@
it("Can't add an admin to a destroyed collection.", async () => {
await usingPlaygrounds(async (helper) => {
- const [alice, bob] = await helper.arrange.creteAccounts([10n, 10n, 10n], donor);
+ const [alice, bob] = await helper.arrange.createAccounts([10n, 10n, 10n], donor);
const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
await collection.burn(alice);
@@ -116,7 +116,7 @@
it('Add an admin to a collection that has reached the maximum number of admins limit', async () => {
await usingPlaygrounds(async (helper) => {
- const [alice, ...accounts] = await helper.arrange.creteAccounts([10n, 0n, 0n, 0n, 0n, 0n, 0n, 0n], donor);
+ const [alice, ...accounts] = await helper.arrange.createAccounts([10n, 0n, 0n, 0n, 0n, 0n, 0n, 0n], donor);
const collection = await helper.nft.mintCollection(alice, {name: 'Collection Name', description: 'Collection Description', tokenPrefix: 'COL'});
const chainAdminLimit = (helper.api!.consts.common.collectionAdminsLimit as any).toNumber();
tests/src/app-promotion.test.tsdiffbeforeafterboth--- a/tests/src/app-promotion.test.ts
+++ b/tests/src/app-promotion.test.ts
@@ -28,7 +28,7 @@
import {encodeAddress} from '@polkadot/util-crypto';
import {stringToU8a} from '@polkadot/util';
import {ApiPromise} from '@polkadot/api';
-import {contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3} from './eth/util/helpers';
+import {SponsoringMode, contractHelpers, createEthAccountWithBalance, deployFlipper, itWeb3, transferBalanceToEth} from './eth/util/helpers';
chai.use(chaiAsPromised);
const expect = chai.expect;
@@ -66,7 +66,7 @@
it('should change balance state to "locked", add it to "staked" map, and increase "totalStaked" amount', async () => {
await usingPlaygrounds(async (helper) => {
const totalStakedBefore = await helper.staking.getTotalStaked();
- const [staker] = await helper.arrange.creteAccounts([400n], alice);
+ const [staker] = await helper.arrange.createAccounts([400n], alice);
// Minimum stake amount is 100:
await expect(helper.staking.stake(staker, 100n * nominal - 1n)).to.be.eventually.rejected;
@@ -89,7 +89,7 @@
it('should reject transaction if stake amount is more than total free balance', async () => {
await usingPlaygrounds(async helper => {
- const [staker] = await helper.arrange.creteAccounts([300n], alice);
+ const [staker] = await helper.arrange.createAccounts([300n], alice);
// Can't stake full balance because Alice needs to pay some fee
await expect(helper.staking.stake(staker, 300n * nominal)).to.be.eventually.rejected;
@@ -103,7 +103,7 @@
it('for different accounts in one block is possible', async () => {
await usingPlaygrounds(async helper => {
- const crowd = await helper.arrange.creteAccounts([1000n, 1000n, 1000n, 1000n], alice);
+ const crowd = await helper.arrange.createAccounts([1000n, 1000n, 1000n, 1000n], alice);
const crowdStartsToStake = crowd.map(user => helper.staking.stake(user, 100n * nominal));
await expect(Promise.all(crowdStartsToStake)).to.be.eventually.fulfilled;
@@ -121,7 +121,7 @@
it('should change balance state to "reserved", add it to "pendingUnstake" map, and subtract it from totalStaked', async () => {
await usingPlaygrounds(async helper => {
const totalStakedBefore = await helper.staking.getTotalStaked();
- const [staker] = await helper.arrange.creteAccounts([1000n], alice);
+ const [staker] = await helper.arrange.createAccounts([1000n], alice);
await helper.staking.stake(staker, 500n * nominal);
await helper.staking.unstake(staker);
@@ -133,7 +133,7 @@
it('should remove multiple stakes', async () => {
await usingPlaygrounds(async helper => {
- const [staker] = await helper.arrange.creteAccounts([1000n], alice);
+ const [staker] = await helper.arrange.createAccounts([1000n], alice);
await helper.staking.stake(staker, 100n * nominal);
await helper.staking.stake(staker, 200n * nominal);
await helper.staking.stake(staker, 300n * nominal);
@@ -159,7 +159,7 @@
it('should not have any effects if no active stakes', async () => {
await usingPlaygrounds(async (helper) => {
- const [staker] = await helper.arrange.creteAccounts([1000n], alice);
+ const [staker] = await helper.arrange.createAccounts([1000n], alice);
// unstake has no effect if no stakes at all
await helper.staking.unstake(staker);
@@ -182,30 +182,31 @@
it('should keep different unlocking block for each unlocking stake', async () => {
await usingPlaygrounds(async (helper) => {
- const [staker] = await helper.arrange.creteAccounts([1000n], alice);
+ const [staker] = await helper.arrange.createAccounts([1000n], alice);
await helper.staking.stake(staker, 100n * nominal);
await helper.staking.unstake(staker);
- await helper.staking.stake(staker, 100n * nominal);
+ await helper.staking.stake(staker, 120n * nominal);
await helper.staking.unstake(staker);
- expect.fail('Not implemented');
+
+ const unstakingPerBlock = await helper.staking.getPendingUnstakePerBlock({Substrate: staker.address});
+ expect(unstakingPerBlock).has.length(2);
+ expect(unstakingPerBlock[0][1]).to.equal(100n * nominal);
+ expect(unstakingPerBlock[1][1]).to.equal(120n * nominal);
});
});
it('should unlock balance after unlocking period ends and subtract it from "pendingUnstake"', async () => {
await usingPlaygrounds(async (helper) => {
- const [staker] = await helper.arrange.creteAccounts([1000n], alice);
+ const [staker] = await helper.arrange.createAccounts([1000n], alice);
await helper.staking.stake(staker, 100n * nominal);
await helper.staking.unstake(staker);
- // get unstake from block
- // wait it
- // check balance returned
expect.fail('Not implemented');
});
});
it('should be possible for different accounts in one block', async () => {
await usingPlaygrounds(async (helper) => {
- const stakers = await helper.arrange.creteAccounts([200n, 200n, 200n, 200n, 200n], alice);
+ const stakers = await helper.arrange.createAccounts([200n, 200n, 200n, 200n, 200n], alice);
await Promise.all(stakers.map(staker => helper.staking.stake(staker, 100n * nominal)));
await Promise.all(stakers.map(staker => helper.staking.unstake(staker)));
@@ -236,7 +237,7 @@
// We are not going to set an eth address as a sponsor,
// but we do want to check, it doesn't break anything;
await usingPlaygrounds(async (helper) => {
- const [charlie] = await helper.arrange.creteAccounts([10n], alice);
+ const [charlie] = await helper.arrange.createAccounts([10n], alice);
const ethCharlie = helper.address.substrateToEth(charlie.address);
// Alice sets Ethereum address as a sudo. Then Substrate address back...
await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.promotion.setAdminAddress({Ethereum: ethCharlie})))).to.be.eventually.fulfilled;
@@ -250,7 +251,7 @@
it('can be reassigned', async () => {
await usingPlaygrounds(async (helper) => {
- const [oldAdmin, newAdmin, collectionOwner] = await helper.arrange.creteAccounts([10n, 10n, 10n], alice);
+ const [oldAdmin, newAdmin, collectionOwner] = await helper.arrange.createAccounts([10n, 10n, 10n], alice);
const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
await expect(helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.promotion.setAdminAddress(normalizeAccountId(oldAdmin))))).to.be.eventually.fulfilled;
@@ -269,10 +270,28 @@
await helper.signTransaction(alice, tx);
});
});
-
+
+ it('should actually sponsor transactions', async () => {
+ await usingPlaygrounds(async (helper) => {
+ const [collectionOwner, tokenSender, receiver] = await helper.arrange.createAccounts([10n, 10n, 0n], alice);
+ const collection = await helper.nft.mintCollection(collectionOwner, {name: 'Name', description: 'Description', tokenPrefix: 'Prefix', limits: {sponsorTransferTimeout: 0}});
+ const token = await collection.mintToken(collectionOwner, {Substrate: tokenSender.address});
+ await helper.signTransaction(palletAdmin, helper.api!.tx.promotion.sponsorCollection(collection.collectionId));
+ const palletBalanceBefore = await helper.balance.getSubstrate(palletAddress);
+
+ await token.transfer(tokenSender, {Substrate: receiver.address});
+ expect (await token.getOwner()).to.be.deep.equal({Substrate: receiver.address});
+ const palletBalanceAfter = await helper.balance.getSubstrate(palletAddress);
+
+ // senders balance the same
+ expect (await helper.balance.getSubstrate(tokenSender.address)).to.be.equal(10n * nominal);
+ expect (palletBalanceBefore > palletBalanceAfter).to.be.true;
+ });
+ });
+
it('can not be set by non admin', async () => {
await usingPlaygrounds(async (helper) => {
- const [collectionOwner, nonAdmin] = await helper.arrange.creteAccounts([10n, 10n], alice);
+ const [collectionOwner, nonAdmin] = await helper.arrange.createAccounts([10n, 10n], alice);
const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
@@ -283,7 +302,7 @@
it('should set pallet address as confirmed admin', async () => {
await usingPlaygrounds(async (helper) => {
- const [collectionOwner, oldSponsor] = await helper.arrange.creteAccounts([20n, 20n], alice);
+ const [collectionOwner, oldSponsor] = await helper.arrange.createAccounts([20n, 20n], alice);
// Can set sponsoring for collection without sponsor
const collectionWithoutSponsor = await helper.nft.mintCollection(collectionOwner, {name: 'No-sponsor', description: 'New Collection', tokenPrefix: 'Promotion'});
@@ -306,7 +325,7 @@
it('can be overwritten by collection owner', async () => {
await usingPlaygrounds(async (helper) => {
- const [collectionOwner, newSponsor] = await helper.arrange.creteAccounts([20n, 0n], alice);
+ const [collectionOwner, newSponsor] = await helper.arrange.createAccounts([20n, 0n], alice);
const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
const collectionId = collection.collectionId;
@@ -341,7 +360,7 @@
it('should reject transaction if collection was burnt', async () => {
await usingPlaygrounds(async (helper) => {
- const [collectionOwner] = await helper.arrange.creteAccounts([10n], alice);
+ const [collectionOwner] = await helper.arrange.createAccounts([10n], alice);
const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
await collection.burn(collectionOwner);
@@ -353,7 +372,7 @@
describe('app-promotion stopSponsoringCollection', () => {
it('can not be called by non-admin', async () => {
await usingPlaygrounds(async (helper) => {
- const [collectionOwner, nonAdmin] = await helper.arrange.creteAccounts([10n, 10n], alice);
+ const [collectionOwner, nonAdmin] = await helper.arrange.createAccounts([10n, 10n], alice);
const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
await expect(helper.signTransaction(palletAdmin, helper.api!.tx.promotion.sponsorCollection(collection.collectionId))).to.be.eventually.fulfilled;
@@ -365,7 +384,7 @@
it('should set sponsoring as disabled', async () => {
await usingPlaygrounds(async (helper) => {
- const [collectionOwner] = await helper.arrange.creteAccounts([10n, 10n], alice);
+ const [collectionOwner] = await helper.arrange.createAccounts([10n, 10n], alice);
const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
await expect(helper.signTransaction(palletAdmin, helper.api!.tx.promotion.sponsorCollection(collection.collectionId))).to.be.eventually.fulfilled;
@@ -377,7 +396,7 @@
it('should not affect collection which is not sponsored by pallete', async () => {
await usingPlaygrounds(async (helper) => {
- const [collectionOwner] = await helper.arrange.creteAccounts([10n, 10n], alice);
+ const [collectionOwner] = await helper.arrange.createAccounts([10n, 10n], alice);
const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion', pendingSponsor: collectionOwner.address});
await collection.confirmSponsorship(collectionOwner);
@@ -389,7 +408,7 @@
it('should reject transaction if collection does not exist', async () => {
await usingPlaygrounds(async (helper) => {
- const [collectionOwner] = await helper.arrange.creteAccounts([10n], alice);
+ const [collectionOwner] = await helper.arrange.createAccounts([10n], alice);
const collection = await helper.nft.mintCollection(collectionOwner, {name: 'New', description: 'New Collection', tokenPrefix: 'Promotion'});
await collection.burn(collectionOwner);
@@ -471,7 +490,7 @@
itWeb3('can not be set by non admin', async ({api, web3, privateKeyWrapper}) => {
await usingPlaygrounds(async (helper) => {
- const [nonAdmin] = await helper.arrange.creteAccounts([50n], alice);
+ const [nonAdmin] = await helper.arrange.createAccounts([50n], alice);
const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
const flipper = await deployFlipper(web3, contractOwner);
const contractMethods = contractHelpers(web3, contractOwner);
@@ -488,88 +507,95 @@
},
});
});
- });
- it('will return unused gas fee to app-promotion pallete', async () => {
- // TODO
- // arrange: Alice deploys Flipper
- // arrange: Admin calls appPromotion.sponsorContract(Flipper.address)
+ itWeb3('should be rejected for non-contract address', async ({api, web3, privateKeyWrapper}) => {
+ await usingPlaygrounds(async (helper) => {
- // assert: Bob calls Flipper - expect balances deposit event do not appears for Bob /// Unused gas fee returns to contract
- // assert: Bobs balance the same
+ });
+ });
});
- it('will failed for non contract address', async () => {
- // arrange: web3 creates new address - 0x0
+ itWeb3('should actually sponsor transactions', async ({api, web3, privateKeyWrapper}) => {
+ await usingPlaygrounds(async (helper) => {
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+ const flipper = await deployFlipper(web3, contractOwner);
+ const contractHelper = contractHelpers(web3, contractOwner);
+ await contractHelper.methods.setSponsoringRateLimit(flipper.options.address, 0).send({from: contractOwner});
+ await contractHelper.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: contractOwner});
+ await transferBalanceToEth(api, alice, flipper.options.address, 1000n);
- // assert: Admin calls appPromotion.sponsorContract(0x0) throws
- // assert: Admin calls appPromotion.sponsorContract(Substrate address) throws
- });
+ await helper.signTransaction(palletAdmin, api.tx.promotion.sponsorConract(flipper.options.address));
+ await flipper.methods.flip().send({from: caller});
+ expect(await flipper.methods.getValue().call()).to.be.true;
- it('will actually sponsor transactions', async () => {
- // TODO test it because this is a new way of contract sponsoring
- });
-});
+ const callerBalance = await helper.balance.getEthereum(caller);
+ const contractBalanceAfter = await helper.balance.getEthereum(flipper.options.address);
-describe('app-promotion stopSponsoringContract', () => {
- before(async function () {
- await usingPlaygrounds(async (helper, privateKeyWrapper) => {
- if (!getModuleNames(helper.api!).includes(Pallets.AppPromotion)) this.skip();
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- palletAdmin = privateKeyWrapper('//palletAdmin');
- await helper.balance.transferToSubstrate(alice, palletAdmin.address, 10n * helper.balance.getOneTokenNominal());
- await helper.balance.transferToSubstrate(alice, palletAddress, 10n * helper.balance.getOneTokenNominal());
-
- const tx = helper.api!.tx.sudo.sudo(helper.api!.tx.promotion.setAdminAddress(normalizeAccountId(palletAdmin)));
- await helper.signTransaction(alice, tx);
-
- nominal = helper.balance.getOneTokenNominal();
+ expect(callerBalance).to.be.equal(1000n * nominal);
+ expect(1000n * nominal > contractBalanceAfter).to.be.true;
});
});
-
- it('will set contract sponsoring mode as disabled', async () => {
- // arrange: Alice deploys Flipper
- // arrange: Admin calls appPromotion.sponsorContract(Flipper.address)
-
- // act: Admin calls appPromotion.stopSponsoringContract(Flipper.address)
- // assert: contract sponsoring mode = TODO
+});
- // act: Bob calls Flipper
+describe('app-promotion stopSponsoringContract', () => {
+ itWeb3('should remove pallet address from contract sponsors', async ({api, web3, privateKeyWrapper}) => {
+ await usingPlaygrounds(async (helper) => {
+ const caller = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+ const flipper = await deployFlipper(web3, contractOwner);
+ await transferBalanceToEth(api, alice, flipper.options.address);
+ const contractHelper = contractHelpers(web3, contractOwner);
+ await contractHelper.methods.setSponsoringMode(flipper.options.address, SponsoringMode.Generous).send({from: contractOwner});
+ await helper.signTransaction(palletAdmin, api.tx.promotion.sponsorConract(flipper.options.address));
+ await helper.signTransaction(palletAdmin, api.tx.promotion.stopSponsoringContract(flipper.options.address));
- // assert: PalleteAddress balance did not change
- // assert: Bobs balance less than before /// Bob payed some fee
- });
+ expect(await contractHelper.methods.hasSponsor(flipper.options.address).call()).to.be.false;
+ expect((await api.query.evmContractHelpers.owner(flipper.options.address)).toJSON()).to.be.equal(contractOwner);
+ expect((await api.query.evmContractHelpers.sponsoring(flipper.options.address)).toJSON()).to.deep.equal({
+ disabled: null,
+ });
+
+ await flipper.methods.flip().send({from: caller});
+ expect(await flipper.methods.getValue().call()).to.be.true;
- it('can not be called by non-admin', async () => {
- // arrange: Alice deploys Flipper
- // arrange: Admin calls appPromotion.sponsorContract(Flipper.address)
+ const callerBalance = await helper.balance.getEthereum(caller);
+ const contractBalanceAfter = await helper.balance.getEthereum(flipper.options.address);
- // assert: Random calls appPromotion.stopSponsoringContract(Flipper.address) throws
- // assert: contract sponsor is PallereAddress
+ // caller payed for call
+ expect(1000n * nominal > callerBalance).to.be.true;
+ expect(contractBalanceAfter).to.be.equal(1000n * nominal);
+ });
});
- it('will not affect a contract which is not sponsored by pallete', async () => {
- // arrange: Alice deploys Flipper
- // arrange: Alice sets self sponsoring for Flipper
-
- // act: Admin calls appPromotion.stopSponsoringContract(Flipper.address) throws
+ itWeb3('can not be called by non-admin', async ({api, web3, privateKeyWrapper}) => {
+ await usingPlaygrounds(async (helper) => {
+ const [nonAdmin] = await helper.arrange.createAccounts([10n], alice);
+ const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+ const flipper = await deployFlipper(web3, contractOwner);
- // assert: contract.sponsoringMode = Self
- // assert: contract.sponsor to be contract
+ await helper.signTransaction(palletAdmin, api.tx.promotion.sponsorConract(flipper.options.address));
+ await expect(helper.signTransaction(nonAdmin, api.tx.promotion.stopSponsoringContract(flipper.options.address))).to.be.rejected;
+ });
});
- it('will failed for non contract address', async () => {
- // arrange: web3 creates new address - 0x0
+ itWeb3('should not affect a contract which is not sponsored by pallete', async ({api, web3, privateKeyWrapper}) => {
+ await usingPlaygrounds(async (helper) => {
+ const [nonAdmin] = await helper.arrange.createAccounts([10n], alice);
+ const contractOwner = (await createEthAccountWithBalance(api, web3, privateKeyWrapper)).toLowerCase();
+ const flipper = await deployFlipper(web3, contractOwner);
+ const contractHelper = contractHelpers(web3, contractOwner);
+ await expect(contractHelper.methods.selfSponsoredEnable(flipper.options.address).send()).to.be.not.rejected;
- // expect stopSponsoringContract(0x0) throws
+ await expect(helper.signTransaction(nonAdmin, api.tx.promotion.stopSponsoringContract(flipper.options.address))).to.be.rejected;
+ });
});
});
describe('app-promotion rewards', () => {
it('should credit 0.05% for staking period', async () => {
await usingPlaygrounds(async helper => {
- const [staker] = await helper.arrange.creteAccounts([5000n], alice);
+ const [staker] = await helper.arrange.createAccounts([5000n], alice);
await helper.staking.stake(staker, 100n * nominal);
await helper.staking.stake(staker, 200n * nominal);
@@ -580,6 +606,18 @@
expect(totalStakedPerBlock).to.be.deep.equal([calculateIncome(100n * nominal, 10n), calculateIncome(200n * nominal, 10n)]);
});
});
+
+ it('can not be initialized by non admin', async () => {
+ await usingPlaygrounds(async (helper) => {
+ expect.fail('Test not implemented');
+ });
+ });
+
+ it('shoud be paid for more than one period if payments was missed', async () => {
+ await usingPlaygrounds(async (helper) => {
+ expect.fail('Test not implemented');
+ });
+ });
it('should not be credited for unstaked (reserved) balance', async () => {
await usingPlaygrounds(async helper => {
@@ -589,7 +627,7 @@
it('should bring compound interest', async () => {
await usingPlaygrounds(async helper => {
- const [staker] = await helper.arrange.creteAccounts([800n], alice);
+ const [staker] = await helper.arrange.createAccounts([800n], alice);
await helper.staking.stake(staker, 100n * nominal);
await helper.staking.stake(staker, 200n * nominal);
@@ -607,7 +645,24 @@
});
});
- // TODO (load test. Can pay reward for 10000 addresses)
+ it.skip('can handle 40.000 rewards', async () => {
+ await usingPlaygrounds(async (helper) => {
+ const [donor] = await helper.arrange.createAccounts([7_000_000n], alice);
+ const crowdStakes = async () => {
+ // each account in the crowd stakes 2 times
+ const crowd = await helper.arrange.createCrowd(500, 300n, donor);
+ await Promise.all(crowd.map(account => helper.staking.stake(account, 100n * nominal)));
+ await Promise.all(crowd.map(account => helper.staking.stake(account, 100n * nominal)));
+ //
+ };
+
+ for (let i = 0; i < 40; i++) {
+ await crowdStakes();
+ }
+
+ // TODO pay rewards for some period
+ });
+ });
});
async function waitForRelayBlock(api: ApiPromise, blocks = 1): Promise<void> {
tests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -27,6 +27,7 @@
const alice = privateKey('//Alice');
const bob = privateKey('//Bob');
const collection = await helper.nft.mintCollection(alice, {name: 'test', description: 'test', tokenPrefix: 'test'});
+
const collectionInfo = await collection.getData();
expect(collectionInfo?.raw.owner.toString()).to.be.deep.eq(alice.address);
// first - add collection admin Bob
tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// SPDX-License-Identifier: Apache-2.034import {mnemonicGenerate} from '@polkadot/util-crypto';5import {UniqueHelper} from './unique';6import {ApiPromise, WsProvider} from '@polkadot/api';7import * as defs from '../../interfaces/definitions';8import {TSigner} from './types';9import {IKeyringPair} from '@polkadot/types/types';101112export class DevUniqueHelper extends UniqueHelper {13 /**14 * Arrange methods for tests15 */16 arrange: ArrangeGroup;1718 constructor(logger: { log: (msg: any, level: any) => void, level: any }) {19 super(logger);20 this.arrange = new ArrangeGroup(this);21 }2223 async connect(wsEndpoint: string, listeners?: any): Promise<void> {24 const wsProvider = new WsProvider(wsEndpoint);25 this.api = new ApiPromise({26 provider: wsProvider,27 signedExtensions: {28 ContractHelpers: {29 extrinsic: {},30 payload: {},31 },32 FakeTransactionFinalizer: {33 extrinsic: {},34 payload: {},35 },36 },37 rpc: {38 unique: defs.unique.rpc,39 rmrk: defs.rmrk.rpc,40 eth: {41 feeHistory: {42 description: 'Dummy',43 params: [],44 type: 'u8',45 },46 maxPriorityFeePerGas: {47 description: 'Dummy',48 params: [],49 type: 'u8',50 },51 },52 },53 });54 await this.api.isReadyOrError;55 this.network = await UniqueHelper.detectNetwork(this.api);56 }57}5859class ArrangeGroup {60 helper: UniqueHelper;6162 constructor(helper: UniqueHelper) {63 this.helper = helper;64 }6566 /**67 * Generates accounts with the specified UNQ token balance 68 * @param balances balances for generated accounts. Each balance will be multiplied by the token nominal.69 * @param donor donor account for balances70 * @returns array of newly created accounts71 * @example const [acc1, acc2, acc3] = await createAccounts([0n, 10n, 20n], donor); 72 */73 creteAccounts = async (balances: bigint[], donor: IKeyringPair): Promise<IKeyringPair[]> => {74 let nonce = await this.helper.chain.getNonce(donor.address);75 const tokenNominal = this.helper.balance.getOneTokenNominal();76 const transactions = [];77 const accounts: IKeyringPair[] = [];78 for (const balance of balances) {79 const recepient = this.helper.util.fromSeed(mnemonicGenerate());80 accounts.push(recepient);81 if (balance !== 0n) {82 const tx = this.helper.constructApiCall('api.tx.balances.transfer', [{Id: recepient.address}, balance * tokenNominal]);83 transactions.push(this.helper.signTransaction(donor, tx, 'account generation', {nonce}));84 nonce++;85 }86 }8788 await Promise.all(transactions).catch(e => {});89 90 //#region TODO remove this region, when nonce problem will be solved91 const checkBalances = async () => {92 let isSuccess = true;93 for (let i = 0; i < balances.length; i++) {94 const balance = await this.helper.balance.getSubstrate(accounts[i].address);95 if (balance !== balances[i] * tokenNominal) {96 isSuccess = false;97 break;98 }99 }100 return isSuccess;101 };102103 let accountsCreated = false;104 // checkBalances retry up to 5 blocks105 for (let index = 0; index < 5; index++) {106 console.log(await this.helper.chain.getLatestBlockNumber());107 accountsCreated = await checkBalances();108 if(accountsCreated) break;109 await this.waitNewBlocks(1);110 }111112 if (!accountsCreated) throw Error('Accounts generation failed');113 //#endregion114115 return accounts;116 };117118 /**119 * Wait for specified bnumber of blocks120 * @param blocksCount number of blocks to wait121 * @returns 122 */123 async waitNewBlocks(blocksCount = 1): Promise<void> {124 const promise = new Promise<void>(async (resolve) => {125 const unsubscribe = await this.helper.api!.rpc.chain.subscribeNewHeads(() => {126 if (blocksCount > 0) {127 blocksCount--;128 } else {129 unsubscribe();130 resolve();131 }132 });133 });134 return promise;135 }136}