git.delta.rocks / unique-network / refs/commits / 4d07c60d3d95

difftreelog

source

tests/src/app-promotion.test.ts8.2 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 {default as usingApi, submitTransactionAsync} from './substrate/substrate-api';18import {IKeyringPair, ITuple} from '@polkadot/types/types';19import {20  21  createMultipleItemsExpectSuccess,22  isTokenExists,23  getLastTokenId,24  getAllowance,25  approve,26  transferFrom,27  createCollection,28  transfer,29  burnItem,30  normalizeAccountId,31  CrossAccountId,32  createFungibleItemExpectSuccess,33  U128_MAX,34  burnFromExpectSuccess,35  UNIQUE,36  getModuleNames,37  Pallets,38  getBlockNumber,39} from './util/helpers';4041import chai, {use} from 'chai';42import chaiAsPromised from 'chai-as-promised';43import getBalance, {getBalanceSingle} from './substrate/get-balance';44import {unique} from './interfaces/definitions';45import {usingPlaygrounds} from './util/playgrounds';46import {default as waitNewBlocks} from './substrate/wait-new-blocks';4748import BN from 'bn.js';49import {mnemonicGenerate} from '@polkadot/util-crypto';50import {UniqueHelper} from './util/playgrounds/unique';51chai.use(chaiAsPromised);52const expect = chai.expect;5354let alice: IKeyringPair;55let bob: IKeyringPair;56let palletAdmin: IKeyringPair;57let nominal: bigint; 5859describe('integration test: AppPromotion', () => {60  before(async function() {61    await usingPlaygrounds(async (helper, privateKeyWrapper) => {62      if (!getModuleNames(helper.api!).includes(Pallets.AppPromotion)) this.skip();63      alice = privateKeyWrapper('//Alice');64      bob = privateKeyWrapper('//Bob');65      palletAdmin = privateKeyWrapper('//palletAdmin');66      const tx = helper.api!.tx.sudo.sudo(helper.api!.tx.promotion.setAdminAddress(palletAdmin.addressRaw));67      nominal = helper.balance.getOneTokenNominal();68      await submitTransactionAsync(alice, tx);69    });70  });71  it('will change balance state to "locked", add it to "staked" map, and increase "totalStaked" amount', async () => {72    // arrange: Alice balance = 100073    // act:     Alice calls appPromotion.stake(100)74    // assert:  Alice locked balance equal 10075    // assert:  Alice free balance closeTo 90076    // assert:  query appPromotion.staked(Alice) equal [100]77    // assert:  query appPromotion.totalStaked() increased by 10078    // act:     Alice extrinsic appPromotion.stake(200)79  80    // assert:  Alice locked balance equal 30081    // assert:  query appPromotion.staked(Alice) equal [100, 200]82    // assert:  query appPromotion.totalStaked() increased by 20083    84    await usingPlaygrounds(async (helper, privateKeyWrapper) => {85      const totalStakedBefore = (await helper.api!.rpc.unique.totalStaked()).toBigInt();86      const staker = await createUser();87   88      const firstStakedBlock = await helper.chain.getLatestBlockNumber();89      90      await expect(submitTransactionAsync(staker, helper.api!.tx.promotion.stake(1n * nominal))).to.be.eventually.fulfilled;91      expect((await helper.api!.rpc.unique.totalStakingLocked(normalizeAccountId(staker))).toBigInt()).to.be.equal(nominal);92      expect(9n * nominal - await helper.balance.getSubstrate(staker.address) <= nominal / 2n).to.be.true;93      expect((await helper.api!.rpc.unique.totalStaked(normalizeAccountId(staker))).toBigInt()).to.be.equal(nominal);94      expect((await helper.api!.rpc.unique.totalStaked()).toBigInt()).to.be.equal(totalStakedBefore + nominal);95      96      await waitNewBlocks(helper.api!, 1);97      const secondStakedBlock = await helper.chain.getLatestBlockNumber();98      99      await expect(submitTransactionAsync(staker, helper.api!.tx.promotion.stake(2n * nominal))).to.be.eventually.fulfilled;100      expect((await helper.api!.rpc.unique.totalStakingLocked(normalizeAccountId(staker))).toBigInt()).to.be.equal(3n * nominal);101      102      const stakedPerBlock = (await helper.api!.rpc.unique.totalStakedPerBlock(normalizeAccountId(staker))).map(([block, amount]) => [block.toBigInt(), amount.toBigInt()]);103      expect(stakedPerBlock.map((x) => x[1])).to.be.deep.equal([nominal, 2n * nominal]);104    });105  });106  107  it('will throws if stake amount is more than total free balance', async () => {108    // arrange: Alice balance = 1000109    // assert:  Alice calls appPromotion.stake(1000) throws /// because Alice needs some fee110111    // act:     Alice calls appPromotion.stake(700)112    // assert:  Alice calls appPromotion.stake(400) throws /// because Alice has ~300 free QTZ and 700 locked113114    await usingPlaygrounds(async helper => { 115      116      const staker = await createUser();117      118      await expect(submitTransactionAsync(staker, helper.api!.tx.promotion.stake(10n * nominal))).to.be.eventually.rejected;119      await expect(submitTransactionAsync(staker, helper.api!.tx.promotion.stake(7n * nominal))).to.be.eventually.fulfilled;120      await expect(submitTransactionAsync(staker, helper.api!.tx.promotion.stake(4n * nominal))).to.be.eventually.rejected;121      122    });123  });124  125  it.skip('for different accounts in one block is possible', async () => {126    // arrange: Alice, Bob, Charlie, Dave balance = 1000127    // arrange: Alice, Bob, Charlie, Dave calls appPromotion.stake(100) in the same time128129    // assert:  query appPromotion.staked(Alice/Bob/Charlie/Dave) equal [100]130    await usingPlaygrounds(async helper => {131      const crowd = await creteAccounts([10n, 10n, 10n, 10n], alice, helper);132      // const promises = crowd.map(async user => submitTransactionAsync(user, helper.api!.tx.promotion.stake(nominal)));133      // await expect(Promise.all(promises)).to.be.eventually.fulfilled;134    });135  });136137});138139describe.skip('unstake balance extrinsic', () => {140  before(async function() {141    await usingPlaygrounds(async (helper, privateKeyWrapper) => {142      if (!getModuleNames(helper.api!).includes(Pallets.AppPromotion)) this.skip();143      alice = privateKeyWrapper('//Alice');144      bob = privateKeyWrapper('//Bob');145      palletAdmin = privateKeyWrapper('//palletAdmin');146      const tx = helper.api!.tx.sudo.sudo(helper.api!.tx.promotion.setAdminAddress(palletAdmin.addressRaw));147      nominal = helper.balance.getOneTokenNominal();148      await submitTransactionAsync(alice, tx);149    });150  });151  it('will change balance state to "reserved", add it to "pendingUnstake" map, and subtract it from totalStaked', async () => {152    // arrange: Alice balance = 1000153    // arrange: Alice calls appPromotion.stake(Alice, 500)154155    // act:     Alice calls appPromotion.unstake(300)156    // assert:  Alice reserved balance to equal 300157    // assert:  query appPromotion.staked(Alice) equal [200] /// 500 - 300158    // assert:  query appPromotion.pendingUnstake(Alice) to equal [300]159    // assert:  query appPromotion.totalStaked() decreased by 300160  });161});162163164165async function createUser(amount?: bigint) {166  return await usingPlaygrounds(async (helper, privateKeyWrapper) => {167    const user: IKeyringPair = privateKeyWrapper(`//Alice+${(new Date()).getTime()}`);168    await helper.balance.transferToSubstrate(alice, user.address, amount ? amount : 10n * helper.balance.getOneTokenNominal());169    return user;170  });171}172173const creteAccounts = async (balances: bigint[], donor: IKeyringPair, helper: UniqueHelper) => {174  let nonce = await helper.chain.getNonce(donor.address);175  const tokenNominal = helper.balance.getOneTokenNominal();176  const transactions = [];177  const accounts = [];178  for (const balance of balances) {179    const recepient = helper.util.fromSeed(mnemonicGenerate());180    accounts.push(recepient);181    if (balance !== 0n){182      const tx = helper.constructApiCall('api.tx.balances.transfer', [{Id: recepient.address}, balance * tokenNominal]);183      transactions.push(helper.signTransaction(donor, tx, 'account generation', {nonce}));184      nonce++;185    }186  }187188  await Promise.all(transactions);189  return accounts;190};