Skip to content

feat: per-chain RPC config + Polygon default RPC fix - #11

Merged
junjieit merged 4 commits into
mainfrom
feat/per-chain-rpc-config
Jul 29, 2026
Merged

feat: per-chain RPC config + Polygon default RPC fix#11
junjieit merged 4 commits into
mainfrom
feat/per-chain-rpc-config

Conversation

@junjieit

Copy link
Copy Markdown
Collaborator

What & why

The only way to point ChainPilot at a custom JSON-RPC endpoint was the global --rpc-url flag: CLI-only, applies to every chain at once, and not persistable. This PR lets users persist a per-chain RPC URL via the config.env file and the config subcommand, keyed by chain id.

Precedence: --rpc-url flag > configured RPC_URL_<chainId> > chain built-in default. The flag keeps winning for all chains (unchanged).

Feature (feat: commit)

  • AppConfig gains rpc_overrides, populated from RPC_URL_<chainId> env vars (persisted in config.env, already loaded at startup). rpc_url_for_chain consults it below the flag override.
  • config subcommand rpc_url support:
    • config set rpc_url <url> → active chain (--chain-id, default 1)
    • config set rpc_url.56 <url> → chain 56
    • config set rpc_url '{"1":"…","56":"…"}' → JSON map, merges (unlisted chains untouched)
    • config get rpc_url → all configured chains; rpc_url.56 / --chain-id 56 → one chain
    • config unset rpc_url.56 → one chain; bare config unset rpc_url → all
    • config list appends rpc_url.<id> rows
  • URLs validated as http(s); bad chain-id suffixes rejected at set time.
  • Docs (README.md, SKILL.md) and --help updated.

Fix (fix: commit)

polygon-rpc.com now returns "API key disabled / tenant disabled" (403), and the other listed fallbacks are deprecated. Swapped to PublicNode (matching the repo convention) with a 1rpc.io fallback — both verified returning chainId 0x89.

Testing

  • 183 unit tests pass (added resolution + subcommand tests); no new clippy warnings.
  • Verified end-to-end: a configured RPC_URL_1 is actually used by an on-chain command and --rpc-url still overrides it; Polygon on-chain read succeeds through the new default RPC.

🤖 Generated with Claude Code

junjieit and others added 2 commits July 29, 2026 18:03
Persist a custom JSON-RPC endpoint per chain, keyed by chain id, instead of
only the ephemeral `--rpc-url` flag. Precedence:
`--rpc-url` flag > configured RPC_URL_<chainId> > chain built-in default.

- AppConfig gains `rpc_overrides`, populated from RPC_URL_<chainId> env vars
  (persisted in config.env); rpc_url_for_chain consults it below the flag.
- `config set/get/unset rpc_url[.<chainId>]` with active-chain default,
  `.` suffix targeting, and a JSON `{chainId: url}` map that merges.
- URLs validated as http(s); bad chain-id suffixes rejected at set time.
- Docs + `--help` updated; new unit tests for resolution and the subcommand.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
polygon-rpc.com now returns "API key disabled / tenant disabled" (403), and
the other listed fallbacks are deprecated. Switch to PublicNode (matching the
repo convention) with a 1rpc.io fallback; both verified returning chainId 0x89.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@junjieit
junjieit force-pushed the feat/per-chain-rpc-config branch from a8de11d to ae3d971 Compare July 29, 2026 10:10
@github-actions

Copy link
Copy Markdown
  • P1 – Config inspection reports the wrong effective RPC configuration. src/commands/config.rs:120 builds RPC listings only from config.env, so RPC_URL_56=https://... chainpilot config get rpc_url and config list omit an override that the application actually uses. Additionally, the single-chain path at line 353 checks the file before the environment, contrary to the documented environment-over-file precedence. Use the effective AppConfig::rpc_overrides map, or merge environment and file values with environment taking priority.

  • P2 – Chinese README is out of sync. The new per-chain RPC workflow is documented in README.md:151, but README_CN.md:66 still omits RPC_URL_<chainId> and line 141 says unsupported chains require --rpc-url. Add the equivalent configuration table entry, precedence rules, and config set/get/unset rpc_url examples.

Project-specific checks: no new direct stdout printing; new output uses print_output. Clap help accurately describes the new key forms and scopes. skills/chainpilot/SKILL.md was updated consistently; evm-wallet is unaffected.

Tests could not complete because crates.io DNS resolution is unavailable in the environment.

Address PR review:

P1 — `config get rpc_url` / `config list` read only config.env, so an
env-only `RPC_URL_<chainId>` override the app actually uses was omitted, and
the single-chain path checked the file before the environment (contrary to the
documented env-over-file precedence). Inspection now reports the effective
value: env vars win over the file and env-only overrides are included, for the
RPC map and for the API-key rows alike (new `effective_simple_value` /
`effective_rpc_for` / `effective_rpc_overrides` helpers).

P2 — README_CN.md was out of sync: add `RPC_URL_<chainId>` to the env list and
config table, the per-chain RPC precedence + `config set/get/unset rpc_url`
examples, and the unsupported-chain note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
  • P2 – Bare RPC scope is documented inconsistently. src/commands/config.rs:378 and src/commands/config.rs:474 make bare config get/unset rpc_url target one chain whenever chain_id_overridden is true, including when CHAIN_ID comes from the environment. However, the clap text at src/cli/config.rs:35 mentions only explicit --chain-id, while the README examples at README.md:167 and README_CN.md:161 state unconditionally that bare get/unset operates on all chains. This is especially risky for unset, since users may believe all overrides were removed. Either make bare operations consistently mean “all chains,” or document both --chain-id and CHAIN_ID as changing the scope in clap and both READMEs.

Project-specific checks:

  • Output convention: complete; all new command output uses print_output, with no new direct stdout printing.
  • Help docs: RPC syntax is covered, apart from the scope mismatch above.
  • Skills: skills/chainpilot/SKILL.md was updated and accurately covers the workflow.
  • Multi-language README: both files contain corresponding feature updates, apart from the shared behavior mismatch above.
  • Tests could not be run because Cargo attempted to access index.crates.io, which is unavailable in this environment.

Address PR review (P2): bare get/unset previously narrowed to the active chain
whenever `chain_id_overridden` was set — including from an ambient `CHAIN_ID`
env var — while the READMEs stated bare = all chains and the clap/SKILL text
mentioned only `--chain-id`. For the destructive `unset`, an ambient CHAIN_ID
would silently remove just one override instead of all.

Bare `rpc_url` now always targets all chains for get/unset, regardless of
`--chain-id` / `CHAIN_ID`; use `rpc_url.<chainId>` to target one. `set` keeps
its active-chain default (non-destructive, echoes the chain it wrote). Docs
(clap, both READMEs, SKILL) updated to state this precisely; added a regression
test that bare unset clears all even when the active chain id is set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
  • P2 src/commands/config.rs:501: config get/list includes environment-only RPC_URL_<id> values, but config unset rpc_url[.<id>] examines only config.env. For example, with RPC_URL_56=x, get rpc_url lists chain 56 while unset rpc_url responds “No RPC endpoints were set.” If both sources define it, unset reports success although the environment override remains effective. Make the status explicitly say only persisted entries were removed and that an environment override remains; update README/help/skill wording from “all configured chains” to “all persisted overrides.”

Project-specific checks:

  • Output convention: complete; no new direct println!/print!, and command results use print_output.
  • Help docs: otherwise accurate and complete.
  • Skills: skills/chainpilot/SKILL.md covers the new workflow, subject to the wording issue above.
  • READMEs: English and Chinese updates are synchronized, subject to the same wording issue.
  • Tests could not run because dependencies were unavailable locally and crates.io network access was blocked. git diff --check passed.

@junjieit
junjieit merged commit a966acc into main Jul 29, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant