github.com/turingchain2020/turingchain@v1.1.21/system/dapp/commands/wallet.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package commands 6 7 import ( 8 "fmt" 9 "os" 10 "strconv" 11 "time" 12 13 "github.com/turingchain2020/turingchain/rpc/jsonclient" 14 rpctypes "github.com/turingchain2020/turingchain/rpc/types" 15 commandtypes "github.com/turingchain2020/turingchain/system/dapp/commands/types" 16 "github.com/turingchain2020/turingchain/types" 17 "github.com/spf13/cobra" 18 ) 19 20 // WalletCmd wallet command 21 func WalletCmd() *cobra.Command { 22 cmd := &cobra.Command{ 23 Use: "wallet", 24 Short: "Wallet management", 25 Args: cobra.MinimumNArgs(1), 26 } 27 28 cmd.AddCommand( 29 LockCmd(), 30 UnlockCmd(), 31 WalletStatusCmd(), 32 SetPwdCmd(), 33 WalletListTxsCmd(), 34 MergeBalanceCmd(), 35 AutoMineCmd(), 36 SignRawTxCmd(), 37 NoBalanceCmd(), 38 SetFeeCmd(), 39 SendTxCmd(), 40 ) 41 42 return cmd 43 } 44 45 // LockCmd lock the wallet 46 func LockCmd() *cobra.Command { 47 cmd := &cobra.Command{ 48 Use: "lock", 49 Short: "Lock wallet", 50 Run: lock, 51 } 52 return cmd 53 } 54 55 func lock(cmd *cobra.Command, args []string) { 56 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 57 var res rpctypes.Reply 58 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.Lock", nil, &res) 59 ctx.Run() 60 } 61 62 // UnlockCmd unlock the wallet 63 func UnlockCmd() *cobra.Command { 64 cmd := &cobra.Command{ 65 Use: "unlock", 66 Short: "Unlock wallet", 67 Run: unLock, 68 } 69 addUnlockFlags(cmd) 70 return cmd 71 } 72 73 func addUnlockFlags(cmd *cobra.Command) { 74 cmd.Flags().StringP("pwd", "p", "", "password needed to unlock") 75 cmd.MarkFlagRequired("pwd") 76 77 cmd.Flags().Int64P("time_out", "t", 0, "time out for unlock operation(0 for unlimited)") 78 cmd.Flags().StringP("scope", "s", "wallet", "unlock scope(wallet/ticket)") 79 } 80 81 func unLock(cmd *cobra.Command, args []string) { 82 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 83 pwd, _ := cmd.Flags().GetString("pwd") 84 timeOut, _ := cmd.Flags().GetInt64("time_out") 85 scope, _ := cmd.Flags().GetString("scope") 86 var walletOrTicket bool 87 switch scope { 88 case "wallet": 89 walletOrTicket = false 90 case "ticket": 91 walletOrTicket = true 92 default: 93 fmt.Println("unlock scope code wrong: wallet or ticket") 94 return 95 } 96 97 params := types.WalletUnLock{ 98 Passwd: pwd, 99 Timeout: timeOut, 100 WalletOrTicket: walletOrTicket, 101 } 102 var res rpctypes.Reply 103 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.UnLock", params, &res) 104 ctx.Run() 105 } 106 107 // WalletStatusCmd get wallet status 108 func WalletStatusCmd() *cobra.Command { 109 cmd := &cobra.Command{ 110 Use: "status", 111 Short: "Get wallet status", 112 Run: walletStatus, 113 } 114 return cmd 115 } 116 117 func walletStatus(cmd *cobra.Command, args []string) { 118 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 119 var res rpctypes.WalletStatus 120 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.GetWalletStatus", nil, &res) 121 ctx.Run() 122 } 123 124 // SetPwdCmd set password 125 func SetPwdCmd() *cobra.Command { 126 cmd := &cobra.Command{ 127 Use: "set_pwd", 128 Short: "Set password", 129 Run: setPwd, 130 } 131 addSetPwdFlags(cmd) 132 return cmd 133 } 134 135 func addSetPwdFlags(cmd *cobra.Command) { 136 cmd.Flags().StringP("old", "o", "", "old password") 137 cmd.MarkFlagRequired("old") 138 139 cmd.Flags().StringP("new", "n", "", "new password,[8-30]letter and digit") 140 cmd.MarkFlagRequired("new") 141 } 142 143 func setPwd(cmd *cobra.Command, args []string) { 144 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 145 oldPwd, _ := cmd.Flags().GetString("old") 146 newPwd, _ := cmd.Flags().GetString("new") 147 params := types.ReqWalletSetPasswd{ 148 OldPass: oldPwd, 149 NewPass: newPwd, 150 } 151 var res rpctypes.Reply 152 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.SetPasswd", params, &res) 153 ctx.Run() 154 } 155 156 // WalletListTxsCmd get wallet transactions 157 func WalletListTxsCmd() *cobra.Command { 158 cmd := &cobra.Command{ 159 Use: "list_txs", 160 Short: "List transactions in wallet", 161 Run: walletListTxs, 162 } 163 addWalletListTxsFlags(cmd) 164 return cmd 165 } 166 167 func addWalletListTxsFlags(cmd *cobra.Command) { 168 cmd.Flags().StringP("from", "f", "", "from which transaction begin") 169 cmd.MarkFlagRequired("from") 170 171 cmd.Flags().Int32P("count", "c", 0, "number of transactions") 172 cmd.MarkFlagRequired("count") 173 174 cmd.Flags().Int32P("direction", "d", 0, "query direction (0: pre page, 1: next page)") 175 } 176 177 func walletListTxs(cmd *cobra.Command, args []string) { 178 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 179 txHash, _ := cmd.Flags().GetString("from") 180 count, _ := cmd.Flags().GetInt32("count") 181 direction, _ := cmd.Flags().GetInt32("direction") 182 params := rpctypes.ReqWalletTransactionList{ 183 FromTx: txHash, 184 Count: count, 185 Direction: direction, 186 } 187 var res rpctypes.WalletTxDetails 188 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.WalletTxList", params, &res) 189 ctx.SetResultCb(parseWalletTxListRes) 190 ctx.Run() 191 } 192 193 func parseWalletTxListRes(arg interface{}) (interface{}, error) { 194 res := arg.(*rpctypes.WalletTxDetails) 195 var result commandtypes.WalletTxDetailsResult 196 for _, v := range res.TxDetails { 197 amountResult := strconv.FormatFloat(float64(v.Amount)/float64(types.Coin), 'f', 4, 64) 198 wtxd := &commandtypes.WalletTxDetailResult{ 199 Tx: commandtypes.DecodeTransaction(v.Tx), 200 Receipt: v.Receipt, 201 Height: v.Height, 202 Index: v.Index, 203 Blocktime: v.BlockTime, 204 Amount: amountResult, 205 Fromaddr: v.FromAddr, 206 Txhash: v.TxHash, 207 ActionName: v.ActionName, 208 } 209 result.TxDetails = append(result.TxDetails, wtxd) 210 } 211 return result, nil 212 } 213 214 // MergeBalanceCmd merge all balance to an account 215 func MergeBalanceCmd() *cobra.Command { 216 cmd := &cobra.Command{ 217 Use: "merge", 218 Short: "Merge accounts' balance into address", 219 Run: mergeBalance, 220 } 221 addMergeBalanceFlags(cmd) 222 return cmd 223 } 224 225 func addMergeBalanceFlags(cmd *cobra.Command) { 226 cmd.Flags().StringP("to", "t", "", "destination account address") 227 cmd.MarkFlagRequired("to") 228 } 229 230 func mergeBalance(cmd *cobra.Command, args []string) { 231 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 232 toAddr, _ := cmd.Flags().GetString("to") 233 params := types.ReqWalletMergeBalance{ 234 To: toAddr, 235 } 236 var res rpctypes.ReplyHashes 237 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.MergeBalance", params, &res) 238 ctx.Run() 239 } 240 241 // AutoMineCmd set auto mining: 为了兼容现在的命令行, 这个命令就放到wallet,实际上依赖 ticket 242 func AutoMineCmd() *cobra.Command { 243 cmd := &cobra.Command{ 244 Use: "auto_mine", 245 Short: "Set auto mine on/off. Deprecated", 246 Run: autoMine, 247 } 248 addAutoMineFlags(cmd) 249 return cmd 250 } 251 252 func addAutoMineFlags(cmd *cobra.Command) { 253 cmd.Flags().Int32P("flag", "f", 0, `auto mine(0: off, 1: on)`) 254 cmd.MarkFlagRequired("flag") 255 } 256 257 func autoMine(cmd *cobra.Command, args []string) { 258 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 259 flag, _ := cmd.Flags().GetInt32("flag") 260 if flag != 0 && flag != 1 { 261 err := cmd.UsageFunc()(cmd) 262 if err != nil { 263 fmt.Fprintln(os.Stderr, err) 264 } 265 return 266 } 267 params := struct { 268 Flag int32 269 }{ 270 Flag: flag, 271 } 272 var res rpctypes.Reply 273 ctx := jsonclient.NewRPCCtx(rpcLaddr, "ticket.SetAutoMining", params, &res) 274 ctx.Run() 275 } 276 277 // NoBalanceCmd sign raw tx 278 func NoBalanceCmd() *cobra.Command { 279 cmd := &cobra.Command{ 280 Use: "nobalance", 281 Short: "Create nobalance transaction", 282 Run: noBalanceTx, 283 } 284 addNoBalanceFlags(cmd) 285 return cmd 286 } 287 288 func addNoBalanceFlags(cmd *cobra.Command) { 289 cmd.Flags().StringP("data", "d", "", "raw transaction data") 290 cmd.MarkFlagRequired("data") 291 cmd.Flags().StringP("key", "k", "", "private key of pay fee account (optional)") 292 cmd.Flags().StringP("payaddr", "a", "", "account address of pay fee (optional)") 293 cmd.Flags().StringP("expire", "e", "120s", "transaction expire time") 294 } 295 296 // SignRawTxCmd sign raw tx 297 func SignRawTxCmd() *cobra.Command { 298 cmd := &cobra.Command{ 299 Use: "sign", 300 Short: "Sign transaction", 301 Run: signRawTx, 302 } 303 addSignRawTxFlags(cmd) 304 return cmd 305 } 306 307 func addSignRawTxFlags(cmd *cobra.Command) { 308 cmd.Flags().StringP("data", "d", "", "raw transaction data") 309 cmd.MarkFlagRequired("data") 310 311 cmd.Flags().Int32P("index", "i", 0, "transaction index to be signed") 312 cmd.Flags().StringP("key", "k", "", "private key (optional)") 313 cmd.Flags().StringP("addr", "a", "", "account address (optional)") 314 cmd.Flags().StringP("expire", "e", "120s", "transaction expire time") 315 cmd.Flags().Float64P("fee", "f", 0, "transaction fee (optional), auto set proper fee if not set or zero fee") 316 cmd.Flags().StringP("to", "t", "", "new to addr (optional)") 317 318 // A duration string is a possibly signed sequence of 319 // decimal numbers, each with optional fraction and a unit suffix, 320 // such as "300ms", "-1.5h" or "2h45m". 321 // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". 322 } 323 324 func noBalanceTx(cmd *cobra.Command, args []string) { 325 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 326 data, _ := cmd.Flags().GetString("data") 327 addr, _ := cmd.Flags().GetString("payaddr") 328 privkey, _ := cmd.Flags().GetString("key") 329 expire, _ := cmd.Flags().GetString("expire") 330 expireTime, err := time.ParseDuration(expire) 331 if err != nil { 332 fmt.Fprintln(os.Stderr, err) 333 return 334 } 335 if expireTime < time.Minute*2 && expireTime != time.Second*0 { 336 expire = "120s" 337 fmt.Println("expire time must longer than 2 minutes, changed expire time into 2 minutes") 338 } 339 params := types.NoBalanceTx{ 340 PayAddr: addr, 341 TxHex: data, 342 Expire: expire, 343 Privkey: privkey, 344 } 345 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.CreateNoBalanceTransaction", params, nil) 346 ctx.RunWithoutMarshal() 347 } 348 349 func signRawTx(cmd *cobra.Command, args []string) { 350 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 351 data, _ := cmd.Flags().GetString("data") 352 key, _ := cmd.Flags().GetString("key") 353 addr, _ := cmd.Flags().GetString("addr") 354 index, _ := cmd.Flags().GetInt32("index") 355 to, _ := cmd.Flags().GetString("to") 356 fee, _ := cmd.Flags().GetFloat64("fee") 357 expire, _ := cmd.Flags().GetString("expire") 358 expire, err := commandtypes.CheckExpireOpt(expire) 359 if err != nil { 360 fmt.Fprintln(os.Stderr, err) 361 return 362 } 363 feeInt64 := int64(fee * 1e4) 364 params := types.ReqSignRawTx{ 365 Addr: addr, 366 Privkey: key, 367 TxHex: data, 368 Expire: expire, 369 Index: index, 370 Fee: feeInt64 * 1e4, 371 NewToAddr: to, 372 } 373 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.SignRawTx", params, nil) 374 ctx.RunWithoutMarshal() 375 } 376 377 // SetFeeCmd set tx fee 378 func SetFeeCmd() *cobra.Command { 379 cmd := &cobra.Command{ 380 Use: "set_fee", 381 Short: "Set transaction fee", 382 Run: setFee, 383 } 384 addSetFeeFlags(cmd) 385 return cmd 386 } 387 388 func addSetFeeFlags(cmd *cobra.Command) { 389 cmd.Flags().Float64P("amount", "a", 0, "tx fee amount") 390 cmd.MarkFlagRequired("amount") 391 } 392 393 func setFee(cmd *cobra.Command, args []string) { 394 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 395 amount, _ := cmd.Flags().GetFloat64("amount") 396 amountInt64 := int64(amount * 1e4) 397 params := types.ReqWalletSetFee{ 398 Amount: amountInt64 * 1e4, 399 } 400 var res rpctypes.Reply 401 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.SetTxFee", params, &res) 402 ctx.Run() 403 } 404 405 // SendTxCmd send raw tx 406 func SendTxCmd() *cobra.Command { 407 cmd := &cobra.Command{ 408 Use: "send", 409 Short: "Send a transaction", 410 Run: sendTx, 411 } 412 addSendTxFlags(cmd) 413 return cmd 414 } 415 416 func addSendTxFlags(cmd *cobra.Command) { 417 cmd.Flags().StringP("data", "d", "", "transaction content") 418 cmd.MarkFlagRequired("data") 419 420 cmd.Flags().StringP("token", "t", types.TRC, "token name. (TRC supported)") 421 } 422 423 func sendTx(cmd *cobra.Command, args []string) { 424 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 425 data, _ := cmd.Flags().GetString("data") 426 token, _ := cmd.Flags().GetString("token") 427 params := rpctypes.RawParm{ 428 Token: token, 429 Data: data, 430 } 431 432 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.SendTransaction", params, nil) 433 ctx.RunWithoutMarshal() 434 }