Skip to content

Commit

Permalink
feat: kucoin api
Browse files Browse the repository at this point in the history
  • Loading branch information
linstohu committed Nov 13, 2023
1 parent fcd8b65 commit c70cdb7
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 32 deletions.
16 changes: 9 additions & 7 deletions kucoin/rest/account/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package account

import (
"context"
"encoding/json"
"errors"
"log/slog"
"net/http"
Expand All @@ -43,6 +42,7 @@ type AccountClientCfg struct {

BaseURL string `validate:"required"`
Key string `validate:"required"`
KeyVersion string `validate:"required"`
Secret string `validate:"required"`
Passphrase string `validate:"required"`
}
Expand All @@ -56,11 +56,13 @@ func NewAccountClient(cfg *AccountClientCfg) (*AccountClient, error) {
}

cli, err := utils.NewKucoinRestClient(&utils.KucoinClientCfg{
Debug: cfg.Debug,
Logger: cfg.Logger,
BaseURL: cfg.BaseURL,
Key: cfg.Key,
Secret: cfg.Secret,
Debug: cfg.Debug,
Logger: cfg.Logger,
BaseURL: cfg.BaseURL,
Key: cfg.Key,
KeyVersion: cfg.KeyVersion,
Secret: cfg.Secret,
Passphrase: cfg.Passphrase,
})
if err != nil {
return nil, err
Expand Down Expand Up @@ -114,7 +116,7 @@ func (a *AccountClient) GetAccountList(ctx context.Context, param types.GetAccou
}

var ret []*types.AccountModel
if err := json.Unmarshal(ar.RawData, &ret); err != nil {
if err := ar.ReadData(&ret); err != nil {
return nil, err
}

Expand Down
10 changes: 6 additions & 4 deletions kucoin/rest/account/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ import (

func testNewAccountClient(t *testing.T) *AccountClient {
cli, err := NewAccountClient(&AccountClientCfg{
BaseURL: utils.SpotBaseURL,
Key: os.Getenv("KUCOIN_KEY"),
Secret: os.Getenv("KUCOIN_SECRET"),
Debug: true,
BaseURL: utils.SpotBaseURL,
Key: os.Getenv("KUCOIN_KEY"),
KeyVersion: utils.ApiKeyVersionV2,
Secret: os.Getenv("KUCOIN_SECRET"),
Passphrase: os.Getenv("KUCOIN_PASS"),
Debug: true,
})

if err != nil {
Expand Down
4 changes: 2 additions & 2 deletions kucoin/rest/account/types/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
package types

type GetAccountListParam struct {
Currency string `url:"currency" validate:"omitempty"`
Type string `url:"type" validate:"omitempty"`
Currency string `url:"currency,omitempty" validate:"omitempty"`
Type string `url:"type,omitempty" validate:"omitempty"`
}

// An AccountModel represents an account.
Expand Down
40 changes: 23 additions & 17 deletions kucoin/rest/utils/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
"log/slog"
Expand All @@ -41,8 +42,8 @@ type KucoinClient struct {
// logger
logger *slog.Logger

baseURL string
key, secret, passphrase string
baseURL string
key, secret, passphrase, keyVersion string
}

type KucoinClientCfg struct {
Expand All @@ -52,6 +53,7 @@ type KucoinClientCfg struct {

BaseURL string `validate:"required"`
Key string
KeyVersion string
Secret string
Passphrase string
}
Expand All @@ -67,8 +69,9 @@ func NewKucoinRestClient(cfg *KucoinClientCfg) (*KucoinClient, error) {
logger: cfg.Logger,
baseURL: cfg.BaseURL,
key: cfg.Key,
keyVersion: cfg.KeyVersion,
secret: cfg.Secret,
passphrase: cfg.Passphrase,
passphrase: sign([]byte(cfg.Secret), []byte(cfg.Passphrase)),
}

if cli.logger == nil {
Expand Down Expand Up @@ -125,26 +128,22 @@ func (k *KucoinClient) GenSignature(req HTTPRequest) (map[string]string, error)
b.Write([]byte(reqBody))
}

t := IntToString(time.Now().UnixNano() / 1000000)
p := []byte(t + b.String())
s := string(k.Sign(p))
t := time.Now().UnixMilli()

signStr := fmt.Sprintf("%v%s", t, b.String())
s := sign([]byte(k.secret), []byte(signStr))

ksHeaders := map[string]string{
"KC-API-KEY": k.key,
"KC-API-PASSPHRASE": k.passphrase,
"KC-API-TIMESTAMP": t,
"KC-API-SIGN": s,
"KC-API-KEY": k.key,
"KC-API-PASSPHRASE": k.passphrase,
"KC-API-TIMESTAMP": fmt.Sprintf("%v", t),
"KC-API-SIGN": s,
"KC-API-KEY-VERSION": "2",
}

return ksHeaders, nil
}

// Sign makes a signature by sha256.
func (k *KucoinClient) Sign(plain []byte) []byte {
hm := hmac.New(sha256.New, []byte(k.secret))
hm.Write(plain)
return hm.Sum(nil)
}

func (s *KucoinClient) SendHTTPRequest(ctx context.Context, req HTTPRequest) (*HTTPResponse, error) {
client := http.Client{}

Expand Down Expand Up @@ -204,3 +203,10 @@ func (s *KucoinClient) SendHTTPRequest(ctx context.Context, req HTTPRequest) (*H

return NewResponse(&req, resp, nil), nil
}

// sign makes a signature by sha256.
func sign(key, plain []byte) string {
hm := hmac.New(sha256.New, key)
hm.Write(plain)
return base64.StdEncoding.EncodeToString(hm.Sum(nil))
}
2 changes: 1 addition & 1 deletion kucoin/rest/utils/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (h *HTTPRequest) RequestURI() (string, error) {
url.RawQuery = q.Encode()
}

return url.String(), nil
return url.RequestURI(), nil
}

func (h *HTTPRequest) RequestBody() (string, error) {
Expand Down
8 changes: 7 additions & 1 deletion kucoin/rest/utils/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ var (
FuturesBaseURL = "https://api-futures.kucoin.com"
)

var NIL = "<nil>"
var NIL = "<nil>"

// ApiKeyVersionV1 is v1 api key version
const ApiKeyVersionV1 = "1"

// ApiKeyVersionV2 is v2 api key version
const ApiKeyVersionV2 = "2"

0 comments on commit c70cdb7

Please sign in to comment.