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  }