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

SDK: return estimated bridge time along with the quotes #1520

Merged
merged 9 commits into from
Nov 1, 2023

Conversation

ChiTimesChi
Copy link
Collaborator

@ChiTimesChi ChiTimesChi commented Oct 30, 2023

Description

  • Added the median time from the explorer statistics as estimated bridging time for both SynapseBridge and SynapseCCTP.
  • This estimated time is now returned in bridgeQuote() alongside other quote data

Summary by CodeRabbit

New Features:

  • Introduced getEstimatedTime function to RouterSet, SynapseCCTPRouterSet, and SynapseRouterSet classes, providing estimated transaction completion times for various blockchain chains.
  • Added estimatedTime property to the BridgeQuote interface, enhancing transaction information with estimated completion times.

Tests:

  • Added comprehensive tests for the new getEstimatedTime function across supported and unsupported chains.
  • Expanded bridge quote test cases to include the new estimatedTime property.

Chores:

  • Updated exports and global data structures to support the new getEstimatedTime function and estimatedTime property.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 30, 2023

Here is the updated walkthrough:

Walkthrough

The changes introduce a new feature to estimate the time for bridge transactions across different blockchain networks. This is achieved by adding new data structures for median times, updating router classes with a new method getEstimatedTime, and modifying the BridgeQuote interface. The changes also include comprehensive tests for the new functionality.

Changes

File(s) Summary
packages/sdk-router/src/constants/index.ts, packages/sdk-router/src/constants/medianTime.ts Added new export medianTime and introduced two new global data structures MEDIAN_TIME_BRIDGE and MEDIAN_TIME_CCTP mapping chain IDs to specific time values.
packages/sdk-router/src/router/routerSet.ts, packages/sdk-router/src/router/types.ts Added a new method getEstimatedTime to the RouterSet class and a new property estimatedTime to the BridgeQuote interface.
packages/sdk-router/src/router/synapseCCTPRouterSet.ts, packages/sdk-router/src/router/synapseRouterSet.ts Implemented the getEstimatedTime function in SynapseCCTPRouterSet and SynapseRouterSet classes, retrieving estimated times from the new constants.
packages/sdk-router/src/router/synapseCCTPRouterSet.test.ts, packages/sdk-router/src/router/synapseRouterSet.test.ts, packages/sdk-router/src/sdk.test.ts Added comprehensive tests for the new getEstimatedTime function and the updated bridgeQuote function.

🐇🍂

As the leaves fall and the pumpkins glow,

CodeRabbit hops and the changes flow.

Time estimates for bridges, a feature so grand,

Now in the code, by a rabbit's hand.

With each hop forward, we make a gain,

In the world of code, there's no room for pain.

So here's to the season, to the cool autumn day,

And to the code that keeps evolving, in a magical way! 🎃🍁


Tips

Chat with CodeRabbit Bot (@coderabbitai)

  • If you reply to a review comment from CodeRabbit, the bot will automatically respond.
  • To engage with CodeRabbit bot directly around the specific lines of code in the PR, mention @coderabbitai in your review comment
  • Note: Review comments are made on code diffs or files, not on the PR overview.
  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai help to get help.
  • @coderabbitai resolve to resolve all the CodeRabbit review comments.

Note: For conversation with the bot, please use the review comments on code diffs or files.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.json

@codecov
Copy link

codecov bot commented Oct 30, 2023

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (4d83d5d) 51.16094% compared to head (f3b8ae6) 50.76872%.
Report is 23 commits behind head on master.

Additional details and impacted files
@@                 Coverage Diff                 @@
##              master       #1520         +/-   ##
===================================================
- Coverage   51.16094%   50.76872%   -0.39222%     
===================================================
  Files            366         358          -8     
  Lines          25195       23871       -1324     
  Branches         271         272          +1     
===================================================
- Hits           12890       12119        -771     
+ Misses         11035       10598        -437     
+ Partials        1270        1154        -116     
Flag Coverage Δ
cctp-relayer ?
packages 90.88099% <100.00000%> (+0.26095%) ⬆️
promexporter ?

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

Files Coverage Δ
packages/contracts-core/contracts/Destination.sol 88.13559% <100.00000%> (ø)
packages/contracts-core/contracts/GasOracle.sol 100.00000% <100.00000%> (ø)
packages/contracts-core/contracts/Origin.sol 95.65217% <100.00000%> (+0.19762%) ⬆️
packages/contracts-core/contracts/Summit.sol 96.66667% <100.00000%> (+0.03745%) ⬆️
...ges/contracts-core/contracts/hubs/ExecutionHub.sol 97.59036% <100.00000%> (+0.02938%) ⬆️
...ages/contracts-core/contracts/hubs/SnapshotHub.sol 83.89831% <100.00000%> (+0.70502%) ⬆️
...ackages/contracts-core/contracts/hubs/StateHub.sol 95.83333% <100.00000%> (ø)
.../contracts-core/contracts/inbox/StatementInbox.sol 89.74359% <ø> (ø)
...ntracts-core/contracts/libs/memory/Attestation.sol 100.00000% <ø> (ø)
...ontracts-core/contracts/libs/memory/ByteString.sol 96.77419% <ø> (ø)
... and 18 more

... and 23 files with indirect coverage changes

☔ 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.

Review Status

Actionable comments generated: 2

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between f75a32b and 5657077.
Files selected for processing (9)
  • packages/sdk-router/src/constants/index.ts (1 hunks)
  • packages/sdk-router/src/constants/medianTime.ts (1 hunks)
  • packages/sdk-router/src/router/routerSet.ts (2 hunks)
  • packages/sdk-router/src/router/synapseCCTPRouterSet.test.ts (2 hunks)
  • packages/sdk-router/src/router/synapseCCTPRouterSet.ts (2 hunks)
  • packages/sdk-router/src/router/synapseRouterSet.test.ts (2 hunks)
  • packages/sdk-router/src/router/synapseRouterSet.ts (2 hunks)
  • packages/sdk-router/src/router/types.ts (1 hunks)
  • packages/sdk-router/src/sdk.test.ts (6 hunks)
Files skipped from review due to trivial changes (3)
  • packages/sdk-router/src/constants/index.ts
  • packages/sdk-router/src/constants/medianTime.ts
  • packages/sdk-router/src/router/types.ts
Additional comments: 11
packages/sdk-router/src/router/synapseRouterSet.test.ts (3)
  • 5-11: The new imports MEDIAN_TIME_BRIDGE and SUPPORTED_CHAIN_IDS are correctly added. Ensure that these constants are correctly defined in the ../constants module.

  • 58-73: The new getEstimatedTime function is correctly tested. It checks for both supported and unsupported chains. The error message for unsupported chains is clear and informative.

  • 75-77: No changes are made to the getRouter function. Ensure that this function still works as expected after the changes made in this pull request.

packages/sdk-router/src/router/synapseCCTPRouterSet.test.ts (2)
  • 5-11: The new imports MEDIAN_TIME_CCTP and CCTP_SUPPORTED_CHAIN_IDS are used in the tests for the getEstimatedTime function. Ensure that these constants are correctly defined in the ../constants module.

  • 68-92: The tests for the getEstimatedTime function are comprehensive, covering both supported and unsupported chains. The error messages in the tests are clear and informative. However, it would be beneficial to add a test case for a chain that is supported but does not have a provider.

it('Throws error for supported chain without a provider', () => {
  // Use a chain ID for a supported chain that does not have a provider
  const unsupportedChainId = ...;
  expect(() => routerSet.getEstimatedTime(unsupportedChainId)).toThrow(
    `No estimated time for chain ${unsupportedChainId}`
  )
})
packages/sdk-router/src/router/routerSet.ts (2)
  • 63-71: The getEstimatedTime method is a good addition to the RouterSet class. It provides an abstract method that can be implemented by subclasses to provide estimated times for transactions. This is a good use of the abstraction principle in OOP. However, it would be helpful to clarify what happens when the chain ID is not supported. Does it return a default value or throw an error? This should be clearly documented in the method's comments.

  • 197-209: The finalizeBridgeRoute method now includes the estimatedTime in its return value. This is a good addition as it provides more information to the user about the transaction. However, it would be helpful to handle the case where getEstimatedTime throws an error (if it does so when the chain ID is not supported). This could be done with a try-catch block around the call to getEstimatedTime.

Here is a suggested change to handle potential errors from getEstimatedTime:

  originQuery.minAmountOut,
  hasComplexBridgeAction(destQuery)
)
+ try {
+   const estimatedTime = this.getEstimatedTime(bridgeRoute.originChainId)
+ } catch (error) {
+   console.error(`Error getting estimated time for chain ${bridgeRoute.originChainId}: ${error}`)
+   const estimatedTime = 0 // or some other default value
+ }
return {
  feeAmount,
  feeConfig,
  routerAddress: originRouter.address,
  maxAmountOut: destQuery.minAmountOut,
  originQuery,
  destQuery,
  estimatedTime,
}
}
}
packages/sdk-router/src/sdk.test.ts (4)
  • 25-26: The new global variables MEDIAN_TIME_BRIDGE and MEDIAN_TIME_CCTP are imported correctly. These variables are used to map supported chain IDs to specific time values.

  • 570-572: The test cases are correctly checking the estimated time for bridge quotes. They are comparing the estimated time returned by the bridgeQuote function with the expected median time for the corresponding chain ID.

  • 562-574: New test cases are added to check the functionality of the bridgeQuote function for different bridging scenarios. These tests are correctly checking the router address, the presence of the swapAdapter property in the originQuery, and the estimated time for the bridge quote.

  • 502-574: The SynapseSDK class is instantiated with different chain configurations and the bridgeQuote function is called with different parameters to fetch bridge quotes. The test cases are correctly checking the returned bridge quotes.

Comment on lines +20 to +25
public getEstimatedTime(chainId: number): number {
const medianTime =
MEDIAN_TIME_BRIDGE[chainId as keyof typeof MEDIAN_TIME_BRIDGE]
invariant(medianTime, `No estimated time for chain ${chainId}`)
return medianTime
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The getEstimatedTime function is well implemented. It retrieves the median time from the MEDIAN_TIME_BRIDGE constant using the chainId as the key. If no estimated time is found for the given chain, it throws an error. This is a good practice as it ensures that the function fails fast when it encounters an unsupported chain ID. However, it would be beneficial to include a more detailed error message that also suggests a solution, such as using a supported chain ID.

- invariant(medianTime, `No estimated time for chain ${chainId}`)
+ invariant(medianTime, `No estimated time for chain ${chainId}. Please use a supported chain ID.`)

Commitable suggestion (Beta)
Suggested change
public getEstimatedTime(chainId: number): number {
const medianTime =
MEDIAN_TIME_BRIDGE[chainId as keyof typeof MEDIAN_TIME_BRIDGE]
invariant(medianTime, `No estimated time for chain ${chainId}`)
return medianTime
}
public getEstimatedTime(chainId: number): number {
const medianTime =
MEDIAN_TIME_BRIDGE[chainId as keyof typeof MEDIAN_TIME_BRIDGE]
invariant(medianTime, `No estimated time for chain ${chainId}. Please use a supported chain ID.`)
return medianTime
}

Comment on lines +20 to +25
public getEstimatedTime(chainId: number): number {
const medianTime =
MEDIAN_TIME_CCTP[chainId as keyof typeof MEDIAN_TIME_CCTP]
invariant(medianTime, `No estimated time for chain ${chainId}`)
return medianTime
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The getEstimatedTime function is well implemented. It correctly retrieves the estimated time from the MEDIAN_TIME_CCTP constant and throws an error if the time is not available for the specified chain. However, it would be better to handle the case when the chainId is not in MEDIAN_TIME_CCTP more gracefully. Instead of throwing an error, you could return a default value or a message indicating that the time is not available. This would prevent the application from crashing if an unsupported chainId is passed to the function.

  public getEstimatedTime(chainId: number): number | string {
    const medianTime =
      MEDIAN_TIME_CCTP[chainId as keyof typeof MEDIAN_TIME_CCTP]
-   invariant(medianTime, `No estimated time for chain ${chainId}`)
+   if (!medianTime) {
+     return `No estimated time for chain ${chainId}`
+   }
    return medianTime
  }

Commitable suggestion (Beta)
Suggested change
public getEstimatedTime(chainId: number): number {
const medianTime =
MEDIAN_TIME_CCTP[chainId as keyof typeof MEDIAN_TIME_CCTP]
invariant(medianTime, `No estimated time for chain ${chainId}`)
return medianTime
}
public getEstimatedTime(chainId: number): number | string {
const medianTime =
MEDIAN_TIME_CCTP[chainId as keyof typeof MEDIAN_TIME_CCTP]
if (!medianTime) {
return `No estimated time for chain ${chainId}`
}
return medianTime
}

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.

Review Status

Actionable comments generated: 1

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 5657077 and 5de23d1.
Files selected for processing (3)
  • packages/sdk-router/src/operations/bridge.ts (1 hunks)
  • packages/sdk-router/src/sdk.test.ts (7 hunks)
  • packages/sdk-router/src/sdk.ts (1 hunks)
Files skipped from review due to trivial changes (1)
  • packages/sdk-router/src/sdk.ts
Additional comments: 3
packages/sdk-router/src/sdk.test.ts (3)
  • 25-26: The new constants MEDIAN_TIME_BRIDGE and MEDIAN_TIME_CCTP are imported correctly.

  • 570-572: The test cases correctly check if the estimated time matches the expected median time for the respective chains and routers.

  • 687-752: The new test cases for the getEstimatedTime function are well-structured and cover all the necessary scenarios, including both supported and unsupported chains and routers.

Comment on lines 117 to 142
return bestSet.finalizeBridgeRoute(bestRoute, deadline)
}

/**
* Returns the estimated time for a bridge operation from a given origin chain using a given router.
* This will be the estimated time for the bridge operation to be completed regardless of the destination chain,
* or the bridge token.
*
* @param originChainId - The ID of the origin chain.
* @param routerAddress - The address of the router deployed on the origin chain.
* @returns - The estimated time for a bridge operation.
* @throws - Will throw an error if the router address is unknown for the given chain.
*/
export function getEstimatedTime(
this: SynapseSDK,
originChainId: number,
routerAddress: string
): number {
if (this.synapseRouterSet.getRouter(originChainId, routerAddress)) {
return this.synapseRouterSet.getEstimatedTime(originChainId)
}
if (this.synapseCCTPRouterSet.getRouter(originChainId, routerAddress)) {
return this.synapseCCTPRouterSet.getEstimatedTime(originChainId)
}
throw new Error('Unknown router address')
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The getEstimatedTime function is well implemented. It checks both synapseRouterSet and synapseCCTPRouterSet for the router and returns the estimated time accordingly. If the router is not found in either set, it throws an error, which is a good practice for error handling. However, it would be more informative if the error message included the originChainId and routerAddress for better debugging.

-  throw new Error('Unknown router address')
+  throw new Error(`Unknown router address for originChainId: ${originChainId}, routerAddress: ${routerAddress}`)

Commitable suggestion (Beta)
Suggested change
return bestSet.finalizeBridgeRoute(bestRoute, deadline)
}
/**
* Returns the estimated time for a bridge operation from a given origin chain using a given router.
* This will be the estimated time for the bridge operation to be completed regardless of the destination chain,
* or the bridge token.
*
* @param originChainId - The ID of the origin chain.
* @param routerAddress - The address of the router deployed on the origin chain.
* @returns - The estimated time for a bridge operation.
* @throws - Will throw an error if the router address is unknown for the given chain.
*/
export function getEstimatedTime(
this: SynapseSDK,
originChainId: number,
routerAddress: string
): number {
if (this.synapseRouterSet.getRouter(originChainId, routerAddress)) {
return this.synapseRouterSet.getEstimatedTime(originChainId)
}
if (this.synapseCCTPRouterSet.getRouter(originChainId, routerAddress)) {
return this.synapseCCTPRouterSet.getEstimatedTime(originChainId)
}
throw new Error('Unknown router address')
}
throw new Error(`Unknown router address for originChainId: ${originChainId}, routerAddress: ${routerAddress}`)

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.

Review Status

Actionable comments generated: 1

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 5de23d1 and f3b8ae6.
Files selected for processing (2)
  • packages/sdk-router/src/constants/medianTime.ts (1 hunks)
  • packages/sdk-router/src/operations/bridge.ts (1 hunks)
Additional comments: 1
packages/sdk-router/src/constants/medianTime.ts (1)
  • 1-39: The new data structures MEDIAN_TIME_BRIDGE and MEDIAN_TIME_CCTP are well defined and follow the correct syntax. The use of the SupportedChainId enum as keys is a good practice as it ensures consistency and avoids potential errors due to typos. However, ensure that the median times are accurate and up-to-date. If these values change frequently, consider fetching them from a reliable source at runtime instead of hardcoding them.

Comment on lines 117 to +142
return bestSet.finalizeBridgeRoute(bestRoute, deadline)
}

/**
* Returns the estimated time for a bridge operation from a given origin chain using a given router.
* This will be the estimated time for the bridge operation to be completed regardless of the destination chain,
* or the bridge token.
*
* @param originChainId - The ID of the origin chain.
* @param routerAddress - The address of the router deployed on the origin chain.
* @returns - The estimated time for a bridge operation, in seconds.
* @throws - Will throw an error if the router address is unknown for the given chain.
*/
export function getEstimatedTime(
this: SynapseSDK,
originChainId: number,
routerAddress: string
): number {
if (this.synapseRouterSet.getRouter(originChainId, routerAddress)) {
return this.synapseRouterSet.getEstimatedTime(originChainId)
}
if (this.synapseCCTPRouterSet.getRouter(originChainId, routerAddress)) {
return this.synapseCCTPRouterSet.getEstimatedTime(originChainId)
}
throw new Error('Unknown router address')
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The getEstimatedTime function is well implemented. It checks both synapseRouterSet and synapseCCTPRouterSet for the router and returns the estimated time accordingly. If the router is not found in either set, it throws an error, which is a good practice for error handling. However, it would be more informative if the error message included the originChainId and routerAddress for easier debugging.

-  throw new Error('Unknown router address')
+  throw new Error(`Unknown router address for originChainId: ${originChainId}, routerAddress: ${routerAddress}`)

Commitable suggestion (Beta)
Suggested change
return bestSet.finalizeBridgeRoute(bestRoute, deadline)
}
/**
* Returns the estimated time for a bridge operation from a given origin chain using a given router.
* This will be the estimated time for the bridge operation to be completed regardless of the destination chain,
* or the bridge token.
*
* @param originChainId - The ID of the origin chain.
* @param routerAddress - The address of the router deployed on the origin chain.
* @returns - The estimated time for a bridge operation, in seconds.
* @throws - Will throw an error if the router address is unknown for the given chain.
*/
export function getEstimatedTime(
this: SynapseSDK,
originChainId: number,
routerAddress: string
): number {
if (this.synapseRouterSet.getRouter(originChainId, routerAddress)) {
return this.synapseRouterSet.getEstimatedTime(originChainId)
}
if (this.synapseCCTPRouterSet.getRouter(originChainId, routerAddress)) {
return this.synapseCCTPRouterSet.getEstimatedTime(originChainId)
}
throw new Error('Unknown router address')
}
throw new Error(`Unknown router address for originChainId: ${originChainId}, routerAddress: ${routerAddress}`)

@ChiTimesChi ChiTimesChi merged commit bf9ba9c into master Nov 1, 2023
36 checks passed
@ChiTimesChi ChiTimesChi deleted the sdk/estimated-bridge-time branch November 1, 2023 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants