From 26c779443fd03e439ab7cbc8da658cddaebdc633 Mon Sep 17 00:00:00 2001 From: Edwin Greene Date: Wed, 6 Mar 2024 13:16:00 -0500 Subject: [PATCH] Update Rest API tokens endpoint to accept multiple token ids (#7870) * Update Rest API tokens endpoint to accept multiple token id query parameters Signed-off-by: Edwin Greene --- .../__tests__/specs/tokens/multiple-ids.json | 110 ++++++++++++++++++ hedera-mirror-rest/__tests__/tokens.test.js | 70 ++++++++++- hedera-mirror-rest/tokens.js | 10 ++ 3 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 hedera-mirror-rest/__tests__/specs/tokens/multiple-ids.json diff --git a/hedera-mirror-rest/__tests__/specs/tokens/multiple-ids.json b/hedera-mirror-rest/__tests__/specs/tokens/multiple-ids.json new file mode 100644 index 00000000000..a1124755dec --- /dev/null +++ b/hedera-mirror-rest/__tests__/specs/tokens/multiple-ids.json @@ -0,0 +1,110 @@ +{ + "description": "Token api call with multiple token id query parameters", + "setup": { + "entities": [ + { + "num": 1, + "type": "TOKEN" + }, + { + "num": 1135, + "type": "TOKEN" + }, + { + "realm": 7, + "num": 25301, + "type": "TOKEN" + }, + { + "realm": 23, + "num": 45678, + "type": "TOKEN" + } + ], + "tokens": [ + { + "token_id": "0.0.1", + "symbol": "FIRSTMOVERLPDJH", + "created_timestamp": "1234567890000000001", + "type": "FUNGIBLE_COMMON" + }, + { + "token_id": "0.0.1135", + "symbol": "ORIGINALRDKSE", + "created_timestamp": "1234567890000000002", + "decimals": 2, + "name": "Original", + "type": "FUNGIBLE_COMMON" + }, + { + "token_id": "0.7.25301", + "symbol": "MIRRORTOKEN", + "created_timestamp": "1234567890000000003", + "decimals": 3, + "name": "Mirror", + "type": "FUNGIBLE_COMMON" + }, + { + "token_id": "0.23.45678", + "symbol": "HEDERACOIN", + "created_timestamp": "1234567890000000004", + "type": "FUNGIBLE_COMMON" + } + ] + }, + "tests": [ + { + "urls": [ + "/api/v1/tokens?token.id=0.0.1135&token.id=0.7.25301", + "/api/v1/tokens?token.id=0.0.1135&token.id=eq:0.7.25301", + "/api/v1/tokens?token.id=0.0.1135&token.id=eq:0.7.25301&token.id=gt:1134&token.id=lte:0.7.25301", + "/api/v1/tokens?token.id=0.0.1135&token.id=eq:0.7.25301&token.id=gte:1135&token.id=lt:0.7.25302" + ], + "responseStatus": 200, + "responseJson": { + "tokens": [ + { + "token_id": "0.0.1135", + "symbol": "ORIGINALRDKSE", + "admin_key": null, + "decimals": 2, + "name": "Original", + "type": "FUNGIBLE_COMMON" + }, + { + "token_id": "0.7.25301", + "symbol": "MIRRORTOKEN", + "admin_key": null, + "decimals": 3, + "name": "Mirror", + "type": "FUNGIBLE_COMMON" + } + ], + "links": { + "next": null + } + } + }, + { + "urls": [ + "/api/v1/tokens?token.id=0.0.1135&token.id=0.7.25301&token.id=gt:1134&token.id=lt:0.7.25301" + ], + "responseStatus": 200, + "responseJson": { + "tokens": [ + { + "token_id": "0.0.1135", + "symbol": "ORIGINALRDKSE", + "admin_key": null, + "decimals": 2, + "name": "Original", + "type": "FUNGIBLE_COMMON" + } + ], + "links": { + "next": null + } + } + } + ] +} diff --git a/hedera-mirror-rest/__tests__/tokens.test.js b/hedera-mirror-rest/__tests__/tokens.test.js index 2a1b0ca4930..03238661c69 100644 --- a/hedera-mirror-rest/__tests__/tokens.test.js +++ b/hedera-mirror-rest/__tests__/tokens.test.js @@ -90,6 +90,57 @@ describe('token extractSqlFromTokenRequest tests', () => { ); }); + test('Verify multiple token ids query', () => { + const initialQuery = tokens.tokensSelectQuery; + const initialParams = []; + const filters = [ + { + key: constants.filterKeys.TOKEN_ID, + operator: ' = ', + value: '111', + }, + { + key: constants.filterKeys.TOKEN_ID, + operator: ' = ', + value: '222', + }, + { + key: constants.filterKeys.TOKEN_ID, + operator: ' = ', + value: '333', + }, + ]; + + const expectedQuery = ` + select + t.decimals, + t.freeze_status, + e.key, + t.kyc_status, + t.name, + t.symbol, + t.token_id, + t.type + from token t + where t.token_id = any($1) + order by t.token_id asc + limit $2`; + const expectedParams = [['111', '222', '333'], defaultLimit]; + const expectedOrder = constants.orderFilterValues.ASC; + const expectedLimit = defaultLimit; + + verifyExtractSqlFromTokenRequest( + initialQuery, + initialParams, + filters, + undefined, + expectedQuery, + expectedParams, + expectedOrder, + expectedLimit + ); + }); + test('Verify public key filter', () => { const initialQuery = [tokens.tokensSelectQuery, tokens.entityIdJoinQuery].join('\n'); const initialParams = []; @@ -260,6 +311,9 @@ describe('token extractSqlFromTokenRequest tests', () => { value: '3c3d546321ff6f63d701d2ec5c277095874e19f4a235bee1e6bb19258bf362be', }, {key: constants.filterKeys.TOKEN_ID, operator: ' > ', value: '2'}, + {key: constants.filterKeys.TOKEN_ID, operator: ' =< ', value: '98'}, + {key: constants.filterKeys.TOKEN_ID, operator: ' = ', value: '3'}, + {key: constants.filterKeys.TOKEN_ID, operator: ' = ', value: '100'}, { key: constants.filterKeys.TOKEN_TYPE, operator: ' = ', @@ -290,10 +344,20 @@ describe('token extractSqlFromTokenRequest tests', () => { where ta.associated is true and e.public_key = $2 and t.token_id > $3 - and t.type = $4 + and t.token_id =< $4 + and t.type = $5 + and t.token_id = any($6) order by t.token_id desc - limit $5`; - const expectedParams = [5, '3c3d546321ff6f63d701d2ec5c277095874e19f4a235bee1e6bb19258bf362be', '2', tokenType, '3']; + limit $7`; + const expectedParams = [ + 5, + '3c3d546321ff6f63d701d2ec5c277095874e19f4a235bee1e6bb19258bf362be', + '2', + '98', + tokenType, + ['3', '100'], + '3', + ]; const expectedOrder = constants.orderFilterValues.DESC; const expectedLimit = 3; diff --git a/hedera-mirror-rest/tokens.js b/hedera-mirror-rest/tokens.js index 8ebcc82028b..b57874a227c 100644 --- a/hedera-mirror-rest/tokens.js +++ b/hedera-mirror-rest/tokens.js @@ -149,6 +149,7 @@ const extractSqlFromTokenRequest = (query, params, filters, conditions) => { // add filters let limit = defaultLimit; let order = orderFilterValues.ASC; + const inClause = []; conditions = conditions || []; for (const filter of filters) { if (filter.key === filterKeys.LIMIT) { @@ -172,9 +173,18 @@ const extractSqlFromTokenRequest = (query, params, filters, conditions) => { continue; } + if (columnKey === sqlQueryColumns.TOKEN_ID && filter.operator === utils.opsMap.eq) { + inClause.push(filter.value); + continue; + } + conditions.push(`${filterColumnMap[filter.key]}${filter.operator}$${params.push(filter.value)}`); } + if (inClause.length > 0) { + conditions.push(`${sqlQueryColumns.TOKEN_ID} = any($${params.push(inClause)})`); + } + const whereQuery = conditions.length !== 0 ? `where ${conditions.join(' and ')}` : ''; const orderQuery = `order by ${sqlQueryColumns.TOKEN_ID} ${order}`; const limitQuery = `limit $${params.push(limit)}`;