mirror of
https://github.com/luxfi/cli.git
synced 2026-10-30 17:01:20 +00:00
The local C-Chain genesis is chainId 31337 (genesis/configs/local/cchain.json) while the primary network ID is 1337 — deliberately distinct so a wallet or tool never conflates them. The cli constant was misnamed localEVMChainID=1337; rename to localCChainID=31337, derive funded-account keys from the primary networkID (P/X addresses are network-scoped; the C-Chain 0x is chain-agnostic), and print both IDs on start so a builder has exactly what they need locally. Co-authored-by: Hanzo Dev <[email protected]>
125 lines
4.7 KiB
Go
125 lines
4.7 KiB
Go
// Copyright (C) 2022-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package networkcmd
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
|
|
"github.com/luxfi/cli/pkg/key"
|
|
"github.com/luxfi/cli/pkg/ux"
|
|
)
|
|
|
|
const (
|
|
// Primary network ID and C-Chain EVM chain ID are DISTINCT on purpose: a
|
|
// wallet or tool must never conflate "which primary network" (1337) with
|
|
// "which EVM chain" (31337). Matches genesis/configs/local — network.json
|
|
// networkID 1337, cchain.json chainId 31337.
|
|
localnetNetworkID = uint32(1337)
|
|
localCChainID = 31337
|
|
localnetValidators = 3
|
|
// lightMnemonic re-exports the single source of truth (key.LightMnemonic
|
|
// → github.com/luxfi/light.Mnemonic); do not re-declare the literal.
|
|
lightMnemonic = key.LightMnemonic
|
|
)
|
|
|
|
// StartLocal starts a 3-node localnet on K8s via the operator.
|
|
// No netrunner — the operator manages StatefulSets, chain creation and deployment.
|
|
//
|
|
// lux network start --local
|
|
// lux network start --local --k8s colima
|
|
func StartLocal() error {
|
|
ux.Logger.PrintToUser("")
|
|
ux.Logger.PrintToUser("╔══════════════════════════════════════════════╗")
|
|
ux.Logger.PrintToUser("║ Lux Network — Localnet (3 nodes, K8s) ║")
|
|
ux.Logger.PrintToUser("╚══════════════════════════════════════════════╝")
|
|
ux.Logger.PrintToUser("")
|
|
|
|
ctx := k8sCluster
|
|
if ctx == "" {
|
|
ctx = "colima"
|
|
}
|
|
|
|
if err := checkK8s(ctx); err != nil {
|
|
return fmt.Errorf("K8s not available (context: %s): %w\nStart colima: colima start --kubernetes --cpu 4 --memory 8", ctx, err)
|
|
}
|
|
ux.Logger.PrintToUser("K8s context: %s", ctx)
|
|
|
|
// The two IDs a builder needs, stated once and kept distinct.
|
|
ux.Logger.PrintToUser("")
|
|
ux.Logger.PrintToUser("Primary network ID: %d · C-Chain EVM chain ID: %d", localnetNetworkID, localCChainID)
|
|
|
|
// Show funded accounts (P/X addresses are network-scoped, so key derivation
|
|
// takes the primary networkID; the C-Chain 0x address is chain-agnostic).
|
|
ux.Logger.PrintToUser("")
|
|
ux.Logger.PrintToUser("Funded Accounts (light mnemonic):")
|
|
for i := 0; i < localnetValidators; i++ {
|
|
sf, err := key.NewSoftFromMnemonicWithAccount(localnetNetworkID, lightMnemonic, uint32(i))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
label := ""
|
|
if i == 0 {
|
|
label = " (deployer)"
|
|
}
|
|
ux.Logger.PrintToUser(" [%d] %s%s", i, sf.C(), label)
|
|
}
|
|
ux.Logger.PrintToUser("")
|
|
|
|
home, _ := os.UserHomeDir()
|
|
operatorDir := filepath.Join(home, "work", "lux", "operator")
|
|
|
|
// The localnet CRs live in their own namespace; the operator (deployed by
|
|
// config/default into its own namespace) watches cluster-wide. AlreadyExists
|
|
// is the expected steady state, so this is the one apply whose error is fine.
|
|
_ = kubectl(ctx, "create", "namespace", "lux-system")
|
|
|
|
// Operator CRDs — canonical home is spec/crd/bases/<group>.
|
|
ux.Logger.PrintToUser("-> Operator CRDs")
|
|
if err := kubectl(ctx, "apply", "-f", filepath.Join(operatorDir, "spec", "crd", "bases", "lux.cloud")); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Operator RBAC + Deployment — canonical home is the config/default kustomize.
|
|
ux.Logger.PrintToUser("-> Operator RBAC + Deployment")
|
|
if err := kubectl(ctx, "apply", "-k", filepath.Join(operatorDir, "config", "default")); err != nil {
|
|
return err
|
|
}
|
|
|
|
// LuxNetwork CR for the localnet.
|
|
ux.Logger.PrintToUser("-> LuxNetwork (%d validators, network ID %d)", localnetValidators, localnetNetworkID)
|
|
if err := kubectl(ctx, "apply", "-f", filepath.Join(operatorDir, "spec", "examples", "luxnetwork-devnet.yaml")); err != nil {
|
|
return err
|
|
}
|
|
|
|
ux.Logger.PrintToUser("")
|
|
ux.Logger.PrintToUser("╔══════════════════════════════════════════════╗")
|
|
ux.Logger.PrintToUser("║ Localnet deploying via operator ║")
|
|
ux.Logger.PrintToUser("║ Check: lux network status ║")
|
|
ux.Logger.PrintToUser("║ Stop: lux network stop ║")
|
|
ux.Logger.PrintToUser("╚══════════════════════════════════════════════╝")
|
|
|
|
return nil
|
|
}
|
|
|
|
func checkK8s(ctx string) error {
|
|
cmd := exec.Command("kubectl", "--context", ctx, "cluster-info")
|
|
cmd.Stdout = nil
|
|
cmd.Stderr = nil
|
|
return cmd.Run()
|
|
}
|
|
|
|
func kubectl(ctx string, args ...string) error {
|
|
fullArgs := append([]string{"--context", ctx}, args...)
|
|
cmd := exec.Command("kubectl", fullArgs...)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("kubectl %v: %w", args, err)
|
|
}
|
|
return nil
|
|
}
|