From 1a5f4a0a7376c1771f4d2e86b3ee93c778269c1f Mon Sep 17 00:00:00 2001 From: abtestingalpha Date: Tue, 24 Sep 2024 16:53:52 -0400 Subject: [PATCH] Adds validateRouteExists validation --- .../rest-api/src/routes/bridgeLimitsRoute.ts | 8 +++++++ packages/rest-api/src/routes/bridgeRoute.ts | 8 +++++++ .../src/tests/bridgeLimitsRoute.test.ts | 15 +++++++++++++ .../rest-api/src/tests/bridgeRoute.test.ts | 17 ++++++++++++++ .../rest-api/src/utils/bridgeRouteMapping.ts | 10 +++++---- .../src/validations/validateRouteExists.ts | 20 +++++++++++++++++ .../src/validations/validateTokens.ts | 22 ------------------- 7 files changed, 74 insertions(+), 26 deletions(-) create mode 100644 packages/rest-api/src/validations/validateRouteExists.ts delete mode 100644 packages/rest-api/src/validations/validateTokens.ts diff --git a/packages/rest-api/src/routes/bridgeLimitsRoute.ts b/packages/rest-api/src/routes/bridgeLimitsRoute.ts index 14ab637671..392937ac28 100644 --- a/packages/rest-api/src/routes/bridgeLimitsRoute.ts +++ b/packages/rest-api/src/routes/bridgeLimitsRoute.ts @@ -8,6 +8,7 @@ import { isTokenSupportedOnChain } from './../utils/isTokenSupportedOnChain' import { isTokenAddress } from '../utils/isTokenAddress' import { normalizeNativeTokenAddress } from '../middleware/normalizeNativeTokenAddress' import { checksumAddresses } from '../middleware/checksumAddresses' +import { validateRouteExists } from '../validations/validateRouteExists' const router = express.Router() @@ -130,6 +131,13 @@ router.get( isTokenSupportedOnChain(value, req.query.toChain as string) ) .withMessage('Token not supported on specified chain'), + check() + .custom((_value, { req }) => { + const { fromChain, toChain, fromToken, toToken } = req.query + + return validateRouteExists(fromChain, fromToken, toChain, toToken) + }) + .withMessage('No valid route exists for the chain/token combination'), ], showFirstValidationError, bridgeLimitsController diff --git a/packages/rest-api/src/routes/bridgeRoute.ts b/packages/rest-api/src/routes/bridgeRoute.ts index 01fccb708b..0e4a88b947 100644 --- a/packages/rest-api/src/routes/bridgeRoute.ts +++ b/packages/rest-api/src/routes/bridgeRoute.ts @@ -8,6 +8,7 @@ import { bridgeController } from '../controllers/bridgeController' import { isTokenSupportedOnChain } from '../utils/isTokenSupportedOnChain' import { checksumAddresses } from '../middleware/checksumAddresses' import { normalizeNativeTokenAddress } from '../middleware/normalizeNativeTokenAddress' +import { validateRouteExists } from '../validations/validateRouteExists' const router = express.Router() @@ -222,6 +223,13 @@ router.get( ) .withMessage('Token not supported on specified chain'), check('amount').isNumeric().exists().withMessage('amount is required'), + check() + .custom((_value, { req }) => { + const { fromChain, toChain, fromToken, toToken } = req.query + + return validateRouteExists(fromChain, fromToken, toChain, toToken) + }) + .withMessage('No valid route exists for the chain/token combination'), ], showFirstValidationError, bridgeController diff --git a/packages/rest-api/src/tests/bridgeLimitsRoute.test.ts b/packages/rest-api/src/tests/bridgeLimitsRoute.test.ts index 921393773b..6c195f8bd9 100644 --- a/packages/rest-api/src/tests/bridgeLimitsRoute.test.ts +++ b/packages/rest-api/src/tests/bridgeLimitsRoute.test.ts @@ -3,6 +3,7 @@ import express from 'express' import bridgeLimitsRoute from '../routes/bridgeLimitsRoute' import { USDC, ETH } from '../constants/bridgeable' +import { NativeGasAddress } from '../constants' const app = express() app.use('/bridgeLimits', bridgeLimitsRoute) @@ -34,6 +35,20 @@ describe('Get Bridge Limits Route', () => { expect(response.body).toHaveProperty('minOriginAmount') }, 10_000) + it('should return 400 for unsupported route', async () => { + const response = await request(app).get('/bridgeLimits').query({ + fromChain: '1', + toChain: '10', + fromToken: NativeGasAddress, + toToken: USDC.addresses[10], + }) + expect(response.status).toBe(400) + expect(response.body.error).toHaveProperty( + 'message', + 'No valid route exists for the chain/token combination' + ) + }, 10_000) + it('should return 400 for unsupported fromChain', async () => { const response = await request(app).get('/bridgeLimits').query({ fromChain: '999', diff --git a/packages/rest-api/src/tests/bridgeRoute.test.ts b/packages/rest-api/src/tests/bridgeRoute.test.ts index 756089f50b..35feb4197b 100644 --- a/packages/rest-api/src/tests/bridgeRoute.test.ts +++ b/packages/rest-api/src/tests/bridgeRoute.test.ts @@ -17,6 +17,7 @@ describe('Bridge Route with Real Synapse Service', () => { toToken: USDC.addresses[10], amount: '1000', }) + expect(response.status).toBe(200) expect(Array.isArray(response.body)).toBe(true) expect(response.body.length).toBeGreaterThan(0) @@ -55,6 +56,22 @@ describe('Bridge Route with Real Synapse Service', () => { expect(response.body[0]).toHaveProperty('bridgeFeeFormatted') }, 15000) + it('should return 400 for unsupported route', async () => { + const response = await request(app).get('/bridge').query({ + fromChain: '1', + toChain: '10', + fromToken: NativeGasAddress, + toToken: USDC.addresses[10], + amount: '10', + }) + + expect(response.status).toBe(400) + expect(response.body.error).toHaveProperty( + 'message', + 'No valid route exists for the chain/token combination' + ) + }, 15000) + it('should return 400 for unsupported fromChain, with error message', async () => { const response = await request(app).get('/bridge').query({ fromChain: '999', diff --git a/packages/rest-api/src/utils/bridgeRouteMapping.ts b/packages/rest-api/src/utils/bridgeRouteMapping.ts index 996652e543..992ccffe0f 100644 --- a/packages/rest-api/src/utils/bridgeRouteMapping.ts +++ b/packages/rest-api/src/utils/bridgeRouteMapping.ts @@ -13,7 +13,7 @@ type TransformedBridgeRoutes = Record const constructJSON = ( swappableMap, exclusionList -): TransformedBridgeRoutes => { +): StringifiedBridgeRoutes => { const result = {} // Iterate through the chains @@ -56,8 +56,7 @@ const constructJSON = ( } } } - - return transformBridgeRouteValues(result) + return result } const transformPair = (string: string): any => { @@ -97,4 +96,7 @@ const transformBridgeRouteValues = ( ) } -export const BRIDGE_ROUTE_MAPPING = constructJSON(BRIDGE_MAP, []) +export const BRIDGE_ROUTE_MAPPING_SYMBOLS = constructJSON(BRIDGE_MAP, []) +export const BRIDGE_ROUTE_MAPPING = transformBridgeRouteValues( + BRIDGE_ROUTE_MAPPING_SYMBOLS +) diff --git a/packages/rest-api/src/validations/validateRouteExists.ts b/packages/rest-api/src/validations/validateRouteExists.ts new file mode 100644 index 0000000000..4339d9d8c1 --- /dev/null +++ b/packages/rest-api/src/validations/validateRouteExists.ts @@ -0,0 +1,20 @@ +import { tokenAddressToToken } from '../utils/tokenAddressToToken' +import { BRIDGE_ROUTE_MAPPING_SYMBOLS } from '../utils/bridgeRouteMapping' + +export const validateRouteExists = (fromChain, fromToken, toChain, toToken) => { + const fromTokenInfo = tokenAddressToToken(fromChain.toString(), fromToken) + const toTokenInfo = tokenAddressToToken(toChain.toString(), toToken) + + if (!fromTokenInfo || !toTokenInfo) { + return false + } + + const key = `${fromTokenInfo.symbol}-${fromChain}` + const routes = BRIDGE_ROUTE_MAPPING_SYMBOLS[key] + + if (!routes) { + return false + } + + return routes.includes(`${toTokenInfo.symbol}-${toChain}`) +} diff --git a/packages/rest-api/src/validations/validateTokens.ts b/packages/rest-api/src/validations/validateTokens.ts deleted file mode 100644 index 6e89a9c70c..0000000000 --- a/packages/rest-api/src/validations/validateTokens.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { check } from 'express-validator' - -import { tokenSymbolToToken } from '../utils/tokenSymbolToToken' - -export const validateTokens = (chainParam, tokenParam, paramName) => { - return check(tokenParam) - .isString() - .exists() - .withMessage(`${paramName} is required`) - .custom((value, { req }) => { - const chain = req.query[chainParam] - const tokenInfo = tokenSymbolToToken(chain, value) - if (!tokenInfo) { - throw new Error(`Invalid ${paramName} symbol`) - } - if (!req.res.locals.tokenInfo) { - req.res.locals.tokenInfo = {} - } - req.res.locals.tokenInfo[paramName] = tokenInfo - return true - }) -}