Skip to content

feat: add chains list and chains gas commands#35

Closed
ggonzalez94 wants to merge 3 commits into
mainfrom
make-the-cli-agent-great
Closed

feat: add chains list and chains gas commands#35
ggonzalez94 wants to merge 3 commits into
mainfrom
make-the-cli-agent-great

Conversation

@ggonzalez94
Copy link
Copy Markdown
Owner

@ggonzalez94 ggonzalez94 commented Mar 8, 2026

Summary

  • Adds chains list command to enumerate all supported chains with names, slugs, CAIP-2 identifiers, namespaces, and accepted aliases
  • Adds chains gas --chain <id> command to query current EVM gas prices (base fee, priority fee, legacy gas price) via RPC
  • Both commands require no API keys and bypass cache initialization

chains list

Enables agents to programmatically discover valid --chain values:

defi chains list --results-only --select slug,caip2,namespace

chains gas

Gives agents gas price context before planning execution (swaps, bridges, lend operations):

defi chains gas --chain 1 --results-only
# Returns: chain_id, chain_name, block_number, eip1559, base_fee_gwei, priority_fee_gwei, gas_price_gwei
defi chains gas --chain base --rpc-url https://custom-rpc.example --results-only

Test plan

  • Unit tests for ListChains (dedup, sort, aliases)
  • Unit tests for weiToGwei conversion
  • fetchGasPrice with mock JSON-RPC server (EIP-1559 and legacy modes)
  • End-to-end test via Runner.Run with mock RPC
  • Non-EVM chain rejection + missing flag validation tests
  • Cache bypass tests for both commands
  • go test ./... passes
  • go vet ./... passes

🤖 Generated with Claude Code


Note

Medium Risk
Introduces new CLI surfaces that open live RPC connections and add concurrent multi-chain fetching, which can affect reliability/latency and error handling, but changes are isolated to new commands and models.

Overview
Adds two new chain discovery utilities: chains list to enumerate all supported chains (slug, CAIP-2, namespace, aliases), and chains gas to query live EVM gas pricing via JSON-RPC (EIP-1559 detection, block number, gwei values) with optional --rpc-url override.

chains gas supports comma-separated multi-chain requests fetched in parallel with partial-result warnings, rejects non-EVM chains, and both new commands are treated as metadata by bypassing cache initialization. The PR also introduces new output models (SupportedChain, GasPrice), an id.ListChains() helper to dedupe/sort chains and surface aliases, plus comprehensive unit/E2E tests and docs/README/CHANGELOG updates for the new commands.

Written by Cursor Bugbot for commit 650fa54. This will update automatically on new commits. Configure here.

ggonzalez94 and others added 2 commits March 8, 2026 15:28
Agents and automation tools need to discover available chains before
using other commands. This adds `chains list` which enumerates all
supported chains with names, slugs, CAIP-2 identifiers, namespaces,
and accepted aliases. No API keys required; bypasses cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Agents planning execution need gas price context before deciding whether
to proceed with swaps, bridges, or other on-chain operations. This adds
`chains gas --chain <id>` which queries current base fee, priority fee,
and legacy gas price via RPC with EIP-1559 detection.

No API keys required, bypasses cache, supports --rpc-url override.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ggonzalez94 ggonzalez94 changed the title feat: add chains list command for programmatic chain discovery feat: add chains list and chains gas commands Mar 9, 2026
Comment thread internal/model/types.go
BlockNumber int64 `json:"block_number"`
EIP1559 bool `json:"eip1559"`
BaseFeeGwei string `json:"base_fee_gwei"`
PriorityFeeGwei string `json:"priority_fee_gwei"`
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing omitempty on EIP-1559-only JSON fields

Medium Severity

BaseFeeGwei and PriorityFeeGwei in GasPrice lack omitempty JSON tags. For non-EIP1559 (legacy) chains, these fields are never set by fetchGasPrice, so they serialize as "base_fee_gwei": "" and "priority_fee_gwei": "" — empty strings in a field that otherwise holds numeric gwei values. This is inconsistent with the SupportedChain struct in the same PR, which uses omitempty for its optional fields. For an automation-friendly CLI, empty strings in numeric-typed fields can break downstream parsers that use .get() with a "0" default, since float("") raises errors. Since this is a new API surface, fixing it later would be a breaking change.

Fix in Cursor Fix in Web

Allow --chain to accept comma-separated chain identifiers (e.g.
--chain 1,10,137,8453,42161) for parallel multi-chain gas price
queries. Single-chain usage preserves the existing scalar response
for backward compatibility. Multi-chain returns an array with
partial-result support and warnings for failed chains.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ggonzalez94
Copy link
Copy Markdown
Owner Author

New: Multi-chain batch gas queries

Added support for comma-separated chains in chains gas:

# Before: one chain at a time
defi chains gas --chain 1 --results-only
defi chains gas --chain 10 --results-only
defi chains gas --chain 137 --results-only

# After: batch query with parallel RPC fetching
defi chains gas --chain 1,10,137,8453,42161 --results-only

Behavior:

  • Single chain: preserves existing scalar GasPrice response (backward compatible)
  • Multiple chains: returns []GasPrice array in input order
  • Parallel RPC fetching for all chains simultaneously
  • Partial-result support: if some chains fail, successful results are returned with warnings
  • --rpc-url rejected with multiple chains (ambiguous which chain to override)

All existing tests pass + new tests for multi-chain, rpc-url rejection, non-EVM rejection in multi-chain, and scalar preservation.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread internal/app/runner.go
gwei := new(big.Float).SetInt(wei)
gwei.Quo(gwei, big.NewFloat(1e9))
return gwei.Text('f', 6)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

weiToGwei returns inconsistent format for nil versus zero

Low Severity

weiToGwei returns "0" (no decimal places) for a nil input but "0.000000" (six decimal places) for a zero *big.Int. This format inconsistency means two semantically equivalent zero values produce different string representations. While current callers never pass nil, the function's contract is inconsistent and could produce surprising output if future callers do.

Fix in Cursor Fix in Web

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 650fa54261

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/app/runner.go
Comment on lines +491 to +492
partial := len(warnings) > 0
return s.emitSuccess(trimRootPath(cmd.CommandPath()), prices, warnings, cacheMetaBypass(), nil, partial)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Enforce strict mode before returning partial gas results

In the multi-chain chains gas path, partial failures are converted into warnings and then returned via emitSuccess, but this bypasses the strict-mode guard used by runCachedCommand to raise CodePartialStrict on partial data. As a result, defi chains gas --strict --chain ... can still exit successfully when one or more RPC calls fail, which is especially risky with --results-only because warnings are not emitted there and automation can treat incomplete results as complete.

Useful? React with 👍 / 👎.

Comment thread internal/app/runner.go
Comment on lines +452 to +456
result, err := fetchGasPrice(ctx, entries[0].chain, entries[0].rpcURL, s.runner.now)
if err != nil {
return err
}
return s.emitSuccess(trimRootPath(cmd.CommandPath()), result, nil, cacheMetaBypass(), nil, false)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep chains gas response type consistent with schema metadata

This branch returns a scalar GasPrice object for a single chain, while the command metadata below declares the response as []model.GasPrice; schema-driven clients using schema chains gas will therefore expect an array and mis-handle the default single-chain response shape. The command should use one stable response type (or an explicit union schema) to avoid contract drift for automation.

Useful? React with 👍 / 👎.

@ggonzalez94
Copy link
Copy Markdown
Owner Author

Closing: superseded by #43 which contains all commits from this stacked branch chain (this PR's 3 commits are included in #43's 10).

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