codebase: Cleanup various things (#1935)

* codebase: Rid base64/hex to string common funcs

* codebase: Rid local scope variable usage and other improvements

* codebase: Refactor currency pair usage across multiple exchanges

- Updated HitBTC tests to use the new currency pair format.
- Modified Kraken futures types to use currency.Pair instead of string for Symbol.
- Adjusted Kraken wrapper methods to handle currency pairs correctly.
- Refined OKX tests and types to utilize currency.Pair for instrument IDs.
- Enhanced Poloniex tests to consistently use predefined currency pairs.
- Streamlined order and orderbook tests to replace string pairs with currency.NewBTCUSD().
- Improved Yobit tests to utilize a standardized currency pair format.
- Updated validator wrapper to use currency pairs directly instead of string conversions.

* codebase: Use types.Number where possible

* refactor: update PayoutFee type to types.Number for consistency

* Refactor: Remove crypto functions to use standard library and other minor changes

- Removed custom crypto functions for SHA256, SHA512, and MD5 from the common/crypto package.
- Replaced usages of removed functions with standard library implementations in various files including:
  - cmd/websocket_client/main.go
  - engine/apiserver.go
  - exchanges/kraken/kraken.go
  - exchanges/lbank/lbank.go
  - exchanges/okx/okx_business_websocket.go
  - exchanges/kucoin/kucoin_websocket.go
  - gctscript/vm/vm.go
- Updated tests to reflect changes in the crypto functions.
- Renamed several functions for clarity, particularly in the context of order book updates across multiple exchanges.

* refactor: replace assert with require for consistency in test assertions

* refactor: Improve Binance futures candlestick test, standardise orderbook update function names and improve test parallelism

* refactor: Replace require.Len with require.Equal for better output in TestGetFuturesKlineData
This commit is contained in:
Adrian Gallagher
2025-06-12 14:12:36 +10:00
committed by GitHub
parent ce134a0a1d
commit d5ba674fc4
115 changed files with 1327 additions and 3112 deletions

View File

@@ -3,6 +3,7 @@ package coinbasepro
import (
"bytes"
"context"
"encoding/base64"
"errors"
"fmt"
"net/http"
@@ -89,50 +90,14 @@ func (c *CoinbasePro) GetOrderbook(ctx context.Context, symbol string, level int
}
ob.Sequence = orderbook.Sequence
for x := range orderbook.Asks {
priceConv, ok := orderbook.Asks[x][0].(string)
if !ok {
return nil, errors.New("unable to type assert price")
}
price, err := strconv.ParseFloat(priceConv, 64)
if err != nil {
return nil, err
}
amountConv, ok := orderbook.Asks[x][1].(string)
if !ok {
return nil, errors.New("unable to type assert amount")
}
amount, err := strconv.ParseFloat(amountConv, 64)
if err != nil {
return nil, err
}
ordID, ok := orderbook.Asks[x][2].(string)
if !ok {
return nil, errors.New("unable to type assert order ID")
}
ob.Asks[x] = OrderL3{Price: price, Amount: amount, OrderID: ordID}
ob.Asks[x].Price = orderbook.Asks[x][0].Float64()
ob.Asks[x].Amount = orderbook.Asks[x][1].Float64()
ob.Asks[x].OrderID = orderbook.Asks[x][2].String()
}
for x := range orderbook.Bids {
priceConv, ok := orderbook.Bids[x][0].(string)
if !ok {
return nil, errors.New("unable to type assert price")
}
price, err := strconv.ParseFloat(priceConv, 64)
if err != nil {
return nil, err
}
amountConv, ok := orderbook.Bids[x][1].(string)
if !ok {
return nil, errors.New("unable to type assert amount")
}
amount, err := strconv.ParseFloat(amountConv, 64)
if err != nil {
return nil, err
}
ordID, ok := orderbook.Bids[x][2].(string)
if !ok {
return nil, errors.New("unable to type assert order ID")
}
ob.Bids[x] = OrderL3{Price: price, Amount: amount, OrderID: ordID}
ob.Bids[x].Price = orderbook.Bids[x][0].Float64()
ob.Bids[x].Amount = orderbook.Bids[x][1].Float64()
ob.Bids[x].OrderID = orderbook.Bids[x][2].String()
}
return ob, nil
}
@@ -142,50 +107,14 @@ func (c *CoinbasePro) GetOrderbook(ctx context.Context, symbol string, level int
Asks: make([]OrderL1L2, len(orderbook.Asks)),
}
for x := range orderbook.Asks {
priceConv, ok := orderbook.Asks[x][0].(string)
if !ok {
return nil, errors.New("unable to type assert price")
}
price, err := strconv.ParseFloat(priceConv, 64)
if err != nil {
return nil, err
}
amountConv, ok := orderbook.Asks[x][1].(string)
if !ok {
return nil, errors.New("unable to type assert amount")
}
amount, err := strconv.ParseFloat(amountConv, 64)
if err != nil {
return nil, err
}
numOrders, ok := orderbook.Asks[x][2].(float64)
if !ok {
return nil, errors.New("unable to type assert number of orders")
}
ob.Asks[x] = OrderL1L2{Price: price, Amount: amount, NumOrders: numOrders}
ob.Asks[x].Price = orderbook.Asks[x][0].Float64()
ob.Asks[x].Amount = orderbook.Asks[x][1].Float64()
ob.Asks[x].NumOrders = orderbook.Asks[x][2].Float64()
}
for x := range orderbook.Bids {
priceConv, ok := orderbook.Bids[x][0].(string)
if !ok {
return nil, errors.New("unable to type assert price")
}
price, err := strconv.ParseFloat(priceConv, 64)
if err != nil {
return nil, err
}
amountConv, ok := orderbook.Bids[x][1].(string)
if !ok {
return nil, errors.New("unable to type assert amount")
}
amount, err := strconv.ParseFloat(amountConv, 64)
if err != nil {
return nil, err
}
numOrders, ok := orderbook.Bids[x][2].(float64)
if !ok {
return nil, errors.New("unable to type assert number of orders")
}
ob.Bids[x] = OrderL1L2{Price: price, Amount: amount, NumOrders: numOrders}
ob.Bids[x].Price = orderbook.Bids[x][0].Float64()
ob.Bids[x].Amount = orderbook.Bids[x][1].Float64()
ob.Bids[x].NumOrders = orderbook.Bids[x][2].Float64()
}
return ob, nil
}
@@ -772,15 +701,13 @@ func (c *CoinbasePro) SendAuthenticatedHTTPRequest(ctx context.Context, ep excha
n := strconv.FormatInt(time.Now().Unix(), 10)
message := n + method + "/" + path + string(payload)
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(message),
[]byte(creds.Secret))
hmac, err := crypto.GetHMAC(crypto.HashSHA256, []byte(message), []byte(creds.Secret))
if err != nil {
return nil, err
}
headers := make(map[string]string)
headers["CB-ACCESS-SIGN"] = crypto.Base64Encode(hmac)
headers["CB-ACCESS-SIGN"] = base64.StdEncoding.EncodeToString(hmac)
headers["CB-ACCESS-TIMESTAMP"] = n
headers["CB-ACCESS-KEY"] = creds.Key
headers["CB-ACCESS-PASSPHRASE"] = creds.ClientID

View File

@@ -110,15 +110,10 @@ func TestGetHistoricRatesGranularityCheck(t *testing.T) {
}
}
func TestCoinbasePro_GetHistoricCandlesExtended(t *testing.T) {
start := time.Unix(1546300800, 0)
end := time.Unix(1577836799, 0)
_, err := c.GetHistoricCandlesExtended(t.Context(),
testPair, asset.Spot, kline.OneDay, start, end)
if err != nil {
t.Fatal(err)
}
func TestGetHistoricCandlesExtended(t *testing.T) {
t.Parallel()
_, err := c.GetHistoricCandlesExtended(t.Context(), testPair, asset.Spot, kline.OneDay, time.Unix(1546300800, 0), time.Unix(1577836799, 0))
assert.NoError(t, err, "GetHistoricCandlesExtended should not error")
}
func TestGetStats(t *testing.T) {

View File

@@ -348,9 +348,9 @@ type OrderbookL3 struct {
// OrderbookResponse is a generalized response for order books
type OrderbookResponse struct {
Sequence int64 `json:"sequence"`
Bids [][3]any `json:"bids"`
Asks [][3]any `json:"asks"`
Sequence int64 `json:"sequence"`
Bids [][3]types.Number `json:"bids"`
Asks [][3]types.Number `json:"asks"`
}
// FillResponse contains fill information from the exchange
@@ -444,11 +444,11 @@ type WebsocketTicker struct {
// WebsocketOrderbookSnapshot defines a snapshot response
type WebsocketOrderbookSnapshot struct {
ProductID string `json:"product_id"`
Type string `json:"type"`
Bids [][2]string `json:"bids"`
Asks [][2]string `json:"asks"`
Time time.Time `json:"time"`
ProductID string `json:"product_id"`
Type string `json:"type"`
Bids [][2]types.Number `json:"bids"`
Asks [][2]types.Number `json:"asks"`
Time time.Time `json:"time"`
}
// WebsocketL2Update defines an update on the L2 orderbooks

View File

@@ -2,6 +2,7 @@ package coinbasepro
import (
"context"
"encoding/base64"
"errors"
"fmt"
"net/http"
@@ -119,7 +120,7 @@ func (c *CoinbasePro) wsHandleData(respRaw []byte) error {
return err
}
err = c.ProcessUpdate(&update)
err = c.ProcessOrderbookUpdate(&update)
if err != nil {
return err
}
@@ -288,50 +289,29 @@ func (c *CoinbasePro) ProcessSnapshot(snapshot *WebsocketOrderbookSnapshot) erro
return err
}
base := orderbook.Base{
Pair: pair,
Bids: make(orderbook.Tranches, len(snapshot.Bids)),
Asks: make(orderbook.Tranches, len(snapshot.Asks)),
ob := &orderbook.Base{
Pair: pair,
Bids: make(orderbook.Tranches, len(snapshot.Bids)),
Asks: make(orderbook.Tranches, len(snapshot.Asks)),
Asset: asset.Spot,
Exchange: c.Name,
VerifyOrderbook: c.CanVerifyOrderbook,
LastUpdated: snapshot.Time,
}
for i := range snapshot.Bids {
var price float64
price, err = strconv.ParseFloat(snapshot.Bids[i][0], 64)
if err != nil {
return err
}
var amount float64
amount, err = strconv.ParseFloat(snapshot.Bids[i][1], 64)
if err != nil {
return err
}
base.Bids[i] = orderbook.Tranche{Price: price, Amount: amount}
ob.Bids[i].Price = snapshot.Bids[i][0].Float64()
ob.Bids[i].Amount = snapshot.Bids[i][1].Float64()
}
for i := range snapshot.Asks {
var price float64
price, err = strconv.ParseFloat(snapshot.Asks[i][0], 64)
if err != nil {
return err
}
var amount float64
amount, err = strconv.ParseFloat(snapshot.Asks[i][1], 64)
if err != nil {
return err
}
base.Asks[i] = orderbook.Tranche{Price: price, Amount: amount}
ob.Asks[i].Price = snapshot.Asks[i][0].Float64()
ob.Asks[i].Amount = snapshot.Asks[i][1].Float64()
}
base.Asset = asset.Spot
base.Pair = pair
base.Exchange = c.Name
base.VerifyOrderbook = c.CanVerifyOrderbook
base.LastUpdated = snapshot.Time
return c.Websocket.Orderbook.LoadSnapshot(&base)
return c.Websocket.Orderbook.LoadSnapshot(ob)
}
// ProcessUpdate updates the orderbook local cache
func (c *CoinbasePro) ProcessUpdate(update *WebsocketL2Update) error {
// ProcessOrderbookUpdate updates the orderbook local cache
func (c *CoinbasePro) ProcessOrderbookUpdate(update *WebsocketL2Update) error {
if len(update.Changes) == 0 {
return errors.New("no data in websocket update")
}
@@ -447,7 +427,7 @@ func (c *CoinbasePro) authWsSubscibeReq(r *WebsocketSubscribe) error {
if err != nil {
return err
}
r.Signature = crypto.Base64Encode(hmac)
r.Signature = base64.StdEncoding.EncodeToString(hmac)
r.Key = creds.Key
r.Passphrase = creds.ClientID
return nil