mirror of
https://github.com/luxfi/cli.git
synced 2026-10-30 17:01:20 +00:00
Sweep "brand" out of the API entirely. Package and types now match the
domain vocabulary the user sees in chain.yaml + CLI output:
pkg/brand → pkg/network (one package per concept)
Brand → Spec (parsed chain.yaml)
NetCfg → Env (per-env block)
RuntimeProfile → Profile
RuntimeProfile.Brand → Profile.Name
ChainLock → Lock
$LUX_BRAND_PATH → $LUX_NETWORK_PATH
Surface BOTH identifiers distinctly — they are deliberately different:
NetworkID uint32 — validator wire, --network-id, info.getNetworkID
PrimaryEvmChainID uint64 — C-chain EIP-155, eth_chainId, MetaMask
Lux brand keeps them apart (NID 1 / EVM 96369). Sovereign-L1 brand
forks (Zoo, Hanzo, Pars, Osage, Liquidity) collapse them by convention
(Zoo NID == EVM == 200200). The validator no longer enforces equality;
both are surfaced in lux ps and lux info.
New verb:
lux info <name>/<env> full Profile dump (both IDs, ports, paths,
snapshot name, service label, RPC endpoints,
live probe state)
lux ps output now shows NETWORK_ID and EVM_CHAIN_ID as separate columns.
chain.lock manifest now records both IDs so booting against a foreign
EVM-chain-ID dataDir is also rejected (previously only checked
networkID).
95 lines
2.3 KiB
Go
95 lines
2.3 KiB
Go
package network
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// EnvVar is the colon-separated path of universe directories scanned
|
|
// for chain.yaml — same shape as $PATH.
|
|
const EnvVar = "LUX_NETWORK_PATH"
|
|
|
|
// DefaultPath is the workspace convention: ~/work/<name>/universe.
|
|
func DefaultPath() string {
|
|
home, _ := os.UserHomeDir()
|
|
return strings.Join([]string{
|
|
filepath.Join(home, "work", "lux", "universe"),
|
|
filepath.Join(home, "work", "zoo", "universe"),
|
|
filepath.Join(home, "work", "hanzo", "universe"),
|
|
filepath.Join(home, "work", "pars", "universe"),
|
|
filepath.Join(home, "work", "osage", "universe"),
|
|
filepath.Join(home, "work", "adnexus", "universe"),
|
|
}, ":")
|
|
}
|
|
|
|
// Registry holds networks discovered from $LUX_NETWORK_PATH.
|
|
type Registry struct {
|
|
specs map[string]*Spec // slug → Spec
|
|
}
|
|
|
|
// Discover scans $LUX_NETWORK_PATH for chain.yaml files. Networks
|
|
// later in the path do NOT override earlier ones — first-wins, like
|
|
// $PATH. Unreadable / malformed files are skipped with a warning.
|
|
func Discover() (*Registry, error) {
|
|
pathStr := os.Getenv(EnvVar)
|
|
if pathStr == "" {
|
|
pathStr = DefaultPath()
|
|
}
|
|
r := &Registry{specs: map[string]*Spec{}}
|
|
for _, dir := range strings.Split(pathStr, ":") {
|
|
if dir == "" {
|
|
continue
|
|
}
|
|
yaml := filepath.Join(dir, "chain.yaml")
|
|
st, err := os.Stat(yaml)
|
|
if err != nil || st.IsDir() {
|
|
continue
|
|
}
|
|
s, err := ParseFile(yaml)
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "warn: %s: %v\n", yaml, err)
|
|
continue
|
|
}
|
|
name := s.Network.Slug
|
|
if _, dup := r.specs[name]; !dup {
|
|
r.specs[name] = s
|
|
}
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
// Lookup returns the network spec by name slug.
|
|
func (r *Registry) Lookup(name string) (*Spec, error) {
|
|
s, ok := r.specs[name]
|
|
if !ok {
|
|
known := r.Names()
|
|
return nil, fmt.Errorf("network %q not discovered under $%s (known: %v)", name, EnvVar, known)
|
|
}
|
|
return s, nil
|
|
}
|
|
|
|
// Names returns all discovered network slugs, sorted.
|
|
func (r *Registry) Names() []string {
|
|
out := make([]string, 0, len(r.specs))
|
|
for n := range r.specs {
|
|
out = append(out, n)
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|
|
|
|
// Refs returns all (name/env) pairs in the registry, sorted.
|
|
func (r *Registry) Refs() []string {
|
|
var out []string
|
|
for _, s := range r.specs {
|
|
for env := range s.Networks {
|
|
out = append(out, s.Network.Slug+"/"+env)
|
|
}
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|