Skip to content

Commit

Permalink
exchanges: Add Kucoin support (#1102)
Browse files Browse the repository at this point in the history
* init

* updates config

* wrapper configuration

* updates exchange readme

* adds SendAuthHTTPRequest and SendHTTPRequest

* adds ratelimit file

* adds test case and minor fixes

* improve error handling

* update testcases and improve GetSymbols API

* adds SPOT API's

* minor fix

* WIP

* WIP

* adds test case

* adds check in test case

* fixes in Auth. HTTP

* improvements

* adds trade, kline support and testcases

* adds SPOT API and testcases for same

* adds SPOT API and testcases

* adds SPOT API and testcase

* WIP

* adds API's

* adds API's

* adds test cases

* adds comment to exported data types

* adds API and test cases

* adds API

* adds API

* rearrange functions

* WIP: adds API

* adds API for Post Order SPOT

* adds API and few fixes

* fixes

* WIP

* WIP

* add PostBulkOrder API and its test case

* fix issues

* adds cancel order APIs and test cases for same

* add minor test fixes

* add API

* adds API

* fixes

* add API

* adds API and test cases

* fix test

* adds API

* adds test

* fix test

* adds API and test

* adds deposit API and test cases

* WIP

* adds API and test cases

* WIP

* WIP

* add public future API and test cases

* WIP

* remove v2 API and replace them with v1

* update test cases

* adds future order API and test cases

* adds futures order API

* adds API

* add API and test cases

* adds API and test cases

* adds API and test cases

* adds API and test cases

* Adding wrapper functions

* Fix on wrapper function

* Adding websocket support

* Complete addressing WS push datas

* Adding spot push data unit tests

* adding futures websocket push data handlers

* Adding futures websocket push data handlers

* Added unit tests

* Updating unit tests

* Updating wrapper and unit test functions

* Adding missing wrapper functions and code cleaning up

* Resolved linter issues

* Fixing websocket issues

* Fixing websocket issues

* Slight fix on config_example file

* Minor update

* Basic nits updates

* Fix minor linter issues

* Minor update

* Minor unit test update

* Minor unit test update

* Code update and linter issues fix

* Removed unnecessary type conversion codes

* Monor update based on review comment

* Fix based on review comments

* Adding rate-limiter

* Websocket update and overall minor fixes

* Removed IsAssetTypeEnabled method implementation

* Fix connection and formatting issues

* Updating orderbook issues

* Very minor label fix

* Minor error returning fix

* code cleaning up and minor spelling fix

* Updates on unit test

* Update on unit tests and slight code structure

* unit test update

* orderbook update and minor fix

* fix on race

* Mini linter fix

* fix minor parameter and unit test issues

* handler funcs and models update

* Fixing websocket and unit test issues

* order side string for active orders

* Fix on websocket and unit tests

* Minor type changes

* Minor Orderbook fix and unit test update

* Small fix on orderbook

* Updating orderbook functionality

* FIx on websocket orderbook handlers

* Small update on kucoin websocket

* fix missed review comments

* fix based on review comments

* Updating websocket orderbook and fixing unit tests

* Minor fixes

* unit test update

* Updating unit test according to enabled asset type

* toggle canManipulateRealOrders const

* Unit test update

* Fix minor issues

* minor fix

* documentation fix

* wrapper coverage and unused params fix

* testing and minor changes

* documentation, websocket and unit test update

* minor linter fix

* Websocket spot/margin subscription update

* minor ticker update fix

* minor fixes on endpoints

* timestamp and number convert method and unit tests

* timestamp convert minor update

* minor type and conversion fix

* create a common timestamp convert and fix minor issues

* linter and ticker fix

* Updating unit tests and order placing endpoint methods

* Added a pairs check

* Fix config test error

* rm unused error variable

* Fix source of linter issue

* code update: convert, wrapper and websocket fix

* minor code update

* Websocket code and unit tests update

* Websocket ticker ask/bid type change and small error msg fix

* docs update

* fix: websocket orderbook handling

* change orderbook channel to marketOrderbookLevel2Channels and fix websocket orderbook update

* Minor func rename and reciever change

* Minor orderbook unit test issue fix

* comment: about why we used a random delimiter '-' for futures

* update config files and FetchTradablePair func for futures pairs

* futures config pairs update

* remove ConnextionMonitorDelay from websocket setup

* fix on types and futures pair conversion

* updating config pairs

* change NewPairFromString to DeriveFrom

* unit tests update

* unit tests update

* Added TickerBatching

* added GetStandardConfig to GetDefaultConfig

---------

Co-authored-by: Jaydeep Rajpurohit <[email protected]>
  • Loading branch information
samuael and Jdpurohit authored Sep 27, 2023
1 parent 5f2f6f8 commit 6105071
Show file tree
Hide file tree
Showing 29 changed files with 11,306 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ __debug_bin

# Coverage reports
coverage.txt
wrapperconfig.json
wrapperconfig.json
6 changes: 3 additions & 3 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ gloriousCode | https://github.com/gloriousCode
dependabot[bot] | https://github.com/apps/dependabot
dependabot-preview[bot] | https://github.com/apps/dependabot-preview
xtda | https://github.com/xtda
lrascao | https://github.com/lrascao
gbjk | https://github.com/gbjk
lrascao | https://github.com/lrascao
Rots | https://github.com/Rots
vazha | https://github.com/vazha
ydm | https://github.com/ydm
Expand All @@ -19,12 +19,12 @@ marcofranssen | https://github.com/marcofranssen
geseq | https://github.com/geseq
Beadko | https://github.com/Beadko
TaltaM | https://github.com/TaltaM
samuael | https://github.com/samuael
dackroyd | https://github.com/dackroyd
cranktakular | https://github.com/cranktakular
khcchiu | https://github.com/khcchiu
samuael | https://github.com/samuael
woshidama323 | https://github.com/woshidama323
yangrq1018 | https://github.com/yangrq1018
woshidama323 | https://github.com/woshidama323
crackcomm | https://github.com/crackcomm
azhang | https://github.com/azhang
andreygrehov | https://github.com/andreygrehov
Expand Down
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
| Huobi.Pro | Yes | Yes | NA |
| ItBit | Yes | NA | No |
| Kraken | Yes | Yes | NA |
| Kucoin | Yes | Yes | NA |
| Lbank | Yes | No | NA |
| Okcoin | Yes | Yes | No |
| Okx | Yes | Yes | NA |
Expand Down Expand Up @@ -143,14 +144,14 @@ Binaries will be published once the codebase reaches a stable condition.

|User|Contribution Amount|
|--|--|
| [thrasher-](https://github.com/thrasher-) | 682 |
| [shazbert](https://github.com/shazbert) | 299 |
| [gloriousCode](https://github.com/gloriousCode) | 217 |
| [dependabot[bot]](https://github.com/apps/dependabot) | 202 |
| [thrasher-](https://github.com/thrasher-) | 683 |
| [shazbert](https://github.com/shazbert) | 301 |
| [gloriousCode](https://github.com/gloriousCode) | 219 |
| [dependabot[bot]](https://github.com/apps/dependabot) | 207 |
| [dependabot-preview[bot]](https://github.com/apps/dependabot-preview) | 88 |
| [xtda](https://github.com/xtda) | 47 |
| [gbjk](https://github.com/gbjk) | 35 |
| [lrascao](https://github.com/lrascao) | 27 |
| [gbjk](https://github.com/gbjk) | 26 |
| [Rots](https://github.com/Rots) | 15 |
| [vazha](https://github.com/vazha) | 15 |
| [ydm](https://github.com/ydm) | 15 |
Expand All @@ -162,12 +163,12 @@ Binaries will be published once the codebase reaches a stable condition.
| [geseq](https://github.com/geseq) | 8 |
| [Beadko](https://github.com/Beadko) | 6 |
| [TaltaM](https://github.com/TaltaM) | 6 |
| [samuael](https://github.com/samuael) | 6 |
| [dackroyd](https://github.com/dackroyd) | 5 |
| [cranktakular](https://github.com/cranktakular) | 5 |
| [khcchiu](https://github.com/khcchiu) | 5 |
| [samuael](https://github.com/samuael) | 5 |
| [yangrq1018](https://github.com/yangrq1018) | 4 |
| [woshidama323](https://github.com/woshidama323) | 3 |
| [yangrq1018](https://github.com/yangrq1018) | 3 |
| [crackcomm](https://github.com/crackcomm) | 3 |
| [azhang](https://github.com/azhang) | 2 |
| [andreygrehov](https://github.com/andreygrehov) | 2 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ _b in this context is an `IBotExchange` implemented struct_
| Huobi.Pro | Yes | Yes | No |
| ItBit | Yes | NA | No |
| Kraken | Yes | Yes | No |
| Kucoin | Yes | No | Yes |
| Lbank | Yes | No | Yes |
| Okcoin | Yes | Yes | Yes |
| Okx | Yes | Yes | Yes |
Expand Down
1 change: 1 addition & 0 deletions cmd/documentation/root_templates/root_readme.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader
| Huobi.Pro | Yes | Yes | NA |
| ItBit | Yes | NA | No |
| Kraken | Yes | Yes | NA |
| Kucoin | Yes | Yes | NA |
| Lbank | Yes | No | NA |
| Okcoin | Yes | Yes | No |
| Okx | Yes | Yes | NA |
Expand Down
5 changes: 5 additions & 0 deletions cmd/exchange_wrapper_issues/wrapperconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@
"secret": "Secret",
"otpSecret": "-"
},
"kucoin":{
"key": "Key",
"secret": "Secret",
"otpSecret": "-"
},
"lbank": {
"key": "Key",
"secret": "Secret",
Expand Down
54 changes: 54 additions & 0 deletions common/convert/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package convert

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"math"
Expand Down Expand Up @@ -242,3 +243,56 @@ func (f StringToFloat64) Float64() float64 {
func (f StringToFloat64) Decimal() decimal.Decimal {
return decimal.NewFromFloat(float64(f))
}

// ExchangeTime provides timestamp to time conversion method.
type ExchangeTime time.Time

// UnmarshalJSON is custom type json unmarshaller for ExchangeTime
func (k *ExchangeTime) UnmarshalJSON(data []byte) error {
var timestamp interface{}
err := json.Unmarshal(data, &timestamp)
if err != nil {
return err
}
var standard int64
switch value := timestamp.(type) {
case string:
if value == "" {
// Setting the time to zero value because some timestamp fields could return an empty string while there is no error
// So, in such cases, Time returns zero timestamp.
break
}
standard, err = strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
case int64:
standard = value
case float64:
// Warning: converting float64 to int64 instance may create loss of precision in the timestamp information.
// be aware or consider customizing this section if found necessary.
standard = int64(value)
case nil:
// for some exchange timestamp fields, if the timestamp information is not specified,
// the data is 'nil' instead of zero value string or integer value.
default:
return fmt.Errorf("unsupported timestamp type %T", timestamp)
}

switch {
case standard == 0:
*k = ExchangeTime(time.Time{})
case standard >= 1e13:
*k = ExchangeTime(time.Unix(standard/1e9, standard%1e9))
case standard > 9999999999:
*k = ExchangeTime(time.UnixMilli(standard))
default:
*k = ExchangeTime(time.Unix(standard, 0))
}
return nil
}

// Time returns a time.Time instance from ExchangeTime instance object.
func (k ExchangeTime) Time() time.Time {
return time.Time(k)
}
83 changes: 83 additions & 0 deletions common/convert/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,3 +400,86 @@ func BenchmarkStringToFloat64(b *testing.B) {
}
}
}

func TestExchangeTimeUnmarshalJSON(t *testing.T) {
t.Parallel()
unmarshaledResult := &struct {
Timestamp ExchangeTime `json:"ts"`
}{}
data1 := `{"ts":""}`
result := time.Time{}
err := json.Unmarshal([]byte(data1), &unmarshaledResult)
if err != nil {
t.Fatal(err)
} else if !unmarshaledResult.Timestamp.Time().Equal(result) {
t.Errorf("found %v, but expected %v", unmarshaledResult.Timestamp.Time(), result)
}
data2 := `{"ts":"1685564775371"}`
result = time.UnixMilli(1685564775371)
err = json.Unmarshal([]byte(data2), &unmarshaledResult)
if err != nil {
t.Fatal(err)
} else if !unmarshaledResult.Timestamp.Time().Equal(result) {
t.Errorf("found %v, but expected %v", unmarshaledResult.Timestamp.Time(), result)
}
data3 := `{"ts":1685564775371}`
err = json.Unmarshal([]byte(data3), &unmarshaledResult)
if err != nil {
t.Fatal(err)
} else if !unmarshaledResult.Timestamp.Time().Equal(result) {
t.Errorf("found %v, but expected %v", unmarshaledResult.Timestamp.Time(), result)
}
data4 := `{"ts":"1685564775"}`
result = time.Unix(1685564775, 0)
err = json.Unmarshal([]byte(data4), &unmarshaledResult)
if err != nil {
t.Fatal(err)
} else if !unmarshaledResult.Timestamp.Time().Equal(result) {
t.Errorf("found %v, but expected %v", unmarshaledResult.Timestamp.Time(), result)
}
data5 := `{"ts":1685564775}`
err = json.Unmarshal([]byte(data5), &unmarshaledResult)
if err != nil {
t.Fatal(err)
} else if !unmarshaledResult.Timestamp.Time().Equal(result) {
t.Errorf("found %v, but expected %v", unmarshaledResult.Timestamp.Time(), result)
}
data6 := `{"ts":"1685564775371320000"}`
result = time.Unix(int64(1685564775371320000)/1e9, int64(1685564775371320000)%1e9)
err = json.Unmarshal([]byte(data6), &unmarshaledResult)
if err != nil {
t.Fatal(err)
} else if !unmarshaledResult.Timestamp.Time().Equal(result) {
t.Errorf("found %v, but expected %v", unmarshaledResult.Timestamp.Time(), result)
}
data7 := `{"ts":"abcdefg"}`
err = json.Unmarshal([]byte(data7), &unmarshaledResult)
if err == nil {
t.Fatal("expecting error but found nil")
}
data8 := `{"ts":0}`
result = time.Time{}
err = json.Unmarshal([]byte(data8), &unmarshaledResult)
if err != nil {
t.Fatal(err)
} else if !unmarshaledResult.Timestamp.Time().Equal(result) {
t.Errorf("found %v, but expected %v", unmarshaledResult.Timestamp.Time(), result)
}
}

// 2239239 516.1 ns/op 424 B/op 9 allocs/op
func BenchmarkExchangeTimeUnmarshaling(b *testing.B) {
unmarshaledResult := &struct {
Timestamp ExchangeTime `json:"ts"`
}{}
data5 := `{"ts":1685564775}`
result := time.Unix(1685564775, 0)
var err error
for i := 0; i < b.N; i++ {
if err = json.Unmarshal([]byte(data5), &unmarshaledResult); err != nil {
b.Fatal(err)
} else if !unmarshaledResult.Timestamp.Time().Equal(result) {
b.Fatalf("found %v, but expected %v", unmarshaledResult.Timestamp.Time(), result)
}
}
}
Loading

0 comments on commit 6105071

Please sign in to comment.