From af851a5d12609c280f895dcb05101bf1471b5a6d Mon Sep 17 00:00:00 2001 From: Mantre Date: Mon, 11 Sep 2023 03:45:33 +0800 Subject: [PATCH] fix: fixing wallet-cli issues (#686) --- cmd/cmd.go | 14 ++++- cmd/daemon/init.go | 4 +- cmd/daemon/main.go | 17 +++--- cmd/daemon/start.go | 4 +- cmd/wallet/address.go | 83 +++++++++++++-------------- cmd/wallet/create.go | 24 ++++---- cmd/wallet/history.go | 29 ++++++---- cmd/wallet/main.go | 31 +++++----- cmd/wallet/recover.go | 28 +++++---- cmd/wallet/tx.go | 129 +++++++++++++++++++++--------------------- wallet/errors.go | 17 +++--- wallet/servers.json | 6 +- wallet/store.go | 8 ++- wallet/wallet.go | 4 +- wallet/wallet_test.go | 9 ++- 15 files changed, 223 insertions(+), 184 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index 06e2bf369..dace04ab3 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -360,13 +360,23 @@ func StartNode(workingDir string, passwordFetcher func(*wallet.Wallet) (string, // Now, attempt to restore the config file with the number of validators from the old config. switch gen.ChainType() { + case genesis.Mainnet: + panic("not yet implemented!") + case genesis.Testnet: err = config.SaveTestnetConfig(confPath, confBack.Node.NumValidators) if err != nil { return nil, nil, err } - case genesis.Mainnet: - panic("not yet implemented!") + + case genesis.Localnet: + err = config.SaveLocalnetConfig(confPath, confBack.Node.NumValidators) + if err != nil { + return nil, nil, err + } + + default: + return nil, nil, fmt.Errorf("invalid chain type") } PrintSuccessMsgf("Config restored to the default values") diff --git a/cmd/daemon/init.go b/cmd/daemon/init.go index 85fd8531a..264ead395 100644 --- a/cmd/daemon/init.go +++ b/cmd/daemon/init.go @@ -10,11 +10,11 @@ import ( "github.com/spf13/cobra" ) -// BuildInitCmd builds the init command for the Pactus blockchain. +// buildInitCmd builds a sub-command to initialized the Pactus blockchain node. func buildInitCmd(parentCmd *cobra.Command) { initCmd := &cobra.Command{ Use: "init", - Short: "Initialize the Pactus blockchain", + Short: "Initialize the Pactus blockchain node", } parentCmd.AddCommand(initCmd) workingDirOpt := initCmd.Flags().StringP("working-dir", "w", diff --git a/cmd/daemon/main.go b/cmd/daemon/main.go index 2acb870ed..9a8bd353c 100644 --- a/cmd/daemon/main.go +++ b/cmd/daemon/main.go @@ -1,25 +1,26 @@ package main import ( - "fmt" - + "github.com/pactus-project/pactus/cmd" "github.com/spf13/cobra" ) func main() { rootCmd := &cobra.Command{ - Use: "pactus-daemon", - Short: "Pactus daemon", - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("use --help") - }, + Use: "pactus-daemon", + Short: "Pactus daemon", + CompletionOptions: cobra.CompletionOptions{HiddenDefaultCmd: true}, } + // Hide the "help" sub-command + rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) + buildVersionCmd(rootCmd) buildInitCmd(rootCmd) buildStartCmd(rootCmd) + err := rootCmd.Execute() if err != nil { - panic(err) + cmd.PrintErrorMsgf("%s", err) } } diff --git a/cmd/daemon/start.go b/cmd/daemon/start.go index d1d985989..364ec4e47 100644 --- a/cmd/daemon/start.go +++ b/cmd/daemon/start.go @@ -12,11 +12,11 @@ import ( "github.com/spf13/cobra" ) -// Start starts the pactus node. +// buildStartCmd builds a sub-command to starts the Pactus blockchain node. func buildStartCmd(parentCmd *cobra.Command) { startCmd := &cobra.Command{ Use: "start", - Short: "Start the Pactus blockchain", + Short: "Start the Pactus blockchain node", } parentCmd.AddCommand(startCmd) diff --git a/cmd/wallet/address.go b/cmd/wallet/address.go index 0b70183c6..97f6b3c70 100644 --- a/cmd/wallet/address.go +++ b/cmd/wallet/address.go @@ -9,10 +9,11 @@ import ( "github.com/spf13/cobra" ) +// buildAllAddrCmd builds all sub-commands related to addresses. func buildAllAddrCmd(parentCmd *cobra.Command) { addrCmd := &cobra.Command{ Use: "address", - Short: "Manage address book", + Short: "Manage the address book", } parentCmd.AddCommand(addrCmd) @@ -25,19 +26,19 @@ func buildAllAddrCmd(parentCmd *cobra.Command) { buildSetLabelCmd(addrCmd) } -// AllAddresses lists all the wallet addresses. +// buildAllAddressesCmd builds a command to list all addresses from the wallet. func buildAllAddressesCmd(parentCmd *cobra.Command) { allAddressCmd := &cobra.Command{ Use: "all", - Short: "Show all addresses", + Short: "Display all stored addresses", } parentCmd.AddCommand(allAddressCmd) balanceOpt := allAddressCmd.Flags().Bool("balance", - false, "show account balance") + false, "Display the account balance for each address") stakeOpt := allAddressCmd.Flags().Bool("stake", - false, "show validator stake") + false, "Display the validator stake for each address") allAddressCmd.Run = func(_ *cobra.Command, _ []string) { wallet, err := openWallet() @@ -67,11 +68,11 @@ func buildAllAddressesCmd(parentCmd *cobra.Command) { } } -// NewAddress creates a new address. +// buildNewAddressCmd builds a command for creating a new wallet address. func buildNewAddressCmd(parentCmd *cobra.Command) { newAddressCmd := &cobra.Command{ Use: "new", - Short: "Creating a new address", + Short: "Create a new address", } parentCmd.AddCommand(newAddressCmd) @@ -91,25 +92,26 @@ func buildNewAddressCmd(parentCmd *cobra.Command) { } } -// Balance shows the balance of an address. +// buildBalanceCmd builds a command to display the balance of a given address. func buildBalanceCmd(parentCmd *cobra.Command) { balanceCmd := &cobra.Command{ - Use: "balance", - Short: "Show the balance of an address", + Use: "balance [flags]
", + Short: "Display the balance of an address", + Args: cobra.ExactArgs(1), } parentCmd.AddCommand(balanceCmd) - addrArg := addAddressArg(parentCmd) + balanceCmd.Run = func(_ *cobra.Command, args []string) { + addr := args[0] - balanceCmd.Run = func(_ *cobra.Command, _ []string) { wallet, err := openWallet() cmd.FatalErrorCheck(err) cmd.PrintLine() - balance, err := wallet.Balance(*addrArg) + balance, err := wallet.Balance(addr) cmd.FatalErrorCheck(err) - stake, err := wallet.Stake(*addrArg) + stake, err := wallet.Stake(addr) cmd.FatalErrorCheck(err) cmd.PrintInfoMsgf("balance: %v\tstake: %v", @@ -117,23 +119,25 @@ func buildBalanceCmd(parentCmd *cobra.Command) { } } -// PrivateKey returns the private key of an address. +// buildPrivateKeyCmd builds a command to show the private key of a given address. func buildPrivateKeyCmd(parentCmd *cobra.Command) { privateKeyCmd := &cobra.Command{ - Use: "priv", - Short: "Show the private key of an address", + Use: "priv [flags]
", + Short: "Display the private key for a specified address", + Args: cobra.ExactArgs(1), } parentCmd.AddCommand(privateKeyCmd) - addrArg := addAddressArg(parentCmd) - passOpt := addPasswordOption(parentCmd) + passOpt := addPasswordOption(privateKeyCmd) + + privateKeyCmd.Run = func(_ *cobra.Command, args []string) { + addr := args[0] - privateKeyCmd.Run = func(_ *cobra.Command, _ []string) { wallet, err := openWallet() cmd.FatalErrorCheck(err) password := getPassword(wallet, *passOpt) - prv, err := wallet.PrivateKey(password, *addrArg) + prv, err := wallet.PrivateKey(password, addr) cmd.FatalErrorCheck(err) cmd.PrintLine() @@ -141,21 +145,22 @@ func buildPrivateKeyCmd(parentCmd *cobra.Command) { } } -// PublicKey returns the public key of an address. +// buildPublicKeyCmd builds a command to show the public key of a given address. func buildPublicKeyCmd(parentCmd *cobra.Command) { publicKeyCmd := &cobra.Command{ - Use: "pub", - Short: "Show the public key of an address", + Use: "pub [flags]
", + Short: "Display the public key for a specified address", + Args: cobra.ExactArgs(1), } parentCmd.AddCommand(publicKeyCmd) - addrArg := addAddressArg(parentCmd) + publicKeyCmd.Run = func(_ *cobra.Command, args []string) { + addr := args[0] - publicKeyCmd.Run = func(_ *cobra.Command, _ []string) { wallet, err := openWallet() cmd.FatalErrorCheck(err) - info := wallet.AddressInfo(*addrArg) + info := wallet.AddressInfo(addr) if info == nil { cmd.PrintErrorMsgf("Address not found") return @@ -169,7 +174,7 @@ func buildPublicKeyCmd(parentCmd *cobra.Command) { } } -// ImportPrivateKey imports a private key into the wallet. +// buildImportPrivateKeyCmd build a command to import a private key into the wallet. func buildImportPrivateKeyCmd(parentCmd *cobra.Command) { importPrivateKeyCmd := &cobra.Command{ Use: "import", @@ -177,7 +182,7 @@ func buildImportPrivateKeyCmd(parentCmd *cobra.Command) { } parentCmd.AddCommand(importPrivateKeyCmd) - passOpt := addPasswordOption(parentCmd) + passOpt := addPasswordOption(importPrivateKeyCmd) importPrivateKeyCmd.Run = func(_ *cobra.Command, _ []string) { prvStr := cmd.PromptInput("Private Key") @@ -201,24 +206,25 @@ func buildImportPrivateKeyCmd(parentCmd *cobra.Command) { } } -// SetLabel set label for the address. +// buildSetLabelCmd build a command to set or update the label for an address. func buildSetLabelCmd(parentCmd *cobra.Command) { setLabelCmd := &cobra.Command{ - Use: "label", - Short: "Set label for the an address", + Use: "label [flags]
", + Short: "Assign or update a label for a specific address", + Args: cobra.ExactArgs(1), } parentCmd.AddCommand(setLabelCmd) - addrArg := addAddressArg(parentCmd) + setLabelCmd.Run = func(c *cobra.Command, args []string) { + addr := args[0] - setLabelCmd.Run = func(_ *cobra.Command, _ []string) { wallet, err := openWallet() cmd.FatalErrorCheck(err) - oldLabel := wallet.Label(*addrArg) + oldLabel := wallet.Label(addr) newLabel := cmd.PromptInputWithSuggestion("Label", oldLabel) - err = wallet.SetLabel(*addrArg, newLabel) + err = wallet.SetLabel(addr, newLabel) cmd.FatalErrorCheck(err) err = wallet.Save() @@ -228,8 +234,3 @@ func buildSetLabelCmd(parentCmd *cobra.Command) { cmd.PrintSuccessMsgf("Label set successfully") } } - -func addAddressArg(c *cobra.Command) *string { - return c.Flags().String("ADDRESS", - "", "address string") -} diff --git a/cmd/wallet/create.go b/cmd/wallet/create.go index a88d3be1f..87ef3acb3 100644 --- a/cmd/wallet/create.go +++ b/cmd/wallet/create.go @@ -7,16 +7,18 @@ import ( "github.com/spf13/cobra" ) -// Generate creates a new wallet. -func buildGenerateCmd(parentCmd *cobra.Command) { +// buildCreateCmd builds a command to create a new wallet. +func buildCreateCmd(parentCmd *cobra.Command) { generateCmd := &cobra.Command{ Use: "create", Short: "Create a new wallet", } parentCmd.AddCommand(generateCmd) - testnetOpt := generateCmd.Flags().Bool("testnet", false, "creating wallet for testnet") - entropyOpt := generateCmd.Flags().Int("entropy", 128, "Entropy bit length") + testnetOpt := generateCmd.Flags().Bool("testnet", false, + "Create a wallet for the testnet environment") + entropyOpt := generateCmd.Flags().Int("entropy", 128, + "Specify the entropy bit length") generateCmd.Run = func(_ *cobra.Command, _ []string) { password := cmd.PromptPassword("Password", true) @@ -26,28 +28,28 @@ func buildGenerateCmd(parentCmd *cobra.Command) { if *testnetOpt { network = genesis.Testnet } - wallet, err := wallet.Create(*pathArg, mnemonic, password, network) + wallet, err := wallet.Create(*pathOpt, mnemonic, password, network) cmd.FatalErrorCheck(err) err = wallet.Save() cmd.FatalErrorCheck(err) cmd.PrintLine() - cmd.PrintSuccessMsgf("Wallet created successfully at: %s", wallet.Path()) - cmd.PrintInfoMsgf("Seed: \"%v\"", mnemonic) + cmd.PrintSuccessMsgf("Your wallet was successfully created at: %s", wallet.Path()) + cmd.PrintInfoMsgf("Seed phrase: \"%v\"", mnemonic) cmd.PrintWarnMsgf("Please keep your seed in a safe place; " + "if you lose it, you will not be able to restore your wallet.") } } -// ChangePassword updates the wallet password. +// buildChangePasswordCmd builds a command to update the wallet's password. func buildChangePasswordCmd(parentCmd *cobra.Command) { changePasswordCmd := &cobra.Command{ Use: "password", - Short: "Change wallet password", + Short: "Change the wallet's password", } parentCmd.AddCommand(changePasswordCmd) - passOpt := addPasswordOption(parentCmd) + passOpt := addPasswordOption(changePasswordCmd) changePasswordCmd.Run = func(_ *cobra.Command, _ []string) { wallet, err := openWallet() @@ -63,6 +65,6 @@ func buildChangePasswordCmd(parentCmd *cobra.Command) { cmd.FatalErrorCheck(err) cmd.PrintLine() - cmd.PrintWarnMsgf("Wallet password updated") + cmd.PrintWarnMsgf("Your wallet password successfully updated.") } } diff --git a/cmd/wallet/history.go b/cmd/wallet/history.go index 3dbd5acb1..78662f3da 100644 --- a/cmd/wallet/history.go +++ b/cmd/wallet/history.go @@ -8,10 +8,11 @@ import ( "github.com/spf13/cobra" ) +// buildAllHistoryCmd builds all sub-commands related to the wallet history. func buildAllHistoryCmd(parentCmd *cobra.Command) { historyCmd := &cobra.Command{ Use: "history", - Short: "Check the wallet history", + Short: "Retrieve the transaction history of the wallet.", } parentCmd.AddCommand(historyCmd) @@ -19,20 +20,21 @@ func buildAllHistoryCmd(parentCmd *cobra.Command) { buildShowHistoryCmd(historyCmd) } +// buildAddToHistoryCmd builds a command for adding a transaction to the wallet's history. func buildAddToHistoryCmd(parentCmd *cobra.Command) { addToHistoryCmd := &cobra.Command{ - Use: "add", - Short: "Add a transaction to the wallet history", + Use: "add [flags] ", + Short: "Add a transaction to the wallet's history.", } parentCmd.AddCommand(addToHistoryCmd) - txID := addToHistoryCmd.Flags().String("ID", "", "transaction id") + addToHistoryCmd.Run = func(_ *cobra.Command, args []string) { + txID := args[0] - addToHistoryCmd.Run = func(_ *cobra.Command, _ []string) { wallet, err := openWallet() cmd.FatalErrorCheck(err) - id, err := hash.FromString(*txID) + id, err := hash.FromString(txID) cmd.FatalErrorCheck(err) err = wallet.AddTransaction(id) @@ -41,23 +43,26 @@ func buildAddToHistoryCmd(parentCmd *cobra.Command) { err = wallet.Save() cmd.FatalErrorCheck(err) - cmd.PrintInfoMsgf("Transaction added to wallet") + cmd.PrintInfoMsgf("Transaction successfully added to the wallet.") } } +// buildShowHistoryCmd builds a command for displaying the transaction history of a specific address. func buildShowHistoryCmd(parentCmd *cobra.Command) { showHistoryCmd := &cobra.Command{ - Use: "get", - Short: "Show the transaction history of any address", + Use: "get [flags]
", + Short: "Display the transaction history for a given address.", + Args: cobra.ExactArgs(1), } parentCmd.AddCommand(showHistoryCmd) - addrArg := addAddressArg(parentCmd) - showHistoryCmd.Run = func(_ *cobra.Command, _ []string) { + showHistoryCmd.Run = func(_ *cobra.Command, args []string) { + addr := args[0] + wallet, err := openWallet() cmd.FatalErrorCheck(err) - history := wallet.GetHistory(*addrArg) + history := wallet.GetHistory(addr) for i, h := range history { if h.Time != nil { cmd.PrintInfoMsgf("%d %v %v %v %s\t%v", diff --git a/cmd/wallet/main.go b/cmd/wallet/main.go index cc1fdd855..fb63fa783 100644 --- a/cmd/wallet/main.go +++ b/cmd/wallet/main.go @@ -3,12 +3,13 @@ package main import ( "fmt" + "github.com/pactus-project/pactus/cmd" "github.com/pactus-project/pactus/wallet" "github.com/spf13/cobra" ) var ( - pathArg *string + pathOpt *string offlineOpt *bool serverAddrOpt *string ) @@ -20,7 +21,7 @@ func addPasswordOption(c *cobra.Command) *string { func openWallet() (*wallet.Wallet, error) { if !*offlineOpt && *serverAddrOpt != "" { - wallet, err := wallet.Open(*pathArg, true) + wallet, err := wallet.Open(*pathOpt, true) if err != nil { return nil, err } @@ -32,7 +33,7 @@ func openWallet() (*wallet.Wallet, error) { } return wallet, err } - wallet, err := wallet.Open(*pathArg, *offlineOpt) + wallet, err := wallet.Open(*pathOpt, *offlineOpt) if err != nil { return nil, err } @@ -41,30 +42,28 @@ func openWallet() (*wallet.Wallet, error) { func main() { rootCmd := &cobra.Command{ - Use: "pactus-wallet", - Short: "Pactus wallet", - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("use --help") - }, + Use: "pactus-wallet", + Short: "Pactus wallet", + CompletionOptions: cobra.CompletionOptions{HiddenDefaultCmd: true}, } - pathArg = rootCmd.Flags().String("PATH", "", "the path to the wallet file") - offlineOpt = rootCmd.Flags().Bool("offline", false, "offline mode") - serverAddrOpt = rootCmd.Flags().String("server", "", "server gRPC address") + // Hide the "help" sub-command + rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) - buildGenerateCmd(rootCmd) + pathOpt = rootCmd.PersistentFlags().String("path", "default_wallet", "the path to the wallet file") + offlineOpt = rootCmd.PersistentFlags().Bool("offline", false, "offline mode") + serverAddrOpt = rootCmd.PersistentFlags().String("server", "", "server gRPC address") + + buildCreateCmd(rootCmd) buildRecoverCmd(rootCmd) buildGetSeedCmd(rootCmd) buildChangePasswordCmd(rootCmd) - // transaction commands buildAllTransactionCmd(rootCmd) - // address commands buildAllAddrCmd(rootCmd) - // history commands buildAllHistoryCmd(rootCmd) err := rootCmd.Execute() if err != nil { - panic(err) + cmd.PrintErrorMsgf("%s", err) } } diff --git a/cmd/wallet/recover.go b/cmd/wallet/recover.go index 5a8c56963..0c2cf31a5 100644 --- a/cmd/wallet/recover.go +++ b/cmd/wallet/recover.go @@ -2,11 +2,12 @@ package main import ( "github.com/pactus-project/pactus/cmd" + "github.com/pactus-project/pactus/genesis" "github.com/pactus-project/pactus/wallet" "github.com/spf13/cobra" ) -// Recover recovers a wallet from mnemonic (seed phrase). +// buildRecoverCmd builds a command to recover a wallet using a mnemonic (seed phrase). func buildRecoverCmd(parentCmd *cobra.Command) { recoverCmd := &cobra.Command{ Use: "recover", @@ -14,37 +15,40 @@ func buildRecoverCmd(parentCmd *cobra.Command) { } parentCmd.AddCommand(recoverCmd) - passwordOpt := addPasswordOption(parentCmd) - - seedOpt := recoverCmd.Flags().StringP("seed", "s", "", "wallet seed phrase (mnemonic)") + passOpt := addPasswordOption(recoverCmd) + testnetOpt := recoverCmd.Flags().Bool("testnet", true, + "Recover the wallet for the testnet environment") + seedOpt := recoverCmd.Flags().StringP("seed", "s", "", "Mnemonic (seed phrase) used for wallet recovery") recoverCmd.Run = func(_ *cobra.Command, _ []string) { mnemonic := *seedOpt if mnemonic == "" { mnemonic = cmd.PromptInput("Seed") } - password := *passwordOpt - - wallet, err := wallet.Create(*pathArg, mnemonic, password, 0) + chainType := genesis.Mainnet + if *testnetOpt { + chainType = genesis.Testnet + } + wallet, err := wallet.Create(*pathOpt, mnemonic, *passOpt, chainType) cmd.FatalErrorCheck(err) err = wallet.Save() cmd.FatalErrorCheck(err) cmd.PrintLine() - cmd.PrintInfoMsgf("Wallet recovered successfully at: %s", wallet.Path()) + cmd.PrintInfoMsgf("Wallet successfully recovered and saved at: %s", wallet.Path()) } } -// GetSeed prints the seed phrase (mnemonics). +// buildGetSeedCmd builds a command to display the wallet's mnemonic (seed phrase). func buildGetSeedCmd(parentCmd *cobra.Command) { getSeedCmd := &cobra.Command{ Use: "seed", - Short: "Show secret seed phrase (mnemonic) that can be used to recover this wallet", + Short: "Display the mnemonic (seed phrase) that can be used to recover this wallet", } parentCmd.AddCommand(getSeedCmd) - passOpt := addPasswordOption(parentCmd) + passOpt := addPasswordOption(getSeedCmd) getSeedCmd.Run = func(_ *cobra.Command, _ []string) { wallet, err := openWallet() @@ -55,6 +59,6 @@ func buildGetSeedCmd(parentCmd *cobra.Command) { cmd.FatalErrorCheck(err) cmd.PrintLine() - cmd.PrintInfoMsgf("Seed: \"%v\"", mnemonic) + cmd.PrintInfoMsgf("Your wallet's seed phrase is: \"%v\"", mnemonic) } } diff --git a/cmd/wallet/tx.go b/cmd/wallet/tx.go index cf0c53a76..1a38cd2fc 100644 --- a/cmd/wallet/tx.go +++ b/cmd/wallet/tx.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/cobra" ) +// buildAllTransactionCmd builds all sub-commands related to the transactions. func buildAllTransactionCmd(parentCmd *cobra.Command) { txCmd := &cobra.Command{ Use: "tx", @@ -21,21 +22,24 @@ func buildAllTransactionCmd(parentCmd *cobra.Command) { buildWithdrawTxCmd(txCmd) } +// buildTransferTxCmd builds a command for create, sign and publish a `Transfer` transaction. func buildTransferTxCmd(parentCmd *cobra.Command) { transferCmd := &cobra.Command{ - Use: "transfer", - Short: "Create, sign and publish a Transfer transaction", + Use: "transfer [flags] ", + Short: "Create, sign and publish a `Transfer` transaction", + Args: cobra.ExactArgs(3), } parentCmd.AddCommand(transferCmd) - fromArg := transferCmd.Flags().String("FROM", "", "sender address") - toArg := transferCmd.Flags().String("TO", "", "receiver address") - amtArg := transferCmd.Flags().Float64("AMOUNT", 0, "the amount to be transferred") + stampOpt, seqOpt, feeOpt, memoOpt, noConfirmOpt := addCommonTxOptions(transferCmd) + passOpt := addPasswordOption(transferCmd) - stampOpt, seqOpt, feeOpt, memoOpt, noConfirmOpt := addCommonTxOptions(parentCmd) - passOpt := addPasswordOption(parentCmd) + transferCmd.Run = func(_ *cobra.Command, args []string) { + from := args[0] + to := args[1] + amount, err := util.StringToChange(args[2]) + cmd.FatalErrorCheck(err) - transferCmd.Run = func(_ *cobra.Command, _ []string) { w, err := openWallet() cmd.FatalErrorCheck(err) @@ -46,37 +50,39 @@ func buildTransferTxCmd(parentCmd *cobra.Command) { wallet.OptionMemo(*memoOpt), } - trx, err := w.MakeTransferTx(*fromArg, *toArg, util.CoinToChange(*amtArg), - opts...) + trx, err := w.MakeTransferTx(from, to, amount, opts...) cmd.FatalErrorCheck(err) cmd.PrintLine() - cmd.PrintInfoMsgf("You are going to sign this \033[1mSend\033[0m transition:") - cmd.PrintInfoMsgf("From : %s", *fromArg) - cmd.PrintInfoMsgf("To : %s", *toArg) - cmd.PrintInfoMsgf("Amount: %.9f", *amtArg) + cmd.PrintInfoMsgf("You are going to sign this \033[1mTransfer\033[0m transition:") + cmd.PrintInfoMsgf("From : %s", from) + cmd.PrintInfoMsgf("To : %s", to) + cmd.PrintInfoMsgf("Amount: %.9f", util.ChangeToCoin(amount)) cmd.PrintInfoMsgf("Fee : %.9f", util.ChangeToCoin(trx.Fee())) signAndPublishTx(w, trx, *noConfirmOpt, *passOpt) } } +// buildBondTxCmd builds a command for create, sign and publish a `Bond` transaction. func buildBondTxCmd(parentCmd *cobra.Command) { - bondTransactionCmd := &cobra.Command{ - Use: "bond", - Short: "Create, sign and publish a Bond transaction", + bondCmd := &cobra.Command{ + Use: "bond [flags] ", + Short: "Create, sign and publish a `Bond` transaction", + Args: cobra.ExactArgs(3), } - parentCmd.AddCommand(bondTransactionCmd) + parentCmd.AddCommand(bondCmd) - fromArg := bondTransactionCmd.Flags().String("FROM", "", "sender address") - toArg := bondTransactionCmd.Flags().String("TO", "", "receiver validator address") - amtArg := bondTransactionCmd.Flags().Float64("STAKE", 0, "stake amount") - pubKeyOpt := bondTransactionCmd.Flags().String("pub", "", "validator public key") + pubKeyOpt := bondCmd.Flags().String("pub", "", "Validator's public key") + stampOpt, seqOpt, feeOpt, memoOpt, noConfirmOpt := addCommonTxOptions(bondCmd) + passOpt := addPasswordOption(bondCmd) - stampOpt, seqOpt, feeOpt, memoOpt, noConfirmOpt := addCommonTxOptions(parentCmd) - passOpt := addPasswordOption(parentCmd) + bondCmd.Run = func(_ *cobra.Command, args []string) { + from := args[0] + to := args[1] + amount, err := util.StringToChange(args[2]) + cmd.FatalErrorCheck(err) - bondTransactionCmd.Run = func(_ *cobra.Command, _ []string) { w, err := openWallet() cmd.FatalErrorCheck(err) @@ -87,35 +93,35 @@ func buildBondTxCmd(parentCmd *cobra.Command) { wallet.OptionMemo(*memoOpt), } - trx, err := w.MakeBondTx(*fromArg, *toArg, *pubKeyOpt, - util.CoinToChange(*amtArg), opts...) + trx, err := w.MakeBondTx(from, to, *pubKeyOpt, amount, opts...) cmd.FatalErrorCheck(err) cmd.PrintLine() cmd.PrintInfoMsgf("You are going to sign this \033[1mBond\033[0m transition:") - cmd.PrintInfoMsgf("Account : %s", *fromArg) - cmd.PrintInfoMsgf("Validator: %s", *toArg) - cmd.PrintInfoMsgf("Amount : %.9f", *amtArg) + cmd.PrintInfoMsgf("Account : %s", from) + cmd.PrintInfoMsgf("Validator: %s", to) + cmd.PrintInfoMsgf("Stake : %.9f", util.ChangeToCoin(amount)) cmd.PrintInfoMsgf("Fee : %.9f", util.ChangeToCoin(trx.Fee())) signAndPublishTx(w, trx, *noConfirmOpt, *passOpt) } } +// buildBondTxCmd builds a command for create, sign and publish a `Unbond` transaction. func buildUnbondTxCmd(parentCmd *cobra.Command) { - unbondTransactionCmd := &cobra.Command{ - Use: "unbond", - Short: "Create, sign and publish an Unbond transaction", + unbondCmd := &cobra.Command{ + Use: "unbond [flags]
", + Short: "Create, sign and publish an `Unbond` transaction", + Args: cobra.ExactArgs(1), } - parentCmd.AddCommand(unbondTransactionCmd) + parentCmd.AddCommand(unbondCmd) - fromArg := unbondTransactionCmd.Flags().String("ADDR", "", - "validator's address") + stampOpt, seqOpt, feeOpt, memoOpt, noConfirmOpt := addCommonTxOptions(unbondCmd) + passOpt := addPasswordOption(unbondCmd) - stampOpt, seqOpt, feeOpt, memoOpt, noConfirmOpt := addCommonTxOptions(parentCmd) - passOpt := addPasswordOption(parentCmd) + unbondCmd.Run = func(_ *cobra.Command, args []string) { + from := args[0] - unbondTransactionCmd.Run = func(_ *cobra.Command, _ []string) { w, err := openWallet() cmd.FatalErrorCheck(err) @@ -126,38 +132,36 @@ func buildUnbondTxCmd(parentCmd *cobra.Command) { wallet.OptionMemo(*memoOpt), } - trx, err := w.MakeUnbondTx(*fromArg, opts...) + trx, err := w.MakeUnbondTx(from, opts...) cmd.FatalErrorCheck(err) cmd.PrintLine() cmd.PrintInfoMsgf("You are going to sign this \033[1mUnbond\033[0m transition:") - cmd.PrintInfoMsgf("Validator: %s", *fromArg) + cmd.PrintInfoMsgf("Validator: %s", from) cmd.PrintInfoMsgf("Fee : %.9f", util.ChangeToCoin(trx.Fee())) signAndPublishTx(w, trx, *noConfirmOpt, *passOpt) } } +// buildWithdrawTxCmd builds a command for create, sign and publish a `Withdraw` transaction. func buildWithdrawTxCmd(parentCmd *cobra.Command) { - withdrawTransactionCmd := &cobra.Command{ - Use: "withdraw", - Short: "Create, sign and publish a Withdraw transaction", + withdrawCmd := &cobra.Command{ + Use: "withdraw [flags] ", + Short: "Create, sign and publish a `Withdraw` transaction", + Args: cobra.ExactArgs(3), } - parentCmd.AddCommand(withdrawTransactionCmd) - - fromArg := withdrawTransactionCmd.Flags().String("FROM", - "", "withdraw from Validator address") + parentCmd.AddCommand(withdrawCmd) - toArg := withdrawTransactionCmd.Flags().String("TO", - "", "deposit to account address") + stampOpt, seqOpt, feeOpt, memoOpt, noConfirmOpt := addCommonTxOptions(withdrawCmd) + passOpt := addPasswordOption(withdrawCmd) - amtArg := withdrawTransactionCmd.Flags().Float64("AMOUNT", - 0, "the amount to be transferred") - - stampOpt, seqOpt, feeOpt, memoOpt, noConfirmOpt := addCommonTxOptions(parentCmd) - passOpt := addPasswordOption(parentCmd) + withdrawCmd.Run = func(_ *cobra.Command, args []string) { + from := args[0] + to := args[1] + amount, err := util.StringToChange(args[2]) + cmd.FatalErrorCheck(err) - withdrawTransactionCmd.Run = func(_ *cobra.Command, _ []string) { w, err := openWallet() cmd.FatalErrorCheck(err) @@ -168,15 +172,14 @@ func buildWithdrawTxCmd(parentCmd *cobra.Command) { wallet.OptionMemo(*memoOpt), } - trx, err := w.MakeWithdrawTx(*fromArg, *toArg, - util.CoinToChange(*amtArg), opts...) + trx, err := w.MakeWithdrawTx(from, to, amount, opts...) cmd.FatalErrorCheck(err) cmd.PrintLine() cmd.PrintInfoMsgf("You are going to sign this \033[1mWithdraw\033[0m transition:") - cmd.PrintInfoMsgf("Validator: %s", *fromArg) - cmd.PrintInfoMsgf("Account : %s", *toArg) - cmd.PrintInfoMsgf("Amount : %.9f", *amtArg) + cmd.PrintInfoMsgf("Validator: %s", from) + cmd.PrintInfoMsgf("Account : %s", to) + cmd.PrintInfoMsgf("Amount : %.9f", util.ChangeToCoin(amount)) cmd.PrintInfoMsgf("Fee : %.9f", util.ChangeToCoin(trx.Fee())) signAndPublishTx(w, trx, *noConfirmOpt, *passOpt) @@ -194,10 +197,10 @@ func addCommonTxOptions(c *cobra.Command) (*string, *int, *float64, *string, *bo "transaction fee, if not specified will calculate automatically") memoOpt := c.Flags().String("memo", "", - "transaction memo, maximum should be 64 character (optional)") + "transaction memo, maximum should be 64 character") noConfirmOpt := c.Flags().Bool("no-confirm", false, - "no confirmation question (optional)") + "no confirmation question") return stampOpt, seqOpt, feeOpt, memoOpt, noConfirmOpt } diff --git a/wallet/errors.go b/wallet/errors.go index 479497217..420a5560c 100644 --- a/wallet/errors.go +++ b/wallet/errors.go @@ -6,9 +6,6 @@ import ( ) var ( - // ErrInvalidCRC describes an error in which the wallet CRC is invalid. - ErrInvalidCRC = errors.New("invalid CRC") - // ErrInvalidNetwork describes an error in which the network is invalid. ErrInvalidNetwork = errors.New("invalid network") @@ -20,16 +17,22 @@ var ( ErrHistoryExists = errors.New("transaction already exists") ) +// CRCNotMatchError describes an error in which the wallet CRC is not macthed. +type CRCNotMatchError struct { + Expected uint32 + Got uint32 +} + +func (e CRCNotMatchError) Error() string { + return fmt.Sprintf("crc not matched, expected: %d, got: %d", e.Expected, e.Got) +} + // WalletExitsError describes an error in which a wallet exists in the // given path. type WalletExitsError struct { //nolint Path string } -func NewWalletExitsError(path string) error { - return WalletExitsError{Path: path} -} - func (e WalletExitsError) Error() string { return fmt.Sprintf("a wallet exists at: %s", e.Path) } diff --git a/wallet/servers.json b/wallet/servers.json index 88468ccba..6fa07f08d 100644 --- a/wallet/servers.json +++ b/wallet/servers.json @@ -1,17 +1,17 @@ { "mainnet": [ { - "ip": "172.104.46.145:9090", + "ip": "localhost:0", "name": "testnet-1" } ], "testnet": [ { - "ip": "172.104.46.145:9090", + "ip": "172.104.46.145:50052", "name": "testnet-1" }, { - "ip": "94.101.184.118:9090", + "ip": "94.101.184.118:50052", "name": "testnet-2" } ] diff --git a/wallet/store.go b/wallet/store.go index 0508e80ec..1522f714c 100644 --- a/wallet/store.go +++ b/wallet/store.go @@ -31,8 +31,12 @@ func (s *store) Save(bs []byte) error { return err } - if s.VaultCRC != s.calcVaultCRC() { - return ErrInvalidCRC + crc := s.calcVaultCRC() + if s.VaultCRC != crc { + return CRCNotMatchError{ + Expected: crc, + Got: s.VaultCRC, + } } return nil diff --git a/wallet/wallet.go b/wallet/wallet.go index ea788eaea..cfae6ae45 100644 --- a/wallet/wallet.go +++ b/wallet/wallet.go @@ -68,7 +68,9 @@ func Open(path string, offline bool) (*Wallet, error) { func Create(path, mnemonic, password string, chain genesis.ChainType) (*Wallet, error) { path = util.MakeAbs(path) if util.PathExists(path) { - return nil, NewWalletExitsError(path) + return nil, WalletExitsError{ + Path: path, + } } var coinType uint32 diff --git a/wallet/wallet_test.go b/wallet/wallet_test.go index 75d4e4efc..008ec7554 100644 --- a/wallet/wallet_test.go +++ b/wallet/wallet_test.go @@ -113,7 +113,10 @@ func TestOpenWallet(t *testing.T) { assert.NoError(t, util.WriteFile(td.wallet.path, bs)) _, err := Open(td.wallet.path, true) - assert.ErrorIs(t, err, ErrInvalidCRC) + assert.ErrorIs(t, err, CRCNotMatchError{ + Expected: td.wallet.store.calcVaultCRC(), + Got: 0, + }) }) t.Run("Invalid json", func(t *testing.T) { @@ -135,7 +138,9 @@ func TestRecoverWallet(t *testing.T) { assert.NoError(t, td.wallet.Save()) _, err := Create(td.wallet.path, mnemonic, password, 0) - assert.ErrorIs(t, err, NewWalletExitsError(td.wallet.path)) + assert.ErrorIs(t, err, WalletExitsError{ + Path: td.wallet.path, + }) }) t.Run("Invalid mnemonic", func(t *testing.T) {