From c695ad4625407d019f2321b22159b53ab89ae8d2 Mon Sep 17 00:00:00 2001 From: defi-moses Date: Sat, 28 Sep 2024 12:11:34 +0100 Subject: [PATCH 1/3] adding originUserAddress for refunds --- .../rest-api/src/controllers/bridgeController.ts | 14 ++++++++++++-- .../src/controllers/bridgeTxInfoController.ts | 16 +++++++++++++--- packages/rest-api/src/routes/bridgeRoute.ts | 6 ++++++ .../rest-api/src/routes/bridgeTxInfoRoute.ts | 6 ++++++ 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/packages/rest-api/src/controllers/bridgeController.ts b/packages/rest-api/src/controllers/bridgeController.ts index 568c4eb0fc..f69c8715f0 100644 --- a/packages/rest-api/src/controllers/bridgeController.ts +++ b/packages/rest-api/src/controllers/bridgeController.ts @@ -11,7 +11,14 @@ export const bridgeController = async (req, res) => { return res.status(400).json({ errors: errors.array() }) } try { - const { fromChain, toChain, amount, fromToken, toToken } = req.query + const { + fromChain, + toChain, + amount, + fromToken, + toToken, + originUserAddress, + } = req.query const fromTokenInfo = tokenAddressToToken(fromChain.toString(), fromToken) const toTokenInfo = tokenAddressToToken(toChain.toString(), toToken) @@ -23,7 +30,10 @@ export const bridgeController = async (req, res) => { Number(toChain), fromToken, toToken, - amountInWei + amountInWei, + originUserAddress + ? { originUserAddress: originUserAddress.toString() } + : {} ) const payload = resp.map((quote) => { diff --git a/packages/rest-api/src/controllers/bridgeTxInfoController.ts b/packages/rest-api/src/controllers/bridgeTxInfoController.ts index 0a0b4bc7bc..01a56f01ca 100644 --- a/packages/rest-api/src/controllers/bridgeTxInfoController.ts +++ b/packages/rest-api/src/controllers/bridgeTxInfoController.ts @@ -11,8 +11,15 @@ export const bridgeTxInfoController = async (req, res) => { } try { - const { fromChain, toChain, amount, destAddress, fromToken, toToken } = - req.query + const { + fromChain, + toChain, + amount, + destAddress, + fromToken, + toToken, + originUserAddress, + } = req.query const fromTokenInfo = tokenAddressToToken(fromChain.toString(), fromToken) @@ -23,7 +30,10 @@ export const bridgeTxInfoController = async (req, res) => { Number(toChain), fromToken, toToken, - amountInWei + amountInWei, + originUserAddress + ? { originUserAddress: originUserAddress.toString() } + : {} ) const txInfoArray = await Promise.all( diff --git a/packages/rest-api/src/routes/bridgeRoute.ts b/packages/rest-api/src/routes/bridgeRoute.ts index 0e4a88b947..c391b250cc 100644 --- a/packages/rest-api/src/routes/bridgeRoute.ts +++ b/packages/rest-api/src/routes/bridgeRoute.ts @@ -49,6 +49,12 @@ const router = express.Router() * schema: * type: number * description: The amount of tokens to bridge + * - in: query + * name: originUserAddress + * required: false + * schema: + * type: string + * description: The address of the user on the origin chain * responses: * 200: * description: Successful response diff --git a/packages/rest-api/src/routes/bridgeTxInfoRoute.ts b/packages/rest-api/src/routes/bridgeTxInfoRoute.ts index 5a0ce30326..9154467e37 100644 --- a/packages/rest-api/src/routes/bridgeTxInfoRoute.ts +++ b/packages/rest-api/src/routes/bridgeTxInfoRoute.ts @@ -51,6 +51,12 @@ const router = express.Router() * type: number * description: The amount of tokens to bridge * - in: query + * name: originUserAddress + * required: false + * schema: + * type: string + * description: The address of the user on the origin chain + * - in: query * name: destAddress * required: true * schema: From 2c4a2035b740789b71ffa3383b3def6a52d336b5 Mon Sep 17 00:00:00 2001 From: abtestingalpha Date: Sat, 28 Sep 2024 10:41:18 -0400 Subject: [PATCH 2/3] Adds validation & tests --- packages/rest-api/src/routes/bridgeRoute.ts | 5 +++ .../rest-api/src/routes/bridgeTxInfoRoute.ts | 4 ++ .../rest-api/src/tests/bridgeRoute.test.ts | 34 ++++++++++++++++ .../src/tests/bridgeTxInfoRoute.test.ts | 39 +++++++++++++++++++ 4 files changed, 82 insertions(+) diff --git a/packages/rest-api/src/routes/bridgeRoute.ts b/packages/rest-api/src/routes/bridgeRoute.ts index c391b250cc..5c5d7b6c65 100644 --- a/packages/rest-api/src/routes/bridgeRoute.ts +++ b/packages/rest-api/src/routes/bridgeRoute.ts @@ -1,5 +1,6 @@ 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' @@ -236,6 +237,10 @@ router.get( return validateRouteExists(fromChain, fromToken, toChain, toToken) }) .withMessage('No valid route exists for the chain/token combination'), + check('originUserAddress') + .optional() + .custom((value) => isAddress(value)) + .withMessage('Invalid originUserAddress address'), ], showFirstValidationError, bridgeController diff --git a/packages/rest-api/src/routes/bridgeTxInfoRoute.ts b/packages/rest-api/src/routes/bridgeTxInfoRoute.ts index 9154467e37..ed36c7dde1 100644 --- a/packages/rest-api/src/routes/bridgeTxInfoRoute.ts +++ b/packages/rest-api/src/routes/bridgeTxInfoRoute.ts @@ -177,6 +177,10 @@ router.get( return validateRouteExists(fromChain, fromToken, toChain, toToken) }) .withMessage('No valid route exists for the chain/token combination'), + check('originUserAddress') + .optional() + .custom((value) => isAddress(value)) + .withMessage('Invalid originUserAddress address'), ], showFirstValidationError, bridgeTxInfoController diff --git a/packages/rest-api/src/tests/bridgeRoute.test.ts b/packages/rest-api/src/tests/bridgeRoute.test.ts index 3617d5d71b..542feab63a 100644 --- a/packages/rest-api/src/tests/bridgeRoute.test.ts +++ b/packages/rest-api/src/tests/bridgeRoute.test.ts @@ -25,6 +25,23 @@ describe('Bridge Route with Real Synapse Service', () => { expect(response.body[0]).toHaveProperty('bridgeFeeFormatted') }, 15000) + it('should return bridge quotes for valid originUserAddress', async () => { + const response = await request(app).get('/bridge').query({ + fromChain: '1', + toChain: '10', + fromToken: USDC.addresses[1], + toToken: USDC.addresses[10], + amount: '1000', + originUserAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', + }) + + expect(response.status).toBe(200) + expect(Array.isArray(response.body)).toBe(true) + expect(response.body.length).toBeGreaterThan(0) + expect(response.body[0]).toHaveProperty('maxAmountOutStr') + expect(response.body[0]).toHaveProperty('bridgeFeeFormatted') + }, 15000) + it('should return bridge quotes for ZeroAddress', async () => { const response = await request(app).get('/bridge').query({ fromChain: '1', @@ -56,6 +73,23 @@ describe('Bridge Route with Real Synapse Service', () => { expect(response.body[0]).toHaveProperty('bridgeFeeFormatted') }, 15000) + it('should return 400 for invalid originUserAddress', async () => { + const response = await request(app).get('/bridge').query({ + fromChain: '1', + toChain: '10', + fromToken: USDC.addresses[1], + toToken: USDC.addresses[10], + amount: '1000', + originUserAddress: 'invalid_address', + }) + + expect(response.status).toBe(400) + expect(response.body.error).toHaveProperty( + 'message', + 'Invalid originUserAddress address' + ) + }, 15000) + it('should return 400 for unsupported route', async () => { const response = await request(app).get('/bridge').query({ fromChain: '1', diff --git a/packages/rest-api/src/tests/bridgeTxInfoRoute.test.ts b/packages/rest-api/src/tests/bridgeTxInfoRoute.test.ts index 9f5d183bbe..e39450e725 100644 --- a/packages/rest-api/src/tests/bridgeTxInfoRoute.test.ts +++ b/packages/rest-api/src/tests/bridgeTxInfoRoute.test.ts @@ -29,6 +29,45 @@ describe('Bridge TX Info Route', () => { ) }, 10_000) + it('should return bridge transaction info for valid input with valid originUserAddress', async () => { + const response = await request(app).get('/bridgeTxInfo').query({ + fromChain: '1', + toChain: '137', + fromToken: USDC.addresses[1], + toToken: USDC.addresses[137], + amount: '1000', + destAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', + originUserAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', + }) + + expect(response.status).toBe(200) + expect(Array.isArray(response.body)).toBe(true) + expect(response.body.length).toBeGreaterThan(0) + expect(response.body[0]).toHaveProperty('data') + expect(response.body[0]).toHaveProperty( + 'to', + '0xd5a597d6e7ddf373a92C8f477DAAA673b0902F48' + ) + }, 10_000) + + it('should return 400 for invalid originUserAddress', async () => { + const response = await request(app).get('/bridgeTxInfo').query({ + fromChain: '1', + toChain: '137', + fromToken: USDC.addresses[1], + toToken: USDC.addresses[137], + amount: '1000', + destAddress: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e', + originUserAddress: 'invalid_address', + }) + + expect(response.status).toBe(400) + expect(response.body.error).toHaveProperty( + 'message', + 'Invalid originUserAddress address' + ) + }, 10_000) + it('should return 400 for unsupported route', async () => { const response = await request(app).get('/bridgeTxInfo').query({ fromChain: '1', From 877b09b5e32c8f88aecea6cd799e5449d723c3ab Mon Sep 17 00:00:00 2001 From: abtestingalpha Date: Sat, 28 Sep 2024 10:45:01 -0400 Subject: [PATCH 3/3] Reorder for required first --- packages/rest-api/src/routes/bridgeTxInfoRoute.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/rest-api/src/routes/bridgeTxInfoRoute.ts b/packages/rest-api/src/routes/bridgeTxInfoRoute.ts index ed36c7dde1..44b6904e08 100644 --- a/packages/rest-api/src/routes/bridgeTxInfoRoute.ts +++ b/packages/rest-api/src/routes/bridgeTxInfoRoute.ts @@ -51,17 +51,17 @@ const router = express.Router() * type: number * description: The amount of tokens to bridge * - in: query - * name: originUserAddress - * required: false - * schema: - * type: string - * description: The address of the user on the origin chain - * - in: query * name: destAddress * required: true * schema: * type: string * description: The destination address for the bridged tokens + * - in: query + * name: originUserAddress + * required: false + * schema: + * type: string + * description: The address of the user on the origin chain * responses: * 200: * description: Successful response