Skip to content

Commit

Permalink
new tests and new functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Defi-Moses committed Sep 17, 2024
1 parent 42890d9 commit f0a059b
Show file tree
Hide file tree
Showing 16 changed files with 161 additions and 72 deletions.
2 changes: 1 addition & 1 deletion packages/rest-api/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ module.exports = {
'^.+\\.(ts|tsx)$': 'babel-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
moduleDirectories: ['node_modules', 'src'],
moduleDirectories: ['node_modules', '<rootDir>'],
}
1 change: 1 addition & 0 deletions packages/rest-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"ethers": "5.7.2",
"express": "^4.18.2",
"express-validator": "^7.2.0",
"jest": "^29.7.0",
"lodash": "^4.17.21"
},
"description": "A node.js project exposing a rest api for synapse sdk quotes",
Expand Down
11 changes: 0 additions & 11 deletions packages/rest-api/src/controllers/bridgeController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
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'
Expand All @@ -14,19 +13,9 @@ export const bridgeController = async (req, res) => {
try {
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(
Expand Down
12 changes: 0 additions & 12 deletions packages/rest-api/src/controllers/bridgeTxInfoController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
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'
Expand All @@ -15,18 +14,7 @@ export const bridgeTxInfoController = async (req, res) => {
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)

Expand Down
20 changes: 8 additions & 12 deletions packages/rest-api/src/controllers/swapController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { validationResult } from 'express-validator'
import { formatUnits, parseUnits } from '@ethersproject/units'
import { isAddress } from 'ethers/lib/utils'
import { BigNumber } from '@ethersproject/bignumber'

import { Synapse } from '../services/synapseService'
import { tokenAddressToToken } from '../utils/tokenAddressToToken'
Expand All @@ -13,29 +13,25 @@ export const swapController = async (req, res) => {
try {
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),
fromToken,
toToken,
amountInWei
)

const formattedMaxAmountOut = formatUnits(
BigNumber.from(quote.maxAmountOut),
toTokenInfo.decimals
)

res.json({
maxAmountOut: formatUnits(quote.maxAmountOut, toTokenInfo.decimals),
...quote,
maxAmountOut: formattedMaxAmountOut,
})
} catch (err) {
res.status(500).json({
Expand Down
12 changes: 0 additions & 12 deletions packages/rest-api/src/controllers/swapTxInfoController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
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'
Expand All @@ -14,18 +13,7 @@ export const swapTxInfoController = async (req, res) => {
try {
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)

Expand Down
19 changes: 14 additions & 5 deletions packages/rest-api/src/routes/bridgeRoute.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import express from 'express'
import { check } from 'express-validator'
import { isAddress } from 'ethers/lib/utils'

import { isTokenAddress } from '../utils/isTokenAddress'
import { CHAINS_ARRAY } from '../constants/chains'
import { showFirstValidationError } from '../middleware/showFirstValidationError'
import { bridgeController } from '../controllers/bridgeController'
import { isTokenSupportedOnChain } from '../utils/isTokenSupportedOnChain'

const router = express.Router()

Expand All @@ -26,13 +27,21 @@ router.get(
check('fromToken')
.exists()
.withMessage('fromToken is required')
.custom((value) => isAddress(value))
.withMessage('Invalid fromToken address'),
.custom((value) => isTokenAddress(value))
.withMessage('Invalid fromToken address')
.custom((value, { req }) =>
isTokenSupportedOnChain(value, req.query.fromChain as string)
)
.withMessage('Token not supported on specified chain'),
check('toToken')
.exists()
.withMessage('toToken is required')
.custom((value) => isAddress(value))
.withMessage('Invalid toToken address'),
.custom((value) => isTokenAddress(value))
.withMessage('Invalid toToken address')
.custom((value, { req }) =>
isTokenSupportedOnChain(value, req.query.toChain as string)
)
.withMessage('Token not supported on specified chain'),
check('amount').isNumeric().exists().withMessage('amount is required'),
],
showFirstValidationError,
Expand Down
18 changes: 14 additions & 4 deletions packages/rest-api/src/routes/bridgeTxInfoRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { isAddress } from 'ethers/lib/utils'
import { CHAINS_ARRAY } from '../constants/chains'
import { showFirstValidationError } from '../middleware/showFirstValidationError'
import { bridgeTxInfoController } from '../controllers/bridgeTxInfoController'
import { isTokenAddress } from '../utils/isTokenAddress'
import { isTokenSupportedOnChain } from '../utils/isTokenSupportedOnChain'

const router = express.Router()

Expand All @@ -26,13 +28,21 @@ router.get(
check('fromToken')
.exists()
.withMessage('fromToken is required')
.custom((value) => isAddress(value))
.withMessage('Invalid fromToken address'),
.custom((value) => isTokenAddress(value))
.withMessage('Invalid fromToken address')
.custom((value, { req }) =>
isTokenSupportedOnChain(value, req.query.fromChain as string)
)
.withMessage('Token not supported on specified chain'),
check('toToken')
.exists()
.withMessage('toToken is required')
.custom((value) => isAddress(value))
.withMessage('Invalid toToken address'),
.custom((value) => isTokenAddress(value))
.withMessage('Invalid toToken address')
.custom((value, { req }) =>
isTokenSupportedOnChain(value, req.query.toChain as string)
)
.withMessage('Token not supported on specified chain'),
check('amount').isNumeric().exists().withMessage('amount is required'),
check('destAddress')
.exists()
Expand Down
19 changes: 14 additions & 5 deletions packages/rest-api/src/routes/swapRoute.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import express from 'express'
import { check } from 'express-validator'
import { isAddress } from 'ethers/lib/utils'

import { showFirstValidationError } from '../middleware/showFirstValidationError'
import { swapController } from '../controllers/swapController'
import { CHAINS_ARRAY } from '../constants/chains'
import { isTokenAddress } from '../utils/isTokenAddress'
import { isTokenSupportedOnChain } from '../utils/isTokenSupportedOnChain'

const router = express.Router()

Expand All @@ -20,13 +21,21 @@ router.get(
check('fromToken')
.exists()
.withMessage('fromToken is required')
.custom((value) => isAddress(value))
.withMessage('Invalid fromToken address'),
.custom((value) => isTokenAddress(value))
.withMessage('Invalid fromToken address')
.custom((value, { req }) =>
isTokenSupportedOnChain(value, req.query.chain as string)
)
.withMessage('Token not supported on specified chain'),
check('toToken')
.exists()
.withMessage('toToken is required')
.custom((value) => isAddress(value))
.withMessage('Invalid toToken address'),
.custom((value) => isTokenAddress(value))
.withMessage('Invalid toToken address')
.custom((value, { req }) =>
isTokenSupportedOnChain(value, req.query.chain as string)
)
.withMessage('Token not supported on specified chain'),
check('amount').isNumeric().exists().withMessage('amount is required'),
],
showFirstValidationError,
Expand Down
18 changes: 14 additions & 4 deletions packages/rest-api/src/routes/swapTxInfoRoute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { isAddress } from 'ethers/lib/utils'
import { CHAINS_ARRAY } from '../constants/chains'
import { showFirstValidationError } from '../middleware/showFirstValidationError'
import { swapTxInfoController } from '../controllers/swapTxInfoController'
import { isTokenAddress } from '../utils/isTokenAddress'
import { isTokenSupportedOnChain } from '../utils/isTokenSupportedOnChain'

const router = express.Router()

Expand All @@ -20,13 +22,21 @@ router.get(
check('fromToken')
.exists()
.withMessage('fromToken is required')
.custom((value) => isAddress(value))
.withMessage('Invalid fromToken address'),
.custom((value) => isTokenAddress(value))
.withMessage('Invalid fromToken address')
.custom((value, { req }) =>
isTokenSupportedOnChain(value, req.query.chain as string)
)
.withMessage('Token not supported on specified chain'),
check('toToken')
.exists()
.withMessage('toToken is required')
.custom((value) => isAddress(value))
.withMessage('Invalid toToken address'),
.custom((value) => isTokenAddress(value))
.withMessage('Invalid toToken address')
.custom((value, { req }) =>
isTokenSupportedOnChain(value, req.query.chain as string)
)
.withMessage('Token not supported on specified chain'),
check('amount').isNumeric().exists().withMessage('amount is required'),
check('address')
.exists()
Expand Down
27 changes: 21 additions & 6 deletions packages/rest-api/src/tests/bridgeRoute.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ const app = express()
app.use('/bridge', bridgeRoute)

describe('Bridge Route with Real Synapse Service', () => {
it('should return bridge quotes for valid input, 1000 USDC from Ethereum to Polygon', async () => {
it('should return bridge quotes for valid input, 1000 USDC from Ethereum to Optimism', async () => {
const response = await request(app).get('/bridge').query({
fromChain: '1',
toChain: '137',
toChain: '10',
fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC on Ethereum
toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', // USDC.e on Polygon
toToken: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', // USDC on Optimism
amount: '1000',
})
expect(response.status).toBe(200)
Expand Down Expand Up @@ -42,7 +42,7 @@ describe('Bridge Route with Real Synapse Service', () => {
fromChain: '1',
toChain: '999',
fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
toToken: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
amount: '1000',
})
expect(response.status).toBe(400)
Expand All @@ -64,12 +64,27 @@ describe('Bridge Route with Real Synapse Service', () => {
)
}, 10000)

it('should return 400 for missing amount, with error message', async () => {
it('should return 400 for token not supported on specified chain, with error message', async () => {
const response = await request(app).get('/bridge').query({
fromChain: '1',
toChain: '137',
fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
fromToken: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', // SNX on Ethereum (Not supported)
toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
amount: '1000',
})
expect(response.status).toBe(400)
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: '10',
fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
toToken: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',
})
expect(response.status).toBe(400)
expect(response.body.error).toHaveProperty('field', 'amount')
Expand Down
16 changes: 16 additions & 0 deletions packages/rest-api/src/tests/bridgeTxInfoRoute.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,22 @@ describe('Bridge TX Info Route', () => {
)
}, 10_000)

it('should return 400 for token not supported on specified chain', async () => {
const response = await request(app).get('/bridgeTxInfo').query({
fromChain: '1',
toChain: '137',
fromToken: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', // SNX on Ethereum (Not supported)
toToken: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
amount: '1000',
destAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
})
expect(response.status).toBe(400)
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',
Expand Down
15 changes: 15 additions & 0 deletions packages/rest-api/src/tests/swapRoute.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ describe('Swap Route with Real Synapse Service', () => {
)
}, 10_000)

it('should return 400 for token not supported on specified chain', async () => {
const response = await request(app).get('/swap').query({
chain: '1',
fromToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
toToken: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F', // SNX on Ethereum (Not supported)
amount: '1000',
})

expect(response.status).toBe(400)
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',
Expand Down
Loading

0 comments on commit f0a059b

Please sign in to comment.