-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[wip] feat(api): bridge limit script #3131
Changes from 29 commits
f131926
acd653c
6ada55a
8530122
4428e8d
69f36c3
b48a36e
d4fac70
5e5e2b7
7eab9a7
f56517a
ddb245d
139e27c
95a93ca
96ec975
be863d5
c6cd501
bb9aa82
9fb48d8
d006117
8ce1097
f844897
8a8c923
07980e5
46e73c2
6696b4d
0cce954
2039353
b342984
f6246d4
a1d4650
33f5584
60138d4
64f6816
6990b0f
fdefa7e
eb7aa76
68c6c48
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,110 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import { validationResult } from 'express-validator' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import { BigNumber } from 'ethers' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import { parseUnits } from '@ethersproject/units' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
import { Synapse } from '../services/synapseService' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import { tokenAddressToToken } from '../utils/tokenAddressToToken' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import { formatBNToString } from '../utils/formatBNToString' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
import { BRIDGE_LIMIT_MAPPING } from '../utils/bridgeLimitMapping' | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
export const getBridgeLimitsController = async (req, res) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
const errors = validationResult(req) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!errors.isEmpty()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
return res.status(400).json({ errors: errors.array() }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
const { fromChain, fromToken, toChain, toToken } = req.query | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+6
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add validation rules for query parameters While the code correctly checks for validation errors, there are no visible validation rules for the query parameters ( [
query('fromChain').isNumeric(),
query('toChain').isNumeric(),
query('fromToken').isEthereumAddress(),
query('toToken').isEthereumAddress(),
] This will ensure that the input parameters are of the correct type and format before processing. |
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
const fromTokenInfo = tokenAddressToToken(fromChain, fromToken) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
const toTokenInfo = tokenAddressToToken(toChain, toToken) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add error handling for invalid token information Currently, if Apply this diff to implement error handling: const fromTokenInfo = tokenAddressToToken(fromChain, fromToken)
const toTokenInfo = tokenAddressToToken(toChain, toToken)
+ if (!fromTokenInfo) {
+ return res.status(400).json({ error: 'Invalid fromToken address' })
+ }
+ if (!toTokenInfo) {
+ return res.status(400).json({ error: 'Invalid toToken address' })
+ } Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
const upperLimitValue = parseUnits('1000000', fromTokenInfo.decimals) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
const upperLimitBridgeQuotes = await Synapse.allBridgeQuotes( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Number(fromChain), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Number(toChain), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
fromTokenInfo.address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
toTokenInfo.address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
upperLimitValue | ||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
const lowerLimitValues = ['0.01', '10'] | ||||||||||||||||||||||||||||||||||||||||||||||||||||
let lowerLimitBridgeQuotes = null | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
for (const limit of lowerLimitValues) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
const lowerLimitAmount = parseUnits(limit, fromTokenInfo.decimals) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
lowerLimitBridgeQuotes = await Synapse.allBridgeQuotes( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Number(fromChain), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
Number(toChain), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
fromTokenInfo.address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
toTokenInfo.address, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
lowerLimitAmount | ||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
if (lowerLimitBridgeQuotes && lowerLimitBridgeQuotes.length > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
break | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
const maxBridgeAmountQuote = upperLimitBridgeQuotes.reduce( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
(maxQuote, currentQuote) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
const currentMaxAmount = currentQuote.maxAmountOut | ||||||||||||||||||||||||||||||||||||||||||||||||||||
const maxAmount = maxQuote ? maxQuote.maxAmountOut : BigNumber.from(0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
return currentMaxAmount.gt(maxAmount) ? currentQuote : maxQuote | ||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
null | ||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle empty The Apply this diff to add the necessary check: + let maxBridgeAmountQuote = null
+ if (upperLimitBridgeQuotes && upperLimitBridgeQuotes.length > 0) {
maxBridgeAmountQuote = upperLimitBridgeQuotes.reduce(
(maxQuote, currentQuote) => {
const currentMaxAmount = currentQuote.maxAmountOut
const maxAmount = maxQuote ? maxQuote.maxAmountOut : BigNumber.from(0)
return currentMaxAmount.gt(maxAmount) ? currentQuote : maxQuote
},
null
)
+ } Similarly, ensure that Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
const minBridgeAmountQuote = lowerLimitBridgeQuotes.reduce( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
(minQuote, currentQuote) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
const currentFeeAmount = currentQuote.feeAmount | ||||||||||||||||||||||||||||||||||||||||||||||||||||
const minFeeAmount = minQuote ? minQuote.feeAmount : null | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
return !minFeeAmount || currentFeeAmount.lt(minFeeAmount) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
? currentQuote | ||||||||||||||||||||||||||||||||||||||||||||||||||||
: minQuote | ||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
null | ||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle empty Just like with Apply this diff to add the necessary check: + let minBridgeAmountQuote = null
+ if (lowerLimitBridgeQuotes && lowerLimitBridgeQuotes.length > 0) {
minBridgeAmountQuote = lowerLimitBridgeQuotes.reduce(
(minQuote, currentQuote) => {
const currentFeeAmount = currentQuote.feeAmount
const minFeeAmount = minQuote ? minQuote.feeAmount : null
return !minFeeAmount || currentFeeAmount.lt(minFeeAmount)
? currentQuote
: minQuote
},
null
)
+ } Ensure that you handle cases where Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!maxBridgeAmountQuote || !minBridgeAmountQuote) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
return res.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
maxOriginAmount: null, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
minOriginAmount: null, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
const maxAmountOriginQueryTokenOutInfo = tokenAddressToToken( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
toChain, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
maxBridgeAmountQuote.destQuery.tokenOut | ||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
const minAmountOriginQueryTokenOutInfo = tokenAddressToToken( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
fromChain, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
minBridgeAmountQuote.originQuery.tokenOut | ||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
const maxOriginAmount = formatBNToString( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
maxBridgeAmountQuote.maxAmountOut, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
maxAmountOriginQueryTokenOutInfo.decimals | ||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
const minOriginAmount = formatBNToString( | ||||||||||||||||||||||||||||||||||||||||||||||||||||
minBridgeAmountQuote.feeAmount, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
minAmountOriginQueryTokenOutInfo.decimals | ||||||||||||||||||||||||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Verify correct usage of token decimals in amount formatting When formatting For Consider updating the formatting to use the correct token decimals: const maxOriginAmount = formatBNToString(
maxBridgeAmountQuote.maxAmountOut,
- maxAmountOriginQueryTokenOutInfo.decimals
+ toTokenInfo.decimals
)
const minOriginAmount = formatBNToString(
minBridgeAmountQuote.feeAmount,
- minAmountOriginQueryTokenOutInfo.decimals
+ fromTokenInfo.decimals
)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
return res.json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
BRIDGE_LIMIT_MAPPING, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
maxOriginAmount, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
minOriginAmount, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Evaluate the necessity of including Including Apply this diff to remove return res.json({
- BRIDGE_LIMIT_MAPPING,
maxOriginAmount,
minOriginAmount,
}) Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
} catch (err) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
res.status(500).json({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
error: | ||||||||||||||||||||||||||||||||||||||||||||||||||||
'An unexpected error occurred in /getBridgeLimits. Please try again later.', | ||||||||||||||||||||||||||||||||||||||||||||||||||||
details: err.message, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid exposing sensitive error details in the response Returning Apply this diff to modify the error handling: + console.error('Error in /getBridgeLimitsController:', err)
res.status(500).json({
error:
'An unexpected error occurred in /getBridgeLimits. Please try again later.',
- details: err.message,
}) Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import express from 'express' | ||
import { check } from 'express-validator' | ||
import { isAddress } from '@ethersproject/address' | ||
|
||
import { CHAINS_ARRAY } from '../constants/chains' | ||
import { showFirstValidationError } from '../middleware/showFirstValidationError' | ||
import { getBridgeLimitsController } from '../controllers/bridgeLimitsController' | ||
|
||
const router = express.Router() | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add swagger docs (see other routes for examples) |
||
router.get( | ||
'/', | ||
[ | ||
check('fromChain') | ||
.isNumeric() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. existence checks should come first:
|
||
.custom((value) => CHAINS_ARRAY.some((c) => c.id === Number(value))) | ||
.withMessage('Unsupported fromChain') | ||
.exists() | ||
.withMessage('originChainId is required'), | ||
check('toChain') | ||
.isNumeric() | ||
.custom((value) => CHAINS_ARRAY.some((c) => c.id === Number(value))) | ||
.withMessage('Unsupported toChain') | ||
.exists() | ||
.withMessage('toChain is required'), | ||
check('fromToken') | ||
.exists() | ||
.withMessage('fromToken is required') | ||
.custom((value) => isAddress(value)) | ||
.withMessage('Invalid fromToken address'), | ||
check('toToken') | ||
.exists() | ||
.withMessage('toToken is required') | ||
.custom((value) => isAddress(value)) | ||
.withMessage('Invalid toToken address'), | ||
], | ||
showFirstValidationError, | ||
getBridgeLimitsController | ||
) | ||
|
||
export default router |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import request from 'supertest' | ||
import express from 'express' | ||
|
||
import bridgeLimitsRoute from '../routes/bridgeLimitsRoute' | ||
|
||
const app = express() | ||
app.use('/bridgeLimits', bridgeLimitsRoute) | ||
|
||
describe('Get Bridge Limits Route', () => { | ||
it('should return min/max origin amounts for valid input', async () => { | ||
const response = await request(app).get('/bridgeLimits').query({ | ||
fromChain: 1, | ||
fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', | ||
toChain: 10, | ||
toToken: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', | ||
}) | ||
|
||
expect(response.status).toBe(200) | ||
expect(response.body).toHaveProperty('maxOriginAmount') | ||
expect(response.body).toHaveProperty('minOriginAmount') | ||
}, 10_000) | ||
|
||
it('should return 400 for unsupported fromChain', async () => { | ||
const response = await request(app).get('/bridgeLimits').query({ | ||
fromChain: '999', | ||
toChain: '137', | ||
fromToken: '0x176211869cA2b568f2A7D4EE941E073a821EE1ff', | ||
toToken: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', | ||
}) | ||
expect(response.status).toBe(400) | ||
expect(response.body.error).toHaveProperty( | ||
'message', | ||
'Unsupported fromChain' | ||
) | ||
}, 10_000) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LGTM: Unsupported fromChain test case is correct, but there's a duplication. The test case for unsupported fromChain is well-structured, checking both the status code and the error message. However, there's a duplicate test case (lines 37-49) with identical content. Remove the duplicate test case (lines 37-49) to maintain a clean and efficient test suite. Also applies to: 37-49 ToolsGitleaks
|
||
|
||
it('should return 400 for unsupported ', async () => { | ||
const response = await request(app).get('/bridgeLimits').query({ | ||
fromChain: '999', | ||
toChain: '137', | ||
fromToken: '0x176211869cA2b568f2A7D4EE941E073a821EE1ff', | ||
toToken: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', | ||
}) | ||
expect(response.status).toBe(400) | ||
expect(response.body.error).toHaveProperty( | ||
'message', | ||
'Unsupported fromChain' | ||
) | ||
}, 10_000) | ||
|
||
it('should return 400 for unsupported toChain', async () => { | ||
const response = await request(app).get('/bridgeLimits').query({ | ||
fromChain: '137', | ||
toChain: '999', | ||
fromToken: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359', | ||
toToken: '0x176211869cA2b568f2A7D4EE941E073a821EE1ff', | ||
}) | ||
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({ | ||
fromChain: '1', | ||
toChain: '137', | ||
toToken: '0x176211869cA2b568f2A7D4EE941E073a821EE1ff', | ||
}) | ||
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({ | ||
fromChain: '1', | ||
toChain: '137', | ||
fromToken: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', | ||
}) | ||
expect(response.status).toBe(400) | ||
expect(response.body.error).toHaveProperty('field', 'toToken') | ||
}, 10_000) | ||
}) |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,104 @@ | ||||||||||||||||
import { BRIDGE_MAP } from '../constants/bridgeMap' | ||||||||||||||||
import * as ALL_TOKENS from '../constants/bridgeable' | ||||||||||||||||
|
||||||||||||||||
const constructJSON = (swappableMap, exclusionList) => { | ||||||||||||||||
const result = {} | ||||||||||||||||
|
||||||||||||||||
// Iterate through the origin chains | ||||||||||||||||
for (const originChainId in swappableMap) { | ||||||||||||||||
for (const originTokenAddress in swappableMap[originChainId]) { | ||||||||||||||||
const originToken = swappableMap[originChainId][originTokenAddress] | ||||||||||||||||
const originKey = `${originToken.symbol}-${originChainId}` | ||||||||||||||||
|
||||||||||||||||
// Use transformPair to get token object | ||||||||||||||||
const transformedOriginToken = transformPair(originKey) | ||||||||||||||||
|
||||||||||||||||
if (!transformedOriginToken || exclusionList.includes(originKey)) { | ||||||||||||||||
continue | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
// Initialize origin chain and origin token with symbol and swappableType if not existing | ||||||||||||||||
if (!result[originChainId]) { | ||||||||||||||||
result[originChainId] = {} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
if (!result[originChainId][transformedOriginToken.address]) { | ||||||||||||||||
result[originChainId][transformedOriginToken.address] = { | ||||||||||||||||
symbol: transformedOriginToken.symbol, | ||||||||||||||||
swappableType: transformedOriginToken.swapableType, // Fetch swappableType | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistent property name 'swappableType' vs 'swapableType' The property name is inconsistently spelled between Apply this diff to fix the inconsistency: Option 1: Rename - swapableType: token.swapableType,
+ swappableType: token.swapableType, Option 2: Rename - swappableType: transformedOriginToken.swapableType, // Fetch swappableType
+ swapableType: transformedOriginToken.swapableType, // Fetch swapableType Ensure that the property name is consistent throughout the codebase. Also applies to: 99-99 |
||||||||||||||||
routes: {}, | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
// Iterate through destination chains | ||||||||||||||||
for (const destinationChainId in swappableMap) { | ||||||||||||||||
if (originChainId === destinationChainId) { | ||||||||||||||||
continue | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
for (const destinationTokenAddress in swappableMap[ | ||||||||||||||||
destinationChainId | ||||||||||||||||
]) { | ||||||||||||||||
const destinationToken = | ||||||||||||||||
swappableMap[destinationChainId][destinationTokenAddress] | ||||||||||||||||
const destinationKey = `${destinationToken.symbol}-${destinationChainId}` | ||||||||||||||||
|
||||||||||||||||
// Use transformPair for destination token as well | ||||||||||||||||
const transformedDestinationToken = transformPair(destinationKey) | ||||||||||||||||
|
||||||||||||||||
if ( | ||||||||||||||||
!transformedDestinationToken || | ||||||||||||||||
exclusionList.includes(destinationKey) | ||||||||||||||||
) { | ||||||||||||||||
continue | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
// Check for bridge compatibility by comparing origin and destination symbols | ||||||||||||||||
for (const bridgeSymbol of originToken.origin) { | ||||||||||||||||
if ( | ||||||||||||||||
originToken.origin.includes(bridgeSymbol) && | ||||||||||||||||
destinationToken.destination.includes(bridgeSymbol) | ||||||||||||||||
) { | ||||||||||||||||
Comment on lines
+59
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant condition in bridge compatibility check The condition Simplify the condition by removing the redundant check: for (const bridgeSymbol of originToken.origin) {
- if (
- originToken.origin.includes(bridgeSymbol) &&
- destinationToken.destination.includes(bridgeSymbol)
- ) {
+ if (destinationToken.destination.includes(bridgeSymbol)) {
// Initialize destination token
}
} Committable suggestion
Suggested change
|
||||||||||||||||
// Initialize destination token with symbol, minValue, maxValue if not existing | ||||||||||||||||
if ( | ||||||||||||||||
!result[originChainId][transformedOriginToken.address].routes[ | ||||||||||||||||
destinationChainId | ||||||||||||||||
] | ||||||||||||||||
) { | ||||||||||||||||
result[originChainId][transformedOriginToken.address].routes[ | ||||||||||||||||
destinationChainId | ||||||||||||||||
] = {} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
result[originChainId][transformedOriginToken.address].routes[ | ||||||||||||||||
destinationChainId | ||||||||||||||||
][transformedDestinationToken.address] = { | ||||||||||||||||
symbol: transformedDestinationToken.symbol, | ||||||||||||||||
minOriginValue: null, | ||||||||||||||||
maxOriginValue: null, | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
return result | ||||||||||||||||
} | ||||||||||||||||
Comment on lines
+6
to
+90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider optimizing nested loops for performance The Explore ways to optimize the loops, such as:
This could enhance the efficiency of the function when dealing with extensive token maps. |
||||||||||||||||
|
||||||||||||||||
export const transformPair = (string: string): any => { | ||||||||||||||||
const [symbol, chainId] = string.split('-') | ||||||||||||||||
const token = Object.values(ALL_TOKENS).find((t) => t.routeSymbol === symbol) | ||||||||||||||||
const address = token?.addresses[chainId] | ||||||||||||||||
if (token && address) { | ||||||||||||||||
return { | ||||||||||||||||
symbol, | ||||||||||||||||
chainId, | ||||||||||||||||
address, | ||||||||||||||||
swapableType: token.swapableType, | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
export const BRIDGE_LIMIT_MAPPING = constructJSON(BRIDGE_MAP, []) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure validation middleware is correctly set up for request parameters
While
validationResult(req)
checks for validation errors, there is no indication that validation rules forfromChain
,fromToken
,toChain
, andtoToken
have been established. To prevent invalid or malicious inputs, please ensure that appropriate validation middleware is applied to these parameters. This should include checks such asisNumeric
for chain IDs andisTokenAddress
for token addresses to enhance error messaging and debugging.