github.com/turingchain2020/turingchain@v1.1.21/system/dapp/commands/send.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 "bytes" 9 "errors" 10 "fmt" 11 "os" 12 "os/exec" 13 "strings" 14 15 "github.com/spf13/cobra" 16 17 "github.com/turingchain2020/turingchain/common/address" 18 ) 19 20 //OneStepSendCmd send cmd 21 func OneStepSendCmd() *cobra.Command { 22 cmd := &cobra.Command{ 23 Use: "send", 24 Short: "send tx in one step", 25 DisableFlagParsing: true, 26 Run: func(cmd *cobra.Command, args []string) { 27 oneStepSend(cmd, os.Args[0], args) 28 }, 29 } 30 cmd.Flags().StringP("key", "k", "", "private key or from address for sign tx") 31 //cmd.MarkFlagRequired("key") 32 return cmd 33 } 34 35 // one step send 36 func oneStepSend(cmd *cobra.Command, cmdName string, params []string) { 37 if len(params) < 1 || params[0] == "help" || params[0] == "--help" || params[0] == "-h" { 38 loadSendHelp() 39 return 40 } 41 42 var createParams, keyParams []string 43 //取出send命令的key参数, 保留原始构建的参数列表 44 for i, v := range params { 45 if strings.HasPrefix(v, "-k=") || strings.HasPrefix(v, "--key=") { 46 keyParams = append(keyParams, v) 47 createParams = append(params[:i], params[i+1:]...) 48 break 49 } else if (v == "-k" || v == "--key") && i < len(params)-1 { 50 keyParams = append(keyParams, v, params[i+1]) 51 createParams = append(params[:i], params[i+2:]...) 52 break 53 } 54 } 55 //调用send命令parse函数解析key参数 56 err := cmd.Flags().Parse(keyParams) 57 key, _ := cmd.Flags().GetString("key") 58 if len(key) < 32 || err != nil { 59 loadSendHelp() 60 fmt.Fprintln(os.Stderr, "Error: required flag(s) \"key\" not proper set") 61 return 62 } 63 64 //构造签名命令的key参数 65 if address.CheckAddress(key) == nil { 66 keyParams = append([]string{}, "-a", key) 67 } else { 68 keyParams = append([]string{}, "-k", key) 69 } 70 //创建交易命令 71 cmdCreate := exec.Command(cmdName, createParams...) 72 createRes, err := execCmd(cmdCreate) 73 if err != nil { 74 fmt.Fprintln(os.Stderr, err) 75 return 76 } 77 //cli不传任何参数不会报错, 输出帮助信息 78 if strings.Contains(createRes, "\n") { 79 fmt.Println(createRes) 80 return 81 } 82 //采用内部的构造交易命令,解析rpc_laddr地址参数 83 createCmd, createFlags, _ := cmd.Root().Traverse(createParams) 84 _ = createCmd.ParseFlags(createFlags) 85 rpcAddr, _ := createCmd.Flags().GetString("rpc_laddr") 86 //交易签名命令调用 87 signParams := []string{"wallet", "sign", "-d", createRes, "--rpc_laddr", rpcAddr} 88 cmdSign := exec.Command(cmdName, append(signParams, keyParams...)...) 89 signRes, err := execCmd(cmdSign) 90 if err != nil { 91 fmt.Fprintln(os.Stderr, err) 92 return 93 } 94 //交易发送命令调用 95 sendParams := []string{"wallet", "send", "-d", signRes, "--rpc_laddr", rpcAddr} 96 cmdSend := exec.Command(cmdName, sendParams...) 97 sendRes, err := execCmd(cmdSend) 98 if err != nil { 99 fmt.Fprintln(os.Stderr, err) 100 return 101 } 102 fmt.Println(sendRes) 103 } 104 105 func execCmd(c *exec.Cmd) (string, error) { 106 var outBuf, errBuf bytes.Buffer 107 c.Stderr = &errBuf 108 c.Stdout = &outBuf 109 110 if err := c.Run(); err != nil { 111 return "", errors.New(err.Error() + "\n" + errBuf.String()) 112 } 113 if len(errBuf.String()) > 0 { 114 return "", errors.New(errBuf.String()) 115 } 116 outBytes := outBuf.Bytes() 117 return string(outBytes[:len(outBytes)-1]), nil 118 } 119 120 func loadSendHelp() { 121 help := `[Integrate create/sign/send transaction operations in one command] 122 Usage: 123 -cli send [flags] 124 125 Examples: 126 cli send coins transfer -a 1 -n note -t toAddr -k [privateKey | fromAddr] 127 128 equivalent to three steps: 129 1. cli coins transfer -a 1 -n note -t toAddr //create raw tx 130 2. cli wallet sign -d rawTx -k privateKey //sign raw tx 131 3. cli wallet send -d signTx //send tx to block chain 132 133 Flags: 134 -h, --help help for send 135 -k, --key private key or from address for sign tx, required` 136 fmt.Println(help) 137 }