Files
gocryptotrader/exchanges/interfaces.go
Ryan O'Hara-Reid 3f8d799613 bybit: Add websocket trading functionality across all assets (#1672)
* fix whoops

* const trafficCheckInterval; rm testmain

* y

* fix lint

* bump time check window

* stream: fix intermittant test failures while testing routines and remove code that is not needed.

* spells

* cant do what I did

* protect race due to routine.

* update testURL

* use mock websocket connection instead of test URL's

* linter: fix

* remove url because its throwing errors on CI builds

* connections drop all the time, don't need to worry about not being able to echo back ws data as it can be easily reviewed _test file side.

* remove another superfluous url thats not really set up for this

* spawn overwatch routine when there is no errors, inline checker instead of waiting for a time period, add sleep inline with echo handler as this is really quick and wanted to ensure that latency is handing correctly

* linter: fixerino uperino

* fix ID bug, why I do this, I don't know.

* glorious: panix

* linter: things

* whoops

* dont need to make consecutive Unix() calls

* websocket: fix potential panic on error and no responses and adding waitForResponses

* bybit: enable multiconnection handling across websocket endpoints

* rm debug lines

* bybit: Add websocket trading functionality across all assets

* rm json parser and handle in json package instead

* in favour of json package unmarshalling

* Add bool ConnectionDoesNotRequireSubscriptions so that we don't need to handle dummy sub

* handle pong response

* spelling

* linter: fix

* fix processing issues with tickers

* fix processing issues with tickers

* linter: fix

* linter: fix again

* * change field name OutboundRequestSignature to WrapperDefinedConnectionSignature for agnostic inbound and outbound connections.
* change method name GetOutboundConnection to GetConnection for agnostic inbound and outbound connections.
* drop outbound field map for improved performance just using a range and field check (less complex as well)
* change field name connections to connectionToWrapper for better clarity

* spells and magic and wands

* merge: fixup

* linter: fix

* spelling: fix

* glorious: nits

* comparable check for signature

* mv err var

* rm comment as it does not

* update time fields for orderbook latency

* fix time conversion

* Add func MatchReturnResponses

* glorious: nits and stuff

* lint: fix

* attempt to fix race

* linter: fix

* fix tests

* types/time: strict usage of time type for usage with unix timestamps

* fix tests etc

* Allow match back with order details

* Add time in force values for different order types + extra return information on websocket trading

* glorious: nits

* gk: nits; engine log cleanup

* gk: nits; OCD

* gk: nits; move function change file names

* gk: nits; 🚀

* gk: nits; convert variadic function and message inspection to interface and include a specific function for that handling so as to not need nil on every call

* gk: nits; continued

* gk: engine nits; rm loaded exchange

* gk: nits; drop WebsocketLoginResponse

* stream: Add match method EnsureMatchWithData

* gk: nits; rn Inspect to IsFinal

* gk: nits; rn to MessageFilter

* linter: fix

* gateio: update rate limit definitions (cherry-pick)

* Add test and missing

* Shared REST rate limit definitions with Websocket service, set lookup item to nil for systems that do not require rate limiting; add glorious nit

* integrate rate limits for websocket trading spot

* bybit: split public and private processing to dedicated handler add supporting function and tests

* use correct handler for private inbound connection

* bybit/websocket: allow a shared ID between outbound payloads for inbound matching

* conform to match upstream changes

* standardise names to upstream style

* fix wrapper standards test when sending a auth request through a websocket connection

* whoops

* Update exchanges/gateio/gateio_types.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits

* linter: fix

* linter: overload

* whoops

* spelling fixes on recent merge

* glorious: nits

* linter: fix?

* glorious: nits

* gk: assert errors touched

* gk: unexport derive functions

* gk: nitssssssss

* fix test

* gk: nitters v1

* gk: http status

* gk/nits: Add getAssetFromFuturesPair

* gk: nits single response when submitting

* gk: new pair with delimiter in tests

* gk: param update slice to slice of pointers

* gk: add asset type in params, includes t.Context() for tests

* linter: fix

* linter: fix

* fix merge whoopsie

* glorious: nits

* gk: nit

* linter: fix

* glorious: nits

* linter/misc: fix and remove meows

* linter: fix

* misc/linter: fix

* change function names

* okx: update requestID gen func without func wrapping

* RM: functions not needed

* Update docs/ADD_NEW_EXCHANGE.md

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* gk: nitsssssss

* linter: fix

* Update exchanges/bybit/bybit_test.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/bybit/bybit_test.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* gk: nit words

* cranktakular: nits

* websocket: skip connections with subscriptions not required during channel flush

* websocket: simplify error handling in FlushChannels using if short

* linter: fix

* cranktakular: nits and expand coverage

* linter: fix?

* misc fix

* cranktakular: missing nit which I thumbed up but did not do. Sillllllly billlyyyy nilllyyy

* fix comments

* bybit: fix merge regression on websocket message filter

* cranktakular: nits

* bybit: Add global rate limits for websocket

* ai: nits

* linter: fix

* cranktakular: purge DCP ref/handling and add another TODO

* Update exchanges/bybit/bybit_websocket.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits

* fix test

* fix alignment issue and rm println

* Update exchanges/bybit/bybit_websocket.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/bybit/bybit_websocket.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: fix

* Update exchanges/bybit/bybit_websocket.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

* bybit: use connection method for segregated match on multi-connection

* cleanup after master merge

* fix test and config whoops

* cranktakular: nits

* exchange: add missing tests for base method websocket order funcs

* cranktakular: nits and refresh + tests

* cranktakular: pedantic nits

* linter: fixes

* t.Parallel tests

* glorious nit

* Update exchange/websocket/connection.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* gk: nits

* boss king: nits

* canktakular: nits

* Update exchanges/bybit/bybit_websocket.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/bybit/bybit_websocket_requests.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/bybit/bybit_websocket_requests.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/bybit/bybit_websocket_requests.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* Update exchanges/bybit/bybit_websocket_requests.go

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>

* gk: nits

* linter: fix

* Update exchanges/bybit/bybit.go

Co-authored-by: Samuael A. <39623015+samuael@users.noreply.github.com>

* Update exchanges/bybit/bybit.go

Co-authored-by: Samuael A. <39623015+samuael@users.noreply.github.com>

* bossking: nits

* gk: much nicer design

* gk: revised naming for consideration

* gk: nits

* gk: nits restrict in configtest.json and not worry about many pairs enabled

* rm log

* linter: fix

* codex: nit

* cranktakular: nits

* Update exchanges/bybit/bybit_websocket_requests.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/bybit/bybit_websocket_requests.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/bybit/bybit_wrapper.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits!

* thrasher: nits

---------

Co-authored-by: shazbert <ryan.oharareid@thrasher.io>
Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>
Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
Co-authored-by: Samuael A. <39623015+samuael@users.noreply.github.com>
2025-09-17 13:45:58 +10:00

203 lines
11 KiB
Go

package exchange
import (
"context"
"text/template"
"time"
"github.com/thrasher-corp/gocryptotrader/common/key"
"github.com/thrasher-corp/gocryptotrader/config"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchange/order/limits"
"github.com/thrasher-corp/gocryptotrader/exchange/websocket"
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/collateral"
"github.com/thrasher-corp/gocryptotrader/exchanges/currencystate"
"github.com/thrasher-corp/gocryptotrader/exchanges/deposit"
"github.com/thrasher-corp/gocryptotrader/exchanges/fundingrate"
"github.com/thrasher-corp/gocryptotrader/exchanges/futures"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/margin"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
// IBotExchange enforces standard functions for all exchanges supported in
// GoCryptoTrader
type IBotExchange interface {
Setup(exch *config.Exchange) error
Bootstrap(context.Context) (continueBootstrap bool, err error)
SetDefaults()
Shutdown() error
GetName() string
SetEnabled(bool)
GetEnabledFeatures() FeaturesEnabled
GetSupportedFeatures() FeaturesSupported
GetTradingRequirements() protocol.TradingRequirements
GetCachedTicker(p currency.Pair, a asset.Item) (*ticker.Price, error)
UpdateTicker(ctx context.Context, p currency.Pair, a asset.Item) (*ticker.Price, error)
UpdateTickers(ctx context.Context, a asset.Item) error
GetCachedOrderbook(p currency.Pair, a asset.Item) (*orderbook.Book, error)
UpdateOrderbook(ctx context.Context, p currency.Pair, a asset.Item) (*orderbook.Book, error)
FetchTradablePairs(ctx context.Context, a asset.Item) (currency.Pairs, error)
UpdateTradablePairs(ctx context.Context, forceUpdate bool) error
GetEnabledPairs(a asset.Item) (currency.Pairs, error)
GetAvailablePairs(a asset.Item) (currency.Pairs, error)
GetPairFormat(asset.Item, bool) (currency.PairFormat, error)
SetPairs(pairs currency.Pairs, a asset.Item, enabled bool) error
GetAssetTypes(enabled bool) asset.Items
GetRecentTrades(ctx context.Context, p currency.Pair, a asset.Item) ([]trade.Data, error)
GetHistoricTrades(ctx context.Context, p currency.Pair, a asset.Item, startTime, endTime time.Time) ([]trade.Data, error)
GetFeeByType(ctx context.Context, f *FeeBuilder) (float64, error)
GetLastPairsUpdateTime() int64
GetWithdrawPermissions() uint32
FormatWithdrawPermissions() string
GetAccountFundingHistory(ctx context.Context) ([]FundingHistory, error)
GetDepositAddress(ctx context.Context, cryptocurrency currency.Code, accountID, chain string) (*deposit.Address, error)
GetAvailableTransferChains(ctx context.Context, cryptocurrency currency.Code) ([]string, error)
GetWithdrawalsHistory(ctx context.Context, code currency.Code, a asset.Item) ([]WithdrawalHistory, error)
WithdrawCryptocurrencyFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error)
WithdrawFiatFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error)
WithdrawFiatFundsToInternationalBank(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error)
SetHTTPClientUserAgent(ua string) error
GetHTTPClientUserAgent() (string, error)
SetClientProxyAddress(addr string) error
GetBase() *Base
GetHistoricCandles(ctx context.Context, pair currency.Pair, a asset.Item, interval kline.Interval, start, end time.Time) (*kline.Item, error)
GetHistoricCandlesExtended(ctx context.Context, pair currency.Pair, a asset.Item, interval kline.Interval, start, end time.Time) (*kline.Item, error)
DisableRateLimiter() error
EnableRateLimiter() error
GetServerTime(ctx context.Context, ai asset.Item) (time.Time, error)
GetWebsocket() (*websocket.Manager, error)
SubscribeToWebsocketChannels(channels subscription.List) error
UnsubscribeToWebsocketChannels(channels subscription.List) error
GetSubscriptions() (subscription.List, error)
GetSubscriptionTemplate(*subscription.Subscription) (*template.Template, error)
FlushWebsocketChannels() error
AuthenticateWebsocket(ctx context.Context) error
CanUseAuthenticatedWebsocketEndpoints() bool
GetOrderExecutionLimits(a asset.Item, cp currency.Pair) (limits.MinMaxLevel, error)
CheckOrderExecutionLimits(a asset.Item, cp currency.Pair, price, amount float64, orderType order.Type) error
UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) error
GetCredentials(ctx context.Context) (*account.Credentials, error)
EnsureOnePairEnabled() error
PrintEnabledPairs()
IsVerbose() bool
GetCurrencyTradeURL(ctx context.Context, a asset.Item, cp currency.Pair) (string, error)
// ValidateAPICredentials function validates the API keys by sending an
// authenticated REST request. See exchange specific wrapper implementation.
ValidateAPICredentials(ctx context.Context, a asset.Item) error
// VerifyAPICredentials determines if the credentials supplied have unset
// required values. See exchanges/credentials.go Base method for
// implementation.
VerifyAPICredentials(creds *account.Credentials) error
// GetDefaultCredentials returns the exchange.Base api credentials loaded by
// config.json. See exchanges/credentials.go Base method for implementation.
GetDefaultCredentials() *account.Credentials
FunctionalityChecker
AccountManagement
OrderManagement
CurrencyStateManagement
FuturesManagement
MarginManagement
// MatchSymbolWithAvailablePairs returns a currency pair based on the supplied
// symbol and asset type. If the string is expected to have a delimiter this
// will attempt to screen it out.
MatchSymbolWithAvailablePairs(symbol string, a asset.Item, hasDelimiter bool) (currency.Pair, error)
// MatchSymbolCheckEnabled returns a currency pair based on the supplied symbol
// and asset type against the available pairs list. If the string is expected to
// have a delimiter this will attempt to screen it out. It will also check if
// the pair is enabled.
MatchSymbolCheckEnabled(symbol string, a asset.Item, hasDelimiter bool) (pair currency.Pair, enabled bool, err error)
// IsPairEnabled checks if a pair is enabled for an enabled asset type
IsPairEnabled(pair currency.Pair, a asset.Item) (bool, error)
}
// OrderManagement defines functionality for order management
type OrderManagement interface {
SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitResponse, error)
ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error)
CancelOrder(ctx context.Context, o *order.Cancel) error
CancelBatchOrders(ctx context.Context, o []order.Cancel) (*order.CancelBatchResponse, error)
CancelAllOrders(ctx context.Context, orders *order.Cancel) (order.CancelAllResponse, error)
GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, assetType asset.Item) (*order.Detail, error)
GetActiveOrders(ctx context.Context, getOrdersRequest *order.MultiOrderRequest) (order.FilteredOrders, error)
GetOrderHistory(ctx context.Context, getOrdersRequest *order.MultiOrderRequest) (order.FilteredOrders, error)
WebsocketSubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitResponse, error)
WebsocketSubmitOrders(ctx context.Context, orders []*order.Submit) (responses []*order.SubmitResponse, err error)
WebsocketModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error)
WebsocketCancelOrder(ctx context.Context, ord *order.Cancel) error
}
// CurrencyStateManagement defines functionality for currency state management
type CurrencyStateManagement interface {
GetCurrencyStateSnapshot() ([]currencystate.Snapshot, error)
UpdateCurrencyStates(ctx context.Context, a asset.Item) error
CanTradePair(p currency.Pair, a asset.Item) error
CanTrade(c currency.Code, a asset.Item) error
CanWithdraw(c currency.Code, a asset.Item) error
CanDeposit(c currency.Code, a asset.Item) error
}
// AccountManagement defines functionality for exchange account management
type AccountManagement interface {
UpdateAccountInfo(ctx context.Context, a asset.Item) (account.Holdings, error)
GetCachedAccountInfo(ctx context.Context, a asset.Item) (account.Holdings, error)
HasAssetTypeAccountSegregation() bool
}
// FunctionalityChecker defines functionality for retrieving exchange
// support/enabled features
type FunctionalityChecker interface {
IsEnabled() bool
IsAssetWebsocketSupported(a asset.Item) bool
SupportsAsset(assetType asset.Item) bool
SupportsREST() bool
SupportsWithdrawPermissions(permissions uint32) bool
SupportsRESTTickerBatchUpdates() bool
IsWebsocketEnabled() bool
SupportsWebsocket() bool
SupportsAutoPairUpdates() bool
IsWebsocketAuthenticationSupported() bool
IsRESTAuthenticationSupported() bool
}
// FuturesManagement manages futures orders, pnl and collateral calculations
type FuturesManagement interface {
GetOpenInterest(context.Context, ...key.PairAsset) ([]futures.OpenInterest, error)
ScaleCollateral(ctx context.Context, calculator *futures.CollateralCalculator) (*collateral.ByCurrency, error)
GetPositionSummary(context.Context, *futures.PositionSummaryRequest) (*futures.PositionSummary, error)
CalculateTotalCollateral(context.Context, *futures.TotalCollateralCalculator) (*futures.TotalCollateralResponse, error)
GetFuturesPositions(context.Context, *futures.PositionsRequest) ([]futures.PositionDetails, error)
GetHistoricalFundingRates(context.Context, *fundingrate.HistoricalRatesRequest) (*fundingrate.HistoricalRates, error)
GetLatestFundingRates(context.Context, *fundingrate.LatestRateRequest) ([]fundingrate.LatestRateResponse, error)
IsPerpetualFutureCurrency(asset.Item, currency.Pair) (bool, error)
GetCollateralCurrencyForContract(asset.Item, currency.Pair) (currency.Code, asset.Item, error)
GetFuturesPositionSummary(context.Context, *futures.PositionSummaryRequest) (*futures.PositionSummary, error)
GetFuturesPositionOrders(context.Context, *futures.PositionsRequest) ([]futures.PositionResponse, error)
SetCollateralMode(ctx context.Context, item asset.Item, mode collateral.Mode) error
GetCollateralMode(ctx context.Context, item asset.Item) (collateral.Mode, error)
SetLeverage(ctx context.Context, item asset.Item, pair currency.Pair, marginType margin.Type, amount float64, orderSide order.Side) error
GetLeverage(ctx context.Context, item asset.Item, pair currency.Pair, marginType margin.Type, orderSide order.Side) (float64, error)
}
// MarginManagement manages margin positions and rates
type MarginManagement interface {
SetMarginType(ctx context.Context, item asset.Item, pair currency.Pair, tp margin.Type) error
ChangePositionMargin(ctx context.Context, change *margin.PositionChangeRequest) (*margin.PositionChangeResponse, error)
GetMarginRatesHistory(context.Context, *margin.RateHistoryRequest) (*margin.RateHistoryResponse, error)
futures.PNLCalculation
GetFuturesContractDetails(ctx context.Context, item asset.Item) ([]futures.Contract, error)
}