Skip to content

Commit

Permalink
[ioctl] add bc delegate command
Browse files Browse the repository at this point in the history
  • Loading branch information
dustinxie committed Jun 21, 2023
1 parent 1abbc44 commit 399238d
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 1 deletion.
1 change: 1 addition & 0 deletions ioctl/cmd/bc/bc.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func init() {
BCCmd.AddCommand(_bcInfoCmd)
BCCmd.AddCommand(_bcBucketListCmd)
BCCmd.AddCommand(_bcBucketCmd)
BCCmd.AddCommand(_bcDelegateCmd)
BCCmd.PersistentFlags().StringVar(&config.ReadConfig.Endpoint, "endpoint",
config.ReadConfig.Endpoint, config.TranslateInLang(_flagEndpointUsages, config.UILanguage))
BCCmd.PersistentFlags().BoolVar(&config.Insecure, "insecure", config.Insecure,
Expand Down
144 changes: 144 additions & 0 deletions ioctl/cmd/bc/bcdelegate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright (c) 2022 IoTeX Foundation
// This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
// or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
// This source code is governed by Apache License 2.0 that can be found in the LICENSE file.

package bc

import (
"context"
"fmt"
"math/big"
"strings"

"github.com/grpc-ecosystem/go-grpc-middleware/util/metautils"
"github.com/iotexproject/iotex-proto/golang/iotexapi"
"github.com/iotexproject/iotex-proto/golang/iotextypes"
"github.com/spf13/cobra"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"

"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/output"
"github.com/iotexproject/iotex-core/ioctl/util"
)

// Multi-language support
var (
_bcDelegateCmdShorts = map[config.Language]string{
config.English: "Get delegate information on IoTeX blockchain",
config.Chinese: "在IoTeX区块链上读取代表信息",
}
_bcDelegateUses = map[config.Language]string{
config.English: "delegate [name]",
config.Chinese: "delegate [名字]",
}
)

// _bcBucketCmd represents the bc Bucket command
var _bcDelegateCmd = &cobra.Command{
Use: config.TranslateInLang(_bcDelegateUses, config.UILanguage),
Short: config.TranslateInLang(_bcDelegateCmdShorts, config.UILanguage),
Args: cobra.ExactArgs(1),
Example: `ioctl bc delegate name, to read delegate information by name`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
cmd.SilenceUsage = true
err = getDelegate(args[0])
return output.PrintError(err)
},
}

type delegateMessage struct {
Delegate *iotextypes.CandidateV2 `json:"delegate"`
}

func (m *delegateMessage) delegateString() string {
var (
d = m.Delegate
vote, _ = new(big.Int).SetString(d.TotalWeightedVotes, 10)
token, _ = new(big.Int).SetString(d.SelfStakingTokens, 10)
lines []string
)
lines = append(lines, "{")
lines = append(lines, fmt.Sprintf(" name: %s", d.Name))
lines = append(lines, fmt.Sprintf(" ownerAddress: %s", d.OwnerAddress))
lines = append(lines, fmt.Sprintf(" operatorAddress: %s", d.OperatorAddress))
lines = append(lines, fmt.Sprintf(" rewardAddress: %s", d.RewardAddress))
lines = append(lines, fmt.Sprintf(" totalWeightedVotes: %s", util.RauToString(vote, util.IotxDecimalNum)))
lines = append(lines, fmt.Sprintf(" selfStakeBucketIdx: %d", d.SelfStakeBucketIdx))
lines = append(lines, fmt.Sprintf(" selfStakingTokens: %s IOTX", util.RauToString(token, util.IotxDecimalNum)))
lines = append(lines, "}")
return strings.Join(lines, "\n")
}

func (m *delegateMessage) String() string {
if output.Format == "" {
return m.delegateString()
}
return output.FormatString(output.Result, m)
}

func getDelegate(arg string) error {
d, err := getDelegateByName(arg)
if err != nil {
return err
}
message := delegateMessage{
Delegate: d,
}
fmt.Println(message.String())
return nil
}

func getDelegateByName(name string) (*iotextypes.CandidateV2, error) {
conn, err := util.ConnectToEndpoint(config.ReadConfig.SecureConnect && !config.Insecure)
if err != nil {
return nil, output.NewError(output.NetworkError, "failed to connect to endpoint", err)
}
defer conn.Close()
cli := iotexapi.NewAPIServiceClient(conn)
method := &iotexapi.ReadStakingDataMethod{
Method: iotexapi.ReadStakingDataMethod_CANDIDATE_BY_NAME,
}
methodData, err := proto.Marshal(method)
if err != nil {
return nil, output.NewError(output.SerializationError, "failed to marshal read staking data method", err)
}
readStakingdataRequest := &iotexapi.ReadStakingDataRequest{
Request: &iotexapi.ReadStakingDataRequest_CandidateByName_{
CandidateByName: &iotexapi.ReadStakingDataRequest_CandidateByName{
CandName: name,
},
},
}
requestData, err := proto.Marshal(readStakingdataRequest)
if err != nil {
return nil, output.NewError(output.SerializationError, "failed to marshal read staking data request", err)
}

request := &iotexapi.ReadStateRequest{
ProtocolID: []byte("staking"),
MethodName: methodData,
Arguments: [][]byte{requestData},
}

ctx := context.Background()
jwtMD, err := util.JwtAuth()
if err == nil {
ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx)
}

response, err := cli.ReadState(ctx, request)
if err != nil {
sta, ok := status.FromError(err)
if ok {
return nil, output.NewError(output.APIError, sta.Message(), nil)
}
return nil, output.NewError(output.NetworkError, "failed to invoke ReadState api", err)
}
delegate := iotextypes.CandidateV2{}
if err := proto.Unmarshal(response.Data, &delegate); err != nil {
return nil, output.NewError(output.SerializationError, "failed to unmarshal response", err)
}
return &delegate, nil
}
2 changes: 1 addition & 1 deletion ioctl/cmd/node/nodedelegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var (
}
_delegateCmdShorts = map[config.Language]string{
config.English: "Print consensus delegates information in certain epoch",
config.Chinese: "打印在特定epoch内的公认代表的信息",
config.Chinese: "打印在特定epoch内的共识代表的信息",
}
_flagEpochNumUsages = map[config.Language]string{
config.English: "specify specific epoch",
Expand Down

0 comments on commit 399238d

Please sign in to comment.