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).
64 lines
1.5 KiB
Go
64 lines
1.5 KiB
Go
// Package pscmd implements `lux ps` — for every name/env in the
|
|
// registry, probe the local port and report whether a matching node is
|
|
// up.
|
|
package pscmd
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"text/tabwriter"
|
|
"time"
|
|
|
|
"os"
|
|
|
|
"github.com/luxfi/cli/pkg/network"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
func NewCmd() *cobra.Command {
|
|
return &cobra.Command{
|
|
Use: "ps",
|
|
Short: "List running sovereign-L1 nodes on this host",
|
|
Long: `Probes the resolved httpPort for every (network, env) tuple in the
|
|
registry and reports up/down + networkID match.`,
|
|
Args: cobra.ExactArgs(0),
|
|
RunE: func(*cobra.Command, []string) error {
|
|
reg, err := network.Discover()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
|
fmt.Fprintln(w, "NETWORK\tNETWORK_ID\tEVM_CHAIN_ID\tPORT\tSTATE\tPID")
|
|
for _, ref := range reg.Refs() {
|
|
prof, err := network.Resolve(ref)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
state, pid := probe(prof)
|
|
cid := "-"
|
|
if prof.PrimaryEvmChainID != 0 {
|
|
cid = fmt.Sprintf("%d", prof.PrimaryEvmChainID)
|
|
}
|
|
fmt.Fprintf(w, "%s\t%d\t%s\t%d\t%s\t%d\n",
|
|
ref, prof.NetworkID, cid, prof.HTTPPort, state, pid)
|
|
}
|
|
return w.Flush()
|
|
},
|
|
SilenceUsage: true,
|
|
}
|
|
}
|
|
|
|
func probe(p *network.Profile) (state string, pid int) {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
matches, found, err := p.Probe(ctx)
|
|
if err != nil {
|
|
return "down", 0
|
|
}
|
|
if !matches {
|
|
return fmt.Sprintf("FOREIGN(nid=%d)", found), 0
|
|
}
|
|
pid, _ = network.PIDOnPort(p.HTTPPort)
|
|
return "up", pid
|
|
}
|