Skip to content

Conversation

@danieljrc888
Copy link
Contributor

@danieljrc888 danieljrc888 commented Jul 14, 2025

Fixes #issue-number-here

What

  • changed thing a for b
  • also did this other unrelated thing in my path

Why

  • to fix a bug
  • to add more value to the user

Testing done

  • tested the new feature
  • tested the bug fix

Decisions made

Checks

  • I have tested this code
  • I have reviewed my own PR
  • I have created an issue for this PR
  • I have set a descriptive PR title compliant with conventional commits

Reviewing tips

User facing release notes

Summary by CodeRabbit

  • New Features

    • Introduced centralized configuration for Hardhat network settings, allowing for consistent management of connection details.
    • Enhanced gas estimation to dynamically calculate gas using the Hardhat network for more accurate results.
  • Refactor

    • Updated backend modules and tests to utilize the new centralized Hardhat configuration, enhancing maintainability and reducing duplication.
    • Separated Hardhat URL and port into distinct environment variables for clearer configuration in test environments.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 14, 2025

"""

Walkthrough

A centralized configuration system for Hardhat network settings was introduced via a new HardhatConfig class. Multiple backend modules and test files were refactored to use this class for obtaining Hardhat URLs and Web3 instances, replacing direct environment variable access. The test Docker Compose file was updated to split the Hardhat URL and port into separate environment variables. The get_gas_estimate function was enhanced to perform dynamic gas estimation using Hardhat.

Changes

File(s) Change Summary
backend/config/init.py Added package docstring for backend configuration package.
backend/config/hardhat_config.py Introduced HardhatConfig class with static methods for Hardhat URL, port, full URL, and Web3 instance retrieval.
backend/database_handler/transactions_processor.py Replaced environment variable logic with HardhatConfig.get_web3_instance() for Web3 connection.
backend/protocol_rpc/endpoint_generator.py Replaced manual Hardhat URL construction with HardhatConfig.get_full_url() for forwarding eth_ methods.
backend/rollup/consensus_service.py Centralized Web3 instance creation using HardhatConfig.get_web3_instance() instead of env variable logic.
backend/protocol_rpc/endpoints.py Modified get_gas_estimate to perform dynamic gas estimation via Hardhat using HardhatConfig.get_web3_instance().
tests/hardhat/docker-compose.yml Split HARDHAT_URL and HARDHAT_PORT into separate environment variables.
tests/hardhat/test_hardhat.py Refactored to use HardhatConfig.get_web3_instance() for test Hardhat connection.
tests/db-sqlalchemy/conftest.py Modified transactions_processor fixture to patch HardhatConfig.get_web3_instance() with a mocked Web3.
tests/db-sqlalchemy/transactions_processor_test.py Renamed and simplified fixture by removing Web3 mocking; only environment variables patched now.

Sequence Diagram(s)

sequenceDiagram
    participant Module as Backend Module
    participant HardhatConfig
    participant Web3

    Module->>HardhatConfig: get_web3_instance()
    HardhatConfig->>HardhatConfig: get_base_url(), get_port()
    HardhatConfig->>Web3: Create Web3(HTTPProvider(full_url))
    HardhatConfig-->>Module: Return Web3 instance
Loading

Possibly related PRs

Suggested reviewers

  • cristiam86

Poem

A bunny hops through lines anew,
Centralized configs—what a view!
No more chasing envs around,
In HardhatConfig, they're safely found.
With Web3 linked in every place,
The code now runs a smoother race!
🐇✨
"""

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • 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/schema.v2.json

Documentation and Community

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (1)
backend/protocol_rpc/endpoint_generator.py (1)

70-91: Potential malformed Hardhat URL – safeguard against double port
HardhatConfig.get_full_url() blindly concatenates base_url and port, so an env value like HARDHAT_URL=http://hardhat:8545 will yield http://hardhat:8545:8545, which the requests call below will fail on.

Quick fix inside _before_request scope (until HardhatConfig is patched):

-    hardhat_url = HardhatConfig.get_full_url()
+    raw_url = HardhatConfig.get_full_url()
+    # strip duplicate port if present (temporary guard)
+    if raw_url.count(":") > 2:  # scheme + host + (>1) port
+        host_part, _, port_part = raw_url.rpartition(":")
+        if host_part.endswith(port_part):
+            raw_url = host_part  # port already embedded
+    hardhat_url = raw_url

Long-term: make HardhatConfig.get_full_url() detect an existing port and avoid appending a second one.

🧹 Nitpick comments (2)
backend/database_handler/transactions_processor.py (1)

18-19: Consider injecting the Web3 instance instead of constructing it internally
Hard-wiring a new Web3 connection for every TransactionsProcessor hampers unit-testing (mocking) and forces duplicate connections across services.
Pass a Web3 instance (or the HardhatConfig singleton) through the constructor and default to HardhatConfig.get_web3_instance() only when none is supplied.

Also applies to: 108-109

backend/config/hardhat_config.py (1)

20-25: Consider URL validation to prevent malformed URLs.

The get_full_url() method assumes the base URL doesn't already include a port. If someone sets HARDHAT_URL to "http://localhost:8545", the result would be "http://localhost:8545:8545".

Consider adding validation or documentation to clarify the expected format of HARDHAT_URL.

Example improvement:

@staticmethod
def get_full_url() -> str:
    """Get the complete Hardhat URL with port."""
    port = HardhatConfig.get_port()
    url = HardhatConfig.get_base_url()
+   # Ensure base URL doesn't already include port
+   if ':' in url.split('://', 1)[1]:
+       return url
    return f"{url}:{port}"
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e786d6 and 244bf07.

📒 Files selected for processing (7)
  • backend/config/__init__.py (1 hunks)
  • backend/config/hardhat_config.py (1 hunks)
  • backend/database_handler/transactions_processor.py (2 hunks)
  • backend/protocol_rpc/endpoint_generator.py (3 hunks)
  • backend/rollup/consensus_service.py (2 hunks)
  • tests/hardhat/docker-compose.yml (1 hunks)
  • tests/hardhat/test_hardhat.py (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
backend/rollup/consensus_service.py (1)
backend/config/hardhat_config.py (2)
  • HardhatConfig (7-31)
  • get_web3_instance (28-31)
backend/protocol_rpc/endpoint_generator.py (1)
backend/config/hardhat_config.py (2)
  • HardhatConfig (7-31)
  • get_full_url (21-25)
backend/database_handler/transactions_processor.py (1)
backend/config/hardhat_config.py (2)
  • HardhatConfig (7-31)
  • get_web3_instance (28-31)
tests/hardhat/test_hardhat.py (1)
backend/config/hardhat_config.py (2)
  • HardhatConfig (7-31)
  • get_web3_instance (28-31)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Load Tests / load-test
  • GitHub Check: test
  • GitHub Check: backend-unit-tests
🔇 Additional comments (6)
backend/config/__init__.py (1)

1-1: Minimal, but fine for package declaration
A single-line docstring is enough to establish the namespace; no further action required for now.

tests/hardhat/docker-compose.yml (1)

33-34: Verify compatibility with existing deployments
Splitting HARDHAT_URL and HARDHAT_PORT improves clarity but will break any environment that still exports a full URL with the port included (e.g. http://hardhat:8545).
Please double-check CI/production env-files and Helm charts before merging.

backend/rollup/consensus_service.py (1)

10-20: Check web3.is_connected() availability across Web3 versions
web3.is_connected() exists only in Web3 ≥ 6.x; older installations expose isConnected.
If the project supports both 5.x and 6.x, wrap the call:

self.web3_connected = (
    self.web3.is_connected()
    if hasattr(self.web3, "is_connected")
    else self.web3.isConnected()
)

(or pin Web3 ≥ 6 in requirements.txt).

tests/hardhat/test_hardhat.py (2)

3-3: Good centralization of Hardhat configuration.

The import of HardhatConfig aligns with the new centralized configuration approach, removing the need for direct environment variable access in test files.


43-43: Excellent refactoring to use centralized Web3 instance creation.

The change from manual Web3 instantiation to using HardhatConfig.get_web3_instance() improves maintainability by centralizing the connection logic. The connection check and error handling remain intact, ensuring the same behavior.

backend/config/hardhat_config.py (1)

7-31: Well-designed centralized configuration class.

The HardhatConfig class provides a clean, centralized approach to managing Hardhat network settings. The static methods, clear docstrings, and sensible defaults make this a maintainable solution.

@danieljrc888 danieljrc888 force-pushed the dxp-365-improve-gas-estimation-rpc-endpoint-2 branch from 244bf07 to b338c7b Compare July 14, 2025 11:19
@danieljrc888 danieljrc888 force-pushed the dxp-365-improve-gas-estimation-rpc-endpoint-2 branch from b338c7b to 70ba9be Compare July 14, 2025 11:22
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 70ba9be and f8512bf.

📒 Files selected for processing (1)
  • backend/protocol_rpc/endpoints.py (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
backend/protocol_rpc/endpoints.py (1)
backend/config/hardhat_config.py (2)
  • HardhatConfig (7-31)
  • get_web3_instance (28-31)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Load Tests / load-test
  • GitHub Check: test
  • GitHub Check: backend-unit-tests
🔇 Additional comments (1)
backend/protocol_rpc/endpoints.py (1)

12-12: LGTM: Import statement is correctly added.

The new import for HardhatConfig is properly added and aligns with the centralized configuration approach mentioned in the AI summary.

Comment on lines 881 to +915
def get_gas_estimate(data: Any) -> str:
gas_price_in_wei = 30 * 10**6
return hex(gas_price_in_wei)
"""
Estimate gas for a transaction using Hardhat service.
Falls back to a default value if the estimation fails.
"""
fallback_gas_estimate = 30 * 10**6

try:
web3 = HardhatConfig.get_web3_instance()
tx_params = {}
if isinstance(data, dict):
if "from" in data:
tx_params["from"] = data["from"]
if "to" in data:
tx_params["to"] = data["to"]
# Handle both 'data' and 'input' fields (some clients use 'input' instead of 'data')
if "data" in data:
tx_params["data"] = data["data"]
elif "input" in data:
tx_params["data"] = data["input"]
if "value" in data:
tx_params["value"] = (
int(data["value"], 16)
if isinstance(data["value"], str)
else data["value"]
)
if tx_params:
gas_estimate = web3.eth.estimate_gas(tx_params)
return hex(gas_estimate)
else:
return hex(fallback_gas_estimate)

except Exception:
return hex(fallback_gas_estimate)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling and parameter validation in gas estimation.

The dynamic gas estimation implementation is a good improvement, but there are several areas that need attention:

  1. Overly broad exception handling: The except Exception: catches all exceptions, which might hide important errors and make debugging difficult.

  2. Missing parameter validation: The function doesn't validate addresses or other parameters before passing them to Web3.

  3. Incomplete value conversion: The hex string conversion assumes proper formatting but doesn't handle edge cases.

  4. Missing gas parameter handling: The function doesn't process the "gas" parameter that might be included in the transaction data.

Consider applying these improvements:

def get_gas_estimate(data: Any) -> str:
    """
    Estimate gas for a transaction using Hardhat service.
    Falls back to a default value if the estimation fails.
    """
    fallback_gas_estimate = 30 * 10**6

    try:
        web3 = HardhatConfig.get_web3_instance()
        tx_params = {}
        if isinstance(data, dict):
            if "from" in data:
                tx_params["from"] = data["from"]
            if "to" in data:
                tx_params["to"] = data["to"]
            # Handle both 'data' and 'input' fields (some clients use 'input' instead of 'data')
            if "data" in data:
                tx_params["data"] = data["data"]
            elif "input" in data:
                tx_params["data"] = data["input"]
            if "value" in data:
-                tx_params["value"] = (
-                    int(data["value"], 16)
-                    if isinstance(data["value"], str)
-                    else data["value"]
-                )
+                value = data["value"]
+                if isinstance(value, str):
+                    # Handle hex strings with or without '0x' prefix
+                    tx_params["value"] = int(value, 16) if value.startswith(('0x', '0X')) else int(value, 16)
+                else:
+                    tx_params["value"] = value
+            if "gas" in data:
+                gas = data["gas"]
+                if isinstance(gas, str):
+                    tx_params["gas"] = int(gas, 16) if gas.startswith(('0x', '0X')) else int(gas, 16)
+                else:
+                    tx_params["gas"] = gas
+                    
        if tx_params:
            gas_estimate = web3.eth.estimate_gas(tx_params)
            return hex(gas_estimate)
        else:
            return hex(fallback_gas_estimate)

-    except Exception:
+    except (ValueError, ConnectionError, TimeoutError) as e:
+        # Log the specific error for debugging
+        print(f"Gas estimation failed: {e}")
+        return hex(fallback_gas_estimate)
+    except Exception as e:
+        # Log unexpected errors
+        print(f"Unexpected error in gas estimation: {e}")
        return hex(fallback_gas_estimate)
📝 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. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def get_gas_estimate(data: Any) -> str:
gas_price_in_wei = 30 * 10**6
return hex(gas_price_in_wei)
"""
Estimate gas for a transaction using Hardhat service.
Falls back to a default value if the estimation fails.
"""
fallback_gas_estimate = 30 * 10**6
try:
web3 = HardhatConfig.get_web3_instance()
tx_params = {}
if isinstance(data, dict):
if "from" in data:
tx_params["from"] = data["from"]
if "to" in data:
tx_params["to"] = data["to"]
# Handle both 'data' and 'input' fields (some clients use 'input' instead of 'data')
if "data" in data:
tx_params["data"] = data["data"]
elif "input" in data:
tx_params["data"] = data["input"]
if "value" in data:
tx_params["value"] = (
int(data["value"], 16)
if isinstance(data["value"], str)
else data["value"]
)
if tx_params:
gas_estimate = web3.eth.estimate_gas(tx_params)
return hex(gas_estimate)
else:
return hex(fallback_gas_estimate)
except Exception:
return hex(fallback_gas_estimate)
def get_gas_estimate(data: Any) -> str:
"""
Estimate gas for a transaction using Hardhat service.
Falls back to a default value if the estimation fails.
"""
fallback_gas_estimate = 30 * 10**6
try:
web3 = HardhatConfig.get_web3_instance()
tx_params = {}
if isinstance(data, dict):
if "from" in data:
tx_params["from"] = data["from"]
if "to" in data:
tx_params["to"] = data["to"]
# Handle both 'data' and 'input' fields (some clients use 'input' instead of 'data')
if "data" in data:
tx_params["data"] = data["data"]
elif "input" in data:
tx_params["data"] = data["input"]
if "value" in data:
value = data["value"]
if isinstance(value, str):
# Handle hex strings with or without '0x' prefix
tx_params["value"] = int(value, 16) if value.startswith(('0x', '0X')) else int(value, 16)
else:
tx_params["value"] = value
if "gas" in data:
gas = data["gas"]
if isinstance(gas, str):
tx_params["gas"] = int(gas, 16) if gas.startswith(('0x', '0X')) else int(gas, 16)
else:
tx_params["gas"] = gas
if tx_params:
gas_estimate = web3.eth.estimate_gas(tx_params)
return hex(gas_estimate)
else:
return hex(fallback_gas_estimate)
except (ValueError, ConnectionError, TimeoutError) as e:
# Log the specific error for debugging
print(f"Gas estimation failed: {e}")
return hex(fallback_gas_estimate)
except Exception as e:
# Log unexpected errors
print(f"Unexpected error in gas estimation: {e}")
return hex(fallback_gas_estimate)
🤖 Prompt for AI Agents
In backend/protocol_rpc/endpoints.py around lines 882 to 915, improve
get_gas_estimate by replacing the broad except Exception with more specific
exception handling to avoid masking errors, validate Ethereum addresses and
other parameters before using them in web3 calls, enhance the conversion of the
"value" field to safely handle edge cases and invalid formats, and add support
to process the "gas" parameter from the input data if present to ensure accurate
gas estimation.

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
23.3% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants