Skip to content

Commit

Permalink
REST API Improvements [SLT-179] (#3133)
Browse files Browse the repository at this point in the history
* fix swaptxinfo function

* Updates test coverage command

* migrating to using token addresses instead of symbols

* fix linting errors

* fixing swaptxinfocontroller

* new tests and new functionality

---------

Co-authored-by: abtestingalpha <[email protected]>
  • Loading branch information
Defi-Moses and abtestingalpha authored Sep 18, 2024
1 parent 89907ce commit 7a118c9
Show file tree
Hide file tree
Showing 19 changed files with 320 additions and 98 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>'],
}
3 changes: 2 additions & 1 deletion packages/rest-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"lint:check": "eslint . --max-warnings=0",
"ci:lint": "npm run lint:check",
"test": "jest",
"test:coverage": "echo 'No tests defined.'"
"test:coverage": "jest --collect-coverage"
},
"dependencies": {
"@ethersproject/bignumber": "^5.7.0",
Expand All @@ -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",
"supertest": "^6.3.3",
"typescript": "^4.8.3"
Expand Down
12 changes: 7 additions & 5 deletions packages/rest-api/src/controllers/bridgeController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,26 @@ import { parseUnits } from '@ethersproject/units'

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)
if (!errors.isEmpty()) {
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

const fromTokenInfo = tokenAddressToToken(fromChain.toString(), fromToken)
const toTokenInfo = tokenAddressToToken(toChain.toString(), toToken)

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) => ({
Expand Down
14 changes: 8 additions & 6 deletions packages/rest-api/src/controllers/bridgeTxInfoController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { validationResult } from 'express-validator'
import { parseUnits } from '@ethersproject/units'

import { Synapse } from '../services/synapseService'
import { tokenAddressToToken } from '../utils/tokenAddressToToken'

export const bridgeTxInfoController = async (req, res) => {
const errors = validationResult(req)
Expand All @@ -10,17 +11,18 @@ 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

const fromTokenInfo = tokenAddressToToken(fromChain.toString(), fromToken)

const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals)

const quotes = await Synapse.allBridgeQuotes(
Number(fromChain),
Number(toChain),
fromTokenInfo.address,
toTokenInfo.address,
fromToken,
toToken,
amountInWei
)

Expand All @@ -31,7 +33,7 @@ export const bridgeTxInfoController = async (req, res) => {
quote.routerAddress,
Number(fromChain),
Number(toChain),
fromTokenInfo.address,
fromToken,
amountInWei,
quote.originQuery,
quote.destQuery
Expand Down
21 changes: 15 additions & 6 deletions packages/rest-api/src/controllers/swapController.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
import { validationResult } from 'express-validator'
import { formatUnits, parseUnits } from '@ethersproject/units'
import { BigNumber } from '@ethersproject/bignumber'

import { Synapse } from '../services/synapseService'
import { tokenAddressToToken } from '../utils/tokenAddressToToken'

export const swapController = async (req, res) => {
const errors = validationResult(req)
if (!errors.isEmpty()) {
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

const fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken)
const toTokenInfo = tokenAddressToToken(chain.toString(), toToken)

const amountInWei = parseUnits(amount.toString(), fromTokenInfo.decimals)
const quote = await Synapse.swapQuote(
Number(chain),
fromTokenInfo.address,
toTokenInfo.address,
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
15 changes: 8 additions & 7 deletions packages/rest-api/src/controllers/swapTxInfoController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { validationResult } from 'express-validator'
import { parseUnits } from '@ethersproject/units'

import { Synapse } from '../services/synapseService'
import { tokenAddressToToken } from '../utils/tokenAddressToToken'

export const swapTxInfoController = async (req, res) => {
const errors = validationResult(req)
Expand All @@ -10,23 +11,23 @@ export const swapTxInfoController = async (req, res) => {
}

try {
const { chain, amount } = req.query
const fromTokenInfo = res.locals.tokenInfo.fromToken
const toTokenInfo = res.locals.tokenInfo.toToken
const { chain, amount, address, fromToken, toToken } = req.query

const fromTokenInfo = tokenAddressToToken(chain.toString(), fromToken)

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),
fromTokenInfo.address,
toTokenInfo.address,
address,
fromToken,
amountInWei,
quote.query
)
Expand Down
25 changes: 21 additions & 4 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 { isTokenAddress } from '../utils/isTokenAddress'
import { CHAINS_ARRAY } from '../constants/chains'
import { validateTokens } from '../validations/validateTokens'
import { showFirstValidationError } from '../middleware/showFirstValidationError'
import { bridgeController } from '../controllers/bridgeController'
import { isTokenSupportedOnChain } from '../utils/isTokenSupportedOnChain'

const router = express.Router()

Expand All @@ -23,9 +24,25 @@ 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) => 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) => 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,
bridgeController
Expand Down
32 changes: 27 additions & 5 deletions packages/rest-api/src/routes/bridgeTxInfoRoute.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
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'
import { isTokenAddress } from '../utils/isTokenAddress'
import { isTokenSupportedOnChain } from '../utils/isTokenSupportedOnChain'

const router = express.Router()

Expand All @@ -23,10 +25,30 @@ 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) => 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) => 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()
.withMessage('destAddress is required')
.custom((value) => isAddress(value))
.withMessage('Invalid destination address'),
],
showFirstValidationError,
bridgeTxInfoController
Expand Down
23 changes: 20 additions & 3 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 { validateTokens } from '../validations/validateTokens'
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 @@ -17,8 +18,24 @@ 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) => 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) => 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
31 changes: 27 additions & 4 deletions packages/rest-api/src/routes/swapTxInfoRoute.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
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'
import { isTokenAddress } from '../utils/isTokenAddress'
import { isTokenSupportedOnChain } from '../utils/isTokenSupportedOnChain'

const router = express.Router()

Expand All @@ -17,9 +19,30 @@ 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) => 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) => 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()
.withMessage('address is required')
.custom((value) => isAddress(value))
.withMessage('Invalid Ethereum address'),
],
showFirstValidationError,
swapTxInfoController
Expand Down
Loading

0 comments on commit 7a118c9

Please sign in to comment.