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 okx
import (
"bytes"
"context"
"encoding/base64"
"errors"
"fmt"
"net"
@@ -5878,7 +5879,7 @@ URL arguments must be encoded in the request path
result must be a pointer
The response will be unmarshalled first into []any{result}, which matches most APIs, and fallback to directly into result
*/
func (ok *Okx) SendHTTPRequest(ctx context.Context, ep exchange.URL, f request.EndpointLimit, httpMethod, requestPath string, data, result any, authenticated request.AuthType) (err error) {
func (ok *Okx) SendHTTPRequest(ctx context.Context, ep exchange.URL, f request.EndpointLimit, httpMethod, requestPath string, data, result any, requestType request.AuthType) (err error) {
endpoint, err := ok.API.Endpoints.GetURL(ep)
if err != nil {
return err
@@ -5888,42 +5889,38 @@ func (ok *Okx) SendHTTPRequest(ctx context.Context, ep exchange.URL, f request.E
Msg string `json:"msg"`
Data json.RawMessage `json:"data"`
}
requestType := request.AuthType(request.UnauthenticatedRequest)
newRequest := func() (*request.Item, error) {
utcTime := time.Now().UTC().Format(time.RFC3339)
payload := []byte("")
var payload []byte
if data != nil {
payload, err = json.Marshal(data)
if err != nil {
return nil, err
}
}
path := endpoint + requestPath
headers := make(map[string]string)
headers["Content-Type"] = "application/json"
if simulate, okay := ctx.Value(testNetVal).(bool); okay && simulate {
headers["x-simulated-trading"] = "1"
}
if authenticated == request.AuthenticatedRequest {
if requestType == request.AuthenticatedRequest {
creds, err := ok.GetCredentials(ctx)
if err != nil {
return nil, err
}
signPath := "/" + apiPath + requestPath
var hmac []byte
hmac, err = crypto.GetHMAC(crypto.HashSHA256, []byte(utcTime+httpMethod+signPath+string(payload)), []byte(creds.Secret))
utcTime := time.Now().UTC().Format(time.RFC3339)
hmac, err := crypto.GetHMAC(crypto.HashSHA256, []byte(utcTime+httpMethod+signPath+string(payload)), []byte(creds.Secret))
if err != nil {
return nil, err
}
headers["OK-ACCESS-KEY"] = creds.Key
headers["OK-ACCESS-SIGN"] = crypto.Base64Encode(hmac)
headers["OK-ACCESS-SIGN"] = base64.StdEncoding.EncodeToString(hmac)
headers["OK-ACCESS-TIMESTAMP"] = utcTime
headers["OK-ACCESS-PASSPHRASE"] = creds.ClientID
}
return &request.Item{
Method: strings.ToUpper(httpMethod),
Path: path,
Path: endpoint + requestPath,
Headers: headers,
Body: bytes.NewBuffer(payload),
Result: &resp,
@@ -5932,14 +5929,11 @@ func (ok *Okx) SendHTTPRequest(ctx context.Context, ep exchange.URL, f request.E
HTTPRecording: ok.HTTPRecording,
}, nil
}
if err = ok.SendPayload(ctx, f, newRequest, requestType); err != nil {
if authenticated == request.AuthenticatedRequest {
return fmt.Errorf("%w %w", request.ErrAuthRequestFailed, err)
}
if err := ok.SendPayload(ctx, f, newRequest, requestType); err != nil {
return err
}
if err == nil && resp.Code.Int64() != 0 {
if authenticated == request.AuthenticatedRequest {
if resp.Code.Int64() != 0 {
if requestType == request.AuthenticatedRequest {
err = request.ErrAuthRequestFailed
}
if resp.Msg != "" {

View File

@@ -2,6 +2,7 @@ package okx
import (
"context"
"encoding/base64"
"fmt"
"net/http"
"strconv"
@@ -87,22 +88,21 @@ func (ok *Okx) WsSpreadAuth(ctx context.Context) error {
return err
}
ok.Websocket.SetCanUseAuthenticatedEndpoints(true)
timeUnix := time.Now()
ts := time.Now().Unix()
signPath := "/users/self/verify"
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(strconv.FormatInt(timeUnix.Unix(), 10)+http.MethodGet+signPath),
[]byte(strconv.FormatInt(ts, 10)+http.MethodGet+signPath),
[]byte(creds.Secret),
)
if err != nil {
return err
}
base64Sign := crypto.Base64Encode(hmac)
args := []WebsocketLoginData{
{
APIKey: creds.Key,
Passphrase: creds.ClientID,
Timestamp: timeUnix.Unix(),
Sign: base64Sign,
Timestamp: ts,
Sign: base64.StdEncoding.EncodeToString(hmac),
},
}
return ok.SendAuthenticatedWebsocketRequest(ctx, request.Unset, "login-response", operationLogin, args, nil)
@@ -178,7 +178,8 @@ func (ok *Okx) handleBusinessSubscription(operation string, subscriptions subscr
arg := SubscriptionInfo{
Channel: subscriptions[i].Channel,
}
var instrumentID, instrumentFamily, spreadID string
var instrumentFamily, spreadID string
var instrumentID currency.Pair
switch arg.Channel {
case okxSpreadOrders,
okxSpreadTrades,
@@ -189,7 +190,7 @@ func (ok *Okx) handleBusinessSubscription(operation string, subscriptions subscr
spreadID = subscriptions[i].Pairs[0].String()
case channelPublicBlockTrades,
channelBlockTickers:
instrumentID = subscriptions[i].Pairs[0].String()
instrumentID = subscriptions[i].Pairs[0]
}
instrumentFamilyInterface, okay := subscriptions[i].Params["instFamily"]
if okay {

View File

@@ -421,14 +421,14 @@ func (ok *Okx) underlyingFromInstID(instrumentType, instID string) (string, erro
return "", errInvalidInstrumentType
}
for a := range insts {
if insts[a].InstrumentID == instID {
if insts[a].InstrumentID.String() == instID {
return insts[a].Underlying, nil
}
}
} else {
for _, insts := range ok.instrumentsInfoMap {
for a := range insts {
if insts[a].InstrumentID == instID {
if insts[a].InstrumentID.String() == instID {
return insts[a].Underlying, nil
}
}
@@ -4209,7 +4209,7 @@ func TestInstrument(t *testing.T) {
assert.Equal(t, currency.BTC.String(), i.ContractValueCurrency, "expected BTC contract value currency")
assert.True(t, i.ExpTime.Time().IsZero(), "expected empty expiry time")
assert.Equal(t, "BTC-USDC", i.InstrumentFamily, "expected BTC-USDC instrument family")
assert.Equal(t, "BTC-USDC-SWAP", i.InstrumentID, "expected BTC-USDC-SWAP instrument ID")
assert.Equal(t, "BTC-USDC-SWAP", i.InstrumentID.String(), "expected BTC-USDC-SWAP instrument ID")
swap := GetInstrumentTypeFromAssetItem(asset.PerpetualSwap)
assert.Equal(t, swap, i.InstrumentType, "expected SWAP instrument type")
@@ -6014,14 +6014,14 @@ func (ok *Okx) instrumentFamilyFromInstID(instrumentType, instID string) (string
return "", errInvalidInstrumentType
}
for a := range insts {
if insts[a].InstrumentID == instID {
if insts[a].InstrumentID.String() == instID {
return insts[a].InstrumentFamily, nil
}
}
} else {
for _, insts := range ok.instrumentsInfoMap {
for a := range insts {
if insts[a].InstrumentID == instID {
if insts[a].InstrumentID.String() == instID {
return insts[a].InstrumentFamily, nil
}
}

View File

@@ -181,19 +181,19 @@ type PremiumInfo struct {
// TickerResponse represents the detailed data from the market ticker endpoint.
type TickerResponse struct {
InstrumentType string `json:"instType"`
InstrumentID string `json:"instId"`
LastTradePrice types.Number `json:"last"`
LastTradeSize types.Number `json:"lastSz"`
BestAskPrice types.Number `json:"askPx"`
BestAskSize types.Number `json:"askSz"`
BestBidPrice types.Number `json:"bidPx"`
BestBidSize types.Number `json:"bidSz"`
Open24H types.Number `json:"open24h"`
High24H types.Number `json:"high24h"`
Low24H types.Number `json:"low24h"`
VolCcy24H types.Number `json:"volCcy24h"`
Vol24H types.Number `json:"vol24h"`
InstrumentType string `json:"instType"`
InstrumentID currency.Pair `json:"instId"`
LastTradePrice types.Number `json:"last"`
LastTradeSize types.Number `json:"lastSz"`
BestAskPrice types.Number `json:"askPx"`
BestAskSize types.Number `json:"askSz"`
BestBidPrice types.Number `json:"bidPx"`
BestBidSize types.Number `json:"bidSz"`
Open24H types.Number `json:"open24h"`
High24H types.Number `json:"high24h"`
Low24H types.Number `json:"low24h"`
VolCcy24H types.Number `json:"volCcy24h"`
Vol24H types.Number `json:"vol24h"`
OpenPriceInUTC0 string `json:"sodUtc0"`
OpenPriceInUTC8 string `json:"sodUtc8"`
@@ -363,34 +363,34 @@ type InstrumentsFetchParams struct {
// Instrument representing an instrument with open contract
type Instrument struct {
InstrumentType string `json:"instType"`
InstrumentID string `json:"instId"`
InstrumentFamily string `json:"instFamily"`
Underlying string `json:"uly"`
Category string `json:"category"`
BaseCurrency string `json:"baseCcy"`
QuoteCurrency string `json:"quoteCcy"`
SettlementCurrency string `json:"settleCcy"`
ContractValue types.Number `json:"ctVal"`
ContractMultiplier types.Number `json:"ctMult"`
ContractValueCurrency string `json:"ctValCcy"`
OptionType string `json:"optType"`
StrikePrice types.Number `json:"stk"`
ListTime types.Time `json:"listTime"`
ExpTime types.Time `json:"expTime"`
MaxLeverage types.Number `json:"lever"`
TickSize types.Number `json:"tickSz"`
LotSize types.Number `json:"lotSz"`
MinimumOrderSize types.Number `json:"minSz"`
ContractType string `json:"ctType"`
Alias string `json:"alias"`
State string `json:"state"`
MaxQuantityOfSpotLimitOrder types.Number `json:"maxLmtSz"`
MaxQuantityOfMarketLimitOrder types.Number `json:"maxMktSz"`
MaxQuantityOfSpotTwapLimitOrder types.Number `json:"maxTwapSz"`
MaxSpotIcebergSize types.Number `json:"maxIcebergSz"`
MaxTriggerSize types.Number `json:"maxTriggerSz"`
MaxStopSize types.Number `json:"maxStopSz"`
InstrumentType string `json:"instType"`
InstrumentID currency.Pair `json:"instId"`
InstrumentFamily string `json:"instFamily"`
Underlying string `json:"uly"`
Category string `json:"category"`
BaseCurrency string `json:"baseCcy"`
QuoteCurrency string `json:"quoteCcy"`
SettlementCurrency string `json:"settleCcy"`
ContractValue types.Number `json:"ctVal"`
ContractMultiplier types.Number `json:"ctMult"`
ContractValueCurrency string `json:"ctValCcy"`
OptionType string `json:"optType"`
StrikePrice types.Number `json:"stk"`
ListTime types.Time `json:"listTime"`
ExpTime types.Time `json:"expTime"`
MaxLeverage types.Number `json:"lever"`
TickSize types.Number `json:"tickSz"`
LotSize types.Number `json:"lotSz"`
MinimumOrderSize types.Number `json:"minSz"`
ContractType string `json:"ctType"`
Alias string `json:"alias"`
State string `json:"state"`
MaxQuantityOfSpotLimitOrder types.Number `json:"maxLmtSz"`
MaxQuantityOfMarketLimitOrder types.Number `json:"maxMktSz"`
MaxQuantityOfSpotTwapLimitOrder types.Number `json:"maxTwapSz"`
MaxSpotIcebergSize types.Number `json:"maxIcebergSz"`
MaxTriggerSize types.Number `json:"maxTriggerSz"`
MaxStopSize types.Number `json:"maxStopSz"`
}
// DeliveryHistoryDetail holds instrument ID and delivery price information detail
@@ -3063,16 +3063,16 @@ type SpreadTrade struct {
// SpreadInstrument retrieve all available spreads based on the request parameters
type SpreadInstrument struct {
SpreadID string `json:"sprdId"`
SpreadType string `json:"sprdType"`
State string `json:"state"`
BaseCurrency string `json:"baseCcy"`
SizeCurrency string `json:"szCcy"`
QuoteCurrency string `json:"quoteCcy"`
TickSize types.Number `json:"tickSz"`
MinSize types.Number `json:"minSz"`
LotSize types.Number `json:"lotSz"`
ListTime types.Time `json:"listTime"`
SpreadID currency.Pair `json:"sprdId"`
SpreadType string `json:"sprdType"`
State string `json:"state"`
BaseCurrency string `json:"baseCcy"`
SizeCurrency string `json:"szCcy"`
QuoteCurrency string `json:"quoteCcy"`
TickSize types.Number `json:"tickSz"`
MinSize types.Number `json:"minSz"`
LotSize types.Number `json:"lotSz"`
ListTime types.Time `json:"listTime"`
Legs []struct {
InstrumentID string `json:"instId"`
Side string `json:"side"`
@@ -3169,12 +3169,12 @@ type WebsocketLoginData struct {
// SubscriptionInfo holds the channel and instrument IDs
type SubscriptionInfo struct {
Channel string `json:"channel,omitempty"`
InstrumentID string `json:"instId,omitempty"`
InstrumentFamily string `json:"instFamily,omitempty"`
InstrumentType string `json:"instType,omitempty"`
Underlying string `json:"uly,omitempty"`
UID string `json:"uid,omitempty"` // user identifier
Channel string `json:"channel,omitempty"`
InstrumentID currency.Pair `json:"instId,omitzero"`
InstrumentFamily string `json:"instFamily,omitempty"`
InstrumentType string `json:"instType,omitempty"`
Underlying string `json:"uly,omitempty"`
UID string `json:"uid,omitempty"` // user identifier
// For Algo Orders
AlgoID string `json:"algoId,omitempty"`
@@ -4329,8 +4329,8 @@ type APYItem struct {
// WsOrderbook5 stores the orderbook data for orderbook 5 websocket
type WsOrderbook5 struct {
Argument struct {
Channel string `json:"channel"`
InstrumentID string `json:"instId"`
Channel string `json:"channel"`
InstrumentID currency.Pair `json:"instId"`
} `json:"arg"`
Data []Book5Data `json:"data"`
}

View File

@@ -3,6 +3,7 @@ package okx
import (
"bytes"
"context"
"encoding/base64"
"errors"
"fmt"
"hash/crc32"
@@ -291,23 +292,22 @@ func (ok *Okx) WsAuth(ctx context.Context) error {
})
ok.Websocket.SetCanUseAuthenticatedEndpoints(true)
timeUnix := time.Now()
ts := time.Now().Unix()
signPath := "/users/self/verify"
hmac, err := crypto.GetHMAC(crypto.HashSHA256,
[]byte(strconv.FormatInt(timeUnix.UTC().Unix(), 10)+http.MethodGet+signPath),
[]byte(strconv.FormatInt(ts, 10)+http.MethodGet+signPath),
[]byte(creds.Secret),
)
if err != nil {
return err
}
base64Sign := crypto.Base64Encode(hmac)
args := []WebsocketLoginData{
{
APIKey: creds.Key,
Passphrase: creds.ClientID,
Timestamp: timeUnix.Unix(),
Sign: base64Sign,
Timestamp: ts,
Sign: base64.StdEncoding.EncodeToString(hmac),
},
}
@@ -720,10 +720,6 @@ func (ok *Okx) wsProcessIndexCandles(respRaw []byte) error {
return kline.ErrNoTimeSeriesDataToConvert
}
pair, err := currency.NewPairFromString(response.Argument.InstrumentID)
if err != nil {
return err
}
var assets []asset.Item
if response.Argument.InstrumentType != "" {
assetType, err := assetTypeFromInstrumentType(response.Argument.InstrumentType)
@@ -732,7 +728,7 @@ func (ok *Okx) wsProcessIndexCandles(respRaw []byte) error {
}
assets = append(assets, assetType)
} else {
assets, err = ok.getAssetsFromInstrumentID(response.Argument.InstrumentID)
assets, err = ok.getAssetsFromInstrumentID(response.Argument.InstrumentID.String())
if err != nil {
return err
}
@@ -741,7 +737,7 @@ func (ok *Okx) wsProcessIndexCandles(respRaw []byte) error {
for i := range response.Data {
candlesData := response.Data[i]
myCandle := websocket.KlineData{
Pair: pair,
Pair: response.Argument.InstrumentID,
Exchange: ok.Name,
Timestamp: time.UnixMilli(candlesData[0].Int64()),
Interval: candleInterval,
@@ -865,12 +861,8 @@ func (ok *Okx) wsProcessOrderbook5(data []byte) error {
if len(resp.Data) != 1 {
return fmt.Errorf("%s - no data returned", ok.Name)
}
assets, err := ok.getAssetsFromInstrumentID(resp.Argument.InstrumentID)
if err != nil {
return err
}
pair, err := currency.NewPairFromString(resp.Argument.InstrumentID)
assets, err := ok.getAssetsFromInstrumentID(resp.Argument.InstrumentID.String())
if err != nil {
return err
}
@@ -893,7 +885,7 @@ func (ok *Okx) wsProcessOrderbook5(data []byte) error {
Asks: asks,
Bids: bids,
LastUpdated: resp.Data[0].Timestamp.Time(),
Pair: pair,
Pair: resp.Argument.InstrumentID,
Exchange: ok.Name,
VerifyOrderbook: ok.CanVerifyOrderbook,
})
@@ -956,27 +948,23 @@ func (ok *Okx) wsProcessOrderBooks(data []byte) error {
}
assets = append(assets, assetType)
} else {
assets, err = ok.getAssetsFromInstrumentID(response.Argument.InstrumentID)
assets, err = ok.getAssetsFromInstrumentID(response.Argument.InstrumentID.String())
if err != nil {
return err
}
}
pair, err := currency.NewPairFromString(response.Argument.InstrumentID)
if err != nil {
return err
}
if !pair.IsPopulated() {
if !response.Argument.InstrumentID.IsPopulated() {
return currency.ErrCurrencyPairsEmpty
}
pair.Delimiter = currency.DashDelimiter
response.Argument.InstrumentID.Delimiter = currency.DashDelimiter
for i := range response.Data {
if response.Action == wsOrderbookSnapshot {
err = ok.WsProcessSnapshotOrderBook(&response.Data[i], pair, assets)
err = ok.WsProcessSnapshotOrderBook(&response.Data[i], response.Argument.InstrumentID, assets)
} else {
if len(response.Data[i].Asks) == 0 && len(response.Data[i].Bids) == 0 {
return nil
}
err = ok.WsProcessUpdateOrderbook(&response.Data[i], pair, assets)
err = ok.WsProcessUpdateOrderbook(&response.Data[i], response.Argument.InstrumentID, assets)
}
if err != nil {
if errors.Is(err, errInvalidChecksum) {
@@ -984,7 +972,7 @@ func (ok *Okx) wsProcessOrderBooks(data []byte) error {
{
Channel: response.Argument.Channel,
Asset: assets[0],
Pairs: currency.Pairs{pair},
Pairs: currency.Pairs{response.Argument.InstrumentID},
},
})
if err != nil {
@@ -996,10 +984,7 @@ func (ok *Okx) wsProcessOrderBooks(data []byte) error {
}
}
if ok.Verbose {
log.Debugf(log.ExchangeSys,
"%s passed checksum for pair %v",
ok.Name, pair,
)
log.Debugf(log.ExchangeSys, "%s passed checksum for pair %s", ok.Name, response.Argument.InstrumentID)
}
return nil
}
@@ -1181,7 +1166,7 @@ func (ok *Okx) wsProcessTrades(data []byte) error {
}
assets = append(assets, assetType)
} else {
assets, err = ok.getAssetsFromInstrumentID(response.Argument.InstrumentID)
assets, err = ok.getAssetsFromInstrumentID(response.Argument.InstrumentID.String())
if err != nil {
return err
}
@@ -1324,10 +1309,6 @@ func (ok *Okx) wsProcessCandles(respRaw []byte) error {
if len(response.Data) == 0 {
return kline.ErrNoTimeSeriesDataToConvert
}
pair, err := currency.NewPairFromString(response.Argument.InstrumentID)
if err != nil {
return err
}
var assets []asset.Item
if response.Argument.InstrumentType != "" {
assetType, err := assetTypeFromInstrumentType(response.Argument.InstrumentType)
@@ -1336,7 +1317,7 @@ func (ok *Okx) wsProcessCandles(respRaw []byte) error {
}
assets = append(assets, assetType)
} else {
assets, err = ok.getAssetsFromInstrumentID(response.Argument.InstrumentID)
assets, err = ok.getAssetsFromInstrumentID(response.Argument.InstrumentID.String())
if err != nil {
return err
}
@@ -1346,7 +1327,7 @@ func (ok *Okx) wsProcessCandles(respRaw []byte) error {
for j := range assets {
ok.Websocket.DataHandler <- websocket.KlineData{
Timestamp: time.UnixMilli(response.Data[i][0].Int64()),
Pair: pair,
Pair: response.Argument.InstrumentID,
AssetType: assets[j],
Exchange: ok.Name,
Interval: candleInterval,
@@ -1377,15 +1358,11 @@ func (ok *Okx) wsProcessTickers(data []byte) error {
}
assets = append(assets, assetType)
} else {
assets, err = ok.getAssetsFromInstrumentID(response.Argument.InstrumentID)
assets, err = ok.getAssetsFromInstrumentID(response.Argument.InstrumentID.String())
if err != nil {
return err
}
}
c, err := currency.NewPairFromString(response.Data[i].InstrumentID)
if err != nil {
return err
}
var baseVolume float64
var quoteVolume float64
if cap(assets) == 2 {
@@ -1409,7 +1386,7 @@ func (ok *Okx) wsProcessTickers(data []byte) error {
AskSize: response.Data[i].BestAskSize.Float64(),
Last: response.Data[i].LastTradePrice.Float64(),
AssetType: assets[j],
Pair: c,
Pair: response.Data[i].InstrumentID,
LastUpdated: response.Data[i].TickerDataGenerationTime.Time(),
}
ok.Websocket.DataHandler <- tickData

View File

@@ -258,17 +258,12 @@ func (ok *Okx) FetchTradablePairs(ctx context.Context, a asset.Item) (currency.P
if err != nil {
return nil, err
}
var pair currency.Pair
pairs := make([]currency.Pair, 0, len(insts))
for x := range insts {
if insts[x].State != "live" {
continue
}
pair, err = currency.NewPairDelimiter(insts[x].InstrumentID, format.Delimiter)
if err != nil {
return nil, err
}
pairs = append(pairs, pair)
pairs = append(pairs, insts[x].InstrumentID.Format(format))
}
return pairs, nil
case asset.Spread:
@@ -282,10 +277,7 @@ func (ok *Okx) FetchTradablePairs(ctx context.Context, a asset.Item) (currency.P
}
pairs := make(currency.Pairs, len(spreadInstruments))
for x := range spreadInstruments {
pairs[x], err = currency.NewPairDelimiter(spreadInstruments[x].SpreadID, format.Delimiter)
if err != nil {
return nil, err
}
pairs[x] = spreadInstruments[x].SpreadID.Format(format)
}
return pairs, nil
default:
@@ -323,12 +315,8 @@ func (ok *Okx) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) err
}
limits := make([]order.MinMaxLevel, len(insts))
for x := range insts {
pair, err := currency.NewPairFromString(insts[x].InstrumentID)
if err != nil {
return err
}
limits[x] = order.MinMaxLevel{
Pair: pair,
Pair: insts[x].InstrumentID,
Asset: a,
PriceStepIncrementSize: insts[x].TickSize.Float64(),
MinimumBaseAmount: insts[x].MinimumOrderSize.Float64(),
@@ -345,12 +333,8 @@ func (ok *Okx) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) err
}
limits := make([]order.MinMaxLevel, len(insts))
for x := range insts {
pair, err := currency.NewPairFromString(insts[x].SpreadID)
if err != nil {
return err
}
limits[x] = order.MinMaxLevel{
Pair: pair,
Pair: insts[x].SpreadID,
Asset: a,
PriceStepIncrementSize: insts[x].MinSize.Float64(),
MinimumBaseAmount: insts[x].MinSize.Float64(),
@@ -491,7 +475,7 @@ func (ok *Okx) UpdateTickers(ctx context.Context, assetType asset.Item) error {
}
for y := range ticks {
pair, err := ok.GetPairFromInstrumentID(ticks[y].InstrumentID)
pair, err := ok.GetPairFromInstrumentID(ticks[y].InstrumentID.String())
if err != nil {
return err
}
@@ -2805,11 +2789,6 @@ func (ok *Okx) GetFuturesContractDetails(ctx context.Context, item asset.Item) (
}
resp := make([]futures.Contract, len(result))
for i := range result {
cp, err := currency.NewPairFromString(result[i].InstrumentID)
if err != nil {
return nil, err
}
var (
underlying currency.Pair
settleCurr currency.Code
@@ -2844,7 +2823,7 @@ func (ok *Okx) GetFuturesContractDetails(ctx context.Context, item asset.Item) (
resp[i] = futures.Contract{
Exchange: ok.Name,
Name: cp,
Name: result[i].InstrumentID,
Underlying: underlying,
Asset: item,
StartDate: result[i].ListTime.Time(),
@@ -2870,18 +2849,13 @@ func (ok *Okx) GetFuturesContractDetails(ctx context.Context, item asset.Item) (
}
resp := make([]futures.Contract, len(results))
for s := range results {
var cp currency.Pair
cp, err = currency.NewPairFromString(results[s].SpreadID)
if err != nil {
return nil, err
}
contractSettlementType, err := futures.StringToContractSettlementType(results[s].SpreadType)
if err != nil {
return nil, err
}
resp[s] = futures.Contract{
Exchange: ok.Name,
Name: cp,
Name: results[s].SpreadID,
Asset: asset.Spread,
StartDate: results[s].ListTime.Time(),
EndDate: results[s].ExpTime.Time(),