123456import chai from 'chai';7import chaiAsPromised from 'chai-as-promised';8import { default as usingApi, submitTransactionAsync, submitTransactionExpectFailAsync } from "./substrate/substrate-api";9import { alicesPublicKey, bobsPublicKey } from "./accounts";10import privateKey from "./substrate/privateKey";11import { BigNumber } from 'bignumber.js';12import { IKeyringPair } from '@polkadot/types/types';13import { 14 createCollectionExpectSuccess, 15 createItemExpectSuccess,16 getGenericResult,17 transferExpectSuccess18} from './util/helpers';1920import { default as waitNewBlocks } from './substrate/wait-new-blocks';21import { ApiPromise } from '@polkadot/api';2223chai.use(chaiAsPromised);24const expect = chai.expect;2526const Treasury = "5EYCAe5ijiYfyeZ2JJCGq56LmPyNRAKzpG4QkoQkkQNB5e6Z";27const saneMinimumFee = 0.05;28const saneMaximumFee = 0.5;29const createCollectionDeposit = 100;3031let alice: IKeyringPair;32let bob: IKeyringPair;33343536function skipInflationBlock(api: ApiPromise): Promise<void> {37 const promise = new Promise<void>(async (resolve, reject) => {38 const blockInterval = parseInt((await api.consts.inflation.inflationBlockInterval).toString());39 const unsubscribe = await api.rpc.chain.subscribeNewHeads(head => {40 const currentBlock = parseInt(head.number.toString());41 if (currentBlock % blockInterval < blockInterval - 10) {42 unsubscribe();43 resolve();44 } else {45 console.log(`Skipping inflation block, current block: ${currentBlock}`);46 }47 });48 });4950 return promise;51}5253describe('integration test: Fees must be credited to Treasury:', () => {54 before(async () => {55 await usingApi(async (api) => {56 alice = privateKey('//Alice');57 bob = privateKey('//Bob');58 });59 });6061 it('Total issuance does not change', async () => {62 await usingApi(async (api) => {63 await skipInflationBlock(api);64 await waitNewBlocks(api, 1);6566 const totalBefore = new BigNumber((await api.query.balances.totalIssuance()).toString());6768 const alicePrivateKey = privateKey('//Alice');69 const amount = new BigNumber(1);70 const transfer = api.tx.balances.transfer(bobsPublicKey, amount.toFixed());7172 const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));7374 const totalAfter = new BigNumber((await api.query.balances.totalIssuance()).toString());7576 expect(result.success).to.be.true;77 expect(totalAfter.toFixed()).to.be.equal(totalBefore.toFixed());78 });79 });8081 it('Sender balance decreased by fee+sent amount, Treasury balance increased by fee', async () => {82 await usingApi(async (api) => {83 await skipInflationBlock(api);84 await waitNewBlocks(api, 1);8586 const alicePrivateKey = privateKey('//Alice');87 const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());88 const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());8990 const amount = new BigNumber(1);91 const transfer = api.tx.balances.transfer(bobsPublicKey, amount.toFixed());92 const result = getGenericResult(await submitTransactionAsync(alicePrivateKey, transfer));9394 const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());95 const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());96 const fee = aliceBalanceBefore.minus(aliceBalanceAfter).minus(amount);97 const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);9899 expect(result.success).to.be.true;100 expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());101 });102 });103104 it('Treasury balance increased by failed tx fee', async () => {105 await usingApi(async (api) => {106 await skipInflationBlock(api);107 await waitNewBlocks(api, 1);108109 const bobPrivateKey = privateKey('//Bob');110 const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());111 const bobBalanceBefore = new BigNumber((await api.query.system.account(bobsPublicKey)).data.free.toString());112113 const badTx = api.tx.balances.setBalance(alicesPublicKey, 0, 0);114 await expect(submitTransactionExpectFailAsync(bobPrivateKey, badTx)).to.be.rejected;115116 const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());117 const bobBalanceAfter = new BigNumber((await api.query.system.account(bobsPublicKey)).data.free.toString());118 const fee = bobBalanceBefore.minus(bobBalanceAfter);119 const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);120121 expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());122 });123 });124125 it('NFT Transactions also send fees to Treasury', async () => {126 await usingApi(async (api) => {127 await skipInflationBlock(api);128 await waitNewBlocks(api, 1);129130 const treasuryBalanceBefore = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());131 const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());132133 await createCollectionExpectSuccess();134135 const treasuryBalanceAfter = new BigNumber((await api.query.system.account(Treasury)).data.free.toString());136 const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());137 const fee = aliceBalanceBefore.minus(aliceBalanceAfter);138 const treasuryIncrease = treasuryBalanceAfter.minus(treasuryBalanceBefore);139140 expect(treasuryIncrease.toFixed()).to.be.equal(fee.toFixed());141 });142 });143144 it('Fees are sane', async () => {145 await usingApi(async (api) => {146 await skipInflationBlock(api);147 await waitNewBlocks(api, 1);148149 const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());150151 await createCollectionExpectSuccess();152153 const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());154 const fee = aliceBalanceBefore.minus(aliceBalanceAfter);155156 expect(fee.dividedBy(1e15).toNumber()).to.be.lessThan(saneMaximumFee + createCollectionDeposit);157 expect(fee.dividedBy(1e15).toNumber()).to.be.greaterThan(saneMinimumFee + createCollectionDeposit);158 });159 });160161 it('NFT Transfer fee is close to 0.1 Unique', async () => {162 await usingApi(async (api) => {163 await skipInflationBlock(api);164 await waitNewBlocks(api, 1);165166 const collectionId = await createCollectionExpectSuccess();167 const tokenId = await createItemExpectSuccess(alice, collectionId, 'NFT');168169 const aliceBalanceBefore = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());170 await transferExpectSuccess(collectionId, tokenId, alice, bob, 1, 'NFT');171 const aliceBalanceAfter = new BigNumber((await api.query.system.account(alicesPublicKey)).data.free.toString());172 const fee = aliceBalanceBefore.minus(aliceBalanceAfter);173174 175 const expectedTransferFee = 0.1;176 const tolerance = 0.001;177 expect(fee.dividedBy(1e15).minus(expectedTransferFee).abs().toNumber()).to.be.lessThan(tolerance);178 });179 });180181});182