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

Add relayer API #1785

Merged
merged 45 commits into from
Jan 12, 2024
Merged

Add relayer API #1785

merged 45 commits into from
Jan 12, 2024

Conversation

dwasse
Copy link
Collaborator

@dwasse dwasse commented Jan 8, 2024

Description
Adds a separate RelayerAPIServer for exposing endpoints with information about bridge event statuses as well as an interface for retrying transaction submission.

Notes:

  • rest.APIServer has been renamed to QuoterAPIServer (as opposed to the new RelayerAPIServer) for clarity
  • Chain helper struct now lives in its own package to avoid circular deps

Metadata

Summary by CodeRabbit

  • New Features

    • Introduced a RESTful API service for the RFQ relayer to enhance user interaction with the Request for Quotation system.
    • Added comprehensive end-to-end testing for the relayer API server functionality.
  • Enhancements

    • Improved the relayer service by refining the logic for updating quote request statuses and submitting relay transactions.
    • Streamlined blockchain interaction with the introduction of a new chain package for submitting and handling transactions.
  • Refactor

    • Renamed various internal components to better reflect their purpose, improving clarity and consistency in the codebase.
    • Updated configuration structures to support new relayer API server settings.
  • Bug Fixes

    • Addressed issues in test suites to ensure robustness and reliability.
  • Documentation

    • Updated test documentation to align with code changes and new testing strategies.
  • Chores

    • Incorporated the depguard linter into the project configuration to enforce dependency best practices.

@dwasse dwasse requested a review from trajan0x as a code owner January 8, 2024 21:14
@dwasse dwasse marked this pull request as draft January 8, 2024 21:14
Copy link
Contributor

coderabbitai bot commented Jan 8, 2024

Walkthrough

The changes encompass modifications to the RFQ system to introduce new API endpoints for checking the status of an RFQ relay and retrying transactions via the API. These updates involve adjustments to backend logic, addition of new configuration parameters, enhancements to testing suites, and structural changes to support the new functionality.

Changes

File Pattern Change Summary
services/rfq/e2e/rfq_test.go,
services/rfq/e2e/setup_test.go
Renamed and adjusted exported entities, including variable and function renaming related to the OmniServer, API server, and the Relayer. Added logic to generate a free port and configure the relayer API port. Adjusted SetupTest and TestUSDCtoUSDC functions for setting up the Quoter API and removing redundant code.
services/rfq/relayer/relapi/server.go,
services/rfq/relayer/relapi/suite_test.go,
services/rfq/relayer/relconfig/config.go,
services/rfq/relayer/pricer/fee_pricer.go
No changes.

Assessment against linked issues

Objective Addressed Explanation
#1755: [RFQ] Status Endpoint -
#1756: [RFQ] Retry Endpoint -

Poem

The code evolves with each new task,
🐇 CodeRabbit's work, a meticulous craft.
RFQs now dance with grace and might,
As the codebase shines, a wondrous sight. ✨

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>.
    • Generate unit-tests for this file.
  • 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 tests 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 generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

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 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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

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.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

@github-actions github-actions bot added go Pull requests that update Go code size/m labels Jan 8, 2024
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: 3

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 92a42e5 and 20123b6.
Files selected for processing (8)
  • services/rfq/relayer/relapi/handler.go (1 hunks)
  • services/rfq/relayer/relapi/model.go (1 hunks)
  • services/rfq/relayer/relapi/server.go (1 hunks)
  • services/rfq/relayer/reldb/base/model.go (6 hunks)
  • services/rfq/relayer/reldb/base/quote.go (1 hunks)
  • services/rfq/relayer/reldb/db.go (3 hunks)
  • services/rfq/relayer/service/handlers.go (2 hunks)
  • services/rfq/relayer/service/statushandler.go (1 hunks)
Additional comments: 16
services/rfq/relayer/relapi/model.go (2)
  • 3-9: The GetQuoteRequestStatusResponse struct is well-defined and includes all necessary fields to represent the status of a quote request. The JSON tags are correctly assigned, ensuring proper serialization.

  • 11-17: The PutTxRetryResponse struct is also well-defined. It includes fields that are relevant for a response after a transaction retry attempt. The JSON tags are present and correctly formatted.

services/rfq/relayer/reldb/base/quote.go (2)
  • 37-44: The error message in GetQuoteRequestByID has been updated to a more generic "could not get quote" which is appropriate as it does not assume the nature of the error (previously "could not get quote id"). This change improves the clarity of the error message.

  • 47-56: The new method GetQuoteRequestByOriginTxHash is added to retrieve a quote request by its origin transaction hash. The method correctly handles the case where the quote request is not found by returning ErrNoQuoteForTxHash. The error message for other errors is consistent with the rest of the file.

services/rfq/relayer/relapi/handler.go (2)
  • 32-60: The GetQuoteRequestStatusByTxID handler is correctly implemented. It validates the input, decodes the transaction ID, retrieves the quote request, and sends a well-structured response. Error handling is present for each step where an error might occur.

  • 65-86: The GetQuoteRequestStatusByTxHash handler is similar to the GetQuoteRequestStatusByTxID handler and is correctly implemented. It validates the input, converts the hash to the common.Hash type, retrieves the quote request, and sends a response. Error handling is also correctly implemented.

services/rfq/relayer/relapi/server.go (2)
  • 38-82: The NewAPI function is well-structured and includes error handling for nil arguments. It initializes the chains map and sets up each chain with the necessary components. The error messages are descriptive and will aid in debugging if initialization fails.

  • 92-115: The Run method sets up the Gin engine and routes, and starts the server. The use of ginhelper.New suggests that there is a wrapper around the Gin setup which is not shown here. Ensure that this wrapper is correctly implemented and tested. The logging of the API start is a good practice for observability.

services/rfq/relayer/reldb/db.go (3)
  • 35-36: The addition of the GetQuoteRequestByOriginTxHash method to the Reader interface is consistent with the new functionality introduced in the quote.go file. This ensures that the interface remains accurate with the capabilities of the implementing struct.

  • 53-55: The updated error declarations ErrNoQuoteForID and ErrNoQuoteForTxHash provide clear differentiation between the types of retrieval errors, which is a good practice for error handling and debugging.

  • 68-70: The QuoteRequest struct has been updated to include the OriginTxHash and DestTxHash fields of type common.Hash. This change aligns with the new functionality of retrieving and retrying quote requests by transaction hash.

services/rfq/relayer/reldb/base/model.go (4)
  • 25-25: The addition of originTxHashFieldName is consistent with the other field name declarations and follows the same naming convention.

  • 67-67: The UpdatedAt field has been modified. Ensure that this change is reflected in all places where RequestForQuote is used to avoid any potential issues with database operations.

Verification successful

The ast-grep search for usages of the RequestForQuote struct with the UpdatedAt field did not yield any results. This could mean that there are no explicit initializations of the RequestForQuote struct with the UpdatedAt field in the codebase, or that the field is not being directly manipulated in the code.

To ensure thorough verification, I will perform a broader search to find any references to the RequestForQuote struct, which will help us understand how the UpdatedAt field is being used throughout the codebase.


The search results indicate several references to the RequestForQuote struct within the codebase, particularly in quote.go and model.go. The references in quote.go seem to be related to database operations, such as querying and modeling data. The explicit construction of a RequestForQuote struct is found in model.go, where various fields are being set, but there is no mention of the UpdatedAt field in this construction.

Given that the UpdatedAt field is typically managed by the database layer (often automatically updated to the current timestamp when a record is modified), the absence of explicit references in the construction or queries may not be an issue. However, it's important to ensure that the database schema and any ORM (Object-Relational Mapping) configurations are in sync with this field change.

To further verify the correct handling of the UpdatedAt field, I will search for any database migration files or ORM configuration that might reference this field, to ensure that it is being automatically managed as expected.


The rg search results show several references to the UpdatedAt field across different files in the codebase. Notably, the field is mentioned in model.go as part of the RequestForQuote struct, and it is also referenced in various files within the services/rfq/api directory, indicating its use in API response models and database operations.

The presence of the UpdatedAt field in api_db_test.go suggests that there are tests that check the non-nil nature of this field, which implies that it is expected to be set during database operations. Additionally, the UpdatedAt field is formatted for API responses in util.go, and it is used in client_test.go for constructing test cases.

The UpdatedAt field is also referenced in ethergo/debug/source.go, where it is explicitly set to the current time. This indicates that there might be instances where the field is manually set, although this particular reference seems to be in a debug file and may not reflect the typical usage pattern in production code.

Given the information from the search results, it appears that the UpdatedAt field is indeed used throughout the codebase and is likely managed correctly by the database layer and the application code. There is no indication of a mismatch or mismanagement of this field that would cause issues due to the changes in the RequestForQuote struct.

Based on the evidence gathered, the modification to the UpdatedAt field in the RequestForQuote struct does not seem to introduce any issues, and the field is being handled as expected in various parts of the codebase.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Search for usages of the RequestForQuote struct to verify the UpdatedAt field change.
ast-grep --lang go --pattern $'RequestForQuote { $$$ UpdatedAt: $_ $$$ }'

Length of output: 74



Script:

#!/bin/bash
# Search for references to the RequestForQuote struct to understand how it's used.
ast-grep --lang go --pattern $'RequestForQuote { $$$ }'

Length of output: 3048



Script:

#!/bin/bash
# Search for database migration files or ORM configurations that reference the UpdatedAt field.
rg "UpdatedAt"

Length of output: 1257

* 92-92: The changes to the `Deadline`, `OriginTxHash`, and `DestTxHash` fields in the `RequestForQuote` struct are consistent with the PR objectives to track and retrieve quote requests by transaction hash. Ensure that these fields are properly indexed and used throughout the codebase.

Also applies to: 97-97, 100-100

Verification successful

The output from the rg command shows numerous instances of the OriginTxHash, DestTxHash, and Deadline fields being used across various files in the codebase. This indicates that the new fields are indeed being utilized throughout the codebase, which aligns with the PR objectives and the review comment.

Based on the output, it is evident that the fields are not only present in the RequestForQuote struct but are also integrated into the logic of the application, including database operations, API responses, and internal processing logic.

Given the extensive use of these fields across the codebase, it can be concluded that the changes to the Deadline, OriginTxHash, and DestTxHash fields in the RequestForQuote struct are properly indexed and used, which supports the approval of the changes.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify that the new fields are properly indexed and used.
rg --type go 'OriginTxHash|DestTxHash|Deadline'

Length of output: 239236

* 126-126: The `FromQuoteRequest` and `ToQuoteRequest` functions have been updated to include the `OriginTxHash` field. Verify that the conversion between the struct and the `QuoteRequest` object is correct and that error handling is appropriate.

Also applies to: 182-183

Verification successful

The review comment is correct in stating that the FromQuoteRequest and ToQuoteRequest functions have been updated to include the OriginTxHash field. The conversion between the struct and the QuoteRequest object is handled correctly, with the OriginTxHash being converted to a string in FromQuoteRequest and to a common.Hash in ToQuoteRequest. There is no specific error handling for the OriginTxHash field shown in the output, which is expected as the field is a simple data type conversion.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify that the conversion functions handle the new field correctly.
ast-grep --lang go --pattern $'func FromQuoteRequest($_) $_ { $$$ OriginTxHash: $_ $$$ }'
ast-grep --lang go --pattern $'func ($_ RequestForQuote) ToQuoteRequest() $_ { $$$ OriginTxHash: $_ $$$ }'

Length of output: 198



Script:

#!/bin/bash
# Search for the existence of FromQuoteRequest and ToQuoteRequest functions.
ast-grep --lang go --pattern $'func FromQuoteRequest($_) $_ { $$$ }'
ast-grep --lang go --pattern $'func ($_ RequestForQuote) ToQuoteRequest() $_ { $$$ }'

Length of output: 6467

services/rfq/relayer/service/handlers.go (1)
  • 84-84: The assignment of OriginTxHash in the handleBridgeRequestedLog function aligns with the PR objectives to track the origin transaction hash. Ensure that this new assignment is used correctly in subsequent processing steps.

Comment on lines 89 to 137
// PutTxRetry retries a transaction based on tx hash.
func (h *Handler) PutTxRetry(c *gin.Context) {
txHashStr := c.Query("hash")
if txHashStr == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": unspecifiedTxHash})
return
}

txHash := common.HexToHash(txHashStr)
quoteRequest, err := h.db.GetQuoteRequestByOriginTxHash(c, txHash)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

chainID := quoteRequest.Transaction.DestChainId
chain, ok := h.chains[uint32(chainID)]
if !ok {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("No contract found for chain: %d", chainID)})
return
}

// TODO: this can be deduped with handlers.go code
gasAmount := big.NewInt(0)
if quoteRequest.Transaction.SendChainGas {
gasAmount, err = chain.Bridge.ChainGasAmount(&bind.CallOpts{Context: c})
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("could not get chain gas amount: %s", err.Error())})
return
}
}
nonce, err := chain.SubmitTransaction(c, func(transactor *bind.TransactOpts) (tx *types.Transaction, err error) {
transactor.Value = core.CopyBigInt(gasAmount)

tx, err = chain.Bridge.Relay(transactor, quoteRequest.RawRequest)
if err != nil {
return nil, fmt.Errorf("could not relay: %w", err)
}

return tx, nil
})

resp := PutTxRetryResponse{
TxID: hexutil.Encode(quoteRequest.TransactionID[:]),
ChainID: chainID,
Nonce: nonce,
GasAmount: gasAmount.String(),
}
c.JSON(http.StatusOK, resp)
Copy link
Contributor

Choose a reason for hiding this comment

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

The PutTxRetry handler is responsible for retrying a transaction. It validates the input, retrieves the quote request, and attempts to submit the transaction. The error handling is comprehensive, and the response structure is appropriate. However, there is a TODO comment indicating that some code duplication might exist with handlers.go. This should be addressed to ensure DRY principles are followed.

Comment on lines 118 to 163
// AuthMiddleware is the Gin authentication middleware that authenticates requests using EIP191.
func (r *APIServer) AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
var req model.PutQuoteRequest
if err := c.BindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
c.Abort()
return
}

chain, ok := r.chains[uint32(req.DestChainID)]
if !ok {
c.JSON(http.StatusBadRequest, gin.H{"msg": "dest chain id not supported"})
c.Abort()
return
}

ops := &bind.CallOpts{Context: c}
relayerRole := crypto.Keccak256Hash([]byte("RELAYER_ROLE"))

// authenticate relayer signature with EIP191
deadline := time.Now().Unix() - 1000 // TODO: Replace with some type of r.cfg.AuthExpiryDelta
addressRecovered, err := rest.EIP191Auth(c, deadline)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"msg": fmt.Sprintf("unable to authenticate relayer: %v", err)})
c.Abort()
return
}

has, err := chain.Bridge.HasRole(ops, relayerRole, addressRecovered)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"msg": "unable to check relayer role on-chain"})
c.Abort()
return
} else if !has {
c.JSON(http.StatusBadRequest, gin.H{"msg": "q.Relayer not an on-chain relayer"})
c.Abort()
return
}

// Log and pass to the next middleware if authentication succeeds
// Store the request in context after binding and validation
c.Set("putRequest", &req)
c.Set("relayerAddr", addressRecovered.Hex())
c.Next()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The AuthMiddleware function is responsible for authenticating requests using EIP191. It correctly binds the JSON request, validates the destination chain ID, and recovers the address from the signature. The error handling is comprehensive, and the middleware correctly aborts the request if authentication fails. The TODO comment about replacing the hardcoded deadline with a configurable value should be addressed to make the middleware more flexible.

Comment on lines 156 to 175
// NewChain creates a new chain helper.
func NewChain(ctx context.Context, chainClient client.EVM, addr common.Address, chainListener listener.ContractListener, ts submitter.TransactionSubmitter) (*Chain, error) {
bridge, err := fastbridge.NewFastBridgeRef(addr, chainClient)
if err != nil {
return nil, fmt.Errorf("could not create bridge contract: %w", err)
}
chainID, err := chainClient.ChainID(ctx)
if err != nil {
return nil, fmt.Errorf("could not get chain id: %w", err)
}
return &Chain{
ChainID: uint32(chainID.Int64()),
Bridge: bridge,
Client: chainClient,
// TODO: configure
Confirmations: 1,
listener: chainListener,
submitter: ts,
}, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The NewChain function is a new addition that creates a chain helper. It correctly initializes the fastbridge.FastBridgeRef and retrieves the chain ID. The function includes error handling for each step that could fail. The TODO comment about configuring the number of confirmations indicates that this value should not be hardcoded and should be addressed before finalizing the implementation.

@dwasse dwasse marked this pull request as ready for review January 8, 2024 23:59
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: 7

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 20123b6 and a5b254f.
Files selected for processing (6)
  • services/rfq/relayer/relapi/handler.go (1 hunks)
  • services/rfq/relayer/relapi/model.go (1 hunks)
  • services/rfq/relayer/relapi/server.go (1 hunks)
  • services/rfq/relayer/relapi/server_test.go (1 hunks)
  • services/rfq/relayer/relapi/suite_test.go (1 hunks)
  • services/rfq/relayer/service/handlers.go (3 hunks)
Files skipped from review as they are similar to previous changes (4)
  • services/rfq/relayer/relapi/handler.go
  • services/rfq/relayer/relapi/model.go
  • services/rfq/relayer/relapi/server.go
  • services/rfq/relayer/service/handlers.go
Additional comments: 3
services/rfq/relayer/relapi/server_test.go (1)
  • 145-160: The startAPIServer helper function is used to start the API server. It uses a retry mechanism to wait for the server to start. This is a good practice to ensure the server is ready before proceeding with tests. No issues found here.
services/rfq/relayer/relapi/suite_test.go (2)
  • 34-50: The RelayerServerSuite struct is well-defined with clear fields for the test suite. It includes necessary components such as the API server, database, and wallet, which are essential for the tests. No issues found here.

  • 185-188: The TestRelayerServerSuite function is the entry point for running the test suite. It uses the suite package to run the tests, which is a standard practice in Go for structuring test suites. No issues found here.

Comment on lines 37 to 68
func (c *RelayerServerSuite) TestGetQuoteRequestByTxHash() {
c.startAPIServer()

// Insert quote request to db
quoteRequest := c.getTestQuoteRequest(reldb.Seen)
err := c.database.StoreQuoteRequest(c.GetTestContext(), quoteRequest)
c.Require().NoError(err)

// Fetch the quote request by tx hash
client := &http.Client{}
req, err := http.NewRequestWithContext(c.GetTestContext(), http.MethodGet, fmt.Sprintf("http://localhost:%d/status?hash=%s", c.port, quoteRequest.OriginTxHash), nil)
c.Require().NoError(err)
resp, err := client.Do(req)
c.Require().NoError(err)
defer func() {
err = resp.Body.Close()
c.Require().NoError(err)
}()
c.Equal(http.StatusOK, resp.StatusCode)

// Compare to expected result
var result relapi.GetQuoteRequestStatusResponse
err = json.NewDecoder(resp.Body).Decode(&result)
c.Require().NoError(err)
expectedResult := relapi.GetQuoteRequestStatusResponse{
Status: quoteRequest.Status.String(),
TxID: hexutil.Encode(quoteRequest.TransactionID[:]),
OriginTxHash: quoteRequest.OriginTxHash.String(),
DestTxHash: quoteRequest.DestTxHash.String(),
}
c.Equal(expectedResult, result)
c.GetTestContext().Done()
Copy link
Contributor

Choose a reason for hiding this comment

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

The test TestGetQuoteRequestByTxHash is well-structured and checks the status endpoint by transaction hash. It includes proper setup, execution, and validation steps. However, the test could be improved by adding assertions for the content of the response to ensure that the API returns the correct data.

Comment on lines 71 to 103
func (c *RelayerServerSuite) TestGetQuoteRequestByTxID() {
c.startAPIServer()

// Insert quote request to db
quoteRequest := c.getTestQuoteRequest(reldb.Seen)
err := c.database.StoreQuoteRequest(c.GetTestContext(), quoteRequest)
c.Require().NoError(err)

// Fetch the quote request by tx hash
client := &http.Client{}
txIDStr := hexutil.Encode(quoteRequest.TransactionID[:])
req, err := http.NewRequestWithContext(c.GetTestContext(), http.MethodGet, fmt.Sprintf("http://localhost:%d/status/by_tx_id?id=%s", c.port, txIDStr), nil)
c.Require().NoError(err)
resp, err := client.Do(req)
c.Require().NoError(err)
defer func() {
err = resp.Body.Close()
c.Require().NoError(err)
}()
c.Equal(http.StatusOK, resp.StatusCode)

// Compare to expected result
var result relapi.GetQuoteRequestStatusResponse
err = json.NewDecoder(resp.Body).Decode(&result)
c.Require().NoError(err)
expectedResult := relapi.GetQuoteRequestStatusResponse{
Status: quoteRequest.Status.String(),
TxID: hexutil.Encode(quoteRequest.TransactionID[:]),
OriginTxHash: quoteRequest.OriginTxHash.String(),
DestTxHash: quoteRequest.DestTxHash.String(),
}
c.Equal(expectedResult, result)
c.GetTestContext().Done()
Copy link
Contributor

Choose a reason for hiding this comment

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

The test TestGetQuoteRequestByTxID is similar to TestGetQuoteRequestByTxHash and shares the same strengths and areas for improvement. It would be beneficial to assert the content of the response for completeness.

Comment on lines +162 to +181
func (c *RelayerServerSuite) getTestQuoteRequest(status reldb.QuoteRequestStatus) reldb.QuoteRequest {
txIDRaw := hexutil.Encode(crypto.Keccak256([]byte("test")))
var txID [32]byte
copy(txID[:], txIDRaw)
return reldb.QuoteRequest{
OriginTokenDecimals: 6,
DestTokenDecimals: 6,
TransactionID: txID,
Status: status,
Transaction: fastbridge.IFastBridgeBridgeTransaction{
OriginChainId: c.originChainID,
DestChainId: c.destChainID,
OriginAmount: big.NewInt(100),
DestAmount: big.NewInt(100),
Deadline: big.NewInt(time.Now().Unix()),
Nonce: big.NewInt(0),
},
OriginTxHash: common.HexToHash("0x0000000"),
DestTxHash: common.HexToHash("0x0000001"),
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The getTestQuoteRequest helper function creates a test quote request with predefined values. It's important to ensure that these values are representative of real-world scenarios to make the tests as realistic as possible. If these values are placeholders, consider using more realistic test data.

Comment on lines 52 to 101
// NewRelayerServerSuite creates a end-to-end test suite.
func NewRelayerServerSuite(tb testing.TB) *RelayerServerSuite {
tb.Helper()
return &RelayerServerSuite{
TestSuite: testsuite.NewTestSuite(tb),
}
}

func (c *RelayerServerSuite) SetupTest() {
c.TestSuite.SetupTest()

testOmnirpc := omnirpcHelper.NewOmnirpcServer(c.GetTestContext(), c.T(), c.omniRPCTestBackends...)
omniRPCClient := omniClient.NewOmnirpcClient(testOmnirpc, c.handler, omniClient.WithCaptureReqRes())
c.omniRPCClient = omniRPCClient

arbFastBridgeAddress, ok := c.fastBridgeAddressMap.Load(42161)
c.True(ok)
ethFastBridgeAddress, ok := c.fastBridgeAddressMap.Load(1)
c.True(ok)
port, err := freeport.GetFreePort()
c.port = uint16(port)
c.Require().NoError(err)

c.originChainID = 1
c.destChainID = 42161

testConfig := config.Config{
Database: config.DatabaseConfig{
Type: "sqlite",
DSN: filet.TmpFile(c.T(), "", "").Name(),
},
OmniRPCURL: testOmnirpc,
Bridges: map[uint32]string{
c.originChainID: ethFastBridgeAddress.Hex(),
c.destChainID: arbFastBridgeAddress.Hex(),
},
Port: fmt.Sprintf("%d", port),
}
c.cfg = testConfig

c.wallet, err = wallet.FromRandom()
c.Require().NoError(err)
signer := localsigner.NewSigner(c.wallet.PrivateKey())
submitterCfg := &submitterConfig.Config{}
ts := submitter.NewTransactionSubmitter(c.handler, signer, omniRPCClient, c.database.SubmitterDB(), submitterCfg)

server, err := relapi.NewRelayerAPI(c.GetTestContext(), c.cfg, c.handler, c.omniRPCClient, c.database, ts)
c.Require().NoError(err)
c.RelayerAPIServer = server
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The SetupTest function properly initializes the test environment, including the Omni RPC client, wallet, and API server. It also handles errors appropriately. However, the test suite should clean up any resources it creates, such as temporary files or network listeners, to avoid side effects on other tests or the system.

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: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between a5b254f and b99e4fa.
Files selected for processing (2)
  • services/rfq/relayer/relapi/server.go (1 hunks)
  • services/rfq/relayer/relapi/server_test.go (1 hunks)
Files skipped from review as they are similar to previous changes (2)
  • services/rfq/relayer/relapi/server.go
  • services/rfq/relayer/relapi/server_test.go

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: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 831c50d and 1cca179.
Files selected for processing (1)
  • services/rfq/relayer/relapi/server_test.go (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • services/rfq/relayer/relapi/server_test.go

Copy link

codecov bot commented Jan 9, 2024

Codecov Report

Attention: 97 lines in your changes are missing coverage. Please review.

Comparison is base (986d3ee) 51.41789% compared to head (6beb0f7) 50.98475%.

Files Patch % Lines
services/rfq/relayer/relapi/handler.go 56.09756% 27 Missing and 9 partials ⚠️
services/rfq/relayer/relapi/server.go 54.71698% 16 Missing and 8 partials ⚠️
services/rfq/relayer/reldb/base/quote.go 0.00000% 15 Missing ⚠️
services/rfq/relayer/service/relayer.go 0.00000% 11 Missing ⚠️
services/rfq/relayer/service/handlers.go 0.00000% 6 Missing ⚠️
services/rfq/relayer/reldb/base/model.go 66.66667% 2 Missing and 1 partial ⚠️
services/rfq/relayer/service/statushandler.go 0.00000% 2 Missing ⚠️
Additional details and impacted files
@@                 Coverage Diff                 @@
##              master       #1785         +/-   ##
===================================================
- Coverage   51.41789%   50.98475%   -0.43315%     
===================================================
  Files            407         397         -10     
  Lines          27823       27012        -811     
  Branches         298         298                 
===================================================
- Hits           14306       13772        -534     
+ Misses         12119       11889        -230     
+ Partials        1398        1351         -47     
Flag Coverage Δ
cctp-relayer ?
promexporter ?
rfq 38.95692% <46.99454%> (+1.20378%) ⬆️

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.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 1cca179 and f42f2ce.
Files selected for processing (2)
  • services/rfq/relayer/relapi/server_test.go (1 hunks)
  • services/rfq/relayer/reldb/base/model.go (4 hunks)
Files skipped from review as they are similar to previous changes (1)
  • services/rfq/relayer/relapi/server_test.go
Additional comments: 1
services/rfq/relayer/reldb/base/model.go (1)
  • 26-26: The addition of the originTxHashFieldName variable seems to be consistent with the existing pattern of defining field names using the dbcommon.NewNamer utility. This change is likely intended to standardize the database field name across the application.

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: 4

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between f42f2ce and 2c57477.
Files selected for processing (10)
  • services/rfq/e2e/rfq_test.go (1 hunks)
  • services/rfq/e2e/setup_test.go (3 hunks)
  • services/rfq/relayer/chain/chain.go (1 hunks)
  • services/rfq/relayer/relapi/handler.go (1 hunks)
  • services/rfq/relayer/relapi/server.go (1 hunks)
  • services/rfq/relayer/relapi/suite_test.go (1 hunks)
  • services/rfq/relayer/relconfig/config.go (3 hunks)
  • services/rfq/relayer/service/handlers.go (3 hunks)
  • services/rfq/relayer/service/relayer.go (5 hunks)
  • services/rfq/relayer/service/statushandler.go (4 hunks)
Files skipped from review as they are similar to previous changes (1)
  • services/rfq/relayer/relapi/suite_test.go
Additional comments: 26
services/rfq/relayer/chain/chain.go (3)
  • 20-30: The Chain struct is well-documented, with clear comments about the visibility of fields and future plans for the struct. The fields seem to be appropriately named and typed.

  • 53-57: The SubmitTransaction method correctly delegates the transaction submission to the submitter field of the Chain struct. The use of nolint: wrapcheck on line 55 suggests that the error from SubmitTransaction should not be wrapped, which is acceptable if the error is meant to be handled as is by the caller.

  • 64-90: The SubmitRelay method is responsible for submitting a relay transaction. It checks if the SendChainGas flag is set on the request and fetches the gas amount if necessary. The error handling is consistent, and the method returns detailed errors. The use of core.CopyBigInt on line 77 ensures that the Value field of the transactor is not inadvertently modified elsewhere.

services/rfq/relayer/relapi/server.go (2)
  • 23-31: The RelayerAPIServer struct is well-defined with clear comments. The fields are private, which is good for encapsulation, and the types seem appropriate for their purposes.

  • 33-77: The NewRelayerAPI function performs thorough nil checks on its parameters, which is good for preventing nil dereference errors. The error messages are clear and provide context. The creation of the chains map is done correctly, and the error handling within the loop is consistent.

services/rfq/relayer/relapi/handler.go (6)
  • 14-18: The Handler struct is simple and straightforward, storing a database connection and a map of Chain instances. The naming is clear, and the struct serves its purpose without unnecessary complexity.

  • 20-25: The NewHandler function is a constructor for the Handler struct. It is concise and correctly assigns the provided arguments to the struct fields.

  • 28-31: The GetHealth method is a simple health check endpoint. It returns a JSON response with a status of "ok", which is a common practice for health endpoints.

  • 35-57: The GetQuoteRequestStatusByTxHash method retrieves the status of a quote request by transaction hash. It correctly handles the case where the 'hash' query parameter is not provided and returns an appropriate error response. The method also handles database errors correctly.

  • 59-88: The GetQuoteRequestStatusByTxID method is similar to the previous method but retrieves the status by transaction ID. It includes proper error handling for missing or invalid 'txID' query parameters and database errors.

  • 90-125: The GetTxRetry method allows users to retry a transaction based on its hash. It includes error handling for missing hash parameters, database errors, and errors during the submission of the relay. The response includes the transaction ID, chain ID, nonce, and gas amount, which is useful information for the client.

services/rfq/relayer/service/statushandler.go (2)
  • 28-30: The QuoteRequestHandler struct has been updated to use the chain.Chain type for its Origin and Dest fields. This change aligns with the refactoring mentioned in the AI-generated summary and suggests a consolidation of chain-related functionality.

  • 107-115: The chainIDToChain method has been refactored to use the new chain.NewChain function. This change is consistent with the refactoring strategy and simplifies the creation of Chain instances.

services/rfq/e2e/rfq_test.go (2)
  • 30-37: The IntegrationSuite struct has been updated to include a relayerApiServer field, which is consistent with the changes made to the relayer service. The renaming of the relayer field to relayerApiServer reflects the introduction of the new API server functionality.

  • 30-37: The setup and test methods in the IntegrationSuite struct appear to be correctly updated to accommodate the new relayerApiServer field. The test setup includes the initialization of necessary services and clients, which is appropriate for an integration test suite.

services/rfq/relayer/relconfig/config.go (3)
  • 28-29: The addition of the RelayerAPIURL field to the Config struct is consistent with the PR objectives to enhance the relayer service with new endpoints. The field is properly named, typed as a string, and has an appropriate yaml tag.

  • 40-41: The addition of the APIConfig field to the Config struct is also consistent with the PR objectives. The field is properly named, typed as APIConfig, and has an appropriate yaml tag.

  • 72-77: The new APIConfig struct is introduced to encapsulate the configuration for the relayer API server. The fields Database, OmniRPCURL, and Port are well-named and have appropriate data types and yaml tags. This struct is a good addition for modularity and clarity in configuration management.

services/rfq/relayer/service/relayer.go (5)
  • 22-22: The import of the relapi package is necessary for the use of the RelayerAPIServer within the Relayer struct and is consistent with the changes made in this PR.

  • 36-36: The addition of the apiServer field to the Relayer struct is consistent with the PR's objective to introduce a new API server. The field is properly named and typed as a pointer to RelayerAPIServer.

  • 99-102: The initialization of the apiServer within the NewRelayer function is correctly done, with error handling in place to return an error if the API server cannot be initialized.

  • 116-116: The apiServer is correctly assigned to the Relayer struct within the NewRelayer function.

  • 189-195: The invocation of apiServer.Run within a goroutine in the Start method is correct and follows the pattern of concurrent initialization for other components of the Relayer. Proper error handling is in place.

services/rfq/e2e/setup_test.go (1)
  • 231-245: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [192-242]

The declaration of relayerApiPort and its usage to construct the RelayerAPIURL and APIConfig in the setupRelayer function is correct. The port is dynamically obtained and properly used to set up the configuration for the relayer API server. This is a good practice for test setup to avoid port conflicts.

services/rfq/relayer/service/handlers.go (2)
  • 4-11: > Note: This review was outside the patches, and no patch overlapping with it was found. Original lines [1-1]

The import math/big has been removed. Please ensure that there are no remaining usages of big.Int or related functions that would require this import, as this could lead to compilation errors.

Verification successful

The removal of the math/big import from handlers.go appears to be justified as there are no remaining usages of big.Int or related functions in that file. This suggests that the review comment has been addressed correctly.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Search for any remaining usages of big.Int or related functions in handlers.go
rg --type go 'big\.Int' services/rfq/relayer/service/handlers.go

Length of output: 66

* 4-11: > Note: This review was outside the patches, and no patch overlapping with it was found. Original lines [1-1]

Overall, the changes in the file seem to align with the PR's objectives. However, please address the issues mentioned regarding the handleCommitConfirmed function and the removal of the math/big import.

Comment on lines 175 to 184
err = q.db.UpdateQuoteRequestStatus(ctx, request.TransactionID, reldb.RelayStarted)
if err != nil {
return fmt.Errorf("could not submit transaction: %w", err)
return fmt.Errorf("could not update quote request status: %w", err)
}

err = q.db.UpdateQuoteRequestStatus(ctx, request.TransactionID, reldb.RelayStarted)

// TODO: store the dest txhash connected to the nonce
nonce, _, err := q.Dest.SubmitRelay(ctx, request)
if err != nil {
return err
}
Copy link
Contributor

Choose a reason for hiding this comment

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

There seems to be a logical error in the handleCommitConfirmed function. The variable nonce is retrieved but not used, and there is a redundant error check after the nonce retrieval that will never be executed because the function will return on the first error encountered.

-    _ = nonce
-    if err != nil {
-        return fmt.Errorf("could not update request status: %w", err)
-    }

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
err = q.db.UpdateQuoteRequestStatus(ctx, request.TransactionID, reldb.RelayStarted)
if err != nil {
return fmt.Errorf("could not submit transaction: %w", err)
return fmt.Errorf("could not update quote request status: %w", err)
}
err = q.db.UpdateQuoteRequestStatus(ctx, request.TransactionID, reldb.RelayStarted)
// TODO: store the dest txhash connected to the nonce
nonce, _, err := q.Dest.SubmitRelay(ctx, request)
if err != nil {
return err
}
err = q.db.UpdateQuoteRequestStatus(ctx, request.TransactionID, reldb.RelayStarted)
if err != nil {
return fmt.Errorf("could not update quote request status: %w", err)
}
// TODO: store the dest txhash connected to the nonce
nonce, _, err := q.Dest.SubmitRelay(ctx, request)
if err != nil {
return err
}

Comment on lines +32 to +50
// NewChain creates a new chain.
func NewChain(ctx context.Context, chainClient client.EVM, addr common.Address, chainListener listener.ContractListener, ts submitter.TransactionSubmitter) (*Chain, error) {
bridge, err := fastbridge.NewFastBridgeRef(addr, chainClient)
if err != nil {
return nil, fmt.Errorf("could not create bridge contract: %w", err)
}
chainID, err := chainClient.ChainID(ctx)
if err != nil {
return nil, fmt.Errorf("could not get chain id: %w", err)
}
return &Chain{
ChainID: uint32(chainID.Int64()),
Bridge: bridge,
Client: chainClient,
// TODO: configure
Confirmations: 1,
listener: chainListener,
submitter: ts,
}, nil
Copy link
Contributor

Choose a reason for hiding this comment

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

The NewChain function is responsible for creating a new Chain instance. It performs error checking and returns a new Chain object or an error. The error messages are wrapped for better context. The TODO comment on line 46 indicates that the Confirmations field should be configurable in the future.

- // TODO: configure
- Confirmations: 1,
+ // TODO: This value should be made configurable.
+ Confirmations: defaultConfirmations, // Assuming `defaultConfirmations` is a constant defined elsewhere.

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// NewChain creates a new chain.
func NewChain(ctx context.Context, chainClient client.EVM, addr common.Address, chainListener listener.ContractListener, ts submitter.TransactionSubmitter) (*Chain, error) {
bridge, err := fastbridge.NewFastBridgeRef(addr, chainClient)
if err != nil {
return nil, fmt.Errorf("could not create bridge contract: %w", err)
}
chainID, err := chainClient.ChainID(ctx)
if err != nil {
return nil, fmt.Errorf("could not get chain id: %w", err)
}
return &Chain{
ChainID: uint32(chainID.Int64()),
Bridge: bridge,
Client: chainClient,
// TODO: configure
Confirmations: 1,
listener: chainListener,
submitter: ts,
}, nil
// NewChain creates a new chain.
func NewChain(ctx context.Context, chainClient client.EVM, addr common.Address, chainListener listener.ContractListener, ts submitter.TransactionSubmitter) (*Chain, error) {
bridge, err := fastbridge.NewFastBridgeRef(addr, chainClient)
if err != nil {
return nil, fmt.Errorf("could not create bridge contract: %w", err)
}
chainID, err := chainClient.ChainID(ctx)
if err != nil {
return nil, fmt.Errorf("could not get chain id: %w", err)
}
return &Chain{
ChainID: uint32(chainID.Int64()),
Bridge: bridge,
Client: chainClient,
// TODO: This value should be made configurable.
Confirmations: defaultConfirmations, // Assuming `defaultConfirmations` is a constant defined elsewhere.
listener: chainListener,
submitter: ts,
}, nil
}

Comment on lines 89 to 110
// Run runs the rest api server.
func (r *RelayerAPIServer) Run(ctx context.Context) error {
// TODO: Use Gin Helper
engine := ginhelper.New(logger)
h := NewHandler(r.db, r.chains)

// Assign GET routes
engine.GET(getHealthRoute, h.GetHealth)
engine.GET(getQuoteStatusByTxHashRoute, h.GetQuoteRequestStatusByTxHash)
engine.GET(getQuoteStatusByTxIDRoute, h.GetQuoteRequestStatusByTxID)
engine.GET(getRetryRoute, h.GetTxRetry)

r.engine = engine

connection := baseServer.Server{}
fmt.Printf("starting api at http://localhost:%s\n", r.cfg.APIConfig.Port)
err := connection.ListenAndServe(ctx, fmt.Sprintf(":%s", r.cfg.APIConfig.Port), r.engine)
if err != nil {
return fmt.Errorf("could not start relayer api server: %w", err)
}

return nil
Copy link
Contributor

Choose a reason for hiding this comment

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

The Run method sets up the Gin engine and routes, then starts the server. The TODO comment on line 91 suggests using a Gin Helper, which should be addressed in the future. The server start-up message on line 104 is printed to stdout, which might not be ideal for production environments where logging to a file or a logging system is preferred.

- fmt.Printf("starting api at http://localhost:%s\n", r.cfg.APIConfig.Port)
+ // TODO: Replace with structured logging
+ log.Infof("Starting API at http://localhost:%s", r.cfg.APIConfig.Port)

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// Run runs the rest api server.
func (r *RelayerAPIServer) Run(ctx context.Context) error {
// TODO: Use Gin Helper
engine := ginhelper.New(logger)
h := NewHandler(r.db, r.chains)
// Assign GET routes
engine.GET(getHealthRoute, h.GetHealth)
engine.GET(getQuoteStatusByTxHashRoute, h.GetQuoteRequestStatusByTxHash)
engine.GET(getQuoteStatusByTxIDRoute, h.GetQuoteRequestStatusByTxID)
engine.GET(getRetryRoute, h.GetTxRetry)
r.engine = engine
connection := baseServer.Server{}
fmt.Printf("starting api at http://localhost:%s\n", r.cfg.APIConfig.Port)
err := connection.ListenAndServe(ctx, fmt.Sprintf(":%s", r.cfg.APIConfig.Port), r.engine)
if err != nil {
return fmt.Errorf("could not start relayer api server: %w", err)
}
return nil
// Run runs the rest api server.
func (r *RelayerAPIServer) Run(ctx context.Context) error {
// TODO: Use Gin Helper
engine := ginhelper.New(logger)
h := NewHandler(r.db, r.chains)
// Assign GET routes
engine.GET(getHealthRoute, h.GetHealth)
engine.GET(getQuoteStatusByTxHashRoute, h.GetQuoteRequestStatusByTxHash)
engine.GET(getQuoteStatusByTxIDRoute, h.GetQuoteRequestStatusByTxID)
engine.GET(getRetryRoute, h.GetTxRetry)
r.engine = engine
connection := baseServer.Server{}
// TODO: Replace with structured logging
log.Infof("Starting API at http://localhost:%s", r.cfg.APIConfig.Port)
err := connection.ListenAndServe(ctx, fmt.Sprintf(":%s", r.cfg.APIConfig.Port), r.engine)
if err != nil {
return fmt.Errorf("could not start relayer api server: %w", err)
}
return nil

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: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 2c57477 and 0d0615c.
Files selected for processing (1)
  • services/rfq/relayer/relapi/server.go (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • services/rfq/relayer/relapi/server.go

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: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 0d0615c and 4e4e4d4.
Files selected for processing (3)
  • services/rfq/relayer/relapi/server.go (1 hunks)
  • services/rfq/relayer/relapi/suite_test.go (1 hunks)
  • services/rfq/relayer/relconfig/config.go (3 hunks)
Files skipped from review as they are similar to previous changes (3)
  • services/rfq/relayer/relapi/server.go
  • services/rfq/relayer/relapi/suite_test.go
  • services/rfq/relayer/relconfig/config.go

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: 4

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 4e4e4d4 and 49b6ce4.
Files selected for processing (7)
  • services/rfq/api/client/suite_test.go (2 hunks)
  • services/rfq/api/rest/server.go (5 hunks)
  • services/rfq/api/rest/server_test.go (7 hunks)
  • services/rfq/api/rest/suite_test.go (2 hunks)
  • services/rfq/e2e/rfq_test.go (2 hunks)
  • services/rfq/e2e/setup_test.go (4 hunks)
  • services/rfq/relayer/relapi/server_test.go (1 hunks)
Files skipped from review due to trivial changes (1)
  • services/rfq/api/rest/suite_test.go
Files skipped from review as they are similar to previous changes (3)
  • services/rfq/e2e/rfq_test.go
  • services/rfq/e2e/setup_test.go
  • services/rfq/relayer/relapi/server_test.go
Additional comments: 4
services/rfq/api/rest/server.go (2)
  • 26-28: The renaming of the APIServer struct to QuoterAPIServer is consistent with the PR objectives to enhance the blockchain relayer service and provide more descriptive naming.

  • 42-48: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [45-71]

The NewAPI function has been correctly updated to return a pointer to QuoterAPIServer. The error handling within this function is appropriate, checking for nil arguments before proceeding with the initialization.

services/rfq/api/client/suite_test.go (1)
  • 45-45: The ClientSuite struct has been updated to include the QuoterAPIServer field instead of APIServer. This change is consistent with the renaming throughout the codebase.
services/rfq/api/rest/server_test.go (1)
  • 18-18: The test function TestNewQuoterAPIServer has been correctly renamed and the startQuoterAPIServer method is called to start the server. This is consistent with the changes in the codebase.

Comment on lines 112 to 118
}

// AuthMiddleware is the Gin authentication middleware that authenticates requests using EIP191.
func (r *APIServer) AuthMiddleware() gin.HandlerFunc {
func (r *QuoterAPIServer) AuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
var req model.PutQuoteRequest
if err := c.BindJSON(&req); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [87-117]

The Run method of QuoterAPIServer has been updated to use the ginhelper.New function to create a new Gin engine. The TODO comment suggests that there is an intention to replace the hardcoded deadline with a configurable value. This should be addressed to avoid potential security issues with stale authentication tokens.

@@ -112,7 +112,7 @@
}

// AuthMiddleware is the Gin authentication middleware that authenticates requests using EIP191.
func (r *APIServer) AuthMiddleware() gin.HandlerFunc {
func (r *QuoterAPIServer) AuthMiddleware() gin.HandlerFunc {
Copy link
Contributor

Choose a reason for hiding this comment

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

The AuthMiddleware method correctly implements the EIP191 authentication, but the hardcoded deadline (time.Now().Unix() - 1000) should be replaced with a configurable value from r.cfg.AuthExpiryDelta as indicated by the TODO comment. This is important for security reasons and to allow for easy adjustments without code changes.

Comment on lines +87 to +92
QuoterAPIServer, err := rest.NewAPI(c.GetTestContext(), c.cfg, c.handler, c.omniRPCClient, c.database)
c.Require().NoError(err)
c.APIServer = APIServer
c.QuoterAPIServer = QuoterAPIServer

go func() {
err := c.APIServer.Run(c.GetTestContext())
err := c.QuoterAPIServer.Run(c.GetTestContext())
Copy link
Contributor

Choose a reason for hiding this comment

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

The SetupTest method correctly initializes the QuoterAPIServer and starts it in a goroutine. The use of time.Sleep to wait for the server to start is not ideal for test reliability. Consider using a more deterministic approach to wait for the server to be ready, such as polling on a health check endpoint.

- time.Sleep(2 * time.Second) // Wait for the server to start.
+ // Implement a more reliable way to wait for the server to start, such as polling a health endpoint.

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
QuoterAPIServer, err := rest.NewAPI(c.GetTestContext(), c.cfg, c.handler, c.omniRPCClient, c.database)
c.Require().NoError(err)
c.APIServer = APIServer
c.QuoterAPIServer = QuoterAPIServer
go func() {
err := c.APIServer.Run(c.GetTestContext())
err := c.QuoterAPIServer.Run(c.GetTestContext())
QuoterAPIServer, err := rest.NewAPI(c.GetTestContext(), c.cfg, c.handler, c.omniRPCClient, c.database)
c.Require().NoError(err)
c.QuoterAPIServer = QuoterAPIServer
go func() {
err := c.QuoterAPIServer.Run(c.GetTestContext())
// Implement a more reliable way to wait for the server to start, such as polling a health endpoint.

Comment on lines +206 to +209
// startQuoterAPIServer starts the API server and waits for it to initialize.
func (c *ServerSuite) startQuoterAPIServer() {
go func() {
err := c.APIServer.Run(c.GetTestContext())
err := c.QuoterAPIServer.Run(c.GetTestContext())
Copy link
Contributor

Choose a reason for hiding this comment

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

The startQuoterAPIServer method starts the QuoterAPIServer in a goroutine. As mentioned earlier, using time.Sleep to wait for the server to start is not ideal. A more deterministic approach should be used to ensure the server is ready before proceeding with tests.

- time.Sleep(2 * time.Second) // Wait for the server to start.
+ // Implement a more reliable way to wait for the server to start, such as polling a health endpoint.

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
// startQuoterAPIServer starts the API server and waits for it to initialize.
func (c *ServerSuite) startQuoterAPIServer() {
go func() {
err := c.APIServer.Run(c.GetTestContext())
err := c.QuoterAPIServer.Run(c.GetTestContext())
// startQuoterAPIServer starts the API server and waits for it to initialize.
func (c *ServerSuite) startQuoterAPIServer() {
go func() {
err := c.QuoterAPIServer.Run(c.GetTestContext())
// Implement a more reliable way to wait for the server to start, such as polling a health endpoint.

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: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 49b6ce4 and 51f719d.
Files selected for processing (2)
  • services/rfq/relayer/listener/listener_test.go (3 hunks)
  • services/rfq/relayer/service/statushandler.go (4 hunks)
Additional comments: 6
services/rfq/relayer/listener/listener_test.go (3)
  • 2-17: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [1-8]

The reordering of imports follows the standard Go convention of grouping standard library imports separately from third-party libraries, which is good for readability.

  • 44-44: Adding l.NotNil(bridgeRequestTX) ensures that the MockBridgeRequest function returns a non-nil transaction, which is a good practice for verifying the expected behavior of the mocked function.

  • 68-68: Similarly, adding l.NotNil(bridgeResponseTX) ensures that the MockBridgeRelayer function returns a non-nil transaction. This is a good addition for the same reasons as the previous assertion.

services/rfq/relayer/service/statushandler.go (3)
  • 13-13: The import of the new chain package is correctly placed with other internal package imports, which is consistent with Go conventions.

  • 28-30: The Chain type from the chain package is now used for the Origin and Dest fields in the QuoteRequestHandler struct. This change likely reflects a refactoring effort to consolidate chain-related functionality. Ensure that all references to these fields throughout the codebase have been updated accordingly.

Verification successful

The Chain type from the chain package is correctly used in the QuoteRequestHandler struct, with the Origin and Dest fields being properly assigned. The code snippet provided in the output shows the instantiation of the QuoteRequestHandler with both Origin and Dest fields set, indicating that the refactoring has been consistently applied where this struct is initialized.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Search for references to the Origin and Dest fields in the QuoteRequestHandler struct.
ast-grep --lang go --pattern $'QuoteRequestHandler { $$$ Origin: $_, $$$ }'
ast-grep --lang go --pattern $'QuoteRequestHandler { $$$ Dest: $_, $$$ }'

Length of output: 1031

* 107-116: The `chainIDToChain` method now uses the `NewChain` constructor from the `chain` package. This change centralizes the creation of `Chain` instances and is a good practice for maintainability. However, the `//nolint: wrapcheck` directive on line 115 suggests that error wrapping is being suppressed. It's important to ensure that this suppression is intentional and justified, as error wrapping can provide valuable context for debugging.
Verification successful

The review comment regarding the use of the NewChain constructor in the chainIDToChain method has been verified. The rg command output confirms that the NewChain constructor is indeed used within the chain package and is referenced in the services/rfq/relayer/chain/chain.go and services/rfq/relayer/service/statushandler.go files, among others. This aligns with the changes made in the PR and suggests that the constructor is consistently used where appropriate.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify that the NewChain constructor is used consistently across the codebase.
ast-grep --lang go --pattern $'NewChain($_, $_, $_, $_, $_)'

Length of output: 61



Script:

#!/bin/bash
# Search for the usage of the NewChain constructor across the codebase without specifying the number of arguments.
ast-grep --lang go --pattern $'NewChain($$$)'

Length of output: 46



Script:

#!/bin/bash
# Perform a text-based search for the usage of the NewChain constructor across the codebase.
rg 'NewChain' --type go

Length of output: 24280

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 51f719d and 497bdff.
Files selected for processing (1)
  • services/rfq/relayer/service/handlers.go (3 hunks)
Additional comments: 3
services/rfq/relayer/service/handlers.go (3)
  • 175-184: The handleCommitConfirmed function has been updated to use the SubmitRelay method for submitting the relay transaction. Ensure that the SubmitRelay method is correctly implemented and that all error cases are handled appropriately. Also, the variable nonce is retrieved but not used, which could be an oversight or leftover from a refactor.

  • 225-230: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [230-248]

In the handleProofPosted function, there is a check q.shouldCheckClaim(request) to determine if the claim should be checked. Ensure that this function is correctly implemented and that it accounts for all necessary conditions before proceeding with the claim.

Verification successful

The shouldCheckClaim function is implemented in the statushandler.go file. It uses a claimCache to determine if a claim check should be performed, avoiding too frequent RPC hits. If the TransactionID is present in the claimCache, the function returns false, indicating that the claim should not be checked. Otherwise, it sets the TransactionID in the claimCache with a timeout of 30 seconds and returns true, indicating that the claim should be checked.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify the implementation of shouldCheckClaim method and its conditions.
ast-grep --lang go --pattern $'func ($_ *$_) shouldCheckClaim($_) $_ {
  $$$
}'

Length of output: 848

* 4-11: > Note: This review was outside the patches, and no patch overlapping with it was found. Original lines [250-260]

The handleNotEnoughInventory function updates the status to CommittedPending if there is now enough inventory. This is a good use of the optimistic update pattern, assuming that inventory levels are being updated elsewhere in the system. Confirm that inventory levels are being tracked and updated correctly to avoid any race conditions.

Comment on lines 4 to 11
"context"
"errors"
"fmt"
"math/big"
"strings"

"github.com/synapsecns/sanguine/core"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
Copy link
Contributor

Choose a reason for hiding this comment

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

Note: This review was outside the patches, and no patch overlapping with it was found. Original lines [204-214]

In the handleRelayLog function, there is a comment about the potential for re-orgs but no code to handle such a scenario. If re-orgs are a concern, consider implementing logic to handle them or create a task to address this in the future.

Comment on lines 225 to 230
func (q *QuoteRequestHandler) handleRelayCompleted(ctx context.Context, _ trace.Span, request reldb.QuoteRequest) (err error) {
// relays been completed, it's time to go back to the origin chain and try to prove
_, err = q.Origin.SubmitTransaction(ctx, func(transactor *bind.TransactOpts) (tx *types.Transaction, err error) {
// MAJO MAJOR TODO should be dest tx hash
tx, err = q.Origin.Bridge.Prove(transactor, request.RawRequest, request.DestTxHash)
if err != nil {
return nil, fmt.Errorf("could not relay: %w", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [216-228]

The handleRelayCompleted function appears to be correctly updating the status after submitting a claim transaction. However, there is no check to ensure that the previous status is RelayCompleted before proceeding. This could lead to incorrect state transitions if the function is called out of order.

if request.Status != reldb.RelayCompleted {
-   return fmt.Errorf("incorrect status for proving posting: %w", reldb.ErrInvalidStatus)
+   return nil
}

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: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 497bdff and 5dbd12e.
Files selected for processing (1)
  • services/rfq/relayer/pricer/fee_pricer.go (1 hunks)
Additional comments: 2
services/rfq/relayer/pricer/fee_pricer.go (2)
  • 80-80: The origin parameter in the GetDestinationFee function signature has been replaced with an underscore, indicating it is unused. Ensure that this change does not affect any existing calls to this function where the origin parameter was previously being used.

  • 77-83: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [1-122]

The rest of the file appears to be unchanged and there are no other modifications to the public interface of the feePricer struct. The logic within the GetDestinationFee method remains the same, and the removal of the origin parameter seems to be the only change. Ensure that the rest of the codebase is consistent with this change and that no other parts of the code rely on the origin parameter within the GetDestinationFee method.

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: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 5dbd12e and 5fa3598.
Files selected for processing (5)
  • services/rfq/e2e/rfq_test.go (5 hunks)
  • services/rfq/e2e/setup_test.go (4 hunks)
  • services/rfq/relayer/relapi/server.go (1 hunks)
  • services/rfq/relayer/relapi/suite_test.go (1 hunks)
  • services/rfq/relayer/relconfig/config.go (1 hunks)
Files skipped from review due to trivial changes (1)
  • services/rfq/relayer/relconfig/config.go

@trajan0x trajan0x merged commit 28d459b into master Jan 12, 2024
28 checks passed
@trajan0x trajan0x deleted the feat/rfq-status branch January 12, 2024 14:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
go Pull requests that update Go code size/m
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[RFQ] Retry Endpoint [RFQ] Status Endpoint
2 participants