Files
gocryptotrader/exchanges/exchange_types.go
Ryan O'Hara-Reid cad7586e98 exchange/websocket, gateio: Rename/export package again, add websocket request functions for futures trading (#1603)
* gateio: Add multi asset websocket support WIP.

* meow

* Add tests and shenanigans

* integrate flushing and for enabling/disabling pairs from rpc shenanigans

* some changes

* linter: fixes strikes again.

* Change name ConnectionAssociation -> ConnectionCandidate for better clarity on purpose. Change connections map to point to candidate to track subscriptions for future dynamic connections holder and drop struct ConnectionDetails.

* Add subscription tests (state functional)

* glorious:nits + proxy handling

* Spelling

* linter: fixerino

* instead of nil, dont do nil.

* clean up nils

* cya nils

* don't need to set URL or check if its running

* stream match update

* update tests

* linter: fix

* glorious: nits + handle context cancellations

* stop ping handler routine leak

* * Fix bug where reader routine on error that is not a disconnection error but websocket frame error or anything really makes the reader routine return and then connection never cycles and the buffer gets filled.
* Handle reconnection via an errors.Is check which is simpler and in that scope allow for quick disconnect reconnect without waiting for connection cycle.
* Dial now uses code from DialContext but just calls context.Background()
* Don't allow reader to return on parse binary response error. Just output error and return a non nil response

* Allow rollback on connect on any error across all connections

* fix shadow jutsu

* glorious/gk: nitters - adds in ws mock server

* linter: fix

* fix deadlock on connection as the previous channel had no reader and would hang connection reader for eternity.

* glorious: whooops

* gk: nits

* Leak issue and edge case

* Websocket: Add SendMessageReturnResponses

* whooooooopsie

* gk: nitssssss

* Update exchanges/stream/stream_match.go

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

* Update exchanges/stream/stream_match_test.go

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

* linter: appease the linter gods

* gk: nits

* gk: drain brain

* started

* more changes before merge match pr

* gateio: still building out

* gateio: finish spot

* fix up tests in gateio

* Add tests for stream package

* rm unused field

* glorious: nits

* rn files, specifically set function names to asset and offload routing to websocket type.

* linter: fix

* Add futures websocket request support

* gateio: integrate with IBOTExchange (cherry pick my nose)

* linter: fix

* glorious: nits

* add counter and update gateio

* fix collision issue

* Update exchanges/stream/websocket.go

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

* glorious: nits

* add tests

* linter: fix

* After merge

* Add error connection info

* upgrade to upstream merge

* Fix edge case where it does not reconnect made by an already closed connection

* stream coverage

* glorious: nits

* glorious: nits removed asset error handling in stream package

* linter: fix

* rm block

* Add basic readme

* fix asset enabled flush cycle for multi connection

* spella: fix

* linter: fix

* Add glorious suggestions, fix some race thing

* reinstate name before any routine gets spawned

* stop on error in mock tests

* glorious: nits

* Set correct price

* glorious: nits found in CI build

* Add test for drain, bumped wait times as there seems to be something happening on macos CI builds, used context.WithTimeout because its instant.

* mutex across shutdown and connect for protection

* lint: fix

* test time withoffset, reinstate stop

* 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

* rm json parser and handle in json package instead

* in favour of json package unmarshalling

* 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

* glorious: nits

* comparable check for signature

* mv err var

* glorious: nits and stuff

* attempt to fix race

* 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

* 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

* shift over to websocket package error

* internal/exchange/websocket -> exchange/websocket

* PEAK OCD!

* appease the OCD gods

* thrasher: nits

---------

Co-authored-by: shazbert <ryan.oharareid@thrasher.io>
Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>
Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
2025-04-11 16:47:33 +10:00

327 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/order"
"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
HTTPDebugging bool
BypassConfigFormatUpgrades bool
WebsocketResponseCheckTimeout time.Duration
WebsocketResponseMaxLimit time.Duration
WebsocketOrderbookBufferLimit int64
Websocket *websocket.Manager
*request.Requester
Config *config.Exchange
settingsMutex sync.RWMutex
// CanVerifyOrderbook determines if the orderbook verification can be bypassed,
// increasing potential update speed but decreasing confidence in orderbook
// integrity.
CanVerifyOrderbook bool
order.ExecutionLimits
AssetWebsocketSupport
*currencystate.States
}
// url lookup consts
const (
Invalid URL = iota
RestSpot
RestSpotSupplementary
RestUSDTMargined
RestCoinMargined
RestFutures
RestFuturesSupplementary
RestUSDCMargined
RestSwap
RestSandbox
WebsocketSpot
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"
websocketSpotSupplementaryURL = "WebsocketSpotSupplementaryURL"
chainAnalysisURL = "ChainAnalysisURL"
edgeCase1URL = "EdgeCase1URL"
edgeCase2URL = "EdgeCase2URL"
edgeCase3URL = "EdgeCase3URL"
)
var keyURLs = []URL{
RestSpot,
RestSpotSupplementary,
RestUSDTMargined,
RestCoinMargined,
RestFutures,
RestFuturesSupplementary,
RestUSDCMargined,
RestSwap,
RestSandbox,
WebsocketSpot,
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
}