Files
gocryptotrader/exchanges/exchange_types.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

344 lines
11 KiB
Go

package exchange
import (
"sync"
"time"
"github.com/thrasher-corp/gocryptotrader/config"
"github.com/thrasher-corp/gocryptotrader/currency"
"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/currencystate"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/subscription"
)
// Endpoint authentication types
const (
// Repeated exchange strings
// FeeType custom type for calculating fees based on method
WireTransfer InternationalBankTransactionType = iota
PerfectMoney
Neteller
AdvCash
Payeer
Skrill
Simplex
SEPA
Swift
RapidTransfer
MisterTangoSEPA
Qiwi
VisaMastercard
WebMoney
Capitalist
WesternUnion
MoneyGram
Contact
// Const declarations for fee types
BankFee FeeType = iota
InternationalBankDepositFee
InternationalBankWithdrawalFee
CryptocurrencyTradeFee
CryptocurrencyDepositFee
CryptocurrencyWithdrawalFee
OfflineTradeFee
// Definitions for each type of withdrawal method for a given exchange
NoAPIWithdrawalMethods uint32 = 0
NoAPIWithdrawalMethodsText string = "NONE, WEBSITE ONLY"
AutoWithdrawCrypto uint32 = (1 << 0)
AutoWithdrawCryptoWithAPIPermission uint32 = (1 << 1)
AutoWithdrawCryptoWithSetup uint32 = (1 << 2)
AutoWithdrawCryptoText string = "AUTO WITHDRAW CRYPTO"
AutoWithdrawCryptoWithAPIPermissionText string = "AUTO WITHDRAW CRYPTO WITH API PERMISSION"
AutoWithdrawCryptoWithSetupText string = "AUTO WITHDRAW CRYPTO WITH SETUP"
WithdrawCryptoWith2FA uint32 = (1 << 3)
WithdrawCryptoWithSMS uint32 = (1 << 4)
WithdrawCryptoWithEmail uint32 = (1 << 5)
WithdrawCryptoWithWebsiteApproval uint32 = (1 << 6)
WithdrawCryptoWithAPIPermission uint32 = (1 << 7)
WithdrawCryptoWith2FAText string = "WITHDRAW CRYPTO WITH 2FA"
WithdrawCryptoWithSMSText string = "WITHDRAW CRYPTO WITH SMS"
WithdrawCryptoWithEmailText string = "WITHDRAW CRYPTO WITH EMAIL"
WithdrawCryptoWithWebsiteApprovalText string = "WITHDRAW CRYPTO WITH WEBSITE APPROVAL"
WithdrawCryptoWithAPIPermissionText string = "WITHDRAW CRYPTO WITH API PERMISSION"
AutoWithdrawFiat uint32 = (1 << 8)
AutoWithdrawFiatWithAPIPermission uint32 = (1 << 9)
AutoWithdrawFiatWithSetup uint32 = (1 << 10)
AutoWithdrawFiatText string = "AUTO WITHDRAW FIAT"
AutoWithdrawFiatWithAPIPermissionText string = "AUTO WITHDRAW FIAT WITH API PERMISSION"
AutoWithdrawFiatWithSetupText string = "AUTO WITHDRAW FIAT WITH SETUP"
WithdrawFiatWith2FA uint32 = (1 << 11)
WithdrawFiatWithSMS uint32 = (1 << 12)
WithdrawFiatWithEmail uint32 = (1 << 13)
WithdrawFiatWithWebsiteApproval uint32 = (1 << 14)
WithdrawFiatWithAPIPermission uint32 = (1 << 15)
WithdrawFiatWith2FAText string = "WITHDRAW FIAT WITH 2FA"
WithdrawFiatWithSMSText string = "WITHDRAW FIAT WITH SMS"
WithdrawFiatWithEmailText string = "WITHDRAW FIAT WITH EMAIL"
WithdrawFiatWithWebsiteApprovalText string = "WITHDRAW FIAT WITH WEBSITE APPROVAL"
WithdrawFiatWithAPIPermissionText string = "WITHDRAW FIAT WITH API PERMISSION"
WithdrawCryptoViaWebsiteOnly uint32 = (1 << 16)
WithdrawFiatViaWebsiteOnly uint32 = (1 << 17)
WithdrawCryptoViaWebsiteOnlyText string = "WITHDRAW CRYPTO VIA WEBSITE ONLY"
WithdrawFiatViaWebsiteOnlyText string = "WITHDRAW FIAT VIA WEBSITE ONLY"
NoFiatWithdrawals uint32 = (1 << 18)
NoFiatWithdrawalsText string = "NO FIAT WITHDRAWAL"
UnknownWithdrawalTypeText string = "UNKNOWN"
)
// FeeType is the type for holding a custom fee type (International withdrawal fee)
type FeeType uint8
// InternationalBankTransactionType custom type for calculating fees based on fiat transaction types
type InternationalBankTransactionType uint8
// FeeBuilder is the type which holds all parameters required to calculate a fee
// for an exchange
type FeeBuilder struct {
FeeType FeeType
// Used for calculating crypto trading fees, deposits & withdrawals
Pair currency.Pair
IsMaker bool
// Fiat currency used for bank deposits & withdrawals
FiatCurrency currency.Code
BankTransactionType InternationalBankTransactionType
// Used to multiply for fee calculations
PurchasePrice float64
Amount float64
}
// FundingHistory holds exchange funding history data
type FundingHistory struct {
ExchangeName string
Status string
TransferID string
Description string
Timestamp time.Time
Currency string
Amount float64
Fee float64
TransferType string
CryptoToAddress string
CryptoFromAddress string
CryptoTxID string
CryptoChain string
BankTo string
BankFrom string
}
// WithdrawalHistory holds exchange Withdrawal history data
type WithdrawalHistory struct {
Status string
TransferID string
Description string
Timestamp time.Time
Currency string
Amount float64
Fee float64
TransferType string
CryptoToAddress string
CryptoTxID string
CryptoChain string
BankTo string
}
// Features stores the supported and enabled features
// for the exchange
type Features struct {
Supports FeaturesSupported
Enabled FeaturesEnabled
Subscriptions subscription.List
CurrencyTranslations currency.Translations
TradingRequirements protocol.TradingRequirements
}
// FeaturesEnabled stores the exchange enabled features
type FeaturesEnabled struct {
AutoPairUpdates bool
Kline kline.ExchangeCapabilitiesEnabled
SaveTradeData bool
TradeFeed bool
FillsFeed bool
}
// FeaturesSupported stores the exchanges supported features
type FeaturesSupported struct {
REST bool
RESTCapabilities protocol.Features
Websocket bool
WebsocketCapabilities protocol.Features
WithdrawPermissions uint32
Kline kline.ExchangeCapabilitiesSupported
MaximumOrderHistory time.Duration
FuturesCapabilities FuturesCapabilities
OfflineFuturesCapabilities FuturesCapabilities
}
// FuturesCapabilities stores the exchange's futures capabilities
type FuturesCapabilities struct {
FundingRates bool
MaximumFundingRateHistory time.Duration
FundingRateBatching map[asset.Item]bool
SupportedFundingRateFrequencies map[kline.Interval]bool
Positions bool
OrderManagerPositionTracking bool
Collateral bool
CollateralMode bool
Leverage bool
OpenInterest OpenInterestSupport
}
// OpenInterestSupport helps breakdown a feature and how it is supported
type OpenInterestSupport struct {
Supported bool
SupportedViaTicker bool
SupportsRestBatch bool
}
// MarginCapabilities stores the exchange's margin capabilities
type MarginCapabilities struct {
SetMarginType bool
ChangePositionMargin bool
GetMarginRateHistory bool
}
// Endpoints stores running url endpoints for exchanges
type Endpoints struct {
Exchange string
defaults map[string]string
mu sync.RWMutex
}
// API stores the exchange API settings
type API struct {
AuthenticatedSupport bool
AuthenticatedWebsocketSupport bool
PEMKeySupport bool
Endpoints *Endpoints
credentials account.Credentials
credMu sync.RWMutex
CredentialsValidator config.APICredentialsValidatorConfig
}
// Base stores the individual exchange information
type Base struct {
Name string
Enabled bool
Verbose bool
LoadedByConfig bool
SkipAuthCheck bool
API API
BaseCurrencies currency.Currencies
CurrencyPairs currency.PairsManager
Features Features
HTTPTimeout time.Duration
HTTPRecording bool
HTTPMockDataSliceLimit int // Use with HTTPRecording to reduce the size of recorded mock data
HTTPDebugging bool
BypassConfigFormatUpgrades bool
WebsocketResponseCheckTimeout time.Duration
WebsocketResponseMaxLimit time.Duration
WebsocketOrderbookBufferLimit int64
Websocket *websocket.Manager
*request.Requester
Config *config.Exchange
settingsMutex sync.RWMutex
// ValidateOrderbook determines if the orderbook verification can be bypassed,
// increasing potential update speed but decreasing confidence in orderbook
// integrity.
ValidateOrderbook bool
AssetWebsocketSupport
*currencystate.States
}
// url lookup consts
const (
Invalid URL = iota
RestSpot
RestSpotSupplementary
RestUSDTMargined
RestCoinMargined
RestFutures
RestFuturesSupplementary
RestUSDCMargined
RestSwap
RestSandbox
WebsocketSpot
WebsocketCoinMargined
WebsocketUSDTMargined
WebsocketUSDCMargined
WebsocketOptions
WebsocketTrade
WebsocketPrivate
WebsocketSpotSupplementary
ChainAnalysis
EdgeCase1
EdgeCase2
EdgeCase3
restSpotURL = "RestSpotURL"
restSpotSupplementaryURL = "RestSpotSupplementaryURL"
restUSDTMarginedFuturesURL = "RestUSDTMarginedFuturesURL"
restCoinMarginedFuturesURL = "RestCoinMarginedFuturesURL"
restUSDCMarginedFuturesURL = "RestUSDCMarginedFuturesURL"
restFuturesURL = "RestFuturesURL"
restFuturesSupplementaryURL = "RestFuturesSupplementaryURL"
restSandboxURL = "RestSandboxURL"
restSwapURL = "RestSwapURL"
websocketSpotURL = "WebsocketSpotURL"
websocketCoinMarginedURL = "WebsocketCoinMarginedURL"
websocketUSDTMarginedURL = "WebsocketUSDTMarginedURL"
websocketUSDCMarginedURL = "WebsocketUSDCMarginedURL"
websocketOptionsURL = "WebsocketOptionsURL"
websocketTradeURL = "WebsocketTradeURL"
websocketPrivateURL = "WebsocketPrivateURL"
websocketSpotSupplementaryURL = "WebsocketSpotSupplementaryURL"
chainAnalysisURL = "ChainAnalysisURL"
edgeCase1URL = "EdgeCase1URL"
edgeCase2URL = "EdgeCase2URL"
edgeCase3URL = "EdgeCase3URL"
)
var keyURLs = []URL{
RestSpot,
RestSpotSupplementary,
RestUSDTMargined,
RestCoinMargined,
RestFutures,
RestFuturesSupplementary,
RestUSDCMargined,
RestSwap,
RestSandbox,
WebsocketSpot,
WebsocketCoinMargined,
WebsocketUSDTMargined,
WebsocketUSDCMargined,
WebsocketOptions,
WebsocketTrade,
WebsocketPrivate,
WebsocketSpotSupplementary,
ChainAnalysis,
EdgeCase1,
EdgeCase2,
EdgeCase3,
}
// URL stores uint conversions
type URL uint16
// AssetWebsocketSupport defines the availability of websocket functionality to
// the specific asset type. TODO: Deprecate as this is a temp item to address
// certain limitations quickly.
type AssetWebsocketSupport struct {
unsupported map[asset.Item]bool
m sync.RWMutex
}