From 34b575389a27d9db5eca55a83b715bfc78564df2 Mon Sep 17 00:00:00 2001 From: Vardan Nadkarni Date: Wed, 22 Nov 2023 13:14:44 +0530 Subject: [PATCH 1/7] Added support for receivingChainID to be currentChainID in transactions API --- framework/tests/unit/cacheRedis.spec.js | 4 --- .../blockchain-connector/shared/sdk/schema.js | 17 +++++----- .../business/pendingTransactions.js | 12 ++++++- .../dataService/business/transactions.js | 10 ++++++ .../gateway/tests/unit/shared/status.test.js | 33 +++++-------------- 5 files changed, 39 insertions(+), 37 deletions(-) diff --git a/framework/tests/unit/cacheRedis.spec.js b/framework/tests/unit/cacheRedis.spec.js index e70ea87f8e..a4276a23e2 100644 --- a/framework/tests/unit/cacheRedis.spec.js +++ b/framework/tests/unit/cacheRedis.spec.js @@ -13,10 +13,6 @@ * Removal or modification of this copyright notice is prohibited. * */ -// TODO: mock Redis -// const { redis } = require('redis-mock'); -// jest.doMock('redis', () => redis); - const Cache = require('../../src/cacheRedis'); const customMemoryBank = 'memBank'; diff --git a/services/blockchain-connector/shared/sdk/schema.js b/services/blockchain-connector/shared/sdk/schema.js index b2cf42b5f0..19f1b81a6a 100644 --- a/services/blockchain-connector/shared/sdk/schema.js +++ b/services/blockchain-connector/shared/sdk/schema.js @@ -51,14 +51,15 @@ const getBlockAssetDataSchemaByModule = _module => { const getDataSchemaByEventName = eventName => { if (EVENT_NAME_COMMAND_EXECUTION_RESULT === eventName) return schemas.standardEvent; - // TODO: Optimize - for (let i = 0; i < metadata.modules.length; i++) { - const module = metadata.modules[i]; - - for (let eventIndex = 0; eventIndex < module.events.length; eventIndex++) { - const moduleEvent = module.events[eventIndex]; - if (moduleEvent.name === eventName) return module.events[eventIndex].data; - } + // Find the module that contains the event + const moduleWithEvent = metadata.modules.find(module => + module.events.some(moduleEvent => moduleEvent.name === eventName), + ); + + if (moduleWithEvent) { + // Find the event and return its data schema + const moduleEvent = moduleWithEvent.events.find(event => event.name === eventName); + return moduleEvent ? moduleEvent.data : null; } return null; diff --git a/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js b/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js index 552a182c5f..64bedc9e75 100644 --- a/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js +++ b/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js @@ -21,6 +21,7 @@ const { const logger = Logger(); +const { getCurrentChainID } = require('./interoperability/chain'); const { normalizeTransaction } = require('./transactions'); const { getIndexedAccountInfo } = require('../utils/account'); const { requestConnector } = require('../../utils/request'); @@ -92,7 +93,16 @@ const validateParams = async params => { if (params.senderAddress) validatedParams.senderAddress = params.senderAddress; if (params.recipientAddress) validatedParams.recipientAddress = params.recipientAddress; if (params.moduleCommand) validatedParams.moduleCommand = params.moduleCommand; - if (params.receivingChainID) validatedParams.receivingChainID = params.receivingChainID; + + // If recieving chainID is current chain ID then return all transactions with receivingChainID = null + if (params.receivingChainID) { + const currentChainID = await getCurrentChainID(); + + if (params.receivingChainID === currentChainID) { + params.receivingChainID = null; + } + } + if (params.sort) validatedParams.sort = params.sort; return validatedParams; diff --git a/services/blockchain-indexer/shared/dataService/business/transactions.js b/services/blockchain-indexer/shared/dataService/business/transactions.js index d0edc6cf7d..e74aca8582 100644 --- a/services/blockchain-indexer/shared/dataService/business/transactions.js +++ b/services/blockchain-indexer/shared/dataService/business/transactions.js @@ -25,6 +25,7 @@ const { const { getBlockByID } = require('./blocks'); const { getEventsByHeight } = require('./events'); +const { getCurrentChainID } = require('./interoperability/chain'); const { getIndexedAccountInfo } = require('../utils/account'); const { requestConnector } = require('../../utils/request'); const { normalizeRangeParam } = require('../../utils/param'); @@ -88,6 +89,15 @@ const validateParams = async params => { ); } + // If recieving chainID is current chain ID then return all transactions with receivingChainID = null + if (params.receivingChainID) { + const currentChainID = await getCurrentChainID(); + + if (params.receivingChainID === currentChainID) { + params.receivingChainID = null; + } + } + if (params.executionStatus) { const { executionStatus, ...remParams } = params; params = remParams; diff --git a/services/gateway/tests/unit/shared/status.test.js b/services/gateway/tests/unit/shared/status.test.js index 44504f3587..13e4ef759a 100644 --- a/services/gateway/tests/unit/shared/status.test.js +++ b/services/gateway/tests/unit/shared/status.test.js @@ -22,43 +22,28 @@ const { }, } = require('lisk-service-framework'); -const { getBuildTimestamp } = require('../../../shared/status'); - describe('Test getBuildTimestamp method', () => { const dateStr = '2999-03-21T11:15:59.337Z'; const jsonStr = `{"timestamp": "${dateStr}"}`; const filePath = path.resolve(__dirname, '../../../build.json'); - let fileExistBefore = false; - - beforeAll( - async () => - new Promise((resolve, reject) => { - exists(filePath).then(isExists => { - fileExistBefore = isExists; - if (!isExists) { - return fs.writeFile(filePath, jsonStr, err => { - if (err) return reject(err); - return resolve(); - }); - } - return resolve(); - }); - }), - ); + it('should return current time from the file when build.json file exists', async () => { + const isExists = await exists(filePath); - afterAll(async () => { - if (!fileExistBefore) await rmdir(filePath); - }); + if (!isExists) { + await fs.promises.writeFile(filePath, jsonStr); + } - // TODO: Test is executed before file creation. This needs to be fixed before enabling the tests - xit('should return current time from the file when build.json file exists', async () => { + const { getBuildTimestamp } = require('../../../shared/status'); const response = await getBuildTimestamp(); expect(response).toEqual(dateStr); + + if (!isExists) await rmdir(filePath); }); it('should return current time when build.json file does not exists', async () => { const curDate = new Date(); + const { getBuildTimestamp } = require('../../../shared/status'); const response = await getBuildTimestamp(); expect(new Date(response).getTime()).toBeGreaterThanOrEqual(curDate.getTime()); }); From f55c04fe6a8dc836a4760db797a95aa8c52cee56 Mon Sep 17 00:00:00 2001 From: Vardan Nadkarni Date: Wed, 22 Nov 2023 16:35:46 +0530 Subject: [PATCH 2/7] Fixed TODOs from tests --- .../apis/http-exports/swagger/responses.json | 4 ++-- .../apis/http-version3/swagger/responses.json | 4 ++-- services/gateway/tests/constants/utils.js | 4 ++-- .../integration/api_v3/events/transactions.test.js | 13 +++++++++---- tests/integration/api_v3/rpc/blockchainApps.test.js | 1 - tests/schemas/api_v3/allSchemas.schema.js | 9 +++------ tests/schemas/api_v3/block.schema.js | 4 ++-- tests/schemas/api_v3/spec.schema.js | 6 ++---- 8 files changed, 22 insertions(+), 23 deletions(-) diff --git a/services/gateway/apis/http-exports/swagger/responses.json b/services/gateway/apis/http-exports/swagger/responses.json index 3d3f28116f..eabdfb86ce 100644 --- a/services/gateway/apis/http-exports/swagger/responses.json +++ b/services/gateway/apis/http-exports/swagger/responses.json @@ -1,12 +1,12 @@ { "responses": { - "badParameter": { + "400": { "description": "Bad request", "schema": { "$ref": "#/definitions/badRequest" } }, - "notFound": { + "404": { "description": "Not found", "schema": { "$ref": "#/definitions/notFound" diff --git a/services/gateway/apis/http-version3/swagger/responses.json b/services/gateway/apis/http-version3/swagger/responses.json index 3d3f28116f..eabdfb86ce 100644 --- a/services/gateway/apis/http-version3/swagger/responses.json +++ b/services/gateway/apis/http-version3/swagger/responses.json @@ -1,12 +1,12 @@ { "responses": { - "badParameter": { + "400": { "description": "Bad request", "schema": { "$ref": "#/definitions/badRequest" } }, - "notFound": { + "404": { "description": "Not found", "schema": { "$ref": "#/definitions/notFound" diff --git a/services/gateway/tests/constants/utils.js b/services/gateway/tests/constants/utils.js index 4b6d28b185..3680985fa0 100644 --- a/services/gateway/tests/constants/utils.js +++ b/services/gateway/tests/constants/utils.js @@ -240,13 +240,13 @@ const requireAllJsonExpectedResponse = { paths: {}, }, responses: { - badParameter: { + 400: { description: 'Bad request', schema: { $ref: '#/definitions/badRequest', }, }, - notFound: { + 404: { description: 'Not found', schema: { $ref: '#/definitions/notFound', diff --git a/tests/integration/api_v3/events/transactions.test.js b/tests/integration/api_v3/events/transactions.test.js index 09a4682989..8111b59bcc 100644 --- a/tests/integration/api_v3/events/transactions.test.js +++ b/tests/integration/api_v3/events/transactions.test.js @@ -25,18 +25,23 @@ const { postTransactionSchema, } = require('../../../schemas/api_v3/transaction.schema'); +const { createTokenTransferTx } = require('../txUtil/createTx'); +const { encodeTransaction } = require('../txUtil/encodeTx'); + const baseUrl = config.SERVICE_ENDPOINT; const baseUrlV3 = `${baseUrl}/api/v3`; const endpoint = `${config.SERVICE_ENDPOINT_RPC}/blockchain`; +const authEndpoint = `${baseUrlV3}/auth`; -// TODO: Enable/update test cases once test blockchain is updated -xdescribe('Test subscribe API transaction event', () => { +describe('Test subscribe API transaction event', () => { it('event new.transactions', async () => { + const transaction = await createTokenTransferTx(authEndpoint); + const encodedTx = await encodeTransaction(transaction, baseUrlV3); + // Post signed transaction to lisk-core (test blockchain CI) const postTransaction = await api.post(`${baseUrlV3}/transactions`, { - transaction: - '0802100018002080c2d72f2a200fe9a3f1a21b5530f27f87a414b549e79a940bf24fdf2b2f05e7f22aeeecc86a32240880c2d72f1214df0e187bb3895806261c87cf66e1772566ee8e581a07746573742074783a40a972e48ab2ed5222311538ba7bbd3ab139e2d1e8ce07096a277e53859beaedd3641b6cd5498d489514a2f9dbeb1092c4ceb27cd4f387ca3687dd8c3cfc833d02', + transaction: encodedTx, }); expect(postTransaction).toMap(postTransactionSchema); diff --git a/tests/integration/api_v3/rpc/blockchainApps.test.js b/tests/integration/api_v3/rpc/blockchainApps.test.js index c53a8600b4..3516d8d197 100644 --- a/tests/integration/api_v3/rpc/blockchainApps.test.js +++ b/tests/integration/api_v3/rpc/blockchainApps.test.js @@ -37,7 +37,6 @@ const getNetworkStatus = async params => request(wsRpcUrl, 'get.network.status', let curChainID; -// TODO: Update test when data is available in blockchain_apps table describe('get.blockchain.apps', () => { beforeAll(async () => { const response = await getNetworkStatus(); diff --git a/tests/schemas/api_v3/allSchemas.schema.js b/tests/schemas/api_v3/allSchemas.schema.js index 827fb505fa..40ef2023d0 100644 --- a/tests/schemas/api_v3/allSchemas.schema.js +++ b/tests/schemas/api_v3/allSchemas.schema.js @@ -28,8 +28,7 @@ const schema = { const commandsParamsSchemasSchema = { moduleCommand: Joi.string().pattern(regex.MODULE_COMMAND).required(), - // TODO: Update schema to required when all schemas are available from SDK - schema: Joi.object(schema).optional(), + schema: Joi.object(schema).required(), }; const messagesSchema = { @@ -41,15 +40,13 @@ const messagesSchema = { const eventsSchema = { module: Joi.string().pattern(regex.MODULE).required(), name: Joi.string().pattern(regex.EVENT_NAME).required(), - // TODO: Update schema to required when all schemas are available from SDK - schema: Joi.object(schema).optional(), + schema: Joi.object(schema).required(), }; const assetsSchema = { module: Joi.string().pattern(regex.MODULE).required(), version: Joi.string().required(), - // TODO: Update schema to required when all schemas are available from SDK - schema: Joi.object(schema).optional(), + schema: Joi.object(schema).required(), }; const genericSchema = { diff --git a/tests/schemas/api_v3/block.schema.js b/tests/schemas/api_v3/block.schema.js index 7ab42ea12b..1589603f4b 100644 --- a/tests/schemas/api_v3/block.schema.js +++ b/tests/schemas/api_v3/block.schema.js @@ -52,8 +52,8 @@ const blockSchema = { maxHeightPrevoted: Joi.number().required(), validatorsHash: Joi.string().pattern(regex.HASH_SHA256).required(), numberOfTransactions: Joi.number().integer().min(0).required(), - numberOfAssets: Joi.number().integer().min(1).required(), - numberOfEvents: Joi.number().integer().min(1).required(), + numberOfAssets: Joi.number().integer().min(0).required(), + numberOfEvents: Joi.number().integer().min(0).required(), }; const block = { diff --git a/tests/schemas/api_v3/spec.schema.js b/tests/schemas/api_v3/spec.schema.js index f069a6e438..a5e3568e91 100644 --- a/tests/schemas/api_v3/spec.schema.js +++ b/tests/schemas/api_v3/spec.schema.js @@ -14,7 +14,7 @@ * */ import Joi from 'joi'; -// import regex from './regex'; +import regex from './regex'; const SWAGGER_VERSION = ['2.0']; const SWAGGER_PARAMETER_BODY = ['body']; @@ -224,9 +224,7 @@ const nonBodyParameter = Joi.alternatives( const parameter = Joi.alternatives(bodyParameter, nonBodyParameter.optional()).optional(); -// TODO: Enable when swagger response key is mapped as per schema -// const responseKey = Joi.string().pattern(regex.SWAGGER_RESPONSE_KEY).min(1).required(); -const responseKey = Joi.string().min(1).required(); +const responseKey = Joi.string().pattern(regex.SWAGGER_RESPONSE_KEY).min(1).required(); const responseEntry = Joi.alternatives( Joi.object(response).optional(), Joi.object(jsonReference).optional(), From 6082e7bbac81a7b5d181b0053fcc6eb060197225 Mon Sep 17 00:00:00 2001 From: Vardan Nadkarni Date: Wed, 22 Nov 2023 18:07:42 +0530 Subject: [PATCH 3/7] Add check so that only one pair is accepted among the validParamPairings --- .../dataService/business/pos/stakers.js | 4 ---- services/gateway/shared/paramValidator.js | 20 ++++++++++--------- services/gateway/shared/registerHttpApi.js | 4 +++- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/services/blockchain-indexer/shared/dataService/business/pos/stakers.js b/services/blockchain-indexer/shared/dataService/business/pos/stakers.js index 00d2b7a902..16a34ea32f 100644 --- a/services/blockchain-indexer/shared/dataService/business/pos/stakers.js +++ b/services/blockchain-indexer/shared/dataService/business/pos/stakers.js @@ -59,8 +59,6 @@ const getStakers = async params => { params = remParams; const address = getLisk32AddressFromPublicKey(publicKey); - // TODO: Remove once gateway param pairings check is updated - if (params.validatorAddress && params.validatorAddress !== address) return stakersResponse; params.validatorAddress = address; stakersResponse.meta.validator.address = params.validatorAddress; @@ -75,8 +73,6 @@ const getStakers = async params => { params = remParams; const { address } = await getIndexedAccountInfo({ name }, ['address']); - // TODO: Remove once gateway param pairings check is updated - if (params.validatorAddress && params.validatorAddress !== address) return stakersResponse; params.validatorAddress = address; stakersResponse.meta.validator.name = name; diff --git a/services/gateway/shared/paramValidator.js b/services/gateway/shared/paramValidator.js index 96038b649c..a4cef28553 100644 --- a/services/gateway/shared/paramValidator.js +++ b/services/gateway/shared/paramValidator.js @@ -65,20 +65,23 @@ const parseParams = p => { }; }; -// Returns empty array if inputParamKeys matches with one of the schema paramPairings. +// Returns empty array if inputParamKeys matches with only one of the schema paramPairings. // Otherwise, returns the schema paramPairings const validateFromParamPairings = (paramsRequired = false, inputParamKeys, paramPairings) => { if (!paramsRequired) return []; - const relevantPairings = paramPairings.filter(pairing => - inputParamKeys.some(key => pairing.includes(key)), + // Remove elements not part of paramPairings + const filteredInputParamKeys = inputParamKeys.filter(element => + paramPairings.some(subArray => subArray.includes(element)), ); - if (relevantPairings.length === 0) return paramPairings; - const result = relevantPairings.some(pairing => - pairing.every(param => inputParamKeys.includes(param)), - ); - return result ? [] : paramPairings; + return paramPairings.find( + arr => + arr.length === filteredInputParamKeys.length && + arr.every(el => filteredInputParamKeys.includes(el)), + ) + ? [] + : paramPairings; }; // Returns a list of required routeParams which are not present in requestParams @@ -114,7 +117,6 @@ const looseSpecParams = specPar => return acc; }, {}); -// TODO: Add check so that only one pair is accepted among the validParamPairings const validateInputParams = (rawInputParams = {}, specs) => { const specParams = specs.params || {}; const inputParams = rawInputParams; diff --git a/services/gateway/shared/registerHttpApi.js b/services/gateway/shared/registerHttpApi.js index d3f7b04877..9477a1e793 100644 --- a/services/gateway/shared/registerHttpApi.js +++ b/services/gateway/shared/registerHttpApi.js @@ -138,7 +138,9 @@ const buildAPIConfig = ( if (paramReport.required.length) { throw new ValidationException( - `Require one of the following parameter combination(s): ${paramReport.required.join('; ')}`, + `Require only one of the following parameter combination(s): ${paramReport.required.join( + '; ', + )}`, ); } From a38255e22551f6e9edf32579f4347530a250a424 Mon Sep 17 00:00:00 2001 From: Vardan Nadkarni Date: Wed, 22 Nov 2023 20:43:58 +0530 Subject: [PATCH 4/7] Removed unnecessary TODOs --- .../shared/sdk/constants/eventTopics.js | 1 - .../shared/sdk/formatter.js | 18 +++++++----------- .../blockchain-connector/shared/sdk/schema.js | 19 +++++++++---------- .../shared/utils/account.js | 2 +- .../interoperability/blockchainApps.js | 1 - .../interoperability/blockchainAppsStats.js | 1 - .../dataService/business/pos/validators.js | 4 ---- .../shared/dataService/generators.js | 1 - .../shared/dataService/pos/validators.js | 4 ---- .../gateway/tests/constants/registerApi.js | 2 -- .../shared/buildTransactionStatistics.js | 2 -- 11 files changed, 17 insertions(+), 38 deletions(-) diff --git a/services/blockchain-connector/shared/sdk/constants/eventTopics.js b/services/blockchain-connector/shared/sdk/constants/eventTopics.js index 854653cfe9..c2e9403e4b 100644 --- a/services/blockchain-connector/shared/sdk/constants/eventTopics.js +++ b/services/blockchain-connector/shared/sdk/constants/eventTopics.js @@ -79,7 +79,6 @@ const { const COMMAND_EXECUTION_RESULT_TOPICS = ['transactionID']; -// TODO: Remove when SDK exposes topics information in metadata const EVENT_TOPIC_MAPPINGS_BY_MODULE = { [MODULE_NAME_AUTH]: { [EVENT_NAME_MULTISIGNATURE_REGISTERED]: ['transactionID', 'senderAddress'], diff --git a/services/blockchain-connector/shared/sdk/formatter.js b/services/blockchain-connector/shared/sdk/formatter.js index 828972efa9..7b6d70469c 100644 --- a/services/blockchain-connector/shared/sdk/formatter.js +++ b/services/blockchain-connector/shared/sdk/formatter.js @@ -157,13 +157,11 @@ const formatEvent = (event, skipDecode) => { } if (!eventDataSchema) { - // TODO: Remove this after SDK exposes all event schemas (before tagging rc.0) - console.error(`Event data schema missing for ${event.module}:${event.name}.`); logger.error( `Unable to decode event data. Event data schema missing for ${event.module}:${event.name}.`, ); } else { - // TODO: Remove after SDK fixes the address format (before tagging rc.0) + // TODO: Remove after SDK fixes the address format (https://github.com/LiskHQ/lisk-sdk/issues/7629) Object.keys(eventDataSchema.properties).forEach(prop => { if (prop.endsWith('Address')) { eventData[prop] = getLisk32Address(eventData[prop].toString('hex')); @@ -173,10 +171,9 @@ const formatEvent = (event, skipDecode) => { } const eventTopicMappings = EVENT_TOPIC_MAPPINGS_BY_MODULE[event.module] || {}; - // TODO: Remove after all transaction types are tested (before tagging rc.0) if (!(event.module in EVENT_TOPIC_MAPPINGS_BY_MODULE)) { - console.error(`EVENT_TOPIC_MAPPINGS_BY_MODULE missing for module: ${event.module}.`); - console.info(inspect(event)); + logger.error(`EVENT_TOPIC_MAPPINGS_BY_MODULE missing for module: ${event.module}.`); + logger.info(inspect(event)); } const topics = @@ -184,13 +181,12 @@ const formatEvent = (event, skipDecode) => { ? COMMAND_EXECUTION_RESULT_TOPICS : eventTopicMappings[event.name]; - // TODO: Remove after all transaction types are tested (before tagging rc.0) if (!topics || topics.length === 0) { - console.error(`EVENT_TOPIC_MAPPINGS_BY_MODULE undefined for event: ${event.name}.`); - console.info(inspect(event)); + logger.error(`EVENT_TOPIC_MAPPINGS_BY_MODULE undefined for event: ${event.name}.`); + logger.info(inspect(event)); } else if (topics.length !== event.topics.length) { - console.error(`EVENT_TOPIC_MAPPINGS_BY_MODULE defined incorrectly for event: ${event.name}.`); - console.info(inspect(event)); + logger.error(`EVENT_TOPIC_MAPPINGS_BY_MODULE defined incorrectly for event: ${event.name}.`); + logger.info(inspect(event)); } let eventTopics; diff --git a/services/blockchain-connector/shared/sdk/schema.js b/services/blockchain-connector/shared/sdk/schema.js index 19f1b81a6a..485492a388 100644 --- a/services/blockchain-connector/shared/sdk/schema.js +++ b/services/blockchain-connector/shared/sdk/schema.js @@ -17,6 +17,7 @@ const { EVENT_NAME_COMMAND_EXECUTION_RESULT } = require('./constants/names'); let schemas; let metadata; +const eventSchemaLookup = {}; const setSchemas = _schemas => (schemas = _schemas); @@ -51,18 +52,16 @@ const getBlockAssetDataSchemaByModule = _module => { const getDataSchemaByEventName = eventName => { if (EVENT_NAME_COMMAND_EXECUTION_RESULT === eventName) return schemas.standardEvent; - // Find the module that contains the event - const moduleWithEvent = metadata.modules.find(module => - module.events.some(moduleEvent => moduleEvent.name === eventName), - ); - - if (moduleWithEvent) { - // Find the event and return its data schema - const moduleEvent = moduleWithEvent.events.find(event => event.name === eventName); - return moduleEvent ? moduleEvent.data : null; + // Populate the eventSchemaLookup map with module events if not exists + if (Object.keys(eventSchemaLookup).length === 0) { + metadata.modules.forEach(module => { + module.events.forEach(moduleEvent => { + eventSchemaLookup[moduleEvent.name] = moduleEvent.data; + }); + }); } - return null; + return eventSchemaLookup[eventName] || null; }; module.exports = { diff --git a/services/blockchain-connector/shared/utils/account.js b/services/blockchain-connector/shared/utils/account.js index 8eee546e24..961cea894c 100644 --- a/services/blockchain-connector/shared/utils/account.js +++ b/services/blockchain-connector/shared/utils/account.js @@ -32,7 +32,7 @@ const getLisk32AddressFromPublicKey = publicKey => const getLisk32AddressFromHexAddress = address => getLisk32AddressFromAddress(Buffer.from(address, 'hex')); -// TODO: Remove once SDK returns address in Lisk32 format +// TODO: Remove once SDK returns address in Lisk32 format (https://github.com/LiskHQ/lisk-sdk/issues/7629) const getLisk32Address = address => address.startsWith('lsk') ? address : getLisk32AddressFromHexAddress(address); diff --git a/services/blockchain-indexer/shared/dataService/business/interoperability/blockchainApps.js b/services/blockchain-indexer/shared/dataService/business/interoperability/blockchainApps.js index 8b383ae27f..981220cf78 100644 --- a/services/blockchain-indexer/shared/dataService/business/interoperability/blockchainApps.js +++ b/services/blockchain-indexer/shared/dataService/business/interoperability/blockchainApps.js @@ -44,7 +44,6 @@ const getLSKTokenID = async () => { }; const getBlockchainApps = async params => { - // TODO: Update implementation when interoperability_getOwnChainAccount is available const blockchainAppsTable = await getBlockchainAppsTable(); const blockchainAppsInfo = { diff --git a/services/blockchain-indexer/shared/dataService/business/interoperability/blockchainAppsStats.js b/services/blockchain-indexer/shared/dataService/business/interoperability/blockchainAppsStats.js index b9a286fcbf..8e6d89af12 100644 --- a/services/blockchain-indexer/shared/dataService/business/interoperability/blockchainAppsStats.js +++ b/services/blockchain-indexer/shared/dataService/business/interoperability/blockchainAppsStats.js @@ -49,7 +49,6 @@ const getBlockchainAppsStatistics = async () => { const reloadBlockchainAppsStats = async () => { try { - // TODO: Update implementation once interoperability_getOwnChainAccount is available const blockchainAppsTable = await getBlockchainAppsTable(); const numActivatedChains = await blockchainAppsTable.count({ status: APP_STATUS.ACTIVATED }); diff --git a/services/blockchain-indexer/shared/dataService/business/pos/validators.js b/services/blockchain-indexer/shared/dataService/business/pos/validators.js index ca2af8bcb5..5487af9286 100644 --- a/services/blockchain-indexer/shared/dataService/business/pos/validators.js +++ b/services/blockchain-indexer/shared/dataService/business/pos/validators.js @@ -30,7 +30,6 @@ const verifyIfPunished = async validator => { const latestBlockString = await lastBlockCache.get(LAST_BLOCK_KEY); const latestBlock = latestBlockString ? JSON.parse(latestBlockString) : {}; - // TODO: Get this information from SDK directly once available const isPunished = validator.reportMisbehaviorHeights.some( reportMisbehaviorHeight => reportMisbehaviorHeight.start <= latestBlock.height && @@ -47,9 +46,6 @@ const getPosValidators = async params => { validatorAddressList, async validatorAddress => { const validator = await requestConnector('getPosValidator', { address: validatorAddress }); - // TODO: Add error handling - // TODO: Verify - // TODO: Check if it is possible to move this logic to the connector if (validator.isBanned || (await verifyIfPunished(validator))) { validator.validatorWeight = BigInt('0'); } else { diff --git a/services/blockchain-indexer/shared/dataService/generators.js b/services/blockchain-indexer/shared/dataService/generators.js index ceb358e3e8..af34efc95c 100644 --- a/services/blockchain-indexer/shared/dataService/generators.js +++ b/services/blockchain-indexer/shared/dataService/generators.js @@ -30,7 +30,6 @@ const getGenerators = async params => { const generatorsList = await business.getGenerators(); const validatorList = await getAllValidators(); - // TODO: Optimize. Generate the map with every 'chain_*' event and maintain in the memory const validatorMap = new Map(validatorList.map(validator => [validator.address, validator])); generatorsList.forEach(generator => { if ( diff --git a/services/blockchain-indexer/shared/dataService/pos/validators.js b/services/blockchain-indexer/shared/dataService/pos/validators.js index 1d821c5c40..720dae3f97 100644 --- a/services/blockchain-indexer/shared/dataService/pos/validators.js +++ b/services/blockchain-indexer/shared/dataService/pos/validators.js @@ -255,7 +255,6 @@ const getPosValidators = async params => { return parseToJSONCompatObj(validators); }; -// TODO: Test // Keep the validator cache up-to-date const updateValidatorListEveryBlock = () => { const EVENT_NEW_BLOCK = 'newBlock'; @@ -271,7 +270,6 @@ const updateValidatorListEveryBlock = () => { if ([COMMAND.REGISTER_VALIDATOR, COMMAND.CHANGE_COMMISSION].includes(tx.command)) { updatedValidatorAddresses.push(getLisk32AddressFromPublicKey(tx.senderPublicKey)); } else if (tx.command === COMMAND.STAKE) { - // TODO: Verify tx.params.stakes.forEach(stake => updatedValidatorAddresses.push(stake.validatorAddress), ); @@ -279,7 +277,6 @@ const updateValidatorListEveryBlock = () => { } }); - // TODO: Validate the logic if there is need to update validator cache on (un-)stake tx if (updatedValidatorAddresses.length) { const updatedValidatorAccounts = await business.getPosValidators({ addresses: updatedValidatorAddresses, @@ -317,7 +314,6 @@ const updateValidatorListEveryBlock = () => { validatorList[validatorIndex] && Object.getOwnPropertyNames(validatorList[validatorIndex]).length ) { - // TODO: Update if ( validatorList[validatorIndex].generatedBlocks && validatorList[validatorIndex].rewards diff --git a/services/gateway/tests/constants/registerApi.js b/services/gateway/tests/constants/registerApi.js index 4e87a49b11..8691fd6ac7 100644 --- a/services/gateway/tests/constants/registerApi.js +++ b/services/gateway/tests/constants/registerApi.js @@ -13,7 +13,6 @@ * Removal or modification of this copyright notice is prohibited. * */ -// TODO: Expected response for registerApi method should be dynamically constructed const expectedResponseForRegisterHttpApi = [ { whitelist: [ @@ -116,7 +115,6 @@ const expectedResponseForRegisterHttpApi = [ }, ]; -// TODO: Expected response for registerApi method should be dynamically constructed const expectedResponseForRegisterRpcApi = { events: { request: { diff --git a/services/transaction-statistics/shared/buildTransactionStatistics.js b/services/transaction-statistics/shared/buildTransactionStatistics.js index 90f27cd096..80731a58ce 100644 --- a/services/transaction-statistics/shared/buildTransactionStatistics.js +++ b/services/transaction-statistics/shared/buildTransactionStatistics.js @@ -70,7 +70,6 @@ const getTxValue = tx => { const getRange = tx => { const txValue = getTxValue(tx); - // TODO: Make the conversion factor (1e8) dynamic based on token decimal const lowerBoundExponent = Math.floor(Math.log10(txValue / 1e8)); const lowerBound = Math.pow(10, lowerBoundExponent); const upperBound = Math.pow(10, lowerBoundExponent + 1); @@ -136,7 +135,6 @@ const insertToDB = async (statsList, date) => { statsList.map(statistic => { Object.assign(statistic, { date, amount_range: statistic.range }); - // TODO: Remove next line when CRUD operations are supported by composite primary key statistic.id = `${statistic.date}-${statistic.moduleCommand}-${statistic.amount_range}`; const { range, ...finalStats } = statistic; return finalStats; From 91ebf9299f8f0e9f98a1d725fdb719249aaca210 Mon Sep 17 00:00:00 2001 From: Vardan Nadkarni Date: Wed, 22 Nov 2023 21:48:01 +0530 Subject: [PATCH 5/7] Fixed pending transactions unit tests --- .../business/pendingTransactions.js | 7 +++- .../business/pendingTransactions.test.js | 38 ++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js b/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js index 64bedc9e75..762ac0ecf9 100644 --- a/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js +++ b/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js @@ -99,7 +99,9 @@ const validateParams = async params => { const currentChainID = await getCurrentChainID(); if (params.receivingChainID === currentChainID) { - params.receivingChainID = null; + validatedParams.currentChainTransactions = true; + } else { + validatedParams.receivingChainID = params.receivingChainID; } } @@ -145,7 +147,8 @@ const getPendingTransactions = async params => { (!validatedParams.moduleCommand || transaction.moduleCommand === validatedParams.moduleCommand) && (!validatedParams.receivingChainID || - transaction.params.receivingChainID === validatedParams.receivingChainID), + transaction.params.receivingChainID === validatedParams.receivingChainID) && + (!validatedParams.currentChainTransactions || !transaction.params.receivingChainID), ); pendingTransactions.data = filteredPendingTxs diff --git a/services/blockchain-indexer/tests/unit/shared/dataservice/business/pendingTransactions.test.js b/services/blockchain-indexer/tests/unit/shared/dataservice/business/pendingTransactions.test.js index 84a46b4217..b6ac420b6f 100644 --- a/services/blockchain-indexer/tests/unit/shared/dataservice/business/pendingTransactions.test.js +++ b/services/blockchain-indexer/tests/unit/shared/dataservice/business/pendingTransactions.test.js @@ -20,6 +20,10 @@ const { mockRecipientAddress, } = require('../../constants/pendingTransactions'); +const { + getCurrentChainID, +} = require('../../../../../shared/dataService/business/interoperability/chain'); + jest.mock('lisk-service-framework', () => { const actual = jest.requireActual('lisk-service-framework'); return { @@ -51,6 +55,10 @@ jest.mock('../../../../../shared/dataService/utils/account', () => ({ getIndexedAccountInfo: jest.fn(() => mockSenderAccountDetails), })); +jest.mock('../../../../../shared/dataService/business/interoperability/chain', () => ({ + getCurrentChainID: jest.fn(), +})); + const { validateParams, loadAllPendingTransactions, @@ -88,6 +96,10 @@ describe('Test getPendingTransactions method', () => { await loadAllPendingTransactions(); }); + beforeEach(async () => { + jest.resetModules(); + }); + it('should return all pending transactions without any filters', async () => { const params = { sort: 'id:asc', @@ -131,7 +143,7 @@ describe('Test getPendingTransactions method', () => { expect(result.data.length).toBe(txCountWithParams); }); - it('should return pending transactions with receivingChainID', async () => { + it('should return pending transactions with receivingChainID and receivingChainID is not currentChainID', async () => { const params = { receivingChainID: '02000000', sort: 'id:asc', @@ -139,6 +151,8 @@ describe('Test getPendingTransactions method', () => { limit: 10, }; + getCurrentChainID.mockResolvedValue('02000001'); + const result = await getPendingTransactions(params); let txCountWithParams = 0; @@ -151,6 +165,28 @@ describe('Test getPendingTransactions method', () => { expect(result.data.length).toBe(txCountWithParams); }); + it('should return pending transactions with receivingChainID and receivingChainID is currentChainID', async () => { + const params = { + receivingChainID: '02000000', + sort: 'id:asc', + offset: 0, + limit: 10, + }; + + getCurrentChainID.mockResolvedValue('02000000'); + + const result = await getPendingTransactions(params); + + let txCountWithParams = 0; + mockPendingTransactions.forEach(transaction => { + if (transaction.params && !transaction.params.receivingChainID) { + txCountWithParams++; + } + }); + + expect(result.data.length).toBe(txCountWithParams); + }); + it('should throw ValidationException for invalid parameters', async () => { const params = { nonce: 123, From 23837144418ca7848138aa20cf63867bd731aa36 Mon Sep 17 00:00:00 2001 From: Vardan Nadkarni Date: Wed, 22 Nov 2023 22:50:01 +0530 Subject: [PATCH 6/7] Applied suggestions --- services/blockchain-connector/shared/sdk/formatter.js | 4 ++-- services/blockchain-connector/shared/sdk/schema.js | 10 +++++----- .../shared/dataService/business/pendingTransactions.js | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/services/blockchain-connector/shared/sdk/formatter.js b/services/blockchain-connector/shared/sdk/formatter.js index 7b6d70469c..48eb6801ed 100644 --- a/services/blockchain-connector/shared/sdk/formatter.js +++ b/services/blockchain-connector/shared/sdk/formatter.js @@ -25,7 +25,7 @@ const { getBlockAssetDataSchemaByModule, getTransactionSchema, getTransactionParamsSchema, - getDataSchemaByEventName, + getDataSchemaByEvent, getEventSchema, } = require('./schema'); @@ -146,7 +146,7 @@ const formatEvent = (event, skipDecode) => { if (skipDecode) { eventData = event.data; } else { - const eventDataSchema = getDataSchemaByEventName(event.name); + const eventDataSchema = getDataSchemaByEvent(event); try { eventData = eventDataSchema ? codec.decodeJSON(eventDataSchema, Buffer.from(event.data, 'hex')) diff --git a/services/blockchain-connector/shared/sdk/schema.js b/services/blockchain-connector/shared/sdk/schema.js index 485492a388..8cd2243ef9 100644 --- a/services/blockchain-connector/shared/sdk/schema.js +++ b/services/blockchain-connector/shared/sdk/schema.js @@ -49,19 +49,19 @@ const getBlockAssetDataSchemaByModule = _module => { return schema; }; -const getDataSchemaByEventName = eventName => { - if (EVENT_NAME_COMMAND_EXECUTION_RESULT === eventName) return schemas.standardEvent; +const getDataSchemaByEvent = event => { + if (EVENT_NAME_COMMAND_EXECUTION_RESULT === event.name) return schemas.standardEvent; // Populate the eventSchemaLookup map with module events if not exists if (Object.keys(eventSchemaLookup).length === 0) { metadata.modules.forEach(module => { module.events.forEach(moduleEvent => { - eventSchemaLookup[moduleEvent.name] = moduleEvent.data; + eventSchemaLookup[`${module.name}_${moduleEvent.name}`] = moduleEvent.data; }); }); } - return eventSchemaLookup[eventName] || null; + return eventSchemaLookup[`${event.module}_${event.name}`] || null; }; module.exports = { @@ -76,6 +76,6 @@ module.exports = { getEventSchema, getTransactionSchema, getTransactionParamsSchema, - getDataSchemaByEventName, + getDataSchemaByEvent, getCCMSchema, }; diff --git a/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js b/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js index 762ac0ecf9..d75376f680 100644 --- a/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js +++ b/services/blockchain-indexer/shared/dataService/business/pendingTransactions.js @@ -94,7 +94,7 @@ const validateParams = async params => { if (params.recipientAddress) validatedParams.recipientAddress = params.recipientAddress; if (params.moduleCommand) validatedParams.moduleCommand = params.moduleCommand; - // If recieving chainID is current chain ID then return all transactions with receivingChainID = null + // If receivingChainID is currentChainID then return all the transactions where receivingChainID = null if (params.receivingChainID) { const currentChainID = await getCurrentChainID(); From 2a96a5d7816c05a5880a93ba86c7533568750e06 Mon Sep 17 00:00:00 2001 From: Vardan Nadkarni Date: Thu, 23 Nov 2023 20:10:55 +0530 Subject: [PATCH 7/7] Modified transactions API to return any execution status if not specified --- services/gateway/apis/http-version3/methods/transactions.js | 1 + 1 file changed, 1 insertion(+) diff --git a/services/gateway/apis/http-version3/methods/transactions.js b/services/gateway/apis/http-version3/methods/transactions.js index a2f89c6f20..789b63551c 100644 --- a/services/gateway/apis/http-version3/methods/transactions.js +++ b/services/gateway/apis/http-version3/methods/transactions.js @@ -56,6 +56,7 @@ module.exports = { optional: true, type: 'string', pattern: regex.TRANSACTION_EXECUTION_STATUS, + default: 'pending,successful,failed', }, nonce: { optional: true, type: 'string', min: 1, pattern: regex.NONCE }, limit: { optional: true, type: 'number', min: 1, max: 100, default: 10 },