github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/cmd/spc/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "reflect" 8 "strings" 9 10 "github.com/spf13/cobra" 11 12 "SiaPrime/build" 13 "SiaPrime/node/api/client" 14 ) 15 16 var ( 17 // Flags. 18 hostContractOutputType string // output type for host contracts 19 hostVerbose bool // display additional host info 20 initForce bool // destroy and re-encrypt the wallet on init if it already exists 21 initPassword bool // supply a custom password when creating a wallet 22 renterAllContracts bool // Show all active and expired contracts 23 renterDownloadAsync bool // Downloads files asynchronously 24 renterListVerbose bool // Show additional info about uploaded files. 25 renterShowHistory bool // Show download history in addition to download queue. 26 siaDir string // Path to sia data dir 27 walletRawTxn bool // Encode/decode transactions in base64-encoded binary. 28 ) 29 30 var ( 31 // Globals. 32 rootCmd *cobra.Command // Root command cobra object, used by bash completion cmd. 33 httpClient client.Client 34 ) 35 36 // Exit codes. 37 // inspired by sysexits.h 38 const ( 39 exitCodeGeneral = 1 // Not in sysexits.h, but is standard practice. 40 exitCodeUsage = 64 // EX_USAGE in sysexits.h 41 ) 42 43 // post makes an API call and discards the response. An error is returned if 44 // the response status is not 2xx. 45 // wrap wraps a generic command with a check that the command has been 46 // passed the correct number of arguments. The command must take only strings 47 // as arguments. 48 func wrap(fn interface{}) func(*cobra.Command, []string) { 49 fnVal, fnType := reflect.ValueOf(fn), reflect.TypeOf(fn) 50 if fnType.Kind() != reflect.Func { 51 panic("wrapped function has wrong type signature") 52 } 53 for i := 0; i < fnType.NumIn(); i++ { 54 if fnType.In(i).Kind() != reflect.String { 55 panic("wrapped function has wrong type signature") 56 } 57 } 58 59 return func(cmd *cobra.Command, args []string) { 60 if len(args) != fnType.NumIn() { 61 cmd.UsageFunc()(cmd) 62 os.Exit(exitCodeUsage) 63 } 64 argVals := make([]reflect.Value, fnType.NumIn()) 65 for i := range args { 66 argVals[i] = reflect.ValueOf(args[i]) 67 } 68 fnVal.Call(argVals) 69 } 70 } 71 72 // die prints its arguments to stderr, then exits the program with the default 73 // error code. 74 func die(args ...interface{}) { 75 fmt.Fprintln(os.Stderr, args...) 76 os.Exit(exitCodeGeneral) 77 } 78 79 func main() { 80 root := &cobra.Command{ 81 Use: os.Args[0], 82 Short: "Sia Client v" + build.Version, 83 Long: "Sia Client v" + build.Version, 84 Run: wrap(consensuscmd), 85 } 86 87 rootCmd = root 88 89 // create command tree 90 root.AddCommand(versionCmd) 91 root.AddCommand(stopCmd) 92 93 root.AddCommand(updateCmd) 94 updateCmd.AddCommand(updateCheckCmd) 95 96 root.AddCommand(hostCmd) 97 hostCmd.AddCommand(hostConfigCmd, hostAnnounceCmd, hostFolderCmd, hostContractCmd, hostSectorCmd) 98 hostFolderCmd.AddCommand(hostFolderAddCmd, hostFolderRemoveCmd, hostFolderResizeCmd) 99 hostSectorCmd.AddCommand(hostSectorDeleteCmd) 100 hostCmd.Flags().BoolVarP(&hostVerbose, "verbose", "v", false, "Display detailed host info") 101 hostContractCmd.Flags().StringVarP(&hostContractOutputType, "type", "t", "value", "Select output type") 102 103 root.AddCommand(hostdbCmd) 104 hostdbCmd.AddCommand(hostdbViewCmd) 105 hostdbCmd.Flags().IntVarP(&hostdbNumHosts, "numhosts", "n", 0, "Number of hosts to display from the hostdb") 106 hostdbCmd.Flags().BoolVarP(&hostdbVerbose, "verbose", "v", false, "Display full hostdb information") 107 108 root.AddCommand(minerCmd) 109 minerCmd.AddCommand(minerStartCmd, minerStopCmd) 110 111 root.AddCommand(poolCmd) 112 poolCmd.AddCommand(poolConfigCmd, poolClientsCmd) 113 114 root.AddCommand(stratumminerCmd) 115 stratumminerCmd.AddCommand(stratumminerStartCmd, stratumminerStopCmd) 116 117 root.AddCommand(walletCmd) 118 walletCmd.AddCommand(walletAddressCmd, walletAddressesCmd, walletChangepasswordCmd, walletInitCmd, walletInitSeedCmd, 119 walletLoadCmd, walletLockCmd, walletSeedsCmd, walletSendCmd, walletSweepCmd, walletSignCmd, 120 walletBalanceCmd, walletBroadcastCmd, walletTransactionsCmd, walletUnlockCmd) 121 walletInitCmd.Flags().BoolVarP(&initPassword, "password", "p", false, "Prompt for a custom password") 122 walletInitCmd.Flags().BoolVarP(&initForce, "force", "", false, "destroy the existing wallet and re-encrypt") 123 walletInitSeedCmd.Flags().BoolVarP(&initForce, "force", "", false, "destroy the existing wallet") 124 walletSendCmd.AddCommand(walletSendSiacoinsCmd, walletSendSiafundsCmd) 125 walletUnlockCmd.Flags().BoolVarP(&initPassword, "password", "p", false, "Display interactive password prompt even if SIAPRIME_WALLET_PASSWORD is set") 126 walletBroadcastCmd.Flags().BoolVarP(&walletRawTxn, "raw", "", false, "Decode transaction as base64 instead of JSON") 127 walletSignCmd.Flags().BoolVarP(&walletRawTxn, "raw", "", false, "Encode signed transaction as base64 instead of JSON") 128 129 root.AddCommand(renterCmd) 130 renterCmd.AddCommand(renterFilesDeleteCmd, renterFilesDownloadCmd, 131 renterDownloadsCmd, renterAllowanceCmd, renterSetAllowanceCmd, 132 renterContractsCmd, renterFilesListCmd, renterFilesRenameCmd, 133 renterFilesUploadCmd, renterUploadsCmd, renterExportCmd, 134 renterPricesCmd) 135 136 renterContractsCmd.AddCommand(renterContractsViewCmd) 137 renterAllowanceCmd.AddCommand(renterAllowanceCancelCmd) 138 139 renterCmd.Flags().BoolVarP(&renterListVerbose, "verbose", "v", false, "Show additional file info such as redundancy") 140 renterContractsCmd.Flags().BoolVarP(&renterAllContracts, "all", "A", false, "Show all expired contracts in addition to active contracts") 141 renterDownloadsCmd.Flags().BoolVarP(&renterShowHistory, "history", "H", false, "Show download history in addition to the download queue") 142 renterFilesDownloadCmd.Flags().BoolVarP(&renterDownloadAsync, "async", "A", false, "Download file asynchronously") 143 renterFilesListCmd.Flags().BoolVarP(&renterListVerbose, "verbose", "v", false, "Show additional file info such as redundancy") 144 renterExportCmd.AddCommand(renterExportContractTxnsCmd) 145 146 root.AddCommand(gatewayCmd) 147 gatewayCmd.AddCommand(gatewayConnectCmd, gatewayDisconnectCmd, gatewayAddressCmd, gatewayListCmd) 148 149 root.AddCommand(consensusCmd) 150 151 utilsCmd.AddCommand(bashcomplCmd, mangenCmd, utilsHastingsCmd, utilsEncodeRawTxnCmd, utilsDecodeRawTxnCmd, 152 utilsSigHashCmd, utilsCheckSigCmd) 153 root.AddCommand(utilsCmd) 154 155 // initialize client 156 root.PersistentFlags().StringVarP(&httpClient.Address, "addr", "a", "localhost:4280", "which host/port to communicate with (i.e. the host/port spd is listening on)") 157 root.PersistentFlags().StringVarP(&httpClient.Password, "apipassword", "", "", "the password for the API's http authentication") 158 root.PersistentFlags().StringVarP(&siaDir, "siaprime-directory", "d", build.DefaultSiaDir(), "location of the sia directory") 159 root.PersistentFlags().StringVarP(&httpClient.UserAgent, "useragent", "", "SiaPrime-Agent", "the useragent used by spc to connect to the daemon's API") 160 161 // Check if the api password environment variable is set. 162 apiPassword := os.Getenv("SIAPRIME_API_PASSWORD") 163 if apiPassword != "" { 164 httpClient.Password = apiPassword 165 fmt.Println("Using SIAPRIME_API_PASSWORD environment variable") 166 } 167 168 // If the API password wasn't set we try to read it from the file. If 169 // reading fails, continue silently; but in the next release, this will 170 // be an error. 171 if httpClient.Password == "" { 172 pw, err := ioutil.ReadFile(build.APIPasswordFile(siaDir)) 173 if err == nil { 174 httpClient.Password = strings.TrimSpace(string(pw)) 175 } 176 } 177 178 // run 179 if err := root.Execute(); err != nil { 180 // Since no commands return errors (all commands set Command.Run instead of 181 // Command.RunE), Command.Execute() should only return an error on an 182 // invalid command or flag. Therefore Command.Usage() was called (assuming 183 // Command.SilenceUsage is false) and we should exit with exitCodeUsage. 184 os.Exit(exitCodeUsage) 185 } 186 }