diff --git a/packages/rest-api/src/controllers/bridgeController.ts b/packages/rest-api/src/controllers/bridgeController.ts index aeead94c52..f5cffdb45c 100644 --- a/packages/rest-api/src/controllers/bridgeController.ts +++ b/packages/rest-api/src/controllers/bridgeController.ts @@ -1,8 +1,10 @@ import { validationResult } from 'express-validator' import { parseUnits } from '@ethersproject/units' +import { isAddress } from 'ethers/lib/utils' import { formatBNToString } from '../utils/formatBNToString' import { Synapse } from '../services/synapseService' +import { tokenAddressToToken } from '../utils/tokenAddressToToken' export const bridgeController = async (req, res) => { const errors = validationResult(req) @@ -10,17 +12,28 @@ export const bridgeController = async (req, res) => { return res.status(400).json({ errors: errors.array() }) } try { - const { fromChain, toChain, amount } = req.query - const fromTokenInfo = res.locals.tokenInfo.fromToken - const toTokenInfo = res.locals.tokenInfo.toToken + const { fromChain, toChain, amount, fromToken, toToken } = req.query + + if (!isAddress(fromToken) || !isAddress(toToken)) { + return res.status(400).json({ error: 'Invalid token address' }) + } + + const fromTokenInfo = tokenAddressToToken(fromChain.toString(), fromToken) + const toTokenInfo = tokenAddressToToken(toChain.toString(), toToken) + + if (!fromTokenInfo || !toTokenInfo) { + return res + .status(400) + .json({ error: 'Token not supported on specified chain' }) + } const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals) const resp = await Synapse.allBridgeQuotes( Number(fromChain), Number(toChain), - fromTokenInfo.address, - toTokenInfo.address, + fromToken, + toToken, amountInWei ) const payload = resp.map((quote) => ({ diff --git a/packages/rest-api/src/controllers/bridgeTxInfoController.ts b/packages/rest-api/src/controllers/bridgeTxInfoController.ts index 3f75330dee..62e070d2f4 100644 --- a/packages/rest-api/src/controllers/bridgeTxInfoController.ts +++ b/packages/rest-api/src/controllers/bridgeTxInfoController.ts @@ -1,7 +1,9 @@ import { validationResult } from 'express-validator' import { parseUnits } from '@ethersproject/units' +import { isAddress } from 'ethers/lib/utils' import { Synapse } from '../services/synapseService' +import { tokenAddressToToken } from '../utils/tokenAddressToToken' export const bridgeTxInfoController = async (req, res) => { const errors = validationResult(req) @@ -10,17 +12,28 @@ export const bridgeTxInfoController = async (req, res) => { } try { - const { fromChain, toChain, amount, destAddress } = req.query - const fromTokenInfo = res.locals.tokenInfo.fromToken - const toTokenInfo = res.locals.tokenInfo.toToken + const { fromChain, toChain, amount, destAddress, fromToken, toToken } = req.query + + if (!isAddress(fromToken) || !isAddress(toToken)) { + return res.status(400).json({ error: 'Invalid token address' }) + } + + const fromTokenInfo = tokenAddressToToken(fromChain.toString(), fromToken) + const toTokenInfo = tokenAddressToToken(toChain.toString(), toToken) + + if (!fromTokenInfo || !toTokenInfo) { + return res + .status(400) + .json({ error: 'Token not supported on specified chain' }) + } const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals) const quotes = await Synapse.allBridgeQuotes( Number(fromChain), Number(toChain), - fromTokenInfo.address, - toTokenInfo.address, + fromToken, + toToken, amountInWei ) @@ -31,7 +44,7 @@ export const bridgeTxInfoController = async (req, res) => { quote.routerAddress, Number(fromChain), Number(toChain), - fromTokenInfo.address, + fromToken, amountInWei, quote.originQuery, quote.destQuery diff --git a/packages/rest-api/src/controllers/swapController.ts b/packages/rest-api/src/controllers/swapController.ts index 53d28412bb..44716cef13 100644 --- a/packages/rest-api/src/controllers/swapController.ts +++ b/packages/rest-api/src/controllers/swapController.ts @@ -1,7 +1,9 @@ import { validationResult } from 'express-validator' import { formatUnits, parseUnits } from '@ethersproject/units' +import { isAddress } from 'ethers/lib/utils' import { Synapse } from '../services/synapseService' +import { tokenAddressToToken } from '../utils/tokenAddressToToken' export const swapController = async (req, res) => { const errors = validationResult(req) @@ -9,15 +11,26 @@ export const swapController = async (req, res) => { return res.status(400).json({ errors: errors.array() }) } try { - const { chain, amount } = req.query - const fromTokenInfo = res.locals.tokenInfo.fromToken - const toTokenInfo = res.locals.tokenInfo.toToken + const { chain, amount, fromToken, toToken } = req.query + + if (!isAddress(fromToken) || !isAddress(toToken)) { + return res.status(400).json({ error: 'Invalid token address' }) + } + + const fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken) + const toTokenInfo = tokenAddressToToken(chain.toString(), toToken) + + if (!fromTokenInfo || !toTokenInfo) { + return res + .status(400) + .json({ error: 'Token not supported on specified chain' }) + } const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals) const quote = await Synapse.swapQuote( Number(chain), - fromTokenInfo.address, - toTokenInfo.address, + fromToken, + toToken, amountInWei ) res.json({ diff --git a/packages/rest-api/src/controllers/swapTxInfoController.ts b/packages/rest-api/src/controllers/swapTxInfoController.ts index 618239eb5e..2aa2f824cd 100644 --- a/packages/rest-api/src/controllers/swapTxInfoController.ts +++ b/packages/rest-api/src/controllers/swapTxInfoController.ts @@ -1,7 +1,9 @@ import { validationResult } from 'express-validator' import { parseUnits } from '@ethersproject/units' +import { isAddress } from 'ethers/lib/utils' import { Synapse } from '../services/synapseService' +import { tokenAddressToToken } from '../utils/tokenAddressToToken' export const swapTxInfoController = async (req, res) => { const errors = validationResult(req) @@ -10,23 +12,34 @@ export const swapTxInfoController = async (req, res) => { } try { - const { chain, amount, address } = req.query - const fromTokenInfo = res.locals.tokenInfo.fromToken - const toTokenInfo = res.locals.tokenInfo.toToken + const { chain, amount, address, fromToken, toToken } = req.query + + if (!isAddress(fromToken) || !isAddress(toToken)) { + return res.status(400).json({ error: 'Invalid token address' }) + } + + const fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken) + const toTokenInfo = tokenAddressToToken(chain.toString(), toToken) + + if (!fromTokenInfo || !toTokenInfo) { + return res + .status(400) + .json({ error: 'Token not supported on specified chain' }) + } const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals) const quote = await Synapse.swapQuote( Number(chain), - fromTokenInfo.address, - toTokenInfo.address, + fromToken, + toToken, amountInWei ) const txInfo = await Synapse.swap( Number(chain), address, - toTokenInfo.address, + toToken, amountInWei, quote.query ) diff --git a/packages/rest-api/src/routes/bridgeRoute.ts b/packages/rest-api/src/routes/bridgeRoute.ts index cb00696b5b..c4e03ac540 100644 --- a/packages/rest-api/src/routes/bridgeRoute.ts +++ b/packages/rest-api/src/routes/bridgeRoute.ts @@ -1,8 +1,8 @@ import express from 'express' import { check } from 'express-validator' +import { isAddress } from 'ethers/lib/utils' import { CHAINS_ARRAY } from '../constants/chains' -import { validateTokens } from '../validations/validateTokens' import { showFirstValidationError } from '../middleware/showFirstValidationError' import { bridgeController } from '../controllers/bridgeController' @@ -23,9 +23,17 @@ router.get( .withMessage('Unsupported toChain') .exists() .withMessage('toChain is required'), - validateTokens('fromChain', 'fromToken', 'fromToken'), - validateTokens('toChain', 'toToken', 'toToken'), - check('amount').isNumeric(), + 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'), + check('amount').isNumeric().exists().withMessage('amount is required'), ], showFirstValidationError, bridgeController diff --git a/packages/rest-api/src/routes/bridgeTxInfoRoute.ts b/packages/rest-api/src/routes/bridgeTxInfoRoute.ts index 8929f66202..73f2f74d45 100644 --- a/packages/rest-api/src/routes/bridgeTxInfoRoute.ts +++ b/packages/rest-api/src/routes/bridgeTxInfoRoute.ts @@ -1,8 +1,8 @@ import express from 'express' import { check } from 'express-validator' +import { isAddress } from 'ethers/lib/utils' import { CHAINS_ARRAY } from '../constants/chains' -import { validateTokens } from '../validations/validateTokens' import { showFirstValidationError } from '../middleware/showFirstValidationError' import { bridgeTxInfoController } from '../controllers/bridgeTxInfoController' @@ -23,10 +23,22 @@ router.get( .withMessage('Unsupported toChain') .exists() .withMessage('toChain is required'), - validateTokens('fromChain', 'fromToken', 'fromToken'), - validateTokens('toChain', 'toToken', 'toToken'), - check('amount').isNumeric(), - check('destAddress').isString(), + 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'), + check('amount').isNumeric().exists().withMessage('amount is required'), + check('destAddress') + .exists() + .withMessage('destAddress is required') + .custom((value) => isAddress(value)) + .withMessage('Invalid destination address'), ], showFirstValidationError, bridgeTxInfoController diff --git a/packages/rest-api/src/routes/swapRoute.ts b/packages/rest-api/src/routes/swapRoute.ts index 8aaeac316f..77d279fbc0 100644 --- a/packages/rest-api/src/routes/swapRoute.ts +++ b/packages/rest-api/src/routes/swapRoute.ts @@ -1,7 +1,7 @@ import express from 'express' import { check } from 'express-validator' +import { isAddress } from 'ethers/lib/utils' -import { validateTokens } from '../validations/validateTokens' import { showFirstValidationError } from '../middleware/showFirstValidationError' import { swapController } from '../controllers/swapController' import { CHAINS_ARRAY } from '../constants/chains' @@ -17,8 +17,16 @@ router.get( .withMessage('Unsupported chain') .exists() .withMessage('chain is required'), - validateTokens('chain', 'fromToken', 'fromToken'), - validateTokens('chain', 'toToken', 'toToken'), + 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'), check('amount').isNumeric().exists().withMessage('amount is required'), ], showFirstValidationError, diff --git a/packages/rest-api/src/routes/swapTxInfoRoute.ts b/packages/rest-api/src/routes/swapTxInfoRoute.ts index 9cc9805b6d..956d287aff 100644 --- a/packages/rest-api/src/routes/swapTxInfoRoute.ts +++ b/packages/rest-api/src/routes/swapTxInfoRoute.ts @@ -1,8 +1,8 @@ import express from 'express' import { check } from 'express-validator' +import { isAddress } from 'ethers/lib/utils' import { CHAINS_ARRAY } from '../constants/chains' -import { validateTokens } from '../validations/validateTokens' import { showFirstValidationError } from '../middleware/showFirstValidationError' import { swapTxInfoController } from '../controllers/swapTxInfoController' @@ -17,9 +17,22 @@ router.get( .withMessage('Unsupported chain') .exists() .withMessage('chain is required'), - validateTokens('chain', 'fromToken', 'fromToken'), - validateTokens('chain', 'toToken', 'toToken'), - check('amount').isNumeric(), + 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'), + check('amount').isNumeric().exists().withMessage('amount is required'), + check('address') + .exists() + .withMessage('address is required') + .custom((value) => isAddress(value)) + .withMessage('Invalid Ethereum address'), ], showFirstValidationError, swapTxInfoController diff --git a/packages/rest-api/src/tests/bridgeRoute.test.ts b/packages/rest-api/src/tests/bridgeRoute.test.ts index 16addfc80f..e7795f69a4 100644 --- a/packages/rest-api/src/tests/bridgeRoute.test.ts +++ b/packages/rest-api/src/tests/bridgeRoute.test.ts @@ -11,8 +11,8 @@ describe('Bridge Route with Real Synapse Service', () => { const response = await request(app).get('/bridge').query({ fromChain: '1', toChain: '137', - fromToken: 'USDC', - toToken: 'USDC', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum + toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', // USDC.e on Polygon amount: '1000', }) expect(response.status).toBe(200) @@ -26,8 +26,8 @@ describe('Bridge Route with Real Synapse Service', () => { const response = await request(app).get('/bridge').query({ fromChain: '999', toChain: '137', - fromToken: 'USDC', - toToken: 'USDC', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', amount: '1000', }) expect(response.status).toBe(400) @@ -41,34 +41,36 @@ describe('Bridge Route with Real Synapse Service', () => { const response = await request(app).get('/bridge').query({ fromChain: '1', toChain: '999', - fromToken: 'USDC', - toToken: 'USDC', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', amount: '1000', }) expect(response.status).toBe(400) expect(response.body.error).toHaveProperty('message', 'Unsupported toChain') }, 10000) - it('should return 400 for missing fromToken, with error message', async () => { + it('should return 400 for invalid fromToken address, with error message', async () => { const response = await request(app).get('/bridge').query({ fromChain: '1', toChain: '137', - toToken: 'USDC', + fromToken: 'invalid_address', + toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', amount: '1000', }) - expect(response.status).toBe(400) - expect(response.body.error).toHaveProperty('field', 'fromToken') + expect(response.body.error).toHaveProperty( + 'message', + 'Invalid fromToken address' + ) }, 10000) it('should return 400 for missing amount, with error message', async () => { const response = await request(app).get('/bridge').query({ fromChain: '1', toChain: '137', - fromToken: 'USDC', - toToken: 'USDC', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', }) - expect(response.status).toBe(400) expect(response.body.error).toHaveProperty('field', 'amount') }, 10000) diff --git a/packages/rest-api/src/tests/bridgeTxInfoRoute.test.ts b/packages/rest-api/src/tests/bridgeTxInfoRoute.test.ts index 8e83702336..41b9c77b8e 100644 --- a/packages/rest-api/src/tests/bridgeTxInfoRoute.test.ts +++ b/packages/rest-api/src/tests/bridgeTxInfoRoute.test.ts @@ -11,8 +11,8 @@ describe('Bridge TX Info Route', () => { const response = await request(app).get('/bridgeTxInfo').query({ fromChain: '1', toChain: '137', - fromToken: 'USDC', - toToken: 'USDC', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum + toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', // USDC on Polygon amount: '1000', destAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', }) @@ -31,8 +31,8 @@ describe('Bridge TX Info Route', () => { const response = await request(app).get('/bridgeTxInfo').query({ fromChain: '999', toChain: '137', - fromToken: 'USDC', - toToken: 'USDC', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', amount: '1000', destAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', }) @@ -43,52 +43,47 @@ describe('Bridge TX Info Route', () => { ) }, 10_000) - it('should return 400 for unsupported toChain', async () => { - const response = await request(app).get('/bridgeTxInfo').query({ - fromChain: '1', - toChain: '999', - fromToken: 'USDC', - toToken: 'USDC', - amount: '1000', - destAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', - }) - expect(response.status).toBe(400) - expect(response.body.error).toHaveProperty('message', 'Unsupported toChain') - }, 10_000) - - it('should return 400 for missing fromToken', async () => { + it('should return 400 for invalid fromToken address', async () => { const response = await request(app).get('/bridgeTxInfo').query({ fromChain: '1', toChain: '137', - toToken: 'USDC', + fromToken: 'invalid_address', + toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', amount: '1000', destAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', }) expect(response.status).toBe(400) - expect(response.body.error).toHaveProperty('field', 'fromToken') + expect(response.body.error).toHaveProperty( + 'message', + 'Invalid fromToken address' + ) }, 10_000) it('should return 400 for missing amount', async () => { const response = await request(app).get('/bridgeTxInfo').query({ fromChain: '1', toChain: '137', - fromToken: 'USDC', - toToken: 'USDC', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', destAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', }) expect(response.status).toBe(400) expect(response.body.error).toHaveProperty('field', 'amount') }, 10_000) - it('should return 400 for missing destAddress', async () => { + it('should return 400 for invalid destAddress', async () => { const response = await request(app).get('/bridgeTxInfo').query({ fromChain: '1', toChain: '137', - fromToken: 'USDC', - toToken: 'USDC', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', amount: '1000', + destAddress: 'invalid_address', }) expect(response.status).toBe(400) - expect(response.body.error).toHaveProperty('field', 'destAddress') + expect(response.body.error).toHaveProperty( + 'message', + 'Invalid destination address' + ) }, 10_000) }) diff --git a/packages/rest-api/src/tests/swapRoute.test.ts b/packages/rest-api/src/tests/swapRoute.test.ts index 24d2e05861..4cf644e8d6 100644 --- a/packages/rest-api/src/tests/swapRoute.test.ts +++ b/packages/rest-api/src/tests/swapRoute.test.ts @@ -10,8 +10,8 @@ describe('Swap Route with Real Synapse Service', () => { it('should return a real swap quote for valid input, 1000 USDC', async () => { const response = await request(app).get('/swap').query({ chain: '1', - fromToken: 'USDC', - toToken: 'DAI', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum + toToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI on Ethereum amount: '1000', }) @@ -24,32 +24,35 @@ describe('Swap Route with Real Synapse Service', () => { it('should return 400 for unsupported chain, with error message', async () => { const response = await request(app).get('/swap').query({ chain: '111', - fromToken: 'USDC', - toToken: 'DAI', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', amount: '1000', }) expect(response.status).toBe(400) expect(response.body.error).toHaveProperty('message', 'Unsupported chain') - expect(response.body.error).toHaveProperty('field', 'chain') }, 10_000) - it('should return 400 for missing toToken, with error message', async () => { + it('should return 400 for invalid toToken address, with error message', async () => { const response = await request(app).get('/swap').query({ chain: '1', - fromToken: 'USDC', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: 'invalid_address', amount: '1000', }) expect(response.status).toBe(400) - expect(response.body.error).toHaveProperty('field', 'toToken') + expect(response.body.error).toHaveProperty( + 'message', + 'Invalid toToken address' + ) }, 10_000) it('should return 400 for missing amount, with error message', async () => { const response = await request(app).get('/swap').query({ chain: '1', - fromToken: 'USDC', - toToken: 'DAI', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', }) expect(response.status).toBe(400) diff --git a/packages/rest-api/src/tests/swapTxInfoRoute.test.ts b/packages/rest-api/src/tests/swapTxInfoRoute.test.ts index 3c682006da..479c925ef5 100644 --- a/packages/rest-api/src/tests/swapTxInfoRoute.test.ts +++ b/packages/rest-api/src/tests/swapTxInfoRoute.test.ts @@ -10,9 +10,10 @@ describe('Swap TX Info Route with Real Synapse Service', () => { it('should return transaction info for valid input, 1000 USDC to DAI', async () => { const response = await request(app).get('/swapTxInfo').query({ chain: '1', - fromToken: 'USDC', - toToken: 'DAI', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum + toToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI on Ethereum amount: '1000', + address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', }) expect(response.status).toBe(200) expect(response.body).toHaveProperty('data') @@ -20,33 +21,51 @@ describe('Swap TX Info Route with Real Synapse Service', () => { expect(response.body).toHaveProperty('value') }, 10_000) + it('should return 400 for invalid address, with error message', async () => { + const response = await request(app).get('/swapTxInfo').query({ + chain: '1', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + amount: '1000', + address: 'invalid_address', + }) + expect(response.status).toBe(400) + expect(response.body.error).toHaveProperty('message', 'Invalid Ethereum address') + }, 10_000) + it('should return 400 for unsupported chain, with error message', async () => { const response = await request(app).get('/swapTxInfo').query({ chain: '111', - fromToken: 'USDC', - toToken: 'DAI', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', amount: '1000', + address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', }) expect(response.status).toBe(400) expect(response.body.error).toHaveProperty('message', 'Unsupported chain') - expect(response.body.error).toHaveProperty('field', 'chain') }, 10_000) - it('should return 400 for missing toToken, with error message', async () => { + it('should return 400 for invalid toToken address, with error message', async () => { const response = await request(app).get('/swapTxInfo').query({ chain: '1', - fromToken: 'USDC', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: 'invalid_address', amount: '1000', + address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', }) expect(response.status).toBe(400) - expect(response.body.error).toHaveProperty('field', 'toToken') + expect(response.body.error).toHaveProperty( + 'message', + 'Invalid toToken address' + ) }, 10_000) it('should return 400 for missing amount, with error message', async () => { const response = await request(app).get('/swapTxInfo').query({ chain: '1', - fromToken: 'USDC', - toToken: 'DAI', + fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + toToken: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', }) expect(response.status).toBe(400) expect(response.body.error).toHaveProperty('field', 'amount') diff --git a/packages/rest-api/src/utils/tokenAddressToToken.ts b/packages/rest-api/src/utils/tokenAddressToToken.ts new file mode 100644 index 0000000000..f28c9b86e1 --- /dev/null +++ b/packages/rest-api/src/utils/tokenAddressToToken.ts @@ -0,0 +1,17 @@ +import { BRIDGE_MAP } from '../constants/bridgeMap' + +export const tokenAddressToToken = (chain: string, tokenAddress: string) => { + const chainData = BRIDGE_MAP[chain] + if (!chainData) { + return null + } + const tokenInfo = chainData[tokenAddress] + if (!tokenInfo) { + return null + } + return { + address: tokenAddress, + symbol: tokenInfo.symbol, + decimals: tokenInfo.decimals, + } +} diff --git a/packages/rest-api/src/utils/findTokenInfo.ts b/packages/rest-api/src/utils/tokenSymbolToToken.ts similarity index 82% rename from packages/rest-api/src/utils/findTokenInfo.ts rename to packages/rest-api/src/utils/tokenSymbolToToken.ts index 7cd4e9d63d..bed196c851 100644 --- a/packages/rest-api/src/utils/findTokenInfo.ts +++ b/packages/rest-api/src/utils/tokenSymbolToToken.ts @@ -1,6 +1,6 @@ import { BRIDGE_MAP } from '../constants/bridgeMap' -export const findTokenInfo = (chain: string, tokenSymbol: string) => { +export const tokenSymbolToToken = (chain: string, tokenSymbol: string) => { const chainData = BRIDGE_MAP[chain] if (!chainData) { return null diff --git a/packages/rest-api/src/validations/validateTokens.ts b/packages/rest-api/src/validations/validateTokens.ts index c787115e1e..6e89a9c70c 100644 --- a/packages/rest-api/src/validations/validateTokens.ts +++ b/packages/rest-api/src/validations/validateTokens.ts @@ -1,6 +1,6 @@ import { check } from 'express-validator' -import { findTokenInfo } from '../utils/findTokenInfo' +import { tokenSymbolToToken } from '../utils/tokenSymbolToToken' export const validateTokens = (chainParam, tokenParam, paramName) => { return check(tokenParam) @@ -9,7 +9,7 @@ export const validateTokens = (chainParam, tokenParam, paramName) => { .withMessage(`${paramName} is required`) .custom((value, { req }) => { const chain = req.query[chainParam] - const tokenInfo = findTokenInfo(chain, value) + const tokenInfo = tokenSymbolToToken(chain, value) if (!tokenInfo) { throw new Error(`Invalid ${paramName} symbol`) }