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  }