Okx: Various websocket fixes (#1335)

* Okx: Remove redundant asset types from conversion

* Okx: Fix list of private channels for subscription

* Okx: Fix ws order update Acc and Rem amounts

The amounts aren't treated as deltas by anything receiving them
upstream, e.g. orderManager or wsRoutineManager.
So we should treat them the same as the REST implementation

* Okx: Add context to stream unmarshall errors

I encountered a series of errors with unmarshalling from okx and have no
idea what the messages which weren't valid json actually were.
This fix adds the raw message for context to the error

* Okx: Reduce ping interval

Seeing occassional disconnects and suspect dropping the ping interval
down might help

* Fix ClientSupplier and ClientSupplied inconsist

This simply removes the Supplie. part in favour of the simpler name used
in binance. Seems safe since its already inconsistent and not populated
in at least ws order handlin

* Okx: Fix ClientOrderID ignored in ws orders

* Okx: Standardise Rfq abbrev; Fix RfqIDs

* Okx: Fix RfqIds outside of ClientRfqIds

* Okx: Simplify TestUpdateOrderExecutionLimits

* Okx: Fix panic on no avgPrice and QuoteAmount
This commit is contained in:
Gareth Kirwan
2023-10-03 01:01:36 +01:00
committed by GitHub
parent 6105071114
commit 08c27afded
5 changed files with 532 additions and 513 deletions

View File

@@ -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())
}

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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,