feat(rpc): qn rpc — JSON-RPC calls with managed or custom endpoints#52
Merged
Conversation
Restructure `qn rpc` into explicit subcommands and add a way to target a custom RPC endpoint instead of the account's Tooling Access endpoint. - `qn rpc call <method> [params]` replaces the bare `qn rpc <method>` form, leaving room for future subcommands. Bare `qn rpc` prints help. - `qn rpc list-networks` (alias `ls`) replaces the `--list-networks` flag. - `qn rpc call --endpoint-url <URL>` sends a call to a fully-formed HTTP URL. The URL is self-authenticating: no session token is minted or attached, and the Tooling Access enable/probe recovery is bypassed entirely. - `[rpc] endpoint_url` in config sets a client-wide default; a per-call `--endpoint-url` overrides it. - `--endpoint-url` and `--network` are mutually exclusive (a custom URL is not multichain-routed), enforced at parse time. An unknown `--network` key now surfaces a CLI error pointing at `qn rpc list-networks` instead of the SDK's internal wording. Consumes the published quicknode-sdk 0.7 (4-arg `rpc.call` + `RpcConfig.endpoint_url`). Docs (README, agent context) and tests updated; rpc.rs test count 18.
Add `--params-file <PATH>` / `-f` to `qn rpc call`, mirroring `qn sql query --file`: read the JSON-RPC params from a file, or from stdin when the path is `-`. Mutually exclusive with the positional params argument (clap ArgGroup). The positional params and its `-` stdin form are unchanged. A missing file surfaces "could not read params file '<path>': ...". Tests: file happy path, missing-file error, positional/--params-file conflict.
Disabling Tooling Access cuts off blockchain access for all Quicknode developer tooling on the account, so route it through confirm_mild (Severity::Mild): --yes skips, TTY prompts, non-TTY without --yes returns exit 5. Prompt names the blast radius. Also set explicit value_name on 'qn rpc call' positionals (METHOD, PARAMS) per the CLI value-name convention. Tests: disable now needs --yes (exit 0); no --yes non-TTY returns exit 5 and reaches the mock zero times.
ErikTech
approved these changes
Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
qn rpc— make JSON-RPC calls straight from the terminal, with no endpoint to provision. The CLI mints and refreshes a short-lived session token for you against the account's Tooling Access endpoint, so a bareqn rpc call eth_blockNumberjust works after a one-time enable. You can also point calls at your own fully-formed RPC URL (per-call or via config) when you don't want the managed endpoint.The surface is two subcommands:
qn rpc call <method> [params]— the JSON-RPC callqn rpc list-networks(aliasls) — discover the multichain endpoint's network keysThe end-user experience
First run
In scripts/agents, skip the prompt with
--yes; without it in a non-TTY you get an actionable error (exit 5) and nothing is changed:Making calls
Inline params,
--params-file, and stdin are mutually exclusive ways to supply the same thing; the positional argument and--params-filecan't be combined.Results are schemaless JSON, so
-o json(the default when piped) /yaml/tooncontrol the shape;table/mdfall back to JSON.Multichain
The endpoint serves many chains. List the keys, then target one:
$ qn rpc list-networks btc ethereum-mainnet polygon solana-mainnet $ qn rpc call getSlot --network solana-mainnet "301234567"Network keys are the endpoint's own
multichain_urlskeys and can differ from chain slugs (e.g.polygon, notmatic). An unknown key points you at the discovery command:The network map is cached in
~/.config/qn/networks.toml(per endpoint, 24h TTL), so--networkcalls reuse it.Custom endpoint URL
Send a call to a fully-formed HTTP URL instead of the managed endpoint. The URL is treated as self-authenticating: no session token is minted or attached.
# Per call qn rpc call eth_blockNumber --endpoint-url https://my-endpoint.example/rpcSet a client-wide default in
~/.config/qn/config.tomlso every call uses it without the flag:A per-call
--endpoint-urlstill overrides the config default.--endpoint-urland--networkare mutually exclusive (a custom URL is not multichain-routed):Managing Tooling Access directly
How it works
~/.config/qn/tokens.toml(0600, scoped to the API key by a SHA-256 fingerprint), so subsequent calls skip the mint round trip while it's valid. Switching keys transparently invalidates a stale token.--retries(transient 429/5xx/timeout backoff) on both lanes. Mutations (enable) never retry.--yesto auto-enable, actionable error otherwise), then retries.SDK
Consumes the published
quicknode-sdk0.7 (adds the customendpoint_urlsupport torpc.callandRpcConfig).Testing
tests/rpc.rs: 21 tests — managed-lane happy paths (seeded token, mint-then-call, cache write-back), auto-enable flows (with/without--yes, connect-failure recovery), multichain routing + list, the custom-URL set (routes without minting, config default, flag-overrides-config, failure bypasses enable recovery, URL validation,--endpoint-url/--networkconflict, unknown-network hint), and params-file input (file happy path, missing-file error, positional/--params-fileconflict).tests/tooling_access.rs: status/enable/disable.[rpc]round-trip andvalidate_endpoint_urlunit tests.cargo test,cargo clippy --all-targets -- -D warnings, andcargo fmt --checkall green.