Skip to content

Add proxy routing mode for blockchain APIs - #352

Open
wbssbw wants to merge 4 commits into
mainfrom
blockchain-enable-rpc-proxies
Open

Add proxy routing mode for blockchain APIs#352
wbssbw wants to merge 4 commits into
mainfrom
blockchain-enable-rpc-proxies

Conversation

@wbssbw

@wbssbw wbssbw commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Introduces a RoutingMode enum for the blockchain RPC client that supports two mutually exclusive routing strategies: per-chain node pools (the existing behavior) and a single proxy endpoint. In proxy mode, every chain routes through one URL with the chain identifier appended as a path segment, so arbitrary chain IDs work without per-chain configuration.

Changes

  • Code
    • Added RoutingMode<C, V> enum in runtime/plaid/src/apis/blockchain/common/mod.rs with Nodes and Proxy variants, deserialized via a type tag.
    • Replaced BlockchainClient.node_selector and max_retries fields with a single routing field.
    • Removed get_node_selector; execute_rpc_call now dispatches on routing mode.
    • Proxy mode performs a single attempt against the proxy URL (retries are expected to be handled by the proxy); node mode retains retry-across-nodes behavior with failure deprioritization.
    • Generalized deserialize_chains to be generic over value type and added a deserialize_url helper.
    • Updated EVM and Solana call sites to drop the explicit node-selector lookup.
    • Documented the sticky round-robin behavior in node_selection.rs.
  • Config
    • Updated runtime/plaid/resources/jrp_config/apis.toml to the new routing schema and added commented proxy-mode examples for EVM and Solana.

Rationale

Proxy mode removes the need to enumerate every chain and its node pool, which is impractical when supporting arbitrary chain identifiers. Keeping node mode as the default preserves existing behavior and avoids forcing a migration on users who manage their own node pools.

Breaking Changes

  • The config schema for blockchain families changes: chains and max_retries are replaced by a routing block with type = "nodes" (per-chain chains and max_retries nested inside) or type = "proxy" with a url. Existing configs must be updated to the new structure.

Copilot AI lite review requested due to automatic review settings August 19, 2026 19:35
@wbssbw
wbssbw marked this pull request as ready for review August 19, 2026 19:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a configurable routing strategy to the blockchain RPC client so chain families can either use the existing per-chain node pools or route all calls through a single proxy endpoint (with the chain identifier appended to the URL).

Changes:

  • Introduces RoutingMode<C, V> and replaces BlockchainClient’s per-chain selector + max_retries fields with a single routing field.
  • Updates EVM and Solana client call sites to use the new execute_rpc_call(identifier, ...) API.
  • Updates node-selection documentation and provides updated TOML examples for the new routing schema.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
runtime/plaid/src/apis/blockchain/common/mod.rs Adds RoutingMode, updates config schema, and refactors execute_rpc_call to dispatch based on routing mode.
runtime/plaid/src/apis/blockchain/evm/mod.rs Updates EVM RPC methods to call the new execute_rpc_call signature.
runtime/plaid/src/apis/blockchain/solana/mod.rs Updates Solana RPC methods to call the new execute_rpc_call signature and adjusts tests for the new config shape.
runtime/plaid/src/apis/blockchain/common/node_selection.rs Documents sticky RoundRobin behavior (advance index only on failure).
runtime/plaid/resources/jrp_config/apis.toml Updates example configuration to the new routing schema and adds proxy-mode examples.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread runtime/plaid/src/apis/blockchain/common/mod.rs
Comment thread runtime/plaid/src/apis/blockchain/common/mod.rs
Comment thread runtime/plaid/resources/jrp_config/apis.toml
Comment thread runtime/plaid/resources/jrp_config/apis.toml
Comment thread runtime/plaid/src/apis/blockchain/solana/mod.rs Outdated
Comment thread runtime/plaid/src/apis/blockchain/solana/mod.rs Outdated
Copilot AI review requested due to automatic review settings August 20, 2026 14:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

runtime/plaid/src/apis/blockchain/common/mod.rs:260

  • Proxy routing builds the RPC URL via string concatenation (format!("{}/{identifier}", url.as_str().trim_end_matches('/'))), which can produce invalid URLs (e.g., if the base URL contains a query/fragment) and does not percent-encode the identifier as a path segment. Prefer using Url APIs to append a path segment safely.
            RoutingMode::Proxy { url } => {
                // Append the chain identifier as a path segment
                let rpc = format!("{}/{identifier}", url.as_str().trim_end_matches('/'));
                trace!(
                    "RPC call [{}] via proxy on behalf of module [{module}]",

Copilot AI review requested due to automatic review settings August 20, 2026 21:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (2)

runtime/plaid/src/apis/blockchain/common/mod.rs:259

  • Building the proxy RPC URL via string concatenation can produce an invalid endpoint when the base URL contains a query/fragment (e.g. https://proxy?token=x becomes https://proxy?token=x/<id>), and it also skips percent-encoding the identifier as a path segment. Use Url path segment manipulation instead so the identifier is appended in the path correctly.
            RoutingMode::Proxy { url } => {
                // Append the chain identifier as a path segment
                let rpc = format!("{}/{identifier}", url.as_str().trim_end_matches('/'));
                trace!(

runtime/plaid/src/apis/blockchain/common/mod.rs:294

  • If max_retries is configured as 0, the retry loop never runs and the call fails immediately with AllNodesFailed without attempting any node. Clamp to at least 1 attempt (or reject 0 at config load) to avoid this surprising behavior.
                let mut last_error = BlockchainError::AllNodesFailed;
                for attempt in 1..=*max_retries {
                    let Some(node) = selector.select_node() else {

Copilot AI review requested due to automatic review settings August 21, 2026 02:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (1)

runtime/plaid/src/apis/blockchain/common/mod.rs:273

  • Proxy routing builds the RPC URL via string concatenation (format!("{}/{identifier}", url.as_str().trim_end_matches('/'))), which does not percent-encode the identifier as a path segment and will also produce an invalid URL if the configured base URL includes a query or fragment (the identifier gets appended after ?…). Since url is already a Url, construct the request URL by mutating path segments on a cloned Url and pass rpc_url.as_str() to the request executor.
            RoutingMode::Proxy { url } => {
                // Append the chain identifier as a path segment
                let rpc = format!("{}/{identifier}", url.as_str().trim_end_matches('/'));
                trace!(
                    "RPC call [{}] via proxy on behalf of module [{module}]",

@wbssbw wbssbw added breaking For changes that break existing configurations or modules where recompilation will not fix it API Relating to the API subsystems AI Prompted The code was primarily generated via prompts. Using AI code complete, does not count. labels Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Prompted The code was primarily generated via prompts. Using AI code complete, does not count. API Relating to the API subsystems breaking For changes that break existing configurations or modules where recompilation will not fix it

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants