Files
zeekayandHanzo Dev 62d5f28c22 A chain address is built in one place
The node moved every chain route from /v1/bc/<alias> to /v1/chain/<alias>
and deleted the old prefix, so every chain call answered 404. The address
was spelled out at 112 sites across 34 files and constants.ChainAliasPrefix
was used at none of them, which is why nothing failed to compile when the
segment moved.

route.Chain(uri, alias) composes it now, and route.Alias reads one back,
replacing three hand-rolled parsers — one of which took the alias by
position in the split path and only worked because the new segment happens
to leave the component count unchanged.

TestChainAddressBuiltOnlyHere walks every .go file in the module and fails
on a chain address in a string literal, so the segment cannot drift back;
prose is free to name a route. TestGuardCatchesEachShape plants each
forbidden shape and requires the guard to find it.

The endpoint box and the eleven-chain table were the same list written
twice; there is one list, rendered once, measured rather than hand-padded.
The generated CLI reference and the faucet manifest compose through the
same function.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-30 15:05:42 -07:00

246 lines
5.8 KiB
Go

// Copyright (C) 2022-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
// Package models contains data structures and types used throughout the CLI.
package models
import (
"context"
"fmt"
"os"
"time"
"github.com/luxfi/cli/pkg/route"
"github.com/luxfi/constants"
)
// Network represents a blockchain network type.
type Network int64
// Network type constants.
const (
// Undefined represents an undefined network.
Undefined Network = iota
Mainnet
Testnet
Local
Devnet
)
// UndefinedNetwork is an alias for Undefined for compatibility.
const UndefinedNetwork = Undefined
func (s Network) String() string {
switch s {
case Mainnet:
return "Mainnet"
case Testnet:
return "Testnet"
case Local:
return "Local Network"
case Devnet:
return "Devnet"
}
return "Unknown Network"
}
// NetworkID returns the numeric network ID for the network.
func (s Network) NetworkID() (uint32, error) {
switch s {
case Mainnet:
return constants.MainnetID, nil
case Testnet:
return constants.TestnetID, nil
case Devnet:
return constants.DevnetID, nil
case Local:
return constants.LocalNetworkID, nil
}
return 0, fmt.Errorf("unsupported network")
}
// NetworkIDFlagValue returns the network ID as a string for CLI flags.
func (s Network) NetworkIDFlagValue() string {
id, err := s.NetworkID()
if err != nil {
return ""
}
return fmt.Sprintf("%d", id)
}
// ID returns the numeric network ID, ignoring errors.
func (s Network) ID() uint32 {
id, _ := s.NetworkID()
return id
}
// Kind returns the network type.
func (s Network) Kind() Network {
return s
}
// Name returns the network name as a string
func (s Network) Name() string {
return s.String()
}
// HandlePublicNetworkSimulation returns true if the network simulates a public network.
func (s Network) HandlePublicNetworkSimulation() bool {
return s == Local
}
// NetworkFromString returns a Network from its string representation.
func NetworkFromString(s string) Network {
switch s {
case Mainnet.String():
return Mainnet
case Testnet.String():
return Testnet
case Local.String():
return Local
}
return Undefined
}
// NetworkFromNetworkID returns a Network from its numeric ID.
func NetworkFromNetworkID(networkID uint32) Network {
switch networkID {
case constants.MainnetID:
return Mainnet
case constants.TestnetID:
return Testnet
case constants.LocalNetworkID:
return Local
}
return Undefined
}
// NewLocalNetwork creates a new Local network instance
func NewLocalNetwork() Network {
return Local
}
// NewTestnetNetwork creates a new Testnet network instance
func NewTestnetNetwork() Network {
return Testnet
}
// NewMainnetNetwork creates a new Mainnet network instance
func NewMainnetNetwork() Network {
return Mainnet
}
// NewDevnetNetwork creates a new Devnet network instance
func NewDevnetNetwork() Network {
return Devnet
}
// BootstrappingContext returns a context for bootstrapping operations
func (Network) BootstrappingContext() (context.Context, func()) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
return ctx, cancel
}
// Endpoint returns the RPC endpoint for the network.
// 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("NODE_ENDPOINT"); ovr != "" {
return ovr
}
switch s {
case Mainnet:
return constants.MainnetAPIEndpoint
case Testnet:
return constants.TestnetAPIEndpoint
case Local:
return constants.LocalAPIEndpoint
case Devnet:
return constants.DevnetAPIEndpoint
default:
return constants.LocalAPIEndpoint
}
}
// ClusterName returns the cluster name for the network
func (s Network) ClusterName() string {
switch s {
case Local:
return "local"
default:
return ""
}
}
// WSEndpoints returns the WebSocket endpoints for the network
func (s Network) WSEndpoints() []string {
switch s {
case Mainnet:
return []string{constants.MainnetWSEndpoint}
case Testnet:
return []string{constants.TestnetWSEndpoint}
case Local:
return []string{constants.LocalWSEndpoint}
case Devnet:
return []string{constants.DevnetWSEndpoint}
default:
return []string{constants.LocalWSEndpoint}
}
}
// CChainEndpoint returns the C-Chain endpoint for the network
func (s Network) CChainEndpoint() string {
baseEndpoint := s.Endpoint()
return route.Chain(baseEndpoint, "C") + "/rpc"
}
// CChainWSEndpoint returns the C-Chain WebSocket endpoint for the network
func (s Network) CChainWSEndpoint() string {
wsEndpoints := s.WSEndpoints()
if len(wsEndpoints) > 0 {
return wsEndpoints[0]
}
return ""
}
// Equals checks if two networks are equal
func (s Network) Equals(other Network) bool {
return s == other
}
// SDKNetwork returns the network as an SDK network type
// This is for compatibility with the SDK package
func (s Network) SDKNetwork() interface{} {
// Convert to SDK network type
// This returns an interface{} to avoid circular dependencies
// The caller should type assert to the appropriate SDK network type
return s
}
// GetNetworkFromSidecarNetworkName returns a network based on sidecar network name
func GetNetworkFromSidecarNetworkName(name string) Network {
switch name {
case "mainnet", "Mainnet":
return Mainnet
case "testnet", "Testnet":
return Testnet
case "local", "Local":
return Local
case "devnet", "Devnet":
return Devnet
default:
return Undefined
}
}
// GetRPCEndpoint returns the RPC endpoint for a given base endpoint and blockchain ID
func GetRPCEndpoint(baseEndpoint string, blockchainID string) string {
return route.Chain(baseEndpoint, blockchainID) + "/rpc"
}
// GetWSEndpoint returns the WebSocket endpoint for a given base endpoint and blockchain ID
func GetWSEndpoint(baseEndpoint string, blockchainID string) string {
return route.Chain(baseEndpoint, blockchainID) + "/ws"
}