cmd/exchange_template, exchanges: Update templates and propogate to exchanges (#1777)

* Added TimeInForce type and updated related files

* Linter issue fix and minor coinbasepro type update

* Bitrex consts update

* added unit test and minor changes in bittrex

* Unit tests update

* Fix minor linter issues

* Update TestStringToTimeInForce unit test

* Exchange test template change

* A different approach

* fix conflict with gateio timeInForce

* minor exchange template update

* Minor fix to test_files template

* Update order tests

* Complete updating the order unit tests

* Updating exchange wrapper and test template files

* update kucoin and deribit wrapper to match the time in force change

* minor comment update

* fix time-in-force related test errors

* linter issue fix

* ADD_NEW_EXCHANGE documentation update

* time in force constants, functions and unit tests update

* shift tif policies to TimeInForce

* Update time-in-force, related functions, and unit tests

* fix linter issue and time-in-force processing

* added a good till crossing tif value

* order type fix and fix related tim-in-force entries

* update time-in-force unmarshaling and unit test

* consistency guideline added

* fix time-in-force error in gateio

* linter issue fix

* update based on review comments

* add unit test and fix missing issues

* minor fix and added benchmark unit test

* change GTT to GTC for limit

* fix linter issue

* added time-in-force value to place order param

* fix minor issues based on review comment and move tif code to separate files

* update on exchanges linked to time-in-force

* resolve missing review comments

* minor linter issues fix

* added time-in-force handler and update timeInForce parametered endpoint

* minor fixes based on review

* nits fix

* update based on review

* linter fix

* rm getTimeInForce func and minor change to time-in-force

* minor change

* update based on review comments

* wrappers and time-in-force calling approach

* minor change

* update gateio string to timeInForce conversion and unit test

* update exchange template

* update wrapper template file

* policy comments, and template files update

* rename all exchange types name to Exchange

* update on template files and template generation

* templates and generation code and other updates

* linter issue fix

* added subscriptions and websocket templates

* update ADD_NEW_EXCHANGE.md with recent binance functions and implementations

* rename template files and update unit tests

* minor template and unit test fix

* rename templates and fix on unit tests

* update on template files and documentation

* removed unnecessary tag fix and update templates

* fix Add_NEW_EXCHANGE.md doc file

* formatting, comments, and error checks update on template files

* rename exchange receivers to e and ex for consistency

* rename unit test exchange receiver and minor updates

* linter issues fix

* fix deribit issue and minor style update

* fix test issues caused by receiver change

* raname local variables exchange declaration variables

* update templates comments

* update templates and related comments

* renamed ex to e

* update template comments

* toggle WS to false to improve coverage

* template comments update

* added test coverage to Ws enabled and minor changes

---------

Co-authored-by: Samuel Reid <43227667+cranktakular@users.noreply.github.com>
This commit is contained in:
Samuael A.
2025-07-17 03:46:36 +03:00
committed by GitHub
parent 485397a0c7
commit 3f534a15f1
163 changed files with 20453 additions and 20313 deletions

View File

@@ -18,8 +18,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
)
// Bitmex is the overarching type across this package
type Bitmex struct {
// Exchange implements exchange.IBotExchange and contains additional specific api methods for interacting with Bitmex
type Exchange struct {
exchange.Base
}
@@ -116,104 +116,104 @@ const (
)
// GetAnnouncement returns the general announcements from Bitmex
func (b *Bitmex) GetAnnouncement(ctx context.Context) ([]Announcement, error) {
func (e *Exchange) GetAnnouncement(ctx context.Context) ([]Announcement, error) {
var announcement []Announcement
return announcement, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointAnnouncement,
return announcement, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointAnnouncement,
nil,
&announcement)
}
// GetUrgentAnnouncement returns an urgent announcement for your account
func (b *Bitmex) GetUrgentAnnouncement(ctx context.Context) ([]Announcement, error) {
func (e *Exchange) GetUrgentAnnouncement(ctx context.Context) ([]Announcement, error) {
var announcement []Announcement
return announcement, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return announcement, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointAnnouncementUrgent,
nil,
&announcement)
}
// GetAPIKeys returns the APIkeys from bitmex
func (b *Bitmex) GetAPIKeys(ctx context.Context) ([]APIKey, error) {
func (e *Exchange) GetAPIKeys(ctx context.Context) ([]APIKey, error) {
var keys []APIKey
return keys, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return keys, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointAPIkeys,
nil,
&keys)
}
// RemoveAPIKey removes an Apikey from the bitmex trading engine
func (b *Bitmex) RemoveAPIKey(ctx context.Context, params APIKeyParams) (bool, error) {
func (e *Exchange) RemoveAPIKey(ctx context.Context, params APIKeyParams) (bool, error) {
var keyDeleted bool
return keyDeleted, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete,
return keyDeleted, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete,
bitmexEndpointAPIkeys,
&params,
&keyDeleted)
}
// DisableAPIKey disables an Apikey from the bitmex trading engine
func (b *Bitmex) DisableAPIKey(ctx context.Context, params APIKeyParams) (APIKey, error) {
func (e *Exchange) DisableAPIKey(ctx context.Context, params APIKeyParams) (APIKey, error) {
var keyInfo APIKey
return keyInfo, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return keyInfo, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointDisableAPIkey,
&params,
&keyInfo)
}
// EnableAPIKey enables an Apikey from the bitmex trading engine
func (b *Bitmex) EnableAPIKey(ctx context.Context, params APIKeyParams) (APIKey, error) {
func (e *Exchange) EnableAPIKey(ctx context.Context, params APIKeyParams) (APIKey, error) {
var keyInfo APIKey
return keyInfo, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return keyInfo, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointEnableAPIkey,
&params,
&keyInfo)
}
// GetTrollboxMessages returns messages from the bitmex trollbox
func (b *Bitmex) GetTrollboxMessages(ctx context.Context, params ChatGetParams) ([]Chat, error) {
func (e *Exchange) GetTrollboxMessages(ctx context.Context, params ChatGetParams) ([]Chat, error) {
var messages []Chat
return messages, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointTrollbox, &params, &messages)
return messages, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointTrollbox, &params, &messages)
}
// SendTrollboxMessage sends a message to the bitmex trollbox
func (b *Bitmex) SendTrollboxMessage(ctx context.Context, params ChatSendParams) ([]Chat, error) {
func (e *Exchange) SendTrollboxMessage(ctx context.Context, params ChatSendParams) ([]Chat, error) {
var messages []Chat
return messages, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return messages, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointTrollboxSend,
&params,
&messages)
}
// GetTrollboxChannels the channels from the bitmex trollbox
func (b *Bitmex) GetTrollboxChannels(ctx context.Context) ([]ChatChannel, error) {
func (e *Exchange) GetTrollboxChannels(ctx context.Context) ([]ChatChannel, error) {
var channels []ChatChannel
return channels, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointTrollboxChannels,
return channels, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointTrollboxChannels,
nil,
&channels)
}
// GetTrollboxConnectedUsers the channels from the bitmex trollbox
func (b *Bitmex) GetTrollboxConnectedUsers(ctx context.Context) (ConnectedUsers, error) {
func (e *Exchange) GetTrollboxConnectedUsers(ctx context.Context) (ConnectedUsers, error) {
var users ConnectedUsers
return users, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointTrollboxConnected, nil, &users)
return users, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointTrollboxConnected, nil, &users)
}
// GetAccountExecutions returns all raw transactions, which includes order
// opening and cancellation, and order status changes. It can be quite noisy.
// More focused information is available at /execution/tradeHistory.
func (b *Bitmex) GetAccountExecutions(ctx context.Context, params *GenericRequestParams) ([]Execution, error) {
func (e *Exchange) GetAccountExecutions(ctx context.Context, params *GenericRequestParams) ([]Execution, error) {
var executionList []Execution
return executionList, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return executionList, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointExecution,
params,
&executionList)
@@ -221,17 +221,17 @@ func (b *Bitmex) GetAccountExecutions(ctx context.Context, params *GenericReques
// GetAccountExecutionTradeHistory returns all balance-affecting executions.
// This includes each trade, insurance charge, and settlement.
func (b *Bitmex) GetAccountExecutionTradeHistory(ctx context.Context, params *GenericRequestParams) ([]Execution, error) {
func (e *Exchange) GetAccountExecutionTradeHistory(ctx context.Context, params *GenericRequestParams) ([]Execution, error) {
var tradeHistory []Execution
return tradeHistory, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return tradeHistory, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointExecutionTradeHistory,
params,
&tradeHistory)
}
// GetFullFundingHistory returns funding history
func (b *Bitmex) GetFullFundingHistory(ctx context.Context, symbol, count, filter, columns, start string, reverse bool, startTime, endTime time.Time) ([]Funding, error) {
func (e *Exchange) GetFullFundingHistory(ctx context.Context, symbol, count, filter, columns, start string, reverse bool, startTime, endTime time.Time) ([]Funding, error) {
var fundingHistory []Funding
params := url.Values{}
if symbol != "" {
@@ -260,59 +260,59 @@ func (b *Bitmex) GetFullFundingHistory(ctx context.Context, symbol, count, filte
params.Set("startTime", startTime.Format(time.RFC3339))
params.Set("endTime", endTime.Format(time.RFC3339))
}
return fundingHistory, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointFundingHistory+params.Encode(),
return fundingHistory, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointFundingHistory+params.Encode(),
nil,
&fundingHistory)
}
// GetInstrument returns instrument data
func (b *Bitmex) GetInstrument(ctx context.Context, params *GenericRequestParams) ([]Instrument, error) {
func (e *Exchange) GetInstrument(ctx context.Context, params *GenericRequestParams) ([]Instrument, error) {
var instruments []Instrument
return instruments, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointInstruments,
return instruments, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointInstruments,
params,
&instruments)
}
// GetInstruments returns instrument data
func (b *Bitmex) GetInstruments(ctx context.Context, params *GenericRequestParams) ([]Instrument, error) {
func (e *Exchange) GetInstruments(ctx context.Context, params *GenericRequestParams) ([]Instrument, error) {
var instruments []Instrument
return instruments, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointInstruments,
return instruments, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointInstruments,
params,
&instruments)
}
// GetActiveInstruments returns active instruments
func (b *Bitmex) GetActiveInstruments(ctx context.Context, params *GenericRequestParams) ([]Instrument, error) {
func (e *Exchange) GetActiveInstruments(ctx context.Context, params *GenericRequestParams) ([]Instrument, error) {
var activeInstruments []Instrument
return activeInstruments, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointActiveInstruments,
return activeInstruments, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointActiveInstruments,
params,
&activeInstruments)
}
// GetActiveAndIndexInstruments returns all active instruments and all indices
func (b *Bitmex) GetActiveAndIndexInstruments(ctx context.Context) ([]Instrument, error) {
func (e *Exchange) GetActiveAndIndexInstruments(ctx context.Context) ([]Instrument, error) {
var activeAndIndices []Instrument
return activeAndIndices,
b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointActiveAndIndexInstruments,
e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointActiveAndIndexInstruments,
nil,
&activeAndIndices)
}
// GetActiveIntervals returns funding history
func (b *Bitmex) GetActiveIntervals(ctx context.Context) (InstrumentInterval, error) {
func (e *Exchange) GetActiveIntervals(ctx context.Context) (InstrumentInterval, error) {
var interval InstrumentInterval
return interval, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointActiveIntervals,
return interval, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointActiveIntervals,
nil,
&interval)
}
// GetCompositeIndex returns composite index
func (b *Bitmex) GetCompositeIndex(ctx context.Context, symbol, count, filter, columns, start, reverse string, startTime, endTime time.Time) ([]IndexComposite, error) {
func (e *Exchange) GetCompositeIndex(ctx context.Context, symbol, count, filter, columns, start, reverse string, startTime, endTime time.Time) ([]IndexComposite, error) {
var compositeIndices []IndexComposite
params := url.Values{}
params.Set("symbol", symbol)
@@ -338,82 +338,82 @@ func (b *Bitmex) GetCompositeIndex(ctx context.Context, symbol, count, filter, c
params.Set("startTime", startTime.Format(time.RFC3339))
params.Set("endTime", endTime.Format(time.RFC3339))
}
return compositeIndices, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointCompositeIndex+"?"+params.Encode(),
return compositeIndices, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointCompositeIndex+"?"+params.Encode(),
nil,
&compositeIndices)
}
// GetIndices returns all price indices
func (b *Bitmex) GetIndices(ctx context.Context) ([]Instrument, error) {
func (e *Exchange) GetIndices(ctx context.Context) ([]Instrument, error) {
var indices []Instrument
return indices, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointIndices, nil, &indices)
return indices, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointIndices, nil, &indices)
}
// GetInsuranceFundHistory returns insurance fund history
func (b *Bitmex) GetInsuranceFundHistory(ctx context.Context, params *GenericRequestParams) ([]Insurance, error) {
func (e *Exchange) GetInsuranceFundHistory(ctx context.Context, params *GenericRequestParams) ([]Insurance, error) {
var history []Insurance
return history, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointIndices, params, &history)
return history, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointIndices, params, &history)
}
// GetLeaderboard returns leaderboard information
func (b *Bitmex) GetLeaderboard(ctx context.Context, params LeaderboardGetParams) ([]Leaderboard, error) {
func (e *Exchange) GetLeaderboard(ctx context.Context, params LeaderboardGetParams) ([]Leaderboard, error) {
var leader []Leaderboard
return leader, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointLeader, params, &leader)
return leader, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointLeader, params, &leader)
}
// GetAliasOnLeaderboard returns your alias on the leaderboard
func (b *Bitmex) GetAliasOnLeaderboard(ctx context.Context) (Alias, error) {
func (e *Exchange) GetAliasOnLeaderboard(ctx context.Context) (Alias, error) {
var alias Alias
return alias, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointAlias, nil, &alias)
return alias, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointAlias, nil, &alias)
}
// GetLiquidationOrders returns liquidation orders
func (b *Bitmex) GetLiquidationOrders(ctx context.Context, params *GenericRequestParams) ([]Liquidation, error) {
func (e *Exchange) GetLiquidationOrders(ctx context.Context, params *GenericRequestParams) ([]Liquidation, error) {
var orders []Liquidation
return orders, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointLiquidation,
return orders, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointLiquidation,
params,
&orders)
}
// GetCurrentNotifications returns your current notifications
func (b *Bitmex) GetCurrentNotifications(ctx context.Context) ([]Notification, error) {
func (e *Exchange) GetCurrentNotifications(ctx context.Context) ([]Notification, error) {
var notifications []Notification
return notifications, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return notifications, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointNotifications,
nil,
&notifications)
}
// GetOrders returns all the orders, open and closed
func (b *Bitmex) GetOrders(ctx context.Context, params *OrdersRequest) ([]Order, error) {
func (e *Exchange) GetOrders(ctx context.Context, params *OrdersRequest) ([]Order, error) {
var orders []Order
return orders, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return orders, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointOrder,
params,
&orders)
}
// AmendOrder amends the quantity or price of an open order
func (b *Bitmex) AmendOrder(ctx context.Context, params *OrderAmendParams) (Order, error) {
func (e *Exchange) AmendOrder(ctx context.Context, params *OrderAmendParams) (Order, error) {
var order Order
return order, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPut,
return order, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPut,
bitmexEndpointOrder,
params,
&order)
}
// CreateOrder creates a new order
func (b *Bitmex) CreateOrder(ctx context.Context, params *OrderNewParams) (Order, error) {
func (e *Exchange) CreateOrder(ctx context.Context, params *OrderNewParams) (Order, error) {
var orderInfo Order
return orderInfo, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return orderInfo, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointOrder,
params,
&orderInfo)
@@ -421,223 +421,223 @@ func (b *Bitmex) CreateOrder(ctx context.Context, params *OrderNewParams) (Order
// CancelOrders cancels one or a batch of orders on the exchange and returns
// a cancelled order list
func (b *Bitmex) CancelOrders(ctx context.Context, params *OrderCancelParams) ([]Order, error) {
func (e *Exchange) CancelOrders(ctx context.Context, params *OrderCancelParams) ([]Order, error) {
var cancelledOrders []Order
return cancelledOrders, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete,
return cancelledOrders, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete,
bitmexEndpointOrder,
params,
&cancelledOrders)
}
// CancelAllExistingOrders cancels all open orders on the exchange
func (b *Bitmex) CancelAllExistingOrders(ctx context.Context, params OrderCancelAllParams) ([]Order, error) {
func (e *Exchange) CancelAllExistingOrders(ctx context.Context, params OrderCancelAllParams) ([]Order, error) {
var cancelledOrders []Order
return cancelledOrders, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete,
return cancelledOrders, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete,
bitmexEndpointCancelAllOrders,
params,
&cancelledOrders)
}
// AmendBulkOrders amends multiple orders for the same symbol
func (b *Bitmex) AmendBulkOrders(ctx context.Context, params OrderAmendBulkParams) ([]Order, error) {
func (e *Exchange) AmendBulkOrders(ctx context.Context, params OrderAmendBulkParams) ([]Order, error) {
var amendedOrders []Order
return amendedOrders, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPut,
return amendedOrders, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPut,
bitmexEndpointBulk,
params,
&amendedOrders)
}
// CreateBulkOrders creates multiple orders for the same symbol
func (b *Bitmex) CreateBulkOrders(ctx context.Context, params OrderNewBulkParams) ([]Order, error) {
func (e *Exchange) CreateBulkOrders(ctx context.Context, params OrderNewBulkParams) ([]Order, error) {
var orders []Order
return orders, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return orders, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointBulk,
params,
&orders)
}
// CancelAllOrdersAfterTime closes all positions after a certain time period
func (b *Bitmex) CancelAllOrdersAfterTime(ctx context.Context, params OrderCancelAllAfterParams) ([]Order, error) {
func (e *Exchange) CancelAllOrdersAfterTime(ctx context.Context, params OrderCancelAllAfterParams) ([]Order, error) {
var cancelledOrder []Order
return cancelledOrder, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return cancelledOrder, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointCancelOrderAfter,
params,
&cancelledOrder)
}
// ClosePosition closes a position WARNING deprecated use /order endpoint
func (b *Bitmex) ClosePosition(ctx context.Context, params OrderClosePositionParams) ([]Order, error) {
func (e *Exchange) ClosePosition(ctx context.Context, params OrderClosePositionParams) ([]Order, error) {
var closedPositions []Order
return closedPositions, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return closedPositions, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointOrder,
params,
&closedPositions)
}
// GetOrderbook returns layer two orderbook data
func (b *Bitmex) GetOrderbook(ctx context.Context, params OrderBookGetL2Params) ([]OrderBookL2, error) {
func (e *Exchange) GetOrderbook(ctx context.Context, params OrderBookGetL2Params) ([]OrderBookL2, error) {
var orderBooks []OrderBookL2
return orderBooks, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointOrderbookL2,
return orderBooks, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointOrderbookL2,
params,
&orderBooks)
}
// GetPositions returns positions
func (b *Bitmex) GetPositions(ctx context.Context, params PositionGetParams) ([]Position, error) {
func (e *Exchange) GetPositions(ctx context.Context, params PositionGetParams) ([]Position, error) {
var positions []Position
return positions, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return positions, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointPosition,
params,
&positions)
}
// IsolatePosition enables isolated margin or cross margin per-position
func (b *Bitmex) IsolatePosition(ctx context.Context, params PositionIsolateMarginParams) (Position, error) {
func (e *Exchange) IsolatePosition(ctx context.Context, params PositionIsolateMarginParams) (Position, error) {
var position Position
return position, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return position, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointIsolatePosition,
params,
&position)
}
// LeveragePosition chooses leverage for a position
func (b *Bitmex) LeveragePosition(ctx context.Context, params PositionUpdateLeverageParams) (Position, error) {
func (e *Exchange) LeveragePosition(ctx context.Context, params PositionUpdateLeverageParams) (Position, error) {
var position Position
return position, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return position, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointLeveragePosition,
params,
&position)
}
// UpdateRiskLimit updates risk limit on a position
func (b *Bitmex) UpdateRiskLimit(ctx context.Context, params PositionUpdateRiskLimitParams) (Position, error) {
func (e *Exchange) UpdateRiskLimit(ctx context.Context, params PositionUpdateRiskLimitParams) (Position, error) {
var position Position
return position, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return position, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointAdjustRiskLimit,
params,
&position)
}
// TransferMargin transfers equity in or out of a position
func (b *Bitmex) TransferMargin(ctx context.Context, params PositionTransferIsolatedMarginParams) (Position, error) {
func (e *Exchange) TransferMargin(ctx context.Context, params PositionTransferIsolatedMarginParams) (Position, error) {
var position Position
return position, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return position, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointTransferMargin,
params,
&position)
}
// GetQuotes returns quotations
func (b *Bitmex) GetQuotes(ctx context.Context, params *GenericRequestParams) ([]Quote, error) {
func (e *Exchange) GetQuotes(ctx context.Context, params *GenericRequestParams) ([]Quote, error) {
var quotations []Quote
return quotations, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointQuote,
return quotations, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointQuote,
params,
&quotations)
}
// GetQuotesByBuckets returns previous quotes in time buckets
func (b *Bitmex) GetQuotesByBuckets(ctx context.Context, params *QuoteGetBucketedParams) ([]Quote, error) {
func (e *Exchange) GetQuotesByBuckets(ctx context.Context, params *QuoteGetBucketedParams) ([]Quote, error) {
var quotations []Quote
return quotations, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointQuoteBucketed,
return quotations, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointQuoteBucketed,
params,
&quotations)
}
// GetSettlementHistory returns settlement history
func (b *Bitmex) GetSettlementHistory(ctx context.Context, params *GenericRequestParams) ([]Settlement, error) {
func (e *Exchange) GetSettlementHistory(ctx context.Context, params *GenericRequestParams) ([]Settlement, error) {
var history []Settlement
return history, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointSettlement,
return history, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointSettlement,
params,
&history)
}
// GetStats returns exchange wide per series turnover and volume statistics
func (b *Bitmex) GetStats(ctx context.Context) ([]Stats, error) {
func (e *Exchange) GetStats(ctx context.Context) ([]Stats, error) {
var stats []Stats
return stats, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointStats, nil, &stats)
return stats, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointStats, nil, &stats)
}
// GetStatsHistorical historic stats
func (b *Bitmex) GetStatsHistorical(ctx context.Context) ([]StatsHistory, error) {
func (e *Exchange) GetStatsHistorical(ctx context.Context) ([]StatsHistory, error) {
var history []StatsHistory
return history, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointStatsHistory, nil, &history)
return history, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointStatsHistory, nil, &history)
}
// GetStatSummary returns the stats summary in USD terms
func (b *Bitmex) GetStatSummary(ctx context.Context) ([]StatsUSD, error) {
func (e *Exchange) GetStatSummary(ctx context.Context) ([]StatsUSD, error) {
var summary []StatsUSD
return summary, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointStatsSummary, nil, &summary)
return summary, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointStatsSummary, nil, &summary)
}
// GetTrade returns executed trades on the desk
func (b *Bitmex) GetTrade(ctx context.Context, params *GenericRequestParams) ([]Trade, error) {
func (e *Exchange) GetTrade(ctx context.Context, params *GenericRequestParams) ([]Trade, error) {
var trade []Trade
return trade, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointTrade, params, &trade)
return trade, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointTrade, params, &trade)
}
// GetPreviousTrades previous trade history in time buckets
func (b *Bitmex) GetPreviousTrades(ctx context.Context, params *TradeGetBucketedParams) ([]Trade, error) {
func (e *Exchange) GetPreviousTrades(ctx context.Context, params *TradeGetBucketedParams) ([]Trade, error) {
var trade []Trade
return trade, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointTradeBucketed,
return trade, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointTradeBucketed,
params,
&trade)
}
// GetUserInfo returns your user information
func (b *Bitmex) GetUserInfo(ctx context.Context) (User, error) {
func (e *Exchange) GetUserInfo(ctx context.Context) (User, error) {
var userInfo User
return userInfo, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return userInfo, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUser,
nil,
&userInfo)
}
// UpdateUserInfo updates user information
func (b *Bitmex) UpdateUserInfo(ctx context.Context, params *UserUpdateParams) (User, error) {
func (e *Exchange) UpdateUserInfo(ctx context.Context, params *UserUpdateParams) (User, error) {
var userInfo User
return userInfo, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPut,
return userInfo, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPut,
bitmexEndpointUser,
params,
&userInfo)
}
// GetAffiliateStatus returns your affiliate status
func (b *Bitmex) GetAffiliateStatus(ctx context.Context) (AffiliateStatus, error) {
func (e *Exchange) GetAffiliateStatus(ctx context.Context) (AffiliateStatus, error) {
var status AffiliateStatus
return status, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return status, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUserAffiliate,
nil,
&status)
}
// CancelWithdraw cancels a current withdrawal
func (b *Bitmex) CancelWithdraw(ctx context.Context, token string) (TransactionInfo, error) {
func (e *Exchange) CancelWithdraw(ctx context.Context, token string) (TransactionInfo, error) {
var info TransactionInfo
return info, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return info, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointUserCancelWithdraw,
UserTokenParams{Token: token},
&info)
@@ -645,140 +645,140 @@ func (b *Bitmex) CancelWithdraw(ctx context.Context, token string) (TransactionI
// CheckReferalCode checks a code, will return a percentage eg 0.1 for 10% or
// if err a 404
func (b *Bitmex) CheckReferalCode(ctx context.Context, referralCode string) (float64, error) {
func (e *Exchange) CheckReferalCode(ctx context.Context, referralCode string) (float64, error) {
var percentage float64
return percentage, b.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointUserCheckReferralCode,
return percentage, e.SendHTTPRequest(ctx, exchange.RestSpot, bitmexEndpointUserCheckReferralCode,
UserCheckReferralCodeParams{ReferralCode: referralCode},
&percentage)
}
// GetUserCommision returns your account's commission status.
func (b *Bitmex) GetUserCommision(ctx context.Context) (UserCommission, error) {
func (e *Exchange) GetUserCommision(ctx context.Context) (UserCommission, error) {
var commissionInfo UserCommission
return commissionInfo, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return commissionInfo, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUserCommision,
nil,
&commissionInfo)
}
// ConfirmEmail confirms email address with a token
func (b *Bitmex) ConfirmEmail(ctx context.Context, token string) (ConfirmEmail, error) {
func (e *Exchange) ConfirmEmail(ctx context.Context, token string) (ConfirmEmail, error) {
var confirmation ConfirmEmail
return confirmation, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return confirmation, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUserConfirmEmail,
UserTokenParams{Token: token},
&confirmation)
}
// ConfirmTwoFactorAuth confirms 2FA for this account.
func (b *Bitmex) ConfirmTwoFactorAuth(ctx context.Context, token, typ string) (bool, error) {
func (e *Exchange) ConfirmTwoFactorAuth(ctx context.Context, token, typ string) (bool, error) {
var working bool
return working, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return working, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointUserConfirmTFA,
UserConfirmTFAParams{Token: token, Type: typ},
&working)
}
// ConfirmWithdrawal confirms a withdrawal
func (b *Bitmex) ConfirmWithdrawal(ctx context.Context, token string) (TransactionInfo, error) {
func (e *Exchange) ConfirmWithdrawal(ctx context.Context, token string) (TransactionInfo, error) {
var info TransactionInfo
return info, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return info, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointUserCancelWithdraw,
UserTokenParams{Token: token},
&info)
}
// GetCryptoDepositAddress returns a deposit address for a cryptocurrency
func (b *Bitmex) GetCryptoDepositAddress(ctx context.Context, cryptoCurrency string) (string, error) {
func (e *Exchange) GetCryptoDepositAddress(ctx context.Context, cryptoCurrency string) (string, error) {
var address string
if !strings.EqualFold(cryptoCurrency, currency.XBT.String()) {
return "", fmt.Errorf("%v %w only bitcoin", cryptoCurrency, currency.ErrCurrencyNotSupported)
}
return address, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return address, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUserDepositAddress,
UserCurrencyParams{Currency: "XBt"},
&address)
}
// DisableTFA dsiables 2 factor authentication for your account
func (b *Bitmex) DisableTFA(ctx context.Context, token, typ string) (bool, error) {
func (e *Exchange) DisableTFA(ctx context.Context, token, typ string) (bool, error) {
var disabled bool
return disabled, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return disabled, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointUserDisableTFA,
UserConfirmTFAParams{Token: token, Type: typ},
&disabled)
}
// UserLogOut logs you out of BitMEX
func (b *Bitmex) UserLogOut(ctx context.Context) error {
return b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
func (e *Exchange) UserLogOut(ctx context.Context) error {
return e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointUserLogout,
nil,
nil)
}
// UserLogOutAll logs you out of all systems for BitMEX
func (b *Bitmex) UserLogOutAll(ctx context.Context) (int64, error) {
func (e *Exchange) UserLogOutAll(ctx context.Context) (int64, error) {
var status int64
return status, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return status, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointUserLogoutAll,
nil,
&status)
}
// GetUserMargin returns user margin information
func (b *Bitmex) GetUserMargin(ctx context.Context, currency string) (UserMargin, error) {
func (e *Exchange) GetUserMargin(ctx context.Context, currency string) (UserMargin, error) {
var info UserMargin
return info, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return info, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUserMargin,
UserCurrencyParams{Currency: currency},
&info)
}
// GetAllUserMargin returns user margin information
func (b *Bitmex) GetAllUserMargin(ctx context.Context) ([]UserMargin, error) {
func (e *Exchange) GetAllUserMargin(ctx context.Context) ([]UserMargin, error) {
var info []UserMargin
return info, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return info, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUserMargin,
UserCurrencyParams{Currency: "all"},
&info)
}
// GetMinimumWithdrawalFee returns minimum withdrawal fee information
func (b *Bitmex) GetMinimumWithdrawalFee(ctx context.Context, currency string) (MinWithdrawalFee, error) {
func (e *Exchange) GetMinimumWithdrawalFee(ctx context.Context, currency string) (MinWithdrawalFee, error) {
var fee MinWithdrawalFee
return fee, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return fee, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUserMinWithdrawalFee,
UserCurrencyParams{Currency: currency},
&fee)
}
// GetUserPreferences returns user preferences
func (b *Bitmex) GetUserPreferences(ctx context.Context, params UserPreferencesParams) (User, error) {
func (e *Exchange) GetUserPreferences(ctx context.Context, params UserPreferencesParams) (User, error) {
var userInfo User
return userInfo, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return userInfo, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointUserPreferences,
params,
&userInfo)
}
// EnableTFA enables 2 factor authentication
func (b *Bitmex) EnableTFA(ctx context.Context, typ string) (bool, error) {
func (e *Exchange) EnableTFA(ctx context.Context, typ string) (bool, error) {
var enabled bool
return enabled, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return enabled, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointUserRequestTFA,
UserConfirmTFAParams{Type: typ},
&enabled)
@@ -787,20 +787,20 @@ func (b *Bitmex) EnableTFA(ctx context.Context, typ string) (bool, error) {
// UserRequestWithdrawal This will send a confirmation email to the email
// address on record, unless requested via an API Key with the withdraw
// permission.
func (b *Bitmex) UserRequestWithdrawal(ctx context.Context, params UserRequestWithdrawalParams) (TransactionInfo, error) {
func (e *Exchange) UserRequestWithdrawal(ctx context.Context, params UserRequestWithdrawalParams) (TransactionInfo, error) {
var info TransactionInfo
return info, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
return info, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
bitmexEndpointUserRequestWithdraw,
params,
&info)
}
// GetWalletInfo returns user wallet information
func (b *Bitmex) GetWalletInfo(ctx context.Context, currency string) (WalletInfo, error) {
func (e *Exchange) GetWalletInfo(ctx context.Context, currency string) (WalletInfo, error) {
var info WalletInfo
if err := b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUserWallet,
UserCurrencyParams{Currency: currency},
&info); err != nil {
@@ -818,29 +818,29 @@ func (b *Bitmex) GetWalletInfo(ctx context.Context, currency string) (WalletInfo
}
// GetWalletHistory returns user wallet history transaction data
func (b *Bitmex) GetWalletHistory(ctx context.Context, currency string) ([]TransactionInfo, error) {
func (e *Exchange) GetWalletHistory(ctx context.Context, currency string) ([]TransactionInfo, error) {
var info []TransactionInfo
return info, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return info, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUserWalletHistory,
UserCurrencyParams{Currency: currency},
&info)
}
// GetWalletSummary returns user wallet summary
func (b *Bitmex) GetWalletSummary(ctx context.Context, currency string) ([]TransactionInfo, error) {
func (e *Exchange) GetWalletSummary(ctx context.Context, currency string) ([]TransactionInfo, error) {
var info []TransactionInfo
return info, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
return info, e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet,
bitmexEndpointUserWalletSummary,
UserCurrencyParams{Currency: currency},
&info)
}
// SendHTTPRequest sends an unauthenticated HTTP request
func (b *Bitmex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, params Parameter, result any) error {
func (e *Exchange) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, params Parameter, result any) error {
var respCheck any
endpoint, err := b.API.Endpoints.GetURL(ep)
endpoint, err := e.API.Endpoints.GetURL(ep)
if err != nil {
return err
}
@@ -856,28 +856,28 @@ func (b *Bitmex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path stri
Method: http.MethodGet,
Path: path,
Result: &respCheck,
Verbose: b.Verbose,
HTTPDebugging: b.HTTPDebugging,
HTTPRecording: b.HTTPRecording,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
}
err = b.SendPayload(ctx, request.UnAuth, func() (*request.Item, error) {
err = e.SendPayload(ctx, request.UnAuth, func() (*request.Item, error) {
return item, nil
}, request.UnauthenticatedRequest)
if err != nil {
return err
}
return b.CaptureError(respCheck, result)
return e.CaptureError(respCheck, result)
}
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bitmex
func (b *Bitmex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, verb, path string, params Parameter, result any) error {
creds, err := b.GetCredentials(ctx)
func (e *Exchange) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, verb, path string, params Parameter, result any) error {
creds, err := e.GetCredentials(ctx)
if err != nil {
return err
}
endpoint, err := b.API.Endpoints.GetURL(ep)
endpoint, err := e.API.Endpoints.GetURL(ep)
if err != nil {
return err
}
@@ -916,21 +916,21 @@ func (b *Bitmex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U
Headers: headers,
Body: strings.NewReader(payload),
Result: &respCheck,
Verbose: b.Verbose,
HTTPDebugging: b.HTTPDebugging,
HTTPRecording: b.HTTPRecording,
Verbose: e.Verbose,
HTTPDebugging: e.HTTPDebugging,
HTTPRecording: e.HTTPRecording,
}, nil
}
err = b.SendPayload(ctx, request.Auth, newRequest, request.AuthenticatedRequest)
err = e.SendPayload(ctx, request.Auth, newRequest, request.AuthenticatedRequest)
if err != nil {
return err
}
return b.CaptureError(respCheck, result)
return e.CaptureError(respCheck, result)
}
// CaptureError little hack that captures an error
func (b *Bitmex) CaptureError(resp, reType any) error {
func (e *Exchange) CaptureError(resp, reType any) error {
var Error RequestError
marshalled, err := json.Marshal(resp)
@@ -949,7 +949,7 @@ func (b *Bitmex) CaptureError(resp, reType any) error {
}
// GetFee returns an estimate of fee based on type of transaction
func (b *Bitmex) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
func (e *Exchange) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
var fee float64
var err error
switch feeBuilder.FeeType {

File diff suppressed because it is too large Load Diff

View File

@@ -83,24 +83,24 @@ var defaultSubscriptions = subscription.List{
}
// WsConnect initiates a new websocket connection
func (b *Bitmex) WsConnect() error {
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
func (e *Exchange) WsConnect() error {
if !e.Websocket.IsEnabled() || !e.IsEnabled() {
return websocket.ErrWebsocketNotEnabled
}
ctx := context.TODO()
var dialer gws.Dialer
if err := b.Websocket.Conn.Dial(ctx, &dialer, http.Header{}); err != nil {
if err := e.Websocket.Conn.Dial(ctx, &dialer, http.Header{}); err != nil {
return err
}
b.Websocket.Wg.Add(1)
go b.wsReadData()
e.Websocket.Wg.Add(1)
go e.wsReadData()
if b.Websocket.CanUseAuthenticatedEndpoints() {
if err := b.websocketSendAuth(ctx); err != nil {
b.Websocket.SetCanUseAuthenticatedEndpoints(false)
log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", b.Name, err)
if e.Websocket.CanUseAuthenticatedEndpoints() {
if err := e.websocketSendAuth(ctx); err != nil {
e.Websocket.SetCanUseAuthenticatedEndpoints(false)
log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", e.Name, err)
}
}
@@ -113,22 +113,22 @@ const (
)
// wsReadData receives and passes on websocket messages for processing
func (b *Bitmex) wsReadData() {
defer b.Websocket.Wg.Done()
func (e *Exchange) wsReadData() {
defer e.Websocket.Wg.Done()
for {
resp := b.Websocket.Conn.ReadMessage()
resp := e.Websocket.Conn.ReadMessage()
if resp.Raw == nil {
return
}
err := b.wsHandleData(resp.Raw)
err := e.wsHandleData(resp.Raw)
if err != nil {
b.Websocket.DataHandler <- err
e.Websocket.DataHandler <- err
}
}
}
func (b *Bitmex) wsHandleData(respRaw []byte) error {
func (e *Exchange) wsHandleData(respRaw []byte) error {
// We don't need to know about errors, since we're looking optimistically into the json
op, _ := jsonparser.GetString(respRaw, "request", "op")
errMsg, _ := jsonparser.GetString(respRaw, "error")
@@ -141,8 +141,8 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
return err
}
if b.Verbose {
log.Debugf(log.ExchangeSys, "%s successfully connected to websocket API at time: %s Limit: %d", b.Name, welcomeResp.Timestamp, welcomeResp.Limit.Remaining)
if e.Verbose {
log.Debugf(log.ExchangeSys, "%s successfully connected to websocket API at time: %s Limit: %d", e.Name, welcomeResp.Timestamp, welcomeResp.Limit.Remaining)
}
return nil
case errMsg != "", success:
@@ -156,7 +156,7 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
}
req = string(reqBytes)
}
if err := b.Websocket.Match.RequireMatchWithData(req, respRaw); err != nil {
if err := e.Websocket.Match.RequireMatchWithData(req, respRaw); err != nil {
return fmt.Errorf("%w: %s", err, op)
}
return nil
@@ -178,17 +178,17 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
return fmt.Errorf("empty orderbook data received: %s", respRaw)
}
pair, a, err := b.GetPairAndAssetTypeRequestFormatted(orderbooks.Data[0].Symbol)
pair, a, err := e.GetPairAndAssetTypeRequestFormatted(orderbooks.Data[0].Symbol)
if err != nil {
return err
}
err = b.processOrderbook(orderbooks.Data, orderbooks.Action, pair, a)
err = e.processOrderbook(orderbooks.Data, orderbooks.Action, pair, a)
if err != nil {
return err
}
case bitmexWSTrade:
return b.handleWsTrades(respRaw)
return e.handleWsTrades(respRaw)
case bitmexWSAnnouncement:
var announcement AnnouncementData
if err := json.Unmarshal(respRaw, &announcement); err != nil {
@@ -199,13 +199,13 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
return nil
}
b.Websocket.DataHandler <- announcement.Data
e.Websocket.DataHandler <- announcement.Data
case bitmexWSAffiliate:
var response WsAffiliateResponse
if err := json.Unmarshal(respRaw, &response); err != nil {
return err
}
b.Websocket.DataHandler <- response
e.Websocket.DataHandler <- response
case bitmexWSInstrument:
// ticker
case bitmexWSExecution:
@@ -216,28 +216,28 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
}
for i := range response.Data {
p, a, err := b.GetPairAndAssetTypeRequestFormatted(response.Data[i].Symbol)
p, a, err := e.GetPairAndAssetTypeRequestFormatted(response.Data[i].Symbol)
if err != nil {
return err
}
oStatus, err := order.StringToOrderStatus(response.Data[i].OrdStatus)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
e.Websocket.DataHandler <- order.ClassificationError{
Exchange: e.Name,
OrderID: response.Data[i].OrderID,
Err: err,
}
}
oSide, err := order.StringToOrderSide(response.Data[i].Side)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
e.Websocket.DataHandler <- order.ClassificationError{
Exchange: e.Name,
OrderID: response.Data[i].OrderID,
Err: err,
}
}
b.Websocket.DataHandler <- &order.Detail{
Exchange: b.Name,
e.Websocket.DataHandler <- &order.Detail{
Exchange: e.Name,
OrderID: response.Data[i].OrderID,
AccountID: strconv.FormatInt(response.Data[i].Account, 10),
AssetType: a,
@@ -247,7 +247,7 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
{
Price: response.Data[i].Price,
Amount: response.Data[i].OrderQuantity,
Exchange: b.Name,
Exchange: e.Name,
TID: response.Data[i].ExecID,
Side: oSide,
Timestamp: response.Data[i].Timestamp,
@@ -264,38 +264,38 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
switch response.Action {
case "update", "insert":
for x := range response.Data {
p, a, err := b.GetRequestFormattedPairAndAssetType(response.Data[x].Symbol)
p, a, err := e.GetRequestFormattedPairAndAssetType(response.Data[x].Symbol)
if err != nil {
return err
}
oSide, err := order.StringToOrderSide(response.Data[x].Side)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
e.Websocket.DataHandler <- order.ClassificationError{
Exchange: e.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
}
oType, err := order.StringToOrderType(response.Data[x].OrderType)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
e.Websocket.DataHandler <- order.ClassificationError{
Exchange: e.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
}
oStatus, err := order.StringToOrderStatus(response.Data[x].OrderStatus)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
e.Websocket.DataHandler <- order.ClassificationError{
Exchange: e.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
}
b.Websocket.DataHandler <- &order.Detail{
e.Websocket.DataHandler <- &order.Detail{
Price: response.Data[x].Price,
Amount: response.Data[x].OrderQuantity,
Exchange: b.Name,
Exchange: e.Name,
OrderID: response.Data[x].OrderID,
AccountID: strconv.FormatInt(response.Data[x].Account, 10),
Type: oType,
@@ -308,15 +308,15 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
}
case "delete":
for x := range response.Data {
p, a, err := b.GetRequestFormattedPairAndAssetType(response.Data[x].Symbol)
p, a, err := e.GetRequestFormattedPairAndAssetType(response.Data[x].Symbol)
if err != nil {
return err
}
var oSide order.Side
oSide, err = order.StringToOrderSide(response.Data[x].Side)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
e.Websocket.DataHandler <- order.ClassificationError{
Exchange: e.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
@@ -324,8 +324,8 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
var oType order.Type
oType, err = order.StringToOrderType(response.Data[x].OrderType)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
e.Websocket.DataHandler <- order.ClassificationError{
Exchange: e.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
@@ -333,16 +333,16 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
var oStatus order.Status
oStatus, err = order.StringToOrderStatus(response.Data[x].OrderStatus)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
e.Websocket.DataHandler <- order.ClassificationError{
Exchange: e.Name,
OrderID: response.Data[x].OrderID,
Err: err,
}
}
b.Websocket.DataHandler <- &order.Detail{
e.Websocket.DataHandler <- &order.Detail{
Price: response.Data[x].Price,
Amount: response.Data[x].OrderQuantity,
Exchange: b.Name,
Exchange: e.Name,
OrderID: response.Data[x].OrderID,
AccountID: strconv.FormatInt(response.Data[x].Account, 10),
Type: oType,
@@ -354,14 +354,14 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
}
}
default:
b.Websocket.DataHandler <- fmt.Errorf("%s - Unsupported order update %+v", b.Name, response)
e.Websocket.DataHandler <- fmt.Errorf("%s - Unsupported order update %+v", e.Name, response)
}
case bitmexWSMargin:
var response WsMarginResponse
if err := json.Unmarshal(respRaw, &response); err != nil {
return err
}
b.Websocket.DataHandler <- response
e.Websocket.DataHandler <- response
case bitmexWSPosition:
var response WsPositionResponse
if err := json.Unmarshal(respRaw, &response); err != nil {
@@ -372,28 +372,28 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
if err := json.Unmarshal(respRaw, &response); err != nil {
return err
}
b.Websocket.DataHandler <- response
e.Websocket.DataHandler <- response
case bitmexWSTransact:
var response WsTransactResponse
if err := json.Unmarshal(respRaw, &response); err != nil {
return err
}
b.Websocket.DataHandler <- response
e.Websocket.DataHandler <- response
case bitmexWSWallet:
var response WsWalletResponse
if err := json.Unmarshal(respRaw, &response); err != nil {
return err
}
b.Websocket.DataHandler <- response
e.Websocket.DataHandler <- response
default:
b.Websocket.DataHandler <- websocket.UnhandledMessageWarning{Message: b.Name + websocket.UnhandledMessage + string(respRaw)}
e.Websocket.DataHandler <- websocket.UnhandledMessageWarning{Message: e.Name + websocket.UnhandledMessage + string(respRaw)}
}
return nil
}
// ProcessOrderbook processes orderbook updates
func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, p currency.Pair, a asset.Item) error {
func (e *Exchange) processOrderbook(data []OrderBookL2, action string, p currency.Pair, a asset.Item) error {
if len(data) < 1 {
return errors.New("no orderbook data")
}
@@ -424,17 +424,17 @@ func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, p currency.
book.Asks.Reverse() // Reverse asks for correct alignment
book.Asset = a
book.Pair = p
book.Exchange = b.Name
book.ValidateOrderbook = b.ValidateOrderbook
book.Exchange = e.Name
book.ValidateOrderbook = e.ValidateOrderbook
book.LastUpdated = data[0].Timestamp
err := b.Websocket.Orderbook.LoadSnapshot(&book)
err := e.Websocket.Orderbook.LoadSnapshot(&book)
if err != nil {
return fmt.Errorf("process orderbook error - %s",
err)
}
default:
updateAction, err := b.GetActionFromString(action)
updateAction, err := e.GetActionFromString(action)
if err != nil {
return err
}
@@ -454,7 +454,7 @@ func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, p currency.
bids = append(bids, nItem)
}
err = b.Websocket.Orderbook.Update(&orderbook.Update{
err = e.Websocket.Orderbook.Update(&orderbook.Update{
Bids: bids,
Asks: asks,
Pair: p,
@@ -469,8 +469,8 @@ func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, p currency.
return nil
}
func (b *Bitmex) handleWsTrades(msg []byte) error {
if !b.IsSaveTradeDataEnabled() {
func (e *Exchange) handleWsTrades(msg []byte) error {
if !e.IsSaveTradeDataEnabled() {
return nil
}
var tradeHolder TradeData
@@ -484,7 +484,7 @@ func (b *Bitmex) handleWsTrades(msg []byte) error {
// These have a size of 0 and are used only to indicate a changing price
continue
}
p, a, err := b.GetPairAndAssetTypeRequestFormatted(t.Symbol)
p, a, err := e.GetPairAndAssetTypeRequestFormatted(t.Symbol)
if err != nil {
return err
}
@@ -495,7 +495,7 @@ func (b *Bitmex) handleWsTrades(msg []byte) error {
trades = append(trades, trade.Data{
TID: t.TrdMatchID,
Exchange: b.Name,
Exchange: e.Name,
CurrencyPair: p,
AssetType: a,
Side: oSide,
@@ -504,40 +504,40 @@ func (b *Bitmex) handleWsTrades(msg []byte) error {
Timestamp: t.Timestamp,
})
}
return b.AddTradesToBuffer(trades...)
return e.AddTradesToBuffer(trades...)
}
// generateSubscriptions returns a list of subscriptions from the configured subscriptions feature
func (b *Bitmex) generateSubscriptions() (subscription.List, error) {
return b.Features.Subscriptions.ExpandTemplates(b)
func (e *Exchange) generateSubscriptions() (subscription.List, error) {
return e.Features.Subscriptions.ExpandTemplates(e)
}
// GetSubscriptionTemplate returns a subscription channel template
func (b *Bitmex) GetSubscriptionTemplate(_ *subscription.Subscription) (*template.Template, error) {
func (e *Exchange) GetSubscriptionTemplate(_ *subscription.Subscription) (*template.Template, error) {
return template.New("master.tmpl").Funcs(template.FuncMap{
"channelName": channelName,
}).Parse(subTplText)
}
// Subscribe subscribes to a websocket channel
func (b *Bitmex) Subscribe(subs subscription.List) error {
func (e *Exchange) Subscribe(subs subscription.List) error {
ctx := context.TODO()
return common.AppendError(
b.ParallelChanOp(ctx, subs.Public(), func(ctx context.Context, l subscription.List) error { return b.manageSubs(ctx, wsSubscribeOp, l) }, len(subs)),
b.ParallelChanOp(ctx, subs.Private(), func(ctx context.Context, l subscription.List) error { return b.manageSubs(ctx, wsSubscribeOp, l) }, len(subs)),
e.ParallelChanOp(ctx, subs.Public(), func(ctx context.Context, l subscription.List) error { return e.manageSubs(ctx, wsSubscribeOp, l) }, len(subs)),
e.ParallelChanOp(ctx, subs.Private(), func(ctx context.Context, l subscription.List) error { return e.manageSubs(ctx, wsSubscribeOp, l) }, len(subs)),
)
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
func (b *Bitmex) Unsubscribe(subs subscription.List) error {
func (e *Exchange) Unsubscribe(subs subscription.List) error {
ctx := context.TODO()
return common.AppendError(
b.ParallelChanOp(ctx, subs.Public(), func(ctx context.Context, l subscription.List) error { return b.manageSubs(ctx, wsUnsubscribeOp, l) }, len(subs)),
b.ParallelChanOp(ctx, subs.Private(), func(ctx context.Context, l subscription.List) error { return b.manageSubs(ctx, wsUnsubscribeOp, l) }, len(subs)),
e.ParallelChanOp(ctx, subs.Public(), func(ctx context.Context, l subscription.List) error { return e.manageSubs(ctx, wsUnsubscribeOp, l) }, len(subs)),
e.ParallelChanOp(ctx, subs.Private(), func(ctx context.Context, l subscription.List) error { return e.manageSubs(ctx, wsUnsubscribeOp, l) }, len(subs)),
)
}
func (b *Bitmex) manageSubs(ctx context.Context, op string, subs subscription.List) error {
func (e *Exchange) manageSubs(ctx context.Context, op string, subs subscription.List) error {
req := WebsocketRequest{
Command: op,
}
@@ -550,7 +550,7 @@ func (b *Bitmex) manageSubs(ctx context.Context, op string, subs subscription.Li
if err != nil {
return err
}
resps, errs := b.Websocket.Conn.SendMessageReturnResponses(ctx, request.Unset, string(reqJSON), req, len(subs))
resps, errs := e.Websocket.Conn.SendMessageReturnResponses(ctx, request.Unset, string(reqJSON), req, len(subs))
for _, resp := range resps {
if errMsg, _ := jsonparser.GetString(resp, "error"); errMsg != "" {
errs = common.AppendError(errs, errors.New(errMsg))
@@ -564,9 +564,9 @@ func (b *Bitmex) manageSubs(ctx context.Context, op string, subs subscription.Li
errs = common.AppendError(errs, fmt.Errorf("%w: %s", subscription.ErrNotFound, chanName))
} else {
if op == wsSubscribeOp {
errs = common.AppendError(errs, b.Websocket.AddSuccessfulSubscriptions(b.Websocket.Conn, s))
errs = common.AppendError(errs, e.Websocket.AddSuccessfulSubscriptions(e.Websocket.Conn, s))
} else {
errs = common.AppendError(errs, b.Websocket.RemoveSubscriptions(b.Websocket.Conn, s))
errs = common.AppendError(errs, e.Websocket.RemoveSubscriptions(e.Websocket.Conn, s))
}
}
}
@@ -575,8 +575,8 @@ func (b *Bitmex) manageSubs(ctx context.Context, op string, subs subscription.Li
}
// WebsocketSendAuth sends an authenticated subscription
func (b *Bitmex) websocketSendAuth(ctx context.Context) error {
creds, err := b.GetCredentials(ctx)
func (e *Exchange) websocketSendAuth(ctx context.Context) error {
creds, err := e.GetCredentials(ctx)
if err != nil {
return err
}
@@ -593,21 +593,21 @@ func (b *Bitmex) websocketSendAuth(ctx context.Context) error {
Arguments: []any{creds.Key, timestamp, hex.EncodeToString(hmac)},
}
resp, err := b.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.Command, req)
resp, err := e.Websocket.Conn.SendMessageReturnResponse(ctx, request.Unset, req.Command, req)
if err != nil {
return err
}
if errMsg, _ := jsonparser.GetString(resp, "error"); errMsg != "" {
return errors.New(errMsg)
}
if b.Verbose {
log.Debugf(log.ExchangeSys, "%s websocket: Successfully authenticated websocket connection", b.Name)
if e.Verbose {
log.Debugf(log.ExchangeSys, "%s websocket: Successfully authenticated websocket connection", e.Name)
}
return nil
}
// GetActionFromString matches a string action to an internal action.
func (b *Bitmex) GetActionFromString(s string) (orderbook.ActionType, error) {
func (e *Exchange) GetActionFromString(s string) (orderbook.ActionType, error) {
switch s {
case "update":
return orderbook.UpdateAction, nil

View File

@@ -34,12 +34,12 @@ import (
)
// SetDefaults sets the basic defaults for Bitmex
func (b *Bitmex) SetDefaults() {
b.Name = "Bitmex"
b.Enabled = true
b.Verbose = true
b.API.CredentialsValidator.RequiresKey = true
b.API.CredentialsValidator.RequiresSecret = true
func (e *Exchange) SetDefaults() {
e.Name = "Bitmex"
e.Enabled = true
e.Verbose = true
e.API.CredentialsValidator.RequiresKey = true
e.API.CredentialsValidator.RequiresSecret = true
for _, a := range []asset.Item{asset.Spot, asset.PerpetualContract, asset.Futures, asset.Index} {
ps := currency.PairStore{
@@ -50,16 +50,16 @@ func (b *Bitmex) SetDefaults() {
if a == asset.Spot {
ps.RequestFormat.Delimiter = currency.UnderscoreDelimiter
}
if err := b.SetAssetPairStore(a, ps); err != nil {
log.Errorf(log.ExchangeSys, "%s error storing %q default asset formats: %s", b.Name, a, err)
if err := e.SetAssetPairStore(a, ps); err != nil {
log.Errorf(log.ExchangeSys, "%s error storing %q default asset formats: %s", e.Name, a, err)
}
}
if err := b.DisableAssetWebsocketSupport(asset.Index); err != nil {
log.Errorf(log.ExchangeSys, "%s error disabling %q asset type websocket support: %s", b.Name, asset.Index, err)
if err := e.DisableAssetWebsocketSupport(asset.Index); err != nil {
log.Errorf(log.ExchangeSys, "%s error disabling %q asset type websocket support: %s", e.Name, asset.Index, err)
}
b.Features = exchange.Features{
e.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
REST: true,
Websocket: true,
@@ -124,60 +124,60 @@ func (b *Bitmex) SetDefaults() {
}
var err error
b.Requester, err = request.New(b.Name,
e.Requester, err = request.New(e.Name,
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
request.WithLimiter(GetRateLimit()))
if err != nil {
log.Errorln(log.ExchangeSys, err)
}
b.API.Endpoints = b.NewEndpoints()
err = b.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
e.API.Endpoints = e.NewEndpoints()
err = e.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
exchange.RestSpot: bitmexAPIURL,
exchange.WebsocketSpot: bitmexWSURL,
})
if err != nil {
log.Errorln(log.ExchangeSys, err)
}
b.Websocket = websocket.NewManager()
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
b.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
e.Websocket = websocket.NewManager()
e.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
e.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
e.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
}
// Setup takes in the supplied exchange configuration details and sets params
func (b *Bitmex) Setup(exch *config.Exchange) error {
func (e *Exchange) Setup(exch *config.Exchange) error {
err := exch.Validate()
if err != nil {
return err
}
if !exch.Enabled {
b.SetEnabled(false)
e.SetEnabled(false)
return nil
}
err = b.SetupDefaults(exch)
err = e.SetupDefaults(exch)
if err != nil {
return err
}
wsEndpoint, err := b.API.Endpoints.GetURL(exchange.WebsocketSpot)
wsEndpoint, err := e.API.Endpoints.GetURL(exchange.WebsocketSpot)
if err != nil {
return err
}
err = b.Websocket.Setup(&websocket.ManagerSetup{
err = e.Websocket.Setup(&websocket.ManagerSetup{
ExchangeConfig: exch,
DefaultURL: bitmexWSURL,
RunningURL: wsEndpoint,
Connector: b.WsConnect,
Subscriber: b.Subscribe,
Unsubscriber: b.Unsubscribe,
GenerateSubscriptions: b.generateSubscriptions,
Features: &b.Features.Supports.WebsocketCapabilities,
Connector: e.WsConnect,
Subscriber: e.Subscribe,
Unsubscriber: e.Unsubscribe,
GenerateSubscriptions: e.generateSubscriptions,
Features: &e.Features.Supports.WebsocketCapabilities,
})
if err != nil {
return err
}
return b.Websocket.SetupNewConnection(&websocket.ConnectionSetup{
return e.Websocket.SetupNewConnection(&websocket.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
URL: wsEndpoint,
@@ -185,8 +185,8 @@ func (b *Bitmex) Setup(exch *config.Exchange) error {
}
// FetchTradablePairs returns a list of the exchanges tradable pairs
func (b *Bitmex) FetchTradablePairs(ctx context.Context, a asset.Item) (currency.Pairs, error) {
marketInfo, err := b.GetActiveAndIndexInstruments(ctx)
func (e *Exchange) FetchTradablePairs(ctx context.Context, a asset.Item) (currency.Pairs, error) {
marketInfo, err := e.GetActiveAndIndexInstruments(ctx)
if err != nil {
return nil, err
}
@@ -215,7 +215,7 @@ func (b *Bitmex) FetchTradablePairs(ctx context.Context, a asset.Item) (currency
settlement := strings.Split(marketInfo[x].Symbol, currency.UnderscoreDelimiter)
if len(settlement) != 2 {
log.Warnf(log.ExchangeSys, "%s currency %s %s cannot be added to tradable pairs",
b.Name,
e.Name,
marketInfo[x].Symbol,
a)
break
@@ -234,7 +234,7 @@ func (b *Bitmex) FetchTradablePairs(ctx context.Context, a asset.Item) (currency
isolate := strings.Split(marketInfo[x].Symbol, currency.UnderscoreDelimiter)
if len(isolate[0]) < 3 {
log.Warnf(log.ExchangeSys, "%s currency %s %s be cannot added to tradable pairs",
b.Name,
e.Name,
marketInfo[x].Symbol,
a)
break
@@ -275,29 +275,29 @@ func (b *Bitmex) FetchTradablePairs(ctx context.Context, a asset.Item) (currency
// UpdateTradablePairs updates the exchanges available pairs and stores
// them in the exchanges config
func (b *Bitmex) UpdateTradablePairs(ctx context.Context, _ bool) error {
assets := b.GetAssetTypes(false)
func (e *Exchange) UpdateTradablePairs(ctx context.Context, _ bool) error {
assets := e.GetAssetTypes(false)
for x := range assets {
pairs, err := b.FetchTradablePairs(ctx, assets[x])
pairs, err := e.FetchTradablePairs(ctx, assets[x])
if err != nil {
return err
}
err = b.UpdatePairs(pairs, assets[x], false, false)
err = e.UpdatePairs(pairs, assets[x], false, false)
if err != nil {
return err
}
}
return b.EnsureOnePairEnabled()
return e.EnsureOnePairEnabled()
}
// UpdateTickers updates the ticker for all currency pairs of a given asset type
func (b *Bitmex) UpdateTickers(ctx context.Context, a asset.Item) error {
if !b.SupportsAsset(a) {
func (e *Exchange) UpdateTickers(ctx context.Context, a asset.Item) error {
if !e.SupportsAsset(a) {
return fmt.Errorf("%w for [%v]", asset.ErrNotSupported, a)
}
tick, err := b.GetActiveAndIndexInstruments(ctx)
tick, err := e.GetActiveAndIndexInstruments(ctx)
if err != nil {
return err
}
@@ -311,7 +311,7 @@ instruments:
if tick[j].Typ != futuresID {
continue instruments
}
pair, enabled, err = b.MatchSymbolCheckEnabled(tick[j].Symbol, a, false)
pair, enabled, err = e.MatchSymbolCheckEnabled(tick[j].Symbol, a, false)
case asset.Index:
switch tick[j].Typ {
case bitMEXBasketIndexID,
@@ -326,18 +326,18 @@ instruments:
// contain an underscore. Calling DeriveFrom will then error and
// the instruments will be missed.
tick[j].Symbol = strings.Replace(tick[j].Symbol, currency.UnderscoreDelimiter, "", 1)
pair, enabled, err = b.MatchSymbolCheckEnabled(tick[j].Symbol, a, false)
pair, enabled, err = e.MatchSymbolCheckEnabled(tick[j].Symbol, a, false)
case asset.PerpetualContract:
if tick[j].Typ != perpetualContractID {
continue instruments
}
pair, enabled, err = b.MatchSymbolCheckEnabled(tick[j].Symbol, a, false)
pair, enabled, err = e.MatchSymbolCheckEnabled(tick[j].Symbol, a, false)
case asset.Spot:
if tick[j].Typ != spotID {
continue instruments
}
tick[j].Symbol = strings.Replace(tick[j].Symbol, currency.UnderscoreDelimiter, "", 1)
pair, enabled, err = b.MatchSymbolCheckEnabled(tick[j].Symbol, a, false)
pair, enabled, err = e.MatchSymbolCheckEnabled(tick[j].Symbol, a, false)
}
if err != nil && !errors.Is(err, currency.ErrPairNotFound) {
@@ -357,7 +357,7 @@ instruments:
Close: tick[j].PrevClosePrice,
Pair: pair,
LastUpdated: tick[j].Timestamp,
ExchangeName: b.Name,
ExchangeName: e.Name,
OpenInterest: tick[j].OpenInterest,
AssetType: a,
})
@@ -369,44 +369,44 @@ instruments:
}
// UpdateTicker updates and returns the ticker for a currency pair
func (b *Bitmex) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
if err := b.UpdateTickers(ctx, a); err != nil {
func (e *Exchange) UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error) {
if err := e.UpdateTickers(ctx, a); err != nil {
return nil, err
}
fPair, err := b.FormatExchangeCurrency(p, a)
fPair, err := e.FormatExchangeCurrency(p, a)
if err != nil {
return nil, err
}
return ticker.GetTicker(b.Name, fPair, a)
return ticker.GetTicker(e.Name, fPair, a)
}
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (b *Bitmex) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType asset.Item) (*orderbook.Book, error) {
func (e *Exchange) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType asset.Item) (*orderbook.Book, error) {
if p.IsEmpty() {
return nil, currency.ErrCurrencyPairEmpty
}
if err := b.CurrencyPairs.IsAssetEnabled(assetType); err != nil {
if err := e.CurrencyPairs.IsAssetEnabled(assetType); err != nil {
return nil, err
}
book := &orderbook.Book{
Exchange: b.Name,
Exchange: e.Name,
Pair: p,
Asset: assetType,
ValidateOrderbook: b.ValidateOrderbook,
ValidateOrderbook: e.ValidateOrderbook,
}
if assetType == asset.Index {
return book, common.ErrFunctionNotSupported
}
fPair, err := b.FormatExchangeCurrency(p, assetType)
fPair, err := e.FormatExchangeCurrency(p, assetType)
if err != nil {
return book, err
}
orderbookNew, err := b.GetOrderbook(ctx,
orderbookNew, err := e.GetOrderbook(ctx,
OrderBookGetL2Params{
Symbol: fPair.String(),
Depth: 500,
@@ -441,15 +441,15 @@ func (b *Bitmex) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType
if err != nil {
return book, err
}
return orderbook.Get(b.Name, p, assetType)
return orderbook.Get(e.Name, p, assetType)
}
// UpdateAccountInfo retrieves balances for all enabled currencies for the
// Bitmex exchange
func (b *Bitmex) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (account.Holdings, error) {
func (e *Exchange) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (account.Holdings, error) {
var info account.Holdings
userMargins, err := b.GetAllUserMargin(ctx)
userMargins, err := e.GetAllUserMargin(ctx)
if err != nil {
return info, err
}
@@ -460,7 +460,7 @@ func (b *Bitmex) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
accountID := strconv.FormatInt(userMargins[i].Account, 10)
var wallet WalletInfo
wallet, err = b.GetWalletInfo(ctx, userMargins[i].Currency)
wallet, err = e.GetWalletInfo(ctx, userMargins[i].Currency)
if err != nil {
continue
}
@@ -476,9 +476,9 @@ func (b *Bitmex) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
if info.Accounts, err = account.CollectBalances(accountBalances, assetType); err != nil {
return account.Holdings{}, err
}
info.Exchange = b.Name
info.Exchange = e.Name
creds, err := b.GetCredentials(ctx)
creds, err := e.GetCredentials(ctx)
if err != nil {
return account.Holdings{}, err
}
@@ -491,15 +491,15 @@ func (b *Bitmex) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (a
// GetAccountFundingHistory returns funding history, deposits and
// withdrawals
func (b *Bitmex) GetAccountFundingHistory(ctx context.Context) ([]exchange.FundingHistory, error) {
history, err := b.GetWalletHistory(ctx, "all")
func (e *Exchange) GetAccountFundingHistory(ctx context.Context) ([]exchange.FundingHistory, error) {
history, err := e.GetWalletHistory(ctx, "all")
if err != nil {
return nil, err
}
resp := make([]exchange.FundingHistory, len(history))
for i := range history {
resp[i] = exchange.FundingHistory{
ExchangeName: b.Name,
ExchangeName: e.Name,
Status: history[i].TransactStatus,
Timestamp: history[i].Timestamp,
Currency: history[i].Currency,
@@ -515,8 +515,8 @@ func (b *Bitmex) GetAccountFundingHistory(ctx context.Context) ([]exchange.Fundi
}
// GetWithdrawalsHistory returns previous withdrawals data
func (b *Bitmex) GetWithdrawalsHistory(ctx context.Context, c currency.Code, _ asset.Item) ([]exchange.WithdrawalHistory, error) {
history, err := b.GetWalletHistory(ctx, c.String())
func (e *Exchange) GetWithdrawalsHistory(ctx context.Context, c currency.Code, _ asset.Item) ([]exchange.WithdrawalHistory, error) {
history, err := e.GetWalletHistory(ctx, c.String())
if err != nil {
return nil, err
}
@@ -538,17 +538,17 @@ func (b *Bitmex) GetWithdrawalsHistory(ctx context.Context, c currency.Code, _ a
}
// GetServerTime returns the current exchange server time.
func (b *Bitmex) GetServerTime(_ context.Context, _ asset.Item) (time.Time, error) {
func (e *Exchange) GetServerTime(_ context.Context, _ asset.Item) (time.Time, error) {
return time.Time{}, common.ErrFunctionNotSupported
}
// GetRecentTrades returns the most recent trades for a currency and asset
func (b *Bitmex) GetRecentTrades(ctx context.Context, p currency.Pair, assetType asset.Item) ([]trade.Data, error) {
return b.GetHistoricTrades(ctx, p, assetType, time.Now().Add(-time.Minute*15), time.Now())
func (e *Exchange) GetRecentTrades(ctx context.Context, p currency.Pair, assetType asset.Item) ([]trade.Data, error) {
return e.GetHistoricTrades(ctx, p, assetType, time.Now().Add(-time.Minute*15), time.Now())
}
// GetHistoricTrades returns historic trade data within the timeframe provided
func (b *Bitmex) GetHistoricTrades(ctx context.Context, p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) {
func (e *Exchange) GetHistoricTrades(ctx context.Context, p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) {
if assetType == asset.Index {
return nil, fmt.Errorf("%w %v", asset.ErrNotSupported, assetType)
}
@@ -556,7 +556,7 @@ func (b *Bitmex) GetHistoricTrades(ctx context.Context, p currency.Pair, assetTy
return nil, fmt.Errorf("invalid time range supplied. Start: %v End %v %w", timestampStart, timestampEnd, err)
}
var err error
p, err = b.FormatExchangeCurrency(p, assetType)
p, err = e.FormatExchangeCurrency(p, assetType)
if err != nil {
return nil, err
}
@@ -572,7 +572,7 @@ allTrades:
for {
req.StartTime = ts.UTC().Format("2006-01-02T15:04:05.000Z")
var tradeData []Trade
tradeData, err = b.GetTrade(ctx, req)
tradeData, err = e.GetTrade(ctx, req)
if err != nil {
return nil, err
}
@@ -591,7 +591,7 @@ allTrades:
continue
}
resp = append(resp, trade.Data{
Exchange: b.Name,
Exchange: e.Name,
CurrencyPair: p,
AssetType: assetType,
Side: side,
@@ -612,7 +612,7 @@ allTrades:
break allTrades
}
}
err = b.AddTradesToBuffer(resp...)
err = e.AddTradesToBuffer(resp...)
if err != nil {
return nil, err
}
@@ -622,8 +622,8 @@ allTrades:
}
// SubmitOrder submits a new order
func (b *Bitmex) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitResponse, error) {
if err := s.Validate(b.GetTradingRequirements()); err != nil {
func (e *Exchange) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitResponse, error) {
if err := s.Validate(e.GetTradingRequirements()); err != nil {
return nil, err
}
@@ -632,7 +632,7 @@ func (b *Bitmex) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Submi
errors.New("order contract amount can not have decimals")
}
fPair, err := b.FormatExchangeCurrency(s.Pair, s.AssetType)
fPair, err := e.FormatExchangeCurrency(s.Pair, s.AssetType)
if err != nil {
return nil, err
}
@@ -648,7 +648,7 @@ func (b *Bitmex) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Submi
orderNewParams.Price = s.Price
}
response, err := b.CreateOrder(ctx, &orderNewParams)
response, err := e.CreateOrder(ctx, &orderNewParams)
if err != nil {
return nil, err
}
@@ -657,7 +657,7 @@ func (b *Bitmex) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Submi
// ModifyOrder will allow of changing orderbook placement and limit to
// market conversion
func (b *Bitmex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) {
func (e *Exchange) ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) {
if err := action.Validate(); err != nil {
return nil, err
}
@@ -666,7 +666,7 @@ func (b *Bitmex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.
return nil, errors.New("contract amount can not have decimals")
}
o, err := b.AmendOrder(ctx, &OrderAmendParams{
o, err := e.AmendOrder(ctx, &OrderAmendParams{
OrderID: action.OrderID,
OrderQty: int32(action.Amount),
Price: action.Price,
@@ -687,18 +687,18 @@ func (b *Bitmex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.
}
// CancelOrder cancels an order by its corresponding ID number
func (b *Bitmex) CancelOrder(ctx context.Context, o *order.Cancel) error {
func (e *Exchange) CancelOrder(ctx context.Context, o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
_, err := b.CancelOrders(ctx, &OrderCancelParams{
_, err := e.CancelOrders(ctx, &OrderCancelParams{
OrderID: o.OrderID,
})
return err
}
// CancelBatchOrders cancels an orders by their corresponding ID numbers
func (b *Bitmex) CancelBatchOrders(ctx context.Context, o []order.Cancel) (*order.CancelBatchResponse, error) {
func (e *Exchange) CancelBatchOrders(ctx context.Context, o []order.Cancel) (*order.CancelBatchResponse, error) {
if len(o) == 0 {
return nil, order.ErrCancelOrderIsNil
}
@@ -722,7 +722,7 @@ func (b *Bitmex) CancelBatchOrders(ctx context.Context, o []order.Cancel) (*orde
resp := &order.CancelBatchResponse{
Status: make(map[string]string),
}
cancelResponse, err := b.CancelOrders(ctx, params)
cancelResponse, err := e.CancelOrders(ctx, params)
if err != nil {
return nil, err
}
@@ -733,12 +733,12 @@ func (b *Bitmex) CancelBatchOrders(ctx context.Context, o []order.Cancel) (*orde
}
// CancelAllOrders cancels all orders associated with a currency pair
func (b *Bitmex) CancelAllOrders(ctx context.Context, _ *order.Cancel) (order.CancelAllResponse, error) {
func (e *Exchange) CancelAllOrders(ctx context.Context, _ *order.Cancel) (order.CancelAllResponse, error) {
cancelAllOrdersResponse := order.CancelAllResponse{
Status: make(map[string]string),
}
var emptyParams OrderCancelAllParams
orders, err := b.CancelAllExistingOrders(ctx, emptyParams)
orders, err := e.CancelAllExistingOrders(ctx, emptyParams)
if err != nil {
return cancelAllOrdersResponse, err
}
@@ -753,15 +753,15 @@ func (b *Bitmex) CancelAllOrders(ctx context.Context, _ *order.Cancel) (order.Ca
}
// GetOrderInfo returns order information based on order ID
func (b *Bitmex) GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, assetType asset.Item) (*order.Detail, error) {
func (e *Exchange) GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, assetType asset.Item) (*order.Detail, error) {
if pair.IsEmpty() {
return nil, currency.ErrCurrencyPairEmpty
}
if err := b.CurrencyPairs.IsAssetEnabled(assetType); err != nil {
if err := e.CurrencyPairs.IsAssetEnabled(assetType); err != nil {
return nil, err
}
resp, err := b.GetOrders(ctx, &OrdersRequest{
resp, err := e.GetOrders(ctx, &OrdersRequest{
Filter: `{"orderID":"` + orderID + `"}`,
})
if err != nil {
@@ -777,7 +777,7 @@ func (b *Bitmex) GetOrderInfo(ctx context.Context, orderID string, pair currency
return nil, err
}
var oType order.Type
oType, err = b.getOrderType(resp[i].OrdType)
oType, err = e.getOrderType(resp[i].OrdType)
if err != nil {
return nil, err
}
@@ -787,7 +787,7 @@ func (b *Bitmex) GetOrderInfo(ctx context.Context, orderID string, pair currency
Amount: resp[i].OrderQty,
ExecutedAmount: resp[i].CumQty,
RemainingAmount: resp[i].LeavesQty,
Exchange: b.Name,
Exchange: e.Name,
OrderID: resp[i].OrderID,
Side: orderSideMap[resp[i].Side],
Status: orderStatus,
@@ -800,8 +800,8 @@ func (b *Bitmex) GetOrderInfo(ctx context.Context, orderID string, pair currency
}
// GetDepositAddress returns a deposit address for a specified currency
func (b *Bitmex) GetDepositAddress(ctx context.Context, cryptocurrency currency.Code, _, _ string) (*deposit.Address, error) {
resp, err := b.GetCryptoDepositAddress(ctx, cryptocurrency.String())
func (e *Exchange) GetDepositAddress(ctx context.Context, cryptocurrency currency.Code, _, _ string) (*deposit.Address, error) {
resp, err := e.GetCryptoDepositAddress(ctx, cryptocurrency.String())
if err != nil {
return nil, err
}
@@ -812,7 +812,7 @@ func (b *Bitmex) GetDepositAddress(ctx context.Context, cryptocurrency currency.
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (b *Bitmex) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
func (e *Exchange) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
@@ -826,7 +826,7 @@ func (b *Bitmex) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawReques
r.Fee = withdrawRequest.Crypto.FeeAmount
}
resp, err := b.UserRequestWithdrawal(ctx, r)
resp, err := e.UserRequestWithdrawal(ctx, r)
if err != nil {
return nil, err
}
@@ -839,31 +839,31 @@ func (b *Bitmex) WithdrawCryptocurrencyFunds(ctx context.Context, withdrawReques
// WithdrawFiatFunds returns a withdrawal ID when a withdrawal is
// submitted
func (b *Bitmex) WithdrawFiatFunds(_ context.Context, _ *withdraw.Request) (*withdraw.ExchangeResponse, error) {
func (e *Exchange) WithdrawFiatFunds(_ context.Context, _ *withdraw.Request) (*withdraw.ExchangeResponse, error) {
return nil, common.ErrFunctionNotSupported
}
// WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a withdrawal is
// submitted
func (b *Bitmex) WithdrawFiatFundsToInternationalBank(_ context.Context, _ *withdraw.Request) (*withdraw.ExchangeResponse, error) {
func (e *Exchange) WithdrawFiatFundsToInternationalBank(_ context.Context, _ *withdraw.Request) (*withdraw.ExchangeResponse, error) {
return nil, common.ErrFunctionNotSupported
}
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bitmex) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilder) (float64, error) {
func (e *Exchange) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilder) (float64, error) {
if feeBuilder == nil {
return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer)
}
if !b.AreCredentialsValid(ctx) && // Todo check connection status
if !e.AreCredentialsValid(ctx) && // Todo check connection status
feeBuilder.FeeType == exchange.CryptocurrencyTradeFee {
feeBuilder.FeeType = exchange.OfflineTradeFee
}
return b.GetFee(feeBuilder)
return e.GetFee(feeBuilder)
}
// GetActiveOrders retrieves any orders that are active/open
// This function is not concurrency safe due to orderSide/orderType maps
func (b *Bitmex) GetActiveOrders(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
func (e *Exchange) GetActiveOrders(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
err := req.Validate()
if err != nil {
return nil, err
@@ -872,12 +872,12 @@ func (b *Bitmex) GetActiveOrders(ctx context.Context, req *order.MultiOrderReque
params := OrdersRequest{
Filter: "{\"open\":true}",
}
resp, err := b.GetOrders(ctx, &params)
resp, err := e.GetOrders(ctx, &params)
if err != nil {
return nil, err
}
format, err := b.GetPairFormat(asset.PerpetualContract, false)
format, err := e.GetPairFormat(asset.PerpetualContract, false)
if err != nil {
return nil, err
}
@@ -887,12 +887,12 @@ func (b *Bitmex) GetActiveOrders(ctx context.Context, req *order.MultiOrderReque
var orderStatus order.Status
orderStatus, err = order.StringToOrderStatus(resp[i].OrdStatus)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
log.Errorf(log.ExchangeSys, "%s %v", e.Name, err)
}
var oType order.Type
oType, err = b.getOrderType(resp[i].OrdType)
oType, err = e.getOrderType(resp[i].OrdType)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
log.Errorf(log.ExchangeSys, "%s %v", e.Name, err)
}
orderDetail := order.Detail{
Date: resp[i].Timestamp,
@@ -900,7 +900,7 @@ func (b *Bitmex) GetActiveOrders(ctx context.Context, req *order.MultiOrderReque
Amount: resp[i].OrderQty,
ExecutedAmount: resp[i].CumQty,
RemainingAmount: resp[i].LeavesQty,
Exchange: b.Name,
Exchange: e.Name,
OrderID: resp[i].OrderID,
Side: orderSideMap[resp[i].Side],
Status: orderStatus,
@@ -912,25 +912,25 @@ func (b *Bitmex) GetActiveOrders(ctx context.Context, req *order.MultiOrderReque
orders[i] = orderDetail
}
return req.Filter(b.Name, orders), nil
return req.Filter(e.Name, orders), nil
}
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
// This function is not concurrency safe due to orderSide/orderType maps
func (b *Bitmex) GetOrderHistory(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
func (e *Exchange) GetOrderHistory(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
err := req.Validate()
if err != nil {
return nil, err
}
params := OrdersRequest{}
resp, err := b.GetOrders(ctx, &params)
resp, err := e.GetOrders(ctx, &params)
if err != nil {
return nil, err
}
format, err := b.GetPairFormat(asset.PerpetualContract, false)
format, err := e.GetPairFormat(asset.PerpetualContract, false)
if err != nil {
return nil, err
}
@@ -941,15 +941,15 @@ func (b *Bitmex) GetOrderHistory(ctx context.Context, req *order.MultiOrderReque
var orderStatus order.Status
orderStatus, err = order.StringToOrderStatus(resp[i].OrdStatus)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
log.Errorf(log.ExchangeSys, "%s %v", e.Name, err)
}
pair := currency.NewPairWithDelimiter(resp[i].Symbol, resp[i].SettlCurrency, format.Delimiter)
var oType order.Type
oType, err = b.getOrderType(resp[i].OrdType)
oType, err = e.getOrderType(resp[i].OrdType)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
log.Errorf(log.ExchangeSys, "%s %v", e.Name, err)
}
orderDetail := order.Detail{
@@ -960,7 +960,7 @@ func (b *Bitmex) GetOrderHistory(ctx context.Context, req *order.MultiOrderReque
RemainingAmount: resp[i].LeavesQty,
Date: resp[i].TransactTime,
CloseTime: resp[i].Timestamp,
Exchange: b.Name,
Exchange: e.Name,
OrderID: resp[i].OrderID,
Side: orderSide,
Status: orderStatus,
@@ -971,33 +971,33 @@ func (b *Bitmex) GetOrderHistory(ctx context.Context, req *order.MultiOrderReque
orders[i] = orderDetail
}
return req.Filter(b.Name, orders), nil
return req.Filter(e.Name, orders), nil
}
// AuthenticateWebsocket sends an authentication message to the websocket
func (b *Bitmex) AuthenticateWebsocket(ctx context.Context) error {
return b.websocketSendAuth(ctx)
func (e *Exchange) AuthenticateWebsocket(ctx context.Context) error {
return e.websocketSendAuth(ctx)
}
// ValidateAPICredentials validates current credentials used for wrapper
// functionality
func (b *Bitmex) ValidateAPICredentials(ctx context.Context, assetType asset.Item) error {
_, err := b.UpdateAccountInfo(ctx, assetType)
return b.CheckTransientError(err)
func (e *Exchange) ValidateAPICredentials(ctx context.Context, assetType asset.Item) error {
_, err := e.UpdateAccountInfo(ctx, assetType)
return e.CheckTransientError(err)
}
// GetHistoricCandles returns candles between a time period for a set time interval
func (b *Bitmex) GetHistoricCandles(_ context.Context, _ currency.Pair, _ asset.Item, _ kline.Interval, _, _ time.Time) (*kline.Item, error) {
func (e *Exchange) GetHistoricCandles(_ context.Context, _ currency.Pair, _ asset.Item, _ kline.Interval, _, _ time.Time) (*kline.Item, error) {
return nil, common.ErrFunctionNotSupported
}
// GetHistoricCandlesExtended returns candles between a time period for a set time interval
func (b *Bitmex) GetHistoricCandlesExtended(_ context.Context, _ currency.Pair, _ asset.Item, _ kline.Interval, _, _ time.Time) (*kline.Item, error) {
func (e *Exchange) GetHistoricCandlesExtended(_ context.Context, _ currency.Pair, _ asset.Item, _ kline.Interval, _, _ time.Time) (*kline.Item, error) {
return nil, common.ErrFunctionNotSupported
}
// getOrderType derives an order type from bitmex int representation
func (b *Bitmex) getOrderType(id int64) (order.Type, error) {
func (e *Exchange) getOrderType(id int64) (order.Type, error) {
o, ok := orderTypeMap[id]
if !ok {
return order.UnknownType, fmt.Errorf("unhandled order type for '%d': %w", id, order.ErrTypeIsInvalid)
@@ -1006,15 +1006,15 @@ func (b *Bitmex) getOrderType(id int64) (order.Type, error) {
}
// GetFuturesContractDetails returns details about futures contracts
func (b *Bitmex) GetFuturesContractDetails(ctx context.Context, item asset.Item) ([]futures.Contract, error) {
func (e *Exchange) GetFuturesContractDetails(ctx context.Context, item asset.Item) ([]futures.Contract, error) {
if !item.IsFutures() {
return nil, futures.ErrNotFuturesAsset
}
if !b.SupportsAsset(item) || item == asset.Index {
if !e.SupportsAsset(item) || item == asset.Index {
return nil, fmt.Errorf("%w %v", asset.ErrNotSupported, item)
}
marketInfo, err := b.GetInstruments(ctx, &GenericRequestParams{Reverse: true, Count: 500})
marketInfo, err := e.GetInstruments(ctx, &GenericRequestParams{Reverse: true, Count: 500})
if err != nil {
return nil, err
}
@@ -1052,7 +1052,7 @@ func (b *Bitmex) GetFuturesContractDetails(ctx context.Context, item asset.Item)
contractSettlementType = futures.Inverse
}
resp = append(resp, futures.Contract{
Exchange: b.Name,
Exchange: e.Name,
Name: cp,
Underlying: underlying,
Asset: item,
@@ -1083,21 +1083,21 @@ func (b *Bitmex) GetFuturesContractDetails(ctx context.Context, item asset.Item)
if err != nil {
return nil, err
}
var s, e time.Time
var startTime, endTime time.Time
if marketInfo[x].Front != "" {
s, err = time.Parse(time.RFC3339, marketInfo[x].Front)
startTime, err = time.Parse(time.RFC3339, marketInfo[x].Front)
if err != nil {
return nil, err
}
}
if marketInfo[x].Expiry != "" {
e, err = time.Parse(time.RFC3339, marketInfo[x].Expiry)
endTime, err = time.Parse(time.RFC3339, marketInfo[x].Expiry)
if err != nil {
return nil, err
}
}
var ct futures.ContractType
contractDuration := e.Sub(s)
contractDuration := endTime.Sub(startTime)
switch {
case contractDuration <= kline.OneWeek.Duration()+kline.ThreeDay.Duration():
ct = futures.Weekly
@@ -1122,12 +1122,12 @@ func (b *Bitmex) GetFuturesContractDetails(ctx context.Context, item asset.Item)
contractSettlementType = futures.Quanto
}
resp = append(resp, futures.Contract{
Exchange: b.Name,
Exchange: e.Name,
Name: cp,
Underlying: underlying,
Asset: item,
StartDate: s,
EndDate: e,
StartDate: startTime,
EndDate: endTime,
IsActive: marketInfo[x].State == "Open",
Status: marketInfo[x].State,
Type: ct,
@@ -1141,7 +1141,7 @@ func (b *Bitmex) GetFuturesContractDetails(ctx context.Context, item asset.Item)
}
// GetLatestFundingRates returns the latest funding rates data
func (b *Bitmex) GetLatestFundingRates(ctx context.Context, r *fundingrate.LatestRateRequest) ([]fundingrate.LatestRateResponse, error) {
func (e *Exchange) GetLatestFundingRates(ctx context.Context, r *fundingrate.LatestRateRequest) ([]fundingrate.LatestRateResponse, error) {
if r == nil {
return nil, fmt.Errorf("%w LatestRateRequest", common.ErrNilPointer)
}
@@ -1154,7 +1154,7 @@ func (b *Bitmex) GetLatestFundingRates(ctx context.Context, r *fundingrate.Lates
if r.Pair.IsEmpty() {
count = "500"
} else {
isPerp, err := b.IsPerpetualFutureCurrency(r.Asset, r.Pair)
isPerp, err := e.IsPerpetualFutureCurrency(r.Asset, r.Pair)
if err != nil {
return nil, err
}
@@ -1163,12 +1163,12 @@ func (b *Bitmex) GetLatestFundingRates(ctx context.Context, r *fundingrate.Lates
}
}
format, err := b.GetPairFormat(r.Asset, true)
format, err := e.GetPairFormat(r.Asset, true)
if err != nil {
return nil, err
}
fPair := format.Format(r.Pair)
rates, err := b.GetFullFundingHistory(ctx, fPair, count, "", "", "", true, time.Time{}, time.Time{})
rates, err := e.GetFullFundingHistory(ctx, fPair, count, "", "", "", true, time.Time{}, time.Time{})
if err != nil {
return nil, err
}
@@ -1188,7 +1188,7 @@ func (b *Bitmex) GetLatestFundingRates(ctx context.Context, r *fundingrate.Lates
}
var cp currency.Pair
var isEnabled bool
cp, isEnabled, err = b.MatchSymbolCheckEnabled(rates[i].Symbol, r.Asset, false)
cp, isEnabled, err = e.MatchSymbolCheckEnabled(rates[i].Symbol, r.Asset, false)
if err != nil && !errors.Is(err, currency.ErrPairNotFound) {
return nil, err
}
@@ -1196,7 +1196,7 @@ func (b *Bitmex) GetLatestFundingRates(ctx context.Context, r *fundingrate.Lates
continue
}
var isPerp bool
isPerp, err = b.IsPerpetualFutureCurrency(r.Asset, cp)
isPerp, err = e.IsPerpetualFutureCurrency(r.Asset, cp)
if err != nil {
return nil, err
}
@@ -1204,7 +1204,7 @@ func (b *Bitmex) GetLatestFundingRates(ctx context.Context, r *fundingrate.Lates
continue
}
resp = append(resp, fundingrate.LatestRateResponse{
Exchange: b.Name,
Exchange: e.Name,
Asset: r.Asset,
Pair: cp,
LatestRate: fundingrate.Rate{
@@ -1219,17 +1219,17 @@ func (b *Bitmex) GetLatestFundingRates(ctx context.Context, r *fundingrate.Lates
}
// IsPerpetualFutureCurrency ensures a given asset and currency is a perpetual future
func (b *Bitmex) IsPerpetualFutureCurrency(a asset.Item, _ currency.Pair) (bool, error) {
func (e *Exchange) IsPerpetualFutureCurrency(a asset.Item, _ currency.Pair) (bool, error) {
return a == asset.PerpetualContract, nil
}
// UpdateOrderExecutionLimits updates order execution limits
func (b *Bitmex) UpdateOrderExecutionLimits(_ context.Context, _ asset.Item) error {
func (e *Exchange) UpdateOrderExecutionLimits(_ context.Context, _ asset.Item) error {
return common.ErrNotYetImplemented
}
// GetOpenInterest returns the open interest rate for a given asset pair
func (b *Bitmex) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]futures.OpenInterest, error) {
func (e *Exchange) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]futures.OpenInterest, error) {
for i := range k {
if k[i].Asset == asset.Spot || k[i].Asset == asset.Index {
// avoid API calls or returning errors after a successful retrieval
@@ -1237,16 +1237,16 @@ func (b *Bitmex) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]fut
}
}
if len(k) != 1 {
activeInstruments, err := b.GetActiveAndIndexInstruments(ctx)
activeInstruments, err := e.GetActiveAndIndexInstruments(ctx)
if err != nil {
return nil, err
}
resp := make([]futures.OpenInterest, 0, len(activeInstruments))
for i := range activeInstruments {
for _, a := range b.CurrencyPairs.GetAssetTypes(true) {
for _, a := range e.CurrencyPairs.GetAssetTypes(true) {
var symbol currency.Pair
var enabled bool
symbol, enabled, err = b.MatchSymbolCheckEnabled(activeInstruments[i].Symbol, a, false)
symbol, enabled, err = e.MatchSymbolCheckEnabled(activeInstruments[i].Symbol, a, false)
if err != nil && !errors.Is(err, currency.ErrPairNotFound) {
return nil, err
}
@@ -1265,7 +1265,7 @@ func (b *Bitmex) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]fut
}
resp = append(resp, futures.OpenInterest{
Key: key.ExchangePairAsset{
Exchange: b.Name,
Exchange: e.Name,
Base: symbol.Base.Item,
Quote: symbol.Quote.Item,
Asset: a,
@@ -1276,18 +1276,18 @@ func (b *Bitmex) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]fut
}
return resp, nil
}
_, isEnabled, err := b.MatchSymbolCheckEnabled(k[0].Pair().String(), k[0].Asset, false)
_, isEnabled, err := e.MatchSymbolCheckEnabled(k[0].Pair().String(), k[0].Asset, false)
if err != nil && !errors.Is(err, currency.ErrPairNotFound) {
return nil, err
}
if !isEnabled {
return nil, fmt.Errorf("%w %v %v", currency.ErrPairNotEnabled, k[0].Asset, k[0].Pair())
}
symbolStr, err := b.FormatSymbol(k[0].Pair(), k[0].Asset)
symbolStr, err := e.FormatSymbol(k[0].Pair(), k[0].Asset)
if err != nil {
return nil, err
}
instrument, err := b.GetInstrument(ctx, &GenericRequestParams{Symbol: symbolStr})
instrument, err := e.GetInstrument(ctx, &GenericRequestParams{Symbol: symbolStr})
if err != nil {
return nil, err
}
@@ -1297,7 +1297,7 @@ func (b *Bitmex) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]fut
resp := make([]futures.OpenInterest, 1)
resp[0] = futures.OpenInterest{
Key: key.ExchangePairAsset{
Exchange: b.Name,
Exchange: e.Name,
Base: k[0].Base,
Quote: k[0].Quote,
Asset: k[0].Asset,
@@ -1308,8 +1308,8 @@ func (b *Bitmex) GetOpenInterest(ctx context.Context, k ...key.PairAsset) ([]fut
}
// GetCurrencyTradeURL returns the URL to the exchange's trade page for the given asset and currency pair
func (b *Bitmex) GetCurrencyTradeURL(_ context.Context, a asset.Item, cp currency.Pair) (string, error) {
_, err := b.CurrencyPairs.IsPairEnabled(cp, a)
func (e *Exchange) GetCurrencyTradeURL(_ context.Context, a asset.Item, cp currency.Pair) (string, error) {
_, err := e.CurrencyPairs.IsPairEnabled(cp, a)
if err != nil {
return "", err
}