diff --git a/plugins/build-web3/skills/build-web3/references/quicknode/cli-reference.md b/plugins/build-web3/skills/build-web3/references/quicknode/cli-reference.md index 363db2e..8a09833 100644 --- a/plugins/build-web3/skills/build-web3/references/quicknode/cli-reference.md +++ b/plugins/build-web3/skills/build-web3/references/quicknode/cli-reference.md @@ -50,6 +50,8 @@ qn agent context qn agent context -o json ``` +**Test:** `qn agent context` with `QN_API_KEY` empty — 370 lines of Markdown titled `# qn — usage guide for agents`, with 9 `##` sections. It succeeds with no key, which is how you confirm it needs no authentication + ## Output Formats Set output with `--format` or `-o`. @@ -62,7 +64,11 @@ Set output with `--format` or `-o`. | `md` | Markdown tables for issues and docs | | `toon` | Compact LLM-oriented structured output | -Examples: +With `--format` unset the CLI reads `[output] format` from the config file, then defaults to `table` on a TTY and `json` when stdout is piped. `--wide`/`-w` affects only `table` and `md`. + +**The piped default is not universal.** `qn rpc list-networks` prints a bare +newline-separated list of slugs even when piped, with no JSON. A script that +pipes it and parses JSON fails. Pass `-o json` explicitly for that command. ```bash qn endpoint list --format json @@ -70,6 +76,20 @@ qn usage summary --from 7d -o yaml qn endpoint list --wide ``` +**Test:** `qn endpoint list | head -c 1`, `qn chain list | head -c 1`, and `qn kv set list | head -c 1` all print `{`; `qn rpc list-networks | head -c 1` prints `0`, the first character of `0g-galileo`. The piped default holds for three of these four commands and not for the fourth + +## Exit Codes + +| Code | Meaning | +|------|---------| +| `0` | Success | +| `1` | Usage error — bad flag, missing argument, unparseable value | +| `2` | API or request error — the server rejected the call (also plan-gated features, and drawdown credit exhaustion) | +| `3` | Indeterminate outcome on a paid call — the request was sent but the response was lost; the wallet may already be charged | +| `4` | No credentials — no `--api-key`, no `--config-file`, no `~/.config/qn/config.toml` | +| `5` | Gated command refused — a destructive command ran in a non-TTY without `--yes`, before any request was sent | +| `130` | Interrupted (SIGINT) | + ## Command Groups ### Auth @@ -106,17 +126,24 @@ qn auth login qn rpc call eth_getBlockByNumber '["latest", false]' --network base-mainnet ``` +With `-o json` the CLI prints the JSON-RPC `result` **unwrapped**. There is no +`jsonrpc`, `id`, or `result` field to read past. + +**Test:** `base-mainnet` · block `latest` — `-o json` prints the block object itself at the top level, keyed `baseFeePerGas` through `withdrawalsRoot`, with no `jsonrpc`, `id`, or `result` wrapper; `transactions` holds hashes, not objects, because the second parameter is `false` + Params: positional (JSON array), by name (JSON object), from a file, or from stdin. ```bash qn rpc call eth_blockNumber -qn rpc call eth_getBalance '["0xabc...", "latest"]' +qn rpc call eth_getBalance '["0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8", "latest"]' qn rpc call getSlot --network solana-mainnet qn rpc call eth_call --params-file params.json -echo '[...]' | qn rpc call eth_call - +echo '[{"to": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "data": "0x18160ddd"}, "latest"]' | qn rpc call eth_call - cat params.json | qn rpc call eth_call -f - ``` +**Test:** `ethereum-mainnet` · block `latest` — `eth_getBalance` returns a hex quantity, and the piped `eth_call` returns USDC `totalSupply()` as one 32-byte hex word + `--network ` selects a network on the multichain endpoint (e.g. `base-mainnet`, `solana-mainnet`, `polygon`, `btc`). Omit it for the default network. `qn rpc list-networks` (alias `ls`) lists available keys — no RPC call made. ```bash @@ -124,6 +151,8 @@ qn rpc list-networks qn rpc list-networks -o json ``` +**Test:** `qn rpc list-networks` — one network key per line, sorted, `0g-galileo` first and `zora-mainnet` last (132 keys on 2026-09-04; the count grows, so do not gate on it). With `-o json` the payload is `{"networks": [...]}`. It is **not** the `data` envelope the other list commands use, so `.data` is `undefined` + `--endpoint-url ` sends the call to a self-authenticating URL instead of the Tooling Access endpoint, overriding `[rpc] endpoint_url` in `~/.config/qn/config.toml`. Mutually exclusive with `--network`. First-run `qn rpc call` prompts `[y/N]` to enable Tooling Access if it isn't provisioned yet. Pass `-y`/`--yes` to auto-confirm non-interactively. @@ -132,6 +161,8 @@ First-run `qn rpc call` prompts `[y/N]` to enable Tooling Access if it isn't pro qn rpc call eth_blockNumber --network base-mainnet -y ``` +**Test:** `base-mainnet` · block `latest` — returns a bare JSON string such as `"0x308471d"`, not an object. `-y` exits `0` and prompts nothing when Tooling Access is already enabled, so it is safe to pass unconditionally in a script + ### Paid RPC (x402 and MPP) Requires CLI v0.6.0+. `qn rpc call` can pay for a call with stablecoins through the x402 or MPP gateway instead of using the account's API key. This lane requires no Quicknode account, API key, login, Tooling Access, or provisioned endpoint — only a funded local wallet. @@ -174,7 +205,9 @@ qn rpc mpp supported-networks qn rpc mpp supported-payments ``` -Use a slug from `supported-networks` as `--network`. Use a row from `supported-payments` — it returns the payment network, asset symbol, and token address — as `--payment-network` and `--payment-asset`. Query these instead of hardcoding a network or asset list. +Use a slug from `supported-networks` as `--network`. Use a row from `supported-payments` as `--payment-network` and `--payment-asset`. Query these instead of hardcoding a network or asset list. + +Rows carry `network` and `address`; `asset` is optional. `network` is a slug (`base-sepolia`) or a raw CAIP-2 id (`eip155:1952`). `--payment-asset` accepts a symbol or a contract address/mint. The query network and the payment network are independent. `--network ethereum-mainnet` with `--payment-network base-sepolia` pays on Base Sepolia for an Ethereum Mainnet read. @@ -327,6 +360,8 @@ qn endpoint log-details qn endpoint metrics --metric method_calls_over_time --period day ``` +On plans that do not support logging, they exit `2` reporting `unauthorized. Check your API key`; `-v` shows the details. + Commands that create, update, pause, resume, archive, enable or disable multichain, or change endpoint security/rate limits mutate endpoint state. ```bash @@ -439,6 +474,14 @@ qn stream test-filter \ --filter-file filter.js ``` +**Test:** `ethereum-mainnet` · block `17811625` — `result` is a JSON string holding the filter's return value, and `logs` is `[]` + +`test-filter` prints `{ "result": ..., "logs": [] }`, where `result` is the filter's return value as a JSON-encoded string, not an object. + +A filter that calls `console.log` makes the command fail with `Error: unexpected response shape from API.` and exit `1`. The request itself succeeds — the API returns HTTP `201` with each log entry as a `{ "level", "message" }` object, which the client decodes as a string and rejects, so `logs` only ever renders as `[]`. Filters run through the CLI or the SDK must not call `console.log`. + +The filter file exports `main(stream)`. For the `block` dataset `stream.data` is an array of blocks, one per batch entry. + Create and lifecycle commands change Stream state and may prompt: ```bash @@ -469,9 +512,11 @@ qn webhook create \ --url https://example.com/webhook \ --compression none \ --template evm-wallet \ - --wallet 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 + --wallet 0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8 ``` +Pass `--wallet` once per address. `--wallets-list-name ` is the alternative: it reads the addresses from a saved Key-Value Store list instead. + Webhook lifecycle and update commands: ```bash @@ -496,7 +541,7 @@ qn kv set delete mykey qn kv set bulk --add threshold=750000 --delete old_threshold ``` -Lists store ordered values under one key: +Lists store multiple values under one key. `qn kv list get` returns items sorted lexicographically, not in insertion order: ```bash qn kv list list @@ -509,6 +554,11 @@ qn kv list update allowlist --add 0x456 --remove 0xabc qn kv list delete allowlist ``` +Every `delete` needs `--yes` when no terminal is attached. Without it the command +exits non-zero and deletes nothing. + +**Test:** `qn kv set list` — `data` is an **array** of `{key, value}`; `qn kv list list` — `data` is an **object** with a `keys` array. The two commands do not share a response shape + ### SQL Explorer ```bash @@ -519,6 +569,8 @@ qn sql query --file query.sql --cluster-id hyperliquid-core-mainnet qn sql query --file - --cluster-id hyperliquid-core-mainnet ``` +`qn sql query` costs API credits on every call; `qn sql schema` is free. + ### Account Operations ```bash @@ -536,7 +588,16 @@ qn billing payments qn completions zsh ``` -`qn chain credits ` returns the per-method API credit costs for that chain, using the same chain slugs returned by `qn chain list`. Use it when an agent needs account-aware credit costs instead of hardcoding method multipliers. +`qn chain credits ` returns the per-method API credit costs for that chain. Use it when an agent needs account-aware credit costs. + +The CLI uses three chain vocabularies: + +| Where | Vocabulary | Examples | +|-------|-----------|----------| +| `qn chain list` | short slugs | `eth`, `matic`, `sol`, `btc` | +| `qn chain credits ` | accepts either the short slug or the long name | `eth` or `ethereum`, `sol` or `solana` | +| `qn endpoint create --chain` | long names | `ethereum`, `solana` | +| `qn rpc call --network` / `qn rpc list-networks` | network keys | `ethereum-mainnet`, `base-mainnet`, `solana-mainnet`, `polygon`, `btc` | ## Confirmation Behavior diff --git a/plugins/build-web3/skills/build-web3/references/quicknode/sdk-reference.md b/plugins/build-web3/skills/build-web3/references/quicknode/sdk-reference.md index c984ded..752655c 100644 --- a/plugins/build-web3/skills/build-web3/references/quicknode/sdk-reference.md +++ b/plugins/build-web3/skills/build-web3/references/quicknode/sdk-reference.md @@ -87,7 +87,10 @@ if (!status.enabled) { // params defaults to []; pass an array (positional) or object (by name). const blockNumber = await qn.rpc.call("eth_blockNumber"); -const balance = await qn.rpc.call("eth_getBalance", ["0xabc...", "latest"]); +const balance = await qn.rpc.call("eth_getBalance", [ + "0xBE0eB53F46cd790Cd13851d5EFf43D12404d33E8", + "latest", +]); // Multichain: seed the network map from admin.getEndpointUrls, then select // a network by its multichain_urls key as the 3rd argument. @@ -124,6 +127,8 @@ try { // await qn.admin.disableToolingAccess(); ``` +**Test:** `ethereum-mainnet` · block `latest` — `eth_getBalance` on that address returns a hex quantity; passing the truncated placeholder `0xabc...` instead throws `RpcError` with `code === -32602` + ### Account Info and API Credits ```typescript @@ -140,7 +145,9 @@ for (const row of credits.data.slice(0, 5)) { } ``` -`accountInfo()` calls the Admin API account-info endpoint and returns details such as account id, name, creation timestamp, billing version, and current subscription. `getApiCredits(chain)` calls the per-chain API credits endpoint and returns `{ method, credits }` rows for the supplied chain slug. Use `listChains()` to discover valid chain slugs. +`accountInfo()` calls the Admin API account-info endpoint and returns details such as account id, name, creation timestamp, billing version, and current subscription. `getApiCredits(chain)` calls the per-chain API credits endpoint and returns `{ method, credits }` rows for the supplied chain. + +`listChains()` returns short slugs (`eth`, `matic`, `sol`). `getApiCredits` accepts either the slug or the long name. The `rpc` client uses a third vocabulary, network keys such as `ethereum-mainnet`. ### Streams @@ -165,9 +172,21 @@ const test = await qn.streams.testFilter({ filterFunction, }); -console.log({ streams: streams.pageInfo.total, enabled: enabled.total, result: test.result }); +// test.result is a JSON-encoded string. +const filtered = JSON.parse(test.result); + +console.log({ + streams: streams.pageInfo.total, + enabled: enabled.total, + filtered, + logs: test.logs, +}); ``` +**Test:** `ethereum-mainnet` · block `17811625` — `typeof test.result === "string"` and `test.logs` is `[]`; a filter calling `console.log` throws `DecodeError` instead + +`testFilter` returns `{ result: string, logs: string[] }`, where `result` is the filter's output serialized as JSON. A filter that calls `console.log` makes `testFilter` throw `DecodeError`: the API returns each log entry as an object and the client decodes `logs` as strings, so `logs` only ever resolves to `[]`. + ### Webhooks ```typescript @@ -199,6 +218,8 @@ if (sets.data.length > 0) { console.log({ sets: sets.data.length, lists: lists.data.keys.length }); ``` +`getSets()` returns `{ data: [{ key, value }], cursor }` with `data` as an array; `getLists()` returns `{ data: { keys: [...] }, cursor }` with `data` as an object wrapping `keys`. `getSet(key)` returns `{ value }` as a string. List items come back sorted lexicographically, not in insertion order. + ### SQL Explorer ```typescript @@ -214,9 +235,12 @@ const result = await qn.sql.query( const schema = await qn.sql.getSchema("hyperliquid-core-mainnet"); console.log(`${result.rows} rows, ${result.credits} credits`); -console.log(schema); +console.log(result.data); // the rows themselves +console.log(schema.tables.map((t) => t.name)); ``` +`query` returns `{ meta, data, rows, rowsBeforeLimitAtLeast, statistics, credits }`. `rows` is a count; the row objects are in `data`, keyed by the selected columns. `rowsBeforeLimitAtLeast` is the match count before `LIMIT`. `query` costs API credits on every call; `getSchema` is free. + ## RPC Micropayments Node 3.8.0+, other languages 0.8.0+. The `rpc` client can pay for calls with stablecoins through the x402 or MPP gateway instead of an API key. Set a payment wallet and the SDK handles the HTTP `402 Payment Required` challenge, signs the payment, and resends the request. This lane needs no Quicknode account, API key, or provisioned endpoint — construct the SDK without an API key. @@ -287,12 +311,14 @@ quicknode-sdk = { version = "0.8", features = ["payments", "payments-svm", "paym ```typescript import { generatePaymentWallet } from "@quicknode/sdk"; -const wallet = generatePaymentWallet("evm"); // "evm" or "svm" +const wallet = generatePaymentWallet("evm"); // "evm" | "svm" | "tempo" console.log("Fund this address:", wallet.address); // Persist wallet.key now. It cannot be recovered later. ``` -Use `evm` for x402 on EVM and for MPP on Tempo; use `svm` for x402 on Solana. Other bindings expose it as `generate_payment_wallet`. +**Test:** offline, no network — `evm` and `tempo` return a 42-character `0x` address, `svm` a base58 address; any other value throws `ConfigError` naming all three + +`chain` is typed `"evm" | "svm" | "tempo"`. Use `evm` for x402 on EVM, `svm` for x402 on Solana, and `evm` or `tempo` for MPP on Tempo — both return a secp256k1 hex key. Other bindings expose it as `generate_payment_wallet`. ### x402 Credit Drawdown @@ -349,6 +375,22 @@ The gateway has no read-only channel endpoint, so it cannot reconstruct a lost l | `PaymentRejectedError` | The gateway refused the payment; nothing settled | | `PaymentIndeterminateError` | Outcome unknown — the payment may have settled. Check the wallet before retrying; never blind-retry a paid call | +## Errors + +Every SDK call throws from one typed hierarchy rooted at `QuicknodeError`. All of these are named exports. + +| Error | Extra fields | Raised when | +|-------|--------------|-------------| +| `QuicknodeError` | — | Base class for every SDK error | +| `ConfigError` | — | Bad or missing configuration — an unknown network key before `setNetworks`, an unknown payment chain | +| `HttpError` | — | Transport failure | +| `TimeoutError` | — | Extends `HttpError`. Request exceeded `QN_SDK__HTTP__TIMEOUT_SECS` | +| `ConnectionError` | — | Extends `HttpError`. Could not reach the host | +| `ApiError` | `status`, `body` | The API returned a non-2xx response | +| `DecodeError` | `body` | The response could not be decoded into the expected shape | +| `RpcError` | `code` | The JSON-RPC response carried an `error` member | +| `PaymentError` | — | Base class for the payment lane (see the table above) | + ## Other Languages Python, Rust, and Ruby expose the same product-client model through language-native method names: