github.com/turingchain2020/turingchain@v1.1.21/system/dapp/commands/tx.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 "strings" 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 // TxCmd transaction command 21 func TxCmd() *cobra.Command { 22 cmd := &cobra.Command{ 23 Use: "tx", 24 Short: "Transaction management", 25 Args: cobra.MinimumNArgs(1), 26 } 27 28 cmd.AddCommand( 29 QueryTxCmd(), 30 QueryTxByAddrCmd(), 31 QueryTxsByHashesCmd(), 32 GetRawTxCmd(), 33 DecodeTxCmd(), 34 GetAddrOverviewCmd(), 35 ReWriteRawTxCmd(), 36 ) 37 38 return cmd 39 } 40 41 // QueryTxByAddrCmd get tx by address 42 func QueryTxByAddrCmd() *cobra.Command { 43 cmd := &cobra.Command{ 44 Use: "query_addr", 45 Short: "Query transaction by account address", 46 Run: queryTxByAddr, 47 } 48 addQueryTxByAddrFlags(cmd) 49 return cmd 50 } 51 52 func addQueryTxByAddrFlags(cmd *cobra.Command) { 53 cmd.Flags().StringP("addr", "a", "", "account address") 54 cmd.MarkFlagRequired("addr") 55 56 cmd.Flags().Int32P("flag", "f", 0, "transaction type(0: all txs relevant to addr, 1: addr as sender, 2: addr as receiver) (default 0)") 57 cmd.Flags().Int32P("count", "c", 10, "maximum return number of transactions") 58 cmd.Flags().Int32P("direction", "d", 0, "query direction from height:index(0: positive order -1:negative order) (default 0)") 59 cmd.Flags().Int64P("height", "t", -1, "transaction's block height(-1: from latest txs, >=0: query from height)") 60 cmd.Flags().Int64P("index", "i", 0, "query from index of tx in block height[0-100000] (default 0)") 61 } 62 63 func queryTxByAddr(cmd *cobra.Command, args []string) { 64 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 65 addr, _ := cmd.Flags().GetString("addr") 66 flag, _ := cmd.Flags().GetInt32("flag") 67 count, _ := cmd.Flags().GetInt32("count") 68 direction, _ := cmd.Flags().GetInt32("direction") 69 height, _ := cmd.Flags().GetInt64("height") 70 index, _ := cmd.Flags().GetInt64("index") 71 params := types.ReqAddr{ 72 Addr: addr, 73 Flag: flag, 74 Count: count, 75 Direction: direction, 76 Height: height, 77 Index: index, 78 } 79 var res rpctypes.ReplyTxInfos 80 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.GetTxByAddr", params, &res) 81 ctx.Run() 82 } 83 84 // QueryTxCmd query tx by hash 85 func QueryTxCmd() *cobra.Command { 86 cmd := &cobra.Command{ 87 Use: "query", 88 Short: "Query transaction by hash", 89 Run: queryTx, 90 } 91 addQueryTxFlags(cmd) 92 return cmd 93 } 94 95 func addQueryTxFlags(cmd *cobra.Command) { 96 cmd.Flags().StringP("hash", "s", "", "transaction hash") 97 cmd.MarkFlagRequired("hash") 98 } 99 100 func queryTx(cmd *cobra.Command, args []string) { 101 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 102 hash, _ := cmd.Flags().GetString("hash") 103 if len(hash) != 66 { 104 fmt.Print(types.ErrHashNotExist.Error()) 105 return 106 } 107 params := rpctypes.QueryParm{ 108 Hash: hash, 109 } 110 var res rpctypes.TransactionDetail 111 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.QueryTransaction", params, &res) 112 ctx.SetResultCb(parseQueryTxRes) 113 ctx.Run() 114 } 115 116 func parseQueryTxRes(arg interface{}) (interface{}, error) { 117 res := arg.(*rpctypes.TransactionDetail) 118 amountResult := strconv.FormatFloat(float64(res.Amount)/float64(types.Coin), 'f', 4, 64) 119 result := commandtypes.TxDetailResult{ 120 Tx: commandtypes.DecodeTransaction(res.Tx), 121 Receipt: res.Receipt, 122 Proofs: res.Proofs, 123 Height: res.Height, 124 Index: res.Index, 125 Blocktime: res.Blocktime, 126 Amount: amountResult, 127 Fromaddr: res.Fromaddr, 128 ActionName: res.ActionName, 129 Assets: res.Assets, 130 TxProofs: res.TxProofs, 131 FullHash: res.FullHash, 132 } 133 return result, nil 134 } 135 136 // QueryTxsByHashesCmd get transactions by hashes 137 func QueryTxsByHashesCmd() *cobra.Command { 138 cmd := &cobra.Command{ 139 Use: "query_hash", 140 Short: "Get transactions by hashes", 141 Run: getTxsByHashes, 142 } 143 addGetTxsByHashesFlags(cmd) 144 return cmd 145 } 146 147 func addGetTxsByHashesFlags(cmd *cobra.Command) { 148 cmd.Flags().StringP("hashes", "s", "", "transaction hash(es), separated by space") 149 cmd.MarkFlagRequired("hashes") 150 } 151 152 func getTxsByHashes(cmd *cobra.Command, args []string) { 153 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 154 hashes, _ := cmd.Flags().GetString("hashes") 155 hashesArr := strings.Split(hashes, " ") 156 params := rpctypes.ReqHashes{ 157 Hashes: hashesArr, 158 } 159 160 var res rpctypes.TransactionDetails 161 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.GetTxByHashes", params, &res) 162 ctx.SetResultCb(parseQueryTxsByHashesRes) 163 ctx.Run() 164 } 165 166 func parseQueryTxsByHashesRes(arg interface{}) (interface{}, error) { 167 var result commandtypes.TxDetailsResult 168 for _, v := range arg.(*rpctypes.TransactionDetails).Txs { 169 if v == nil { 170 result.Txs = append(result.Txs, nil) 171 continue 172 } 173 amountResult := strconv.FormatFloat(float64(v.Amount)/float64(types.Coin), 'f', 4, 64) 174 td := commandtypes.TxDetailResult{ 175 Tx: commandtypes.DecodeTransaction(v.Tx), 176 Receipt: v.Receipt, 177 Proofs: v.Proofs, 178 Height: v.Height, 179 Index: v.Index, 180 Blocktime: v.Blocktime, 181 Amount: amountResult, 182 Fromaddr: v.Fromaddr, 183 ActionName: v.ActionName, 184 Assets: v.Assets, 185 } 186 result.Txs = append(result.Txs, &td) 187 } 188 return result, nil 189 } 190 191 // GetRawTxCmd get raw transaction hex 192 func GetRawTxCmd() *cobra.Command { 193 cmd := &cobra.Command{ 194 Use: "get_hex", 195 Short: "Get transaction hex by hash", 196 Run: getTxHexByHash, 197 } 198 addGetRawTxFlags(cmd) 199 return cmd 200 } 201 202 func addGetRawTxFlags(cmd *cobra.Command) { 203 cmd.Flags().StringP("hash", "s", "", "transaction hash") 204 cmd.MarkFlagRequired("hash") 205 } 206 207 func getTxHexByHash(cmd *cobra.Command, args []string) { 208 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 209 txHash, _ := cmd.Flags().GetString("hash") 210 params := rpctypes.QueryParm{ 211 Hash: txHash, 212 } 213 214 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.GetHexTxByHash", params, nil) 215 ctx.RunWithoutMarshal() 216 } 217 218 // DecodeTxCmd decode raw hex to transaction 219 func DecodeTxCmd() *cobra.Command { 220 cmd := &cobra.Command{ 221 Use: "decode", 222 Short: "Decode a hex format transaction", 223 Run: decodeTx, 224 } 225 addDecodeTxFlags(cmd) 226 return cmd 227 } 228 229 func addDecodeTxFlags(cmd *cobra.Command) { 230 cmd.Flags().StringP("data", "d", "", "transaction content") 231 cmd.MarkFlagRequired("data") 232 } 233 234 func decodeTx(cmd *cobra.Command, args []string) { 235 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 236 data, _ := cmd.Flags().GetString("data") 237 params := types.ReqDecodeRawTransaction{ 238 TxHex: data, 239 } 240 241 var res rpctypes.ReplyTxList 242 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.DecodeRawTransaction", params, &res) 243 ctx.SetResultCb(parseReplyTxList) 244 ctx.Run() 245 } 246 247 func parseReplyTxList(view interface{}) (interface{}, error) { 248 replyTxList := view.(*rpctypes.ReplyTxList) 249 var commandtxs commandtypes.TxListResult 250 for _, cmdtx := range replyTxList.Txs { 251 txResult := commandtypes.DecodeTransaction(cmdtx) 252 commandtxs.Txs = append(commandtxs.Txs, txResult) 253 } 254 return &commandtxs, nil 255 } 256 257 // GetAddrOverviewCmd get overview of an address 258 func GetAddrOverviewCmd() *cobra.Command { 259 cmd := &cobra.Command{ 260 Use: "addr_overview", 261 Short: "View transactions of address", 262 Run: viewAddress, 263 } 264 addAddrViewFlags(cmd) 265 return cmd 266 } 267 268 func addAddrViewFlags(cmd *cobra.Command) { 269 cmd.Flags().StringP("addr", "a", "", "account address") 270 cmd.MarkFlagRequired("addr") 271 } 272 273 func viewAddress(cmd *cobra.Command, args []string) { 274 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 275 addr, _ := cmd.Flags().GetString("addr") 276 params := types.ReqAddr{ 277 Addr: addr, 278 } 279 280 var res types.AddrOverview 281 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.GetAddrOverview", params, &res) 282 ctx.SetResultCb(parseAddrOverview) 283 ctx.Run() 284 } 285 286 func parseAddrOverview(view interface{}) (interface{}, error) { 287 res := view.(*types.AddrOverview) 288 balance := strconv.FormatFloat(float64(res.GetBalance())/float64(types.Coin), 'f', 4, 64) 289 receiver := strconv.FormatFloat(float64(res.GetReciver())/float64(types.Coin), 'f', 4, 64) 290 addrOverview := &commandtypes.AddrOverviewResult{ 291 Balance: balance, 292 Receiver: receiver, 293 TxCount: res.GetTxCount(), 294 } 295 return addrOverview, nil 296 } 297 298 // ReWriteRawTxCmd re-write raw transaction hex 299 func ReWriteRawTxCmd() *cobra.Command { 300 cmd := &cobra.Command{ 301 Use: "rewrite", 302 Short: "rewrite transaction parameters", 303 Run: reWriteRawTx, 304 } 305 addReWriteRawTxFlags(cmd) 306 return cmd 307 } 308 309 func addReWriteRawTxFlags(cmd *cobra.Command) { 310 cmd.Flags().StringP("tx", "s", "", "transaction hex") 311 cmd.MarkFlagRequired("tx") 312 cmd.Flags().StringP("to", "t", "", "to addr (optional)") 313 cmd.Flags().Float64P("fee", "f", 0, "transaction fee (optional)") 314 cmd.Flags().StringP("expire", "e", "", "expire time (optional)") 315 cmd.Flags().Int32P("index", "i", 0, "transaction index to be signed") 316 } 317 318 func reWriteRawTx(cmd *cobra.Command, args []string) { 319 rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") 320 txHex, _ := cmd.Flags().GetString("tx") 321 to, _ := cmd.Flags().GetString("to") 322 fee, _ := cmd.Flags().GetFloat64("fee") 323 index, _ := cmd.Flags().GetInt32("index") 324 expire, _ := cmd.Flags().GetString("expire") 325 326 var err error 327 if expire != "" { 328 expire, err = commandtypes.CheckExpireOpt(expire) 329 if err != nil { 330 fmt.Fprintln(os.Stderr, err) 331 return 332 } 333 } 334 335 feeInt64 := int64(fee * 1e4) 336 337 params := rpctypes.ReWriteRawTx{ 338 Tx: txHex, 339 To: to, 340 Fee: feeInt64 * 1e4, 341 Expire: expire, 342 Index: index, 343 } 344 345 ctx := jsonclient.NewRPCCtx(rpcLaddr, "Turingchain.ReWriteRawTx", params, nil) 346 ctx.RunWithoutMarshal() 347 }