1234567891011121314151617import {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 73 74 75 76 77 78 79 80 81 82 83 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 109 110111 112 113114 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 127 128129 130 await usingPlaygrounds(async helper => {131 const crowd = await creteAccounts([10n, 10n, 10n, 10n], alice, helper);132 133 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 153 154155 156 157 158 159 160 });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};