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

feat(katana): modify DevApi trait with new endpoints #2490

Open
wants to merge 26 commits into
base: main
Choose a base branch
from

Conversation

fabrobles92
Copy link
Contributor

@fabrobles92 fabrobles92 commented Oct 1, 2024

Description

Add starknet-devnet's endpoint proxy.

Methods

The full list of the methods are as follows, taken from starknet-devnet-rs:

  • POST /create_block
  • POST /abort_blocks
  • POST /restart
  • POST /set_time
  • POST /increase_time
  • GET /predeployed_accounts
  • GET /account_balance
  • GET /fee_token
  • POST /mint
  • GET /fork_status

but for now, this PR will only addressing the account related endpoints:

  • GET /predeployed_accounts
  • GET /account_balance
  • GET /fee_token

Related issue

Please link related issues: Fixes #1586

Tests

  • Yes
  • No, because they aren't needed
  • No, because I need help

Added to documentation?

  • README.md
  • Dojo Book
  • No documentation needed

Checklist

  • I've formatted my code (scripts/prettier.sh, scripts/rust_fmt.sh, scripts/cairo_fmt.sh)
  • I've linted my code (scripts/clippy.sh, scripts/docs.sh)
  • I've commented my code
  • I've requested a review after addressing the comments

Summary by CodeRabbit

  • New Features

    • Added string parsing support for PriceUnit enum
    • Introduced new methods for retrieving account balances and minting
    • Implemented a proxy middleware for HTTP GET request handling
  • Dependency Updates

    • Added several new dependencies for JSON-RPC, HTTP, and async programming support
  • Refactor

    • Enhanced RPC server middleware configuration
    • Improved HTTP transport response handling

Copy link

codecov bot commented Oct 1, 2024

Codecov Report

Attention: Patch coverage is 24.80000% with 94 lines in your changes missing coverage. Please review.

Project coverage is 55.76%. Comparing base (38f68db) to head (17a53b5).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
crates/katana/rpc/rpc/src/proxy_get_request.rs 42.85% 40 Missing ⚠️
crates/katana/rpc/rpc/src/transport/http.rs 0.00% 25 Missing ⚠️
crates/katana/rpc/rpc/src/dev.rs 0.00% 17 Missing ⚠️
crates/katana/primitives/src/fee.rs 0.00% 6 Missing ⚠️
crates/katana/primitives/src/genesis/constant.rs 0.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2490      +/-   ##
==========================================
- Coverage   55.82%   55.76%   -0.06%     
==========================================
  Files         446      448       +2     
  Lines       57728    57854     +126     
==========================================
+ Hits        32225    32264      +39     
- Misses      25503    25590      +87     

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

Copy link
Member

@kariy kariy left a comment

Choose a reason for hiding this comment

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

we can just proxy them like we did for the /health endpoint here.

so based on the predefined paths we can just proxy them to the appropriate json rpc methods. eg /fee_token , we can add a new ProxyGetRequestLayer::new("/fee_token", "dev_feeToken")
and so on.

based on the ProxyGetRequest implementation, seems like it can only proxy GET request only. and will treat all POST as is.
what we could do is probably implement our own ProxyLayer that will proxy specific paths but for both GET and POST. Or perhaps for this PR we can just do for the GET requests only (ie /predeployed_accounts, /account_balance, /fee_token)

crates/katana/rpc/rpc/src/proxy_get_request.rs Outdated Show resolved Hide resolved
crates/katana/node/src/lib.rs Outdated Show resolved Hide resolved
Copy link
Member

@kariy kariy left a comment

Choose a reason for hiding this comment

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

ok i just realized that the list of devnet methods that i listed out in the pr desc are outdated.

some of them have been removed, we follow the new version:

https://github.com/0xSpaceShard/starknet-devnet-rs/blob/main/crates/starknet-devnet-server/src/server.rs#L25

crates/katana/rpc/rpc/src/dev.rs Outdated Show resolved Hide resolved
crates/katana/rpc/rpc/src/dev.rs Outdated Show resolved Hide resolved
@glihm glihm added katana This issue is related to Katana contributor labels Nov 7, 2024
@glihm glihm changed the title Modify DevApi trait with new endpoints feat(katana): modify DevApi trait with new endpoints Nov 14, 2024
@fabrobles92 fabrobles92 requested a review from kariy December 19, 2024 14:27
@glihm
Copy link
Collaborator

glihm commented Jan 3, 2025

Thank you @fabrobles92 for the rebase. You could check the scripts to make the sure linters are not complaining in the CI. 👍

@fabrobles92 fabrobles92 marked this pull request as ready for review January 4, 2025 05:11
Copy link

coderabbitai bot commented Jan 4, 2025

Walkthrough

The pull request introduces enhancements to the Katana devnet RPC functionality, focusing on adding new HTTP endpoints for account-related operations. The changes span multiple files across the primitives and RPC modules, implementing string parsing for price units, adding methods for account balance retrieval, and creating a proxy layer to handle HTTP GET requests for RPC methods.

Changes

File Change Summary
primitives/src/fee.rs Added FromStr trait implementation for PriceUnit enum
primitives/src/genesis/constant.rs Added get_erc20_address function to retrieve contract addresses
rpc/rpc-api/src/dev.rs Added account_balance and mint methods to DevApi trait
rpc/rpc/Cargo.toml Added multiple dependencies for RPC and async processing
rpc/rpc/src/dev.rs Implemented account_balance and mint methods for DevApi
rpc/rpc/src/lib.rs Added new proxy_get_request module and DevnetProxyLayer
rpc/rpc/src/proxy_get_request.rs Created middleware for proxying HTTP GET requests to RPC methods
rpc/rpc/src/transport/http.rs Added response handling module for HTTP responses
rpc/rpc/src/transport/mod.rs Added new http module

Assessment against linked issues

Objective Addressed Explanation
/account_balance (GET)
/mint (POST) Placeholder method added, but full implementation seems pending
/predeployed_accounts (GET) Not implemented in this PR
/fee_token (GET) Not implemented in this PR

Sequence Diagram

sequenceDiagram
    participant Client
    participant DevnetProxyLayer
    participant RpcServer
    participant DevApi

    Client->>DevnetProxyLayer: GET /account_balance
    DevnetProxyLayer->>RpcServer: Transform to RPC call
    RpcServer->>DevApi: account_balance method
    DevApi-->>RpcServer: Return account balance
    RpcServer-->>DevnetProxyLayer: RPC response
    DevnetProxyLayer-->>Client: HTTP response with balance
Loading

Ohayo, sensei! The PR looks like it's making solid progress towards exposing those devnet endpoints. While not all requested features are fully implemented, it's laying down a robust foundation for future expansions. Keep coding! 🚀


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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

Documentation and Community

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

Copy link

@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: 2

🧹 Nitpick comments (8)
crates/katana/rpc/rpc/src/proxy_get_request.rs (3)

25-34: Ohayo sensei! Gentle reminder about error handling in the constructor.

Currently, DevnetProxyLayer::new() unconditionally returns Ok(Self {}). Consider if there's any scenario where invalid config or environment might warrant returning an error. If none is expected, this is fine!


70-86: Ohayo sensei! Potential improvements for concurrency checks.

The Service implementation blocks on transformations and error handling within a single async flow. If future concurrency expansions are needed, ensure there's no shared mutable data that requires synchronization here.


96-116: Ohayo sensei! Mindful handling of fallback scenario.

When method.is_empty(), the code short-circuits to return the original response. Double-check that this behavior is consistent with other devnet endpoints. If you plan to support more GET endpoints, consider grouping them or returning a descriptive error.

crates/katana/rpc/rpc-api/src/dev.rs (1)

31-32: Ohayo sensei! Clarify mint method's purpose.

The mint method is empty. If it's intentionally left unimplemented, please add a doc comment explaining. Otherwise, you could remove it until it's ready or return an explicit unimplemented error.

crates/katana/rpc/rpc/src/transport/http.rs (1)

33-36: Ohayo sensei! Confirm success response body format.

ok_response returns the raw body as a string. If some calls need to wrap it in a JSON object (e.g., {"data": ...}), consider implementing a pattern to avoid confusion in the client.

crates/katana/rpc/rpc/src/lib.rs (1)

118-118: Ohayo sensei! Validate usage scope before layering.

DevnetProxyLayer is layered for all incoming requests. If certain requests need bypassing, consider conditionally applying the layer or scoping it specifically.

crates/katana/rpc/rpc/src/dev.rs (1)

118-120: Ohayo sensei! ‘mint’ method awaiting details.

This method is an empty stub. Confirm its usage in starknet-devnet and possibly clarify if it should produce minted tokens or remain unimplemented.

crates/katana/primitives/src/genesis/constant.rs (1)

122-129: Ohayo sensei! A small suggestion to simplify the contract address conversion.

Currently, you store erc20_contract_address as a ContractAddress, then you call ContractAddress::new(erc20_contract_address.into()). Since DEFAULT_ETH_FEE_TOKEN_ADDRESS and DEFAULT_STRK_FEE_TOKEN_ADDRESS are already ContractAddress, you can directly return them or return a cloned value without chaining the constructor.

For instance, you could do:

 pub fn get_erc20_address(unit: &PriceUnit) -> Result<ContractAddress, Error> {
     let erc20_contract_address = match unit {
         PriceUnit::Wei => DEFAULT_ETH_FEE_TOKEN_ADDRESS,
         PriceUnit::Fri => DEFAULT_STRK_FEE_TOKEN_ADDRESS,
     };

-    Ok(ContractAddress::new(erc20_contract_address.into()))
+    Ok(erc20_contract_address)
 }

This avoids allocating a new ContractAddress and keeps the code straightforward.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 38f68db and 17a53b5.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (9)
  • crates/katana/primitives/src/fee.rs (2 hunks)
  • crates/katana/primitives/src/genesis/constant.rs (2 hunks)
  • crates/katana/rpc/rpc-api/src/dev.rs (1 hunks)
  • crates/katana/rpc/rpc/Cargo.toml (2 hunks)
  • crates/katana/rpc/rpc/src/dev.rs (2 hunks)
  • crates/katana/rpc/rpc/src/lib.rs (2 hunks)
  • crates/katana/rpc/rpc/src/proxy_get_request.rs (1 hunks)
  • crates/katana/rpc/rpc/src/transport/http.rs (1 hunks)
  • crates/katana/rpc/rpc/src/transport/mod.rs (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • crates/katana/rpc/rpc/src/transport/mod.rs
🔇 Additional comments (7)
crates/katana/rpc/rpc/src/proxy_get_request.rs (1)

132-142: Ohayo sensei! Watch out for JSON parse failures.

In RpcPayload, only result is deserialized. If the JSON schema changes or result is missing, we reply with an internal error. You may consider logging partial parse results for debugging.

crates/katana/rpc/rpc-api/src/dev.rs (1)

28-29: Ohayo sensei! Validate input on account_balance.

While address is a string, consider if it can be validated directly in this trait and return an explicit error if invalid. Relying on the server impl to unwrap might lead to inconsistent error handling.

crates/katana/rpc/rpc/src/transport/http.rs (1)

1-16: Ohayo sensei! Kudos on the modular response approach.

internal_error() looks neat. If you foresee various error types, consider abstracting them. Right now, everything is InternalError.

crates/katana/rpc/rpc/src/lib.rs (1)

6-6: Ohayo sensei! Good use of layering.

Importing DevnetProxyLayer neatly organizes the proxied GET requests. Keep ensuring minimal coupling by exposing only essential public items from the module.

crates/katana/primitives/src/fee.rs (1)

34-43: Ohayo sensei! Looks great for straightforward string parsing.

If your usage scenario might involve different cases (e.g., "wei" or "Wei"), you could match them in a case-insensitive way. Otherwise, this is perfectly fine. Proceed as is if a strict match on "WEI" and "FRI" is desired.

crates/katana/rpc/rpc/Cargo.toml (2)

37-46: Ohayo sensei! These asynchronous and serde additions are good for the new devnet endpoints.

Just make sure no library remains unused and consider any potential overlap with existing features in the workspace. Everything else looks consistent. Nicely done!


10-12: Ohayo sensei! Verify the jsonrpsee and hyper versions for compatibility.

Double-check that these versions align with the rest of the workspace and that there are no known security advisories. This ensures a stable and secure dependency set.

✅ Verification successful

Ohayo sensei! The dependencies are compatible and secure.

Looking at the workspace dependencies in the root Cargo.toml:

  • hyper is set to workspace version "0.14.27" which is compatible with jsonrpsee's requirements
  • jsonrpsee dependencies in the RPC crate are pinned to version "0.16.3" which is a stable release

The versions are consistent across the workspace and there are no conflicting version requirements.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Checking cargo tree for potential conflicts
cargo tree -p jsonrpsee-core
cargo tree -p hyper

Length of output: 244


Script:

#!/bin/bash
# Let's check for jsonrpsee and hyper dependencies across the workspace
fd Cargo.toml --exec grep -l "jsonrpsee\|hyper"

# Then examine the content of these files
fd Cargo.toml --exec sh -c 'echo "=== {} ==="; cat {}'

# Also check workspace dependencies in the root Cargo.toml
if [ -f "Cargo.toml" ]; then
    echo "=== Root Cargo.toml ==="
    cat Cargo.toml
fi

Length of output: 71528

Comment on lines +151 to +162
fn get_account_balance(query: Option<&str>) -> (Box<JsonRawValue>, std::string::String) {
let default = String::new();

let query = query.unwrap_or(&default);
let params: HashMap<_, _> = form_urlencoded::parse(query.as_bytes()).into_owned().collect();

let address = params.get("contract_address").unwrap_or(&default);
let unit = params.get("unit").unwrap_or(&default);

let json_string = format!(r#"{{"address":"{}", "unit":"{}"}}"#, address, unit);
(JsonRawValue::from_string(json_string).unwrap(), "dev_accountBalance".to_string())
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ohayo sensei! Suggest graceful error handling for query extraction.

get_account_balance uses unwrap() for from_string. A malformed query string would panic. Consider returning a user-friendly error or defaulting gracefully.

 fn get_account_balance(query: Option<&str>) -> (Box<JsonRawValue>, std::string::String) {
     ...
-    (JsonRawValue::from_string(json_string).unwrap(), "dev_accountBalance".to_string())
+    let raw_value = match JsonRawValue::from_string(json_string) {
+        Ok(val) => val,
+        Err(_) => {
+            // fallback or error handling
+            JsonRawValue::from_string(r#"{}"#.to_string()).unwrap()
+        }
+    };
+    (raw_value, "dev_accountBalance".to_string())
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +103 to +116
async fn account_balance(&self, address: String, unit: String) -> Result<u128, Error> {
let account_address: ContractAddress = Felt::from_str(address.as_str()).unwrap().into();
let unit = PriceUnit::from_str(unit.to_uppercase().as_str()).unwrap_or(PriceUnit::Wei);

let erc20_address =
get_erc20_address(&unit).map_err(|_| http::response::internal_error()).unwrap();

let provider = self.backend.blockchain.provider();
let state = provider.latest().unwrap();
let storage_slot = get_fee_token_balance_base_storage_address(account_address);
let balance_felt = state.storage(erc20_address, storage_slot).unwrap().unwrap();
let balance: u128 = balance_felt.to_string().parse().unwrap();
Ok(balance)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Ohayo sensei! Avoid panics on invalid address or unit.

Felt::from_str(address.as_str()).unwrap() and PriceUnit::from_str(...) can cause runtime panics if the user sends malformed data. Returning a structured error might be safer.

- let account_address: ContractAddress = Felt::from_str(address.as_str()).unwrap().into();
- let unit = PriceUnit::from_str(unit.to_uppercase().as_str()).unwrap_or(PriceUnit::Wei);
+ let account_address: ContractAddress = Felt::from_str(address.as_str())
+     .map_err(|_| DevApiError::InvalidAddress(address.clone()))?
+     .into();
+ let unit = PriceUnit::from_str(unit.to_uppercase().as_str())
+     .map_err(|_| DevApiError::InvalidPriceUnit(unit.clone()))?;
📝 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
async fn account_balance(&self, address: String, unit: String) -> Result<u128, Error> {
let account_address: ContractAddress = Felt::from_str(address.as_str()).unwrap().into();
let unit = PriceUnit::from_str(unit.to_uppercase().as_str()).unwrap_or(PriceUnit::Wei);
let erc20_address =
get_erc20_address(&unit).map_err(|_| http::response::internal_error()).unwrap();
let provider = self.backend.blockchain.provider();
let state = provider.latest().unwrap();
let storage_slot = get_fee_token_balance_base_storage_address(account_address);
let balance_felt = state.storage(erc20_address, storage_slot).unwrap().unwrap();
let balance: u128 = balance_felt.to_string().parse().unwrap();
Ok(balance)
}
async fn account_balance(&self, address: String, unit: String) -> Result<u128, Error> {
let account_address: ContractAddress = Felt::from_str(address.as_str())
.map_err(|_| DevApiError::InvalidAddress(address.clone()))?
.into();
let unit = PriceUnit::from_str(unit.to_uppercase().as_str())
.map_err(|_| DevApiError::InvalidPriceUnit(unit.clone()))?;
let erc20_address =
get_erc20_address(&unit).map_err(|_| http::response::internal_error()).unwrap();
let provider = self.backend.blockchain.provider();
let state = provider.latest().unwrap();
let storage_slot = get_fee_token_balance_base_storage_address(account_address);
let balance_felt = state.storage(erc20_address, storage_slot).unwrap().unwrap();
let balance: u128 = balance_felt.to_string().parse().unwrap();
Ok(balance)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contributor katana This issue is related to Katana
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Expose devnet endpoints
3 participants