mirror of
https://github.com/luxfi/cli.git
synced 2026-10-30 17:01:20 +00:00
luxfi/utils is now luxfi/util. Same code and history, one fewer character at every import site, and a name that reads as a bag of utilities rather than a plural of some thing called a util. Co-authored-by: Hanzo Dev <[email protected]>
198 lines
5.4 KiB
Go
198 lines
5.4 KiB
Go
// Copyright (C) 2022-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package validatorcmd
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/luxfi/cli/pkg/cobrautils"
|
|
"github.com/luxfi/cli/pkg/networkoptions"
|
|
"github.com/luxfi/cli/pkg/utils"
|
|
"github.com/luxfi/cli/pkg/ux"
|
|
"github.com/luxfi/constants"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/sdk/contract"
|
|
"github.com/luxfi/sdk/models"
|
|
"github.com/luxfi/sdk/validator"
|
|
sdkutils "github.com/luxfi/util"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var globalNetworkFlags networkoptions.NetworkFlags
|
|
|
|
var (
|
|
l1 string
|
|
validationIDStr string
|
|
nodeIDStr string
|
|
)
|
|
|
|
func NewGetBalanceCmd() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "getBalance",
|
|
Short: "Gets current balance of validator on P-Chain",
|
|
Long: `This command gets the remaining validator P-Chain balance that is available to pay
|
|
P-Chain continuous fee`,
|
|
RunE: getBalance,
|
|
Args: cobrautils.ExactArgs(0),
|
|
}
|
|
|
|
// Network flags handled at higher level to avoid conflicts
|
|
cmd.Flags().StringVar(&l1, "l1", "", "name of L1")
|
|
cmd.Flags().StringVar(&validationIDStr, "validation-id", "", "validation ID of the validator")
|
|
cmd.Flags().StringVar(&nodeIDStr, "node-id", "", "node ID of the validator")
|
|
return cmd
|
|
}
|
|
|
|
func getBalance(_ *cobra.Command, _ []string) error {
|
|
network, err := networkoptions.GetNetworkFromCmdLineFlags(
|
|
app,
|
|
"",
|
|
globalNetworkFlags,
|
|
true,
|
|
false,
|
|
networkoptions.DefaultSupportedNetworkOptions,
|
|
"",
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
validationID, cancel, err := getNodeValidationID(network, l1, nodeIDStr, validationIDStr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if cancel {
|
|
return nil
|
|
}
|
|
if validationID == ids.Empty {
|
|
return fmt.Errorf("the specified node is not a L1 validator")
|
|
}
|
|
|
|
balance, err := validator.GetValidatorBalance(network, validationID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ux.Logger.PrintToUser(" Validator Balance: %.5f LUX", float64(balance)/float64(constants.Lux))
|
|
|
|
return nil
|
|
}
|
|
|
|
// getNodeValidationID returns the node validation ID based on input
|
|
// present in given args and prompted to the user
|
|
// it also returns a boolean that is true if the user cancels
|
|
// operations during prompting
|
|
func getNodeValidationID(
|
|
network models.Network,
|
|
l1 string,
|
|
nodeIDStr,
|
|
validationIDStr string,
|
|
) (ids.ID, bool, error) {
|
|
var (
|
|
validationID ids.ID
|
|
err error
|
|
)
|
|
if validationIDStr != "" {
|
|
validationID, err = ids.FromString(validationIDStr)
|
|
if err != nil {
|
|
return validationID, false, err
|
|
}
|
|
return validationID, false, nil
|
|
}
|
|
l1ListOption := "I will choose from the L1 validators list"
|
|
validationIDOption := "I know the validation ID"
|
|
cancelOption := "Cancel"
|
|
option := l1ListOption
|
|
if l1 == "" && nodeIDStr == "" {
|
|
options := []string{l1ListOption, validationIDOption, cancelOption}
|
|
option, err = app.Prompt.CaptureList(
|
|
"How do you want to specify the L1 validator",
|
|
options,
|
|
)
|
|
if err != nil {
|
|
return ids.Empty, false, err
|
|
}
|
|
}
|
|
switch option {
|
|
case l1ListOption:
|
|
chainSpec := contract.ChainSpec{
|
|
BlockchainName: l1,
|
|
}
|
|
chainSpec.SetEnabled(
|
|
true, // prompt blockchain name
|
|
false, // do not prompt for PChain
|
|
false, // do not prompt for XChain
|
|
false, // do not prompt for CChain
|
|
true, // prompt blockchain ID
|
|
)
|
|
chainSpec.OnlySOV = true
|
|
if l1 == "" {
|
|
if cancel, err := contract.PromptChain(
|
|
app.GetSDKApp(),
|
|
network,
|
|
"Choose the L1",
|
|
"",
|
|
&chainSpec,
|
|
); err != nil {
|
|
return ids.Empty, false, err
|
|
} else if cancel {
|
|
return ids.Empty, true, nil
|
|
}
|
|
l1 = chainSpec.BlockchainName
|
|
}
|
|
sc, err := app.LoadSidecar(l1)
|
|
if err != nil {
|
|
return ids.Empty, false, fmt.Errorf("failed to load sidecar: %w", err)
|
|
}
|
|
if !sc.Sovereign {
|
|
return ids.Empty, false, fmt.Errorf("lux validator commands are only applicable to sovereign L1s")
|
|
}
|
|
if sc.Networks[network.Name()].ValidatorManagerAddress == "" {
|
|
return ids.Empty, false, fmt.Errorf("unable to find Validator Manager address")
|
|
}
|
|
chainID, err := contract.GetNetworkID(app.GetSDKApp(), network, chainSpec)
|
|
if err != nil {
|
|
return ids.Empty, false, err
|
|
}
|
|
validators, err := validator.GetCurrentValidators(network, chainID)
|
|
if err != nil {
|
|
return ids.Empty, false, err
|
|
}
|
|
if len(validators) == 0 {
|
|
return ids.Empty, false, fmt.Errorf("l1 has no validators")
|
|
}
|
|
if nodeIDStr == "" {
|
|
nodeIDStrs := sdkutils.Map(validators, func(v validator.CurrentValidatorInfo) string { return v.NodeID.String() })
|
|
sort.Strings(nodeIDStrs)
|
|
// CaptureListWithSize returns a slice, we want the first (and only) element
|
|
selected, err := app.Prompt.CaptureListWithSize("Choose Node ID of the validator", nodeIDStrs, 1)
|
|
if err != nil {
|
|
return ids.Empty, false, err
|
|
}
|
|
if len(selected) == 0 {
|
|
return ids.Empty, false, fmt.Errorf("no node ID selected")
|
|
}
|
|
nodeIDStr = selected[0]
|
|
}
|
|
nodeID, err := ids.NodeIDFromString(nodeIDStr)
|
|
if err != nil {
|
|
return ids.Empty, false, err
|
|
}
|
|
found := utils.Find(validators, func(v validator.CurrentValidatorInfo) bool { return v.NodeID == nodeID })
|
|
if found == nil {
|
|
return ids.Empty, false, fmt.Errorf("node %s not found among L1 validators", nodeID.String())
|
|
}
|
|
validationID = found.ValidationID
|
|
case validationIDOption:
|
|
validationID, err = app.Prompt.CaptureID("What is the validator's validationID?")
|
|
if err != nil {
|
|
return ids.Empty, false, err
|
|
}
|
|
case cancelOption:
|
|
return ids.Empty, true, nil
|
|
}
|
|
return validationID, false, nil
|
|
}
|