From 4bca617bb2e52b93069c60e297e01569b16d2ae4 Mon Sep 17 00:00:00 2001 From: Frank <35358771+Frankonly@users.noreply.github.com> Date: Tue, 19 Mar 2019 17:34:44 -0700 Subject: [PATCH] Name auto match for ioctl (#778) --- cli/ioctl/cmd/account/account.go | 46 ++++++++++++++++++++++- cli/ioctl/cmd/action/action.go | 2 +- cli/ioctl/cmd/action/actionhash.go | 55 +++++++++++++++++++++++----- cli/ioctl/cmd/action/actioninvoke.go | 6 ++- cli/ioctl/cmd/node/nodedelegate.go | 25 +++++++++++-- 5 files changed, 116 insertions(+), 18 deletions(-) diff --git a/cli/ioctl/cmd/account/account.go b/cli/ioctl/cmd/account/account.go index 00b40d250c..40169e403d 100644 --- a/cli/ioctl/cmd/account/account.go +++ b/cli/ioctl/cmd/account/account.go @@ -28,6 +28,11 @@ import ( "github.com/iotexproject/iotex-core/protogen/iotextypes" ) +// Errors +var ( + ErrNoNameFound = errors.New("no name is found") +) + // AccountCmd represents the account command var AccountCmd = &cobra.Command{ Use: "account", @@ -67,14 +72,13 @@ func Sign(signer, password string, hash []byte) ([]byte, error) { return nil, errors.Errorf("account %s's address does not match with keys in keystore", signer) } -// Address returns the address corresponding to name +// Address returns the address corresponding to name, parameter in can be name or IoTeX address func Address(in string) (string, error) { if len(in) >= validator.IoAddrLen { if err := validator.ValidateAddress(in); err != nil { return "", err } return in, nil - } config, err := config.LoadConfig() if err != nil { @@ -91,6 +95,28 @@ func Address(in string) (string, error) { return "", errors.Errorf("cannot find account from #%s", in) } +// Name returns the name corresponding to address +func Name(address string) (string, error) { + if err := validator.ValidateAddress(address); err != nil { + return "", err + } + config, err := config.LoadConfig() + if err != nil { + return "", err + } + for name, addr := range config.AccountList { + if addr == address { + return name, nil + } + } + for name, addr := range config.NameList { + if addr == address { + return name, nil + } + } + return "", ErrNoNameFound +} + // GetAccountMeta gets account metadata func GetAccountMeta(addr string) (*iotextypes.AccountMeta, error) { conn, err := util.ConnectToEndpoint() @@ -108,6 +134,22 @@ func GetAccountMeta(addr string) (*iotextypes.AccountMeta, error) { return response.AccountMeta, nil } +// GetNameMap gets the map from address to names of both AccountList and NameList +func GetNameMap() (map[string]string, error) { + cfg, err := config.LoadConfig() + if err != nil { + return nil, err + } + names := make(map[string]string) + for name, addr := range cfg.NameList { + names[addr] = name + } + for name, addr := range cfg.AccountList { + names[addr] = name + } + return names, nil +} + func newAccount(name string, walletDir string) (string, error) { fmt.Printf("#%s: Set password\n", name) bytePassword, err := terminal.ReadPassword(int(syscall.Stdin)) diff --git a/cli/ioctl/cmd/action/action.go b/cli/ioctl/cmd/action/action.go index 88134ede07..b387c226e1 100644 --- a/cli/ioctl/cmd/action/action.go +++ b/cli/ioctl/cmd/action/action.go @@ -59,7 +59,7 @@ func setActionFlags(cmds ...*cobra.Command) { cmd.Flags().Uint64VarP(&gasLimit, "gas-limit", "l", 0, "set gas limit") cmd.Flags().StringVarP(&gasPrice, "gas-price", "p", "", "set gas price (unit: 10^(-6)Iotx)") - cmd.Flags().StringVarP(&signer, "signer", "s", "", "choose a signing key") + cmd.Flags().StringVarP(&signer, "signer", "s", "", "choose a signing account") cmd.Flags().Uint64VarP(&nonce, "nonce", "n", 0, "set nonce") cmd.MarkFlagRequired("gas-limit") cmd.MarkFlagRequired("gas-price") diff --git a/cli/ioctl/cmd/action/actionhash.go b/cli/ioctl/cmd/action/actionhash.go index 03712154b8..50d90d6f04 100644 --- a/cli/ioctl/cmd/action/actionhash.go +++ b/cli/ioctl/cmd/action/actionhash.go @@ -10,12 +10,14 @@ import ( "context" "errors" "fmt" + "strconv" "github.com/golang/protobuf/proto" "github.com/spf13/cobra" "go.uber.org/zap" "github.com/iotexproject/iotex-core/address" + "github.com/iotexproject/iotex-core/cli/ioctl/cmd/account" "github.com/iotexproject/iotex-core/cli/ioctl/util" "github.com/iotexproject/iotex-core/pkg/keypair" "github.com/iotexproject/iotex-core/pkg/log" @@ -97,36 +99,69 @@ func printActionProto(action *iotextypes.Action) (string, error) { return "", err } switch { - case action.Core.GetTransfer() != nil || - action.Core.GetClaimFromRewardingFund() != nil: - return fmt.Sprintf("senderAddress: %s\n", senderAddress.String()) + - proto.MarshalTextString(action.Core) + + case action.Core.GetTransfer() != nil: + transfer := action.Core.GetTransfer() + return fmt.Sprintf("senderAddress: %s %s\n", senderAddress.String(), + match(senderAddress.String(), "address")) + + "transfer: <\n" + + fmt.Sprintf(" recipient: %s %s\n", transfer.Recipient, + match(transfer.Recipient, "address")) + + fmt.Sprintf(" amount: %s\n", transfer.Amount) + + fmt.Sprintf(" payload: %x\n", transfer.Payload) + + ">\n" + fmt.Sprintf("senderPubKey: %x\n", action.SenderPubKey) + fmt.Sprintf("signature: %x\n", action.Signature), nil case action.Core.GetExecution() != nil: execution := action.Core.GetExecution() - return fmt.Sprintf("senderAddress: %s\n", senderAddress.String()) + + return fmt.Sprintf("senderAddress: %s %s\n", senderAddress.String(), + match(senderAddress.String(), "address")) + fmt.Sprintf("version: %d\n", action.Core.GetVersion()) + fmt.Sprintf("nonce: %d\n", action.Core.GetNonce()) + fmt.Sprintf("gasLimit: %d\n", action.Core.GasLimit) + fmt.Sprintf("gasPrice: %s\n", action.Core.GasPrice) + "execution: <\n" + - fmt.Sprintf(" contract: %s\n", execution.Contract) + + fmt.Sprintf(" contract: %s %s\n", execution.Contract, + match(execution.Contract, "address")) + fmt.Sprintf(" amount: %s\n", execution.Amount) + fmt.Sprintf(" data: %x\n", execution.Data) + ">\n" + fmt.Sprintf("senderPubKey: %x\n", action.SenderPubKey) + fmt.Sprintf("signature: %x\n", action.Signature), nil + case action.Core.GetClaimFromRewardingFund() != nil: + return fmt.Sprintf("senderAddress: %s %s\n", senderAddress.String(), + match(senderAddress.String(), "address")) + + proto.MarshalTextString(action.Core) + + fmt.Sprintf("senderPubKey: %x\n", action.SenderPubKey) + + fmt.Sprintf("signature: %x\n", action.Signature), nil } return "", errors.New("action can not match") } func printReceiptProto(receipt *iotextypes.Receipt) string { - status := []string{"Fail", "Success"} - return fmt.Sprintf("returnValue %x\n", receipt.ReturnValue) + - fmt.Sprintf("status: %d (%s)\n", receipt.Status, status[receipt.Status]) + + return fmt.Sprintf("returnValue: %x\n", receipt.ReturnValue) + + fmt.Sprintf("status: %d %s\n", receipt.Status, + match(strconv.Itoa(int(receipt.Status)), "status")) + fmt.Sprintf("actHash: %x\n", receipt.ActHash) + fmt.Sprintf("gasConsumed: %d\n", receipt.GasConsumed) + - fmt.Sprintf("contractAddress: %s\n", receipt.ContractAddress) + fmt.Sprintf("contractAddress: %s %s\n", receipt.ContractAddress, + match(receipt.ContractAddress, "address")) //TODO: print logs } + +func match(in string, matchType string) string { + switch matchType { + case "address": + name, err := account.Name(in) + if err != nil { + return "" + } + return "(" + name + ")" + case "status": + if in == "0" { + return "(Fail)" + } else if in == "1" { + return "(Success)" + } + } + return "" +} diff --git a/cli/ioctl/cmd/action/actioninvoke.go b/cli/ioctl/cmd/action/actioninvoke.go index a278510f88..650d803658 100644 --- a/cli/ioctl/cmd/action/actioninvoke.go +++ b/cli/ioctl/cmd/action/actioninvoke.go @@ -31,9 +31,11 @@ var actionInvokeCmd = &cobra.Command{ // invoke invokes smart contract on IoTeX blockchain func invoke(args []string) string { - contract := args[0] + contract, err := account.Address(args[0]) + if err != nil { + return err.Error() + } amount := big.NewInt(0) - var err error if len(args) == 2 { amount, err = util.StringToRau(args[1], util.IotxDecimalNum) if err != nil { diff --git a/cli/ioctl/cmd/node/nodedelegate.go b/cli/ioctl/cmd/node/nodedelegate.go index e91625f8dd..a0532cb63a 100644 --- a/cli/ioctl/cmd/node/nodedelegate.go +++ b/cli/ioctl/cmd/node/nodedelegate.go @@ -9,6 +9,7 @@ package node import ( "context" "fmt" + "strconv" "strings" "github.com/spf13/cobra" @@ -58,14 +59,32 @@ func delegate(args []string) string { return err.Error() } if len(delegate) != 0 { + name, err := account.Name(delegate) + if err != nil && err != account.ErrNoNameFound { + return err.Error() + } return fmt.Sprintf("Epoch: %d, Total blocks: %d\n", epochNum, response.TotalBlks) + - fmt.Sprintf("%s: %d", delegate, response.BlksPerDelegate[delegate]) + fmt.Sprintf("%s %s %d", delegate, name, response.BlksPerDelegate[delegate]) + } + + names, err := account.GetNameMap() + if err != nil { + return err.Error() + } + formatNameLen := 0 + for delegate := range response.BlksPerDelegate { + if len(names[delegate]) > formatNameLen { + formatNameLen = len(names[delegate]) + } } + formatTitleString := "%-41s %-" + strconv.Itoa(formatNameLen) + "s %-s" + formatDataString := "%-41s %-" + strconv.Itoa(formatNameLen) + "s %-d" lines := make([]string, 0) - lines = append(lines, fmt.Sprintf("Epoch: %d, Total blocks: %d", + lines = append(lines, fmt.Sprintf("Epoch: %d, Total blocks: %d\n", epochNum, response.TotalBlks)) + lines = append(lines, fmt.Sprintf(formatTitleString, "Address", "Name", "Blocks")) for delegate, productivity := range response.BlksPerDelegate { - lines = append(lines, fmt.Sprintf("%s: %d", delegate, productivity)) + lines = append(lines, fmt.Sprintf(formatDataString, delegate, names[delegate], productivity)) } return strings.Join(lines, "\n") }