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 }