Chains
The chain profile manager loads presets from JSON, supports custom registration, resolves chains by id or numeric chain-id, and manages the active chain selection.
Source file: internal/chains/chains.go
The chain profile manager loads presets from a JSON file, supports custom chain registration at runtime, and resolves chains by id or numeric chain-id. It manages the active chain selection for the daemon.
Design decisions
Preset + custom model
Chains come from two sources:
- Presets: Loaded from
chains/presets.jsonat startup. Each preset may reference an environment variable for its RPC URL (rpc_url_env), resolved lazily on access. - Custom: Registered at runtime via
ChainRegister. Stored in memory only (not persisted to disk).
Numeric chain-id fallback
Callers (and agents) commonly pass the numeric EVM chain-id (e.g., "125") rather than the profile id (e.g., "paxeer-mainnet"). The Get method maps numeric input to the matching profile by iterating presets and custom chains, so deploy/call/simulate resolve either way.
Inline RPC resolution
The Resolve method accepts three sources: chainID, rpcURL, and activeID. When rpcURL is provided directly, it returns an anonymous inline chain profile without requiring registration. This supports ad-hoc chain targeting.
Thread safety
All reads acquire RLock, all writes acquire Lock. The resolveEnv helper lazily resolves rpc_url_env references on each access.
ChainProfile
type ChainProfile struct {
ID string `json:"id"`
Name string `json:"name"`
RPCURL string `json:"rpc_url,omitempty"`
RPCURLEnv string `json:"rpc_url_env,omitempty"`
ChainID uint64 `json:"chain_id"`
Preset string `json:"preset,omitempty"`
Explorer string `json:"explorer,omitempty"`
Features []string `json:"features,omitempty"`
Active bool `json:"active,omitempty"`
}
Custom chains are registered with Features: []string{"debug_trace"} by default.
Operations
| Method | Description |
|---|---|
New(presetsPath) | Load presets from JSON file |
SetProjectRoot(root) | Store default project root for relative lookups |
List(activeID) | Return all chains with active marker |
Get(id) | Resolve by profile id or numeric chain-id |
Register(req) | Add/update a custom chain (requires id, chain_id, rpc_url) |
Resolve(chainID, rpcURL, activeID) | Pick chain from id, inline rpc, or active |
AvailableIDs() | Return chain ids with configured RPC |
Default presets path
func DefaultPresetsPath(projectRoot string) string {
return filepath.Join(projectRoot, "chains", "presets.json")
}
Modifying the chain manager
| What to change | Where |
|---|---|
| Add chain field | pkg/types/chain.go - ChainProfile |
| Change preset format | internal/chains/chains.go - presetsFile struct |
| Add chain validation | internal/chains/chains.go - Register method |
| Persist custom chains | internal/chains/chains.go - add file write on Register |
