exchanges: Refactor time handling and other minor improvements (#1948)

* exchanges: Refactor time handling and other minor improvements

- Updated Kraken wrapper to utilise new time handling methods.
- Simplified Kucoin types by removing unnecessary structures and using direct JSON unmarshalling.
- Improved websocket handling in Kucoin to directly parse candlestick data.
- Modified Lbank types to use the new time representation.
- Adjusted Poloniex wrapper and types to utilise the new time handling.
- Updated Yobit types and wrapper to reflect changes in time representation.
- Introduced DateTime type for better handling of specific time formats.
- Added tests for DateTime unmarshalling to ensure correctness.
- Rid UTC().Unix and UTC().UnixMilli as it's not needed
- Correct Huobi timestamp usage for some endpoints.
- Rid RFC3339 time parsing since Go does that automatically.

* exchanges: Refactor JSON unmarshalling for various types and improve test coverage

* linter: Update error message in TestGetKlines

* refactor: Simplify JSON unmarshalling in MovementHistory and improve test assertions in GetKlines

* refactor: Improve JSON unmarshalling for channel name and clarify comment in wsProcessOpenOrders

* refactor: Update time handling in Huobi types to use types.Time for createdAt fields and relax GetLiquidationOrders test

* refactor: Move wsTicker, wsSpread, wsTrades, and wsCandle types to kraken_types.go for better organistion

* refactor: Add validation for underlying parameter in GetExpirationTime and update tests
This commit is contained in:
Adrian Gallagher
2025-07-01 09:11:55 +10:00
committed by GitHub
parent 48a66c9faa
commit 3cc9a2b9e0
92 changed files with 2488 additions and 3276 deletions

View File

@@ -7,13 +7,13 @@ import (
// Trades holds trade data
type Trades struct {
TradeID int64 `json:"trade_id"`
Type string `json:"type"`
Quantity float64 `json:"quantity,string"`
Price float64 `json:"price,string"`
Amount float64 `json:"amount,string"`
Date int64 `json:"date"`
Pair string `json:"pair"`
TradeID int64 `json:"trade_id"`
Type string `json:"type"`
Quantity float64 `json:"quantity,string"`
Price float64 `json:"price,string"`
Amount float64 `json:"amount,string"`
Date types.Time `json:"date"`
Pair string `json:"pair"`
}
// Orderbook holds the orderbook data
@@ -29,15 +29,15 @@ type Orderbook struct {
// Ticker holds the ticker data
type Ticker struct {
Buy float64 `json:"buy_price,string"`
Sell float64 `json:"sell_price,string"`
Last float64 `json:"last_trade,string"`
High float64 `json:"high,string"`
Low float64 `json:"low,string"`
Average float64 `json:"average,string"`
Volume float64 `json:"vol,string"`
VolumeCurrent float64 `json:"vol_curr,string"`
Updated int64 `json:"updated"`
Buy float64 `json:"buy_price,string"`
Sell float64 `json:"sell_price,string"`
Last float64 `json:"last_trade,string"`
High float64 `json:"high,string"`
Low float64 `json:"low,string"`
Average float64 `json:"average,string"`
Volume float64 `json:"vol,string"`
VolumeCurrent float64 `json:"vol_curr,string"`
Updated types.Time `json:"updated"`
}
// PairSettings holds the pair settings
@@ -59,33 +59,33 @@ type AuthResponse struct {
// UserInfo stores the user info
type UserInfo struct {
AuthResponse
UID int `json:"uid"`
ServerDate int `json:"server_date"`
Balances map[string]string `json:"balances"`
Reserved map[string]string `json:"reserved"`
UID int `json:"uid"`
ServerDate int `json:"server_date"`
Balances map[string]types.Number `json:"balances"`
Reserved map[string]types.Number `json:"reserved"`
}
// OpenOrders stores the order info
type OpenOrders struct {
OrderID int64 `json:"order_id,string"`
Created int64 `json:"created,string"`
Type string `json:"type"`
Pair string `json:"pair"`
Price float64 `json:"price,string"`
Quantity float64 `json:"quantity,string"`
Amount float64 `json:"amount,string"`
OrderID int64 `json:"order_id,string"`
Created types.Time `json:"created"`
Type string `json:"type"`
Pair string `json:"pair"`
Price float64 `json:"price,string"`
Quantity float64 `json:"quantity,string"`
Amount float64 `json:"amount,string"`
}
// UserTrades stores the users trade info
type UserTrades struct {
TradeID int64 `json:"trade_id"`
Date int64 `json:"date"`
Type string `json:"type"`
Pair string `json:"pair"`
OrderID int64 `json:"order_id"`
Quantity float64 `json:"quantity"`
Price float64 `json:"price"`
Amount float64 `json:"amount"`
TradeID int64 `json:"trade_id"`
Date types.Time `json:"date"`
Type string `json:"type"`
Pair string `json:"pair"`
OrderID int64 `json:"order_id"`
Quantity float64 `json:"quantity"`
Price float64 `json:"price"`
Amount float64 `json:"amount"`
}
// CancelledOrder stores cancelled order data
@@ -139,14 +139,14 @@ type WalletHistory struct {
Begin int64 `json:"begin,string"`
End int64 `json:"end,string"`
History []struct {
Timestamp int64 `json:"dt"`
Type string `json:"type"`
Currency string `json:"curr"`
Status string `json:"status"`
Provider string `json:"provider"`
Amount float64 `json:"amount,string"`
Account string `json:"account"`
TXID string `json:"txid"`
Timestamp types.Time `json:"dt"`
Type string `json:"type"`
Currency string `json:"curr"`
Status string `json:"status"`
Provider string `json:"provider"`
Amount float64 `json:"amount,string"`
Account string `json:"account"`
TXID string `json:"txid"`
}
}

View File

@@ -182,7 +182,7 @@ func (e *EXMO) UpdateTickers(ctx context.Context, a asset.Item) error {
Bid: tick.Buy,
Low: tick.Low,
Volume: tick.Volume,
LastUpdated: time.Unix(tick.Updated, 0),
LastUpdated: tick.Updated.Time(),
ExchangeName: e.Name,
AssetType: a,
})
@@ -272,11 +272,13 @@ func (e *EXMO) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType a
// UpdateAccountInfo retrieves balances for all enabled currencies for the
// Exmo exchange
func (e *EXMO) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (account.Holdings, error) {
var response account.Holdings
response.Exchange = e.Name
result, err := e.GetUserInfo(ctx)
if err != nil {
return response, err
return account.Holdings{}, err
}
response := account.Holdings{
Exchange: e.Name,
}
currencies := make([]account.Balance, 0, len(result.Balances))
@@ -287,15 +289,7 @@ func (e *EXMO) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (acc
if z != x {
continue
}
var avail, reserved float64
avail, err = strconv.ParseFloat(y, 64)
if err != nil {
return response, err
}
reserved, err = strconv.ParseFloat(w, 64)
if err != nil {
return response, err
}
avail, reserved := y.Float64(), w.Float64()
exchangeCurrency.Total = avail + reserved
exchangeCurrency.Hold = reserved
exchangeCurrency.Free = avail
@@ -335,7 +329,7 @@ func (e *EXMO) GetAccountFundingHistory(ctx context.Context) ([]exchange.Funding
resp = append(resp, exchange.FundingHistory{
Status: hist.History[i].Status,
TransferID: hist.History[i].TXID,
Timestamp: time.Unix(hist.History[i].Timestamp, 0),
Timestamp: hist.History[i].Timestamp.Time(),
Currency: hist.History[i].Currency,
Amount: hist.History[i].Amount,
BankFrom: hist.History[i].Provider,
@@ -358,7 +352,7 @@ func (e *EXMO) GetWithdrawalsHistory(ctx context.Context, _ currency.Code, _ ass
resp = append(resp, exchange.WithdrawalHistory{
Status: hist.History[i].Status,
TransferID: hist.History[i].TXID,
Timestamp: time.Unix(hist.History[i].Timestamp, 0),
Timestamp: hist.History[i].Timestamp.Time(),
Currency: hist.History[i].Currency,
Amount: hist.History[i].Amount,
CryptoTxID: hist.History[i].TXID,
@@ -396,7 +390,7 @@ func (e *EXMO) GetRecentTrades(ctx context.Context, p currency.Pair, assetType a
Side: side,
Price: mapData[i].Price,
Amount: mapData[i].Quantity,
Timestamp: time.Unix(mapData[i].Date, 0),
Timestamp: mapData[i].Date.Time(),
}
}
@@ -596,21 +590,18 @@ func (e *EXMO) GetActiveOrders(ctx context.Context, req *order.MultiOrderRequest
orders := make([]order.Detail, 0, len(resp))
for i := range resp {
var symbol currency.Pair
symbol, err = currency.NewPairDelimiter(resp[i].Pair, "_")
symbol, err := currency.NewPairDelimiter(resp[i].Pair, "_")
if err != nil {
return nil, err
}
orderDate := time.Unix(resp[i].Created, 0)
var side order.Side
side, err = order.StringToOrderSide(resp[i].Type)
side, err := order.StringToOrderSide(resp[i].Type)
if err != nil {
return nil, err
}
orders = append(orders, order.Detail{
OrderID: strconv.FormatInt(resp[i].OrderID, 10),
Amount: resp[i].Quantity,
Date: orderDate,
Date: resp[i].Created.Time(),
Price: resp[i].Price,
Side: side,
Exchange: e.Name,
@@ -654,9 +645,7 @@ func (e *EXMO) GetOrderHistory(ctx context.Context, req *order.MultiOrderRequest
if err != nil {
return nil, err
}
orderDate := time.Unix(allTrades[i].Date, 0)
var side order.Side
side, err = order.StringToOrderSide(allTrades[i].Type)
side, err := order.StringToOrderSide(allTrades[i].Type)
if err != nil {
return nil, err
}
@@ -666,7 +655,7 @@ func (e *EXMO) GetOrderHistory(ctx context.Context, req *order.MultiOrderRequest
ExecutedAmount: allTrades[i].Quantity,
Cost: allTrades[i].Amount,
CostAsset: pair.Quote,
Date: orderDate,
Date: allTrades[i].Date.Time(),
Price: allTrades[i].Price,
Side: side,
Exchange: e.Name,