Skip to content
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

[DNM] Bridge endpoint consolidation [SLT-453] #3371

Merged
merged 2 commits into from
Nov 18, 2024
Merged

Conversation

Defi-Moses
Copy link
Collaborator

@Defi-Moses Defi-Moses commented Nov 5, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced optional destAddress parameter for the /bridge endpoint, enhancing token bridging capabilities.
    • Added optional address parameter for the /swap endpoint, allowing users to specify the address performing the swap.
  • Documentation

    • Updated API documentation to reflect the new parameters and their descriptions for improved clarity and usability.
  • Tests

    • Expanded test coverage for both /bridge and /swap endpoints to ensure robust handling of new parameters and error scenarios.

Copy link
Contributor

coderabbitai bot commented Nov 5, 2024

Walkthrough

The pull request introduces enhancements to the Synapse Protocol REST API, specifically in the bridge and swap functionalities. It adds optional query parameters destAddress and address to their respective controllers and routes, updating the request handling and response structures accordingly. The API documentation is also revised to reflect these changes, including validation logic for the new parameters. Additionally, new test cases are added to ensure proper functionality and error handling for the updated routes.

Changes

File Path Change Summary
packages/rest-api/src/controllers/bridgeController.ts - Added optional destAddress parameter to the request query.
- Updated type definitions for request query.
- Modified response logic to include callData based on destAddress.
packages/rest-api/src/controllers/swapController.ts - Added optional address parameter to the request query.
- Updated logic to conditionally call Synapse.swap based on address presence, and modified response to include callData.
packages/rest-api/src/routes/bridgeRoute.ts - Added optional destAddress parameter in OpenAPI documentation and route validation.
- Updated response schema to include callData property.
packages/rest-api/src/routes/swapRoute.ts - Added optional address parameter in OpenAPI documentation.
- Implemented validation for address parameter.
- Updated response schema to include callData object.
packages/rest-api/src/tests/bridgeRoute.test.ts - Added new test cases for handling destAddress, including valid, invalid, and absence scenarios.
packages/rest-api/src/tests/swapRoute.test.ts - Added new test cases for handling address, including valid, invalid, and absence scenarios.
packages/rest-api/swagger.json - Updated API documentation to include new destAddress and address parameters for /bridge and /swap endpoints, respectively.

Possibly related PRs

Suggested labels

size/m, M-explorer-ui

Suggested reviewers

  • trajan0x
  • bigboydiamonds
  • abtestingalpha

🐇 In the land of code where the rabbits play,
New paths are forged, come join the fray!
With destAddress and address in tow,
Our API leaps, ready to grow!
So hop along, let’s test and see,
What wonders await in our code spree! 🌟


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 2782388 and 7d0afc5.

📒 Files selected for processing (2)
  • packages/rest-api/src/routes/bridgeRoute.ts (3 hunks)
  • packages/rest-api/src/routes/swapRoute.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/rest-api/src/routes/bridgeRoute.ts
  • packages/rest-api/src/routes/swapRoute.ts

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

cloudflare-workers-and-pages bot commented Nov 5, 2024

Deploying sanguine-fe with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7d0afc5
Status: ✅  Deploy successful!
Preview URL: https://23a8196e.sanguine-fe.pages.dev
Branch Preview URL: https://api-bridge-change.sanguine-fe.pages.dev

View logs

Copy link

codecov bot commented Nov 5, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 90.44834%. Comparing base (798286f) to head (7d0afc5).
Report is 2 commits behind head on master.

Additional details and impacted files
@@              Coverage Diff              @@
##              master       #3371   +/-   ##
=============================================
  Coverage   90.44834%   90.44834%           
=============================================
  Files             54          54           
  Lines           1026        1026           
  Branches          82          82           
=============================================
  Hits             928         928           
  Misses            95          95           
  Partials           3           3           
Flag Coverage Δ
packages 90.44834% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (15)
packages/rest-api/src/controllers/swapController.ts (1)

46-46: Document response schema changes

The addition of callData to the response payload is a breaking change that needs proper documentation and potentially a version bump.

Please ensure you:

  1. Update OpenAPI/Swagger documentation to reflect the new response format
  2. Consider versioning the API endpoint (e.g., /v2/swap) to maintain backward compatibility
  3. Add examples in the API documentation showing both cases (with and without address)
packages/rest-api/src/controllers/bridgeController.ts (2)

49-82: Consider performance optimization for response processing

The current implementation processes quotes sequentially within Promise.all. For large response sets, this could impact performance.

Consider parallel processing of independent operations:

const processQuote = async (quote) => {
  const [originQueryTokenOutInfo, callData] = await Promise.all([
    Promise.resolve(tokenAddressToToken(fromChain.toString(), quote.originQuery.tokenOut)),
    destAddress ? Synapse.bridge(...) : Promise.resolve(null)
  ]);
  return {
    ...quote,
    maxAmountOutStr: formatBNToString(quote.maxAmountOut, toTokenInfo.decimals),
    bridgeFeeFormatted: formatBNToString(quote.feeAmount, originQueryTokenOutInfo.decimals),
    callData,
  };
};

49-82: Consider implementing pagination for large response sets

The response processing loads all quotes into memory simultaneously. For large datasets, this could cause memory issues.

Consider implementing pagination:

  1. Add limit and offset query parameters
  2. Process only the requested subset of quotes
  3. Return metadata about total available quotes
packages/rest-api/src/tests/swapRoute.test.ts (4)

137-154: Consider parameterizing the test wallet address.

The test provides good coverage of the callData structure, but using a hardcoded wallet address might make the test brittle. Consider moving the address to a test constants file or using a deterministic test wallet.

+// At the top of the file with other imports
+import { TEST_WALLET_ADDRESS } from '../constants/test'

-      address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
+      address: TEST_WALLET_ADDRESS,

156-169: Add descriptive comment explaining the null callData behavior.

The test correctly verifies the default behavior, but it would be helpful to document why callData is null when no address is provided.

+  // When no address is provided, callData should be null as transaction details
+  // cannot be constructed without a destination address
   it('should return swap quote without callData when address is not provided', async () => {

171-182: Enhance invalid address test coverage.

Consider adding more test cases for different types of invalid addresses:

  • Zero address (0x0000...)
  • Almost valid address (wrong checksum)
  • Address with invalid length

Example addition:

it.each([
  ['0x0000000000000000000000000000000000000000', 'Zero address not allowed'],
  ['0x742d35Cc6634C0532925a3b844Bc454e4438f44', 'Invalid address length'],
  ['0x742d35cc6634c0532925a3b844bc454e4438f44e', 'Invalid checksum']
])('should return 400 for invalid address: %s', async (address, scenario) => {
  const response = await request(app).get('/swap').query({
    chain: '1',
    fromToken: USDC.addresses[1],
    toToken: DAI.addresses[1],
    amount: '1000',
    address,
  })

  expect(response.status).toBe(400)
  expect(response.body.error).toHaveProperty('message', 'Invalid address')
})

136-182: Consider grouping related test cases.

The new address-related tests would be better organized using a describe block to group them together.

+  describe('address parameter handling', () => {
     it('should return swap quote with callData when address is provided', async () => {
       // ... existing test
     })

     it('should return swap quote without callData when address is not provided', async () => {
       // ... existing test
     })

     it('should return 400 for invalid address', async () => {
       // ... existing test
     })
+  })
packages/rest-api/src/routes/swapRoute.ts (1)

196-199: Consider normalizing the address parameter.

The validation for the optional address parameter is well implemented. However, for consistency with other address parameters in the route (fromToken and toToken), consider adding the address parameter to the checksumAddresses middleware.

 router.get(
   '/',
   normalizeNativeTokenAddress(['fromToken', 'toToken']),
-  checksumAddresses(['fromToken', 'toToken']),
+  checksumAddresses(['fromToken', 'toToken', 'address']),
   [
packages/rest-api/src/tests/bridgeRoute.test.ts (3)

177-194: Consider enhancing test coverage with additional assertions.

While the test effectively verifies the presence of callData and its structure, consider adding:

  1. Type checks for callData properties
  2. Assertions for maxAmountOutStr and bridgeFeeFormatted to maintain consistency with other test cases
 expect(response.body[0].callData).toHaveProperty('to')
 expect(response.body[0].callData).toHaveProperty('data')
 expect(response.body[0].callData).toHaveProperty('value')
+expect(typeof response.body[0].callData.to).toBe('string')
+expect(typeof response.body[0].callData.data).toBe('string')
+expect(typeof response.body[0].callData.value).toBe('string')
+expect(response.body[0]).toHaveProperty('maxAmountOutStr')
+expect(response.body[0]).toHaveProperty('bridgeFeeFormatted')

196-209: Maintain consistency with other test cases.

Consider adding assertions for maxAmountOutStr and bridgeFeeFormatted to maintain consistency with other test cases in the file.

 expect(response.body.length).toBeGreaterThan(0)
 expect(response.body[0].callData).toBeNull()
+expect(response.body[0]).toHaveProperty('maxAmountOutStr')
+expect(response.body[0]).toHaveProperty('bridgeFeeFormatted')

211-223: Ensure error response structure consistency.

To maintain consistency with other error cases in the file (e.g., invalid originUserAddress), consider adding an assertion for the error object structure.

 expect(response.status).toBe(400)
+expect(response.body).toHaveProperty('error')
 expect(response.body.error).toHaveProperty('message', 'Invalid destAddress')
packages/rest-api/src/routes/bridgeRoute.ts (3)

59-64: Enhance OpenAPI documentation for destAddress parameter.

While the documentation is technically correct, consider adding more details:

  • Specify that it expects an EVM-compatible address
  • Add an example value
  • Clarify if this is different from originUserAddress and when to use each
 *       - in: query
 *         name: destAddress
 *         required: false
 *         schema:
 *           type: string
-*         description: The destination address for the bridge transaction
+*         description: The EVM-compatible destination address where bridged tokens will be sent. If not provided, tokens will be sent to the origin user's address.
+*         example: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"

110-119: Add descriptions and examples for callData response field.

The new callData object in the response schema needs more context:

  • Add descriptions for each field
  • Include example values
  • Explain when this object will be null
 *                   callData:
 *                     type: object
 *                     nullable: true
 *                     properties:
 *                       to:
 *                         type: string
+*                         description: The target contract address for the bridge transaction
+*                         example: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
 *                       data:
 *                         type: string
+*                         description: The encoded function call data for the bridge transaction
+*                         example: "0x095ea7b3000000000000000000000000..."
 *                       value:
 *                         type: string
+*                         description: The amount of native tokens to send with the transaction (in wei)
+*                         example: "0x0"
+*                     description: Transaction details returned when destAddress is provided, null otherwise

258-261: Consider additional validation rules for destAddress.

While the basic address validation is good, consider adding these safety checks:

  • Prevent setting destAddress same as originUserAddress to avoid confusion
  • Add chain-specific address validation if different chains use different address formats
     check('destAddress')
       .optional()
       .custom((value) => isAddress(value))
-      .withMessage('Invalid destAddress'),
+      .withMessage('Invalid destAddress')
+      .custom((value, { req }) => {
+        if (value && req.query.originUserAddress && 
+            value.toLowerCase() === req.query.originUserAddress.toLowerCase()) {
+          throw new Error('destAddress cannot be the same as originUserAddress');
+        }
+        return true;
+      }),
packages/rest-api/swagger.json (1)

200-208: Consider enhancing parameter documentation.

While the parameter descriptions are clear, consider adding:

  1. Example values in the parameter definitions
  2. More detailed descriptions explaining the expected format (e.g., if it should be a checksummed Ethereum address)
  3. Common use cases or scenarios
 {
   "in": "query",
   "name": "destAddress",
   "required": true,
   "schema": {
     "type": "string"
   },
-  "description": "The destination address of the user on the destination chain"
+  "description": "The destination address of the user on the destination chain. Must be a valid, checksummed Ethereum address (e.g., 0x1234...abcd) where the bridged tokens will be received.",
+  "example": "0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
 }

Also applies to: 1218-1226

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between f2f1139 and 2782388.

📒 Files selected for processing (7)
  • packages/rest-api/src/controllers/bridgeController.ts (2 hunks)
  • packages/rest-api/src/controllers/swapController.ts (2 hunks)
  • packages/rest-api/src/routes/bridgeRoute.ts (3 hunks)
  • packages/rest-api/src/routes/swapRoute.ts (4 hunks)
  • packages/rest-api/src/tests/bridgeRoute.test.ts (1 hunks)
  • packages/rest-api/src/tests/swapRoute.test.ts (1 hunks)
  • packages/rest-api/swagger.json (2 hunks)
🧰 Additional context used
📓 Learnings (2)
packages/rest-api/src/controllers/swapController.ts (2)
Learnt from: Defi-Moses
PR: synapsecns/sanguine#3133
File: packages/rest-api/src/routes/swapRoute.ts:21-0
Timestamp: 2024-09-17T23:09:10.071Z
Learning: The `/swap` route does not accept an `address` parameter.
Learnt from: Defi-Moses
PR: synapsecns/sanguine#3133
File: packages/rest-api/src/routes/swapRoute.ts:21-0
Timestamp: 2024-10-08T15:41:48.274Z
Learning: The `/swap` route does not accept an `address` parameter.
packages/rest-api/src/routes/swapRoute.ts (4)
Learnt from: Defi-Moses
PR: synapsecns/sanguine#3133
File: packages/rest-api/src/routes/swapRoute.ts:21-0
Timestamp: 2024-09-17T23:09:10.071Z
Learning: The `/swap` route does not accept an `address` parameter.
Learnt from: Defi-Moses
PR: synapsecns/sanguine#3133
File: packages/rest-api/src/routes/swapRoute.ts:21-0
Timestamp: 2024-10-08T15:41:48.274Z
Learning: The `/swap` route does not accept an `address` parameter.
Learnt from: Defi-Moses
PR: synapsecns/sanguine#3133
File: packages/rest-api/src/routes/swapRoute.ts:21-0
Timestamp: 2024-10-08T15:41:49.333Z
Learning: The `/swap` route does not accept an `address` parameter.
Learnt from: Defi-Moses
PR: synapsecns/sanguine#3133
File: packages/rest-api/src/routes/swapRoute.ts:21-0
Timestamp: 2024-10-08T15:41:49.333Z
Learning: The `/swap` route does not accept an `address` parameter.
🔇 Additional comments (8)
packages/rest-api/src/controllers/swapController.ts (1)

Line range hint 15-46: Verify PR scope and implementation

The PR title mentions "Bridge endpoint consolidation" but the changes are in the swap controller. This seems inconsistent with the stated objectives.

Let's check for related bridge endpoint changes:

packages/rest-api/src/controllers/bridgeController.ts (2)

22-31: ⚠️ Potential issue

Add validation for destAddress parameter

While the type definition is correct, there's no visible validation for the destAddress parameter to ensure it's a valid Ethereum address format. This could lead to runtime errors if an invalid address is provided.

Let's verify if validation exists in the route file:

#!/bin/bash
# Search for destAddress validation in route files
rg -l "destAddress.*validate" --type ts

If validation is missing, consider adding validation using express-validator:

check('destAddress')
  .optional()
  .isEthereumAddress()
  .withMessage('Invalid destination address format')

59-59: ⚠️ Potential issue

Add type safety for routerAddress

The quote.routerAddress is used without type validation, which could cause runtime errors if the quote structure changes.

Let's verify the quote type definition:

packages/rest-api/src/routes/swapRoute.ts (1)

3-3: LGTM!

The isAddress import is correctly added and necessary for validating the new optional address parameter.

packages/rest-api/src/tests/bridgeRoute.test.ts (1)

177-223: Verify API documentation and error handling consistency.

Let's ensure the API documentation and error handling are consistent with these test changes.

✅ Verification successful

API documentation and error handling are consistent with test changes

The verification confirms that:

  1. The OpenAPI documentation correctly specifies destAddress as an optional parameter in the /bridge endpoint
  2. The response schema includes the callData object that matches the test expectations
  3. Error handling for invalid destAddress is properly implemented in the route validation
  4. The controller correctly handles the optional destAddress parameter and generates callData accordingly
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify API documentation and error handling consistency

# Test 1: Check if destAddress is documented in swagger
echo "Checking swagger documentation for destAddress..."
rg -A 5 "destAddress" "**/swagger.json"

# Test 2: Check error handling consistency across routes
echo "Checking error handling consistency..."
rg -A 2 "response.status).toBe\(400\)" "**/*.test.ts"

Length of output: 442


Script:

#!/bin/bash
# Let's try a different approach to verify API documentation and error handling

# Check for OpenAPI/Swagger documentation files with different extensions
echo "Checking for API documentation files..."
fd -e yaml -e yml -e json . | grep -i 'swagger\|openapi'

# Check the route handler implementation
echo "Checking bridge route implementation..."
rg -l "destAddress" "packages/rest-api/src"

# Check error handling patterns
echo "Checking error handling patterns..."
rg "status\(400\)" "packages/rest-api/src"

# Look for validation logic
echo "Checking validation logic..."
rg "destAddress.*valid" "packages/rest-api/src"

Length of output: 2725


Script:

#!/bin/bash
# Let's check the API documentation and validation implementation

# Check the bridge route API documentation
echo "Checking bridge route API documentation..."
cat "packages/rest-api/swagger.json"

# Check the validation implementation in bridge route
echo "Checking bridge route validation..."
cat "packages/rest-api/src/routes/bridgeRoute.ts"

# Check the controller implementation
echo "Checking bridge controller implementation..."
cat "packages/rest-api/src/controllers/bridgeController.ts"

Length of output: 109099

packages/rest-api/src/routes/bridgeRoute.ts (1)

Line range hint 1-261: Verify PR readiness given [DNM] tag.

This PR is marked as "Do Not Merge". Please clarify:

  • Is this ready for review or still work in progress?
  • Are there additional changes planned for the bridge endpoint consolidation?
  • What are the remaining tasks for SLT-453?
✅ Verification successful

PR is ready for review - [DNM] tag can be removed

The code appears to be production-ready based on the following evidence:

  • Comprehensive test coverage for the bridge endpoints including positive and negative test cases
  • No TODOs, FIXMEs or pending work found in the codebase
  • All core functionality is implemented and tested:
    • Input validation
    • Error handling
    • Bridge quotes retrieval
    • Transaction status checks
    • Support for optional parameters
  • Tests are passing with realistic test data and proper assertions

The [DNM] tag appears to be a precautionary measure that can now be removed as the implementation is complete and well-tested.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for related changes in other files
echo "Checking for related bridge endpoint changes..."
rg -l "bridge.*endpoint" --type ts

echo "Checking for other files importing bridgeRoute..."
rg -l "from ['\"].*bridgeRoute" --type ts

Length of output: 555


Script:

#!/bin/bash
# Check PR title and description for DNM context
gh pr view --json title,body

# Check commit messages for additional context
git log --pretty=format:"%s" -n 5

# Check for recent changes in bridge-related files
git diff HEAD~1 packages/rest-api/src/routes/bridgeRoute.ts || true

Length of output: 109099


Script:

#!/bin/bash
# Check PR title and description for DNM context
gh pr view --json title,body

# Check for any pending changes or TODOs in the codebase
rg -i "todo|fixme|xxx|hack" --type ts packages/rest-api/

# Check for any related test files and their status
find packages/rest-api/src/tests -name "*bridge*.test.ts" -type f -exec cat {} \;

Length of output: 19953

packages/rest-api/swagger.json (2)

200-208: LGTM! Well-documented parameter additions.

The new required parameters destAddress and address are properly defined with clear descriptions and appropriate schema types.

Also applies to: 1218-1226


200-208: Excellent parameter consistency across endpoints!

The new parameters maintain consistency with their corresponding transaction info endpoints (/bridgeTxInfo and /swapTxInfo), ensuring a coherent API design.

Also applies to: 1218-1226

@Defi-Moses Defi-Moses merged commit 0eae097 into master Nov 18, 2024
43 checks passed
@Defi-Moses Defi-Moses deleted the api/bridge-change branch November 18, 2024 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant