github.com/frankrap/okex-api@v1.0.4/utils.go (about)

     1  package okex
     2  
     3  /*
     4   utils
     5   @author Tony Tian
     6   @date 2018-03-17
     7   @version 1.0.0
     8  */
     9  
    10  import (
    11  	"bytes"
    12  	"compress/flate"
    13  	"crypto/hmac"
    14  	"crypto/md5"
    15  	"crypto/sha256"
    16  	"encoding/base64"
    17  	"errors"
    18  	"fmt"
    19  	"io/ioutil"
    20  	"net/http"
    21  	"net/url"
    22  	"sort"
    23  	"strconv"
    24  	"strings"
    25  	"time"
    26  )
    27  
    28  /*
    29   signing a message
    30   using: hmac sha256 + base64
    31    eg:
    32      message = Pre_hash function comment
    33      secretKey = E65791902180E9EF4510DB6A77F6EBAE
    34  
    35    return signed string = TO6uwdqz+31SIPkd4I+9NiZGmVH74dXi+Fd5X0EzzSQ=
    36  */
    37  func HmacSha256Base64Signer(message string, secretKey string) (string, error) {
    38  	mac := hmac.New(sha256.New, []byte(secretKey))
    39  	_, err := mac.Write([]byte(message))
    40  	if err != nil {
    41  		return "", err
    42  	}
    43  	return base64.StdEncoding.EncodeToString(mac.Sum(nil)), nil
    44  }
    45  
    46  /*
    47   the pre hash string
    48    eg:
    49      timestamp = 2018-03-08T10:59:25.789Z
    50      method  = POST
    51      request_path = /orders?before=2&limit=30
    52      body = {"product_id":"BTC-USD-0309","order_id":"377454671037440"}
    53  
    54    return pre hash string = 2018-03-08T10:59:25.789ZPOST/orders?before=2&limit=30{"product_id":"BTC-USD-0309","order_id":"377454671037440"}
    55  */
    56  func PreHashString(timestamp string, method string, requestPath string, body string) string {
    57  	return timestamp + strings.ToUpper(method) + requestPath + body
    58  }
    59  
    60  /*
    61    md5 sign
    62  */
    63  func Md5Signer(message string) string {
    64  	data := []byte(message)
    65  	has := md5.Sum(data)
    66  	return fmt.Sprintf("%x", has)
    67  }
    68  
    69  /*
    70   int convert string
    71  */
    72  func Int2String(arg int) string {
    73  	return strconv.Itoa(arg)
    74  }
    75  
    76  /*
    77   int64 convert string
    78  */
    79  func Int642String(arg int64) string {
    80  	return strconv.FormatInt(int64(arg), 10)
    81  }
    82  
    83  /*
    84    json string convert struct
    85  */
    86  func JsonString2Struct(jsonString string, result interface{}) error {
    87  	jsonBytes := []byte(jsonString)
    88  	err := json.Unmarshal(jsonBytes, result)
    89  	return err
    90  }
    91  
    92  /*
    93    json byte array convert struct
    94  */
    95  func JsonBytes2Struct(jsonBytes []byte, result interface{}) error {
    96  	err := json.Unmarshal(jsonBytes, result)
    97  	return err
    98  }
    99  
   100  /*
   101   struct convert json string
   102  */
   103  func Struct2JsonString(structt interface{}) (jsonString string, err error) {
   104  	data, err := json.Marshal(structt)
   105  	if err != nil {
   106  		return "", err
   107  	}
   108  	return string(data), nil
   109  }
   110  
   111  /*
   112    ternary operator replace language: a == b ? c : d
   113  */
   114  func T3O(condition bool, trueValue, falseValue interface{}) interface{} {
   115  	if condition {
   116  		return trueValue
   117  	}
   118  	return falseValue
   119  }
   120  
   121  /*
   122   Get a epoch time
   123    eg: 1521221737.376
   124  */
   125  func EpochTime() string {
   126  	millisecond := time.Now().UnixNano() / 1000000
   127  	epoch := strconv.Itoa(int(millisecond))
   128  	epochBytes := []byte(epoch)
   129  	epoch = string(epochBytes[:10]) + "." + string(epochBytes[10:])
   130  	return epoch
   131  }
   132  
   133  /*
   134   Get a iso time
   135    eg: 2018-03-16T18:02:48.284Z
   136  */
   137  func IsoTime() string {
   138  	utcTime := time.Now().UTC()
   139  	iso := utcTime.String()
   140  	isoBytes := []byte(iso)
   141  	iso = string(isoBytes[:10]) + "T" + string(isoBytes[11:23]) + "Z"
   142  	return iso
   143  }
   144  
   145  /*
   146   Get utc +8 -- 1540365300000 -> 2018-10-24 15:15:00 +0800 CST
   147  */
   148  func LongTimeToUTC8(longTime int64) time.Time {
   149  	timeString := Int64ToString(longTime)
   150  	sec := timeString[0:10]
   151  	nsec := timeString[10:len(timeString)]
   152  	return time.Unix(StringToInt64(sec), StringToInt64(nsec))
   153  }
   154  
   155  /*
   156   1540365300000 -> 2018-10-24 15:15:00
   157  */
   158  func LongTimeToUTC8Format(longTime int64) string {
   159  	return LongTimeToUTC8(longTime).Format("2006-01-02 15:04:05")
   160  }
   161  
   162  /*
   163    iso time change to time.Time
   164    eg: "2018-11-18T16:51:55.933Z" -> 2018-11-18 16:51:55.000000933 +0000 UTC
   165  */
   166  func IsoToTime(iso string) (time.Time, error) {
   167  	nilTime := time.Now()
   168  	if iso == "" {
   169  		return nilTime, errors.New("illegal parameter")
   170  	}
   171  	// "2018-03-18T06:51:05.933Z"
   172  	isoBytes := []byte(iso)
   173  	year, err := strconv.Atoi(string(isoBytes[0:4]))
   174  	if err != nil {
   175  		return nilTime, errors.New("illegal year")
   176  	}
   177  	month, err := strconv.Atoi(string(isoBytes[5:7]))
   178  	if err != nil {
   179  		return nilTime, errors.New("illegal month")
   180  	}
   181  	day, err := strconv.Atoi(string(isoBytes[8:10]))
   182  	if err != nil {
   183  		return nilTime, errors.New("illegal day")
   184  	}
   185  	hour, err := strconv.Atoi(string(isoBytes[11:13]))
   186  	if err != nil {
   187  		return nilTime, errors.New("illegal hour")
   188  	}
   189  	min, err := strconv.Atoi(string(isoBytes[14:16]))
   190  	if err != nil {
   191  		return nilTime, errors.New("illegal min")
   192  	}
   193  	sec, err := strconv.Atoi(string(isoBytes[17:19]))
   194  	if err != nil {
   195  		return nilTime, errors.New("illegal sec")
   196  	}
   197  	nsec, err := strconv.Atoi(string(isoBytes[20 : len(isoBytes)-1]))
   198  	if err != nil {
   199  		return nilTime, errors.New("illegal nsec")
   200  	}
   201  	return time.Date(year, time.Month(month), day, hour, min, sec, nsec, time.UTC), nil
   202  }
   203  
   204  /*
   205   Get a http request body is a json string and a byte array.
   206  */
   207  func ParseRequestParams(params interface{}) (string, *bytes.Reader, error) {
   208  	if params == nil {
   209  		return "", nil, errors.New("illegal parameter")
   210  	}
   211  	data, err := json.Marshal(params)
   212  	if err != nil {
   213  		return "", nil, errors.New("json convert string error")
   214  	}
   215  	jsonBody := string(data)
   216  	binBody := bytes.NewReader(data)
   217  	return jsonBody, binBody, nil
   218  }
   219  
   220  /*
   221   Set http request headers:
   222     Accept: application/json
   223     Content-Type: application/json; charset=UTF-8  (default)
   224     Cookie: locale=en_US        (English)
   225     OK-ACCESS-KEY: (Your setting)
   226     OK-ACCESS-SIGN: (Use your setting, auto sign and add)
   227     OK-ACCESS-TIMESTAMP: (Auto add)
   228     OK-ACCESS-PASSPHRASE: Your setting
   229  */
   230  func Headers(request *http.Request, config Config, timestamp string, sign string) {
   231  	request.Header.Add(ACCEPT, APPLICATION_JSON)
   232  	request.Header.Add(CONTENT_TYPE, APPLICATION_JSON_UTF8)
   233  	request.Header.Add(COOKIE, LOCALE+config.I18n)
   234  	request.Header.Add(OK_ACCESS_KEY, config.ApiKey)
   235  	request.Header.Add(OK_ACCESS_SIGN, sign)
   236  	request.Header.Add(OK_ACCESS_TIMESTAMP, timestamp)
   237  	request.Header.Add(OK_ACCESS_PASSPHRASE, config.Passphrase)
   238  }
   239  
   240  /*
   241   Get a new map.eg: {string:string}
   242  */
   243  func NewParams() map[string]string {
   244  	return make(map[string]string)
   245  }
   246  
   247  /*
   248    build http get request params, and order
   249    eg:
   250      params := make(map[string]string)
   251  	params["bb"] = "222"
   252  	params["aa"] = "111"
   253  	params["cc"] = "333"
   254    return string: eg: aa=111&bb=222&cc=333
   255  */
   256  func BuildOrderParams(params map[string]string) string {
   257  	var keys []string
   258  	for k := range params {
   259  		keys = append(keys, k)
   260  	}
   261  	sort.Strings(keys)
   262  	urlParams := url.Values{}
   263  	for k := range params {
   264  		urlParams.Add(k, params[k])
   265  	}
   266  	return urlParams.Encode()
   267  }
   268  
   269  /*
   270   Get api requestPath + requestParams
   271  	params := NewParams()
   272  	params["depth"] = "200"
   273  	params["conflated"] = "0"
   274  	url := BuildParams("/api/futures/v3/products/BTC-USD-0310/book", params)
   275   return eg:/api/futures/v3/products/BTC-USD-0310/book?conflated=0&depth=200
   276  */
   277  func BuildParams(requestPath string, params map[string]string) string {
   278  	urlParams := url.Values{}
   279  	for k := range params {
   280  		urlParams.Add(k, params[k])
   281  	}
   282  	return requestPath + "?" + urlParams.Encode()
   283  }
   284  
   285  /*
   286   Get api v1 requestPath + requestParams
   287  	params := okex.NewParams()
   288  	params["symbol"] = "btc_usd"
   289  	params["contract_type"] = "this_week"
   290  	params["status"] = "1"
   291  	requestPath := "/api/v1/future_explosive.do"
   292      return eg: /api/v1/future_explosive.do?api_key=88af5759-61f2-47e9-b2e9-17ce3a390488&contract_type=this_week&status=1&symbol=btc_usd&sign=966ACD0DE5F729BC9C9C03D92ABBEB68
   293  */
   294  func BuildAPIV1Params(requestPath string, params map[string]string, config Config) string {
   295  	params["api_key"] = config.ApiKey
   296  	sortParams := BuildOrderParams(params)
   297  	preMd5Params := sortParams + "&secret_key=" + config.SecretKey
   298  	md5Sign := Md5Signer(preMd5Params)
   299  	requestParams := sortParams + "&sign=" + strings.ToUpper(md5Sign)
   300  	return requestPath + "?" + requestParams
   301  }
   302  
   303  func GetResponseDataJsonString(response *http.Response) string {
   304  	return response.Header.Get(ResultDataJsonString)
   305  }
   306  func GetResponsePageJsonString(response *http.Response) string {
   307  	return response.Header.Get(ResultPageJsonString)
   308  }
   309  
   310  /*
   311    ternary operator biz extension
   312  */
   313  func T3Ox(err error, value interface{}) (interface{}, error) {
   314  	if err != nil {
   315  		return nil, err
   316  	}
   317  	return value, nil
   318  }
   319  
   320  /*
   321    return decimalism string 9223372036854775807 -> "9223372036854775807"
   322  */
   323  func Int64ToString(arg int64) string {
   324  	return strconv.FormatInt(arg, 10)
   325  }
   326  
   327  func IntToString(arg int) string {
   328  	return strconv.Itoa(arg)
   329  }
   330  
   331  func StringToInt64(arg string) int64 {
   332  	value, err := strconv.ParseInt(arg, 10, 64)
   333  	if err != nil {
   334  		return 0
   335  	} else {
   336  		return value
   337  	}
   338  }
   339  
   340  func StringToInt(arg string) int {
   341  	value, err := strconv.Atoi(arg)
   342  	if err != nil {
   343  		return 0
   344  	} else {
   345  		return value
   346  	}
   347  }
   348  
   349  /*
   350    call fmt.Println(...)
   351  */
   352  func FmtPrintln(flag string, info interface{}) {
   353  	fmt.Print(flag)
   354  	if info != nil {
   355  		jsonString, err := Struct2JsonString(info)
   356  		if err != nil {
   357  			fmt.Println(err)
   358  		}
   359  		fmt.Println(jsonString)
   360  	} else {
   361  		fmt.Println("{}")
   362  	}
   363  }
   364  
   365  func GetInstrumentIdUri(uri, instrumentId string) string {
   366  	return strings.Replace(uri, "{instrument_id}", instrumentId, -1)
   367  }
   368  
   369  func GetCurrencyUri(uri, currency string) string {
   370  	return strings.Replace(uri, "{currency}", currency, -1)
   371  }
   372  
   373  func GetInstrumentIdOrdersUri(uri, instrumentId string, orderId string) string {
   374  	uri = strings.Replace(uri, "{instrument_id}", instrumentId, -1)
   375  	uri = strings.Replace(uri, "{order_id}", orderId, -1)
   376  	return uri
   377  }
   378  
   379  func GetUnderlyingUri(uri, underlying string) string {
   380  	return strings.Replace(uri, "{underlying}", underlying, -1)
   381  }
   382  
   383  func FlateUnCompress(data []byte) ([]byte, error) {
   384  	return ioutil.ReadAll(flate.NewReader(bytes.NewReader(data)))
   385  }
   386  
   387  // "socks5://127.0.0.1:1080"
   388  func ParseProxy(proxyURL string) (res func(*http.Request) (*url.URL, error), err error) {
   389  	var purl *url.URL
   390  	purl, err = url.Parse(proxyURL)
   391  	if err != nil {
   392  		return
   393  	}
   394  	res = http.ProxyURL(purl)
   395  	return
   396  }