Skip to content

Commit

Permalink
feat(rest-api): Adds validateRouteExists validation [SLT-260] (#3180)
Browse files Browse the repository at this point in the history
* Adds validateRouteExists validation

* Remove timeouts for 400s
  • Loading branch information
abtestingalpha authored Sep 25, 2024
1 parent 6ec996d commit ceff8bc
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 40 deletions.
8 changes: 8 additions & 0 deletions packages/rest-api/src/routes/bridgeLimitsRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions packages/rest-api/src/routes/bridgeRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions packages/rest-api/src/routes/bridgeTxInfoRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { isTokenAddress } from '../utils/isTokenAddress'
import { isTokenSupportedOnChain } from '../utils/isTokenSupportedOnChain'
import { checksumAddresses } from '../middleware/checksumAddresses'
import { normalizeNativeTokenAddress } from '../middleware/normalizeNativeTokenAddress'
import { validateRouteExists } from '../validations/validateRouteExists'

const router = express.Router()

Expand Down Expand Up @@ -163,6 +164,13 @@ router.get(
.withMessage('destAddress is required')
.custom((value) => isAddress(value))
.withMessage('Invalid destination address'),
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,
bridgeTxInfoController
Expand Down
23 changes: 19 additions & 4 deletions packages/rest-api/src/tests/bridgeLimitsRoute.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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'
)
})

it('should return 400 for unsupported fromChain', async () => {
const response = await request(app).get('/bridgeLimits').query({
fromChain: '999',
Expand All @@ -46,7 +61,7 @@ describe('Get Bridge Limits Route', () => {
'message',
'Unsupported fromChain'
)
}, 10_000)
})

it('should return 400 for unsupported toChain', async () => {
const response = await request(app).get('/bridgeLimits').query({
Expand All @@ -57,7 +72,7 @@ describe('Get Bridge Limits Route', () => {
})
expect(response.status).toBe(400)
expect(response.body.error).toHaveProperty('message', 'Unsupported toChain')
}, 10_000)
})

it('should return 400 for missing fromToken', async () => {
const response = await request(app).get('/bridgeLimits').query({
Expand All @@ -67,7 +82,7 @@ describe('Get Bridge Limits Route', () => {
})
expect(response.status).toBe(400)
expect(response.body.error).toHaveProperty('field', 'fromToken')
}, 10_000)
})

it('should return 400 for missing toToken', async () => {
const response = await request(app).get('/bridgeLimits').query({
Expand All @@ -77,5 +92,5 @@ describe('Get Bridge Limits Route', () => {
})
expect(response.status).toBe(400)
expect(response.body.error).toHaveProperty('field', 'toToken')
}, 10_000)
})
})
27 changes: 22 additions & 5 deletions packages/rest-api/src/tests/bridgeRoute.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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'
)
})

it('should return 400 for unsupported fromChain, with error message', async () => {
const response = await request(app).get('/bridge').query({
fromChain: '999',
Expand All @@ -68,7 +85,7 @@ describe('Bridge Route with Real Synapse Service', () => {
'message',
'Unsupported fromChain'
)
}, 10000)
})

it('should return 400 for unsupported toChain, with error message', async () => {
const response = await request(app).get('/bridge').query({
Expand All @@ -80,7 +97,7 @@ describe('Bridge Route with Real Synapse Service', () => {
})
expect(response.status).toBe(400)
expect(response.body.error).toHaveProperty('message', 'Unsupported toChain')
}, 10000)
})

it('should return 400 for invalid fromToken address, with error message', async () => {
const response = await request(app).get('/bridge').query({
Expand All @@ -95,7 +112,7 @@ describe('Bridge Route with Real Synapse Service', () => {
'message',
'Invalid fromToken address'
)
}, 10000)
})

it('should return 400 for token not supported on specified chain, with error message', async () => {
const response = await request(app).get('/bridge').query({
Expand All @@ -110,7 +127,7 @@ describe('Bridge Route with Real Synapse Service', () => {
'message',
'Invalid fromToken address'
)
}, 10000)
})

it('should return 400 for missing amount, with error message', async () => {
const response = await request(app).get('/bridge').query({
Expand All @@ -121,5 +138,5 @@ describe('Bridge Route with Real Synapse Service', () => {
})
expect(response.status).toBe(400)
expect(response.body.error).toHaveProperty('field', 'amount')
}, 10000)
})
})
27 changes: 22 additions & 5 deletions packages/rest-api/src/tests/bridgeTxInfoRoute.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import express from 'express'

import bridgeTxInfoRoute from '../routes/bridgeTxInfoRoute'
import { USDC } from '../constants/bridgeable'
import { NativeGasAddress } from '../constants'

const app = express()
app.use('/bridgeTxInfo', bridgeTxInfoRoute)
Expand All @@ -28,6 +29,22 @@ describe('Bridge TX Info Route', () => {
)
}, 10_000)

it('should return 400 for unsupported route', async () => {
const response = await request(app).get('/bridgeTxInfo').query({
fromChain: '1',
toChain: '10',
fromToken: NativeGasAddress,
toToken: USDC.addresses[10],
amount: '10',
destAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
})
expect(response.status).toBe(400)
expect(response.body.error).toHaveProperty(
'message',
'No valid route exists for the chain/token combination'
)
})

it('should return 400 for unsupported fromChain', async () => {
const response = await request(app).get('/bridgeTxInfo').query({
fromChain: '999',
Expand All @@ -42,7 +59,7 @@ describe('Bridge TX Info Route', () => {
'message',
'Unsupported fromChain'
)
}, 10_000)
})

it('should return 400 for invalid fromToken address', async () => {
const response = await request(app).get('/bridgeTxInfo').query({
Expand All @@ -58,7 +75,7 @@ describe('Bridge TX Info Route', () => {
'message',
'Invalid fromToken address'
)
}, 10_000)
})

it('should return 400 for token not supported on specified chain', async () => {
const response = await request(app).get('/bridgeTxInfo').query({
Expand All @@ -74,7 +91,7 @@ describe('Bridge TX Info Route', () => {
'message',
'Invalid fromToken address'
)
}, 10_000)
})

it('should return 400 for missing amount', async () => {
const response = await request(app).get('/bridgeTxInfo').query({
Expand All @@ -86,7 +103,7 @@ describe('Bridge TX Info Route', () => {
})
expect(response.status).toBe(400)
expect(response.body.error).toHaveProperty('field', 'amount')
}, 10_000)
})

it('should return 400 for invalid destAddress', async () => {
const response = await request(app).get('/bridgeTxInfo').query({
Expand All @@ -102,5 +119,5 @@ describe('Bridge TX Info Route', () => {
'message',
'Invalid destination address'
)
}, 10_000)
})
})
10 changes: 6 additions & 4 deletions packages/rest-api/src/utils/bridgeRouteMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type TransformedBridgeRoutes = Record<string, TokenData[]>
const constructJSON = (
swappableMap,
exclusionList
): TransformedBridgeRoutes => {
): StringifiedBridgeRoutes => {
const result = {}

// Iterate through the chains
Expand Down Expand Up @@ -56,8 +56,7 @@ const constructJSON = (
}
}
}

return transformBridgeRouteValues(result)
return result
}

const transformPair = (string: string): any => {
Expand Down Expand Up @@ -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
)
20 changes: 20 additions & 0 deletions packages/rest-api/src/validations/validateRouteExists.ts
Original file line number Diff line number Diff line change
@@ -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}`)
}
22 changes: 0 additions & 22 deletions packages/rest-api/src/validations/validateTokens.ts

This file was deleted.

0 comments on commit ceff8bc

Please sign in to comment.