github.com/turingchain2020/turingchain@v1.1.21/system/dapp/commands/types/utils.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 types 6 7 import ( 8 // "encoding/json" 9 10 "strconv" 11 "strings" 12 13 "github.com/turingchain2020/turingchain/common/address" 14 "github.com/turingchain2020/turingchain/rpc/jsonclient" 15 rpctypes "github.com/turingchain2020/turingchain/rpc/types" 16 cty "github.com/turingchain2020/turingchain/system/dapp/coins/types" 17 "github.com/turingchain2020/turingchain/types" 18 "github.com/spf13/cobra" 19 20 // TODO: 暂时将插件中的类型引用起来,后续需要修改 21 22 "encoding/hex" 23 "errors" 24 "fmt" 25 "math" 26 "time" 27 ) 28 29 // DecodeTransaction decode transaction function 30 func DecodeTransaction(tx *rpctypes.Transaction) *TxResult { 31 result := &TxResult{ 32 Execer: tx.Execer, 33 Payload: tx.Payload, 34 RawPayload: tx.RawPayload, 35 Signature: tx.Signature, 36 Fee: tx.FeeFmt, 37 Amount: tx.AmountFmt, 38 Expire: tx.Expire, 39 Nonce: tx.Nonce, 40 To: tx.To, 41 From: tx.From, 42 GroupCount: tx.GroupCount, 43 Header: tx.Header, 44 Next: tx.Next, 45 Hash: tx.Hash, 46 ChainID: tx.ChainID, 47 } 48 return result 49 } 50 51 // DecodeAccount decode account func 52 func DecodeAccount(acc *types.Account, precision int64) *AccountResult { 53 balanceResult := strconv.FormatFloat(float64(acc.GetBalance())/float64(precision), 'f', 4, 64) 54 frozenResult := strconv.FormatFloat(float64(acc.GetFrozen())/float64(precision), 'f', 4, 64) 55 accResult := &AccountResult{ 56 Addr: acc.GetAddr(), 57 Currency: acc.GetCurrency(), 58 Balance: balanceResult, 59 Frozen: frozenResult, 60 } 61 return accResult 62 } 63 64 // SendToAddress send to address func 65 func SendToAddress(rpcAddr string, from string, to string, amount int64, note string, isToken bool, tokenSymbol string, isWithdraw bool) { 66 amt := amount 67 if isWithdraw { 68 amt = -amount 69 } 70 params := types.ReqWalletSendToAddress{From: from, To: to, Amount: amt, Note: note} 71 if !isToken { 72 params.IsToken = false 73 } else { 74 params.IsToken = true 75 params.TokenSymbol = tokenSymbol 76 } 77 78 var res rpctypes.ReplyHash 79 ctx := jsonclient.NewRPCCtx(rpcAddr, "Turingchain.SendToAddress", params, &res) 80 ctx.Run() 81 } 82 83 // CreateRawTx create rawtransaction func 84 func CreateRawTx(cmd *cobra.Command, to string, amount float64, note string, isWithdraw bool, tokenSymbol, execName string) (string, error) { 85 title, _ := cmd.Flags().GetString("title") 86 cfg := types.GetCliSysParam(title) 87 88 if amount < 0 { 89 return "", types.ErrAmount 90 } 91 if float64(types.MaxCoin/types.Coin) < amount { 92 return "", types.ErrAmount 93 } 94 //检测to地址的合法性 95 if to != "" { 96 if err := address.CheckAddress(to); err != nil { 97 return "", types.ErrInvalidAddress 98 } 99 } 100 paraName, _ := cmd.Flags().GetString("paraName") 101 amountInt64 := int64(math.Trunc((amount+0.0000001)*1e4)) * 1e4 102 if execName != "" && !types.IsAllowExecName([]byte(execName), []byte(execName)) { 103 return "", types.ErrExecNameNotMatch 104 } 105 var tx *types.Transaction 106 transfer := &cty.CoinsAction{} 107 if !isWithdraw { 108 if execName != "" { 109 v := &cty.CoinsAction_TransferToExec{TransferToExec: &types.AssetsTransferToExec{Amount: amountInt64, Note: []byte(note), ExecName: execName, To: to}} 110 transfer.Value = v 111 transfer.Ty = cty.CoinsActionTransferToExec 112 } else { 113 v := &cty.CoinsAction_Transfer{Transfer: &types.AssetsTransfer{Amount: amountInt64, Note: []byte(note), To: to}} 114 transfer.Value = v 115 transfer.Ty = cty.CoinsActionTransfer 116 } 117 } else { 118 v := &cty.CoinsAction_Withdraw{Withdraw: &types.AssetsWithdraw{Amount: amountInt64, Note: []byte(note), ExecName: execName, To: to}} 119 transfer.Value = v 120 transfer.Ty = cty.CoinsActionWithdraw 121 } 122 execer := []byte(getRealExecName(paraName, "coins")) 123 if paraName == "" { 124 tx = &types.Transaction{Execer: execer, Payload: types.Encode(transfer), To: to} 125 } else { 126 tx = &types.Transaction{Execer: execer, Payload: types.Encode(transfer), To: address.ExecAddress(string(execer))} 127 } 128 tx, err := types.FormatTx(cfg, string(execer), tx) 129 if err != nil { 130 return "", err 131 } 132 txHex := types.Encode(tx) 133 return hex.EncodeToString(txHex), nil 134 } 135 136 // GetExecAddr get exec address func 137 func GetExecAddr(exec string) (string, error) { 138 if ok := types.IsAllowExecName([]byte(exec), []byte(exec)); !ok { 139 return "", types.ErrExecNameNotAllow 140 } 141 142 addrResult := address.ExecAddress(exec) 143 result := addrResult 144 return result, nil 145 } 146 147 // FormatAmountValue2Display 将传输、计算的amount值格式化成显示值 148 func FormatAmountValue2Display(amount int64) string { 149 return strconv.FormatFloat(float64(amount)/float64(types.Coin), 'f', 4, 64) 150 } 151 152 // FormatAmountDisplay2Value 将显示、输入的amount值格式话成传输、计算值 153 func FormatAmountDisplay2Value(amount float64) int64 { 154 return int64(amount*types.InputPrecision) * types.Multiple1E4 155 } 156 157 // GetAmountValue 将命令行中的amount值转换成int64 158 func GetAmountValue(cmd *cobra.Command, field string) int64 { 159 amount, _ := cmd.Flags().GetFloat64(field) 160 return FormatAmountDisplay2Value(amount) 161 } 162 163 func getRealExecName(paraName string, name string) string { 164 if strings.HasPrefix(name, "user.p.") { 165 return name 166 } 167 return paraName + name 168 } 169 170 func parseTxHeight(expire string) error { 171 if len(expire) == 0 { 172 return errors.New("expire string should not be empty") 173 } 174 175 if expire[0] == 'H' && expire[1] == ':' { 176 txHeight, err := strconv.Atoi(expire[2:]) 177 if err != nil { 178 return err 179 } 180 if txHeight <= 0 { 181 //fmt.Printf("txHeight should be grate to 0") 182 return errors.New("txHeight should be grate to 0") 183 } 184 185 return nil 186 } 187 188 return errors.New("Invalid expire format. Should be one of {time:\"3600s/1min/1h\" block:\"123\" txHeight:\"H:123\"}") 189 } 190 191 // CheckExpireOpt parse expire option in command 192 func CheckExpireOpt(expire string) (string, error) { 193 //时间格式123s/1m/1h 194 expireTime, err := time.ParseDuration(expire) 195 if err == nil { 196 if expireTime < time.Minute*2 && expireTime != time.Second*0 { 197 expire = "120s" 198 fmt.Println("expire time must longer than 2 minutes, changed expire time into 2 minutes") 199 } 200 201 return expire, nil 202 } 203 204 //区块高度格式,123 205 blockInt, err := strconv.Atoi(expire) 206 if err == nil { 207 if blockInt <= 0 { 208 fmt.Printf("block height should be grate to 0") 209 return "", errors.New("block height should be grate to 0") 210 } 211 return expire, nil 212 } 213 214 //Txheight格式,H:123 215 err = parseTxHeight(expire) 216 if err != nil { 217 return "", err 218 } 219 220 return expire, err 221 }