kaspad/cmd/kaspactl/kaspactl.go
stasatdaglabs f46dec449d [NOD-510] Change all references to Bitcoin to Kaspa (#531)
* [NOD-510] Change coinbase flags to kaspad.

* [NOD-510] Removed superfluous spaces after periods in comments.

* [NOD-510] Rename btcd -> kaspad in the root folder.

* [NOD-510] Rename BtcEncode -> KaspaEncode and BtcDecode -> KaspaDecode.

* [NOD-510] Rename BtcEncode -> KaspaEncode and BtcDecode -> KaspaDecode.

* [NOD-510] Continue renaming btcd -> kaspad.

* [NOD-510] Rename btcjson -> kaspajson.

* [NOD-510] Rename file names inside kaspajson.

* [NOD-510] Rename kaspajson -> jsonrpc.

* [NOD-510] Finish renaming in addrmgr.

* [NOD-510] Rename package btcec to ecc.

* [NOD-510] Finish renaming stuff in blockdag.

* [NOD-510] Rename stuff in cmd.

* [NOD-510] Rename stuff in config.

* [NOD-510] Rename stuff in connmgr.

* [NOD-510] Rename stuff in dagconfig.

* [NOD-510] Rename stuff in database.

* [NOD-510] Rename stuff in docker.

* [NOD-510] Rename stuff in integration.

* [NOD-510] Rename jsonrpc to rpcmodel.

* [NOD-510] Rename stuff in limits.

* [NOD-510] Rename stuff in logger.

* [NOD-510] Rename stuff in mempool.

* [NOD-510] Rename stuff in mining.

* [NOD-510] Rename stuff in netsync.

* [NOD-510] Rename stuff in peer.

* [NOD-510] Rename stuff in release.

* [NOD-510] Rename stuff in rpcclient.

* [NOD-510] Rename stuff in server.

* [NOD-510] Rename stuff in signal.

* [NOD-510] Rename stuff in txscript.

* [NOD-510] Rename stuff in util.

* [NOD-510] Rename stuff in wire.

* [NOD-510] Fix failing tests.

* [NOD-510] Fix merge errors.

* [NOD-510] Fix go vet errors.

* [NOD-510] Remove merged file that's no longer relevant.

* [NOD-510] Add a comment above Op0.

* [NOD-510] Fix some comments referencing Bitcoin Core.

* [NOD-510] Fix some more comments referencing Bitcoin Core.

* [NOD-510] Fix bitcoin -> kaspa.

* [NOD-510] Fix more bitcoin -> kaspa.

* [NOD-510] Fix comments, remove DisconnectBlock in addrindex.

* [NOD-510] Rename KSPD to KASD.

* [NOD-510] Fix comments and user agent.
2019-12-12 15:21:41 +02:00

168 lines
4.7 KiB
Go

package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/kaspanet/kaspad/rpcmodel"
)
const (
showHelpMessage = "Specify -h to show available options"
listCmdMessage = "Specify -l to list available commands"
)
// commandUsage display the usage for a specific command.
func commandUsage(method string) {
usage, err := rpcmodel.MethodUsageText(method)
if err != nil {
// This should never happen since the method was already checked
// before calling this function, but be safe.
fmt.Fprintln(os.Stderr, "Failed to obtain command usage:", err)
return
}
fmt.Fprintln(os.Stderr, "Usage:")
fmt.Fprintf(os.Stderr, " %s\n", usage)
}
// usage displays the general usage when the help flag is not displayed and
// and an invalid command was specified. The commandUsage function is used
// instead when a valid command was specified.
func usage(errorMessage string) {
appName := filepath.Base(os.Args[0])
appName = strings.TrimSuffix(appName, filepath.Ext(appName))
fmt.Fprintln(os.Stderr, errorMessage)
fmt.Fprintln(os.Stderr, "Usage:")
fmt.Fprintf(os.Stderr, " %s [OPTIONS] <command> <args...>\n\n",
appName)
fmt.Fprintln(os.Stderr, showHelpMessage)
fmt.Fprintln(os.Stderr, listCmdMessage)
}
func main() {
cfg, args, err := loadConfig()
if err != nil {
os.Exit(1)
}
if len(args) < 1 {
usage("No command specified")
os.Exit(1)
}
// Ensure the specified method identifies a valid registered command and
// is one of the usable types.
method := args[0]
usageFlags, err := rpcmodel.MethodUsageFlags(method)
if err != nil {
fmt.Fprintf(os.Stderr, "Unrecognized command '%s'\n", method)
fmt.Fprintln(os.Stderr, listCmdMessage)
os.Exit(1)
}
if usageFlags&unusableFlags != 0 {
fmt.Fprintf(os.Stderr, "The '%s' command can only be used via "+
"websockets\n", method)
fmt.Fprintln(os.Stderr, listCmdMessage)
os.Exit(1)
}
// Convert remaining command line args to a slice of interface values
// to be passed along as parameters to new command creation function.
//
// Since some commands, such as submitblock, can involve data which is
// too large for the Operating System to allow as a normal command line
// parameter, support using '-' as an argument to allow the argument
// to be read from a stdin pipe.
bio := bufio.NewReader(os.Stdin)
params := make([]interface{}, 0, len(args[1:]))
for _, arg := range args[1:] {
if arg == "-" {
param, err := bio.ReadString('\n')
if err != nil && err != io.EOF {
fmt.Fprintf(os.Stderr, "Failed to read data "+
"from stdin: %s\n", err)
os.Exit(1)
}
if err == io.EOF && len(param) == 0 {
fmt.Fprintln(os.Stderr, "Not enough lines "+
"provided on stdin")
os.Exit(1)
}
param = strings.TrimRight(param, "\r\n")
params = append(params, param)
continue
}
params = append(params, arg)
}
// Attempt to create the appropriate command using the arguments
// provided by the user.
cmd, err := rpcmodel.NewCommand(method, params...)
if err != nil {
// Show the error along with its error code when it's a
// rpcmodel.Error as it reallistcally will always be since the
// NewCommand function is only supposed to return errors of that
// type.
if jerr, ok := err.(rpcmodel.Error); ok {
fmt.Fprintf(os.Stderr, "%s error: %s (command code: %s)\n",
method, err, jerr.ErrorCode)
commandUsage(method)
os.Exit(1)
}
// The error is not a rpcmodel.Error and this really should not
// happen. Nevertheless, fallback to just showing the error
// if it should happen due to a bug in the package.
fmt.Fprintf(os.Stderr, "%s error: %s\n", method, err)
commandUsage(method)
os.Exit(1)
}
// Marshal the command into a JSON-RPC byte slice in preparation for
// sending it to the RPC server.
marshalledJSON, err := rpcmodel.MarshalCommand(1, cmd)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
// Send the JSON-RPC request to the server using the user-specified
// connection configuration.
result, err := sendPostRequest(marshalledJSON, cfg)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
// Choose how to display the result based on its type.
strResult := string(result)
if strings.HasPrefix(strResult, "{") || strings.HasPrefix(strResult, "[") {
var dst bytes.Buffer
if err := json.Indent(&dst, result, "", " "); err != nil {
fmt.Fprintf(os.Stderr, "Failed to format result: %s",
err)
os.Exit(1)
}
fmt.Println(dst.String())
} else if strings.HasPrefix(strResult, `"`) {
var str string
if err := json.Unmarshal(result, &str); err != nil {
fmt.Fprintf(os.Stderr, "Failed to unmarshal result: %s",
err)
os.Exit(1)
}
fmt.Println(str)
} else if strResult != "null" {
fmt.Println(strResult)
}
}