package commands
import (
- "context"
"fmt"
- "net"
- "net/http"
"os"
- "path/filepath"
"regexp"
- "strings"
- "time"
"github.com/spf13/cobra"
- jww "github.com/spf13/jwalterweatherman"
- "github.com/bytom/blockchain"
- "github.com/bytom/blockchain/rpc"
+ "github.com/bytom/util"
)
-const (
- // Success indicates the rpc calling is successful.
- Success = iota
- // ErrLocalExe indicates error occurs before the rpc calling.
- ErrLocalExe
- // ErrConnect indicates error occurs connecting to the bytomd, e.g.,
- // bytomd can't parse the received arguments.
- ErrConnect
- // ErrLocalParse indicates error occurs locally when parsing the response.
- ErrLocalParse
- // ErrRemote indicates error occurs in bytomd.
- ErrRemote
-)
+// bytomcli usage template
+var usageTemplate = `Usage:{{if .Runnable}}
+ {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
+ {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
+
+Aliases:
+ {{.NameAndAliases}}{{end}}{{if .HasExample}}
+
+Examples:
+{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
+
+Available Commands:
+ {{range .Commands}}{{if (and .IsAvailableCommand (.Name | WalletDisable))}}
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}
+
+ available with wallet enable:
+ {{range .Commands}}{{if (and .IsAvailableCommand (.Name | WalletEnable))}}
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
+
+Flags:
+{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
+
+Global Flags:
+{{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}}
+
+Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}}
+ {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
+
+Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
+`
// commandError is an error used to signal different error situations in command handling.
type commandError struct {
Short: "Bytomcli is a commond line client for bytom core (a.k.a. bytomd)",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
+ cmd.SetUsageTemplate(usageTemplate)
cmd.Usage()
}
},
func Execute() {
AddCommands()
+ AddTemplateFunc()
if _, err := BytomcliCmd.ExecuteC(); err != nil {
- os.Exit(ErrLocalExe)
+ os.Exit(util.ErrLocalExe)
}
}
BytomcliCmd.AddCommand(createAccountCmd)
BytomcliCmd.AddCommand(deleteAccountCmd)
BytomcliCmd.AddCommand(listAccountsCmd)
- BytomcliCmd.AddCommand(updateAccountTagsCmd)
BytomcliCmd.AddCommand(createAccountReceiverCmd)
- BytomcliCmd.AddCommand(createAccountAddressCmd)
+ BytomcliCmd.AddCommand(listAddressesCmd)
+ BytomcliCmd.AddCommand(validateAddressCmd)
BytomcliCmd.AddCommand(createAssetCmd)
+ BytomcliCmd.AddCommand(getAssetCmd)
BytomcliCmd.AddCommand(listAssetsCmd)
- BytomcliCmd.AddCommand(updateAssetTagsCmd)
+ BytomcliCmd.AddCommand(updateAssetAliasCmd)
+ BytomcliCmd.AddCommand(getTransactionCmd)
BytomcliCmd.AddCommand(listTransactionsCmd)
+
+ BytomcliCmd.AddCommand(getUnconfirmedTransactionCmd)
+ BytomcliCmd.AddCommand(listUnconfirmedTransactionsCmd)
+
+ BytomcliCmd.AddCommand(getMemPoolTransactionCmd)
+ BytomcliCmd.AddCommand(listMemPoolTransactionsCmd)
+ BytomcliCmd.AddCommand(decodeRawTransactionCmd)
+
BytomcliCmd.AddCommand(listUnspentOutputsCmd)
BytomcliCmd.AddCommand(listBalancesCmd)
BytomcliCmd.AddCommand(buildTransactionCmd)
BytomcliCmd.AddCommand(signTransactionCmd)
BytomcliCmd.AddCommand(submitTransactionCmd)
- BytomcliCmd.AddCommand(signSubTransactionCmd)
+ BytomcliCmd.AddCommand(estimateTransactionGasCmd)
- BytomcliCmd.AddCommand(blockHeightCmd)
- BytomcliCmd.AddCommand(blockHashCmd)
- BytomcliCmd.AddCommand(getBlockByHashCmd)
- BytomcliCmd.AddCommand(getBlockHeaderByHashCmd)
- BytomcliCmd.AddCommand(getBlockTransactionsCountByHashCmd)
- BytomcliCmd.AddCommand(getBlockByHeightCmd)
- BytomcliCmd.AddCommand(getBlockTransactionsCountByHeightCmd)
+ BytomcliCmd.AddCommand(getBlockCountCmd)
+ BytomcliCmd.AddCommand(getBlockHashCmd)
+ BytomcliCmd.AddCommand(getBlockCmd)
+ BytomcliCmd.AddCommand(getBlockHeaderCmd)
+ BytomcliCmd.AddCommand(getDifficultyCmd)
+ BytomcliCmd.AddCommand(getHashRateCmd)
BytomcliCmd.AddCommand(createKeyCmd)
BytomcliCmd.AddCommand(deleteKeyCmd)
BytomcliCmd.AddCommand(listKeysCmd)
- BytomcliCmd.AddCommand(exportPrivateCmd)
- BytomcliCmd.AddCommand(importPrivateCmd)
+ BytomcliCmd.AddCommand(resetKeyPwdCmd)
- BytomcliCmd.AddCommand(isMiningCmd)
-
- BytomcliCmd.AddCommand(netInfoCmd)
- BytomcliCmd.AddCommand(netListeningCmd)
- BytomcliCmd.AddCommand(peerCountCmd)
- BytomcliCmd.AddCommand(netSyncingCmd)
-
- BytomcliCmd.AddCommand(gasRateCmd)
+ BytomcliCmd.AddCommand(signMsgCmd)
+ BytomcliCmd.AddCommand(verifyMsgCmd)
+ BytomcliCmd.AddCommand(decodeProgCmd)
BytomcliCmd.AddCommand(createTransactionFeedCmd)
BytomcliCmd.AddCommand(listTransactionFeedsCmd)
BytomcliCmd.AddCommand(getTransactionFeedCmd)
BytomcliCmd.AddCommand(updateTransactionFeedCmd)
- BytomcliCmd.AddCommand(versionCmd)
-}
-
-func mustRPCClient() *rpc.Client {
- // TODO(kr): refactor some of this cert-loading logic into bytom/blockchain
- // and use it from cored as well.
- // Note that this function, unlike maybeUseTLS in cored,
- // does not load the cert and key from env vars,
- // only from the filesystem.
- certFile := filepath.Join(home, "tls.crt")
- keyFile := filepath.Join(home, "tls.key")
- config, err := blockchain.TLSConfig(certFile, keyFile, "")
- if err == blockchain.ErrNoTLS {
- return &rpc.Client{BaseURL: *coreURL}
- } else if err != nil {
- jww.ERROR.Println("loading TLS cert:", err)
- }
-
- t := &http.Transport{
- DialContext: (&net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 30 * time.Second,
- DualStack: true,
- }).DialContext,
- MaxIdleConns: 100,
- IdleConnTimeout: 90 * time.Second,
- TLSClientConfig: config,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 1 * time.Second,
- }
+ BytomcliCmd.AddCommand(isMiningCmd)
+ BytomcliCmd.AddCommand(setMiningCmd)
- url := *coreURL
- if strings.HasPrefix(url, "http:") {
- url = "https:" + url[5:]
- }
+ BytomcliCmd.AddCommand(netInfoCmd)
+ BytomcliCmd.AddCommand(gasRateCmd)
- return &rpc.Client{
- BaseURL: url,
- Client: &http.Client{Transport: t},
- }
+ BytomcliCmd.AddCommand(versionCmd)
}
-func clientCall(path string, req ...interface{}) (interface{}, int) {
-
- var response = &blockchain.Response{}
- var request interface{}
-
- if req != nil {
- request = req[0]
+// AddTemplateFunc adds usage template to the root command BytomcliCmd.
+func AddTemplateFunc() {
+ walletEnableCmd := []string{
+ createAccountCmd.Name(),
+ listAccountsCmd.Name(),
+ deleteAccountCmd.Name(),
+ createAccountReceiverCmd.Name(),
+ listAddressesCmd.Name(),
+ validateAddressCmd.Name(),
+
+ createAssetCmd.Name(),
+ getAssetCmd.Name(),
+ listAssetsCmd.Name(),
+ updateAssetAliasCmd.Name(),
+
+ createKeyCmd.Name(),
+ deleteKeyCmd.Name(),
+ listKeysCmd.Name(),
+ resetKeyPwdCmd.Name(),
+ signMsgCmd.Name(),
+
+ buildTransactionCmd.Name(),
+ signTransactionCmd.Name(),
+
+ getTransactionCmd.Name(),
+ listTransactionsCmd.Name(),
+ listUnspentOutputsCmd.Name(),
+ listBalancesCmd.Name(),
}
- client := mustRPCClient()
- client.Call(context.Background(), path, request, response)
-
- switch response.Status {
- case blockchain.FAIL:
- jww.ERROR.Println(response.Msg)
- return nil, ErrRemote
- case "":
- jww.ERROR.Println("Unable to connect to the bytomd")
- return nil, ErrConnect
- }
-
- return response.Data, Success
+ cobra.AddTemplateFunc("WalletEnable", func(cmdName string) bool {
+ for _, name := range walletEnableCmd {
+ if name == cmdName {
+ return true
+ }
+ }
+ return false
+ })
+
+ cobra.AddTemplateFunc("WalletDisable", func(cmdName string) bool {
+ for _, name := range walletEnableCmd {
+ if name == cmdName {
+ return false
+ }
+ }
+ return true
+ })
}