diff --git a/ioctl/cmd/action/stake2.go b/ioctl/cmd/action/stake2.go index 22b3bce3e9..923f9b26f1 100644 --- a/ioctl/cmd/action/stake2.go +++ b/ioctl/cmd/action/stake2.go @@ -19,7 +19,7 @@ import ( var ( _stake2CmdShorts = map[config.Language]string{ config.English: "Support native staking of IoTeX blockchain", - config.Chinese: "支持来自ioctl的本地质押", + config.Chinese: "支持来自 ioctl 的本地质押", } _stake2FlagEndpointUsages = map[config.Language]string{ config.English: "set endpoint for once", @@ -27,7 +27,7 @@ var ( } _stake2FlagInsecureUsages = map[config.Language]string{ config.English: "insecure connection for once (default false)", - config.Chinese: "一次不安全的连接(默认为false)", + config.Chinese: "一次不安全的连接(默认为 false)", } _stake2FlagAutoStakeUsages = map[config.Language]string{ config.English: "auto-stake boost: the voting power will not decrease", @@ -54,6 +54,9 @@ func init() { Stake2Cmd.AddCommand(_stake2ReleaseCmd) Stake2Cmd.AddCommand(_stake2RegisterCmd) Stake2Cmd.AddCommand(_stake2ChangeCmd) + Stake2Cmd.AddCommand(_stake2EndorseCmd) + Stake2Cmd.AddCommand(_stake2UnEndorseCmd) + Stake2Cmd.AddCommand(_stake2ActivateCmd) Stake2Cmd.PersistentFlags().StringVar(&config.ReadConfig.Endpoint, "endpoint", config.ReadConfig.Endpoint, config.TranslateInLang(_stake2FlagEndpointUsages, config.UILanguage)) Stake2Cmd.PersistentFlags().BoolVar(&config.Insecure, "insecure", config.Insecure, config.TranslateInLang(_stake2FlagInsecureUsages, config.UILanguage)) } diff --git a/ioctl/cmd/action/stake2activate.go b/ioctl/cmd/action/stake2activate.go new file mode 100644 index 0000000000..1358321569 --- /dev/null +++ b/ioctl/cmd/action/stake2activate.go @@ -0,0 +1,78 @@ +package action + +import ( + "strconv" + + "github.com/spf13/cobra" + + "github.com/iotexproject/iotex-core/action" + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/output" +) + +// Multi-language support +var ( + _stake2ActivateCmdUses = map[config.Language]string{ + config.English: "activate BUCKET_INDEX" + + " [-s SIGNER] [-n NONCE] [-l GAS_LIMIT] [-p GAS_PRICE] [-P PASSWORD] [-y]", + config.Chinese: "activate 票索引" + + " [-s 签署人] [-n NONCE] [-l GAS 限制] [-p GAS 价格] [-P 密码] [-y]", + } + + _stake2ActivateCmdShorts = map[config.Language]string{ + config.English: "Activate candidate on IoTeX blockchain", + config.Chinese: "在 IoTeX 区块链上激活质押票的候选人", + } +) + +var ( + // _stake2ActivateCmd represents the stake2 transfer command + _stake2ActivateCmd = &cobra.Command{ + Use: config.TranslateInLang(_stake2ActivateCmdUses, config.UILanguage), + Short: config.TranslateInLang(_stake2ActivateCmdShorts, config.UILanguage), + Args: cobra.RangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + err := stake2Activate(args) + return output.PrintError(err) + }, + } +) + +func init() { + RegisterWriteCommand(_stake2ActivateCmd) +} + +func stake2Activate(args []string) error { + bucketIndex, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return output.NewError(output.ConvertError, "failed to convert bucket index", nil) + } + + sender, err := Signer() + if err != nil { + return output.NewError(output.AddressError, "failed to get signed address", err) + } + + gasLimit := _gasLimitFlag.Value().(uint64) + if gasLimit == 0 { + gasLimit = action.CandidateActivateBaseIntrinsicGas + } + + gasPriceRau, err := gasPriceInRau() + if err != nil { + return output.NewError(0, "failed to get gas price", err) + } + nonce, err := nonce(sender) + if err != nil { + return output.NewError(0, "failed to get nonce ", err) + } + s2t := action.NewCandidateActivate(nonce, gasLimit, gasPriceRau, bucketIndex) + return SendAction( + (&action.EnvelopeBuilder{}). + SetNonce(nonce). + SetGasPrice(gasPriceRau). + SetGasLimit(gasLimit). + SetAction(s2t).Build(), + sender) +} diff --git a/ioctl/cmd/action/stake2endorse.go b/ioctl/cmd/action/stake2endorse.go new file mode 100644 index 0000000000..7e69c36931 --- /dev/null +++ b/ioctl/cmd/action/stake2endorse.go @@ -0,0 +1,112 @@ +package action + +import ( + "strconv" + + "github.com/spf13/cobra" + + "github.com/iotexproject/iotex-core/action" + "github.com/iotexproject/iotex-core/ioctl/config" + "github.com/iotexproject/iotex-core/ioctl/output" +) + +// Multi-language support +var ( + _stake2EndorseCmdUses = map[config.Language]string{ + config.English: "endorse BUCKET_INDEX" + + " [-s SIGNER] [-n NONCE] [-l GAS_LIMIT] [-p GAS_PRICE] [-P PASSWORD] [-y]", + config.Chinese: "endorse 票索引" + + " [-s 签署人] [-n NONCE] [-l GAS 限制] [-p GAS 价格] [-P 密码] [-y]", + } + _stake2UnEndorseCmdUses = map[config.Language]string{ + config.English: "unendorse BUCKET_INDEX" + + " [-s SIGNER] [-n NONCE] [-l GAS_LIMIT] [-p GAS_PRICE] [-P PASSWORD] [-y]", + config.Chinese: "unendorse 票索引" + + " [-s 签署人] [-n NONCE] [-l GAS 限制] [-p GAS 价格] [-P 密码] [-y]", + } + + _stake2EndorseCmdShorts = map[config.Language]string{ + config.English: "Endorse bucket's candidate on IoTeX blockchain", + config.Chinese: "在 IoTeX 区块链上背书候选人", + } + _stake2UnEndorseCmdShorts = map[config.Language]string{ + config.English: "UnEndorse bucket's candidate on IoTeX blockchain", + config.Chinese: "在 IoTeX 区块链上撤销背书", + } +) + +var ( + // _stake2EndorseCmd represents the stake2 transfer command + _stake2EndorseCmd = &cobra.Command{ + Use: config.TranslateInLang(_stake2EndorseCmdUses, config.UILanguage), + Short: config.TranslateInLang(_stake2EndorseCmdShorts, config.UILanguage), + Args: cobra.RangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + err := stake2Endorse(args) + return output.PrintError(err) + }, + } + _stake2UnEndorseCmd = &cobra.Command{ + Use: config.TranslateInLang(_stake2UnEndorseCmdUses, config.UILanguage), + Short: config.TranslateInLang(_stake2UnEndorseCmdShorts, config.UILanguage), + Args: cobra.RangeArgs(1, 2), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.SilenceUsage = true + err := stake2UnEndorse(args) + return output.PrintError(err) + }, + } +) + +func init() { + RegisterWriteCommand(_stake2EndorseCmd) + RegisterWriteCommand(_stake2UnEndorseCmd) +} + +func stake2UnEndorse(args []string) error { + bucketIndex, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return output.NewError(output.ConvertError, "failed to convert bucket index", nil) + } + + return doEndorsement(bucketIndex, false) +} + +func stake2Endorse(args []string) error { + bucketIndex, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return output.NewError(output.ConvertError, "failed to convert bucket index", nil) + } + + return doEndorsement(bucketIndex, true) +} + +func doEndorsement(bucketIndex uint64, isEndorse bool) error { + sender, err := Signer() + if err != nil { + return output.NewError(output.AddressError, "failed to get signed address", err) + } + + gasLimit := _gasLimitFlag.Value().(uint64) + if gasLimit == 0 { + gasLimit = action.CandidateEndorsementBaseIntrinsicGas + } + + gasPriceRau, err := gasPriceInRau() + if err != nil { + return output.NewError(0, "failed to get gas price", err) + } + nonce, err := nonce(sender) + if err != nil { + return output.NewError(0, "failed to get nonce ", err) + } + s2t := action.NewCandidateEndorsement(nonce, gasLimit, gasPriceRau, bucketIndex, isEndorse) + return SendAction( + (&action.EnvelopeBuilder{}). + SetNonce(nonce). + SetGasPrice(gasPriceRau). + SetGasLimit(gasLimit). + SetAction(s2t).Build(), + sender) +}