13 "github.com/btcsuite/btcd/btcjson"
17 showHelpMessage = "Specify -h to show available options"
18 listCmdMessage = "Specify -l to list available commands"
21 // commandUsage display the usage for a specific command.
22 func commandUsage(method string) {
23 usage, err := btcjson.MethodUsageText(method)
25 // This should never happen since the method was already checked
26 // before calling this function, but be safe.
27 fmt.Fprintln(os.Stderr, "Failed to obtain command usage:", err)
31 fmt.Fprintln(os.Stderr, "Usage:")
32 fmt.Fprintf(os.Stderr, " %s\n", usage)
35 // usage displays the general usage when the help flag is not displayed and
36 // and an invalid command was specified. The commandUsage function is used
37 // instead when a valid command was specified.
38 func usage(errorMessage string) {
39 appName := filepath.Base(os.Args[0])
40 appName = strings.TrimSuffix(appName, filepath.Ext(appName))
41 fmt.Fprintln(os.Stderr, errorMessage)
42 fmt.Fprintln(os.Stderr, "Usage:")
43 fmt.Fprintf(os.Stderr, " %s [OPTIONS] <command> <args...>\n\n",
45 fmt.Fprintln(os.Stderr, showHelpMessage)
46 fmt.Fprintln(os.Stderr, listCmdMessage)
50 cfg, args, err := loadConfig()
55 usage("No command specified")
59 // Ensure the specified method identifies a valid registered command and
60 // is one of the usable types.
62 usageFlags, err := btcjson.MethodUsageFlags(method)
64 fmt.Fprintf(os.Stderr, "Unrecognized command '%s'\n", method)
65 fmt.Fprintln(os.Stderr, listCmdMessage)
68 if usageFlags&unusableFlags != 0 {
69 fmt.Fprintf(os.Stderr, "The '%s' command can only be used via "+
70 "websockets\n", method)
71 fmt.Fprintln(os.Stderr, listCmdMessage)
75 // Convert remaining command line args to a slice of interface values
76 // to be passed along as parameters to new command creation function.
78 // Since some commands, such as submitblock, can involve data which is
79 // too large for the Operating System to allow as a normal command line
80 // parameter, support using '-' as an argument to allow the argument
81 // to be read from a stdin pipe.
82 bio := bufio.NewReader(os.Stdin)
83 params := make([]interface{}, 0, len(args[1:]))
84 for _, arg := range args[1:] {
86 param, err := bio.ReadString('\n')
87 if err != nil && err != io.EOF {
88 fmt.Fprintf(os.Stderr, "Failed to read data "+
89 "from stdin: %v\n", err)
92 if err == io.EOF && len(param) == 0 {
93 fmt.Fprintln(os.Stderr, "Not enough lines "+
97 param = strings.TrimRight(param, "\r\n")
98 params = append(params, param)
102 params = append(params, arg)
105 // Attempt to create the appropriate command using the arguments
106 // provided by the user.
107 cmd, err := btcjson.NewCmd(method, params...)
109 // Show the error along with its error code when it's a
110 // btcjson.Error as it reallistcally will always be since the
111 // NewCmd function is only supposed to return errors of that
113 if jerr, ok := err.(btcjson.Error); ok {
114 fmt.Fprintf(os.Stderr, "%s command: %v (code: %s)\n",
115 method, err, jerr.ErrorCode)
120 // The error is not a btcjson.Error and this really should not
121 // happen. Nevertheless, fallback to just showing the error
122 // if it should happen due to a bug in the package.
123 fmt.Fprintf(os.Stderr, "%s command: %v\n", method, err)
128 // Marshal the command into a JSON-RPC byte slice in preparation for
129 // sending it to the RPC server.
130 marshalledJSON, err := btcjson.MarshalCmd(1, cmd)
132 fmt.Fprintln(os.Stderr, err)
136 // Send the JSON-RPC request to the server using the user-specified
137 // connection configuration.
138 result, err := sendPostRequest(marshalledJSON, cfg)
140 fmt.Fprintln(os.Stderr, err)
144 // Choose how to display the result based on its type.
145 strResult := string(result)
146 if strings.HasPrefix(strResult, "{") || strings.HasPrefix(strResult, "[") {
148 if err := json.Indent(&dst, result, "", " "); err != nil {
149 fmt.Fprintf(os.Stderr, "Failed to format result: %v",
153 fmt.Println(dst.String())
155 } else if strings.HasPrefix(strResult, `"`) {
157 if err := json.Unmarshal(result, &str); err != nil {
158 fmt.Fprintf(os.Stderr, "Failed to unmarshal result: %v",
164 } else if strResult != "null" {
165 fmt.Println(strResult)