github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/newcmd/bc/bc.go (about)

     1  // Copyright (c) 2022 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package bc
     7  
     8  import (
     9  	"context"
    10  	"strconv"
    11  
    12  	"github.com/grpc-ecosystem/go-grpc-middleware/util/metautils"
    13  	"github.com/iotexproject/iotex-proto/golang/iotexapi"
    14  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    15  	"github.com/pkg/errors"
    16  	"github.com/spf13/cobra"
    17  	"google.golang.org/grpc/codes"
    18  	"google.golang.org/grpc/status"
    19  	"google.golang.org/protobuf/proto"
    20  
    21  	"github.com/iotexproject/iotex-core/ioctl"
    22  	"github.com/iotexproject/iotex-core/ioctl/config"
    23  	"github.com/iotexproject/iotex-core/ioctl/util"
    24  )
    25  
    26  // Multi-language support
    27  var (
    28  	_bcCmdShorts = map[config.Language]string{
    29  		config.English: "Deal with blockchain of IoTeX blockchain",
    30  		config.Chinese: "处理IoTeX区块链上的区块",
    31  	}
    32  )
    33  
    34  // NewBCCmd represents the bc(block chain) command
    35  func NewBCCmd(client ioctl.Client) *cobra.Command {
    36  	bcShorts, _ := client.SelectTranslation(_bcCmdShorts)
    37  
    38  	bc := &cobra.Command{
    39  		Use:   "bc",
    40  		Short: bcShorts,
    41  	}
    42  	bc.AddCommand(NewBCInfoCmd(client))
    43  	bc.AddCommand(NewBCBlockCmd(client))
    44  
    45  	client.SetEndpointWithFlag(bc.PersistentFlags().StringVar)
    46  	client.SetInsecureWithFlag(bc.PersistentFlags().BoolVar)
    47  	return bc
    48  }
    49  
    50  // GetChainMeta gets blockchain metadata
    51  func GetChainMeta(client ioctl.Client) (*iotextypes.ChainMeta, error) {
    52  	apiServiceClient, err := client.APIServiceClient()
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	ctx := context.Background()
    57  	jwtMD, err := util.JwtAuth()
    58  	if err == nil {
    59  		ctx = metautils.NiceMD(jwtMD).ToOutgoing(context.Background())
    60  	}
    61  	chainMetaResponse, err := apiServiceClient.GetChainMeta(ctx, &iotexapi.GetChainMetaRequest{})
    62  	if err != nil {
    63  		if sta, ok := status.FromError(err); ok {
    64  			if sta.Code() == codes.Unavailable {
    65  				return nil, ioctl.ErrInvalidEndpointOrInsecure
    66  			}
    67  			return nil, errors.New(sta.Message())
    68  		}
    69  		return nil, errors.Wrap(err, "failed to invoke GetChainMeta api")
    70  	}
    71  	return chainMetaResponse.ChainMeta, nil
    72  }
    73  
    74  // GetEpochMeta gets blockchain epoch meta
    75  func GetEpochMeta(client ioctl.Client, epochNum uint64) (*iotexapi.GetEpochMetaResponse, error) {
    76  	apiServiceClient, err := client.APIServiceClient()
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	ctx := context.Background()
    81  	jwtMD, err := util.JwtAuth()
    82  	if err == nil {
    83  		ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx)
    84  	}
    85  	epochMetaresponse, err := apiServiceClient.GetEpochMeta(ctx, &iotexapi.GetEpochMetaRequest{EpochNumber: epochNum})
    86  	if err != nil {
    87  		if sta, ok := status.FromError(err); ok {
    88  			if sta.Code() == codes.Unavailable {
    89  				return nil, ioctl.ErrInvalidEndpointOrInsecure
    90  			}
    91  			return nil, errors.New(sta.Message())
    92  		}
    93  		return nil, errors.Wrap(err, "failed to invoke GetEpochMeta api")
    94  	}
    95  	return epochMetaresponse, nil
    96  }
    97  
    98  // GetProbationList gets probation list
    99  func GetProbationList(client ioctl.Client, epochNum uint64, epochStartHeight uint64) (*iotexapi.ReadStateResponse, error) {
   100  	apiServiceClient, err := client.APIServiceClient()
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	request := &iotexapi.ReadStateRequest{
   106  		ProtocolID: []byte("poll"),
   107  		MethodName: []byte("ProbationListByEpoch"),
   108  		Arguments:  [][]byte{[]byte(strconv.FormatUint(epochNum, 10))},
   109  		Height:     strconv.FormatUint(epochStartHeight, 10),
   110  	}
   111  	ctx := context.Background()
   112  	if jwtMD, err := util.JwtAuth(); err == nil {
   113  		ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx)
   114  	}
   115  
   116  	response, err := apiServiceClient.ReadState(ctx, request)
   117  	if err != nil {
   118  		if sta, ok := status.FromError(err); ok {
   119  			if sta.Code() == codes.NotFound {
   120  				return nil, nil
   121  			} else if sta.Code() == codes.Unavailable {
   122  				return nil, ioctl.ErrInvalidEndpointOrInsecure
   123  			}
   124  			return nil, errors.New(sta.Message())
   125  		}
   126  		return nil, errors.Wrap(err, "failed to invoke ReadState api")
   127  	}
   128  	return response, nil
   129  }
   130  
   131  // GetBucketList get bucket list
   132  func GetBucketList(
   133  	client ioctl.Client,
   134  	methodName iotexapi.ReadStakingDataMethod_Name,
   135  	readStakingDataRequest *iotexapi.ReadStakingDataRequest,
   136  ) (*iotextypes.VoteBucketList, error) {
   137  	apiServiceClient, err := client.APIServiceClient()
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  	methodData, err := proto.Marshal(&iotexapi.ReadStakingDataMethod{Method: methodName})
   142  	if err != nil {
   143  		return nil, errors.Wrap(err, "failed to marshal read staking data method")
   144  	}
   145  	requestData, err := proto.Marshal(readStakingDataRequest)
   146  	if err != nil {
   147  		return nil, errors.Wrap(err, "failed to marshal read staking data request")
   148  	}
   149  	request := &iotexapi.ReadStateRequest{
   150  		ProtocolID: []byte("staking"),
   151  		MethodName: methodData,
   152  		Arguments:  [][]byte{requestData},
   153  	}
   154  	ctx := context.Background()
   155  	if jwtMD, err := util.JwtAuth(); err == nil {
   156  		ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx)
   157  	}
   158  
   159  	response, err := apiServiceClient.ReadState(ctx, request)
   160  	if err != nil {
   161  		if sta, ok := status.FromError(err); ok {
   162  			if sta.Code() == codes.Unavailable {
   163  				return nil, ioctl.ErrInvalidEndpointOrInsecure
   164  			}
   165  			return nil, errors.New(sta.Message())
   166  		}
   167  		return nil, errors.Wrap(err, "failed to invoke ReadState api")
   168  	}
   169  	bucketlist := iotextypes.VoteBucketList{}
   170  	if err := proto.Unmarshal(response.Data, &bucketlist); err != nil {
   171  		return nil, errors.Wrap(err, "failed to unmarshal response")
   172  	}
   173  	return &bucketlist, nil
   174  }