Skip to content

Commit

Permalink
[ioctl] Refactor nodereward command in new ioctl (#3416)
Browse files Browse the repository at this point in the history
* [ioctl] refactor nodereward command in new ioctl

* refactor unit test to cover the modification

* refactor new nodereward as ioctl/cmd/nodereward structure

* refactor unit test to cover the modification

* delete useless message

* fix client.APIServiceClient()

Co-authored-by: huofei <[email protected]>
Co-authored-by: CoderZhi <[email protected]>
  • Loading branch information
3 people authored Jun 25, 2022
1 parent bd7662c commit 612495d
Show file tree
Hide file tree
Showing 2 changed files with 247 additions and 156 deletions.
239 changes: 120 additions & 119 deletions ioctl/newcmd/node/nodereward.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019 IoTeX Foundation
// Copyright (c) 2022 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. 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
Expand All @@ -8,165 +8,166 @@ package node

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

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

"github.com/iotexproject/iotex-proto/golang/iotexapi"

"github.com/iotexproject/iotex-core/ioctl"
"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 (
_rewardUses = map[config.Language]string{
config.English: "reward [ALIAS|DELEGATE_ADDRESS]",
config.Chinese: "reward [别名|委托地址]",
_rewardCmdUses = map[config.Language]string{
config.English: "reward unclaimed|pool [ALIAS|DELEGATE_ADDRESS]",
config.Chinese: "reward 未支取|奖金池 [别名|委托地址]",
}
_rewardShorts = map[config.Language]string{
_rewardCmdShorts = map[config.Language]string{
config.English: "Query rewards",
config.Chinese: "查询奖励",
}
_rewardPoolMessageTranslations = map[config.Language]string{
config.English: "Available Reward: %s IOTX Total Reward: %s IOTX",
config.Chinese: "可用奖金: %s IOTX 总奖金: %s IOTX",
_rewardPoolLong = map[config.Language]string{
config.English: "ioctl node reward pool returns unclaimed and available Rewards in fund pool.\nTotalUnclaimed is the amount of all delegates that have been issued but are not claimed;\nTotalAvailable is the amount of balance that has not been issued to anyone.\n\nioctl node reward unclaimed [ALIAS|DELEGATE_ADDRESS] returns unclaimed rewards of a specific delegate.",
config.Chinese: "ioctl node reward 返回奖金池中的未支取奖励和可获取的奖励. TotalUnclaimed是所有代表已被发放但未支取的奖励的总和; TotalAvailable 是奖金池中未被发放的奖励的总和.\n\nioctl node [ALIAS|DELEGATE_ADDRESS] 返回特定代表的已被发放但未支取的奖励.",
}
)

// NewNodeRewardCmd represents the node reward command
func NewNodeRewardCmd(c ioctl.Client) *cobra.Command {
use, _ := c.SelectTranslation(_rewardUses)
short, _ := c.SelectTranslation(_rewardShorts)
rewardPoolMessageTranslation, _ := c.SelectTranslation(_rewardPoolMessageTranslations)
nc := &cobra.Command{
func NewNodeRewardCmd(client ioctl.Client) *cobra.Command {
use, _ := client.SelectTranslation(_rewardCmdUses)
short, _ := client.SelectTranslation(_rewardCmdShorts)
long, _ := client.SelectTranslation(_rewardPoolLong)

return &cobra.Command{
Use: use,
Short: short,
Args: cobra.MaximumNArgs(1),
Args: cobra.RangeArgs(1, 2),
Long: long,
RunE: func(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = true
var err error
if len(args) == 0 {

apiClient, err := c.APIServiceClient()
if err != nil {
return err
}

response, err := apiClient.ReadState(
context.Background(),
&iotexapi.ReadStateRequest{
ProtocolID: []byte("rewarding"),
MethodName: []byte("AvailableBalance"),
},
)

if err != nil {
sta, ok := status.FromError(err)
if ok {
return output.NewError(output.APIError, sta.Message(), nil)
}
return output.NewError(output.NetworkError, "failed to invoke ReadState api", err)
}

availableRewardRau, ok := new(big.Int).SetString(string(response.Data), 10)
if !ok {
return output.NewError(output.ConvertError, "failed to convert string into big int", err)
switch args[0] {
case "pool":
if len(args) != 1 {
return errors.New("wrong number of arg(s) for ioctl node reward pool command. \nRun 'ioctl node reward --help' for usage")
}

response, err = apiClient.ReadState(
context.Background(),
&iotexapi.ReadStateRequest{
ProtocolID: []byte("rewarding"),
MethodName: []byte("TotalBalance"),
},
)
totalUnclaimed, totalAvailable, totalBalance, err := rewardPool(client)
if err != nil {
sta, ok := status.FromError(err)
if ok {
return output.NewError(output.APIError, sta.Message(), nil)
}
return output.NewError(output.NetworkError, "failed to invoke ReadState api", err)
}
totalRewardRau, ok := new(big.Int).SetString(string(response.Data), 10)
if !ok {
return output.NewError(output.ConvertError, "failed to convert string into big int", err)
}

message := rewardPoolMessage{
AvailableReward: util.RauToString(availableRewardRau, util.IotxDecimalNum),
TotalReward: util.RauToString(totalRewardRau, util.IotxDecimalNum),
return err
}
fmt.Println(message.String(rewardPoolMessageTranslation))

} else {
arg := args[0]
address, err := c.Address(arg)
if err != nil {
return output.NewError(output.AddressError, "failed to get address", err)
cmd.Printf("Total Unclaimed:\t %s IOTX\nTotal Available:\t %s IOTX\nTotal Balance:\t\t %s IOTX\n",
totalUnclaimed, totalAvailable, totalBalance)
case "unclaimed":
if len(args) != 2 {
return errors.New("wrong number of arg(s) for ioctl node reward unclaimed [ALIAS|DELEGATE_ADDRESS] command. \nRun 'ioctl node reward --help' for usage")
}
apiClient, err := c.APIServiceClient()
address, reward, err := reward(client, args[1])
if err != nil {
return err
}

response, err := apiClient.ReadState(
context.Background(),
&iotexapi.ReadStateRequest{
ProtocolID: []byte("rewarding"),
MethodName: []byte("UnclaimedBalance"),
Arguments: [][]byte{[]byte(address)},
},
)
if err != nil {
sta, ok := status.FromError(err)
if ok {
return output.NewError(output.APIError, sta.Message(), nil)
}
return output.NewError(output.NetworkError, "failed to get version from server", err)
}
rewardRau, ok := new(big.Int).SetString(string(response.Data), 10)
if !ok {
return output.NewError(output.ConvertError, "failed to convert string into big int", err)
}
message := rewardMessage{Address: address, Reward: util.RauToString(rewardRau, util.IotxDecimalNum)}
fmt.Println(message.String())

cmd.Printf("%s: %s IOTX\n", address, reward)
default:
return errors.New("unknown command. \nRun 'ioctl node reward --help' for usage")
}
return output.PrintError(err)
return nil
},
}
return nc
}

type rewardPoolMessage struct {
AvailableReward string `json:"availableReward"`
TotalReward string `json:"totalReward"`
}
func rewardPool(client ioctl.Client) (string, string, string, error) {
apiClient, err := client.APIServiceClient()
if err != nil {
return "", "", "", err
}
ctx := context.Background()
jwtMD, err := util.JwtAuth()
if err == nil {
ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx)
}
response, err := apiClient.ReadState(
ctx,
&iotexapi.ReadStateRequest{
ProtocolID: []byte("rewarding"),
MethodName: []byte("AvailableBalance"),
},
)
if err != nil {
sta, ok := status.FromError(err)
if ok {
return "", "", "", errors.New(sta.Message())
}
return "", "", "", errors.Wrap(err, "failed to invoke ReadState api")
}

func (m *rewardPoolMessage) String(trans ...string) string {
availableRewardRau, ok := new(big.Int).SetString(string(response.Data), 10)
if !ok {
return "", "", "", errors.New("failed to convert string into big int")
}

if output.Format == "" {
message := fmt.Sprintf(trans[0],
m.AvailableReward, m.TotalReward)
return message
response, err = apiClient.ReadState(
context.Background(),
&iotexapi.ReadStateRequest{
ProtocolID: []byte("rewarding"),
MethodName: []byte("TotalBalance"),
},
)
if err != nil {
sta, ok := status.FromError(err)
if ok {
return "", "", "", errors.New(sta.Message())
}
return "", "", "", errors.Wrap(err, "failed to invoke ReadState api")
}
return output.FormatStringWithTrans(output.Result, m)
}
totalRewardRau, ok := new(big.Int).SetString(string(response.Data), 10)
if !ok {
return "", "", "", errors.New("failed to convert string into big int")
}

totalUnclaimedRewardRau := big.NewInt(0)
totalUnclaimedRewardRau.Sub(totalRewardRau, availableRewardRau)

type rewardMessage struct {
Address string `json:"address"`
Reward string `json:"reward"`
return util.RauToString(totalUnclaimedRewardRau, util.IotxDecimalNum),
util.RauToString(availableRewardRau, util.IotxDecimalNum),
util.RauToString(totalRewardRau, util.IotxDecimalNum),
err
}

func (m *rewardMessage) String(trans ...string) string {
if output.Format == "" {
message := fmt.Sprintf("%s: %s IOTX", m.Address, m.Reward)
return message
func reward(client ioctl.Client, arg string) (string, string, error) {
address, err := client.Address(arg)
if err != nil {
return "", "", errors.Wrap(err, "failed to get address")
}
apiClient, err := client.APIServiceClient()
if err != nil {
return "", "", errors.Wrap(err, "failed to connect to endpoint")
}
ctx := context.Background()
jwtMD, err := util.JwtAuth()
if err == nil {
ctx = metautils.NiceMD(jwtMD).ToOutgoing(ctx)
}
response, err := apiClient.ReadState(
ctx,
&iotexapi.ReadStateRequest{
ProtocolID: []byte("rewarding"),
MethodName: []byte("UnclaimedBalance"),
Arguments: [][]byte{[]byte(address)},
},
)
if err != nil {
sta, ok := status.FromError(err)
if ok {
return "", "", errors.New(sta.Message())
}
return "", "", errors.Wrap(err, "failed to get version from server")
}
rewardRau, ok := new(big.Int).SetString(string(response.Data), 10)
if !ok {
return "", "", errors.New("failed to convert string into big int")
}
return output.FormatStringWithTrans(output.Result, m)
return address, util.RauToString(rewardRau, util.IotxDecimalNum), err
}
Loading

0 comments on commit 612495d

Please sign in to comment.