diff --git a/.eslintrc.test.js b/.eslintrc.test.js index 8f16527a65f..d9f83ef85ad 100644 --- a/.eslintrc.test.js +++ b/.eslintrc.test.js @@ -3,7 +3,6 @@ module.exports = { rules: { 'arrow-body-style': 'off', 'dot-notation': 'off', - '@typescript-eslint/unbound-method': 'off', '@typescript-eslint/no-magic-numbers': 'off', '@typescript-eslint/unbound-method': 'off', '@typescript-eslint/no-require-imports': 'off', diff --git a/elements/lisk-chain/.eslintignore b/elements/lisk-chain/.eslintignore new file mode 100644 index 00000000000..18f63c615af --- /dev/null +++ b/elements/lisk-chain/.eslintignore @@ -0,0 +1,2 @@ +dist-node +jest.config.js diff --git a/elements/lisk-chain/.eslintrc.js b/elements/lisk-chain/.eslintrc.js new file mode 100644 index 00000000000..8b7fd410b8d --- /dev/null +++ b/elements/lisk-chain/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: '../../.eslintrc.js', + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, +}; diff --git a/elements/lisk-chain/package.json b/elements/lisk-chain/package.json index 6c3e02ee92e..5e69cde1293 100644 --- a/elements/lisk-chain/package.json +++ b/elements/lisk-chain/package.json @@ -24,8 +24,8 @@ "scripts": { "clean": "./scripts/clean.sh", "format": "prettier --write '**/*'", - "lint": "tslint --format verbose --project .", - "lint:fix": "npm run lint -- --fix", + "lint": "eslint . --ext .js,.ts", + "lint:fix": "eslint --fix --ext .js,.ts .", "test": "jest", "test:watch": "npm test -- --watch", "prebuild": "rm -r dist-node/* || mkdir dist-node || true", @@ -50,6 +50,13 @@ "@types/lodash.clonedeep": "4.5.6", "@types/lodash.isequal": "4.5.5", "@types/randomstring": "1.1.6", + "@typescript-eslint/eslint-plugin": "2.28.0", + "@typescript-eslint/parser": "2.28.0", + "eslint": "6.8.0", + "eslint-config-lisk-base": "1.2.2", + "eslint-config-prettier": "6.10.0", + "eslint-plugin-import": "2.20.1", + "eslint-plugin-jest": "23.8.2", "faker": "4.1.0", "jest": "25.1.0", "jest-extended": "0.11.5", @@ -61,9 +68,6 @@ "ts-jest": "25.2.1", "ts-node": "8.6.2", "tsconfig-paths": "3.9.0", - "tslint": "6.0.0", - "tslint-config-prettier": "1.18.0", - "tslint-immutable": "6.0.1", "typescript": "3.8.3" } } diff --git a/elements/lisk-chain/src/account.ts b/elements/lisk-chain/src/account.ts index 259eaf695a2..3e0551cafc0 100644 --- a/elements/lisk-chain/src/account.ts +++ b/elements/lisk-chain/src/account.ts @@ -11,6 +11,7 @@ * * Removal or modification of this copyright notice is prohibited. */ +// eslint-disable-next-line import/no-cycle import { AccountJSON } from './types'; export const accountDefaultValues = { @@ -109,6 +110,7 @@ export class Account { unvoteHeight: unlock.unvoteHeight, })) : []; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition this.totalVotesReceived = BigInt(accountInfo.totalVotesReceived ?? 0); this.delegate = { lastForgedHeight: accountInfo.delegate?.lastForgedHeight ?? 0, @@ -126,7 +128,7 @@ export class Account { optionalKeys: accountInfo.keys?.optionalKeys?.length ? [...accountInfo.keys.optionalKeys] : [], - numberOfSignatures: accountInfo.keys?.numberOfSignatures || 0, + numberOfSignatures: accountInfo.keys?.numberOfSignatures ?? 0, }; // TODO: Remove with https://github.com/LiskHQ/lisk-sdk/issues/5058 diff --git a/elements/lisk-chain/src/block_reward.ts b/elements/lisk-chain/src/block_reward.ts index 79b41fe8088..0a86af9eedc 100644 --- a/elements/lisk-chain/src/block_reward.ts +++ b/elements/lisk-chain/src/block_reward.ts @@ -117,10 +117,10 @@ export const calculateSupply = ( } } - // tslint:disable-next-line prefer-for-of no-let + // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < rewards.length; i += 1) { const reward = rewards[i]; - supply = supply + BigInt(reward[0]) * BigInt(reward[1]); + supply += BigInt(reward[0]) * BigInt(reward[1]); } return supply; @@ -131,7 +131,7 @@ export const getTotalFees = ( ): { readonly totalFee: bigint; readonly totalMinFee: bigint } => blockInstance.transactions.reduce( (prev, current) => { - const minFee = current.minFee; + const { minFee } = current; return { totalFee: prev.totalFee + current.fee, @@ -165,7 +165,7 @@ export const applyFeeAndRewards = async ( generator.balance += givenFee > 0 ? givenFee : BigInt(0); const totalFeeBurntStr = await stateStore.chain.get(CHAIN_STATE_BURNT_FEE); // tslint:disable-next-line no-let - let totalFeeBurnt = BigInt(totalFeeBurntStr || 0); + let totalFeeBurnt = BigInt(totalFeeBurntStr ?? 0); totalFeeBurnt += givenFee > 0 ? totalMinFee : BigInt(0); // Update state store @@ -194,7 +194,7 @@ export const undoFeeAndRewards = async ( generator.balance -= totalFee - totalMinFee; const totalFeeBurntStr = await stateStore.chain.get(CHAIN_STATE_BURNT_FEE); // tslint:disable-next-line no-let - let totalFeeBurnt = BigInt(totalFeeBurntStr || 0); + let totalFeeBurnt = BigInt(totalFeeBurntStr ?? 0); totalFeeBurnt -= totalMinFee; // Update state store diff --git a/elements/lisk-chain/src/chain.ts b/elements/lisk-chain/src/chain.ts index 3e7e01440f1..b28346d62a7 100644 --- a/elements/lisk-chain/src/chain.ts +++ b/elements/lisk-chain/src/chain.ts @@ -105,6 +105,7 @@ const saveBlock = async ( blockJSON: BlockJSON, tx: StorageTransaction, ): Promise => { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (!tx) { throw new Error('Block should only be saved in a database tx'); } @@ -123,7 +124,7 @@ const saveBlock = async ( const applyConfirmedStep = async ( blockInstance: BlockInstance, stateStore: StateStore, -) => { +): Promise => { if (blockInstance.transactions.length <= 0) { return; } @@ -181,6 +182,7 @@ const undoConfirmedStep = async ( } }; +// eslint-disable-next-line new-cap const debug = Debug('lisk:chain'); export class Chain { @@ -248,10 +250,12 @@ export class Chain { totalAmount, }; this.blockReward = { - calculateMilestone: height => + calculateMilestone: (height: number): number => calculateMilestone(height, this.blockRewardArgs), - calculateReward: height => calculateReward(height, this.blockRewardArgs), - calculateSupply: height => calculateSupply(height, this.blockRewardArgs), + calculateReward: (height: number): bigint => + calculateReward(height, this.blockRewardArgs), + calculateSupply: (height: number): bigint => + calculateSupply(height, this.blockRewardArgs), }; this.constants = { stateBlockSize, @@ -325,7 +329,7 @@ export class Chain { this.dataAccess.resetBlockHeaderCache(); } - public async newStateStore(skipLastHeights: number = 0): Promise { + public async newStateStore(skipLastHeights = 0): Promise { const fromHeight = Math.max( 1, this._lastBlock.height - this.constants.stateBlockSize - skipLastHeights, @@ -337,6 +341,7 @@ export class Chain { ); const lastBlockReward = this.blockReward.calculateReward( + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition lastBlockHeaders[0]?.height ?? 1, ); @@ -347,34 +352,6 @@ export class Chain { }); } - private async _cacheBlockHeaders( - storageLastBlock: BlockInstance, - ): Promise { - // Cache the block headers (size=DEFAULT_MAX_BLOCK_HEADER_CACHE) - const fromHeight = Math.max( - storageLastBlock.height - DEFAULT_MAX_BLOCK_HEADER_CACHE, - 1, - ); - const toHeight = storageLastBlock.height; - - debug( - { h: storageLastBlock.height, fromHeight, toHeight }, - 'Cache block headers during chain init', - ); - const blockHeaders = await this.dataAccess.getBlockHeadersByHeightBetween( - fromHeight, - toHeight, - ); - const sortedBlockHeaders = [...blockHeaders].sort( - (a: BlockHeader, b: BlockHeader) => a.height - b.height, - ); - - for (const blockHeader of sortedBlockHeaders) { - debug({ height: blockHeader.height }, 'Add block header to cache'); - this.dataAccess.addBlockHeader(blockHeader); - } - } - public validateBlockHeader(block: BlockInstance, blockBytes: Buffer): void { validatePreviousBlockProperty(block, this.genesisBlock); validateSignature(block, blockBytes, this._networkIdentifier); @@ -394,6 +371,7 @@ export class Chain { validatePayload(block, this.constants.maxPayloadLength); // Update id + // eslint-disable-next-line no-param-reassign block.id = blocksUtils.getId(blockBytes); } @@ -426,7 +404,7 @@ export class Chain { await this.blocksVerify.checkTransactions(blockInstance); } - // tslint:disable-next-line prefer-function-over-method + // eslint-disable-next-line class-methods-use-this public async apply( blockInstance: BlockInstance, stateStore: StateStore, @@ -435,7 +413,7 @@ export class Chain { await applyFeeAndRewards(blockInstance, stateStore); } - // tslint:disable-next-line prefer-function-over-method + // eslint-disable-next-line class-methods-use-this public async applyGenesis( blockInstance: BlockInstance, stateStore: StateStore, @@ -475,7 +453,7 @@ export class Chain { }); } - // tslint:disable-next-line prefer-function-over-method + // eslint-disable-next-line class-methods-use-this public async undo( blockInstance: BlockInstance, stateStore: StateStore, @@ -484,26 +462,6 @@ export class Chain { await undoConfirmedStep(blockInstance, stateStore); } - private async _deleteLastBlock( - lastBlock: BlockInstance, - tx?: StorageTransaction, - ): Promise { - if (lastBlock.height === 1) { - throw new Error('Cannot delete genesis block'); - } - const block = await this.dataAccess.getBlockByID( - lastBlock.previousBlockId as string, - ); - - if (!block) { - throw new Error('PreviousBlock is null'); - } - - await this.storage.entities.Block.delete({ id: lastBlock.id }, {}, tx); - - return block; - } - public async remove( block: BlockInstance, stateStore: StateStore, @@ -641,7 +599,7 @@ export class Chain { } // Temporally added because DPoS uses totalEarning to calculate the vote weight change - // tslint:disable-next-line prefer-function-over-method + // eslint-disable-next-line class-methods-use-this public getTotalEarningAndBurnt( blockInstance: BlockInstance, ): { readonly totalEarning: bigint; readonly totalBurnt: bigint } { @@ -652,4 +610,52 @@ export class Chain { totalBurnt: totalMinFee, }; } + + private async _cacheBlockHeaders( + storageLastBlock: BlockInstance, + ): Promise { + // Cache the block headers (size=DEFAULT_MAX_BLOCK_HEADER_CACHE) + const fromHeight = Math.max( + storageLastBlock.height - DEFAULT_MAX_BLOCK_HEADER_CACHE, + 1, + ); + const toHeight = storageLastBlock.height; + + debug( + { h: storageLastBlock.height, fromHeight, toHeight }, + 'Cache block headers during chain init', + ); + const blockHeaders = await this.dataAccess.getBlockHeadersByHeightBetween( + fromHeight, + toHeight, + ); + const sortedBlockHeaders = [...blockHeaders].sort( + (a: BlockHeader, b: BlockHeader) => a.height - b.height, + ); + + for (const blockHeader of sortedBlockHeaders) { + debug({ height: blockHeader.height }, 'Add block header to cache'); + this.dataAccess.addBlockHeader(blockHeader); + } + } + + private async _deleteLastBlock( + lastBlock: BlockInstance, + tx?: StorageTransaction, + ): Promise { + if (lastBlock.height === 1) { + throw new Error('Cannot delete genesis block'); + } + const block = await this.dataAccess.getBlockByID( + lastBlock.previousBlockId as string, + ); + + if (!block) { + throw new Error('PreviousBlock is null'); + } + + await this.storage.entities.Block.delete({ id: lastBlock.id }, {}, tx); + + return block; + } } diff --git a/elements/lisk-chain/src/data_access/cache/base.ts b/elements/lisk-chain/src/data_access/cache/base.ts index 46f51829987..7ff6259934b 100644 --- a/elements/lisk-chain/src/data_access/cache/base.ts +++ b/elements/lisk-chain/src/data_access/cache/base.ts @@ -49,8 +49,6 @@ export abstract class Base { return this.items[this.length - 1]; } - public abstract add(item: T): T[]; - public empty(): T[] { this._items = []; @@ -64,4 +62,6 @@ export abstract class Base { public get needsRefill(): boolean { return this._needsRefill; } + + public abstract add(item: T): T[]; } diff --git a/elements/lisk-chain/src/data_access/cache/block.ts b/elements/lisk-chain/src/data_access/cache/block.ts index 5ca5c231514..bb5077b4833 100644 --- a/elements/lisk-chain/src/data_access/cache/block.ts +++ b/elements/lisk-chain/src/data_access/cache/block.ts @@ -26,11 +26,13 @@ export class BlockCache extends Base { if (this.items.length) { assert( blockHeader.height === this.last.height + 1, - `Block header with height ${this.last.height + - 1} can only be added, instead received height ${blockHeader.height}`, + `Block header with height ${( + this.last.height + 1 + ).toString()} can only be added, instead received height ${blockHeader.height.toString()}`, ); } + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (this.first && blockHeader.height === this.last.height + 1) { this.items.push(blockHeader); } else { diff --git a/elements/lisk-chain/src/data_access/data_access.ts b/elements/lisk-chain/src/data_access/data_access.ts index 1b2f42dea2e..69d54cd8d0b 100644 --- a/elements/lisk-chain/src/data_access/data_access.ts +++ b/elements/lisk-chain/src/data_access/data_access.ts @@ -72,6 +72,7 @@ export class DataAccess { // Get the height limits to fetch // The method getBlocksByHeightBetween uses gte & lte so we need to adjust values + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const upperHeightToFetch = this._blocksCache.items[0]?.height - 1 || 0; const lowerHeightToFetch = Math.max( @@ -130,6 +131,7 @@ export class DataAccess { } const block = await this._storage.getBlockByHeight(height); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition return block ? this.deserializeBlockHeader(block) : undefined; } @@ -171,6 +173,7 @@ export class DataAccess { public async getLastBlockHeader(): Promise { const cachedBlock = this._blocksCache.last; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (cachedBlock) { return cachedBlock; } @@ -186,12 +189,14 @@ export class DataAccess { const blocks = this._blocksCache.getByIDs(arrayOfBlockIds); const cachedBlock = blocks[blocks.length - 1]; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (cachedBlock) { return cachedBlock; } const block = await this._storage.getLastCommonBlockHeader(arrayOfBlockIds); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition return block ? this.deserializeBlockHeader(block) : undefined; } @@ -208,6 +213,7 @@ export class DataAccess { public async getBlockByID(id: string): Promise { const blockJSON = await this._storage.getBlockByID(id); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition return blockJSON ? this.deserialize(blockJSON) : undefined; } @@ -224,6 +230,7 @@ export class DataAccess { ): Promise { const block = await this._storage.getBlockByHeight(height); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition return block ? this.deserialize(block) : undefined; } @@ -241,7 +248,7 @@ export class DataAccess { public async getBlocksWithLimitAndOffset( limit: number, - offset: number = 0, + offset = 0, ): Promise { // Calculate toHeight const toHeight = offset + limit; @@ -261,6 +268,7 @@ export class DataAccess { public async getLastBlock(): Promise { const block = await this._storage.getLastBlock(); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition return block && this.deserialize(block); } @@ -288,8 +296,8 @@ export class DataAccess { return isEmpty; } - public clearTempBlocks(): void { - this._storage.clearTempBlocks(); + public async clearTempBlocks(): Promise { + await this._storage.clearTempBlocks(); } /** End: Blocks */ @@ -380,20 +388,24 @@ export class DataAccess { public deserialize(blockJSON: BlockJSON): BlockInstance { const transactions = + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition blockJSON.transactions?.map(transaction => this._transactionAdapter.fromJSON(transaction), ) ?? []; return { ...blockJSON, + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition totalAmount: BigInt(blockJSON.totalAmount || 0), + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition totalFee: BigInt(blockJSON.totalFee || 0), + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition reward: BigInt(blockJSON.reward || 0), transactions, }; } - // tslint:disable-next-line:prefer-function-over-method + // eslint-disable-next-line class-methods-use-this public serializeBlockHeader(blockHeader: BlockHeader): BlockHeaderJSON { return { ...blockHeader, @@ -403,12 +415,15 @@ export class DataAccess { }; } - // tslint:disable-next-line:prefer-function-over-method + // eslint-disable-next-line class-methods-use-this public deserializeBlockHeader(blockHeader: BlockHeaderJSON): BlockHeader { return { ...blockHeader, + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition totalAmount: BigInt(blockHeader.totalAmount || 0), + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition totalFee: BigInt(blockHeader.totalFee || 0), + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition reward: BigInt(blockHeader.reward || 0), }; } diff --git a/elements/lisk-chain/src/data_access/storage.ts b/elements/lisk-chain/src/data_access/storage.ts index 32222461b21..aa2079688a6 100644 --- a/elements/lisk-chain/src/data_access/storage.ts +++ b/elements/lisk-chain/src/data_access/storage.ts @@ -42,6 +42,7 @@ export class Storage { arrayOfBlockIds: ReadonlyArray, ): Promise { const blocks = await this._storage.entities.Block.get( + // eslint-disable-next-line camelcase { id_in: arrayOfBlockIds }, { limit: arrayOfBlockIds.length }, ); @@ -60,8 +61,8 @@ export class Storage { toHeight: number, ): Promise { const blocks = await this._storage.entities.Block.get( + // eslint-disable-next-line camelcase { height_gte: fromHeight, height_lte: toHeight }, - // tslint:disable-next-line:no-null-keyword { limit: null, sort: 'height:desc' }, ); @@ -73,6 +74,7 @@ export class Storage { ): Promise { const blocks = await this._storage.entities.Block.get( { + // eslint-disable-next-line camelcase height_in: heightList, }, { @@ -98,6 +100,7 @@ export class Storage { ): Promise { const [block] = await this._storage.entities.Block.get( { + // eslint-disable-next-line camelcase id_in: arrayOfBlockIds, }, { sort: 'height:desc', limit: 1 }, @@ -129,6 +132,7 @@ export class Storage { arrayOfBlockIds: ReadonlyArray, ): Promise { const blocks = await this._storage.entities.Block.get( + // eslint-disable-next-line camelcase { id_in: arrayOfBlockIds }, { extended: true }, ); @@ -150,8 +154,8 @@ export class Storage { toHeight: number, ): Promise { const blocks = await this._storage.entities.Block.get( + // eslint-disable-next-line camelcase { height_gte: fromHeight, height_lte: toHeight }, - // tslint:disable-next-line no-null-keyword { extended: true, limit: null, sort: 'height:desc' }, ); @@ -183,14 +187,15 @@ export class Storage { return isEmpty; } - public clearTempBlocks(): void { - this._storage.entities.TempBlock.truncate(); + public async clearTempBlocks(): Promise { + await this._storage.entities.TempBlock.truncate(); } public async deleteBlocksWithHeightGreaterThan( height: number, ): Promise { await this._storage.entities.Block.delete({ + // eslint-disable-next-line camelcase height_gt: height, }); } @@ -228,6 +233,7 @@ export class Storage { arrayOfPublicKeys: ReadonlyArray, ): Promise { const accounts = await this._storage.entities.Account.get( + // eslint-disable-next-line camelcase { publicKey_in: arrayOfPublicKeys }, { limit: arrayOfPublicKeys.length }, ); @@ -248,6 +254,7 @@ export class Storage { arrayOfAddresses: ReadonlyArray, ): Promise { const accounts = await this._storage.entities.Account.get( + // eslint-disable-next-line camelcase { address_in: arrayOfAddresses }, { limit: arrayOfAddresses.length }, ); @@ -278,6 +285,7 @@ export class Storage { ): Promise { const transactions = await this._storage.entities.Transaction.get( { + // eslint-disable-next-line camelcase id_in: arrayOfTransactionIds, }, { limit: arrayOfTransactionIds.length }, diff --git a/elements/lisk-chain/src/data_access/transaction_interface_adapter.ts b/elements/lisk-chain/src/data_access/transaction_interface_adapter.ts index 1ff08f8499b..1ade74697bb 100644 --- a/elements/lisk-chain/src/data_access/transaction_interface_adapter.ts +++ b/elements/lisk-chain/src/data_access/transaction_interface_adapter.ts @@ -18,10 +18,11 @@ export interface RegisteredTransactions { } export class TransactionInterfaceAdapter { - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any private readonly _transactionClassMap: Map; public constructor(registeredTransactions: RegisteredTransactions = {}) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment this._transactionClassMap = new Map(); Object.keys(registeredTransactions).forEach(transactionType => { this._transactionClassMap.set( @@ -32,13 +33,14 @@ export class TransactionInterfaceAdapter { } public fromJSON(rawTx: TransactionJSON): BaseTransaction { - // tslint:disable-next-line variable-name + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const TransactionClass = this._transactionClassMap.get(rawTx.type); if (!TransactionClass) { throw new Error('Transaction type not found.'); } + // eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-call return new TransactionClass({ ...rawTx, }); diff --git a/elements/lisk-chain/src/index.ts b/elements/lisk-chain/src/index.ts index 22b642a6e24..788db82935e 100644 --- a/elements/lisk-chain/src/index.ts +++ b/elements/lisk-chain/src/index.ts @@ -13,6 +13,7 @@ */ import { Chain } from './chain'; import { EVENT_DELETE_BLOCK, EVENT_NEW_BLOCK } from './constants'; + const events = { EVENT_DELETE_BLOCK, EVENT_NEW_BLOCK }; export { Account } from './account'; diff --git a/elements/lisk-chain/src/state_store/account_store.ts b/elements/lisk-chain/src/state_store/account_store.ts index eb6b5bea522..a39ebfff6bb 100644 --- a/elements/lisk-chain/src/state_store/account_store.ts +++ b/elements/lisk-chain/src/state_store/account_store.ts @@ -11,11 +11,6 @@ * * Removal or modification of this copyright notice is prohibited. */ -// tslint:disable-next-line no-require-imports -import cloneDeep = require('lodash.clonedeep'); -// tslint:disable-next-line no-require-imports -import isEqual = require('lodash.isequal'); - import { Account } from '../account'; import { AccountJSON, @@ -26,6 +21,11 @@ import { } from '../types'; import { uniqBy } from '../utils'; +// eslint-disable-next-line @typescript-eslint/no-require-imports +import cloneDeep = require('lodash.clonedeep'); +// eslint-disable-next-line @typescript-eslint/no-require-imports +import isEqual = require('lodash.isequal'); + export class AccountStore { private readonly _account: StorageEntity; private _data: Account[]; @@ -46,7 +46,6 @@ export class AccountStore { } public async cache(filter: StorageFilters): Promise> { - // tslint:disable-next-line no-null-keyword const result = await this._account.get(filter, { limit: null }); const resultAccountObjects = result.map( accountJSON => new Account(accountJSON), @@ -83,13 +82,12 @@ export class AccountStore { } // Account was not cached previously so we try to fetch it from db - // tslint:disable-next-line no-null-keyword const [elementFromDB] = await this._account.get( { [this._primaryKey]: primaryValue }, - // tslint:disable-next-line no-null-keyword { limit: null }, ); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (elementFromDB) { this._data.push(new Account(elementFromDB)); @@ -112,13 +110,12 @@ export class AccountStore { } // Account was not cached previously so we try to fetch it from db (example delegate account is voted) - // tslint:disable-next-line no-null-keyword const [elementFromDB] = await this._account.get( { [this._primaryKey]: primaryValue }, - // tslint:disable-next-line no-null-keyword { limit: null }, ); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (elementFromDB) { this._data.push(new Account(elementFromDB)); @@ -159,20 +156,21 @@ export class AccountStore { ); } - const updatedKeys = Object.entries(updatedElement).reduce( + const updatedKeys = Object.entries(updatedElement).reduce( (existingUpdatedKeys, [key, value]) => { const account = this._data[elementIndex]; - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-explicit-any if (!isEqual(value, (account as any)[key])) { existingUpdatedKeys.push(key); } return existingUpdatedKeys; }, - [] as string[], + [], ); this._data[elementIndex] = updatedElement; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition this._updatedKeys[elementIndex] = this._updatedKeys[elementIndex] ? [...new Set([...this._updatedKeys[elementIndex], ...updatedKeys])] : updatedKeys; @@ -189,21 +187,17 @@ export class AccountStore { const updateToAccounts = affectedAccounts.map( async ({ updatedItem, updatedKeys }) => { const filter = { [this._primaryKey]: updatedItem[this._primaryKey] }; - const updatedData = updatedKeys.reduce((data, key) => { - // tslint:disable-next-line:no-any - (data as any)[key] = (updatedItem as any)[key]; - - return data; - // tslint:disable-next-line readonly-keyword no-object-literal-type-assertion - }, {} as Partial); - - return this._account.upsert( - filter, - updatedData, - // tslint:disable-next-line:no-null-keyword - null, - tx, + const updatedData = updatedKeys.reduce>( + (data, key) => { + // eslint-disable-next-line + (data as any)[key] = (updatedItem as any)[key]; + + return data; + }, + {}, ); + + return this._account.upsert(filter, updatedData, null, tx); }, ); diff --git a/elements/lisk-chain/src/state_store/chain_state_store.ts b/elements/lisk-chain/src/state_store/chain_state_store.ts index a6e15906e5f..fff80cb7913 100644 --- a/elements/lisk-chain/src/state_store/chain_state_store.ts +++ b/elements/lisk-chain/src/state_store/chain_state_store.ts @@ -21,7 +21,6 @@ interface AdditionalInformation { } interface KeyValuePair { - // tslint:disable-next-line readonly-keyword [key: string]: string; } @@ -115,7 +114,7 @@ export class ChainStateStore { } await Promise.all( - Array.from(this._updatedKeys).map(key => + Array.from(this._updatedKeys).map(async key => this._chainState.setKey(key, this._data[key], tx), ), ); diff --git a/elements/lisk-chain/src/state_store/consensus_state_store.ts b/elements/lisk-chain/src/state_store/consensus_state_store.ts index 9935b8be07b..02b04a77fd1 100644 --- a/elements/lisk-chain/src/state_store/consensus_state_store.ts +++ b/elements/lisk-chain/src/state_store/consensus_state_store.ts @@ -105,7 +105,7 @@ export class ConsensusStateStore { } await Promise.all( - Array.from(this._updatedKeys).map(key => + Array.from(this._updatedKeys).map(async key => this._consensusState.setKey(key, this._data[key], tx), ), ); diff --git a/elements/lisk-chain/src/transactions/transactions_handlers.ts b/elements/lisk-chain/src/transactions/transactions_handlers.ts index 692dbb32365..3a2a2f2395b 100644 --- a/elements/lisk-chain/src/transactions/transactions_handlers.ts +++ b/elements/lisk-chain/src/transactions/transactions_handlers.ts @@ -35,7 +35,7 @@ export const validateTransactions = () => ( export const applyGenesisTransactions = () => async ( transactions: ReadonlyArray, stateStore: StateStore, -) => { +): Promise => { // Avoid merging both prepare statements into one for...of loop as this slows down the call dramatically for (const transaction of transactions) { await transaction.prepare(stateStore); @@ -79,7 +79,7 @@ export const applyTransactions = () => async ( export const checkPersistedTransactions = (dataAccess: DataAccess) => async ( transactions: ReadonlyArray, -) => { +): Promise => { if (!transactions.length) { return []; } @@ -125,6 +125,7 @@ export const checkAllowedTransactions = (contexter: Contexter) => ( transactions.map(transaction => { const context = typeof contexter === 'function' ? contexter() : contexter; const allowed = + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition !(transaction as MatcherTransaction).matcher || (transaction as MatcherTransaction).matcher(context); @@ -135,7 +136,7 @@ export const checkAllowedTransactions = (contexter: Contexter) => ( ? [] : [ new TransactionError( - `Transaction type ${transaction.type} is currently not allowed.`, + `Transaction type ${transaction.type.toString()} is currently not allowed.`, transaction.id, ), ], diff --git a/elements/lisk-chain/src/types.ts b/elements/lisk-chain/src/types.ts index 7d37ad92e1d..04fc0520f54 100644 --- a/elements/lisk-chain/src/types.ts +++ b/elements/lisk-chain/src/types.ts @@ -17,6 +17,7 @@ import { TransactionResponse, } from '@liskhq/lisk-transactions'; +// eslint-disable-next-line import/no-cycle import { Account } from './account'; export interface Indexable { @@ -140,7 +141,7 @@ export interface ChainState { } export interface StorageTransaction { - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any readonly batch: (input: any[]) => Promise; } @@ -227,13 +228,13 @@ export interface StorageEntity { ) => Promise; readonly upsert: ( filters: StorageFilters, - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any data: any, options: StorageOptions | null, tx?: StorageTransaction, ) => Promise; readonly create: ( - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any data: any, filters?: StorageFilters, tx?: StorageTransaction, @@ -259,7 +260,7 @@ export interface BlockStorageEntity extends StorageEntity { export interface TempBlockStorageEntity extends StorageEntity { readonly isEmpty: () => Promise; - readonly truncate: () => void; + readonly truncate: () => Promise; } export interface Storage { diff --git a/elements/lisk-chain/src/utils.ts b/elements/lisk-chain/src/utils.ts index 23fb137d2b3..a8c536dbb68 100644 --- a/elements/lisk-chain/src/utils.ts +++ b/elements/lisk-chain/src/utils.ts @@ -28,11 +28,13 @@ export const getId = (blockBytes: Buffer): string => { return id; }; +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export const uniqBy = ( arr: ReadonlyArray, property: string, set = new Set(), -) => +): T[] => arr.filter(element => + // eslint-disable-next-line (value => !set.has(value) && set.add(value))(element[property]), ); diff --git a/elements/lisk-chain/src/validate.ts b/elements/lisk-chain/src/validate.ts index d0935e8c280..34d46b8dcd1 100644 --- a/elements/lisk-chain/src/validate.ts +++ b/elements/lisk-chain/src/validate.ts @@ -95,17 +95,19 @@ export const validatePayload = ( block.transactions.forEach(transaction => { const transactionBytes = transaction.getBytes(); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (appliedTransactions[transaction.id]) { throw new Error(`Encountered duplicate transaction: ${transaction.id}`); } appliedTransactions[transaction.id] = transaction; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition if (transactionBytes) { transactionsBytesArray.push(transactionBytes); } - // tslint:disable-next-line no-any - totalAmount = totalAmount + BigInt((transaction.asset as any).amount || 0); - totalFee = totalFee + BigInt(transaction.fee); + // eslint-disable-next-line + totalAmount += BigInt((transaction.asset as any).amount || 0); + totalFee += BigInt(transaction.fee); }); const transactionsBuffer = Buffer.concat(transactionsBytesArray); diff --git a/elements/lisk-chain/src/verify.ts b/elements/lisk-chain/src/verify.ts index 52c03408fda..afa14dc3e2a 100644 --- a/elements/lisk-chain/src/verify.ts +++ b/elements/lisk-chain/src/verify.ts @@ -30,7 +30,7 @@ import { export const verifyBlockNotExists = async ( storage: Storage, block: BlockInstance, -) => { +): Promise => { const isPersisted = await storage.entities.Block.isPersisted({ id: block.id, }); @@ -43,7 +43,7 @@ export const verifyPreviousBlockId = ( block: BlockInstance, lastBlock: BlockInstance, genesisBlock: BlockInstance, -) => { +): void => { const isGenesisBlock = block.id === genesisBlock.id && !block.previousBlockId && @@ -94,7 +94,7 @@ export class BlocksVerify { } } - // tslint:disable-next-line prefer-function-over-method + // eslint-disable-next-line @typescript-eslint/require-await,class-methods-use-this public async checkTransactions(blockInstance: BlockInstance): Promise { const { version, height, timestamp, transactions } = blockInstance; if (transactions.length === 0) { diff --git a/elements/lisk-chain/test/.eslintrc.js b/elements/lisk-chain/test/.eslintrc.js new file mode 100644 index 00000000000..a98dfb6d823 --- /dev/null +++ b/elements/lisk-chain/test/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: '../../../.eslintrc.test.js', + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + }, +}; diff --git a/elements/lisk-chain/test/fixtures/block.ts b/elements/lisk-chain/test/fixtures/block.ts index 913656a2d71..911233ecaed 100644 --- a/elements/lisk-chain/test/fixtures/block.ts +++ b/elements/lisk-chain/test/fixtures/block.ts @@ -67,10 +67,13 @@ export const Block = stampit.compose({ this.totalAmount = faker.random .number({ min: 1000, max: 10000 }) .toString(); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition this.version = version || 0; if (this.version === 2) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition this.maxHeightPreviouslyForged = maxHeightPreviouslyForged || 0; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition this.maxHeightPrevoted = maxHeightPrevoted || 0; } }, diff --git a/elements/lisk-chain/test/tslint.json b/elements/lisk-chain/test/tslint.json deleted file mode 120000 index cfef1680c62..00000000000 --- a/elements/lisk-chain/test/tslint.json +++ /dev/null @@ -1 +0,0 @@ -../../../templates/test/tslint.json.tmpl \ No newline at end of file diff --git a/elements/lisk-chain/test/unit/account.spec.ts b/elements/lisk-chain/test/unit/account.spec.ts index 983826cb5f2..0a532c38d7b 100644 --- a/elements/lisk-chain/test/unit/account.spec.ts +++ b/elements/lisk-chain/test/unit/account.spec.ts @@ -85,13 +85,9 @@ describe('account', () => { // Check for delegate.pomHeights array accountObj.delegate.pomHeights.push(900); - expect(accountObj.delegate.pomHeights as number[]).toIncludeAnyMembers([ - 900, - ]); + expect(accountObj.delegate.pomHeights).toIncludeAnyMembers([900]); // Make sure the original object's value is not modified - expect( - accountJSON.delegate.pomHeights as number[], - ).not.toIncludeAnyMembers([900]); + expect(accountJSON.delegate.pomHeights).not.toIncludeAnyMembers([900]); // Check for keys.mandatoryKeys array accountObj.keys.mandatoryKeys.push('xx'); @@ -133,15 +129,15 @@ describe('account', () => { let accountObj: Account; it('should return an instance of Account class with default values for a given address', () => { accountObj = Account.getDefaultAccount(accountAddress); - expect(accountObj).toBeObject; + expect(accountObj).toBeObject(); expect(accountObj).toHaveProperty('address'); expect(accountObj.address).toEqual(accountAddress); expect(accountObj.balance).toEqual(BigInt('0')); expect(accountObj.fees).toEqual(BigInt('0')); expect(accountObj.rewards).toEqual(BigInt('0')); expect(accountObj.totalVotesReceived).toEqual(BigInt('0')); - expect(accountObj.username).toBeNull; - expect(accountObj.publicKey).toEqual(undefined); + expect(accountObj.username).toBeNull(); + expect(accountObj.publicKey).toBeUndefined(); expect(accountObj.isDelegate).toEqual(0); expect(accountObj.missedBlocks).toEqual(0); expect(accountObj.producedBlocks).toEqual(0); @@ -195,8 +191,8 @@ describe('account', () => { expect(accountJSON.balance).toEqual('0'); expect(accountJSON.fees).toEqual('0'); expect(accountJSON.rewards).toEqual('0'); - expect(accountJSON.username).toBeNull; - expect(accountJSON.publicKey).toEqual(undefined); + expect(accountJSON.username).toBeNull(); + expect(accountJSON.publicKey).toBeUndefined(); expect(accountJSON.isDelegate).toEqual(0); expect(accountJSON.missedBlocks).toEqual(0); expect(accountJSON.producedBlocks).toEqual(0); diff --git a/elements/lisk-chain/test/unit/chain.spec.ts b/elements/lisk-chain/test/unit/chain.spec.ts index 93a0d329182..05e5f12d5b1 100644 --- a/elements/lisk-chain/test/unit/chain.spec.ts +++ b/elements/lisk-chain/test/unit/chain.spec.ts @@ -102,7 +102,7 @@ describe('chain', () => { }); describe('constructor', () => { - it('should initialize private variables correctly', async () => { + it('should initialize private variables correctly', () => { // Assert stubbed values are assigned Object.entries(stubs.dependencies).forEach(([stubName, stubValue]) => { expect((chainInstance as any)[stubName]).toEqual(stubValue); @@ -127,7 +127,7 @@ describe('chain', () => { receivedAt: new Date(), }; }); - it('return the _lastBlock without the receivedAt property', async () => { + it('return the _lastBlock without the receivedAt property', () => { // Arrange const { receivedAt, ...block } = genesisBlock as any; // Assert @@ -136,7 +136,7 @@ describe('chain', () => { }); describe('init', () => { - beforeEach(async () => { + beforeEach(() => { stubs.dependencies.storage.entities.Block.begin.mockImplementation( (_: any, callback: any) => callback.call(chainInstance, stubs.tx), ); @@ -147,7 +147,7 @@ describe('chain', () => { stubs.dependencies.storage.entities.Block.get.mockResolvedValue([ genesisBlock, ]); - stubs.tx.batch.mockImplementation((promises: any) => + stubs.tx.batch.mockImplementation(async (promises: any) => Promise.all(promises), ); const random101DelegateAccounts = new Array(101) @@ -212,7 +212,7 @@ describe('chain', () => { it('should not throw when genesis block matches', async () => { // Act & Assert - await expect(chainInstance.init()).resolves.toEqual(undefined); + await expect(chainInstance.init()).resolves.toBeUndefined(); }); }); @@ -262,7 +262,8 @@ describe('chain', () => { }); describe('newStateStore', () => { - beforeEach(async () => { + beforeEach(() => { + // eslint-disable-next-line dot-notation chainInstance['_lastBlock'] = newBlock({ height: 532 }); stubs.dependencies.storage.entities.Block.get.mockResolvedValue([ newBlock(), @@ -271,13 +272,16 @@ describe('chain', () => { }); it('should populate the chain state with genesis block', async () => { + // eslint-disable-next-line dot-notation chainInstance['_lastBlock'] = newBlock({ height: 1 }); await chainInstance.newStateStore(); - await expect( + expect( stubs.dependencies.storage.entities.Block.get, ).toHaveBeenCalledWith( { + // eslint-disable-next-line camelcase height_gte: 1, + // eslint-disable-next-line camelcase height_lte: 1, }, { limit: null, sort: 'height:desc' }, @@ -286,11 +290,13 @@ describe('chain', () => { it('should return with the chain state with lastBlock.height to lastBlock.height - 309', async () => { await chainInstance.newStateStore(); - await expect( + expect( stubs.dependencies.storage.entities.Block.get, ).toHaveBeenCalledWith( { + // eslint-disable-next-line camelcase height_gte: chainInstance.lastBlock.height - 309, + // eslint-disable-next-line camelcase height_lte: chainInstance.lastBlock.height, }, { limit: null, sort: 'height:desc' }, @@ -307,11 +313,13 @@ describe('chain', () => { it('should return with the chain state with lastBlock.height to lastBlock.height - 310', async () => { await chainInstance.newStateStore(1); - await expect( + expect( stubs.dependencies.storage.entities.Block.get, ).toHaveBeenCalledWith( { + // eslint-disable-next-line camelcase height_gte: chainInstance.lastBlock.height - 310, + // eslint-disable-next-line camelcase height_lte: chainInstance.lastBlock.height - 1, }, { limit: null, sort: 'height:desc' }, @@ -403,8 +411,8 @@ describe('chain', () => { Account.getDefaultAccount('5678L'), ]; - beforeEach(async () => { - stubs.tx.batch.mockImplementation((promises: any) => + beforeEach(() => { + stubs.tx.batch.mockImplementation(async (promises: any) => Promise.all(promises), ); stubs.dependencies.storage.entities.Block.begin.mockImplementation( @@ -499,8 +507,8 @@ describe('chain', () => { const block = newBlock(); // Act & Assert - await chainInstance.save(block, stateStoreStub), - expect(stateStoreStub.finalize).toHaveBeenCalledTimes(1); + await chainInstance.save(block, stateStoreStub); + expect(stateStoreStub.finalize).toHaveBeenCalledTimes(1); expect(stateStoreStub.finalize).toHaveBeenCalledWith(stubs.tx); }); @@ -511,9 +519,9 @@ describe('chain', () => { // Act & Assert expect.assertions(1); - await expect(chainInstance.save(block, stateStoreStub)).resolves.toEqual( - undefined, - ); + await expect( + chainInstance.save(block, stateStoreStub), + ).resolves.toBeUndefined(); }); it('should throw error when storage create fails', async () => { @@ -558,14 +566,14 @@ describe('chain', () => { Account.getDefaultAccount('5678L'), ]; - beforeEach(async () => { + beforeEach(() => { stateStoreStub = { finalize: jest.fn(), account: { getUpdated: jest.fn().mockReturnValue(fakeAccounts), }, } as any; - stubs.tx.batch.mockImplementation((promises: any) => + stubs.tx.batch.mockImplementation(async (promises: any) => Promise.all(promises), ); stubs.dependencies.storage.entities.Block.begin.mockImplementation( @@ -626,7 +634,7 @@ describe('chain', () => { }); describe('when saveToTemp parameter is set to true', () => { - beforeEach(async () => { + beforeEach(() => { stubs.dependencies.storage.entities.TempBlock.create.mockResolvedValue(); }); @@ -707,7 +715,7 @@ describe('chain', () => { }); describe('exists()', () => { - beforeEach(async () => { + beforeEach(() => { stubs.dependencies.storage.entities.Block.isPersisted.mockResolvedValue( true, ); @@ -752,7 +760,7 @@ describe('chain', () => { }, ]; - beforeEach(async () => { + beforeEach(() => { stubs.dependencies.storage.entities.Block.get.mockResolvedValue( validBlocks, ); @@ -764,6 +772,7 @@ describe('chain', () => { expect( stubs.dependencies.storage.entities.Block.get, ).toHaveBeenCalledWith( + // eslint-disable-next-line camelcase { height_gte: 0, height_lte: 0 }, { extended: true, limit: null, sort: 'height:desc' }, ); @@ -782,7 +791,7 @@ describe('chain', () => { }, ]; - beforeEach(async () => { + beforeEach(() => { stubs.dependencies.storage.entities.Block.get.mockResolvedValue( validBlocks, ); @@ -797,6 +806,7 @@ describe('chain', () => { expect( stubs.dependencies.storage.entities.Block.get, ).toHaveBeenCalledWith( + // eslint-disable-next-line camelcase { height_gte: 100, height_lte: 101 }, { extended: true, limit: null, sort: 'height:desc' }, ); diff --git a/elements/lisk-chain/test/unit/data_access/cache/block.spec.ts b/elements/lisk-chain/test/unit/data_access/cache/block.spec.ts index fbe1cb1ec38..0a2ce5aa3a8 100644 --- a/elements/lisk-chain/test/unit/data_access/cache/block.spec.ts +++ b/elements/lisk-chain/test/unit/data_access/cache/block.spec.ts @@ -27,13 +27,14 @@ describe('data_access.cache.block', () => { describe('constructor', () => { it('should initialize private variables', () => { expect(blocksCache.maxCachedItems).toEqual(DEFAULT_CACHE_SIZE); - expect(blocksCache.length).toEqual(0); + expect(blocksCache).toHaveLength(0); expect(blocksCache.items).toEqual([]); }); }); describe('add', () => { it('should add block header to cache', () => { + // eslint-disable-next-line new-cap const block = BlockHeaderInstance({ height: 1 }); blocksCache.add(block); @@ -42,22 +43,25 @@ describe('data_access.cache.block', () => { it('should only contain maximum of 500 block header at given point in time', () => { const [blocks] = Array.from({ length: 510 }, (_, i) => + // eslint-disable-next-line new-cap blocksCache.add(BlockHeaderInstance({ height: i })), ); const blockIds = blocks.map(b => b.id); expect(blocksCache.items).toStrictEqual(blocks); - expect(blocksCache.items.length).toEqual(DEFAULT_CACHE_SIZE); + expect(blocksCache.items).toHaveLength(DEFAULT_CACHE_SIZE); expect(blocksCache.getByIDs(blockIds)).toStrictEqual(blocks.reverse()); }); it('should remove the least height block header and add new highest height block header', () => { const [blocks] = Array.from({ length: 510 }, (_, i) => + // eslint-disable-next-line new-cap blocksCache.add(BlockHeaderInstance({ height: i })), ); const maxHeight = Math.max(...blocksCache.items.map(b => b.height)); const minHeight = Math.min(...blocksCache.items.map(b => b.height)); const [lowestHeightBlock] = blocks.filter(b => b.height === minHeight); + // eslint-disable-next-line new-cap const newBlock = BlockHeaderInstance({ height: maxHeight + 1 }); expect(blocksCache.getByHeight(minHeight)).toEqual(lowestHeightBlock); @@ -74,10 +78,12 @@ describe('data_access.cache.block', () => { it('should only allow to insert block header with highest height', () => { const [blocks] = Array.from({ length: 510 }, (_, i) => + // eslint-disable-next-line new-cap blocksCache.add(BlockHeaderInstance({ height: i })), ); const minHeight = Math.min(...blocksCache.items.map(b => b.height)); const [lowestHeightBlock] = blocks.filter(b => b.height === minHeight); + // eslint-disable-next-line new-cap const newBlock = BlockHeaderInstance({ height: minHeight + 1 }); expect(blocksCache.getByHeight(minHeight)).toEqual(lowestHeightBlock); @@ -93,6 +99,7 @@ describe('data_access.cache.block', () => { describe('remove', () => { it('if the cache is emptied below the min cache size it should set needsRefill to true', () => { const [blocks] = Array.from({ length: 303 }, (_, i) => + // eslint-disable-next-line new-cap blocksCache.add(BlockHeaderInstance({ height: i })), ); @@ -103,19 +110,21 @@ describe('data_access.cache.block', () => { describe('getByID', () => { it('should return undefined if block does not exists', () => { + // eslint-disable-next-line new-cap const block = BlockHeaderInstance({ height: 1 }); blocksCache.add(block); expect(blocksCache.items).toStrictEqual([block]); - expect(blocksCache.getByID('123')).toBeUndefined; + expect(blocksCache.getByID('123')).toBeUndefined(); }); - it('should return undefined if block does not exists', () => { + it('should return undefined if block does not exists when empty', () => { expect(blocksCache.items).toStrictEqual([]); - expect(blocksCache.getByID('123')).toBeUndefined; + expect(blocksCache.getByID('123')).toBeUndefined(); }); it('should return the block for a given id', () => { + // eslint-disable-next-line new-cap const block = BlockHeaderInstance({ height: 1 }); blocksCache.add(block); @@ -131,6 +140,7 @@ describe('data_access.cache.block', () => { it('should return empty array if matching block ids does not exists', () => { const [blocks] = Array.from({ length: 10 }, (_, i) => + // eslint-disable-next-line new-cap blocksCache.add(BlockHeaderInstance({ height: i })), ); const blockIds = blocks.map(b => b.id); @@ -141,6 +151,7 @@ describe('data_access.cache.block', () => { it('should return all the blocks for given block ids', () => { const [blocks] = Array.from({ length: 10 }, (_, i) => + // eslint-disable-next-line new-cap blocksCache.add(BlockHeaderInstance({ height: i })), ); const blockIds = blocks.map(b => b.id); @@ -157,6 +168,7 @@ describe('data_access.cache.block', () => { it('should return empty array if blocks does not exists between height range', () => { const [blocks] = Array.from({ length: 10 }, (_, i) => + // eslint-disable-next-line new-cap blocksCache.add(BlockHeaderInstance({ height: i + 1 })), ); @@ -168,6 +180,7 @@ describe('data_access.cache.block', () => { it('should return all the blocks for given block height range', () => { const [blocks] = Array.from({ length: 10 }, (_, i) => + // eslint-disable-next-line new-cap blocksCache.add(BlockHeaderInstance({ height: i + 1 })), ); const heights = blocks.map(b => b.height); diff --git a/elements/lisk-chain/test/unit/data_access/data_access.spec.ts b/elements/lisk-chain/test/unit/data_access/data_access.spec.ts index 4ec5da3f617..f39b5b4238a 100644 --- a/elements/lisk-chain/test/unit/data_access/data_access.spec.ts +++ b/elements/lisk-chain/test/unit/data_access/data_access.spec.ts @@ -21,7 +21,7 @@ describe('data_access.storage', () => { let storageMock: any; let block: BlockInstance; - beforeEach(async () => { + beforeEach(() => { storageMock = { entities: { Block: { @@ -52,11 +52,12 @@ describe('data_access.storage', () => { dataAccess = new DataAccess({ dbStorage: storageMock, - registeredTransactions: { '8': TransferTransaction }, + registeredTransactions: { 8: TransferTransaction }, minBlockHeaderCache: 3, maxBlockHeaderCache: 5, }); block = { + // eslint-disable-next-line new-cap ...BlockHeaderInstance({ height: 1 }), totalAmount: 1, totalFee: 1, @@ -73,11 +74,11 @@ describe('data_access.storage', () => { }); describe('#addBlockHeader', () => { - it('should call blocksCache.add', async () => { + it('should call blocksCache.add', () => { // Arrange (dataAccess as any)._blocksCache = { add: jest.fn() }; // Act - await dataAccess.addBlockHeader(block); + dataAccess.addBlockHeader(block); // Assert expect((dataAccess as any)._blocksCache.add).toHaveBeenCalled(); @@ -452,8 +453,9 @@ describe('data_access.storage', () => { ]); const blocks = []; - for (let i = 0; i < 5; i++) { + for (let i = 0; i < 5; i += 1) { block = { + // eslint-disable-next-line new-cap ...BlockHeaderInstance({ height: i + 10 }), totalAmount: 1, totalFee: 1, diff --git a/elements/lisk-chain/test/unit/data_access/storage.spec.ts b/elements/lisk-chain/test/unit/data_access/storage.spec.ts index 7e141ce7b5a..66990a37e7f 100644 --- a/elements/lisk-chain/test/unit/data_access/storage.spec.ts +++ b/elements/lisk-chain/test/unit/data_access/storage.spec.ts @@ -52,7 +52,7 @@ describe('data access - storage', () => { let storageMock: any; let storageAccess: StorageAccess; - beforeEach(async () => { + beforeEach(() => { storageMock = { entities: { Block: { @@ -85,7 +85,7 @@ describe('data access - storage', () => { }); describe('#getBlockHeadersByIDs', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Block.get.mockResolvedValue(defaultBlocks); }); @@ -104,7 +104,7 @@ describe('data access - storage', () => { }); describe('#getBlockHeadersByHeightBetween', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Block.get.mockResolvedValue(defaultBlocks); }); @@ -123,7 +123,7 @@ describe('data access - storage', () => { }); describe('#getBlockHeadersWithHeights', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Block.get.mockResolvedValue(defaultBlocks); }); @@ -141,7 +141,7 @@ describe('data access - storage', () => { }); describe('#getLastBlockHeader', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Block.get.mockResolvedValue([defaultBlocks[1]]); }); @@ -157,7 +157,7 @@ describe('data access - storage', () => { }); describe('#getLastCommonBlockHeader', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Block.get.mockResolvedValue([defaultBlocks[1]]); }); @@ -176,7 +176,7 @@ describe('data access - storage', () => { }); describe('#getBlocksCount', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Block.count.mockResolvedValue(2); }); @@ -192,7 +192,7 @@ describe('data access - storage', () => { }); describe('#getBlocksByIDs', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Block.get.mockResolvedValue(defaultBlocks); }); @@ -208,7 +208,7 @@ describe('data access - storage', () => { }); describe('#getBlocksByHeightBetween', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Block.get.mockResolvedValue(defaultBlocks); }); @@ -227,7 +227,7 @@ describe('data access - storage', () => { }); describe('#getLastBlock', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Block.get.mockResolvedValue([defaultBlocks[1]]); }); @@ -243,7 +243,7 @@ describe('data access - storage', () => { }); describe('#getTempBlocks', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.TempBlock.get.mockResolvedValue(defaultBlocks); }); @@ -259,7 +259,7 @@ describe('data access - storage', () => { }); describe('#isTempBlockEmpty', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.TempBlock.isEmpty.mockResolvedValue(true); }); @@ -295,7 +295,7 @@ describe('data access - storage', () => { }); describe('#isBlockPersisted', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Block.isPersisted.mockResolvedValue(true); }); @@ -311,7 +311,7 @@ describe('data access - storage', () => { }); describe('#getAccountsByPublicKey', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Account.get.mockResolvedValue(defaultAccounts); }); @@ -329,7 +329,7 @@ describe('data access - storage', () => { }); describe('#getAccountsByAddress', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Account.get.mockResolvedValue(defaultAccounts); }); @@ -358,7 +358,7 @@ describe('data access - storage', () => { }); describe('#getTransactionsByIDs', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Transaction.get.mockResolvedValue( defaultTransactions, @@ -379,7 +379,7 @@ describe('data access - storage', () => { }); describe('#isTransactionPersisted', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageMock.entities.Transaction.isPersisted.mockResolvedValue(true); }); diff --git a/elements/lisk-chain/test/unit/process.spec.ts b/elements/lisk-chain/test/unit/process.spec.ts index cf886675902..b2c3ce7a9de 100644 --- a/elements/lisk-chain/test/unit/process.spec.ts +++ b/elements/lisk-chain/test/unit/process.spec.ts @@ -62,7 +62,7 @@ describe('blocks/header', () => { let block: BlockInstance; let blockBytes: Buffer; - beforeEach(async () => { + beforeEach(() => { storageStub = { entities: { Account: { @@ -119,7 +119,7 @@ describe('blocks/header', () => { describe('#validateBlockHeader', () => { describe('when previous block property is invalid', () => { - it('should throw error', async () => { + it('should throw error', () => { // Arrange block = newBlock({ previousBlockId: undefined, height: 3 }); blockBytes = getBytes(block); @@ -131,7 +131,7 @@ describe('blocks/header', () => { }); describe('when signature is invalid', () => { - it('should throw error', async () => { + it('should throw error', () => { // Arrange block = newBlock({ blockSignature: 'aaaa' }); blockBytes = getBytes(block); @@ -143,7 +143,7 @@ describe('blocks/header', () => { }); describe('when reward is invalid', () => { - it('should throw error', async () => { + it('should throw error', () => { // Arrange block = newBlock({ reward: BigInt(1000000000) }); blockBytes = getBytes(block); @@ -155,7 +155,7 @@ describe('blocks/header', () => { }); describe('when a transaction included is invalid', () => { - it('should throw error', async () => { + it('should throw error', () => { // Arrange const invalidTx = chainInstance.deserializeTransaction( transfer({ @@ -178,7 +178,7 @@ describe('blocks/header', () => { }); describe('when payload length exceeds maximum allowed', () => { - it('should throw error', async () => { + it('should throw error', () => { // Arrange (chainInstance as any).constants.maxPayloadLength = 100; const txs = new Array(200).fill(0).map((_, v) => @@ -187,7 +187,7 @@ describe('blocks/header', () => { passphrase: genesisAccount.passphrase, fee: '10000000', nonce: '0', - recipientId: `${v + 1}L`, + recipientId: `${(v + 1).toString()}L`, amount: '100', networkIdentifier, }) as TransactionJSON, @@ -203,7 +203,7 @@ describe('blocks/header', () => { }); describe('when payload hash is incorrect', () => { - it('should throw error', async () => { + it('should throw error', () => { // Arrange const txs = new Array(20).fill(0).map((_, v) => chainInstance.deserializeTransaction( @@ -211,7 +211,7 @@ describe('blocks/header', () => { fee: '10000000', nonce: '0', passphrase: genesisAccount.passphrase, - recipientId: `${v + 1}L`, + recipientId: `${(v + 1).toString()}L`, amount: '100', networkIdentifier, }) as TransactionJSON, @@ -227,7 +227,7 @@ describe('blocks/header', () => { }); describe('when all the value is valid', () => { - it('should not throw error', async () => { + it('should not throw error', () => { // Arrange const txs = new Array(20).fill(0).map((_, v) => chainInstance.deserializeTransaction( @@ -235,7 +235,7 @@ describe('blocks/header', () => { fee: '10000000', nonce: '0', passphrase: genesisAccount.passphrase, - recipientId: `${v + 1}L`, + recipientId: `${(v + 1).toString()}L`, amount: '100', networkIdentifier, }) as TransactionJSON, @@ -254,7 +254,7 @@ describe('blocks/header', () => { describe('#verify', () => { let stateStore: StateStore; - beforeEach(async () => { + beforeEach(() => { // Arrange stateStore = new StateStore(storageStub, { lastBlockHeaders: [], @@ -337,7 +337,7 @@ describe('blocks/header', () => { let txApplySpy: jest.SpyInstance; let originalClass: typeof BaseTransaction; - beforeEach(async () => { + beforeEach(() => { // Arrage notAllowedTx = chainInstance.deserializeTransaction( transfer({ @@ -354,7 +354,7 @@ describe('blocks/header', () => { ); originalClass = transactionClass; Object.defineProperty(transactionClass.prototype, 'matcher', { - get: () => () => false, + get: () => (): boolean => false, configurable: true, }); (chainInstance as any).dataAccess._transactionAdapter._transactionClassMap.set( @@ -365,16 +365,16 @@ describe('blocks/header', () => { block = newBlock({ transactions: [notAllowedTx] }); }); - afterEach(async () => { + afterEach(() => { Object.defineProperty(originalClass.prototype, 'matcher', { - get: () => () => true, + get: () => (): boolean => true, configurable: true, }); }); it('should not call apply for the transaction and throw error', async () => { // Arrange - const stateStore = new StateStore(storageStub, { + stateStore = new StateStore(storageStub, { lastBlockHeaders: [], networkIdentifier: defaultNetworkIdentifier, lastBlockReward: BigInt(500000000), @@ -397,7 +397,7 @@ describe('blocks/header', () => { describe('when skip existing check is true and transactions are valid', () => { let invalidTx; - beforeEach(async () => { + beforeEach(() => { // Arrage storageStub.entities.Account.get.mockResolvedValue([ { address: genesisAccount.address, balance: '100000000000000' }, @@ -417,7 +417,7 @@ describe('blocks/header', () => { it('should not call apply for the transaction and throw error', async () => { // Act - const stateStore = new StateStore(storageStub, { + stateStore = new StateStore(storageStub, { lastBlockHeaders: [], networkIdentifier: defaultNetworkIdentifier, lastBlockReward: BigInt(500000000), @@ -436,7 +436,7 @@ describe('blocks/header', () => { }); describe('when skip existing check is false and block exists in database', () => { - beforeEach(async () => { + beforeEach(() => { // Arrage storageStub.entities.Block.isPersisted.mockResolvedValue(true); storageStub.entities.Account.get.mockResolvedValue([ @@ -457,7 +457,7 @@ describe('blocks/header', () => { it('should not call apply for the transaction and throw error', async () => { // Arrange - const stateStore = new StateStore(storageStub, { + stateStore = new StateStore(storageStub, { lastBlockHeaders: [], networkIdentifier: defaultNetworkIdentifier, lastBlockReward: BigInt(500000000), @@ -473,7 +473,7 @@ describe('blocks/header', () => { }); describe('when skip existing check is false and block does not exist in database but transaction does', () => { - beforeEach(async () => { + beforeEach(() => { // Arrage storageStub.entities.Account.get.mockResolvedValue([ { address: genesisAccount.address, balance: '100000000000000' }, @@ -495,7 +495,7 @@ describe('blocks/header', () => { it('should not call apply for the transaction and throw error', async () => { // Arrange - const stateStore = new StateStore(storageStub, { + stateStore = new StateStore(storageStub, { lastBlockHeaders: [], networkIdentifier: defaultNetworkIdentifier, lastBlockReward: BigInt(500000000), @@ -537,6 +537,7 @@ describe('blocks/header', () => { lastBlockReward: BigInt(500000000), }); await stateStore.account.cache({ + // eslint-disable-next-line camelcase address_in: [ genesisAccount.address, getAddressFromPublicKey(block.generatorPublicKey), @@ -553,7 +554,7 @@ describe('blocks/header', () => { expect(generator.balance).toEqual(block.reward); }); - it('should not have updated burnt fee', async () => { + it('should not have updated burnt fee', () => { expect(storageStub.entities.ChainState.getKey).not.toHaveBeenCalled(); }); }); @@ -589,6 +590,7 @@ describe('blocks/header', () => { lastBlockReward: BigInt(500000000), }); await stateStore.account.cache({ + // eslint-disable-next-line camelcase address_in: [genesisAccount.address], }); }); @@ -605,7 +607,7 @@ describe('blocks/header', () => { ]); }); - it('should not set the block to the last block', async () => { + it('should not set the block to the last block', () => { expect(chainInstance.lastBlock).toStrictEqual(genesisBlock); }); }); @@ -709,12 +711,12 @@ describe('blocks/header', () => { await chainInstance.apply(block, stateStore); }); - it('should call apply for the transaction', async () => { + it('should call apply for the transaction', () => { expect(validTxApplySpy).toHaveBeenCalledTimes(1); expect(validTx2ApplySpy).toHaveBeenCalledTimes(1); }); - it('should not call account update', async () => { + it('should not call account update', () => { expect(storageStub.entities.Account.upsert).not.toHaveBeenCalled(); }); @@ -779,7 +781,7 @@ describe('blocks/header', () => { ); }); - it('should not call account update', async () => { + it('should not call account update', () => { expect(storageStub.entities.Account.upsert).not.toHaveBeenCalled(); }); @@ -816,7 +818,7 @@ describe('blocks/header', () => { await chainInstance.undo(block, stateStore); }); - it('should not call account update', async () => { + it('should not call account update', () => { expect(storageStub.entities.Account.upsert).not.toHaveBeenCalled(); }); @@ -827,7 +829,7 @@ describe('blocks/header', () => { expect(generator.balance.toString()).toEqual('0'); }); - it('should not deduct burntFee from chain state', async () => { + it('should not deduct burntFee from chain state', () => { expect(storageStub.entities.ChainState.getKey).not.toHaveBeenCalled(); }); }); @@ -943,12 +945,12 @@ describe('blocks/header', () => { await chainInstance.undo(block, stateStore); }); - it('should call undo for the transaction', async () => { + it('should call undo for the transaction', () => { expect(validTxUndoSpy).toHaveBeenCalledTimes(1); expect(validTx2UndoSpy).toHaveBeenCalledTimes(1); }); - it('should not call account update', async () => { + it('should not call account update', () => { expect(storageStub.entities.Account.upsert).not.toHaveBeenCalled(); }); diff --git a/elements/lisk-chain/test/unit/process_transactions.spec.ts b/elements/lisk-chain/test/unit/process_transactions.spec.ts index 5ea5214d6b7..f5d09bb036b 100644 --- a/elements/lisk-chain/test/unit/process_transactions.spec.ts +++ b/elements/lisk-chain/test/unit/process_transactions.spec.ts @@ -54,12 +54,12 @@ describe('#composeTransactionSteps', () => { result = await composedFunction(testTransactions, {} as any); }); - it('should return a combination of the result of executing both steps', async () => { + it('should return a combination of the result of executing both steps', () => { // Assert expect(result).toEqual([...step1Response, ...step2Response]); }); - it('should only pass successfull transactions to the next step', async () => { + it('should only pass successfull transactions to the next step', () => { // Assert expect(step2).toHaveBeenCalledWith([testTransactions[1]], {}); }); diff --git a/elements/lisk-chain/test/unit/slots.spec.ts b/elements/lisk-chain/test/unit/slots.spec.ts index af7a4d047d5..9135a741dec 100644 --- a/elements/lisk-chain/test/unit/slots.spec.ts +++ b/elements/lisk-chain/test/unit/slots.spec.ts @@ -26,7 +26,7 @@ describe('Slots', () => { interval: DEFAULT_BLOCK_TIME, }); - beforeEach(async () => { + beforeEach(() => { jest .spyOn(Date, 'now') .mockReturnValue( @@ -35,13 +35,13 @@ describe('Slots', () => { }); describe('getEpochTime', () => { - it('should return time after epoch in second', async () => { + it('should return time after epoch in second', () => { expect(slots.getEpochTime()).toBe(10); }); }); describe('getRealTime', () => { - it('should return time after epoch in second', async () => { + it('should return time after epoch in second', () => { expect(slots.getRealTime(1000)).toBe( new Date(DEFAULT_EPOCH_TIME).getTime() + 1000 * 1000, ); @@ -49,41 +49,41 @@ describe('Slots', () => { }); describe('getSlotNumber', () => { - it('should return correct slot number from default epoch', async () => { + it('should return correct slot number from default epoch', () => { expect(slots.getSlotNumber()).toBe(1); }); - it('should return correct slot number from input epoch', async () => { + it('should return correct slot number from input epoch', () => { expect(slots.getSlotNumber(20)).toBe(2); }); }); describe('getSlotTime', () => { - it('should return correct time corresponds to the slot', async () => { + it('should return correct time corresponds to the slot', () => { expect(slots.getSlotTime(2)).toBe(20); }); }); describe('getNextSlot', () => { - it('should return correct next slot', async () => { + it('should return correct next slot', () => { expect(slots.getNextSlot()).toBe(2); }); }); describe('isWithinTimeslot', () => { - it('should return true if the slot is within time', async () => { + it('should return true if the slot is within time', () => { expect(slots.isWithinTimeslot(5, 55)).toBeTrue(); }); - it('should return true if the slot is begining of the time', async () => { + it('should return true if the slot is begining of the time', () => { expect(slots.isWithinTimeslot(5, 50)).toBeTrue(); }); - it('should return true if the slot is end of the time', async () => { + it('should return true if the slot is end of the time', () => { expect(slots.isWithinTimeslot(5, 59)).toBeTrue(); }); - it('should return false if the slot is out of the time', async () => { + it('should return false if the slot is out of the time', () => { expect(slots.isWithinTimeslot(5, 49)).toBeFalse(); }); }); diff --git a/elements/lisk-chain/test/unit/state_store_account.spec.ts b/elements/lisk-chain/test/unit/state_store_account.spec.ts index 0837681afb5..7cdb14de92c 100644 --- a/elements/lisk-chain/test/unit/state_store_account.spec.ts +++ b/elements/lisk-chain/test/unit/state_store_account.spec.ts @@ -46,7 +46,7 @@ describe('state store / account', () => { let stateStore: StateStore; let storageStub: any; - beforeEach(async () => { + beforeEach(() => { storageStub = { entities: { Account: { @@ -63,7 +63,7 @@ describe('state store / account', () => { }); describe('cache', () => { - beforeEach(async () => { + beforeEach(() => { // Arrange storageStub.entities.Account.get.mockResolvedValue(defaultAccounts); }); @@ -233,7 +233,7 @@ describe('state store / account', () => { }); describe('finalize', () => { - let txStub = {} as StorageTransaction; + const txStub = {} as StorageTransaction; let existingAccount; let updatedAccount; let missedBlocks: number; diff --git a/elements/lisk-chain/test/unit/state_store_chain_state.spec.ts b/elements/lisk-chain/test/unit/state_store_chain_state.spec.ts index cd87dfb1cd7..7d0f31f1fbc 100644 --- a/elements/lisk-chain/test/unit/state_store_chain_state.spec.ts +++ b/elements/lisk-chain/test/unit/state_store_chain_state.spec.ts @@ -23,7 +23,7 @@ describe('state store / chain_state', () => { { height: 20 }, ] as unknown) as ReadonlyArray; - beforeEach(async () => { + beforeEach(() => { storageStub = { entities: { ChainState: { @@ -41,13 +41,13 @@ describe('state store / chain_state', () => { }); describe('lastBlockHeader', () => { - it('should have first element as lastBlockHeader', async () => { + it('should have first element as lastBlockHeader', () => { expect(stateStore.chain.lastBlockHeader).toEqual({ height: 30 }); }); }); describe('networkIdentifier', () => { - it('should have first element as lastBlockHeader', async () => { + it('should have first element as lastBlockHeader', () => { expect(stateStore.chain.networkIdentifier).toEqual( 'network-identifier-chain-1', ); @@ -55,7 +55,7 @@ describe('state store / chain_state', () => { }); describe('lastBlockReward', () => { - it('should have reward given at the initialization', async () => { + it('should have reward given at the initialization', () => { expect(stateStore.chain.lastBlockReward.toString()).toEqual('500000000'); }); }); @@ -106,7 +106,7 @@ describe('state store / chain_state', () => { describe('set', () => { it('should set value to data and set the updated keys', async () => { // Act - await stateStore.chain.set('key3', 'value3'); + stateStore.chain.set('key3', 'value3'); // Assert expect(await stateStore.chain.get('key3')).toBe('value3'); expect((stateStore.chain as any)._updatedKeys.size).toBe(1); @@ -114,8 +114,8 @@ describe('state store / chain_state', () => { it('should set value to data and set the updated keys only once', async () => { // Act - await stateStore.chain.set('key3', 'value3'); - await stateStore.chain.set('key3', 'value4'); + stateStore.chain.set('key3', 'value3'); + stateStore.chain.set('key3', 'value4'); // Assert expect(await stateStore.chain.get('key3')).toBe('value4'); expect((stateStore.chain as any)._updatedKeys.size).toBe(1); @@ -123,7 +123,7 @@ describe('state store / chain_state', () => { }); describe('finalize', () => { - let txStub = {} as StorageTransaction; + const txStub = {} as StorageTransaction; it('should not call storage if nothing is set', async () => { // Act @@ -134,9 +134,9 @@ describe('state store / chain_state', () => { it('should call storage for all the updated keys', async () => { // Act - await stateStore.chain.set('key3', 'value3'); - await stateStore.chain.set('key3', 'value4'); - await stateStore.chain.set('key4', 'value5'); + stateStore.chain.set('key3', 'value3'); + stateStore.chain.set('key3', 'value4'); + stateStore.chain.set('key4', 'value5'); await stateStore.chain.finalize(txStub); // Assert expect(storageStub.entities.ChainState.setKey).toHaveBeenCalledWith( @@ -153,11 +153,11 @@ describe('state store / chain_state', () => { it('should handle promise rejection', async () => { // Prepare - storageStub.entities.ChainState.setKey.mockImplementation(() => + storageStub.entities.ChainState.setKey.mockImplementation(async () => Promise.reject(new Error('Fake storage layer error')), ); // Act - await stateStore.chain.set('key3', 'value3'); + stateStore.chain.set('key3', 'value3'); // Assert return expect(stateStore.chain.finalize(txStub)).rejects.toThrow( 'Fake storage layer error', diff --git a/elements/lisk-chain/test/unit/state_store_consensus_state.spec.ts b/elements/lisk-chain/test/unit/state_store_consensus_state.spec.ts index a3e09949d1b..72d200e5fd3 100644 --- a/elements/lisk-chain/test/unit/state_store_consensus_state.spec.ts +++ b/elements/lisk-chain/test/unit/state_store_consensus_state.spec.ts @@ -23,7 +23,7 @@ describe('state store / chain_state', () => { { height: 20 }, ] as unknown) as ReadonlyArray; - beforeEach(async () => { + beforeEach(() => { storageStub = { entities: { ConsensusState: { @@ -41,7 +41,7 @@ describe('state store / chain_state', () => { }); describe('lastBlockHeaders', () => { - it('should have first element as lastBlockHeader', async () => { + it('should have first element as lastBlockHeader', () => { expect(stateStore.consensus.lastBlockHeaders).toEqual(lastBlockHeaders); }); }); @@ -92,7 +92,7 @@ describe('state store / chain_state', () => { describe('set', () => { it('should set value to data and set the updated keys', async () => { // Act - await stateStore.consensus.set('key3', 'value3'); + stateStore.consensus.set('key3', 'value3'); // Assert expect(await stateStore.consensus.get('key3')).toBe('value3'); expect((stateStore.consensus as any)._updatedKeys.size).toBe(1); @@ -100,8 +100,8 @@ describe('state store / chain_state', () => { it('should set value to data and set the updated keys only once', async () => { // Act - await stateStore.consensus.set('key3', 'value3'); - await stateStore.consensus.set('key3', 'value4'); + stateStore.consensus.set('key3', 'value3'); + stateStore.consensus.set('key3', 'value4'); // Assert expect(await stateStore.consensus.get('key3')).toBe('value4'); expect((stateStore.consensus as any)._updatedKeys.size).toBe(1); @@ -109,7 +109,7 @@ describe('state store / chain_state', () => { }); describe('finalize', () => { - let txStub = {} as StorageTransaction; + const txStub = {} as StorageTransaction; it('should not call storage if nothing is set', async () => { // Act @@ -120,9 +120,9 @@ describe('state store / chain_state', () => { it('should call storage for all the updated keys', async () => { // Act - await stateStore.consensus.set('key3', 'value3'); - await stateStore.consensus.set('key3', 'value4'); - await stateStore.consensus.set('key4', 'value5'); + stateStore.consensus.set('key3', 'value3'); + stateStore.consensus.set('key3', 'value4'); + stateStore.consensus.set('key4', 'value5'); await stateStore.consensus.finalize(txStub); // Assert expect(storageStub.entities.ConsensusState.setKey).toHaveBeenCalledWith( @@ -139,11 +139,11 @@ describe('state store / chain_state', () => { it('should handle promise rejection', async () => { // Prepare - storageStub.entities.ConsensusState.setKey.mockImplementation(() => + storageStub.entities.ConsensusState.setKey.mockImplementation(async () => Promise.reject(new Error('Fake storage layer error')), ); // Act - await stateStore.consensus.set('key3', 'value3'); + stateStore.consensus.set('key3', 'value3'); // Assert return expect(stateStore.consensus.finalize(txStub)).rejects.toThrow( 'Fake storage layer error', diff --git a/elements/lisk-chain/test/unit/transaction_interface_adapter.spec.ts b/elements/lisk-chain/test/unit/transaction_interface_adapter.spec.ts index 15c641228dc..ffc424fe5aa 100644 --- a/elements/lisk-chain/test/unit/transaction_interface_adapter.spec.ts +++ b/elements/lisk-chain/test/unit/transaction_interface_adapter.spec.ts @@ -34,17 +34,17 @@ describe('transactions', () => { let transactions: TransactionInterfaceAdapter; - beforeEach(async () => { + beforeEach(() => { // Act transactions = new TransactionInterfaceAdapter(registeredTransactions); }); describe('constructor', () => { - it('should create initTransaction with correct properties', async () => { + it('should create initTransaction with correct properties', () => { expect(transactions).toHaveProperty('_transactionClassMap'); }); - it('should have transactionClassMap property with Lisk transaction types', async () => { + it('should have transactionClassMap property with Lisk transaction types', () => { expect([...(transactions as any)._transactionClassMap.keys()]).toEqual([ 8, 10, @@ -56,13 +56,13 @@ describe('transactions', () => { }); describe('fromJSON', () => { - it('should throw an error if transaction type is not registered', async () => { + it('should throw an error if transaction type is not registered', () => { expect(() => transactions.fromJSON({ type: 1 } as any)).toThrow( 'Transaction type not found.', ); }); - it('should initialize a transfer transaction', async () => { + it('should initialize a transfer transaction', () => { const transfer = { type: 8, nonce: '0', @@ -83,7 +83,7 @@ describe('transactions', () => { ); }); - it('should initialize a delegate transaction', async () => { + it('should initialize a delegate transaction', () => { const delegate = { type: 10, nonce: '0', @@ -108,7 +108,7 @@ describe('transactions', () => { ); }); - it('should initialize a vote transaction', async () => { + it('should initialize a vote transaction', () => { const vote = { type: 13, nonce: '0', @@ -136,7 +136,7 @@ describe('transactions', () => { expect(transactions.fromJSON(vote)).toBeInstanceOf(VoteTransaction); }); - it('should initialize a multisignature transaction', async () => { + it('should initialize a multisignature transaction', () => { const multisignature = { type: 12, nonce: '0', diff --git a/elements/lisk-chain/test/unit/transactions.spec.ts b/elements/lisk-chain/test/unit/transactions.spec.ts index aa6d3535c2a..19c60e978f1 100644 --- a/elements/lisk-chain/test/unit/transactions.spec.ts +++ b/elements/lisk-chain/test/unit/transactions.spec.ts @@ -53,7 +53,7 @@ describe('blocks/transactions', () => { let storageStub: any; let slots: Slots; - beforeEach(async () => { + beforeEach(() => { storageStub = { entities: { Account: { @@ -136,7 +136,7 @@ describe('blocks/transactions', () => { notAllowedTx.type, ); Object.defineProperty(transactionClass.prototype, 'matcher', { - get: () => () => false, + get: () => (): boolean => false, configurable: true, }); (chainInstance as any).dataAccess._transactionAdapter._transactionClassMap.set( @@ -234,14 +234,14 @@ describe('blocks/transactions', () => { ); }); - it('should return all transactions', async () => { + it('should return all transactions', () => { // Assert expect(result).toHaveLength(2); expect(result[0].id).toBe(validTx.id); expect(result[1].id).toBe(validTx2.id); }); - it('should call apply for all transactions', async () => { + it('should call apply for all transactions', () => { // Assert expect(validTxSpy).toHaveBeenCalledTimes(1); expect(validTx2Spy).toHaveBeenCalledTimes(1); @@ -279,7 +279,7 @@ describe('blocks/transactions', () => { notAllowedTx.type, ); Object.defineProperty(transactionClass.prototype, 'matcher', { - get: () => () => false, + get: () => (): boolean => false, configurable: true, }); (chainInstance as any).dataAccess._transactionAdapter._transactionClassMap.set( @@ -393,14 +393,14 @@ describe('blocks/transactions', () => { responses = transactionsResponses as TransactionResponse[]; }); - it('should return all transactions response which are all ok', async () => { + it('should return all transactions response which are all ok', () => { // Assert expect(responses).toHaveLength(2); expect(responses.every(res => res.status === 1)).toBeTrue(); expect(responses.every(res => res.errors.length === 0)).toBeTrue(); }); - it('should invoke transaction validations', async () => { + it('should invoke transaction validations', () => { expect(validTxValidateSpy).toHaveBeenCalledTimes(1); expect(validTx2ValidateSpy).toHaveBeenCalledTimes(1); }); @@ -438,7 +438,7 @@ describe('blocks/transactions', () => { notAllowedTx.type, ); Object.defineProperty(transactionClass.prototype, 'matcher', { - get: () => () => false, + get: () => (): boolean => false, configurable: true, }); (chainInstance as any).dataAccess._transactionAdapter._transactionClassMap.set( @@ -583,13 +583,13 @@ describe('blocks/transactions', () => { responses = transactionsResponses as TransactionResponse[]; }); - it('should return transaction with all status 1', async () => { + it('should return transaction with all status 1', () => { expect(responses).toHaveLength(2); expect(responses.every(res => res.status === 1)).toBeTrue(); expect(responses.every(res => res.errors.length === 0)).toBeTrue(); }); - it('should call apply for all the transactions', async () => { + it('should call apply for all the transactions', () => { expect(validTxApplySpy).toHaveBeenCalledTimes(1); expect(validTx2ApplySpy).toHaveBeenCalledTimes(1); }); diff --git a/elements/lisk-chain/test/unit/transactions_handlers.spec.ts b/elements/lisk-chain/test/unit/transactions_handlers.spec.ts index ea2a37a958f..08e9d7db932 100644 --- a/elements/lisk-chain/test/unit/transactions_handlers.spec.ts +++ b/elements/lisk-chain/test/unit/transactions_handlers.spec.ts @@ -33,10 +33,10 @@ describe('transactions', () => { let dataAccessMock: any; let stateStoreMock: any; - beforeEach(async () => { + beforeEach(() => { // Add matcher to transactions - trs1.matcher = () => true; - trs2.matcher = () => true; + trs1.matcher = (): boolean => true; + trs2.matcher = (): boolean => true; // Add prepare steps to transactions trs1.prepare = jest.fn(); @@ -70,7 +70,7 @@ describe('transactions', () => { }); describe('#checkAllowedTransactions', () => { - it('should return a proper response format', async () => { + it('should return a proper response format', () => { // Act const response = transactionHandlers.checkAllowedTransactions( dummyState, @@ -86,11 +86,11 @@ describe('transactions', () => { ]); }); - it('in case of non allowed transactions, it should return responses with TransactionStatus.FAIL and proper error message', async () => { + it('in case of non allowed transactions, it should return responses with TransactionStatus.FAIL and proper error message', () => { // Arrange const disallowedTransaction = { ...trs1, - matcher: () => false, + matcher: (): boolean => false, }; // Act @@ -99,17 +99,18 @@ describe('transactions', () => { )([disallowedTransaction]); // Assert - expect(response.length).toBe(1); + expect(response).toHaveLength(1); expect(response[0]).toHaveProperty('id', disallowedTransaction.id); expect(response[0]).toHaveProperty('status', TransactionStatus.FAIL); - expect(response[0].errors.length).toBe(1); + expect(response[0].errors).toHaveLength(1); expect(response[0].errors[0]).toBeInstanceOf(Error); expect(response[0].errors[0].message).toBe( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `Transaction type ${disallowedTransaction.type} is currently not allowed.`, ); }); - it('should report a transaction as allowed if it does not implement matcher', async () => { + it('should report a transaction as allowed if it does not implement matcher', () => { // Arrange const { matcher, ...transactionWithoutMatcherImpl } = trs1; @@ -119,20 +120,20 @@ describe('transactions', () => { )([transactionWithoutMatcherImpl]); // Assert - expect(response.length).toBe(1); + expect(response).toHaveLength(1); expect(response[0]).toHaveProperty( 'id', transactionWithoutMatcherImpl.id, ); expect(response[0]).toHaveProperty('status', TransactionStatus.OK); - expect(response[0].errors.length).toBe(0); + expect(response[0].errors).toHaveLength(0); }); - it('in case of allowed transactions, it should return responses with TransactionStatus.OK and no errors', async () => { + it('in case of allowed transactions, it should return responses with TransactionStatus.OK and no errors', () => { // Arrange const allowedTransaction = { ...trs1, - matcher: () => true, + matcher: (): boolean => true, }; // Act @@ -141,19 +142,19 @@ describe('transactions', () => { )([allowedTransaction]); // Assert - expect(response.length).toBe(1); + expect(response).toHaveLength(1); expect(response[0]).toHaveProperty('id', allowedTransaction.id); expect(response[0]).toHaveProperty('status', TransactionStatus.OK); - expect(response[0].errors.length).toBe(0); + expect(response[0].errors).toHaveLength(0); }); - it('should return a mix of responses including allowed and disallowed transactions', async () => { + it('should return a mix of responses including allowed and disallowed transactions', () => { // Arrange const testTransactions = [ trs1, // Allowed { ...trs1, - matcher: () => false, // Disallowed + matcher: (): boolean => false, // Disallowed }, ]; @@ -163,18 +164,19 @@ describe('transactions', () => { ); // Assert - expect(response.length).toBe(2); + expect(response).toHaveLength(2); // Allowed transaction formatted response check expect(response[0]).toHaveProperty('id', testTransactions[0].id); expect(response[0]).toHaveProperty('status', TransactionStatus.OK); - expect(response[0].errors.length).toBe(0); + expect(response[0].errors).toHaveLength(0); // Allowed transaction formatted response check expect(response[1]).toHaveProperty('id', testTransactions[1].id); expect(response[1]).toHaveProperty('status', TransactionStatus.FAIL); - expect(response[1].errors.length).toBe(1); + expect(response[1].errors).toHaveLength(1); expect(response[1].errors[0]).toBeInstanceOf(Error); expect(response[1].errors[0].message).toBe( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `Transaction type ${testTransactions[1].type} is currently not allowed.`, ); }); @@ -184,19 +186,19 @@ describe('transactions', () => { const validResponse = { status: TransactionStatus.OK, id: trs1.id }; const invalidResponse = { status: TransactionStatus.FAIL, id: trs2.id }; - beforeEach(async () => { + beforeEach(() => { trs1.validate = jest.fn().mockReturnValue(validResponse); trs2.validate = jest.fn().mockReturnValue(invalidResponse); }); - it('should invoke validate() on each transaction', async () => { + it('should invoke validate() on each transaction', () => { transactionHandlers.validateTransactions()([trs1, trs2]); expect(trs1.validate).toHaveBeenCalledTimes(1); expect(trs2.validate).toHaveBeenCalledTimes(1); }); - it('should return transaction responses', async () => { + it('should return transaction responses', () => { const result = transactionHandlers.validateTransactions()([trs1, trs2]); expect(result).toEqual([validResponse, invalidResponse]); @@ -256,6 +258,7 @@ describe('transactions', () => { ); expect((transactionResponse as any).errors).toHaveLength(1); expect((transactionResponse as any).errors[0].message).toEqual( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions `Transaction is already confirmed: ${trs1.id}`, ); }); @@ -271,7 +274,7 @@ describe('transactions', () => { id: trs2.id, }; - beforeEach(async () => { + beforeEach(() => { trs1.apply.mockReturnValue(trs1Response); trs2.apply.mockReturnValue(trs2Response); }); @@ -325,7 +328,7 @@ describe('transactions', () => { let trs1Response: TransactionResponse; let trs2Response: TransactionResponse; - beforeEach(async () => { + beforeEach(() => { trs1Response = { status: TransactionStatus.OK, id: trs1.id, @@ -356,7 +359,7 @@ describe('transactions', () => { let trs1Response: TransactionResponse; let trs2Response: TransactionResponse; - beforeEach(async () => { + beforeEach(() => { trs1Response = { status: TransactionStatus.OK, id: trs1.id, diff --git a/elements/lisk-chain/test/utils/block.ts b/elements/lisk-chain/test/utils/block.ts index f364201240e..052118c740d 100644 --- a/elements/lisk-chain/test/utils/block.ts +++ b/elements/lisk-chain/test/utils/block.ts @@ -22,9 +22,9 @@ import { LITTLE_ENDIAN, } from '@liskhq/lisk-cryptography'; import { Mnemonic } from '@liskhq/lisk-passphrase'; -import * as genesisBlock from '../fixtures/genesis_block.json'; -import { BlockJSON, BlockInstance } from '../../src/types.js'; import { BaseTransaction } from '@liskhq/lisk-transactions'; +import * as genesisBlock from '../fixtures/genesis_block.json'; +import { BlockJSON, BlockInstance } from '../../src/types'; const SIZE_INT32 = 4; const SIZE_INT64 = 8; @@ -119,10 +119,11 @@ export const getBytes = (block: BlockInstance): Buffer => { ]); }; -const sortTransactions = (transactions: BaseTransaction[]) => +const sortTransactions = (transactions: BaseTransaction[]): void => { transactions.sort((a, b) => (a.type > b.type || a.id > b.id) as any); +}; -const getKeyPair = () => { +const getKeyPair = (): { publicKey: Buffer; privateKey: Buffer } => { const passphrase = Mnemonic.generateMnemonic(); const { publicKeyBytes: publicKey, @@ -134,21 +135,22 @@ const getKeyPair = () => { }; }; +// eslint-disable-next-line @typescript-eslint/explicit-function-return-type const calculateTransactionsInfo = (block: BlockInstance) => { - const sortedTransactions = sortTransactions(block.transactions); + sortTransactions(block.transactions); const transactionsBytesArray = []; let totalFee = BigInt(0); let totalAmount = BigInt(0); let payloadLength = 0; - // eslint-disable-next-line no-plusplus - for (let i = 0; i < sortedTransactions.length; i++) { - const transaction = sortedTransactions[i]; + // eslint-disable-next-line @typescript-eslint/prefer-for-of + for (let i = 0; i < block.transactions.length; i += 1) { + const transaction = block.transactions[i]; const transactionBytes = transaction.getBytes(); - totalFee = totalFee + BigInt(transaction.fee); - totalAmount = - totalAmount + BigInt((transaction as any).asset.amount || '0'); + totalFee += BigInt(transaction.fee); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + totalAmount += BigInt((transaction as any).asset.amount || '0'); payloadLength += transactionBytes.length; transactionsBytesArray.push(transactionBytes); diff --git a/elements/lisk-chain/test/utils/random.ts b/elements/lisk-chain/test/utils/random.ts index c7a73c0b970..3584d0fc1ab 100644 --- a/elements/lisk-chain/test/utils/random.ts +++ b/elements/lisk-chain/test/utils/random.ts @@ -32,7 +32,7 @@ const networkIdentifier = getNetworkIdentifier( 'Lisk', ); -const delegateName = () => { +const delegateName = (): string => { const randomLetter = randomstring.generate({ length: 1, charset: 'alphabetic', @@ -47,6 +47,7 @@ const delegateName = () => { return randomLetter.concat(username); }; +// eslint-disable-next-line export const account = (balance = '0', nonDelegate = false) => { const passphrase = Mnemonic.generateMnemonic(); return { @@ -63,7 +64,7 @@ export const transaction = (nonce?: string): TransactionJSON => transfer({ networkIdentifier, fee: '10000000', - nonce: nonce ? nonce : '0', + nonce: nonce ?? '0', amount: '1', passphrase: genesisAccount.passphrase, recipientId: account().address, diff --git a/elements/lisk-chain/tslint.json b/elements/lisk-chain/tslint.json deleted file mode 120000 index 7566d21211d..00000000000 --- a/elements/lisk-chain/tslint.json +++ /dev/null @@ -1 +0,0 @@ -../../templates/tslint.json.tmpl \ No newline at end of file