diff --git a/exchanges/okx/okx.go b/exchanges/okx/okx.go index e0232bf8..bb5fc88c 100644 --- a/exchanges/okx/okx.go +++ b/exchanges/okx/okx.go @@ -181,7 +181,7 @@ const ( // Block Trading rfqCounterparties = "rfq/counterparties" - rfqCreateRFQ = "rfq/create-rfq" + rfqCreateRfq = "rfq/create-rfq" rfqCancelRfq = "rfq/cancel-rfq" rfqCancelRfqs = "rfq/cancel-batch-rfqs" rfqCancelAllRfqs = "rfq/cancel-all-rfqs" @@ -242,105 +242,105 @@ const ( ) var ( - errNo24HrTradeVolumeFound = errors.New("no trade record found in the 24 trade volume ") - errOracleInformationNotFound = errors.New("oracle information not found") - errExchangeInfoNotFound = errors.New("exchange information not found") - errIndexComponentNotFound = errors.New("unable to fetch index components") - errMissingRequiredArgInstType = errors.New("invalid required argument instrument type") - errLimitValueExceedsMaxOf100 = errors.New("limit value exceeds the maximum value 100") - errMissingInstrumentID = errors.New("missing instrument id") - errFundingRateHistoryNotFound = errors.New("funding rate history not found") - errMissingRequiredUnderlying = errors.New("error missing required parameter underlying") - errMissingRequiredParamInstID = errors.New("missing required parameter instrument id") - errLiquidationOrderResponseNotFound = errors.New("liquidation order not found") - errEitherInstIDOrCcyIsRequired = errors.New("either parameter instId or ccy is required") - errIncorrectRequiredParameterTradeMode = errors.New("unacceptable required argument, trade mode") - errInterestRateAndLoanQuotaNotFound = errors.New("interest rate and loan quota not found") - errUnderlyingsForSpecifiedInstTypeNofFound = errors.New("underlyings for the specified instrument id is not found") - errInsuranceFundInformationNotFound = errors.New("insurance fund information not found") - errMissingExpiryTimeParameter = errors.New("missing expiry date parameter") - errInvalidTradeModeValue = errors.New("invalid trade mode value") - errInvalidOrderType = errors.New("invalid order type") - errInvalidAmount = errors.New("unacceptable quantity to buy or sell") - errMissingClientOrderIDOrOrderID = errors.New("client supplier order id or order id is missing") - errInvalidNewSizeOrPriceInformation = errors.New("invalid the new size or price information") - errMissingNewSize = errors.New("missing the order size information") - errMissingMarginMode = errors.New("missing required param margin mode \"mgnMode\"") - errInvalidTriggerPrice = errors.New("invalid trigger price value") - errInvalidPriceLimit = errors.New("invalid price limit value") - errMissingIntervalValue = errors.New("missing interval value") - errMissingTakeProfitTriggerPrice = errors.New("missing take profit trigger price") - errMissingTakeProfitOrderPrice = errors.New("missing take profit order price") - errMissingSizeLimit = errors.New("missing required parameter \"szLimit\"") - errMissingEitherAlgoIDOrState = errors.New("either algo id or order state is required") - errUnacceptableAmount = errors.New("amount must be greater than 0") - errInvalidCurrencyValue = errors.New("invalid currency value") - errInvalidDepositAmount = errors.New("invalid deposit amount") - errMissingResponseBody = errors.New("error missing response body") - errMissingValidWithdrawalID = errors.New("missing valid withdrawal id") - errNoValidResponseFromServer = errors.New("no valid response from server") - errInstrumentTypeRequired = errors.New("instrument type required") - errInvalidInstrumentType = errors.New("invalid instrument type") - errMissingValidGreeksType = errors.New("missing valid greeks type") - errMissingIsolatedMarginTradingSetting = errors.New("missing isolated margin trading setting, isolated margin trading settings automatic:Auto transfers autonomy:Manual transfers") - errInvalidOrderSide = errors.New("invalid order side") - errOrderSideRequired = errors.New("order side required") - errInvalidCounterParties = errors.New("missing counter parties") - errInvalidLegs = errors.New("no legs are provided") - errMissingRFQIDANDClientSuppliedRFQID = errors.New("missing rfq id or client supplied rfq id") - errMissingRfqIDOrQuoteID = errors.New("either RFQ ID or Quote ID is missing") - errMissingRfqID = errors.New("error missing rfq id") - errMissingLegs = errors.New("missing legs") - errMissingSizeOfQuote = errors.New("missing size of quote leg") - errMossingLegsQuotePrice = errors.New("error missing quote price") - errMissingQuoteIDOrClientSuppliedQuoteID = errors.New("missing quote id or client supplied quote id") - errMissingEitherQuoteIDAOrClientSuppliedQuoteIDs = errors.New("missing either quote ids or client supplied quote ids") - errMissingRequiredParameterSubaccountName = errors.New("missing required parameter subaccount name") - errInvalidTransferAmount = errors.New("unacceptable transfer amount") - errInvalidSubaccount = errors.New("invalid account type") - errMissingDestinationSubaccountName = errors.New("missing destination subaccount name") - errMissingInitialSubaccountName = errors.New("missing initial subaccount name") - errMissingAlgoOrderType = errors.New("missing algo order type \"grid\": Spot grid, \"contract_grid\": Contract grid") - errInvalidMaximumPrice = errors.New("invalid maximum price") - errInvalidMinimumPrice = errors.New("invalid minimum price") - errInvalidGridQuantity = errors.New("invalid grid quantity (grid number)") - errMissingSize = errors.New("missing required argument, size") - errMissingRequiredArgumentDirection = errors.New("missing required argument, direction") - errRequiredParameterMissingLeverage = errors.New("missing required parameter, leverage") - errMissingAlgoOrderID = errors.New("missing algo orders id") - errMissingValidStopType = errors.New("invalid grid order stop type, only values are \"1\" and \"2\" ") - errMissingSubOrderType = errors.New("missing sub order type") - errMissingQuantity = errors.New("invalid quantity to buy or sell") - errDepositAddressNotFound = errors.New("deposit address with the specified currency code and chain not found") - errMissingAtLeast1CurrencyPair = errors.New("at least one currency is required to fetch order history") - errNoCandlestickDataFound = errors.New("no candlesticks data found") - errInvalidWebsocketEvent = errors.New("invalid websocket event") - errMissingValidChannelInformation = errors.New("missing channel information") - errNilArgument = errors.New("nil argument is not acceptable") - errNoOrderParameterPassed = errors.New("no order parameter was passed") - errMaxRFQOrdersToCancel = errors.New("no more than 100 RFQ cancel order parameter is allowed") - errMalformedData = errors.New("malformed data") - errInvalidUnderlying = errors.New("invalid underlying") - errMissingRequiredParameter = errors.New("missing required parameter") - errMissingMakerInstrumentSettings = errors.New("missing maker instrument settings") - errInvalidSubAccountName = errors.New("invalid sub-account name") - errInvalidAPIKey = errors.New("invalid api key") - errInvalidAlgoID = errors.New("invalid algo id") - errInvalidMarginTypeAdjust = errors.New("invalid margin type adjust, only 'add' and 'reduce' are allowed") - errInvalidAlgoOrderType = errors.New("invalid algo order type") - errEmptyArgument = errors.New("empty argument") - errInvalidIPAddress = errors.New("invalid ip address") - errInvalidAPIKeyPermission = errors.New("invalid API Key permission") - errInvalidResponseParam = errors.New("invalid response parameter, response must be non-nil pointer") - errEmptyPlaceOrderResponse = errors.New("empty place order response") - errTooManyArgument = errors.New("too many cancel request params") - errIncompleteCurrencyPair = errors.New("incomplete currency pair") - errInvalidDuration = errors.New("invalid grid contract duration, only '7D', '30D', and '180D' are allowed") - errInvalidProtocolType = errors.New("invalid protocol type, only 'staking' and 'defi' allowed") - errExceedLimit = errors.New("limit exceeded") - errOnlyThreeMonthsSupported = errors.New("only three months of trade data retrieval supported") - errOnlyOneResponseExpected = errors.New("one response item expected") - errNoInstrumentFound = errors.New("no instrument found") + errNo24HrTradeVolumeFound = errors.New("no trade record found in the 24 trade volume ") + errOracleInformationNotFound = errors.New("oracle information not found") + errExchangeInfoNotFound = errors.New("exchange information not found") + errIndexComponentNotFound = errors.New("unable to fetch index components") + errMissingRequiredArgInstType = errors.New("invalid required argument instrument type") + errLimitValueExceedsMaxOf100 = errors.New("limit value exceeds the maximum value 100") + errMissingInstrumentID = errors.New("missing instrument id") + errFundingRateHistoryNotFound = errors.New("funding rate history not found") + errMissingRequiredUnderlying = errors.New("error missing required parameter underlying") + errMissingRequiredParamInstID = errors.New("missing required parameter instrument id") + errLiquidationOrderResponseNotFound = errors.New("liquidation order not found") + errEitherInstIDOrCcyIsRequired = errors.New("either parameter instId or ccy is required") + errIncorrectRequiredParameterTradeMode = errors.New("unacceptable required argument, trade mode") + errInterestRateAndLoanQuotaNotFound = errors.New("interest rate and loan quota not found") + errUnderlyingsForSpecifiedInstTypeNofFound = errors.New("underlyings for the specified instrument id is not found") + errInsuranceFundInformationNotFound = errors.New("insurance fund information not found") + errMissingExpiryTimeParameter = errors.New("missing expiry date parameter") + errInvalidTradeModeValue = errors.New("invalid trade mode value") + errInvalidOrderType = errors.New("invalid order type") + errInvalidAmount = errors.New("unacceptable quantity to buy or sell") + errMissingClientOrderIDOrOrderID = errors.New("client order id or order id is missing") + errInvalidNewSizeOrPriceInformation = errors.New("invalid the new size or price information") + errMissingNewSize = errors.New("missing the order size information") + errMissingMarginMode = errors.New("missing required param margin mode \"mgnMode\"") + errInvalidTriggerPrice = errors.New("invalid trigger price value") + errInvalidPriceLimit = errors.New("invalid price limit value") + errMissingIntervalValue = errors.New("missing interval value") + errMissingTakeProfitTriggerPrice = errors.New("missing take profit trigger price") + errMissingTakeProfitOrderPrice = errors.New("missing take profit order price") + errMissingSizeLimit = errors.New("missing required parameter \"szLimit\"") + errMissingEitherAlgoIDOrState = errors.New("either algo id or order state is required") + errUnacceptableAmount = errors.New("amount must be greater than 0") + errInvalidCurrencyValue = errors.New("invalid currency value") + errInvalidDepositAmount = errors.New("invalid deposit amount") + errMissingResponseBody = errors.New("error missing response body") + errMissingValidWithdrawalID = errors.New("missing valid withdrawal id") + errNoValidResponseFromServer = errors.New("no valid response from server") + errInstrumentTypeRequired = errors.New("instrument type required") + errInvalidInstrumentType = errors.New("invalid instrument type") + errMissingValidGreeksType = errors.New("missing valid greeks type") + errMissingIsolatedMarginTradingSetting = errors.New("missing isolated margin trading setting, isolated margin trading settings automatic:Auto transfers autonomy:Manual transfers") + errInvalidOrderSide = errors.New("invalid order side") + errOrderSideRequired = errors.New("order side required") + errInvalidCounterParties = errors.New("missing counter parties") + errInvalidLegs = errors.New("no legs are provided") + errMissingRfqIDAndClientRfqID = errors.New("missing rfq id or client rfq id") + errMissingRfqIDOrQuoteID = errors.New("either Rfq ID or Quote ID is missing") + errMissingRfqID = errors.New("error missing rfq id") + errMissingLegs = errors.New("missing legs") + errMissingSizeOfQuote = errors.New("missing size of quote leg") + errMossingLegsQuotePrice = errors.New("error missing quote price") + errMissingQuoteIDOrClientQuoteID = errors.New("missing quote id or client quote id") + errMissingEitherQuoteIDAOrClientQuoteIDs = errors.New("missing either quote ids or client quote ids") + errMissingRequiredParameterSubaccountName = errors.New("missing required parameter subaccount name") + errInvalidTransferAmount = errors.New("unacceptable transfer amount") + errInvalidSubaccount = errors.New("invalid account type") + errMissingDestinationSubaccountName = errors.New("missing destination subaccount name") + errMissingInitialSubaccountName = errors.New("missing initial subaccount name") + errMissingAlgoOrderType = errors.New("missing algo order type \"grid\": Spot grid, \"contract_grid\": Contract grid") + errInvalidMaximumPrice = errors.New("invalid maximum price") + errInvalidMinimumPrice = errors.New("invalid minimum price") + errInvalidGridQuantity = errors.New("invalid grid quantity (grid number)") + errMissingSize = errors.New("missing required argument, size") + errMissingRequiredArgumentDirection = errors.New("missing required argument, direction") + errRequiredParameterMissingLeverage = errors.New("missing required parameter, leverage") + errMissingAlgoOrderID = errors.New("missing algo orders id") + errMissingValidStopType = errors.New("invalid grid order stop type, only values are \"1\" and \"2\" ") + errMissingSubOrderType = errors.New("missing sub order type") + errMissingQuantity = errors.New("invalid quantity to buy or sell") + errDepositAddressNotFound = errors.New("deposit address with the specified currency code and chain not found") + errMissingAtLeast1CurrencyPair = errors.New("at least one currency is required to fetch order history") + errNoCandlestickDataFound = errors.New("no candlesticks data found") + errInvalidWebsocketEvent = errors.New("invalid websocket event") + errMissingValidChannelInformation = errors.New("missing channel information") + errNilArgument = errors.New("nil argument is not acceptable") + errNoOrderParameterPassed = errors.New("no order parameter was passed") + errMaxRfqOrdersToCancel = errors.New("no more than 100 Rfq cancel order parameter is allowed") + errMalformedData = errors.New("malformed data") + errInvalidUnderlying = errors.New("invalid underlying") + errMissingRequiredParameter = errors.New("missing required parameter") + errMissingMakerInstrumentSettings = errors.New("missing maker instrument settings") + errInvalidSubAccountName = errors.New("invalid sub-account name") + errInvalidAPIKey = errors.New("invalid api key") + errInvalidAlgoID = errors.New("invalid algo id") + errInvalidMarginTypeAdjust = errors.New("invalid margin type adjust, only 'add' and 'reduce' are allowed") + errInvalidAlgoOrderType = errors.New("invalid algo order type") + errEmptyArgument = errors.New("empty argument") + errInvalidIPAddress = errors.New("invalid ip address") + errInvalidAPIKeyPermission = errors.New("invalid API Key permission") + errInvalidResponseParam = errors.New("invalid response parameter, response must be non-nil pointer") + errEmptyPlaceOrderResponse = errors.New("empty place order response") + errTooManyArgument = errors.New("too many cancel request params") + errIncompleteCurrencyPair = errors.New("incomplete currency pair") + errInvalidDuration = errors.New("invalid grid contract duration, only '7D', '30D', and '180D' are allowed") + errInvalidProtocolType = errors.New("invalid protocol type, only 'staking' and 'defi' allowed") + errExceedLimit = errors.New("limit exceeded") + errOnlyThreeMonthsSupported = errors.New("only three months of trade data retrieval supported") + errOnlyOneResponseExpected = errors.New("one response item expected") + errNoInstrumentFound = errors.New("no instrument found") ) /************************************ MarketData Endpoints *************************************************/ @@ -483,8 +483,8 @@ func (ok *Okx) CancelSingleOrder(ctx context.Context, arg CancelOrderRequestPara if arg.InstrumentID == "" { return nil, errMissingInstrumentID } - if arg.OrderID == "" && arg.ClientSupplierOrderID == "" { - return nil, fmt.Errorf("either order id or client supplier id is required") + if arg.OrderID == "" && arg.ClientOrderID == "" { + return nil, fmt.Errorf("either order id or client id is required") } var resp []OrderData err := ok.SendHTTPRequest(ctx, exchange.RestSpot, cancelOrderEPL, http.MethodPost, cancelTradeOrder, &arg, &resp, true) @@ -508,8 +508,8 @@ func (ok *Okx) CancelMultipleOrders(ctx context.Context, args []CancelOrderReque if arg.InstrumentID == "" { return nil, errMissingInstrumentID } - if arg.OrderID == "" && arg.ClientSupplierOrderID == "" { - return nil, fmt.Errorf("either order id or client supplier id is required") + if arg.OrderID == "" && arg.ClientOrderID == "" { + return nil, fmt.Errorf("either order id or client id is required") } } var resp []OrderData @@ -535,7 +535,7 @@ func (ok *Okx) AmendOrder(ctx context.Context, arg *AmendOrderRequestParams) (*O if arg.InstrumentID == "" { return nil, errMissingInstrumentID } - if arg.ClientSuppliedOrderID == "" && arg.OrderID == "" { + if arg.ClientOrderID == "" && arg.OrderID == "" { return nil, errMissingClientOrderIDOrOrderID } if arg.NewQuantity < 0 && arg.NewPrice < 0 { @@ -558,7 +558,7 @@ func (ok *Okx) AmendMultipleOrders(ctx context.Context, args []AmendOrderRequest if args[x].InstrumentID == "" { return nil, errMissingInstrumentID } - if args[x].ClientSuppliedOrderID == "" && args[x].OrderID == "" { + if args[x].ClientOrderID == "" && args[x].OrderID == "" { return nil, errMissingClientOrderIDOrOrderID } if args[x].NewQuantity < 0 && args[x].NewPrice < 0 { @@ -601,12 +601,12 @@ func (ok *Okx) GetOrderDetail(ctx context.Context, arg *OrderDetailRequestParam) } params.Set("instId", arg.InstrumentID) switch { - case arg.OrderID == "" && arg.ClientSupplierOrderID == "": + case arg.OrderID == "" && arg.ClientOrderID == "": return nil, errMissingClientOrderIDOrOrderID - case arg.ClientSupplierOrderID == "": + case arg.ClientOrderID == "": params.Set("ordId", arg.OrderID) default: - params.Set("clOrdId", arg.ClientSupplierOrderID) + params.Set("clOrdId", arg.ClientOrderID) } var resp []OrderDetail err := ok.SendHTTPRequest(ctx, exchange.RestSpot, getOrderDetEPL, http.MethodGet, common.EncodeURLValues(tradeOrder, params), nil, &resp, true) @@ -906,7 +906,7 @@ func (ok *Okx) cancelAlgoOrder(ctx context.Context, args []AlgoOrderCancelParams } // GetAlgoOrderList retrieves a list of untriggered Algo orders under the current account. -func (ok *Okx) GetAlgoOrderList(ctx context.Context, orderType, algoOrderID, clientSuppliedOrderID, instrumentType, instrumentID string, after, before time.Time, limit int64) ([]AlgoOrderResponse, error) { +func (ok *Okx) GetAlgoOrderList(ctx context.Context, orderType, algoOrderID, clientOrderID, instrumentType, instrumentID string, after, before time.Time, limit int64) ([]AlgoOrderResponse, error) { params := url.Values{} orderType = strings.ToLower(orderType) if orderType == "" { @@ -917,8 +917,8 @@ func (ok *Okx) GetAlgoOrderList(ctx context.Context, orderType, algoOrderID, cli if algoOrderID != "" { params.Set("algoId", algoOrderID) } - if clientSuppliedOrderID != "" { - params.Set("clOrdId", clientSuppliedOrderID) + if clientOrderID != "" { + params.Set("clOrdId", clientOrderID) } instrumentType = strings.ToUpper(instrumentType) if instrumentType != "" { @@ -1065,16 +1065,16 @@ func (ok *Okx) GetCounterparties(ctx context.Context) ([]CounterpartiesResponse, return resp, ok.SendHTTPRequest(ctx, exchange.RestSpot, getCounterpartiesEPL, http.MethodGet, rfqCounterparties, nil, &resp, true) } -// CreateRFQ Creates a new RFQ -func (ok *Okx) CreateRFQ(ctx context.Context, arg CreateRFQInput) (*RFQResponse, error) { +// CreateRfq Creates a new Rfq +func (ok *Okx) CreateRfq(ctx context.Context, arg CreateRfqInput) (*RfqResponse, error) { if len(arg.CounterParties) == 0 { return nil, errInvalidCounterParties } if len(arg.Legs) == 0 { return nil, errInvalidLegs } - var resp []RFQResponse - err := ok.SendHTTPRequest(ctx, exchange.RestSpot, createRfqEPL, http.MethodPost, rfqCreateRFQ, &arg, &resp, true) + var resp []RfqResponse + err := ok.SendHTTPRequest(ctx, exchange.RestSpot, createRfqEPL, http.MethodPost, rfqCreateRfq, &arg, &resp, true) if err != nil { return nil, err } @@ -1084,12 +1084,12 @@ func (ok *Okx) CreateRFQ(ctx context.Context, arg CreateRFQInput) (*RFQResponse, return nil, errNoValidResponseFromServer } -// CancelRFQ Cancel an existing active RFQ that you has previously created. -func (ok *Okx) CancelRFQ(ctx context.Context, arg CancelRFQRequestParam) (*CancelRFQResponse, error) { - if arg.RfqID == "" && arg.ClientSuppliedRFQID == "" { - return nil, errMissingRFQIDANDClientSuppliedRFQID +// CancelRfq Cancel an existing active Rfq that you has previously created. +func (ok *Okx) CancelRfq(ctx context.Context, arg CancelRfqRequestParam) (*CancelRfqResponse, error) { + if arg.RfqID == "" && arg.ClientRfqID == "" { + return nil, errMissingRfqIDAndClientRfqID } - var resp []CancelRFQResponse + var resp []CancelRfqResponse err := ok.SendHTTPRequest(ctx, exchange.RestSpot, cancelRfqEPL, http.MethodPost, rfqCancelRfq, &arg, &resp, true) if err != nil { return nil, err @@ -1100,19 +1100,19 @@ func (ok *Okx) CancelRFQ(ctx context.Context, arg CancelRFQRequestParam) (*Cance return nil, errNoValidResponseFromServer } -// CancelMultipleRFQs cancel multiple active RFQs in a single batch. Maximum 100 RFQ orders can be canceled at a time. -func (ok *Okx) CancelMultipleRFQs(ctx context.Context, arg CancelRFQRequestsParam) ([]CancelRFQResponse, error) { - if len(arg.RfqID) == 0 && len(arg.ClientSuppliedRFQID) == 0 { - return nil, errMissingRFQIDANDClientSuppliedRFQID - } else if len(arg.RfqID)+len(arg.ClientSuppliedRFQID) > 100 { - return nil, errMaxRFQOrdersToCancel +// CancelMultipleRfqs cancel multiple active Rfqs in a single batch. Maximum 100 Rfq orders can be canceled at a time. +func (ok *Okx) CancelMultipleRfqs(ctx context.Context, arg CancelRfqRequestsParam) ([]CancelRfqResponse, error) { + if len(arg.RfqIDs) == 0 && len(arg.ClientRfqIDs) == 0 { + return nil, errMissingRfqIDAndClientRfqID + } else if len(arg.RfqIDs)+len(arg.ClientRfqIDs) > 100 { + return nil, errMaxRfqOrdersToCancel } - var resp []CancelRFQResponse + var resp []CancelRfqResponse return resp, ok.SendHTTPRequest(ctx, exchange.RestSpot, cancelMultipleRfqEPL, http.MethodPost, rfqCancelRfqs, &arg, &resp, true) } -// CancelAllRFQs cancels all active RFQs. -func (ok *Okx) CancelAllRFQs(ctx context.Context) (time.Time, error) { +// CancelAllRfqs cancels all active Rfqs. +func (ok *Okx) CancelAllRfqs(ctx context.Context) (time.Time, error) { var resp []TimestampResponse err := ok.SendHTTPRequest(ctx, exchange.RestSpot, cancelAllRfqsEPL, http.MethodPost, rfqCancelAllRfqs, nil, &resp, true) if err != nil { @@ -1124,7 +1124,7 @@ func (ok *Okx) CancelAllRFQs(ctx context.Context) (time.Time, error) { return time.Time{}, errNoValidResponseFromServer } -// ExecuteQuote executes a Quote. It is only used by the creator of the RFQ +// ExecuteQuote executes a Quote. It is only used by the creator of the Rfq func (ok *Okx) ExecuteQuote(ctx context.Context, arg ExecuteQuoteParams) (*ExecuteQuoteResponse, error) { if arg.RfqID == "" || arg.QuoteID == "" { return nil, errMissingRfqIDOrQuoteID @@ -1140,7 +1140,7 @@ func (ok *Okx) ExecuteQuote(ctx context.Context, arg ExecuteQuoteParams) (*Execu return nil, errNoValidResponseFromServer } -// SetQuoteProducts customize the products which makers want to quote and receive RFQs for, and the corresponding price and size limit. +// SetQuoteProducts customize the products which makers want to quote and receive Rfqs for, and the corresponding price and size limit. func (ok *Okx) SetQuoteProducts(ctx context.Context, args []SetQuoteProductParam) (*SetQuoteProductsResult, error) { if len(args) == 0 { return nil, errEmptyArgument @@ -1189,8 +1189,8 @@ func (ok *Okx) ResetMMPStatus(ctx context.Context) (time.Time, error) { return time.Time{}, errNoValidResponseFromServer } -// CreateQuote allows the user to Quote an RFQ that they are a counterparty to. The user MUST quote -// the entire RFQ and not part of the legs or part of the quantity. Partial quoting or partial fills are not allowed. +// CreateQuote allows the user to Quote an Rfq that they are a counterparty to. The user MUST quote +// the entire Rfq and not part of the legs or part of the quantity. Partial quoting or partial fills are not allowed. func (ok *Okx) CreateQuote(ctx context.Context, arg CreateQuoteParams) (*QuoteResponse, error) { switch { case arg.RfqID == "": @@ -1223,12 +1223,12 @@ func (ok *Okx) CreateQuote(ctx context.Context, arg CreateQuoteParams) (*QuoteRe return nil, errNoValidResponseFromServer } -// CancelQuote cancels an existing active quote you have created in response to an RFQ. +// CancelQuote cancels an existing active quote you have created in response to an Rfq. // rfqCancelQuote = "rfq/cancel-quote" func (ok *Okx) CancelQuote(ctx context.Context, arg CancelQuoteRequestParams) (*CancelQuoteResponse, error) { var resp []CancelQuoteResponse - if arg.ClientSuppliedQuoteID == "" && arg.QuoteID == "" { - return nil, errMissingQuoteIDOrClientSuppliedQuoteID + if arg.ClientQuoteID == "" && arg.QuoteID == "" { + return nil, errMissingQuoteIDOrClientQuoteID } err := ok.SendHTTPRequest(ctx, exchange.RestSpot, cancelQuoteEPL, http.MethodPost, rfqCancelQuote, &arg, &resp, true) if err != nil { @@ -1242,8 +1242,8 @@ func (ok *Okx) CancelQuote(ctx context.Context, arg CancelQuoteRequestParams) (* // CancelMultipleQuote cancel multiple active Quotes in a single batch. Maximum 100 quote orders can be canceled at a time. func (ok *Okx) CancelMultipleQuote(ctx context.Context, arg CancelQuotesRequestParams) ([]CancelQuoteResponse, error) { - if len(arg.QuoteIDs) == 0 && len(arg.ClientSuppliedQuoteIDs) == 0 { - return nil, errMissingEitherQuoteIDAOrClientSuppliedQuoteIDs + if len(arg.QuoteIDs) == 0 && len(arg.ClientQuoteIDs) == 0 { + return nil, errMissingEitherQuoteIDAOrClientQuoteIDs } var resp []CancelQuoteResponse return resp, ok.SendHTTPRequest(ctx, exchange.RestSpot, cancelMultipleQuotesEPL, http.MethodPost, rfqCancelBatchQuotes, &arg, &resp, true) @@ -1262,8 +1262,8 @@ func (ok *Okx) CancelAllQuotes(ctx context.Context) (time.Time, error) { return time.Time{}, errMissingResponseBody } -// GetRfqs retrieves details of RFQs that the user is a counterparty to (either as the creator or the receiver of the RFQ). -func (ok *Okx) GetRfqs(ctx context.Context, arg *RfqRequestParams) ([]RFQResponse, error) { +// GetRfqs retrieves details of Rfqs that the user is a counterparty to (either as the creator or the receiver of the Rfq). +func (ok *Okx) GetRfqs(ctx context.Context, arg *RfqRequestParams) ([]RfqResponse, error) { if arg == nil { return nil, errNilArgument } @@ -1271,8 +1271,8 @@ func (ok *Okx) GetRfqs(ctx context.Context, arg *RfqRequestParams) ([]RFQRespons if arg.RfqID != "" { params.Set("rfqId", arg.RfqID) } - if arg.ClientSuppliedRfqID != "" { - params.Set("clRfqId", arg.ClientSuppliedRfqID) + if arg.ClientRfqID != "" { + params.Set("clRfqId", arg.ClientRfqID) } if arg.State != "" { params.Set("state", strings.ToLower(arg.State)) @@ -1286,7 +1286,7 @@ func (ok *Okx) GetRfqs(ctx context.Context, arg *RfqRequestParams) ([]RFQRespons if arg.Limit > 0 { params.Set("limit", strconv.FormatInt(arg.Limit, 10)) } - var resp []RFQResponse + var resp []RfqResponse return resp, ok.SendHTTPRequest(ctx, exchange.RestSpot, getRfqsEPL, http.MethodGet, common.EncodeURLValues(rfqRfqs, params), nil, &resp, true) } @@ -1299,14 +1299,14 @@ func (ok *Okx) GetQuotes(ctx context.Context, arg *QuoteRequestParams) ([]QuoteR if arg.RfqID != "" { params.Set("rfqId", arg.RfqID) } - if arg.ClientSuppliedRfqID != "" { - params.Set("clRfqId", arg.ClientSuppliedRfqID) + if arg.ClientRfqID != "" { + params.Set("clRfqId", arg.ClientRfqID) } if arg.QuoteID != "" { params.Set("quoteId", arg.QuoteID) } - if arg.ClientSuppliedQuoteID != "" { - params.Set("clQuoteId", arg.ClientSuppliedQuoteID) + if arg.ClientQuoteID != "" { + params.Set("clQuoteId", arg.ClientQuoteID) } if arg.State != "" { params.Set("state", strings.ToLower(arg.State)) @@ -1324,8 +1324,8 @@ func (ok *Okx) GetQuotes(ctx context.Context, arg *QuoteRequestParams) ([]QuoteR return resp, ok.SendHTTPRequest(ctx, exchange.RestSpot, getQuotesEPL, http.MethodGet, common.EncodeURLValues(rfqQuotes, params), nil, &resp, true) } -// GetRFQTrades retrieves the executed trades that the user is a counterparty to (either as the creator or the receiver). -func (ok *Okx) GetRFQTrades(ctx context.Context, arg *RFQTradesRequestParams) ([]RfqTradeResponse, error) { +// GetRfqTrades retrieves the executed trades that the user is a counterparty to (either as the creator or the receiver). +func (ok *Okx) GetRfqTrades(ctx context.Context, arg *RfqTradesRequestParams) ([]RfqTradeResponse, error) { if arg == nil { return nil, errNilArgument } @@ -1333,14 +1333,14 @@ func (ok *Okx) GetRFQTrades(ctx context.Context, arg *RFQTradesRequestParams) ([ if arg.RfqID != "" { params.Set("rfqId", arg.RfqID) } - if arg.ClientSuppliedRfqID != "" { - params.Set("clRfqId", arg.ClientSuppliedRfqID) + if arg.ClientRfqID != "" { + params.Set("clRfqId", arg.ClientRfqID) } if arg.QuoteID != "" { params.Set("quoteId", arg.QuoteID) } - if arg.ClientSuppliedQuoteID != "" { - params.Set("clQuoteId", arg.ClientSuppliedQuoteID) + if arg.ClientQuoteID != "" { + params.Set("clQuoteId", arg.ClientQuoteID) } if arg.State != "" { params.Set("state", strings.ToLower(arg.State)) @@ -1787,10 +1787,10 @@ func (ok *Okx) EstimateQuote(ctx context.Context, arg *EstimateQuoteRequestInput if arg.Side != order.Buy.Lower() && arg.Side != order.Sell.Lower() { return nil, errInvalidOrderSide } - if arg.RFQAmount <= 0 { + if arg.RfqAmount <= 0 { return nil, errors.New("missing rfq amount") } - if arg.RFQSzCurrency == "" { + if arg.RfqSzCurrency == "" { return nil, errors.New("missing rfq currency") } var resp []EstimateQuoteResponse @@ -1821,7 +1821,7 @@ func (ok *Okx) ConvertTrade(ctx context.Context, arg *ConvertTradeInput) (*Conve return nil, errInvalidOrderSide } if arg.Size <= 0 { - return nil, errors.New("quote amount should be more than 0 and RFQ amount") + return nil, errors.New("quote amount should be more than 0 and Rfq amount") } if arg.SizeCurrency == "" { return nil, errors.New("missing size currency") @@ -3042,10 +3042,6 @@ func (ok *Okx) GetInstrumentTypeFromAssetItem(a asset.Item) string { return okxInstTypeSwap case asset.Options: return okxInstTypeOption - case asset.Spot: - return okxInstTypeSpot - case asset.Futures: - return okxInstTypeFutures default: return strings.ToUpper(a.String()) } diff --git a/exchanges/okx/okx_test.go b/exchanges/okx/okx_test.go index 4ac1095a..2f5f2f0a 100644 --- a/exchanges/okx/okx_test.go +++ b/exchanges/okx/okx_test.go @@ -12,6 +12,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/core" @@ -779,59 +780,59 @@ func TestGetCounterparties(t *testing.T) { } } -const createRFQInputJSON = `{"anonymous": true,"counterparties":["Trader1","Trader2"],"clRfqId":"rfq01","legs":[{"sz":"25","side":"buy","instId":"BTCUSD-221208-100000-C"},{"sz":"150","side":"buy","instId":"ETH-USDT","tgtCcy":"base_ccy"}]}` +const createRfqInputJSON = `{"anonymous": true,"counterparties":["Trader1","Trader2"],"clRfqId":"rfq01","legs":[{"sz":"25","side":"buy","instId":"BTCUSD-221208-100000-C"},{"sz":"150","side":"buy","instId":"ETH-USDT","tgtCcy":"base_ccy"}]}` -func TestCreateRFQ(t *testing.T) { +func TestCreateRfq(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders) - var input CreateRFQInput - if err := json.Unmarshal([]byte(createRFQInputJSON), &input); err != nil { - t.Error("Okx Decerializing to CreateRFQInput", err) + var input CreateRfqInput + if err := json.Unmarshal([]byte(createRfqInputJSON), &input); err != nil { + t.Error("Okx Decerializing to CreateRfqInput", err) } - if _, err := ok.CreateRFQ(contextGenerate(), input); err != nil { - t.Error("Okx CreateRFQ() error", err) + if _, err := ok.CreateRfq(contextGenerate(), input); err != nil { + t.Error("Okx CreateRfq() error", err) } } -func TestCancelRFQ(t *testing.T) { +func TestCancelRfq(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders) - _, err := ok.CancelRFQ(contextGenerate(), CancelRFQRequestParam{}) - if err != nil && !errors.Is(err, errMissingRFQIDANDClientSuppliedRFQID) { - t.Errorf("Okx CancelRFQ() expecting %v, but found %v", errMissingRFQIDANDClientSuppliedRFQID, err) + _, err := ok.CancelRfq(contextGenerate(), CancelRfqRequestParam{}) + if err != nil && !errors.Is(err, errMissingRfqIDAndClientRfqID) { + t.Errorf("Okx CancelRfq() expecting %v, but found %v", errMissingRfqIDAndClientRfqID, err) } - _, err = ok.CancelRFQ(contextGenerate(), CancelRFQRequestParam{ - ClientSuppliedRFQID: "somersdjskfjsdkfjxvxv", + _, err = ok.CancelRfq(context.Background(), CancelRfqRequestParam{ + ClientRfqID: "somersdjskfjsdkfjxvxv", }) if err != nil { - t.Error("Okx CancelRFQ() error", err) + t.Error("Okx CancelRfq() error", err) } } -func TestMultipleCancelRFQ(t *testing.T) { +func TestMultipleCancelRfq(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders) - _, err := ok.CancelMultipleRFQs(contextGenerate(), CancelRFQRequestsParam{}) - if err != nil && !errors.Is(err, errMissingRFQIDANDClientSuppliedRFQID) { - t.Errorf("Okx CancelMultipleRFQs() expecting %v, but found %v", errMissingRFQIDANDClientSuppliedRFQID, err) + _, err := ok.CancelMultipleRfqs(contextGenerate(), CancelRfqRequestsParam{}) + if err != nil && !errors.Is(err, errMissingRfqIDAndClientRfqID) { + t.Errorf("Okx CancelMultipleRfqs() expecting %v, but found %v", errMissingRfqIDAndClientRfqID, err) } - _, err = ok.CancelMultipleRFQs(contextGenerate(), CancelRFQRequestsParam{ - ClientSuppliedRFQID: []string{"somersdjskfjsdkfjxvxv"}, + _, err = ok.CancelMultipleRfqs(contextGenerate(), CancelRfqRequestsParam{ + ClientRfqIDs: []string{"somersdjskfjsdkfjxvxv"}, }) if err != nil { - t.Error("Okx CancelMultipleRFQs() error", err) + t.Error("Okx CancelMultipleRfqs() error", err) } } -func TestCancelAllRFQs(t *testing.T) { +func TestCancelAllRfqs(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders) - if _, err := ok.CancelAllRFQs(contextGenerate()); err != nil { - t.Errorf("%s CancelAllRFQs() error %v", ok.Name, err) + if _, err := ok.CancelAllRfqs(contextGenerate()); err != nil { + t.Errorf("%s CancelAllRfqs() error %v", ok.Name, err) } } @@ -915,7 +916,7 @@ func TestCancelQuote(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders) - if _, err := ok.CancelQuote(contextGenerate(), CancelQuoteRequestParams{}); err != nil && !errors.Is(err, errMissingQuoteIDOrClientSuppliedQuoteID) { + if _, err := ok.CancelQuote(contextGenerate(), CancelQuoteRequestParams{}); err != nil && !errors.Is(err, errMissingQuoteIDOrClientQuoteID) { t.Error("Okx CancelQuote() error", err) } if _, err := ok.CancelQuote(contextGenerate(), CancelQuoteRequestParams{ @@ -924,7 +925,7 @@ func TestCancelQuote(t *testing.T) { t.Error("Okx CancelQuote() error", err) } if _, err := ok.CancelQuote(contextGenerate(), CancelQuoteRequestParams{ - ClientSuppliedQuoteID: "1234", + ClientQuoteID: "1234", }); err != nil { t.Error("Okx CancelQuote() error", err) } @@ -934,7 +935,7 @@ func TestCancelMultipleQuote(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders) - if _, err := ok.CancelMultipleQuote(contextGenerate(), CancelQuotesRequestParams{}); err != nil && !errors.Is(errMissingEitherQuoteIDAOrClientSuppliedQuoteIDs, err) { + if _, err := ok.CancelMultipleQuote(contextGenerate(), CancelQuotesRequestParams{}); err != nil && !errors.Is(errMissingEitherQuoteIDAOrClientQuoteIDs, err) { t.Error("Okx CancelQuote() error", err) } if _, err := ok.CancelMultipleQuote(contextGenerate(), CancelQuotesRequestParams{ @@ -958,7 +959,7 @@ func TestCancelAllQuotes(t *testing.T) { } } -func TestGetRFQs(t *testing.T) { +func TestGetRfqs(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, ok) @@ -980,14 +981,14 @@ func TestGetQuotes(t *testing.T) { } } -func TestGetRFQTrades(t *testing.T) { +func TestGetRfqTrades(t *testing.T) { t.Parallel() sharedtestvalues.SkipTestIfCredentialsUnset(t, ok) - if _, err := ok.GetRFQTrades(contextGenerate(), &RFQTradesRequestParams{ + if _, err := ok.GetRfqTrades(contextGenerate(), &RfqTradesRequestParams{ Limit: 1, }); err != nil { - t.Error("Okx GetRFQTrades() error", err) + t.Error("Okx GetRfqTrades() error", err) } } @@ -1227,8 +1228,8 @@ func TestEstimateQuote(t *testing.T) { BaseCurrency: "BTC", QuoteCurrency: "USDT", Side: "sell", - RFQAmount: 30, - RFQSzCurrency: "USDT", + RfqAmount: 30, + RfqSzCurrency: "USDT", }); err != nil { t.Error("Okx EstimateQuote() error", err) } @@ -1883,28 +1884,22 @@ func TestUpdateTradablePairs(t *testing.T) { func TestUpdateOrderExecutionLimits(t *testing.T) { t.Parallel() - type limitTest struct { - pair currency.Pair - } - - tests := map[asset.Item][]limitTest{ + tests := map[asset.Item][]currency.Pair{ asset.Spot: { - {currency.NewPair(currency.ETH, currency.USDT)}, - {currency.NewPair(currency.BTC, currency.USDT)}, + currency.NewPair(currency.ETH, currency.USDT), + currency.NewPair(currency.BTC, currency.USDT), }, asset.Margin: { - {currency.NewPair(currency.ETH, currency.USDT)}, - {currency.NewPair(currency.ETH, currency.BTC)}, + currency.NewPair(currency.ETH, currency.USDT), + currency.NewPair(currency.ETH, currency.BTC), }, } for _, a := range []asset.Item{asset.PerpetualSwap, asset.Futures, asset.Options} { pairs, err := ok.FetchTradablePairs(context.Background(), a) - if err != nil { - t.Errorf("Error fetching dated %s pairs for test: %v", a, err) + if assert.NoErrorf(t, err, "FetchTradablePairs should not error for %s", a) { + tests[a] = []currency.Pair{pairs[0]} } - - tests[a] = []limitTest{{pairs[0]}} } for _, a := range ok.GetAssetTypes(false) { @@ -1913,19 +1908,11 @@ func TestUpdateOrderExecutionLimits(t *testing.T) { continue } - for _, tt := range tests[a] { - limits, err := ok.GetOrderExecutionLimits(a, tt.pair) - if err != nil { - t.Errorf("Okx GetOrderExecutionLimits() error during TestUpdateOrderExecutionLimits; Asset: %s Pair: %s Err: %v", a, tt.pair, err) - continue - } - - if got := limits.PriceStepIncrementSize; got <= 0 { - t.Errorf("Okx UpdateOrderExecutionLimits wrong PriceStepIncrementSize; Asset: %s Pair: %s Got: %v", a, tt.pair, got) - } - - if got := limits.MinimumBaseAmount; got <= 0 { - t.Errorf("Okx UpdateOrderExecutionLimits wrong MinAmount; Pair: %s Got: %v", tt.pair, got) + for _, p := range tests[a] { + limits, err := ok.GetOrderExecutionLimits(a, p) + if assert.NoError(t, err, "GetOrderExecutionLimits should not error") { + assert.Positivef(t, limits.PriceStepIncrementSize, "PriceStepIncrementSize should be positive for %s", p) + assert.Positivef(t, limits.MinimumBaseAmount, "PriceStepIncrementSize should be positive for %s", p) } } } @@ -2552,7 +2539,7 @@ const rfqsPushDataJSON = `{"arg": {"channel": "account-greeks","ccy": "BTC"},"da func TestRfqs(t *testing.T) { t.Parallel() if err := ok.WsHandleData([]byte(rfqsPushDataJSON)); err != nil { - t.Error("Okx RFQS Push Data error", err) + t.Error("Okx Rfqs Push Data error", err) } } diff --git a/exchanges/okx/okx_types.go b/exchanges/okx/okx_types.go index 039c3d36..5e8d2902 100644 --- a/exchanges/okx/okx_types.go +++ b/exchanges/okx/okx_types.go @@ -585,19 +585,19 @@ type CurrencyTakerFlow struct { // PlaceOrderRequestParam requesting parameter for placing an order. type PlaceOrderRequestParam struct { - AssetType asset.Item `json:"-"` - InstrumentID string `json:"instId"` - TradeMode string `json:"tdMode,omitempty"` // cash isolated - ClientSupplierOrderID string `json:"clOrdId,omitempty"` - Currency string `json:"ccy,omitempty"` // Only applicable to cross MARGIN orders in Single-currency margin. - OrderTag string `json:"tag,omitempty"` - Side string `json:"side,omitempty"` - PositionSide string `json:"posSide,omitempty"` - OrderType string `json:"ordType,omitempty"` - Amount float64 `json:"sz,string,omitempty"` - Price float64 `json:"px,string,omitempty"` - ReduceOnly bool `json:"reduceOnly,string,omitempty"` - QuantityType string `json:"tgtCcy,omitempty"` // values base_ccy and quote_ccy + AssetType asset.Item `json:"-"` + InstrumentID string `json:"instId"` + TradeMode string `json:"tdMode,omitempty"` // cash isolated + ClientOrderID string `json:"clOrdId,omitempty"` + Currency string `json:"ccy,omitempty"` // Only applicable to cross MARGIN orders in Single-currency margin. + OrderTag string `json:"tag,omitempty"` + Side string `json:"side,omitempty"` + PositionSide string `json:"posSide,omitempty"` + OrderType string `json:"ordType,omitempty"` + Amount float64 `json:"sz,string,omitempty"` + Price float64 `json:"px,string,omitempty"` + ReduceOnly bool `json:"reduceOnly,string,omitempty"` + QuantityType string `json:"tgtCcy,omitempty"` // values base_ccy and quote_ccy // Added in the websocket requests BanAmend bool `json:"banAmend,omitempty"` // Whether the SPOT Market Order size can be amended by the system. ExpiryTime okxUnixMilliTime `json:"expTime,omitempty"` @@ -605,30 +605,30 @@ type PlaceOrderRequestParam struct { // OrderData response message for place, cancel, and amend an order requests. type OrderData struct { - OrderID string `json:"ordId,omitempty"` - RequestID string `json:"reqId,omitempty"` - ClientSupplierOrderID string `json:"clOrdId,omitempty"` - Tag string `json:"tag,omitempty"` - SCode string `json:"sCode,omitempty"` - SMessage string `json:"sMsg,omitempty"` + OrderID string `json:"ordId,omitempty"` + RequestID string `json:"reqId,omitempty"` + ClientOrderID string `json:"clOrdId,omitempty"` + Tag string `json:"tag,omitempty"` + SCode string `json:"sCode,omitempty"` + SMessage string `json:"sMsg,omitempty"` } // CancelOrderRequestParam represents order parameters to cancel an order. type CancelOrderRequestParam struct { - InstrumentID string `json:"instId"` - OrderID string `json:"ordId"` - ClientSupplierOrderID string `json:"clOrdId,omitempty"` + InstrumentID string `json:"instId"` + OrderID string `json:"ordId"` + ClientOrderID string `json:"clOrdId,omitempty"` } // AmendOrderRequestParams represents amend order requesting parameters. type AmendOrderRequestParams struct { - InstrumentID string `json:"instId"` - CancelOnFail bool `json:"cxlOnFail,omitempty"` - OrderID string `json:"ordId,omitempty"` - ClientSuppliedOrderID string `json:"clOrdId,omitempty"` - ClientSuppliedRequestID string `json:"reqId,omitempty"` - NewQuantity float64 `json:"newSz,string,omitempty"` - NewPrice float64 `json:"newPx,string,omitempty"` + InstrumentID string `json:"instId"` + CancelOnFail bool `json:"cxlOnFail,omitempty"` + OrderID string `json:"ordId,omitempty"` + ClientOrderID string `json:"clOrdId,omitempty"` + ClientRequestID string `json:"reqId,omitempty"` + NewQuantity float64 `json:"newSz,string,omitempty"` + NewPrice float64 `json:"newPx,string,omitempty"` } // ClosePositionsRequestParams input parameters for close position endpoints @@ -638,7 +638,7 @@ type ClosePositionsRequestParams struct { MarginMode string `json:"mgnMode"` // cross or isolated Currency string `json:"ccy"` AutomaticallyCanceled bool `json:"autoCxl"` - ClientSuppliedID string `json:"clOrdId,omitempty"` + ClientID string `json:"clOrdId,omitempty"` Tag string `json:"tag,omitempty"` } @@ -650,9 +650,9 @@ type ClosePositionResponse struct { // OrderDetailRequestParam payload data to request order detail type OrderDetailRequestParam struct { - InstrumentID string `json:"instId"` - OrderID string `json:"ordId"` - ClientSupplierOrderID string `json:"clOrdId"` + InstrumentID string `json:"instId"` + OrderID string `json:"ordId"` + ClientOrderID string `json:"clOrdId"` } // OrderDetail returns a order detail information @@ -661,7 +661,7 @@ type OrderDetail struct { InstrumentID string `json:"instId"` Currency string `json:"ccy"` OrderID string `json:"ordId"` - ClientSupplierOrderID string `json:"clOrdId"` + ClientOrderID string `json:"clOrdId"` Tag string `json:"tag"` ProfitAndLoss string `json:"pnl"` OrderType string `json:"ordType"` @@ -722,7 +722,7 @@ type PendingOrderItem struct { CreationTime time.Time `json:"cTime"` Category string `json:"category"` Currency string `json:"ccy"` - ClientSupplierOrderID string `json:"clOrdId"` + ClientOrderID string `json:"clOrdId"` TransactionFee string `json:"fee"` FeeCurrency string `json:"feeCcy"` LastFilledPrice string `json:"fillPx"` @@ -771,21 +771,21 @@ type TransactionDetailRequestParams struct { // TransactionDetail holds ecently-filled transaction detail data. type TransactionDetail struct { - InstrumentType string `json:"instType"` - InstrumentID string `json:"instId"` - TradeID string `json:"tradeId"` - OrderID string `json:"ordId"` - ClientSuppliedOrderID string `json:"clOrdId"` - BillID string `json:"billId"` - Tag string `json:"tag"` - FillPrice float64 `json:"fillPx,string"` - FillSize float64 `json:"fillSz,string"` - Side string `json:"side"` - PositionSide string `json:"posSide"` - ExecType string `json:"execType"` - FeeCurrency string `json:"feeCcy"` - Fee string `json:"fee"` - Timestamp okxUnixMilliTime `json:"ts"` + InstrumentType string `json:"instType"` + InstrumentID string `json:"instId"` + TradeID string `json:"tradeId"` + OrderID string `json:"ordId"` + ClientOrderID string `json:"clOrdId"` + BillID string `json:"billId"` + Tag string `json:"tag"` + FillPrice float64 `json:"fillPx,string"` + FillSize float64 `json:"fillSz,string"` + Side string `json:"side"` + PositionSide string `json:"posSide"` + ExecType string `json:"execType"` + FeeCurrency string `json:"feeCcy"` + Fee string `json:"fee"` + Timestamp okxUnixMilliTime `json:"ts"` } // AlgoOrderParams holds algo order information. @@ -1020,7 +1020,7 @@ type WithdrawalInput struct { Currency string `json:"ccy"` ChainName string `json:"chain"` ToAddress string `json:"toAddr"` - ClientSuppliedID string `json:"clientId"` + ClientID string `json:"clientId"` } // WithdrawalResponse cryptocurrency withdrawal response @@ -1156,55 +1156,55 @@ type EstimateQuoteRequestInput struct { BaseCurrency string `json:"baseCcy,omitempty"` QuoteCurrency string `json:"quoteCcy,omitempty"` Side string `json:"side,omitempty"` - RFQAmount float64 `json:"rfqSz,omitempty"` - RFQSzCurrency string `json:"rfqSzCcy,omitempty"` + RfqAmount float64 `json:"rfqSz,omitempty"` + RfqSzCurrency string `json:"rfqSzCcy,omitempty"` ClientRequestOrderID string `json:"clQReqId,string,omitempty"` Tag string `json:"tag,omitempty"` } // EstimateQuoteResponse represents estimate quote response data. type EstimateQuoteResponse struct { - BaseCurrency string `json:"baseCcy"` - BaseSize string `json:"baseSz"` - ClientSupplierRequestID string `json:"clQReqId"` - ConvertPrice string `json:"cnvtPx"` - OrigRfqSize string `json:"origRfqSz"` - QuoteCurrency string `json:"quoteCcy"` - QuoteID string `json:"quoteId"` - QuoteSize string `json:"quoteSz"` - QuoteTime okxUnixMilliTime `json:"quoteTime"` - RFQSize string `json:"rfqSz"` - RFQSizeCurrency string `json:"rfqSzCcy"` - Side string `json:"side"` - TTLMs string `json:"ttlMs"` // Validity period of quotation in milliseconds + BaseCurrency string `json:"baseCcy"` + BaseSize string `json:"baseSz"` + ClientRequestID string `json:"clQReqId"` + ConvertPrice string `json:"cnvtPx"` + OrigRfqSize string `json:"origRfqSz"` + QuoteCurrency string `json:"quoteCcy"` + QuoteID string `json:"quoteId"` + QuoteSize string `json:"quoteSz"` + QuoteTime okxUnixMilliTime `json:"quoteTime"` + RfqSize string `json:"rfqSz"` + RfqSizeCurrency string `json:"rfqSzCcy"` + Side string `json:"side"` + TTLMs string `json:"ttlMs"` // Validity period of quotation in milliseconds } // ConvertTradeInput represents convert trade request input type ConvertTradeInput struct { - BaseCurrency string `json:"baseCcy"` - QuoteCurrency string `json:"quoteCcy"` - Side string `json:"side"` - Size float64 `json:"sz,string"` - SizeCurrency string `json:"szCcy"` - QuoteID string `json:"quoteId"` - ClientSupplierOrderID string `json:"clTReqId"` - Tag string `json:"tag"` + BaseCurrency string `json:"baseCcy"` + QuoteCurrency string `json:"quoteCcy"` + Side string `json:"side"` + Size float64 `json:"sz,string"` + SizeCurrency string `json:"szCcy"` + QuoteID string `json:"quoteId"` + ClientOrderID string `json:"clTReqId"` + Tag string `json:"tag"` } // ConvertTradeResponse represents convert trade response type ConvertTradeResponse struct { - BaseCurrency string `json:"baseCcy"` - ClientSupplierOrderID string `json:"clTReqId"` - FillBaseSize float64 `json:"fillBaseSz,string"` - FillPrice string `json:"fillPx"` - FillQuoteSize float64 `json:"fillQuoteSz,string"` - InstrumentID string `json:"instId"` - QuoteCurrency string `json:"quoteCcy"` - QuoteID string `json:"quoteId"` - Side string `json:"side"` - State string `json:"state"` - TradeID string `json:"tradeId"` - Timestamp okxUnixMilliTime `json:"ts"` + BaseCurrency string `json:"baseCcy"` + ClientOrderID string `json:"clTReqId"` + FillBaseSize float64 `json:"fillBaseSz,string"` + FillPrice string `json:"fillPx"` + FillQuoteSize float64 `json:"fillQuoteSz,string"` + InstrumentID string `json:"instId"` + QuoteCurrency string `json:"quoteCcy"` + QuoteID string `json:"quoteId"` + Side string `json:"side"` + State string `json:"state"` + TradeID string `json:"tradeId"` + Timestamp okxUnixMilliTime `json:"ts"` } // ConvertHistory holds convert trade history response @@ -1660,40 +1660,40 @@ type CounterpartiesResponse struct { Type string `json:"type"` } -// RFQOrderLeg represents Rfq Order responses leg. -type RFQOrderLeg struct { +// RfqOrderLeg represents Rfq Order responses leg. +type RfqOrderLeg struct { Size string `json:"sz"` Side string `json:"side"` InstrumentID string `json:"instId"` TgtCurrency string `json:"tgtCcy,omitempty"` } -// CreateRFQInput RFQ create method input. -type CreateRFQInput struct { - Anonymous bool `json:"anonymous"` - CounterParties []string `json:"counterparties"` - ClientSuppliedRFQID string `json:"clRfqId"` - Legs []RFQOrderLeg `json:"legs"` +// CreateRfqInput Rfq create method input. +type CreateRfqInput struct { + Anonymous bool `json:"anonymous"` + CounterParties []string `json:"counterparties"` + ClientRfqID string `json:"clRfqId"` + Legs []RfqOrderLeg `json:"legs"` } -// CancelRFQRequestParam represents cancel RFQ order request params -type CancelRFQRequestParam struct { - RfqID string `json:"rfqId"` - ClientSuppliedRFQID string `json:"clRfqId"` +// CancelRfqRequestParam represents cancel Rfq order request params +type CancelRfqRequestParam struct { + RfqID string `json:"rfqId"` + ClientRfqID string `json:"clRfqId"` } -// CancelRFQRequestsParam represents cancel multiple RFQ orders request params -type CancelRFQRequestsParam struct { - RfqID []string `json:"rfqIds"` - ClientSuppliedRFQID []string `json:"clRfqIds"` +// CancelRfqRequestsParam represents cancel multiple Rfq orders request params +type CancelRfqRequestsParam struct { + RfqIDs []string `json:"rfqIds"` + ClientRfqIDs []string `json:"clRfqIds"` } -// CancelRFQResponse represents cancel RFQ orders response -type CancelRFQResponse struct { - RfqID string `json:"rfqId"` - ClientSuppliedRfqID string `json:"clRfqId"` - StatusCode string `json:"sCode"` - StatusMsg string `json:"sMsg"` +// CancelRfqResponse represents cancel Rfq orders response +type CancelRfqResponse struct { + RfqID string `json:"rfqId"` + ClientRfqID string `json:"clRfqId"` + StatusCode string `json:"sCode"` + StatusMsg string `json:"sMsg"` } // TimestampResponse holds timestamp response only. @@ -1709,15 +1709,15 @@ type ExecuteQuoteParams struct { // ExecuteQuoteResponse represents execute quote response. type ExecuteQuoteResponse struct { - BlockTradedID string `json:"blockTdId"` - RfqID string `json:"rfqId"` - ClientSuppliedRfqID string `json:"clRfqId"` - QuoteID string `json:"quoteId"` - ClientSuppliedQuoteID string `json:"clQuoteId"` - TraderCode string `json:"tTraderCode"` - MakerTraderCode string `json:"mTraderCode"` - CreationTime okxUnixMilliTime `json:"cTime"` - Legs []OrderLeg `json:"legs"` + BlockTradedID string `json:"blockTdId"` + RfqID string `json:"rfqId"` + ClientRfqID string `json:"clRfqId"` + QuoteID string `json:"quoteId"` + ClientQuoteID string `json:"clQuoteId"` + TraderCode string `json:"tTraderCode"` + MakerTraderCode string `json:"mTraderCode"` + CreationTime okxUnixMilliTime `json:"cTime"` + Legs []OrderLeg `json:"legs"` } // OrderLeg represents legs information for both websocket and REST available Quote information. @@ -1736,10 +1736,10 @@ type OrderLeg struct { // CreateQuoteParams holds information related to create quote. type CreateQuoteParams struct { - RfqID string `json:"rfqId"` - ClientSuppliedQuoteID string `json:"clQuoteId"` - QuoteSide order.Side `json:"quoteSide"` - Legs []QuoteLeg `json:"legs"` + RfqID string `json:"rfqId"` + ClientQuoteID string `json:"clQuoteId"` + QuoteSide order.Side `json:"quoteSide"` + Legs []QuoteLeg `json:"legs"` } // QuoteLeg the legs of the Quote. @@ -1755,60 +1755,60 @@ type QuoteLeg struct { // QuoteResponse holds create quote response variables. type QuoteResponse struct { - CreationTime okxUnixMilliTime `json:"cTime"` - UpdateTime okxUnixMilliTime `json:"uTime"` - ValidUntil okxUnixMilliTime `json:"validUntil"` - QuoteID string `json:"quoteId"` - ClientSuppliedQuoteID string `json:"clQuoteId"` - RfqID string `json:"rfqId"` - QuoteSide string `json:"quoteSide"` - ClientSuppliedRfqID string `json:"clRfqId"` - TraderCode string `json:"traderCode"` - State string `json:"state"` - Legs []QuoteLeg `json:"legs"` + CreationTime okxUnixMilliTime `json:"cTime"` + UpdateTime okxUnixMilliTime `json:"uTime"` + ValidUntil okxUnixMilliTime `json:"validUntil"` + QuoteID string `json:"quoteId"` + ClientQuoteID string `json:"clQuoteId"` + RfqID string `json:"rfqId"` + QuoteSide string `json:"quoteSide"` + ClientRfqID string `json:"clRfqId"` + TraderCode string `json:"traderCode"` + State string `json:"state"` + Legs []QuoteLeg `json:"legs"` } // CancelQuoteRequestParams represents cancel quote request params type CancelQuoteRequestParams struct { - QuoteID string `json:"quoteId"` - ClientSuppliedQuoteID string `json:"clQuoteId"` + QuoteID string `json:"quoteId"` + ClientQuoteID string `json:"clQuoteId"` } // CancelQuotesRequestParams represents cancel multiple quotes request params type CancelQuotesRequestParams struct { - QuoteIDs []string `json:"quoteIds,omitempty"` - ClientSuppliedQuoteIDs []string `json:"clQuoteIds,omitempty"` + QuoteIDs []string `json:"quoteIds,omitempty"` + ClientQuoteIDs []string `json:"clQuoteIds,omitempty"` } // CancelQuoteResponse represents cancel quote response type CancelQuoteResponse struct { - QuoteID string `json:"quoteId"` - ClientSuppliedQuoteID string `json:"clQuoteId"` - SCode string `json:"sCode"` - SMsg string `json:"sMsg"` + QuoteID string `json:"quoteId"` + ClientQuoteID string `json:"clQuoteId"` + SCode string `json:"sCode"` + SMsg string `json:"sMsg"` } -// RfqRequestParams represents get RFQ orders param +// RfqRequestParams represents get Rfq orders param type RfqRequestParams struct { - RfqID string - ClientSuppliedRfqID string - State string - BeginningID string - EndID string - Limit int64 + RfqID string + ClientRfqID string + State string + BeginningID string + EndID string + Limit int64 } -// RFQResponse RFQ response detail. -type RFQResponse struct { - CreateTime okxUnixMilliTime `json:"cTime"` - UpdateTime okxUnixMilliTime `json:"uTime"` - ValidUntil okxUnixMilliTime `json:"validUntil"` - TraderCode string `json:"traderCode"` - RFQID string `json:"rfqId"` - ClientSuppliedRFQID string `json:"clRfqId"` - State string `json:"state"` - Counterparties []string `json:"counterparties"` - Legs []struct { +// RfqResponse Rfq response detail. +type RfqResponse struct { + CreateTime okxUnixMilliTime `json:"cTime"` + UpdateTime okxUnixMilliTime `json:"uTime"` + ValidUntil okxUnixMilliTime `json:"validUntil"` + TraderCode string `json:"traderCode"` + RfqID string `json:"rfqId"` + ClientRfqID string `json:"clRfqId"` + State string `json:"state"` + Counterparties []string `json:"counterparties"` + Legs []struct { InstrumentID string `json:"instId"` Size string `json:"sz"` Side string `json:"side"` @@ -1818,44 +1818,44 @@ type RFQResponse struct { // QuoteRequestParams request params. type QuoteRequestParams struct { - RfqID string - ClientSuppliedRfqID string - QuoteID string - ClientSuppliedQuoteID string - State string - BeginID string - EndID string - Limit int64 + RfqID string + ClientRfqID string + QuoteID string + ClientQuoteID string + State string + BeginID string + EndID string + Limit int64 } -// RFQTradesRequestParams represents RFQ trades request param -type RFQTradesRequestParams struct { - RfqID string - ClientSuppliedRfqID string - QuoteID string - BlockTradeID string - ClientSuppliedQuoteID string - State string - BeginID string - EndID string - Limit int64 +// RfqTradesRequestParams represents Rfq trades request param +type RfqTradesRequestParams struct { + RfqID string + ClientRfqID string + QuoteID string + BlockTradeID string + ClientQuoteID string + State string + BeginID string + EndID string + Limit int64 } -// RfqTradeResponse RFQ trade response +// RfqTradeResponse Rfq trade response type RfqTradeResponse struct { - RfqID string `json:"rfqId"` - ClientSuppliedRfqID string `json:"clRfqId"` - QuoteID string `json:"quoteId"` - ClientSuppliedQuoteID string `json:"clQuoteId"` - BlockTradeID string `json:"blockTdId"` - Legs []RFQTradeLeg `json:"legs"` - CreationTime time.Time `json:"cTime"` - TakerTraderCode string `json:"tTraderCode"` - MakerTraderCode string `json:"mTraderCode"` + RfqID string `json:"rfqId"` + ClientRfqID string `json:"clRfqId"` + QuoteID string `json:"quoteId"` + ClientQuoteID string `json:"clQuoteId"` + BlockTradeID string `json:"blockTdId"` + Legs []RfqTradeLeg `json:"legs"` + CreationTime time.Time `json:"cTime"` + TakerTraderCode string `json:"tTraderCode"` + MakerTraderCode string `json:"mTraderCode"` } -// RFQTradeLeg RFQ trade response leg. -type RFQTradeLeg struct { +// RfqTradeLeg Rfq trade response leg. +type RfqTradeLeg struct { InstrumentID string `json:"instId"` Side string `json:"side"` Size string `json:"sz"` @@ -1870,7 +1870,7 @@ type RFQTradeLeg struct { type PublicTradesResponse struct { BlockTradeID string `json:"blockTdId"` CreationTime okxUnixMilliTime `json:"cTime"` - Legs []RFQTradeLeg `json:"legs"` + Legs []RfqTradeLeg `json:"legs"` } // SubaccountInfo represents subaccount information detail. @@ -2256,20 +2256,20 @@ type WSMarketDataResponse struct { // WSPlaceOrderData holds websocket order information. type WSPlaceOrderData struct { - ClientSuppliedOrderID string `json:"clOrdId,omitempty"` - Currency string `json:"ccy,omitempty"` - Tag string `json:"tag,omitempty"` - PositionSide string `json:"posSide,omitempty"` - ExpiryTime int64 `json:"expTime,string,omitempty"` - BanAmend bool `json:"banAmend,omitempty"` - Side string `json:"side"` - InstrumentID string `json:"instId"` - TradeMode string `json:"tdMode"` - OrderType string `json:"ordType"` - Size float64 `json:"sz"` - Price float64 `json:"px,string,omitempty"` - ReduceOnly bool `json:"reduceOnly,string,omitempty"` - TargetCurrency string `json:"tgtCurrency,omitempty"` + ClientOrderID string `json:"clOrdId,omitempty"` + Currency string `json:"ccy,omitempty"` + Tag string `json:"tag,omitempty"` + PositionSide string `json:"posSide,omitempty"` + ExpiryTime int64 `json:"expTime,string,omitempty"` + BanAmend bool `json:"banAmend,omitempty"` + Side string `json:"side"` + InstrumentID string `json:"instId"` + TradeMode string `json:"tdMode"` + OrderType string `json:"ordType"` + Size float64 `json:"sz"` + Price float64 `json:"px,string,omitempty"` + ReduceOnly bool `json:"reduceOnly,string,omitempty"` + TargetCurrency string `json:"tgtCurrency,omitempty"` } // WSPlaceOrder holds the websocket place order input data. @@ -2622,23 +2622,23 @@ type WsGreekData struct { Timestamp okxUnixMilliTime `json:"ts"` } -// WsRFQ represents websocket push data for "rfqs" subscription -type WsRFQ struct { +// WsRfq represents websocket push data for "rfqs" subscription +type WsRfq struct { Argument SubscriptionInfo `json:"arg"` Data []WsRfqData `json:"data"` } // WsRfqData represents rfq order response data streamed through the websocket channel type WsRfqData struct { - CreationTime time.Time `json:"cTime"` - UpdateTime time.Time `json:"uTime"` - TraderCode string `json:"traderCode"` - RfqID string `json:"rfqId"` - ClientSuppliedRfqID string `json:"clRfqId"` - State string `json:"state"` - ValidUntil string `json:"validUntil"` - Counterparties []string `json:"counterparties"` - Legs []RFQOrderLeg `json:"legs"` + CreationTime time.Time `json:"cTime"` + UpdateTime time.Time `json:"uTime"` + TraderCode string `json:"traderCode"` + RfqID string `json:"rfqId"` + ClientRfqID string `json:"clRfqId"` + State string `json:"state"` + ValidUntil string `json:"validUntil"` + Counterparties []string `json:"counterparties"` + Legs []RfqOrderLeg `json:"legs"` } // WsQuote represents websocket push data for "quotes" subscription @@ -2649,16 +2649,16 @@ type WsQuote struct { // WsQuoteData represents a single quote order information type WsQuoteData struct { - ValidUntil okxUnixMilliTime `json:"validUntil"` - UpdatedTime okxUnixMilliTime `json:"uTime"` - CreationTime okxUnixMilliTime `json:"cTime"` - Legs []OrderLeg `json:"legs"` - QuoteID string `json:"quoteId"` - RfqID string `json:"rfqId"` - TraderCode string `json:"traderCode"` - QuoteSide string `json:"quoteSide"` - State string `json:"state"` - ClientSuppliedQuoteID string `json:"clQuoteId"` + ValidUntil okxUnixMilliTime `json:"validUntil"` + UpdatedTime okxUnixMilliTime `json:"uTime"` + CreationTime okxUnixMilliTime `json:"cTime"` + Legs []OrderLeg `json:"legs"` + QuoteID string `json:"quoteId"` + RfqID string `json:"rfqId"` + TraderCode string `json:"traderCode"` + QuoteSide string `json:"quoteSide"` + State string `json:"state"` + ClientQuoteID string `json:"clQuoteId"` } // WsStructureBlocTrade represents websocket push data for "struc-block-trades" subscription @@ -2669,15 +2669,15 @@ type WsStructureBlocTrade struct { // WsBlockTradeResponse represents a structure block order information type WsBlockTradeResponse struct { - CreationTime okxUnixMilliTime `json:"cTime"` - RfqID string `json:"rfqId"` - ClientSuppliedRfqID string `json:"clRfqId"` - QuoteID string `json:"quoteId"` - ClientSuppliedQuoteID string `json:"clQuoteId"` - BlockTradeID string `json:"blockTdId"` - TakerTraderCode string `json:"tTraderCode"` - MakerTraderCode string `json:"mTraderCode"` - Legs []OrderLeg `json:"legs"` + CreationTime okxUnixMilliTime `json:"cTime"` + RfqID string `json:"rfqId"` + ClientRfqID string `json:"clRfqId"` + QuoteID string `json:"quoteId"` + ClientQuoteID string `json:"clQuoteId"` + BlockTradeID string `json:"blockTdId"` + TakerTraderCode string `json:"tTraderCode"` + MakerTraderCode string `json:"mTraderCode"` + Legs []OrderLeg `json:"legs"` } // WsSpotGridAlgoOrder represents websocket push data for "struc-block-trades" subscription diff --git a/exchanges/okx/okx_websocket.go b/exchanges/okx/okx_websocket.go index d8871922..d59755f9 100644 --- a/exchanges/okx/okx_websocket.go +++ b/exchanges/okx/okx_websocket.go @@ -87,17 +87,18 @@ const ( okxChannelAlgoAdvance = "algo-advance" okxChannelLiquidationWarning = "liquidation-warning" okxChannelAccountGreeks = "account-greeks" - okxChannelRFQs = "rfqs" + okxChannelRfqs = "rfqs" okxChannelQuotes = "quotes" okxChannelStructureBlockTrades = "struc-block-trades" okxChannelSpotGridOrder = "grid-orders-spot" okxChannelGridOrdersContract = "grid-orders-contract" okxChannelGridPositions = "grid-positions" okcChannelGridSubOrders = "grid-sub-orders" - okxChannelInstruments = "instruments" - okxChannelOpenInterest = "open-interest" - okxChannelTrades = "trades" + // Public channels + okxChannelInstruments = "instruments" + okxChannelOpenInterest = "open-interest" + okxChannelTrades = "trades" okxChannelEstimatedPrice = "estimated-price" okxChannelMarkPrice = "mark-price" okxChannelPriceLimit = "price-limit" @@ -233,7 +234,7 @@ func (ok *Okx) WsConnect() error { ok.Websocket.Conn.SetupPingHandler(stream.PingHandler{ MessageType: websocket.TextMessage, Message: pingMsg, - Delay: time.Second * 27, + Delay: time.Second * 20, }) if ok.IsWebsocketAuthenticationSupported() { var authDialer websocket.Dialer @@ -262,7 +263,7 @@ func (ok *Okx) WsAuth(ctx context.Context, dialer *websocket.Dialer) error { ok.Websocket.AuthConn.SetupPingHandler(stream.PingHandler{ MessageType: websocket.TextMessage, Message: pingMsg, - Delay: time.Second * 27, + Delay: time.Second * 20, }) creds, err := ok.GetCredentials(ctx) if err != nil { @@ -385,10 +386,25 @@ func (ok *Okx) handleSubscription(operation string, subscriptions []stream.Chann var algoID string var uid string - if arg.Channel == okxChannelAccount || - arg.Channel == okxChannelOrders { + switch arg.Channel { + case okxChannelAccount, + okxChannelPositions, + okxChannelBalanceAndPosition, + okxChannelOrders, + okxChannelAlgoOrders, + okxChannelAlgoAdvance, + okxChannelLiquidationWarning, + okxChannelAccountGreeks, + okxChannelRfqs, + okxChannelQuotes, + okxChannelStructureBlockTrades, + okxChannelSpotGridOrder, + okxChannelGridOrdersContract, + okxChannelGridPositions, + okcChannelGridSubOrders: authSubscription = true } + if arg.Channel == okxChannelGridPositions { algoID, _ = subscriptions[i].Params["algoId"].(string) } @@ -536,7 +552,7 @@ func (ok *Okx) WsHandleData(respRaw []byte) error { if bytes.Equal(respRaw, pongMsg) { return nil } - return err + return fmt.Errorf("%w unmarshalling %v", err, respRaw) } if (resp.Event != "" && (resp.Event == "login" || resp.Event == "error")) || resp.Operation != "" { ok.WsResponseMultiplexer.Message <- &resp @@ -598,8 +614,8 @@ func (ok *Okx) WsHandleData(respRaw []byte) error { case okxChannelAlgoAdvance: var response WsAdvancedAlgoOrder return ok.wsProcessPushData(respRaw, &response) - case okxChannelRFQs: - var response WsRFQ + case okxChannelRfqs: + var response WsRfq return ok.wsProcessPushData(respRaw, &response) case okxChannelQuotes: var response WsQuote @@ -1044,19 +1060,39 @@ func (ok *Okx) wsProcessOrders(respRaw []byte) error { if err != nil { return err } + avgPrice := response.Data[x].AveragePrice.Float64() + orderAmount := response.Data[x].Size + var quoteAmount float64 + if response.Data[x].QuantityType == "quote_ccy" { + // Size is quote amount. + quoteAmount = orderAmount + if avgPrice > 0 { + orderAmount /= avgPrice + } else { + // Size not in Base, and we can't derive a sane value for it + orderAmount = 0 + } + } + var remainingAmount float64 + if orderStatus != order.Filled { + remainingAmount = orderAmount - response.Data[x].AccumulatedFillSize.Float64() + } ok.Websocket.DataHandler <- &order.Detail{ - Price: response.Data[x].Price, - Amount: response.Data[x].Size, - ExecutedAmount: response.Data[x].LastFilledSize.Float64(), - RemainingAmount: response.Data[x].AccumulatedFillSize.Float64() - response.Data[x].LastFilledSize.Float64(), - Exchange: ok.Name, - OrderID: response.Data[x].OrderID, - Type: orderType, - Side: response.Data[x].Side, - Status: orderStatus, - AssetType: a, - Date: response.Data[x].CreationTime, - Pair: pair, + Price: response.Data[x].Price, + Amount: orderAmount, + QuoteAmount: quoteAmount, + ExecutedAmount: response.Data[x].AccumulatedFillSize.Float64(), + RemainingAmount: remainingAmount, + AverageExecutedPrice: avgPrice, + Exchange: ok.Name, + OrderID: response.Data[x].OrderID, + ClientOrderID: response.Data[x].ClientOrderID, + Type: orderType, + Side: response.Data[x].Side, + Status: orderStatus, + AssetType: a, + Date: response.Data[x].CreationTime, + Pair: pair, } } return nil @@ -1377,7 +1413,7 @@ func (ok *Okx) WsCancelOrder(arg CancelOrderRequestParam) (*OrderData, error) { if arg.InstrumentID == "" { return nil, errMissingInstrumentID } - if arg.OrderID == "" && arg.ClientSupplierOrderID == "" { + if arg.OrderID == "" && arg.ClientOrderID == "" { return nil, fmt.Errorf("either order id or client supplier id is required") } randomID, err := common.GenerateRandomString(4, common.NumberCharacters) @@ -1436,7 +1472,7 @@ func (ok *Okx) WsCancelMultipleOrder(args []CancelOrderRequestParam) ([]OrderDat if arg.InstrumentID == "" { return nil, errMissingInstrumentID } - if arg.OrderID == "" && arg.ClientSupplierOrderID == "" { + if arg.OrderID == "" && arg.ClientOrderID == "" { return nil, fmt.Errorf("either order id or client supplier id is required") } } @@ -1510,7 +1546,7 @@ func (ok *Okx) WsAmendOrder(arg *AmendOrderRequestParams) (*OrderData, error) { if arg.InstrumentID == "" { return nil, errMissingInstrumentID } - if arg.ClientSuppliedOrderID == "" && arg.OrderID == "" { + if arg.ClientOrderID == "" && arg.OrderID == "" { return nil, errMissingClientOrderIDOrOrderID } if arg.NewQuantity <= 0 && arg.NewPrice <= 0 { @@ -1571,7 +1607,7 @@ func (ok *Okx) WsAmendMultipleOrders(args []AmendOrderRequestParams) ([]OrderDat if args[x].InstrumentID == "" { return nil, errMissingInstrumentID } - if args[x].ClientSuppliedOrderID == "" && args[x].OrderID == "" { + if args[x].ClientOrderID == "" && args[x].OrderID == "" { return nil, errMissingClientOrderIDOrOrderID } if args[x].NewQuantity <= 0 && args[x].NewPrice <= 0 { @@ -1860,9 +1896,9 @@ func (ok *Okx) AccountGreeksSubscription(operation string, pair currency.Pair) e return ok.wsAuthChannelSubscription(operation, okxChannelAccountGreeks, asset.Empty, pair, "", "", wsSubscriptionParameters{Currency: true}) } -// RfqSubscription subscription to retrieve Rfq updates on RFQ orders. +// RfqSubscription subscription to retrieve Rfq updates on Rfq orders. func (ok *Okx) RfqSubscription(operation, uid string) error { - return ok.wsAuthChannelSubscription(operation, okxChannelRFQs, asset.Empty, currency.EMPTYPAIR, uid, "", wsSubscriptionParameters{}) + return ok.wsAuthChannelSubscription(operation, okxChannelRfqs, asset.Empty, currency.EMPTYPAIR, uid, "", wsSubscriptionParameters{}) } // QuotesSubscription subscription to retrieve Quote subscription diff --git a/exchanges/okx/okx_wrapper.go b/exchanges/okx/okx_wrapper.go index c0f06545..92312717 100644 --- a/exchanges/okx/okx_wrapper.go +++ b/exchanges/okx/okx_wrapper.go @@ -812,14 +812,14 @@ func (ok *Okx) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitR } var orderRequest = &PlaceOrderRequestParam{ - InstrumentID: instrumentID, - TradeMode: tradeMode, - Side: sideType, - OrderType: s.Type.Lower(), - Amount: amount, - ClientSupplierOrderID: s.ClientOrderID, - Price: s.Price, - QuantityType: targetCurrency, + InstrumentID: instrumentID, + TradeMode: tradeMode, + Side: sideType, + OrderType: s.Type.Lower(), + Amount: amount, + ClientOrderID: s.ClientOrderID, + Price: s.Price, + QuantityType: targetCurrency, } switch s.Type.Lower() { case OkxOrderLimit, OkxOrderPostOnly, OkxOrderFOK, OkxOrderIOC: @@ -886,10 +886,10 @@ func (ok *Okx) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Mo return nil, err } amendRequest := AmendOrderRequestParams{ - InstrumentID: instrumentID, - NewQuantity: action.Amount, - OrderID: action.OrderID, - ClientSuppliedOrderID: action.ClientOrderID, + InstrumentID: instrumentID, + NewQuantity: action.Amount, + OrderID: action.OrderID, + ClientOrderID: action.ClientOrderID, } if ok.Websocket.CanUseAuthenticatedWebsocketForWrapper() { _, err = ok.WsAmendOrder(&amendRequest) @@ -919,9 +919,9 @@ func (ok *Okx) CancelOrder(ctx context.Context, ord *order.Cancel) error { } instrumentID := pairFormat.Format(ord.Pair) req := CancelOrderRequestParam{ - InstrumentID: instrumentID, - OrderID: ord.OrderID, - ClientSupplierOrderID: ord.ClientOrderID, + InstrumentID: instrumentID, + OrderID: ord.OrderID, + ClientOrderID: ord.ClientOrderID, } if ok.Websocket.CanUseAuthenticatedWebsocketForWrapper() { _, err = ok.WsCancelOrder(req) @@ -964,9 +964,9 @@ func (ok *Okx) CancelBatchOrders(ctx context.Context, o []order.Cancel) (*order. return nil, err } cancelOrderParams[x] = CancelOrderRequestParam{ - InstrumentID: instrumentID, - OrderID: ord.OrderID, - ClientSupplierOrderID: ord.ClientOrderID, + InstrumentID: instrumentID, + OrderID: ord.OrderID, + ClientOrderID: ord.ClientOrderID, } } var canceledOrders []OrderData @@ -1032,25 +1032,25 @@ ordersLoop: switch { case orderCancellation.OrderID != "" || orderCancellation.ClientOrderID != "": if myOrders[x].OrderID == orderCancellation.OrderID || - myOrders[x].ClientSupplierOrderID == orderCancellation.ClientOrderID { + myOrders[x].ClientOrderID == orderCancellation.ClientOrderID { cancelAllOrdersRequestParams[x] = CancelOrderRequestParam{ - OrderID: myOrders[x].OrderID, - ClientSupplierOrderID: myOrders[x].ClientSupplierOrderID, + OrderID: myOrders[x].OrderID, + ClientOrderID: myOrders[x].ClientOrderID, } break ordersLoop } case orderCancellation.Side == order.Buy || orderCancellation.Side == order.Sell: if myOrders[x].Side == order.Buy || myOrders[x].Side == order.Sell { cancelAllOrdersRequestParams[x] = CancelOrderRequestParam{ - OrderID: myOrders[x].OrderID, - ClientSupplierOrderID: myOrders[x].ClientSupplierOrderID, + OrderID: myOrders[x].OrderID, + ClientOrderID: myOrders[x].ClientOrderID, } continue } default: cancelAllOrdersRequestParams[x] = CancelOrderRequestParam{ - OrderID: myOrders[x].OrderID, - ClientSupplierOrderID: myOrders[x].ClientSupplierOrderID, + OrderID: myOrders[x].OrderID, + ClientOrderID: myOrders[x].ClientOrderID, } } } @@ -1128,7 +1128,7 @@ func (ok *Okx) GetOrderInfo(ctx context.Context, orderID string, pair currency.P Amount: orderDetail.Size.Float64(), Exchange: ok.Name, OrderID: orderDetail.OrderID, - ClientOrderID: orderDetail.ClientSupplierOrderID, + ClientOrderID: orderDetail.ClientOrderID, Side: orderDetail.Side, Type: orderType, Pair: pair, @@ -1293,7 +1293,7 @@ allOrders: FeeAsset: currency.NewCode(orderList[i].FeeCurrency), Exchange: ok.Name, OrderID: orderList[i].OrderID, - ClientOrderID: orderList[i].ClientSupplierOrderID, + ClientOrderID: orderList[i].ClientOrderID, Type: oType, Side: orderSide, Status: orderStatus, @@ -1394,7 +1394,7 @@ allOrders: FeeAsset: currency.NewCode(orderList[i].FeeCurrency), Exchange: ok.Name, OrderID: orderList[i].OrderID, - ClientOrderID: orderList[i].ClientSupplierOrderID, + ClientOrderID: orderList[i].ClientOrderID, Type: oType, Side: orderSide, Status: orderStatus, @@ -2023,7 +2023,7 @@ func (ok *Okx) GetFuturesPositionOrders(ctx context.Context, req *order.Position FeeAsset: currency.NewCode(positions[j].FeeCurrency), Exchange: ok.Name, OrderID: positions[j].OrderID, - ClientOrderID: positions[j].ClientSupplierOrderID, + ClientOrderID: positions[j].ClientOrderID, Type: oType, Side: orderSide, Status: orderStatus,