Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions LLM.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Helm chart at `~/work/lux/devops/charts/lux/`. This ensures:
- Identical deployments to deploy-all.sh
- startup.sh with bootstrap, staking keys, upgrade-file-content, chain configs
- Per-pod LoadBalancer services for external access
- Configurable via `$LUX_CHART_PATH` or `--chart-path`
- Configurable via `$CHART_PATH` or `--chart-path`

## Quick Reference

Expand Down Expand Up @@ -81,7 +81,7 @@ lux chain create mychain --token-name=MYTOKEN --token-symbol=MTK
lux chain import --chain=c --path=/path/to/blocks.rlp # Import RLP blocks to C-Chain
lux chain import --chain=zoo --path=/path/to/zoo.rlp # Import to chain

# AMM Trading (LUX_MNEMONIC supported)
# AMM Trading (MNEMONIC supported)
lux amm balance # Check token balances
lux amm status # Show AMM contract status
lux amm pools # List liquidity pools
Expand Down Expand Up @@ -259,16 +259,16 @@ The AMM CLI supports Uniswap V2/V3 style DEX trading on Lux and Zoo networks.
### Wallet Access (Priority Order)

1. `--private-key` flag (hex private key)
2. `LUX_PRIVATE_KEY` environment variable
3. `LUX_MNEMONIC` environment variable (BIP39 mnemonic)
2. `PRIVATE_KEY` environment variable
3. `MNEMONIC` environment variable (BIP39 mnemonic)

```bash
# Using mnemonic
export LUX_MNEMONIC="word1 word2 ... word12"
export MNEMONIC="word1 word2 ... word12"
lux amm balance --network lux-testnet

# Using private key
export LUX_PRIVATE_KEY="0x..."
export PRIVATE_KEY="0x..."
lux amm balance --network zoo
```

Expand Down
8 changes: 4 additions & 4 deletions cmd/backendcmd/spawnServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var app *application.Lux

// NewCmd creates the lux-server command (formerly cli-backend).
// This is the gRPC server that manages local network nodes.
// The network type is determined by LUX_NETWORK_TYPE environment variable.
// The network type is determined by NETWORK_TYPE environment variable.
func NewCmd(injectedApp *application.Lux) *cobra.Command {
app = injectedApp

Expand All @@ -34,7 +34,7 @@ Each network type (mainnet, testnet, local) runs its own server on a dedicated p
- testnet: 8098
- local: 8099

The network type is determined by the LUX_NETWORK_TYPE environment variable.`,
The network type is determined by the NETWORK_TYPE environment variable.`,
RunE: startBackend,
Args: cobra.ExactArgs(0),
Hidden: true,
Expand All @@ -55,7 +55,7 @@ func NewNetworkCmd(injectedApp *application.Lux, networkType string) *cobra.Comm
Long: fmt.Sprintf("The Lux gRPC server for %s network. Invoked automatically by 'lux network start'.", networkType),
RunE: func(cmd *cobra.Command, args []string) error {
// Override the environment variable with the command's network type
_ = os.Setenv("LUX_NETWORK_TYPE", networkType)
_ = os.Setenv("NETWORK_TYPE", networkType)
return startBackend(cmd, args)
},
Args: cobra.ExactArgs(0),
Expand All @@ -77,7 +77,7 @@ func NewAllNetworkCmds(injectedApp *application.Lux) []*cobra.Command {
func startBackend(_ *cobra.Command, _ []string) error {
// Get network type from environment variable (set by StartServerProcessForNetwork)
// Defaults to "mainnet" for backward compatibility
networkType := os.Getenv("LUX_NETWORK_TYPE")
networkType := os.Getenv("NETWORK_TYPE")
if networkType == "" {
networkType = "mainnet"
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/devcmd/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ func stackUp(*cobra.Command, []string) error {
ux.Logger.PrintToUser("Starting %s on port %d...", name, port)
if _, err := spawnProcessWithEnv(binary, appArgs, logFile, pidDir, name, []string{
fmt.Sprintf("PORT=%d", port),
fmt.Sprintf("LUX_CHAINS_FILE=%s", filepath.Join(baseDir, stackChainsFile)),
fmt.Sprintf("LUX_RPC_URL=http://127.0.0.1:%d", luxdEntry.PortBase+i*portStride),
fmt.Sprintf("CHAINS_FILE=%s", filepath.Join(baseDir, stackChainsFile)),
fmt.Sprintf("RPC_URL=http://127.0.0.1:%d", luxdEntry.PortBase+i*portStride),
}); err != nil {
_ = logFile.Close()
ux.Logger.PrintToUser("Warning: failed to start %s: %v", name, err)
Expand Down
6 changes: 3 additions & 3 deletions cmd/kmscmd/kms.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,13 @@ func runServerStart(cmd *cobra.Command, args []string) error {
// getRootKey gets or generates the root encryption key.
func getRootKey(dataDir string) ([]byte, error) {
// Check environment variable first
if envKey := os.Getenv("LUX_KMS_ROOT_KEY"); envKey != "" {
if envKey := os.Getenv("KMS_ROOT_KEY"); envKey != "" {
key, err := hex.DecodeString(envKey)
if err != nil {
return nil, fmt.Errorf("invalid LUX_KMS_ROOT_KEY: %w", err)
return nil, fmt.Errorf("invalid KMS_ROOT_KEY: %w", err)
}
if len(key) != 32 {
return nil, fmt.Errorf("LUX_KMS_ROOT_KEY must be 32 bytes (64 hex chars)")
return nil, fmt.Errorf("KMS_ROOT_KEY must be 32 bytes (64 hex chars)")
}
return key, nil
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/networkcmd/start_k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ type K8sNetworkConfig struct {
// This delegates to `helm upgrade --install` to ensure a single source of truth.
func StartK8sNetwork(cfg K8sNetworkConfig) error {
// Resolve chart path
chartPath := os.Getenv("LUX_CHART_PATH")
chartPath := os.Getenv("CHART_PATH")
if chartPath == "" {
home, _ := os.UserHomeDir()
chartPath = filepath.Join(home, "work", "lux", "devops", "charts", "lux")
}

// Validate chart exists
if _, err := os.Stat(filepath.Join(chartPath, "Chart.yaml")); err != nil {
return fmt.Errorf("Helm chart not found at %s (set $LUX_CHART_PATH)", chartPath)
return fmt.Errorf("Helm chart not found at %s (set $CHART_PATH)", chartPath)
}

// Validate values file
Expand Down
8 changes: 4 additions & 4 deletions cmd/nodecmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ var (
)

// defaultChartPath returns the default Helm chart path.
// Searches: 1) $LUX_CHART_PATH, 2) ~/work/lux/devops/charts/lux
// Searches: 1) $CHART_PATH, 2) ~/work/lux/devops/charts/lux
func defaultChartPath() string {
if p := os.Getenv("LUX_CHART_PATH"); p != "" {
if p := os.Getenv("CHART_PATH"); p != "" {
return p
}
home, _ := os.UserHomeDir()
Expand All @@ -47,7 +47,7 @@ nodes, upgrade-file-content, chain configs, and per-pod services.

CHART DISCOVERY (in order):
1. --chart-path flag
2. $LUX_CHART_PATH environment variable
2. $CHART_PATH environment variable
3. ~/work/lux/devops/charts/lux/

EXAMPLES:
Expand Down Expand Up @@ -83,7 +83,7 @@ func runDeploy(_ *cobra.Command, _ []string) error {

// Validate chart exists
if _, err := os.Stat(filepath.Join(chart, "Chart.yaml")); err != nil {
return fmt.Errorf("Helm chart not found at %s (set --chart-path or $LUX_CHART_PATH)", chart)
return fmt.Errorf("Helm chart not found at %s (set --chart-path or $CHART_PATH)", chart)
}

// Validate values file exists
Expand Down
4 changes: 2 additions & 2 deletions cmd/nodecmd/k8s_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,14 @@ func TestResolveNetwork(t *testing.T) {

func TestDefaultChartPath(t *testing.T) {
// Without env var, should return ~/work/lux/devops/charts/lux
t.Setenv("LUX_CHART_PATH", "")
t.Setenv("CHART_PATH", "")
p := defaultChartPath()
if p == "" {
t.Error("defaultChartPath() returned empty string")
}

// With env var, should return the env value
t.Setenv("LUX_CHART_PATH", "/custom/chart")
t.Setenv("CHART_PATH", "/custom/chart")
p = defaultChartPath()
if p != "/custom/chart" {
t.Errorf("defaultChartPath() = %q, want /custom/chart", p)
Expand Down
2 changes: 1 addition & 1 deletion cmd/nodecmd/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ KUBERNETES COMMANDS (via Helm chart):
rollback Revert to previous StatefulSet revision

The deploy command uses the canonical Helm chart at ~/work/lux/devops/charts/lux/
(configurable via --chart-path or $LUX_CHART_PATH). All other k8s commands use
(configurable via --chart-path or $CHART_PATH). All other k8s commands use
the Kubernetes API directly for fast read/write operations.

All k8s commands require one of --mainnet, --testnet, --devnet, or --namespace.
Expand Down
6 changes: 3 additions & 3 deletions cmd/rpccmd/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Example:
},
}

cmd.Flags().StringVar(&flags.rpcURL, "rpc-url", "", "Base RPC URL (default: LUX_RPC_URL or running network endpoint)")
cmd.Flags().StringVar(&flags.rpcURL, "rpc-url", "", "Base RPC URL (default: RPC_URL or running network endpoint)")
cmd.Flags().StringVar(&flags.from, "from", "", "Key name to use (default: MNEMONIC account 0)")
cmd.Flags().StringVar(&flags.fromChain, "from-chain", "P", "Source chain: P, X, or C")
cmd.Flags().StringVar(&flags.toChain, "to-chain", "C", "Destination chain: P, X, or C")
Expand Down Expand Up @@ -123,15 +123,15 @@ func resolveRPCBaseURL(app *application.Lux, override string) (string, error) {
if override != "" {
return strings.TrimSuffix(override, "/"), nil
}
if env := os.Getenv("LUX_RPC_URL"); env != "" {
if env := os.Getenv("RPC_URL"); env != "" {
return strings.TrimSuffix(env, "/"), nil
}
if app != nil {
if endpoint := app.GetRunningNetworkEndpoint(); endpoint != "" {
return strings.TrimSuffix(endpoint, "/"), nil
}
}
return "", fmt.Errorf("rpc base URL not set (use --rpc-url or LUX_RPC_URL)")
return "", fmt.Errorf("rpc base URL not set (use --rpc-url or RPC_URL)")
}

func resolveNetworkID(baseURL string) (uint32, error) {
Expand Down
4 changes: 2 additions & 2 deletions cmd/zkcmd/ceremony.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import (
)

// findCeremonyBinary locates the ceremony binary.
// Search order: PATH, $LUX_NODE_ROOT/build/ceremony, /usr/local/bin/ceremony.
// Search order: PATH, $NODE_ROOT/build/ceremony, /usr/local/bin/ceremony.
func findCeremonyBinary() (string, error) {
if p, err := exec.LookPath("ceremony"); err == nil {
return p, nil
}
if root := os.Getenv("LUX_NODE_ROOT"); root != "" {
if root := os.Getenv("NODE_ROOT"); root != "" {
p := filepath.Join(root, "build", "ceremony")
if _, err := os.Stat(p); err == nil {
return p, nil
Expand Down
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ func init() {
// Go's default dialer waits 30s per dead IP before trying the next.
// Allow skipping TLS verification for devnet/internal endpoints
// that may use self-signed or staging certificates.
// Set LUX_INSECURE_TLS=1 to skip verification.
skipTLS := os.Getenv("LUX_INSECURE_TLS") == "1"
// Set INSECURE_TLS=1 to skip verification.
skipTLS := os.Getenv("INSECURE_TLS") == "1"
http.DefaultTransport = &http.Transport{
DialContext: (&net.Dialer{Timeout: 5 * time.Second}).DialContext,
TLSHandshakeTimeout: 10 * time.Second,
Expand Down
2 changes: 1 addition & 1 deletion pkg/binutils/processes.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func StartServerProcessForNetwork(app *application.Lux, networkType string) erro
}

cmd := exec.Command(netrunnerPath, args...) //nolint:gosec // G204: Running our netrunner binary
cmd.Env = append(os.Environ(), fmt.Sprintf("LUX_NETWORK_TYPE=%s", networkType))
cmd.Env = append(os.Environ(), fmt.Sprintf("NETWORK_TYPE=%s", networkType))
cmd.Stdout = outputFile
cmd.Stderr = outputFile

Expand Down
2 changes: 1 addition & 1 deletion pkg/chain/public.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ func (d *PublicDeployer) loadWallet(preloadTxs ...ids.ID) (primary.Wallet, error
ctx := context.Background()
ux.Logger.PrintToUser("loadWallet: starting...")

api := os.Getenv("LUX_NODE_ENDPOINT")
api := os.Getenv("NODE_ENDPOINT")
if api == "" {
switch d.network {
case models.Testnet:
Expand Down
39 changes: 13 additions & 26 deletions pkg/key/backend_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,62 +15,49 @@ import (
"github.com/luxfi/crypto/secp256k1"
)

// Environment variable names for key loading.
// Each variable supports two forms: generic (MNEMONIC) and prefixed (MNEMONIC).
// Generic form takes priority so the same mnemonic/key works across tools.
// Environment variable names for key loading. Brand prefix dropped — these
// are the canonical (unprefixed) names every tool reads.
const (
// EnvMnemonic contains a BIP39 mnemonic phrase.
// Env: MNEMONIC or MNEMONIC
EnvMnemonic = "MNEMONIC"

// EnvPrivateKey contains a hex-encoded secp256k1 private key.
// Env: PRIVATE_KEY or PRIVATE_KEY
EnvPrivateKey = "PRIVATE_KEY"

// EnvBLSKey contains a hex-encoded BLS private key.
// Env: BLS_KEY or LUX_BLS_KEY
EnvBLSKey = "LUX_BLS_KEY"
EnvBLSKey = "BLS_KEY"

// EnvKeyPassword for encrypted key files.
// Env: KEY_PASSWORD or KEY_PASSWORD
EnvKeyPassword = "KEY_PASSWORD"

// EnvKeySessionTimeout configures the session timeout duration.
// Format: Go duration string (e.g., "30s", "5m", "1h").
// Default: 30s (30 seconds of inactivity before auto-lock).
// Env: KEY_SESSION_TIMEOUT or KEY_SESSION_TIMEOUT
EnvKeySessionTimeout = "KEY_SESSION_TIMEOUT"

// EnvKeyIndex selects the BIP-44 address index for mnemonic derivation.
// Path: m/44'/9000'/0'/0/{index} for P/X-Chain.
// Default: "auto" — scans indices 0-99 to find the first funded account.
// Set to a specific number (e.g., "1") to use that index directly.
// Env: MNEMONIC_ACCOUNT or LUX_KEY_INDEX
EnvKeyIndex = "LUX_KEY_INDEX"
// MNEMONIC_ACCOUNT takes priority for backward compatibility with other tools.
EnvKeyIndex = "KEY_INDEX"

// EnvLightMnemonic is the well-known dev/local mnemonic for local development.
// This mnemonic is PUBLIC and safe to commit — it is NOT used for production.
// Env: LIGHT_MNEMONIC
EnvLightMnemonic = "LIGHT_MNEMONIC"

// LightMnemonic is the default mnemonic for local development networks.
// Intentionally public: "light light light light light light light light light light light energy"
LightMnemonic = "light light light light light light light light light light light energy"
)

// getEnv returns the value of an environment variable, checking the generic
// (unprefixed) form first, then the LUX_ prefixed form.
// e.g., getEnv("MNEMONIC") checks MNEMONIC first, then MNEMONIC.
func getEnv(luxPrefixed string) string {
// Try generic form: strip LUX_ prefix
generic := strings.TrimPrefix(luxPrefixed, "LUX_")
if v := os.Getenv(generic); v != "" {
return v
}
return os.Getenv(luxPrefixed)
// getEnv returns the value of the named environment variable.
func getEnv(name string) string {
return os.Getenv(name)
}

// getKeyIndex returns the configured key index from MNEMONIC_ACCOUNT or LUX_KEY_INDEX.
// getKeyIndex returns the configured key index from MNEMONIC_ACCOUNT or KEY_INDEX.
// MNEMONIC_ACCOUNT (industry-standard name) takes priority.
func getKeyIndex() string {
if v := os.Getenv("MNEMONIC_ACCOUNT"); v != "" {
return v
Expand Down Expand Up @@ -160,15 +147,15 @@ func (b *EnvBackend) LoadKey(ctx context.Context, name, password string) (*HDKey
}

func (*EnvBackend) loadFromEnv(name string) (*HDKeySet, error) {
// Priority 1: MNEMONIC / MNEMONIC
// Priority 1: MNEMONIC
if mnemonic := getEnv(EnvMnemonic); mnemonic != "" {
if !ValidateMnemonic(mnemonic) {
return nil, errors.New("invalid mnemonic in MNEMONIC / MNEMONIC")
return nil, errors.New("invalid mnemonic in MNEMONIC")
}
return DeriveAllKeys(name, mnemonic)
}

// Priority 2: PRIVATE_KEY / PRIVATE_KEY (hex-encoded EC key)
// Priority 2: PRIVATE_KEY (hex-encoded EC key)
if privKeyHex := getEnv(EnvPrivateKey); privKeyHex != "" {
privKeyHex = strings.TrimPrefix(privKeyHex, "0x")
privKeyBytes, err := hex.DecodeString(privKeyHex)
Expand Down
4 changes: 2 additions & 2 deletions pkg/key/backend_walletconnect.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ var (
ErrWCUserRejected = errors.New("walletconnect: user rejected request")
ErrWCTimeout = errors.New("walletconnect: request timed out")
ErrWCDisconnected = errors.New("walletconnect: disconnected from relay")
ErrWCNoProjectID = errors.New("walletconnect: project ID required (set LUX_WC_PROJECT_ID)")
ErrWCNoProjectID = errors.New("walletconnect: project ID required (set WC_PROJECT_ID)")
ErrWCInvalidResponse = errors.New("walletconnect: invalid response from wallet")
)

Expand Down Expand Up @@ -135,7 +135,7 @@ func (*WalletConnectBackend) SupportsRemoteSigning() bool {

func (b *WalletConnectBackend) Initialize(ctx context.Context) error {
// Get project ID from environment
b.projectID = os.Getenv("LUX_WC_PROJECT_ID")
b.projectID = os.Getenv("WC_PROJECT_ID")
if b.projectID == "" {
// WalletConnect Cloud project ID is optional but recommended
// Public fallback for development
Expand Down
2 changes: 1 addition & 1 deletion pkg/key/soft_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,7 @@ func GetOrCreateLocalKey(networkID uint32) (*SoftKey, error) {

// Priority 2: MNEMONIC / MNEMONIC
if mnemonic := getEnv(EnvMnemonic); mnemonic != "" {
// MNEMONIC_ACCOUNT (or LUX_KEY_INDEX) selects BIP-44 address index.
// MNEMONIC_ACCOUNT (or KEY_INDEX) selects BIP-44 address index.
// Derivation: m/44'/9000'/0'/0/{account} for P/X-Chain
// m/44'/60'/0'/0/{account} for C-Chain/EVM
// Default: 0
Expand Down
4 changes: 2 additions & 2 deletions pkg/models/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,11 @@ func (Network) BootstrappingContext() (context.Context, func()) {
}

// Endpoint returns the RPC endpoint for the network.
// LUX_NODE_ENDPOINT env var overrides the canonical api.lux*.network DNS
// NODE_ENDPOINT env var overrides the canonical api.lux*.network DNS
// for ops paths where the public endpoint isn't reachable (cross-cluster
// deploys, captive testnets, etc).
func (s Network) Endpoint() string {
if ovr := os.Getenv("LUX_NODE_ENDPOINT"); ovr != "" {
if ovr := os.Getenv("NODE_ENDPOINT"); ovr != "" {
return ovr
}
switch s {
Expand Down
4 changes: 2 additions & 2 deletions pkg/prompts/missing.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
// MissingOpt describes a required option that was not provided.
type MissingOpt struct {
Flag string // e.g., "--chain-id"
Env string // e.g., "LUX_CHAIN_ID" (optional)
Env string // e.g., "CHAIN_ID" (optional)
Prompt string // e.g., "EVM chain ID" - used for interactive prompts
Note string // optional additional context
Default string // optional default value hint
Expand Down Expand Up @@ -53,7 +53,7 @@ func MissingError(cmd string, missing []MissingOpt) error {
//
// missing := []prompts.MissingOpt{}
// if chainID == "" {
// missing = append(missing, prompts.MissingOpt{Flag: "--chain-id", Env: "LUX_CHAIN_ID", Prompt: "EVM chain ID"})
// missing = append(missing, prompts.MissingOpt{Flag: "--chain-id", Env: "CHAIN_ID", Prompt: "EVM chain ID"})
// }
// if err := prompts.PromptOrFail("lux chain create", missing, func(m MissingOpt) (string, error) {
// return app.Prompt.CaptureString(m.Prompt)
Expand Down
Loading
Loading