Skip to content

Commit

Permalink
Exchanges: Convert bespoke Number types to types.Number (#1429)
Browse files Browse the repository at this point in the history
* Kucoin: Rename WsSpotTicker => WsSnapshot

* Kucoin: Replace kucoinNumber => types.Number

* Okcoin: Convert to types.Number

* Gateio: Convert to types.Number

* Okx: Convert to types.Number
  • Loading branch information
gbjk authored Dec 28, 2023
1 parent 9986e80 commit 2b3c63c
Show file tree
Hide file tree
Showing 14 changed files with 334 additions and 583 deletions.
30 changes: 0 additions & 30 deletions exchanges/gateio/gateio_convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,33 +51,3 @@ func (a *gateioTime) UnmarshalJSON(data []byte) error {

// Time represents a time instance.
func (a gateioTime) Time() time.Time { return time.Time(a) }

type gateioNumericalValue float64

// UnmarshalJSON is custom type json unmarshaller for gateioNumericalValue
func (a *gateioNumericalValue) UnmarshalJSON(data []byte) error {
var num interface{}
err := json.Unmarshal(data, &num)
if err != nil {
return err
}

switch d := num.(type) {
case float64:
*a = gateioNumericalValue(d)
case string:
if d == "" {
*a = gateioNumericalValue(0)
return nil
}
convNum, err := strconv.ParseFloat(d, 64)
if err != nil {
return err
}
*a = gateioNumericalValue(convNum)
}
return nil
}

// Float64 returns float64 value from gateioNumericalValue instance.
func (a gateioNumericalValue) Float64() float64 { return float64(a) }
39 changes: 0 additions & 39 deletions exchanges/gateio/gateio_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3307,45 +3307,6 @@ func TestParseGateioTimeUnmarshal(t *testing.T) {
}
}

func TestGateioNumericalValue(t *testing.T) {
t.Parallel()
in := &struct {
Number gateioNumericalValue `json:"number"`
}{}

numberJSON := `{"number":123442.231}`
err := json.Unmarshal([]byte(numberJSON), in)
if err != nil {
t.Fatal(err)
} else if in.Number != 123442.231 {
t.Fatalf("found %f, but expected %f", in.Number, 123442.231)
}

numberJSON = `{"number":"123442.231"}`
err = json.Unmarshal([]byte(numberJSON), in)
if err != nil {
t.Fatal(err)
} else if in.Number != 123442.231 {
t.Fatalf("found %f, but expected %s", in.Number, "123442.231")
}

numberJSON = `{"number":""}`
err = json.Unmarshal([]byte(numberJSON), in)
if err != nil {
t.Fatal(err)
} else if in.Number != 0 {
t.Fatalf("found %f, but expected %d", in.Number, 0)
}

numberJSON = `{"number":0}`
err = json.Unmarshal([]byte(numberJSON), in)
if err != nil {
t.Fatal(err)
} else if in.Number != 0 {
t.Fatalf("found %f, but expected %d", in.Number, 0)
}
}

func TestUpdateOrderExecutionLimits(t *testing.T) {
t.Parallel()

Expand Down
258 changes: 129 additions & 129 deletions exchanges/gateio/gateio_types.go

Large diffs are not rendered by default.

41 changes: 0 additions & 41 deletions exchanges/kucoin/kucoin_convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package kucoin
import (
"encoding/json"
"fmt"
"strconv"
)

// UnmarshalJSON valid data to SubAccountsResponse of return nil if the data is empty list.
Expand All @@ -25,43 +24,3 @@ func (a *SubAccountsResponse) UnmarshalJSON(data []byte) error {
}
return fmt.Errorf("%w can not unmarshal to SubAccountsResponse", errMalformedData)
}

// kucoinNumber unmarshals and extract numeric value from a byte slice.
type kucoinNumber float64

// Float64 returns an float64 value from kucoinNumeric instance
func (a *kucoinNumber) Float64() float64 {
return float64(*a)
}

// UnmarshalJSON decerializes integer and string data having an integer value to int64
func (a *kucoinNumber) UnmarshalJSON(data []byte) error {
var value interface{}
err := json.Unmarshal(data, &value)
if err != nil {
return err
}
switch val := value.(type) {
case float64:
*a = kucoinNumber(val)
case float32:
*a = kucoinNumber(val)
case string:
if val == "" {
*a = kucoinNumber(0) // setting empty string value to zero to reset previous value if exist.
return nil
}
value, err := strconv.ParseFloat(val, 64)
if err != nil {
return err
}
*a = kucoinNumber(value)
case int64:
*a = kucoinNumber(val)
case int32:
*a = kucoinNumber(val)
default:
return fmt.Errorf("unsupported input numeric type %T", value)
}
return nil
}
56 changes: 0 additions & 56 deletions exchanges/kucoin/kucoin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2315,62 +2315,6 @@ func TestFetchAccountInfo(t *testing.T) {
}
}

func TestKucoinNumberUnmarshal(t *testing.T) {
t.Parallel()
data := &struct {
Number kucoinNumber `json:"number"`
}{}
data1 := `{"number": 123.33}`
err := json.Unmarshal([]byte(data1), &data)
if err != nil {
t.Fatal(err)
} else if data.Number.Float64() != 123.33 {
t.Errorf("expecting %.2f, got %.2f", 123.33, data.Number)
}
data2 := `{"number": "123.33"}`
err = json.Unmarshal([]byte(data2), &data)
if err != nil {
t.Fatal(err)
} else if data.Number.Float64() != 123.33 {
t.Errorf("expecting %.2f, got %.2f", 123.33, data.Number)
}
data3 := `{"number": ""}`
err = json.Unmarshal([]byte(data3), &data)
if err != nil {
t.Fatal(err)
} else if data.Number.Float64() != 0 {
t.Errorf("expecting %d, got %.2f", 0, data.Number)
}
data4 := `{"number": "123"}`
err = json.Unmarshal([]byte(data4), &data)
if err != nil {
t.Fatal(err)
} else if data.Number.Float64() != 123 {
t.Errorf("expecting %d, got %.2f", 123, data.Number)
}
data5 := `{"number": 0}`
err = json.Unmarshal([]byte(data5), &data)
if err != nil {
t.Fatal(err)
} else if data.Number.Float64() != 0 {
t.Errorf("expecting %d, got %.2f", 0, data.Number)
}
data6 := `{"number": 123789}`
err = json.Unmarshal([]byte(data6), &data)
if err != nil {
t.Fatal(err)
} else if data.Number.Float64() != 123789 {
t.Errorf("expecting %d, got %.2f", 123789, data.Number)
}
data7 := `{"number": 12321312312312312}`
err = json.Unmarshal([]byte(data7), &data)
if err != nil {
t.Fatal(err)
} else if data.Number.Float64() != float64(12321312312312312) {
t.Errorf("expecting %.f, got %.2f", float64(12321312312312312), data.Number)
}
}

func TestUpdateAccountInfo(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, ku)
Expand Down
21 changes: 11 additions & 10 deletions exchanges/kucoin/kucoin_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/common/convert"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/types"
)

var (
Expand Down Expand Up @@ -810,15 +811,15 @@ type WsTicker struct {
Timestamp convert.ExchangeTime `json:"time"`
}

// WsSpotTicker represents a spot ticker push data.
type WsSpotTicker struct {
Sequence kucoinNumber `json:"sequence"`
Data WsSpotTickerDetail `json:"data"`
// WsSnapshot represents a spot ticker push data.
type WsSnapshot struct {
Sequence types.Number `json:"sequence"`
Data WsSnapshotDetail `json:"data"`
}

// WsSpotTickerDetail represents the detail of a spot ticker data.
// WsSnapshotDetail represents the detail of a spot ticker data.
// This represents all websocket ticker information pushed as a result of subscription to /market/snapshot:{symbol}, and /market/snapshot:{currency,market}
type WsSpotTickerDetail struct {
type WsSnapshotDetail struct {
AveragePrice float64 `json:"averagePrice"`
BaseCurrency string `json:"baseCurrency"`
Board int64 `json:"board"`
Expand Down Expand Up @@ -1070,8 +1071,8 @@ type WsFuturesTicker struct {
FilledSize float64 `json:"size"`
TradeID string `json:"tradeId"`
BestBidSize float64 `json:"bestBidSize"`
BestBidPrice kucoinNumber `json:"bestBidPrice"`
BestAskPrice kucoinNumber `json:"bestAskPrice"`
BestBidPrice types.Number `json:"bestBidPrice"`
BestAskPrice types.Number `json:"bestAskPrice"`
BestAskSize float64 `json:"bestAskSize"`
FilledTime convert.ExchangeTime `json:"ts"`
}
Expand Down Expand Up @@ -1112,8 +1113,8 @@ type WsOrderbookLevel5 struct {
type WsOrderbookLevel5Response struct {
Timestamp convert.ExchangeTime `json:"timestamp"`
Sequence int64 `json:"sequence"`
Bids [][2]kucoinNumber `json:"bids"`
Asks [][2]kucoinNumber `json:"asks"`
Bids [][2]types.Number `json:"bids"`
Asks [][2]types.Number `json:"asks"`
PushTimestamp convert.ExchangeTime `json:"ts"`
}

Expand Down
2 changes: 1 addition & 1 deletion exchanges/kucoin/kucoin_websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,7 @@ func (ku *Kucoin) processOrderbook(respData []byte, symbol string) error {
}

func (ku *Kucoin) processMarketSnapshot(respData []byte) error {
response := WsSpotTicker{}
response := WsSnapshot{}
err := json.Unmarshal(respData, &response)
if err != nil {
return err
Expand Down
39 changes: 0 additions & 39 deletions exchanges/okcoin/okcoin_convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,42 +48,3 @@ func (o *okcoinTime) UnmarshalJSON(data []byte) error {
func (o *okcoinTime) Time() time.Time {
return time.Time(*o)
}

type okcoinNumber float64

// UnmarshalJSON a custom JSON deserialization function for numeric values to okcoinNumber instance.
func (a *okcoinNumber) UnmarshalJSON(data []byte) error {
var value interface{}
err := json.Unmarshal(data, &value)
if err != nil {
return err
}
switch val := value.(type) {
case string:
if val == "" {
*a = okcoinNumber(0)
return nil
}
floatValue, err := strconv.ParseFloat(val, 64)
if err != nil {
return err
}
*a = okcoinNumber(floatValue)
case float64:
*a = okcoinNumber(val)
case int64:
*a = okcoinNumber(val)
case int32:
*a = okcoinNumber(int64(val))
}
return nil
}

// Float64 returns a float64 value from okcoinNumber instance.
func (a okcoinNumber) Float64() float64 { return float64(a) }

// Int64 returns a int64 value from okcoinNumber instance.
func (a okcoinNumber) Int64() int64 { return int64(a) }

// String returns string wrapped float64 value from okcoinNumber instance.
func (a okcoinNumber) String() string { return strconv.FormatFloat(float64(a), 'f', -1, 64) }
22 changes: 0 additions & 22 deletions exchanges/okcoin/okcoin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package okcoin

import (
"context"
"encoding/json"
"errors"
"log"
"os"
Expand Down Expand Up @@ -1768,27 +1767,6 @@ func (o *Okcoin) populateTradablePairs(ctx context.Context) error {
return nil
}

func TestOKCOINNumberUnmarshal(t *testing.T) {
type testNumberHolder struct {
Numb okcoinNumber `json:"numb"`
}
var val testNumberHolder
data1 := `{ "numb":"12345.65" }`
err := json.Unmarshal([]byte(data1), &val)
if err != nil {
t.Error(err)
} else if val.Numb.Float64() != 12345.65 {
t.Errorf("found %.2f, but found %.2f", val.Numb.Float64(), 12345.65)
}
data2 := `{ "numb":"" }`
err = json.Unmarshal([]byte(data2), &val)
if err != nil {
t.Error(err)
} else if val.Numb.Float64() != 0 {
t.Errorf("found %.2f, but found %d", val.Numb.Float64(), 0)
}
}

func TestGetSubAccounts(t *testing.T) {
t.Parallel()
sharedtestvalues.SkipTestIfCredentialsUnset(t, o)
Expand Down
Loading

0 comments on commit 2b3c63c

Please sign in to comment.