mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-09 07:26:48 +00:00
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:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -80,8 +80,8 @@ var subscriptionNames = map[string]string{
|
||||
var standardMarginAssetTypes = []asset.Item{asset.Spot, asset.Margin, asset.CrossMargin}
|
||||
|
||||
// WsConnectSpot initiates a websocket connection
|
||||
func (g *Gateio) WsConnectSpot(ctx context.Context, conn websocket.Connection) error {
|
||||
err := g.CurrencyPairs.IsAssetEnabled(asset.Spot)
|
||||
func (e *Exchange) WsConnectSpot(ctx context.Context, conn websocket.Connection) error {
|
||||
err := e.CurrencyPairs.IsAssetEnabled(asset.Spot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -103,7 +103,7 @@ func (g *Gateio) WsConnectSpot(ctx context.Context, conn websocket.Connection) e
|
||||
}
|
||||
|
||||
// websocketLogin authenticates the websocket connection
|
||||
func (g *Gateio) websocketLogin(ctx context.Context, conn websocket.Connection, channel string) error {
|
||||
func (e *Exchange) websocketLogin(ctx context.Context, conn websocket.Connection, channel string) error {
|
||||
if conn == nil {
|
||||
return fmt.Errorf("%w: %T", common.ErrNilPointer, conn)
|
||||
}
|
||||
@@ -112,7 +112,7 @@ func (g *Gateio) websocketLogin(ctx context.Context, conn websocket.Connection,
|
||||
return errChannelEmpty
|
||||
}
|
||||
|
||||
creds, err := g.GetCredentials(ctx)
|
||||
creds, err := e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -156,7 +156,7 @@ func (g *Gateio) websocketLogin(ctx context.Context, conn websocket.Connection,
|
||||
return fmt.Errorf("%s: %s", wsErr.Errors.Label, wsErr.Errors.Message)
|
||||
}
|
||||
|
||||
func (g *Gateio) generateWsSignature(secret, event, channel string, t int64) (string, error) {
|
||||
func (e *Exchange) generateWsSignature(secret, event, channel string, t int64) (string, error) {
|
||||
msg := "channel=" + channel + "&event=" + event + "&time=" + strconv.FormatInt(t, 10)
|
||||
mac := hmac.New(sha512.New, []byte(secret))
|
||||
if _, err := mac.Write([]byte(msg)); err != nil {
|
||||
@@ -166,51 +166,51 @@ func (g *Gateio) generateWsSignature(secret, event, channel string, t int64) (st
|
||||
}
|
||||
|
||||
// WsHandleSpotData handles spot data
|
||||
func (g *Gateio) WsHandleSpotData(ctx context.Context, respRaw []byte) error {
|
||||
func (e *Exchange) WsHandleSpotData(ctx context.Context, respRaw []byte) error {
|
||||
push, err := parseWSHeader(respRaw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if push.RequestID != "" {
|
||||
return g.Websocket.Match.RequireMatchWithData(push.RequestID, respRaw)
|
||||
return e.Websocket.Match.RequireMatchWithData(push.RequestID, respRaw)
|
||||
}
|
||||
|
||||
if push.Event == subscribeEvent || push.Event == unsubscribeEvent {
|
||||
return g.Websocket.Match.RequireMatchWithData(push.ID, respRaw)
|
||||
return e.Websocket.Match.RequireMatchWithData(push.ID, respRaw)
|
||||
}
|
||||
|
||||
switch push.Channel { // TODO: Convert function params below to only use push.Result
|
||||
case spotTickerChannel:
|
||||
return g.processTicker(push.Result, push.Time)
|
||||
return e.processTicker(push.Result, push.Time)
|
||||
case spotTradesChannel:
|
||||
return g.processTrades(push.Result)
|
||||
return e.processTrades(push.Result)
|
||||
case spotCandlesticksChannel:
|
||||
return g.processCandlestick(push.Result)
|
||||
return e.processCandlestick(push.Result)
|
||||
case spotOrderbookTickerChannel:
|
||||
return g.processOrderbookTicker(push.Result, push.Time)
|
||||
return e.processOrderbookTicker(push.Result, push.Time)
|
||||
case spotOrderbookUpdateChannel:
|
||||
return g.processOrderbookUpdate(ctx, push.Result, push.Time)
|
||||
return e.processOrderbookUpdate(ctx, push.Result, push.Time)
|
||||
case spotOrderbookChannel:
|
||||
return g.processOrderbookSnapshot(push.Result, push.Time)
|
||||
return e.processOrderbookSnapshot(push.Result, push.Time)
|
||||
case spotOrdersChannel:
|
||||
return g.processSpotOrders(respRaw)
|
||||
return e.processSpotOrders(respRaw)
|
||||
case spotUserTradesChannel:
|
||||
return g.processUserPersonalTrades(respRaw)
|
||||
return e.processUserPersonalTrades(respRaw)
|
||||
case spotBalancesChannel:
|
||||
return g.processSpotBalances(ctx, respRaw)
|
||||
return e.processSpotBalances(ctx, respRaw)
|
||||
case marginBalancesChannel:
|
||||
return g.processMarginBalances(ctx, respRaw)
|
||||
return e.processMarginBalances(ctx, respRaw)
|
||||
case spotFundingBalanceChannel:
|
||||
return g.processFundingBalances(respRaw)
|
||||
return e.processFundingBalances(respRaw)
|
||||
case crossMarginBalanceChannel:
|
||||
return g.processCrossMarginBalance(ctx, respRaw)
|
||||
return e.processCrossMarginBalance(ctx, respRaw)
|
||||
case crossMarginLoanChannel:
|
||||
return g.processCrossMarginLoans(respRaw)
|
||||
return e.processCrossMarginLoans(respRaw)
|
||||
case spotPongChannel:
|
||||
default:
|
||||
g.Websocket.DataHandler <- websocket.UnhandledMessageWarning{
|
||||
Message: g.Name + websocket.UnhandledMessage + string(respRaw),
|
||||
e.Websocket.DataHandler <- websocket.UnhandledMessageWarning{
|
||||
Message: e.Name + websocket.UnhandledMessage + string(respRaw),
|
||||
}
|
||||
return errors.New(websocket.UnhandledMessage)
|
||||
}
|
||||
@@ -256,16 +256,16 @@ func parseWSHeader(msg []byte) (r *WSResponse, errs error) {
|
||||
return r, errs
|
||||
}
|
||||
|
||||
func (g *Gateio) processTicker(incoming []byte, pushTime time.Time) error {
|
||||
func (e *Exchange) processTicker(incoming []byte, pushTime time.Time) error {
|
||||
var data WsTicker
|
||||
if err := json.Unmarshal(incoming, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
out := make([]ticker.Price, 0, len(standardMarginAssetTypes))
|
||||
for _, a := range standardMarginAssetTypes {
|
||||
if enabled, _ := g.CurrencyPairs.IsPairEnabled(data.CurrencyPair, a); enabled {
|
||||
if enabled, _ := e.CurrencyPairs.IsPairEnabled(data.CurrencyPair, a); enabled {
|
||||
out = append(out, ticker.Price{
|
||||
ExchangeName: g.Name,
|
||||
ExchangeName: e.Name,
|
||||
Volume: data.BaseVolume.Float64(),
|
||||
QuoteVolume: data.QuoteVolume.Float64(),
|
||||
High: data.High24H.Float64(),
|
||||
@@ -279,13 +279,13 @@ func (g *Gateio) processTicker(incoming []byte, pushTime time.Time) error {
|
||||
})
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- out
|
||||
e.Websocket.DataHandler <- out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processTrades(incoming []byte) error {
|
||||
saveTradeData := g.IsSaveTradeDataEnabled()
|
||||
if !saveTradeData && !g.IsTradeFeedEnabled() {
|
||||
func (e *Exchange) processTrades(incoming []byte) error {
|
||||
saveTradeData := e.IsSaveTradeDataEnabled()
|
||||
if !saveTradeData && !e.IsTradeFeedEnabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -300,12 +300,12 @@ func (g *Gateio) processTrades(incoming []byte) error {
|
||||
}
|
||||
|
||||
for _, a := range standardMarginAssetTypes {
|
||||
if enabled, _ := g.CurrencyPairs.IsPairEnabled(data.CurrencyPair, a); enabled {
|
||||
if err := g.Websocket.Trade.Update(saveTradeData, trade.Data{
|
||||
if enabled, _ := e.CurrencyPairs.IsPairEnabled(data.CurrencyPair, a); enabled {
|
||||
if err := e.Websocket.Trade.Update(saveTradeData, trade.Data{
|
||||
Timestamp: data.CreateTime.Time(),
|
||||
CurrencyPair: data.CurrencyPair,
|
||||
AssetType: a,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
Price: data.Price.Float64(),
|
||||
Amount: data.Amount.Float64(),
|
||||
Side: side,
|
||||
@@ -319,7 +319,7 @@ func (g *Gateio) processTrades(incoming []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processCandlestick(incoming []byte) error {
|
||||
func (e *Exchange) processCandlestick(incoming []byte) error {
|
||||
var data WsCandlesticks
|
||||
if err := json.Unmarshal(incoming, &data); err != nil {
|
||||
return err
|
||||
@@ -335,11 +335,11 @@ func (g *Gateio) processCandlestick(incoming []byte) error {
|
||||
|
||||
out := make([]websocket.KlineData, 0, len(standardMarginAssetTypes))
|
||||
for _, a := range standardMarginAssetTypes {
|
||||
if enabled, _ := g.CurrencyPairs.IsPairEnabled(currencyPair, a); enabled {
|
||||
if enabled, _ := e.CurrencyPairs.IsPairEnabled(currencyPair, a); enabled {
|
||||
out = append(out, websocket.KlineData{
|
||||
Pair: currencyPair,
|
||||
AssetType: a,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
StartTime: data.Timestamp.Time(),
|
||||
Interval: icp[0],
|
||||
OpenPrice: data.OpenPrice.Float64(),
|
||||
@@ -350,17 +350,17 @@ func (g *Gateio) processCandlestick(incoming []byte) error {
|
||||
})
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- out
|
||||
e.Websocket.DataHandler <- out
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOrderbookTicker(incoming []byte, lastPushed time.Time) error {
|
||||
func (e *Exchange) processOrderbookTicker(incoming []byte, lastPushed time.Time) error {
|
||||
var data WsOrderbookTickerData
|
||||
if err := json.Unmarshal(incoming, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
return g.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
Exchange: g.Name,
|
||||
return e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
Exchange: e.Name,
|
||||
Pair: data.Pair,
|
||||
Asset: asset.Spot,
|
||||
LastUpdated: data.UpdateTime.Time(),
|
||||
@@ -370,7 +370,7 @@ func (g *Gateio) processOrderbookTicker(incoming []byte, lastPushed time.Time) e
|
||||
})
|
||||
}
|
||||
|
||||
func (g *Gateio) processOrderbookUpdate(ctx context.Context, incoming []byte, lastPushed time.Time) error {
|
||||
func (e *Exchange) processOrderbookUpdate(ctx context.Context, incoming []byte, lastPushed time.Time) error {
|
||||
var data WsOrderbookUpdate
|
||||
if err := json.Unmarshal(incoming, &data); err != nil {
|
||||
return err
|
||||
@@ -385,7 +385,7 @@ func (g *Gateio) processOrderbookUpdate(ctx context.Context, incoming []byte, la
|
||||
bids[x].Price = data.Bids[x][0].Float64()
|
||||
bids[x].Amount = data.Bids[x][1].Float64()
|
||||
}
|
||||
return g.wsOBUpdateMgr.ProcessOrderbookUpdate(ctx, g, data.FirstUpdateID, &orderbook.Update{
|
||||
return e.wsOBUpdateMgr.ProcessOrderbookUpdate(ctx, e, data.FirstUpdateID, &orderbook.Update{
|
||||
UpdateID: data.LastUpdateID,
|
||||
UpdateTime: data.UpdateTime.Time(),
|
||||
LastPushed: lastPushed,
|
||||
@@ -397,7 +397,7 @@ func (g *Gateio) processOrderbookUpdate(ctx context.Context, incoming []byte, la
|
||||
})
|
||||
}
|
||||
|
||||
func (g *Gateio) processOrderbookSnapshot(incoming []byte, lastPushed time.Time) error {
|
||||
func (e *Exchange) processOrderbookSnapshot(incoming []byte, lastPushed time.Time) error {
|
||||
var data WsOrderbookSnapshot
|
||||
if err := json.Unmarshal(incoming, &data); err != nil {
|
||||
return err
|
||||
@@ -415,9 +415,9 @@ func (g *Gateio) processOrderbookSnapshot(incoming []byte, lastPushed time.Time)
|
||||
}
|
||||
|
||||
for _, a := range standardMarginAssetTypes {
|
||||
if enabled, _ := g.CurrencyPairs.IsPairEnabled(data.CurrencyPair, a); enabled {
|
||||
if err := g.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
Exchange: g.Name,
|
||||
if enabled, _ := e.CurrencyPairs.IsPairEnabled(data.CurrencyPair, a); enabled {
|
||||
if err := e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
Exchange: e.Name,
|
||||
Pair: data.CurrencyPair,
|
||||
Asset: a,
|
||||
LastUpdated: data.UpdateTime.Time(),
|
||||
@@ -432,7 +432,7 @@ func (g *Gateio) processOrderbookSnapshot(incoming []byte, lastPushed time.Time)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processSpotOrders(data []byte) error {
|
||||
func (e *Exchange) processSpotOrders(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -459,7 +459,7 @@ func (g *Gateio) processSpotOrders(data []byte) error {
|
||||
}
|
||||
details[x] = order.Detail{
|
||||
Amount: resp.Result[x].Amount.Float64(),
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
OrderID: resp.Result[x].ID,
|
||||
Side: side,
|
||||
Type: orderType,
|
||||
@@ -472,12 +472,12 @@ func (g *Gateio) processSpotOrders(data []byte) error {
|
||||
LastUpdated: resp.Result[x].UpdateTime.Time(),
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- details
|
||||
e.Websocket.DataHandler <- details
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processUserPersonalTrades(data []byte) error {
|
||||
if !g.IsFillsFeedEnabled() {
|
||||
func (e *Exchange) processUserPersonalTrades(data []byte) error {
|
||||
if !e.IsFillsFeedEnabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -499,7 +499,7 @@ func (g *Gateio) processUserPersonalTrades(data []byte) error {
|
||||
}
|
||||
fills[x] = fill.Data{
|
||||
Timestamp: resp.Result[x].CreateTime.Time(),
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
CurrencyPair: resp.Result[x].CurrencyPair,
|
||||
Side: side,
|
||||
OrderID: resp.Result[x].OrderID,
|
||||
@@ -508,10 +508,10 @@ func (g *Gateio) processUserPersonalTrades(data []byte) error {
|
||||
Amount: resp.Result[x].Amount.Float64(),
|
||||
}
|
||||
}
|
||||
return g.Websocket.Fills.Update(fills...)
|
||||
return e.Websocket.Fills.Update(fills...)
|
||||
}
|
||||
|
||||
func (g *Gateio) processSpotBalances(ctx context.Context, data []byte) error {
|
||||
func (e *Exchange) processSpotBalances(ctx context.Context, data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -522,7 +522,7 @@ func (g *Gateio) processSpotBalances(ctx context.Context, data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
creds, err := g.GetCredentials(ctx)
|
||||
creds, err := e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -540,11 +540,11 @@ func (g *Gateio) processSpotBalances(ctx context.Context, data []byte) error {
|
||||
},
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- changes
|
||||
return account.ProcessChange(g.Name, changes, creds)
|
||||
e.Websocket.DataHandler <- changes
|
||||
return account.ProcessChange(e.Name, changes, creds)
|
||||
}
|
||||
|
||||
func (g *Gateio) processMarginBalances(ctx context.Context, data []byte) error {
|
||||
func (e *Exchange) processMarginBalances(ctx context.Context, data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -555,7 +555,7 @@ func (g *Gateio) processMarginBalances(ctx context.Context, data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
creds, err := g.GetCredentials(ctx)
|
||||
creds, err := e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -572,11 +572,11 @@ func (g *Gateio) processMarginBalances(ctx context.Context, data []byte) error {
|
||||
},
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- changes
|
||||
return account.ProcessChange(g.Name, changes, creds)
|
||||
e.Websocket.DataHandler <- changes
|
||||
return account.ProcessChange(e.Name, changes, creds)
|
||||
}
|
||||
|
||||
func (g *Gateio) processFundingBalances(data []byte) error {
|
||||
func (e *Exchange) processFundingBalances(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -587,11 +587,11 @@ func (g *Gateio) processFundingBalances(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- resp
|
||||
e.Websocket.DataHandler <- resp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processCrossMarginBalance(ctx context.Context, data []byte) error {
|
||||
func (e *Exchange) processCrossMarginBalance(ctx context.Context, data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -602,7 +602,7 @@ func (g *Gateio) processCrossMarginBalance(ctx context.Context, data []byte) err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
creds, err := g.GetCredentials(ctx)
|
||||
creds, err := e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -619,11 +619,11 @@ func (g *Gateio) processCrossMarginBalance(ctx context.Context, data []byte) err
|
||||
},
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- changes
|
||||
return account.ProcessChange(g.Name, changes, creds)
|
||||
e.Websocket.DataHandler <- changes
|
||||
return account.ProcessChange(e.Name, changes, creds)
|
||||
}
|
||||
|
||||
func (g *Gateio) processCrossMarginLoans(data []byte) error {
|
||||
func (e *Exchange) processCrossMarginLoans(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -634,17 +634,17 @@ func (g *Gateio) processCrossMarginLoans(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- resp
|
||||
e.Websocket.DataHandler <- resp
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateSubscriptionsSpot returns configured subscriptions
|
||||
func (g *Gateio) generateSubscriptionsSpot() (subscription.List, error) {
|
||||
return g.Features.Subscriptions.ExpandTemplates(g)
|
||||
func (e *Exchange) generateSubscriptionsSpot() (subscription.List, error) {
|
||||
return e.Features.Subscriptions.ExpandTemplates(e)
|
||||
}
|
||||
|
||||
// GetSubscriptionTemplate returns a subscription channel template
|
||||
func (g *Gateio) GetSubscriptionTemplate(_ *subscription.Subscription) (*template.Template, error) {
|
||||
func (e *Exchange) GetSubscriptionTemplate(_ *subscription.Subscription) (*template.Template, error) {
|
||||
return template.New("master.tmpl").
|
||||
Funcs(sprig.FuncMap()).
|
||||
Funcs(template.FuncMap{
|
||||
@@ -657,16 +657,16 @@ func (g *Gateio) GetSubscriptionTemplate(_ *subscription.Subscription) (*templat
|
||||
}
|
||||
|
||||
// manageSubs sends a websocket message to subscribe or unsubscribe from a list of channel
|
||||
func (g *Gateio) manageSubs(ctx context.Context, event string, conn websocket.Connection, subs subscription.List) error {
|
||||
func (e *Exchange) manageSubs(ctx context.Context, event string, conn websocket.Connection, subs subscription.List) error {
|
||||
var errs error
|
||||
subs, errs = subs.ExpandTemplates(g)
|
||||
subs, errs = subs.ExpandTemplates(e)
|
||||
if errs != nil {
|
||||
return errs
|
||||
}
|
||||
|
||||
for _, s := range subs {
|
||||
if err := func() error {
|
||||
msg, err := g.manageSubReq(ctx, event, conn, s)
|
||||
msg, err := e.manageSubReq(ctx, event, conn, s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -682,9 +682,9 @@ func (g *Gateio) manageSubs(ctx context.Context, event string, conn websocket.Co
|
||||
return fmt.Errorf("(%d) %s", resp.Error.Code, resp.Error.Message)
|
||||
}
|
||||
if event == "unsubscribe" {
|
||||
return g.Websocket.RemoveSubscriptions(conn, s)
|
||||
return e.Websocket.RemoveSubscriptions(conn, s)
|
||||
}
|
||||
return g.Websocket.AddSuccessfulSubscriptions(conn, s)
|
||||
return e.Websocket.AddSuccessfulSubscriptions(conn, s)
|
||||
}(); err != nil {
|
||||
errs = common.AppendError(errs, fmt.Errorf("%s %s %s: %w", s.Channel, s.Asset, s.Pairs, err))
|
||||
}
|
||||
@@ -693,7 +693,7 @@ func (g *Gateio) manageSubs(ctx context.Context, event string, conn websocket.Co
|
||||
}
|
||||
|
||||
// manageSubReq constructs the subscription management message for a subscription
|
||||
func (g *Gateio) manageSubReq(ctx context.Context, event string, conn websocket.Connection, s *subscription.Subscription) (*WsInput, error) {
|
||||
func (e *Exchange) manageSubReq(ctx context.Context, event string, conn websocket.Connection, s *subscription.Subscription) (*WsInput, error) {
|
||||
req := &WsInput{
|
||||
ID: conn.GenerateMessageID(false),
|
||||
Event: event,
|
||||
@@ -702,11 +702,11 @@ func (g *Gateio) manageSubReq(ctx context.Context, event string, conn websocket.
|
||||
Payload: strings.Split(s.QualifiedChannel, ","),
|
||||
}
|
||||
if s.Authenticated {
|
||||
creds, err := g.GetCredentials(ctx)
|
||||
creds, err := e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sig, err := g.generateWsSignature(creds.Secret, event, req.Channel, req.Time)
|
||||
sig, err := e.generateWsSignature(creds.Secret, event, req.Channel, req.Time)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -720,18 +720,18 @@ func (g *Gateio) manageSubReq(ctx context.Context, event string, conn websocket.
|
||||
}
|
||||
|
||||
// Subscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) Subscribe(ctx context.Context, conn websocket.Connection, subs subscription.List) error {
|
||||
return g.manageSubs(ctx, subscribeEvent, conn, subs)
|
||||
func (e *Exchange) Subscribe(ctx context.Context, conn websocket.Connection, subs subscription.List) error {
|
||||
return e.manageSubs(ctx, subscribeEvent, conn, subs)
|
||||
}
|
||||
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) Unsubscribe(ctx context.Context, conn websocket.Connection, subs subscription.List) error {
|
||||
return g.manageSubs(ctx, unsubscribeEvent, conn, subs)
|
||||
func (e *Exchange) Unsubscribe(ctx context.Context, conn websocket.Connection, subs subscription.List) error {
|
||||
return e.manageSubs(ctx, unsubscribeEvent, conn, subs)
|
||||
}
|
||||
|
||||
// GenerateWebsocketMessageID generates a message ID for the individual connection
|
||||
func (g *Gateio) GenerateWebsocketMessageID(bool) int64 {
|
||||
return g.Counter.IncrementAndGet()
|
||||
func (e *Exchange) GenerateWebsocketMessageID(bool) int64 {
|
||||
return e.Counter.IncrementAndGet()
|
||||
}
|
||||
|
||||
// channelName converts global channel names to gateio specific channel names
|
||||
@@ -754,7 +754,7 @@ func singleSymbolChannel(name string) bool {
|
||||
// ValidateSubscriptions implements the subscription.ListValidator interface.
|
||||
// It ensures that, for each orderbook pair asset, only one type of subscription (e.g., best bid/ask, orderbook update, or orderbook snapshot)
|
||||
// is active at a time. Multiple concurrent subscriptions for the same asset are disallowed to prevent orderbook data corruption.
|
||||
func (g *Gateio) ValidateSubscriptions(l subscription.List) error {
|
||||
func (e *Exchange) ValidateSubscriptions(l subscription.List) error {
|
||||
orderbookGuard := map[key.PairAsset]string{}
|
||||
for _, s := range l {
|
||||
n := channelName(s)
|
||||
@@ -920,7 +920,7 @@ const subTplText = `
|
||||
type GeneratePayload func(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error)
|
||||
|
||||
// handleSubscription sends a websocket message to receive data from the channel
|
||||
func (g *Gateio) handleSubscription(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List, generatePayload GeneratePayload) error {
|
||||
func (e *Exchange) handleSubscription(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List, generatePayload GeneratePayload) error {
|
||||
payloads, err := generatePayload(ctx, conn, event, channelsToSubscribe)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -941,9 +941,9 @@ func (g *Gateio) handleSubscription(ctx context.Context, conn websocket.Connecti
|
||||
continue
|
||||
}
|
||||
if event == subscribeEvent {
|
||||
errs = common.AppendError(errs, g.Websocket.AddSuccessfulSubscriptions(conn, channelsToSubscribe[k]))
|
||||
errs = common.AppendError(errs, e.Websocket.AddSuccessfulSubscriptions(conn, channelsToSubscribe[k]))
|
||||
} else {
|
||||
errs = common.AppendError(errs, g.Websocket.RemoveSubscriptions(conn, channelsToSubscribe[k]))
|
||||
errs = common.AppendError(errs, e.Websocket.RemoveSubscriptions(conn, channelsToSubscribe[k]))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -955,13 +955,13 @@ type resultHolder struct {
|
||||
}
|
||||
|
||||
// SendWebsocketRequest sends a websocket request to the exchange
|
||||
func (g *Gateio) SendWebsocketRequest(ctx context.Context, epl request.EndpointLimit, channel string, connSignature, params, result any, expectedResponses int) error {
|
||||
func (e *Exchange) SendWebsocketRequest(ctx context.Context, epl request.EndpointLimit, channel string, connSignature, params, result any, expectedResponses int) error {
|
||||
paramPayload, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conn, err := g.Websocket.GetConnection(connSignature)
|
||||
conn, err := e.Websocket.GetConnection(connSignature)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ var defaultDeliveryFuturesSubscriptions = []string{
|
||||
}
|
||||
|
||||
// WsDeliveryFuturesConnect initiates a websocket connection for delivery futures account
|
||||
func (g *Gateio) WsDeliveryFuturesConnect(ctx context.Context, conn websocket.Connection) error {
|
||||
if err := g.CurrencyPairs.IsAssetEnabled(asset.DeliveryFutures); err != nil {
|
||||
func (e *Exchange) WsDeliveryFuturesConnect(ctx context.Context, conn websocket.Connection) error {
|
||||
if err := e.CurrencyPairs.IsAssetEnabled(asset.DeliveryFutures); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := conn.Dial(ctx, &gws.Dialer{}, http.Header{}); err != nil {
|
||||
@@ -63,18 +63,18 @@ func (g *Gateio) WsDeliveryFuturesConnect(ctx context.Context, conn websocket.Co
|
||||
|
||||
// GenerateDeliveryFuturesDefaultSubscriptions returns delivery futures default subscriptions params.
|
||||
// TODO: Update to use the new subscription template system
|
||||
func (g *Gateio) GenerateDeliveryFuturesDefaultSubscriptions() (subscription.List, error) {
|
||||
func (e *Exchange) GenerateDeliveryFuturesDefaultSubscriptions() (subscription.List, error) {
|
||||
ctx := context.TODO()
|
||||
_, err := g.GetCredentials(ctx)
|
||||
_, err := e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
e.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
}
|
||||
channelsToSubscribe := defaultDeliveryFuturesSubscriptions
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
if e.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
channelsToSubscribe = append(channelsToSubscribe, futuresOrdersChannel, futuresUserTradesChannel, futuresBalancesChannel)
|
||||
}
|
||||
|
||||
pairs, err := g.GetEnabledPairs(asset.DeliveryFutures)
|
||||
pairs, err := e.GetEnabledPairs(asset.DeliveryFutures)
|
||||
if err != nil {
|
||||
if errors.Is(err, asset.ErrNotEnabled) {
|
||||
return nil, nil // no enabled pairs, subscriptions require an associated pair.
|
||||
@@ -96,7 +96,7 @@ func (g *Gateio) GenerateDeliveryFuturesDefaultSubscriptions() (subscription.Lis
|
||||
params["frequency"] = kline.HundredMilliseconds
|
||||
params["level"] = strconv.FormatUint(deliveryFuturesUpdateLimit, 10)
|
||||
}
|
||||
fPair, err := g.FormatExchangeCurrency(pairs[j], asset.DeliveryFutures)
|
||||
fPair, err := e.FormatExchangeCurrency(pairs[j], asset.DeliveryFutures)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -112,25 +112,25 @@ func (g *Gateio) GenerateDeliveryFuturesDefaultSubscriptions() (subscription.Lis
|
||||
}
|
||||
|
||||
// DeliveryFuturesSubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) DeliveryFuturesSubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return g.handleSubscription(ctx, conn, subscribeEvent, channelsToUnsubscribe, g.generateDeliveryFuturesPayload)
|
||||
func (e *Exchange) DeliveryFuturesSubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return e.handleSubscription(ctx, conn, subscribeEvent, channelsToUnsubscribe, e.generateDeliveryFuturesPayload)
|
||||
}
|
||||
|
||||
// DeliveryFuturesUnsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) DeliveryFuturesUnsubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return g.handleSubscription(ctx, conn, unsubscribeEvent, channelsToUnsubscribe, g.generateDeliveryFuturesPayload)
|
||||
func (e *Exchange) DeliveryFuturesUnsubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return e.handleSubscription(ctx, conn, unsubscribeEvent, channelsToUnsubscribe, e.generateDeliveryFuturesPayload)
|
||||
}
|
||||
|
||||
func (g *Gateio) generateDeliveryFuturesPayload(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
func (e *Exchange) generateDeliveryFuturesPayload(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
if len(channelsToSubscribe) == 0 {
|
||||
return nil, errors.New("cannot generate payload, no channels supplied")
|
||||
}
|
||||
var creds *account.Credentials
|
||||
var err error
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
creds, err = g.GetCredentials(ctx)
|
||||
if e.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
creds, err = e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
e.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
}
|
||||
}
|
||||
outbound := make([]WsInput, 0, len(channelsToSubscribe))
|
||||
@@ -142,7 +142,7 @@ func (g *Gateio) generateDeliveryFuturesPayload(ctx context.Context, conn websoc
|
||||
timestamp := time.Now()
|
||||
var params []string
|
||||
params = []string{channelsToSubscribe[i].Pairs[0].String()}
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
if e.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
switch channelsToSubscribe[i].Channel {
|
||||
case futuresOrdersChannel, futuresUserTradesChannel,
|
||||
futuresLiquidatesChannel, futuresAutoDeleveragesChannel,
|
||||
@@ -154,7 +154,7 @@ func (g *Gateio) generateDeliveryFuturesPayload(ctx context.Context, conn websoc
|
||||
params = append([]string{value}, params...)
|
||||
}
|
||||
var sigTemp string
|
||||
sigTemp, err = g.generateWsSignature(creds.Secret, event, channelsToSubscribe[i].Channel, timestamp.Unix())
|
||||
sigTemp, err = e.generateWsSignature(creds.Secret, event, channelsToSubscribe[i].Channel, timestamp.Unix())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -58,12 +58,12 @@ var defaultFuturesSubscriptions = []string{
|
||||
}
|
||||
|
||||
// WsFuturesConnect initiates a websocket connection for futures account
|
||||
func (g *Gateio) WsFuturesConnect(ctx context.Context, conn websocket.Connection) error {
|
||||
func (e *Exchange) WsFuturesConnect(ctx context.Context, conn websocket.Connection) error {
|
||||
a := asset.USDTMarginedFutures
|
||||
if conn.GetURL() == btcFuturesWebsocketURL {
|
||||
a = asset.CoinMarginedFutures
|
||||
}
|
||||
if err := g.CurrencyPairs.IsAssetEnabled(a); err != nil {
|
||||
if err := e.CurrencyPairs.IsAssetEnabled(a); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := conn.Dial(ctx, &gws.Dialer{}, http.Header{}); err != nil {
|
||||
@@ -88,13 +88,13 @@ func (g *Gateio) WsFuturesConnect(ctx context.Context, conn websocket.Connection
|
||||
|
||||
// GenerateFuturesDefaultSubscriptions returns default subscriptions information.
|
||||
// TODO: Update to use the new subscription template system
|
||||
func (g *Gateio) GenerateFuturesDefaultSubscriptions(a asset.Item) (subscription.List, error) {
|
||||
func (e *Exchange) GenerateFuturesDefaultSubscriptions(a asset.Item) (subscription.List, error) {
|
||||
channelsToSubscribe := defaultFuturesSubscriptions
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
if e.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
channelsToSubscribe = append(channelsToSubscribe, futuresOrdersChannel, futuresUserTradesChannel, futuresBalancesChannel)
|
||||
}
|
||||
|
||||
pairs, err := g.GetEnabledPairs(a)
|
||||
pairs, err := e.GetEnabledPairs(a)
|
||||
if err != nil {
|
||||
if errors.Is(err, asset.ErrNotEnabled) {
|
||||
return nil, nil // no enabled pairs, subscriptions require an associated pair.
|
||||
@@ -117,7 +117,7 @@ func (g *Gateio) GenerateFuturesDefaultSubscriptions(a asset.Item) (subscription
|
||||
params["frequency"] = kline.TwentyMilliseconds
|
||||
params["level"] = strconv.FormatUint(futuresOrderbookUpdateLimit, 10)
|
||||
}
|
||||
fPair, err := g.FormatExchangeCurrency(pairs[j], a)
|
||||
fPair, err := e.FormatExchangeCurrency(pairs[j], a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -133,84 +133,84 @@ func (g *Gateio) GenerateFuturesDefaultSubscriptions(a asset.Item) (subscription
|
||||
}
|
||||
|
||||
// FuturesSubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) FuturesSubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return g.handleSubscription(ctx, conn, subscribeEvent, channelsToUnsubscribe, g.generateFuturesPayload)
|
||||
func (e *Exchange) FuturesSubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return e.handleSubscription(ctx, conn, subscribeEvent, channelsToUnsubscribe, e.generateFuturesPayload)
|
||||
}
|
||||
|
||||
// FuturesUnsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (g *Gateio) FuturesUnsubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return g.handleSubscription(ctx, conn, unsubscribeEvent, channelsToUnsubscribe, g.generateFuturesPayload)
|
||||
func (e *Exchange) FuturesUnsubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return e.handleSubscription(ctx, conn, unsubscribeEvent, channelsToUnsubscribe, e.generateFuturesPayload)
|
||||
}
|
||||
|
||||
// WsHandleFuturesData handles futures websocket data
|
||||
func (g *Gateio) WsHandleFuturesData(ctx context.Context, respRaw []byte, a asset.Item) error {
|
||||
func (e *Exchange) WsHandleFuturesData(ctx context.Context, respRaw []byte, a asset.Item) error {
|
||||
push, err := parseWSHeader(respRaw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if push.RequestID != "" {
|
||||
return g.Websocket.Match.RequireMatchWithData(push.RequestID, respRaw)
|
||||
return e.Websocket.Match.RequireMatchWithData(push.RequestID, respRaw)
|
||||
}
|
||||
|
||||
if push.Event == subscribeEvent || push.Event == unsubscribeEvent {
|
||||
return g.Websocket.Match.RequireMatchWithData(push.ID, respRaw)
|
||||
return e.Websocket.Match.RequireMatchWithData(push.ID, respRaw)
|
||||
}
|
||||
|
||||
switch push.Channel {
|
||||
case futuresTickersChannel:
|
||||
return g.processFuturesTickers(respRaw, a)
|
||||
return e.processFuturesTickers(respRaw, a)
|
||||
case futuresTradesChannel:
|
||||
return g.processFuturesTrades(respRaw, a)
|
||||
return e.processFuturesTrades(respRaw, a)
|
||||
case futuresOrderbookChannel:
|
||||
return g.processFuturesOrderbookSnapshot(push.Event, push.Result, a, push.Time)
|
||||
return e.processFuturesOrderbookSnapshot(push.Event, push.Result, a, push.Time)
|
||||
case futuresOrderbookTickerChannel:
|
||||
return g.processFuturesOrderbookTicker(push.Result)
|
||||
return e.processFuturesOrderbookTicker(push.Result)
|
||||
case futuresOrderbookUpdateChannel:
|
||||
return g.processFuturesOrderbookUpdate(ctx, push.Result, a, push.Time)
|
||||
return e.processFuturesOrderbookUpdate(ctx, push.Result, a, push.Time)
|
||||
case futuresCandlesticksChannel:
|
||||
return g.processFuturesCandlesticks(respRaw, a)
|
||||
return e.processFuturesCandlesticks(respRaw, a)
|
||||
case futuresOrdersChannel:
|
||||
processed, err := g.processFuturesOrdersPushData(respRaw, a)
|
||||
processed, err := e.processFuturesOrdersPushData(respRaw, a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- processed
|
||||
e.Websocket.DataHandler <- processed
|
||||
return nil
|
||||
case futuresUserTradesChannel:
|
||||
return g.procesFuturesUserTrades(respRaw, a)
|
||||
return e.procesFuturesUserTrades(respRaw, a)
|
||||
case futuresLiquidatesChannel:
|
||||
return g.processFuturesLiquidatesNotification(respRaw)
|
||||
return e.processFuturesLiquidatesNotification(respRaw)
|
||||
case futuresAutoDeleveragesChannel:
|
||||
return g.processFuturesAutoDeleveragesNotification(respRaw)
|
||||
return e.processFuturesAutoDeleveragesNotification(respRaw)
|
||||
case futuresAutoPositionCloseChannel:
|
||||
return g.processPositionCloseData(respRaw)
|
||||
return e.processPositionCloseData(respRaw)
|
||||
case futuresBalancesChannel:
|
||||
return g.processBalancePushData(ctx, respRaw, a)
|
||||
return e.processBalancePushData(ctx, respRaw, a)
|
||||
case futuresReduceRiskLimitsChannel:
|
||||
return g.processFuturesReduceRiskLimitNotification(respRaw)
|
||||
return e.processFuturesReduceRiskLimitNotification(respRaw)
|
||||
case futuresPositionsChannel:
|
||||
return g.processFuturesPositionsNotification(respRaw)
|
||||
return e.processFuturesPositionsNotification(respRaw)
|
||||
case futuresAutoOrdersChannel:
|
||||
return g.processFuturesAutoOrderPushData(respRaw)
|
||||
return e.processFuturesAutoOrderPushData(respRaw)
|
||||
default:
|
||||
g.Websocket.DataHandler <- websocket.UnhandledMessageWarning{
|
||||
Message: g.Name + websocket.UnhandledMessage + string(respRaw),
|
||||
e.Websocket.DataHandler <- websocket.UnhandledMessageWarning{
|
||||
Message: e.Name + websocket.UnhandledMessage + string(respRaw),
|
||||
}
|
||||
return errors.New(websocket.UnhandledMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gateio) generateFuturesPayload(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
func (e *Exchange) generateFuturesPayload(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
if len(channelsToSubscribe) == 0 {
|
||||
return nil, errors.New("cannot generate payload, no channels supplied")
|
||||
}
|
||||
var creds *account.Credentials
|
||||
var err error
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
creds, err = g.GetCredentials(ctx)
|
||||
if e.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
creds, err = e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
e.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ func (g *Gateio) generateFuturesPayload(ctx context.Context, conn websocket.Conn
|
||||
timestamp := time.Now()
|
||||
var params []string
|
||||
params = []string{channelsToSubscribe[i].Pairs[0].String()}
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
if e.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
switch channelsToSubscribe[i].Channel {
|
||||
case futuresOrdersChannel, futuresUserTradesChannel,
|
||||
futuresLiquidatesChannel, futuresAutoDeleveragesChannel,
|
||||
@@ -237,7 +237,7 @@ func (g *Gateio) generateFuturesPayload(ctx context.Context, conn websocket.Conn
|
||||
params...)
|
||||
}
|
||||
var sigTemp string
|
||||
sigTemp, err = g.generateWsSignature(creds.Secret, event, channelsToSubscribe[i].Channel, timestamp.Unix())
|
||||
sigTemp, err = e.generateWsSignature(creds.Secret, event, channelsToSubscribe[i].Channel, timestamp.Unix())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -298,7 +298,7 @@ func (g *Gateio) generateFuturesPayload(ctx context.Context, conn websocket.Conn
|
||||
return outbound, nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesTickers(data []byte, assetType asset.Item) error {
|
||||
func (e *Exchange) processFuturesTickers(data []byte, assetType asset.Item) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -312,7 +312,7 @@ func (g *Gateio) processFuturesTickers(data []byte, assetType asset.Item) error
|
||||
tickerPriceDatas := make([]ticker.Price, len(resp.Result))
|
||||
for x := range resp.Result {
|
||||
tickerPriceDatas[x] = ticker.Price{
|
||||
ExchangeName: g.Name,
|
||||
ExchangeName: e.Name,
|
||||
Volume: resp.Result[x].Volume24HBase.Float64(),
|
||||
QuoteVolume: resp.Result[x].Volume24HQuote.Float64(),
|
||||
High: resp.Result[x].High24H.Float64(),
|
||||
@@ -323,13 +323,13 @@ func (g *Gateio) processFuturesTickers(data []byte, assetType asset.Item) error
|
||||
LastUpdated: resp.Time.Time(),
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- tickerPriceDatas
|
||||
e.Websocket.DataHandler <- tickerPriceDatas
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesTrades(data []byte, assetType asset.Item) error {
|
||||
saveTradeData := g.IsSaveTradeDataEnabled()
|
||||
if !saveTradeData && !g.IsTradeFeedEnabled() {
|
||||
func (e *Exchange) processFuturesTrades(data []byte, assetType asset.Item) error {
|
||||
saveTradeData := e.IsSaveTradeDataEnabled()
|
||||
if !saveTradeData && !e.IsTradeFeedEnabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -350,16 +350,16 @@ func (g *Gateio) processFuturesTrades(data []byte, assetType asset.Item) error {
|
||||
Timestamp: resp.Result[x].CreateTime.Time(),
|
||||
CurrencyPair: resp.Result[x].Contract,
|
||||
AssetType: assetType,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
Price: resp.Result[x].Price.Float64(),
|
||||
Amount: resp.Result[x].Size,
|
||||
TID: strconv.FormatInt(resp.Result[x].ID, 10),
|
||||
}
|
||||
}
|
||||
return g.Websocket.Trade.Update(saveTradeData, trades...)
|
||||
return e.Websocket.Trade.Update(saveTradeData, trades...)
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesCandlesticks(data []byte, assetType asset.Item) error {
|
||||
func (e *Exchange) processFuturesCandlesticks(data []byte, assetType asset.Item) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -383,7 +383,7 @@ func (g *Gateio) processFuturesCandlesticks(data []byte, assetType asset.Item) e
|
||||
klineDatas[x] = websocket.KlineData{
|
||||
Pair: currencyPair,
|
||||
AssetType: assetType,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
StartTime: resp.Result[x].Timestamp.Time(),
|
||||
Interval: icp[0],
|
||||
OpenPrice: resp.Result[x].OpenPrice.Float64(),
|
||||
@@ -393,21 +393,21 @@ func (g *Gateio) processFuturesCandlesticks(data []byte, assetType asset.Item) e
|
||||
Volume: resp.Result[x].Volume,
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- klineDatas
|
||||
e.Websocket.DataHandler <- klineDatas
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesOrderbookTicker(incoming []byte) error {
|
||||
func (e *Exchange) processFuturesOrderbookTicker(incoming []byte) error {
|
||||
var data WsFuturesOrderbookTicker
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- data
|
||||
e.Websocket.DataHandler <- data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesOrderbookUpdate(ctx context.Context, incoming []byte, a asset.Item, pushTime time.Time) error {
|
||||
func (e *Exchange) processFuturesOrderbookUpdate(ctx context.Context, incoming []byte, a asset.Item, pushTime time.Time) error {
|
||||
var data WsFuturesAndOptionsOrderbookUpdate
|
||||
if err := json.Unmarshal(incoming, &data); err != nil {
|
||||
return err
|
||||
@@ -423,7 +423,7 @@ func (g *Gateio) processFuturesOrderbookUpdate(ctx context.Context, incoming []b
|
||||
bids[x].Amount = data.Bids[x].Size
|
||||
}
|
||||
|
||||
return g.wsOBUpdateMgr.ProcessOrderbookUpdate(ctx, g, data.FirstUpdatedID, &orderbook.Update{
|
||||
return e.wsOBUpdateMgr.ProcessOrderbookUpdate(ctx, e, data.FirstUpdatedID, &orderbook.Update{
|
||||
UpdateID: data.LastUpdatedID,
|
||||
UpdateTime: data.Timestamp.Time(),
|
||||
LastPushed: pushTime,
|
||||
@@ -435,7 +435,7 @@ func (g *Gateio) processFuturesOrderbookUpdate(ctx context.Context, incoming []b
|
||||
})
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesOrderbookSnapshot(event string, incoming []byte, assetType asset.Item, lastPushed time.Time) error {
|
||||
func (e *Exchange) processFuturesOrderbookSnapshot(event string, incoming []byte, assetType asset.Item, lastPushed time.Time) error {
|
||||
if event == "all" {
|
||||
var data WsFuturesOrderbookSnapshot
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
@@ -444,11 +444,11 @@ func (g *Gateio) processFuturesOrderbookSnapshot(event string, incoming []byte,
|
||||
}
|
||||
base := orderbook.Book{
|
||||
Asset: assetType,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
Pair: data.Contract,
|
||||
LastUpdated: data.Timestamp.Time(),
|
||||
LastPushed: lastPushed,
|
||||
ValidateOrderbook: g.ValidateOrderbook,
|
||||
ValidateOrderbook: e.ValidateOrderbook,
|
||||
}
|
||||
base.Asks = make([]orderbook.Level, len(data.Asks))
|
||||
for x := range data.Asks {
|
||||
@@ -460,7 +460,7 @@ func (g *Gateio) processFuturesOrderbookSnapshot(event string, incoming []byte,
|
||||
base.Bids[x].Amount = data.Bids[x].Size
|
||||
base.Bids[x].Price = data.Bids[x].Price.Float64()
|
||||
}
|
||||
return g.Websocket.Orderbook.LoadSnapshot(&base)
|
||||
return e.Websocket.Orderbook.LoadSnapshot(&base)
|
||||
}
|
||||
var data []WsFuturesOrderbookUpdateEvent
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
@@ -496,15 +496,15 @@ func (g *Gateio) processFuturesOrderbookSnapshot(event string, incoming []byte,
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = g.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
err = e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
Asks: ab[0],
|
||||
Bids: ab[1],
|
||||
Asset: assetType,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
Pair: currencyPair,
|
||||
LastUpdated: lastPushed,
|
||||
LastPushed: lastPushed,
|
||||
ValidateOrderbook: g.ValidateOrderbook,
|
||||
ValidateOrderbook: e.ValidateOrderbook,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -513,7 +513,7 @@ func (g *Gateio) processFuturesOrderbookSnapshot(event string, incoming []byte,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesOrdersPushData(data []byte, assetType asset.Item) ([]order.Detail, error) {
|
||||
func (e *Exchange) processFuturesOrdersPushData(data []byte, assetType asset.Item) ([]order.Detail, error) {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -537,8 +537,8 @@ func (g *Gateio) processFuturesOrdersPushData(data []byte, assetType asset.Item)
|
||||
status, err = order.StringToOrderStatus(resp.Result[x].Status)
|
||||
}
|
||||
if err != nil {
|
||||
g.Websocket.DataHandler <- order.ClassificationError{
|
||||
Exchange: g.Name,
|
||||
e.Websocket.DataHandler <- order.ClassificationError{
|
||||
Exchange: e.Name,
|
||||
OrderID: strconv.FormatInt(resp.Result[x].ID, 10),
|
||||
Err: err,
|
||||
}
|
||||
@@ -546,7 +546,7 @@ func (g *Gateio) processFuturesOrdersPushData(data []byte, assetType asset.Item)
|
||||
|
||||
orderDetails[x] = order.Detail{
|
||||
Amount: resp.Result[x].Size,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
OrderID: strconv.FormatInt(resp.Result[x].ID, 10),
|
||||
Status: status,
|
||||
Pair: resp.Result[x].Contract,
|
||||
@@ -562,8 +562,8 @@ func (g *Gateio) processFuturesOrdersPushData(data []byte, assetType asset.Item)
|
||||
return orderDetails, nil
|
||||
}
|
||||
|
||||
func (g *Gateio) procesFuturesUserTrades(data []byte, assetType asset.Item) error {
|
||||
if !g.IsFillsFeedEnabled() {
|
||||
func (e *Exchange) procesFuturesUserTrades(data []byte, assetType asset.Item) error {
|
||||
if !e.IsFillsFeedEnabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -581,7 +581,7 @@ func (g *Gateio) procesFuturesUserTrades(data []byte, assetType asset.Item) erro
|
||||
for x := range resp.Result {
|
||||
fills[x] = fill.Data{
|
||||
Timestamp: resp.Result[x].CreateTime.Time(),
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
CurrencyPair: resp.Result[x].Contract,
|
||||
OrderID: resp.Result[x].OrderID,
|
||||
TradeID: resp.Result[x].ID,
|
||||
@@ -590,10 +590,10 @@ func (g *Gateio) procesFuturesUserTrades(data []byte, assetType asset.Item) erro
|
||||
AssetType: assetType,
|
||||
}
|
||||
}
|
||||
return g.Websocket.Fills.Update(fills...)
|
||||
return e.Websocket.Fills.Update(fills...)
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesLiquidatesNotification(data []byte) error {
|
||||
func (e *Exchange) processFuturesLiquidatesNotification(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -604,11 +604,11 @@ func (g *Gateio) processFuturesLiquidatesNotification(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &resp
|
||||
e.Websocket.DataHandler <- &resp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesAutoDeleveragesNotification(data []byte) error {
|
||||
func (e *Exchange) processFuturesAutoDeleveragesNotification(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -619,11 +619,11 @@ func (g *Gateio) processFuturesAutoDeleveragesNotification(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &resp
|
||||
e.Websocket.DataHandler <- &resp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processPositionCloseData(data []byte) error {
|
||||
func (e *Exchange) processPositionCloseData(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -634,11 +634,11 @@ func (g *Gateio) processPositionCloseData(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &resp
|
||||
e.Websocket.DataHandler <- &resp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processBalancePushData(ctx context.Context, data []byte, assetType asset.Item) error {
|
||||
func (e *Exchange) processBalancePushData(ctx context.Context, data []byte, assetType asset.Item) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -649,7 +649,7 @@ func (g *Gateio) processBalancePushData(ctx context.Context, data []byte, assetT
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
creds, err := g.GetCredentials(ctx)
|
||||
creds, err := e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -670,11 +670,11 @@ func (g *Gateio) processBalancePushData(ctx context.Context, data []byte, assetT
|
||||
},
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- changes
|
||||
return account.ProcessChange(g.Name, changes, creds)
|
||||
e.Websocket.DataHandler <- changes
|
||||
return account.ProcessChange(e.Name, changes, creds)
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesReduceRiskLimitNotification(data []byte) error {
|
||||
func (e *Exchange) processFuturesReduceRiskLimitNotification(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -685,11 +685,11 @@ func (g *Gateio) processFuturesReduceRiskLimitNotification(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &resp
|
||||
e.Websocket.DataHandler <- &resp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesPositionsNotification(data []byte) error {
|
||||
func (e *Exchange) processFuturesPositionsNotification(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -700,11 +700,11 @@ func (g *Gateio) processFuturesPositionsNotification(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &resp
|
||||
e.Websocket.DataHandler <- &resp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processFuturesAutoOrderPushData(data []byte) error {
|
||||
func (e *Exchange) processFuturesAutoOrderPushData(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -715,6 +715,6 @@ func (g *Gateio) processFuturesAutoOrderPushData(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &resp
|
||||
e.Websocket.DataHandler <- &resp
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ var defaultOptionsSubscriptions = []string{
|
||||
}
|
||||
|
||||
// WsOptionsConnect initiates a websocket connection to options websocket endpoints.
|
||||
func (g *Gateio) WsOptionsConnect(ctx context.Context, conn websocket.Connection) error {
|
||||
err := g.CurrencyPairs.IsAssetEnabled(asset.Options)
|
||||
func (e *Exchange) WsOptionsConnect(ctx context.Context, conn websocket.Connection) error {
|
||||
err := e.CurrencyPairs.IsAssetEnabled(asset.Options)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -95,18 +95,18 @@ func (g *Gateio) WsOptionsConnect(ctx context.Context, conn websocket.Connection
|
||||
|
||||
// GenerateOptionsDefaultSubscriptions generates list of channel subscriptions for options asset type.
|
||||
// TODO: Update to use the new subscription template system
|
||||
func (g *Gateio) GenerateOptionsDefaultSubscriptions() (subscription.List, error) {
|
||||
func (e *Exchange) GenerateOptionsDefaultSubscriptions() (subscription.List, error) {
|
||||
ctx := context.TODO()
|
||||
channelsToSubscribe := defaultOptionsSubscriptions
|
||||
var userID int64
|
||||
if g.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
if e.Websocket.CanUseAuthenticatedEndpoints() {
|
||||
var err error
|
||||
_, err = g.GetCredentials(ctx)
|
||||
_, err = e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
e.Websocket.SetCanUseAuthenticatedEndpoints(false)
|
||||
goto getEnabledPairs
|
||||
}
|
||||
response, err := g.GetSubAccountBalances(ctx, "")
|
||||
response, err := e.GetSubAccountBalances(ctx, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -116,14 +116,14 @@ func (g *Gateio) GenerateOptionsDefaultSubscriptions() (subscription.List, error
|
||||
optionsBalancesChannel,
|
||||
)
|
||||
userID = response[0].UserID
|
||||
} else if g.Verbose {
|
||||
} else if e.Verbose {
|
||||
log.Errorf(log.ExchangeSys, "no subaccount found for authenticated options channel subscriptions")
|
||||
}
|
||||
}
|
||||
|
||||
getEnabledPairs:
|
||||
|
||||
pairs, err := g.GetEnabledPairs(asset.Options)
|
||||
pairs, err := e.GetEnabledPairs(asset.Options)
|
||||
if err != nil {
|
||||
if errors.Is(err, asset.ErrNotEnabled) {
|
||||
return nil, nil // no enabled pairs, subscriptions require an associated pair.
|
||||
@@ -156,7 +156,7 @@ getEnabledPairs:
|
||||
}
|
||||
params["user_id"] = userID
|
||||
}
|
||||
fPair, err := g.FormatExchangeCurrency(pairs[j], asset.Options)
|
||||
fPair, err := e.FormatExchangeCurrency(pairs[j], asset.Options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -171,7 +171,7 @@ getEnabledPairs:
|
||||
return subscriptions, nil
|
||||
}
|
||||
|
||||
func (g *Gateio) generateOptionsPayload(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
func (e *Exchange) generateOptionsPayload(ctx context.Context, conn websocket.Connection, event string, channelsToSubscribe subscription.List) ([]WsInput, error) {
|
||||
if len(channelsToSubscribe) == 0 {
|
||||
return nil, errors.New("cannot generate payload, no channels supplied")
|
||||
}
|
||||
@@ -191,7 +191,7 @@ func (g *Gateio) generateOptionsPayload(ctx context.Context, conn websocket.Conn
|
||||
optionsUnderlyingPriceChannel,
|
||||
optionsUnderlyingCandlesticksChannel:
|
||||
var uly currency.Pair
|
||||
uly, err = g.GetUnderlyingFromCurrencyPair(channelsToSubscribe[i].Pairs[0])
|
||||
uly, err = e.GetUnderlyingFromCurrencyPair(channelsToSubscribe[i].Pairs[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -230,12 +230,12 @@ func (g *Gateio) generateOptionsPayload(ctx context.Context, conn websocket.Conn
|
||||
}
|
||||
params = append([]string{strconv.FormatInt(userID, 10)}, params...)
|
||||
var creds *account.Credentials
|
||||
creds, err = g.GetCredentials(ctx)
|
||||
creds, err = e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var sigTemp string
|
||||
sigTemp, err = g.generateWsSignature(creds.Secret, event, channelsToSubscribe[i].Channel, timestamp.Unix())
|
||||
sigTemp, err = e.generateWsSignature(creds.Secret, event, channelsToSubscribe[i].Channel, timestamp.Unix())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -285,106 +285,106 @@ func (g *Gateio) generateOptionsPayload(ctx context.Context, conn websocket.Conn
|
||||
}
|
||||
|
||||
// OptionsSubscribe sends a websocket message to stop receiving data for asset type options
|
||||
func (g *Gateio) OptionsSubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return g.handleSubscription(ctx, conn, subscribeEvent, channelsToUnsubscribe, g.generateOptionsPayload)
|
||||
func (e *Exchange) OptionsSubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return e.handleSubscription(ctx, conn, subscribeEvent, channelsToUnsubscribe, e.generateOptionsPayload)
|
||||
}
|
||||
|
||||
// OptionsUnsubscribe sends a websocket message to stop receiving data for asset type options
|
||||
func (g *Gateio) OptionsUnsubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return g.handleSubscription(ctx, conn, unsubscribeEvent, channelsToUnsubscribe, g.generateOptionsPayload)
|
||||
func (e *Exchange) OptionsUnsubscribe(ctx context.Context, conn websocket.Connection, channelsToUnsubscribe subscription.List) error {
|
||||
return e.handleSubscription(ctx, conn, unsubscribeEvent, channelsToUnsubscribe, e.generateOptionsPayload)
|
||||
}
|
||||
|
||||
// WsHandleOptionsData handles options websocket data
|
||||
func (g *Gateio) WsHandleOptionsData(ctx context.Context, respRaw []byte) error {
|
||||
func (e *Exchange) WsHandleOptionsData(ctx context.Context, respRaw []byte) error {
|
||||
push, err := parseWSHeader(respRaw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if push.Event == subscribeEvent || push.Event == unsubscribeEvent {
|
||||
return g.Websocket.Match.RequireMatchWithData(push.ID, respRaw)
|
||||
return e.Websocket.Match.RequireMatchWithData(push.ID, respRaw)
|
||||
}
|
||||
|
||||
switch push.Channel {
|
||||
case optionsContractTickersChannel:
|
||||
return g.processOptionsContractTickers(push.Result)
|
||||
return e.processOptionsContractTickers(push.Result)
|
||||
case optionsUnderlyingTickersChannel:
|
||||
return g.processOptionsUnderlyingTicker(push.Result)
|
||||
return e.processOptionsUnderlyingTicker(push.Result)
|
||||
case optionsTradesChannel,
|
||||
optionsUnderlyingTradesChannel:
|
||||
return g.processOptionsTradesPushData(respRaw)
|
||||
return e.processOptionsTradesPushData(respRaw)
|
||||
case optionsUnderlyingPriceChannel:
|
||||
return g.processOptionsUnderlyingPricePushData(push.Result)
|
||||
return e.processOptionsUnderlyingPricePushData(push.Result)
|
||||
case optionsMarkPriceChannel:
|
||||
return g.processOptionsMarkPrice(push.Result)
|
||||
return e.processOptionsMarkPrice(push.Result)
|
||||
case optionsSettlementChannel:
|
||||
return g.processOptionsSettlementPushData(push.Result)
|
||||
return e.processOptionsSettlementPushData(push.Result)
|
||||
case optionsContractsChannel:
|
||||
return g.processOptionsContractPushData(push.Result)
|
||||
return e.processOptionsContractPushData(push.Result)
|
||||
case optionsContractCandlesticksChannel,
|
||||
optionsUnderlyingCandlesticksChannel:
|
||||
return g.processOptionsCandlestickPushData(respRaw)
|
||||
return e.processOptionsCandlestickPushData(respRaw)
|
||||
case optionsOrderbookChannel:
|
||||
return g.processOptionsOrderbookSnapshotPushData(push.Event, push.Result, push.Time)
|
||||
return e.processOptionsOrderbookSnapshotPushData(push.Event, push.Result, push.Time)
|
||||
case optionsOrderbookTickerChannel:
|
||||
return g.processOrderbookTickerPushData(respRaw)
|
||||
return e.processOrderbookTickerPushData(respRaw)
|
||||
case optionsOrderbookUpdateChannel:
|
||||
return g.processOptionsOrderbookUpdate(ctx, push.Result, asset.Options, push.Time)
|
||||
return e.processOptionsOrderbookUpdate(ctx, push.Result, asset.Options, push.Time)
|
||||
case optionsOrdersChannel:
|
||||
return g.processOptionsOrderPushData(respRaw)
|
||||
return e.processOptionsOrderPushData(respRaw)
|
||||
case optionsUserTradesChannel:
|
||||
return g.processOptionsUserTradesPushData(respRaw)
|
||||
return e.processOptionsUserTradesPushData(respRaw)
|
||||
case optionsLiquidatesChannel:
|
||||
return g.processOptionsLiquidatesPushData(respRaw)
|
||||
return e.processOptionsLiquidatesPushData(respRaw)
|
||||
case optionsUserSettlementChannel:
|
||||
return g.processOptionsUsersPersonalSettlementsPushData(respRaw)
|
||||
return e.processOptionsUsersPersonalSettlementsPushData(respRaw)
|
||||
case optionsPositionCloseChannel:
|
||||
return g.processPositionCloseData(respRaw)
|
||||
return e.processPositionCloseData(respRaw)
|
||||
case optionsBalancesChannel:
|
||||
return g.processBalancePushData(ctx, respRaw, asset.Options)
|
||||
return e.processBalancePushData(ctx, respRaw, asset.Options)
|
||||
case optionsPositionsChannel:
|
||||
return g.processOptionsPositionPushData(respRaw)
|
||||
return e.processOptionsPositionPushData(respRaw)
|
||||
default:
|
||||
g.Websocket.DataHandler <- websocket.UnhandledMessageWarning{
|
||||
Message: g.Name + websocket.UnhandledMessage + string(respRaw),
|
||||
e.Websocket.DataHandler <- websocket.UnhandledMessageWarning{
|
||||
Message: e.Name + websocket.UnhandledMessage + string(respRaw),
|
||||
}
|
||||
return errors.New(websocket.UnhandledMessage)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsContractTickers(incoming []byte) error {
|
||||
func (e *Exchange) processOptionsContractTickers(incoming []byte) error {
|
||||
var data OptionsTicker
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &ticker.Price{
|
||||
e.Websocket.DataHandler <- &ticker.Price{
|
||||
Pair: data.Name,
|
||||
Last: data.LastPrice.Float64(),
|
||||
Bid: data.Bid1Price.Float64(),
|
||||
Ask: data.Ask1Price.Float64(),
|
||||
AskSize: data.Ask1Size,
|
||||
BidSize: data.Bid1Size,
|
||||
ExchangeName: g.Name,
|
||||
ExchangeName: e.Name,
|
||||
AssetType: asset.Options,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsUnderlyingTicker(incoming []byte) error {
|
||||
func (e *Exchange) processOptionsUnderlyingTicker(incoming []byte) error {
|
||||
var data WsOptionUnderlyingTicker
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &data
|
||||
e.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsTradesPushData(data []byte) error {
|
||||
saveTradeData := g.IsSaveTradeDataEnabled()
|
||||
func (e *Exchange) processOptionsTradesPushData(data []byte) error {
|
||||
saveTradeData := e.IsSaveTradeDataEnabled()
|
||||
if !saveTradeData &&
|
||||
!g.IsTradeFeedEnabled() {
|
||||
!e.IsTradeFeedEnabled() {
|
||||
return nil
|
||||
}
|
||||
resp := struct {
|
||||
@@ -403,56 +403,56 @@ func (g *Gateio) processOptionsTradesPushData(data []byte) error {
|
||||
Timestamp: resp.Result[x].CreateTime.Time(),
|
||||
CurrencyPair: resp.Result[x].Contract,
|
||||
AssetType: asset.Options,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
Price: resp.Result[x].Price,
|
||||
Amount: resp.Result[x].Size,
|
||||
TID: strconv.FormatInt(resp.Result[x].ID, 10),
|
||||
}
|
||||
}
|
||||
return g.Websocket.Trade.Update(saveTradeData, trades...)
|
||||
return e.Websocket.Trade.Update(saveTradeData, trades...)
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsUnderlyingPricePushData(incoming []byte) error {
|
||||
func (e *Exchange) processOptionsUnderlyingPricePushData(incoming []byte) error {
|
||||
var data WsOptionsUnderlyingPrice
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &data
|
||||
e.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsMarkPrice(incoming []byte) error {
|
||||
func (e *Exchange) processOptionsMarkPrice(incoming []byte) error {
|
||||
var data WsOptionsMarkPrice
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &data
|
||||
e.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsSettlementPushData(incoming []byte) error {
|
||||
func (e *Exchange) processOptionsSettlementPushData(incoming []byte) error {
|
||||
var data WsOptionsSettlement
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &data
|
||||
e.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsContractPushData(incoming []byte) error {
|
||||
func (e *Exchange) processOptionsContractPushData(incoming []byte) error {
|
||||
var data WsOptionsContract
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &data
|
||||
e.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsCandlestickPushData(data []byte) error {
|
||||
func (e *Exchange) processOptionsCandlestickPushData(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -476,7 +476,7 @@ func (g *Gateio) processOptionsCandlestickPushData(data []byte) error {
|
||||
klineDatas[x] = websocket.KlineData{
|
||||
Pair: currencyPair,
|
||||
AssetType: asset.Options,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
StartTime: resp.Result[x].Timestamp.Time(),
|
||||
Interval: icp[0],
|
||||
OpenPrice: resp.Result[x].OpenPrice.Float64(),
|
||||
@@ -486,21 +486,21 @@ func (g *Gateio) processOptionsCandlestickPushData(data []byte) error {
|
||||
Volume: resp.Result[x].Amount.Float64(),
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- klineDatas
|
||||
e.Websocket.DataHandler <- klineDatas
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOrderbookTickerPushData(incoming []byte) error {
|
||||
func (e *Exchange) processOrderbookTickerPushData(incoming []byte) error {
|
||||
var data WsOptionsOrderbookTicker
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &data
|
||||
e.Websocket.DataHandler <- &data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsOrderbookUpdate(ctx context.Context, incoming []byte, a asset.Item, pushTime time.Time) error {
|
||||
func (e *Exchange) processOptionsOrderbookUpdate(ctx context.Context, incoming []byte, a asset.Item, pushTime time.Time) error {
|
||||
var data WsFuturesAndOptionsOrderbookUpdate
|
||||
if err := json.Unmarshal(incoming, &data); err != nil {
|
||||
return err
|
||||
@@ -515,7 +515,7 @@ func (g *Gateio) processOptionsOrderbookUpdate(ctx context.Context, incoming []b
|
||||
bids[x].Price = data.Bids[x].Price.Float64()
|
||||
bids[x].Amount = data.Bids[x].Size
|
||||
}
|
||||
return g.wsOBUpdateMgr.ProcessOrderbookUpdate(ctx, g, data.FirstUpdatedID, &orderbook.Update{
|
||||
return e.wsOBUpdateMgr.ProcessOrderbookUpdate(ctx, e, data.FirstUpdatedID, &orderbook.Update{
|
||||
UpdateID: data.LastUpdatedID,
|
||||
UpdateTime: data.Timestamp.Time(),
|
||||
LastPushed: pushTime,
|
||||
@@ -527,7 +527,7 @@ func (g *Gateio) processOptionsOrderbookUpdate(ctx context.Context, incoming []b
|
||||
})
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsOrderbookSnapshotPushData(event string, incoming []byte, lastPushed time.Time) error {
|
||||
func (e *Exchange) processOptionsOrderbookSnapshotPushData(event string, incoming []byte, lastPushed time.Time) error {
|
||||
if event == "all" {
|
||||
var data WsOptionsOrderbookSnapshot
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
@@ -536,11 +536,11 @@ func (g *Gateio) processOptionsOrderbookSnapshotPushData(event string, incoming
|
||||
}
|
||||
base := orderbook.Book{
|
||||
Asset: asset.Options,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
Pair: data.Contract,
|
||||
LastUpdated: data.Timestamp.Time(),
|
||||
LastPushed: lastPushed,
|
||||
ValidateOrderbook: g.ValidateOrderbook,
|
||||
ValidateOrderbook: e.ValidateOrderbook,
|
||||
}
|
||||
base.Asks = make([]orderbook.Level, len(data.Asks))
|
||||
for x := range data.Asks {
|
||||
@@ -552,7 +552,7 @@ func (g *Gateio) processOptionsOrderbookSnapshotPushData(event string, incoming
|
||||
base.Bids[x].Amount = data.Bids[x].Size
|
||||
base.Bids[x].Price = data.Bids[x].Price.Float64()
|
||||
}
|
||||
return g.Websocket.Orderbook.LoadSnapshot(&base)
|
||||
return e.Websocket.Orderbook.LoadSnapshot(&base)
|
||||
}
|
||||
var data []WsFuturesOrderbookUpdateEvent
|
||||
err := json.Unmarshal(incoming, &data)
|
||||
@@ -586,15 +586,15 @@ func (g *Gateio) processOptionsOrderbookSnapshotPushData(event string, incoming
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = g.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
err = e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
Asks: ab[0],
|
||||
Bids: ab[1],
|
||||
Asset: asset.Options,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
Pair: currencyPair,
|
||||
LastUpdated: lastPushed,
|
||||
LastPushed: lastPushed,
|
||||
ValidateOrderbook: g.ValidateOrderbook,
|
||||
ValidateOrderbook: e.ValidateOrderbook,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -603,7 +603,7 @@ func (g *Gateio) processOptionsOrderbookSnapshotPushData(event string, incoming
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsOrderPushData(data []byte) error {
|
||||
func (e *Exchange) processOptionsOrderPushData(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -627,7 +627,7 @@ func (g *Gateio) processOptionsOrderPushData(data []byte) error {
|
||||
}
|
||||
orderDetails[x] = order.Detail{
|
||||
Amount: resp.Result[x].Size,
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
OrderID: strconv.FormatInt(resp.Result[x].ID, 10),
|
||||
Status: status,
|
||||
Pair: resp.Result[x].Contract,
|
||||
@@ -638,12 +638,12 @@ func (g *Gateio) processOptionsOrderPushData(data []byte) error {
|
||||
AccountID: resp.Result[x].User,
|
||||
}
|
||||
}
|
||||
g.Websocket.DataHandler <- orderDetails
|
||||
e.Websocket.DataHandler <- orderDetails
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsUserTradesPushData(data []byte) error {
|
||||
if !g.IsFillsFeedEnabled() {
|
||||
func (e *Exchange) processOptionsUserTradesPushData(data []byte) error {
|
||||
if !e.IsFillsFeedEnabled() {
|
||||
return nil
|
||||
}
|
||||
resp := struct {
|
||||
@@ -660,7 +660,7 @@ func (g *Gateio) processOptionsUserTradesPushData(data []byte) error {
|
||||
for x := range resp.Result {
|
||||
fills[x] = fill.Data{
|
||||
Timestamp: resp.Result[x].CreateTime.Time(),
|
||||
Exchange: g.Name,
|
||||
Exchange: e.Name,
|
||||
CurrencyPair: resp.Result[x].Contract,
|
||||
OrderID: resp.Result[x].OrderID,
|
||||
TradeID: resp.Result[x].ID,
|
||||
@@ -668,10 +668,10 @@ func (g *Gateio) processOptionsUserTradesPushData(data []byte) error {
|
||||
Amount: resp.Result[x].Size,
|
||||
}
|
||||
}
|
||||
return g.Websocket.Fills.Update(fills...)
|
||||
return e.Websocket.Fills.Update(fills...)
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsLiquidatesPushData(data []byte) error {
|
||||
func (e *Exchange) processOptionsLiquidatesPushData(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -682,11 +682,11 @@ func (g *Gateio) processOptionsLiquidatesPushData(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &resp
|
||||
e.Websocket.DataHandler <- &resp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsUsersPersonalSettlementsPushData(data []byte) error {
|
||||
func (e *Exchange) processOptionsUsersPersonalSettlementsPushData(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -697,11 +697,11 @@ func (g *Gateio) processOptionsUsersPersonalSettlementsPushData(data []byte) err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &resp
|
||||
e.Websocket.DataHandler <- &resp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Gateio) processOptionsPositionPushData(data []byte) error {
|
||||
func (e *Exchange) processOptionsPositionPushData(data []byte) error {
|
||||
resp := struct {
|
||||
Time types.Time `json:"time"`
|
||||
Channel string `json:"channel"`
|
||||
@@ -712,6 +712,6 @@ func (g *Gateio) processOptionsPositionPushData(data []byte) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Websocket.DataHandler <- &resp
|
||||
e.Websocket.DataHandler <- &resp
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ var (
|
||||
)
|
||||
|
||||
// authenticateFutures sends an authentication message to the websocket connection
|
||||
func (g *Gateio) authenticateFutures(ctx context.Context, conn websocket.Connection) error {
|
||||
return g.websocketLogin(ctx, conn, "futures.login")
|
||||
func (e *Exchange) authenticateFutures(ctx context.Context, conn websocket.Connection) error {
|
||||
return e.websocketLogin(ctx, conn, "futures.login")
|
||||
}
|
||||
|
||||
// WebsocketFuturesSubmitOrder submits an order via the websocket connection
|
||||
func (g *Gateio) WebsocketFuturesSubmitOrder(ctx context.Context, a asset.Item, order *ContractOrderCreateParams) (*WebsocketFuturesOrderResponse, error) {
|
||||
resps, err := g.WebsocketFuturesSubmitOrders(ctx, a, order)
|
||||
func (e *Exchange) WebsocketFuturesSubmitOrder(ctx context.Context, a asset.Item, order *ContractOrderCreateParams) (*WebsocketFuturesOrderResponse, error) {
|
||||
resps, err := e.WebsocketFuturesSubmitOrders(ctx, a, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func (g *Gateio) WebsocketFuturesSubmitOrder(ctx context.Context, a asset.Item,
|
||||
}
|
||||
|
||||
// WebsocketFuturesSubmitOrders submits orders via the websocket connection. All orders must be for the same asset.
|
||||
func (g *Gateio) WebsocketFuturesSubmitOrders(ctx context.Context, a asset.Item, orders ...*ContractOrderCreateParams) ([]WebsocketFuturesOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketFuturesSubmitOrders(ctx context.Context, a asset.Item, orders ...*ContractOrderCreateParams) ([]WebsocketFuturesOrderResponse, error) {
|
||||
if len(orders) == 0 {
|
||||
return nil, errOrdersEmpty
|
||||
}
|
||||
@@ -65,16 +65,16 @@ func (g *Gateio) WebsocketFuturesSubmitOrders(ctx context.Context, a asset.Item,
|
||||
|
||||
if len(orders) == 1 {
|
||||
var singleResponse WebsocketFuturesOrderResponse
|
||||
err := g.SendWebsocketRequest(ctx, perpetualSubmitOrderEPL, "futures.order_place", a, orders[0], &singleResponse, 2)
|
||||
err := e.SendWebsocketRequest(ctx, perpetualSubmitOrderEPL, "futures.order_place", a, orders[0], &singleResponse, 2)
|
||||
return []WebsocketFuturesOrderResponse{singleResponse}, err
|
||||
}
|
||||
|
||||
var resp []WebsocketFuturesOrderResponse
|
||||
return resp, g.SendWebsocketRequest(ctx, perpetualSubmitBatchOrdersEPL, "futures.order_batch_place", a, orders, &resp, 2)
|
||||
return resp, e.SendWebsocketRequest(ctx, perpetualSubmitBatchOrdersEPL, "futures.order_batch_place", a, orders, &resp, 2)
|
||||
}
|
||||
|
||||
// WebsocketFuturesCancelOrder cancels an order via the websocket connection.
|
||||
func (g *Gateio) WebsocketFuturesCancelOrder(ctx context.Context, orderID string, contract currency.Pair, a asset.Item) (*WebsocketFuturesOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketFuturesCancelOrder(ctx context.Context, orderID string, contract currency.Pair, a asset.Item) (*WebsocketFuturesOrderResponse, error) {
|
||||
if orderID == "" {
|
||||
return nil, order.ErrOrderIDNotSet
|
||||
}
|
||||
@@ -88,11 +88,11 @@ func (g *Gateio) WebsocketFuturesCancelOrder(ctx context.Context, orderID string
|
||||
}{OrderID: orderID}
|
||||
|
||||
var resp WebsocketFuturesOrderResponse
|
||||
return &resp, g.SendWebsocketRequest(ctx, perpetualCancelOrderEPL, "futures.order_cancel", a, params, &resp, 1)
|
||||
return &resp, e.SendWebsocketRequest(ctx, perpetualCancelOrderEPL, "futures.order_cancel", a, params, &resp, 1)
|
||||
}
|
||||
|
||||
// WebsocketFuturesCancelAllOpenFuturesOrders cancels multiple orders via the websocket.
|
||||
func (g *Gateio) WebsocketFuturesCancelAllOpenFuturesOrders(ctx context.Context, contract currency.Pair, a asset.Item, side string) ([]WebsocketFuturesOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketFuturesCancelAllOpenFuturesOrders(ctx context.Context, contract currency.Pair, a asset.Item, side string) ([]WebsocketFuturesOrderResponse, error) {
|
||||
if err := validateFuturesPairAsset(contract, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -107,11 +107,11 @@ func (g *Gateio) WebsocketFuturesCancelAllOpenFuturesOrders(ctx context.Context,
|
||||
}{Contract: contract, Side: side}
|
||||
|
||||
var resp []WebsocketFuturesOrderResponse
|
||||
return resp, g.SendWebsocketRequest(ctx, perpetualCancelOpenOrdersEPL, "futures.order_cancel_cp", a, params, &resp, 2)
|
||||
return resp, e.SendWebsocketRequest(ctx, perpetualCancelOpenOrdersEPL, "futures.order_cancel_cp", a, params, &resp, 2)
|
||||
}
|
||||
|
||||
// WebsocketFuturesAmendOrder amends an order via the websocket connection
|
||||
func (g *Gateio) WebsocketFuturesAmendOrder(ctx context.Context, amend *WebsocketFuturesAmendOrder) (*WebsocketFuturesOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketFuturesAmendOrder(ctx context.Context, amend *WebsocketFuturesAmendOrder) (*WebsocketFuturesOrderResponse, error) {
|
||||
if amend == nil {
|
||||
return nil, fmt.Errorf("%w: %T", common.ErrNilPointer, amend)
|
||||
}
|
||||
@@ -129,11 +129,11 @@ func (g *Gateio) WebsocketFuturesAmendOrder(ctx context.Context, amend *Websocke
|
||||
}
|
||||
|
||||
var resp WebsocketFuturesOrderResponse
|
||||
return &resp, g.SendWebsocketRequest(ctx, perpetualAmendOrderEPL, "futures.order_amend", amend.Asset, amend, &resp, 1)
|
||||
return &resp, e.SendWebsocketRequest(ctx, perpetualAmendOrderEPL, "futures.order_amend", amend.Asset, amend, &resp, 1)
|
||||
}
|
||||
|
||||
// WebsocketFuturesOrderList fetches a list of orders via the websocket connection
|
||||
func (g *Gateio) WebsocketFuturesOrderList(ctx context.Context, list *WebsocketFutureOrdersList) ([]WebsocketFuturesOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketFuturesOrderList(ctx context.Context, list *WebsocketFutureOrdersList) ([]WebsocketFuturesOrderResponse, error) {
|
||||
if list == nil {
|
||||
return nil, fmt.Errorf("%w: %T", common.ErrNilPointer, list)
|
||||
}
|
||||
@@ -147,11 +147,11 @@ func (g *Gateio) WebsocketFuturesOrderList(ctx context.Context, list *WebsocketF
|
||||
}
|
||||
|
||||
var resp []WebsocketFuturesOrderResponse
|
||||
return resp, g.SendWebsocketRequest(ctx, perpetualGetOrdersEPL, "futures.order_list", list.Asset, list, &resp, 1)
|
||||
return resp, e.SendWebsocketRequest(ctx, perpetualGetOrdersEPL, "futures.order_list", list.Asset, list, &resp, 1)
|
||||
}
|
||||
|
||||
// WebsocketFuturesGetOrderStatus gets the status of an order via the websocket connection.
|
||||
func (g *Gateio) WebsocketFuturesGetOrderStatus(ctx context.Context, contract currency.Pair, a asset.Item, orderID string) (*WebsocketFuturesOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketFuturesGetOrderStatus(ctx context.Context, contract currency.Pair, a asset.Item, orderID string) (*WebsocketFuturesOrderResponse, error) {
|
||||
if err := validateFuturesPairAsset(contract, a); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -165,7 +165,7 @@ func (g *Gateio) WebsocketFuturesGetOrderStatus(ctx context.Context, contract cu
|
||||
}{OrderID: orderID}
|
||||
|
||||
var resp WebsocketFuturesOrderResponse
|
||||
return &resp, g.SendWebsocketRequest(ctx, perpetualFetchOrderEPL, "futures.order_status", a, params, &resp, 1)
|
||||
return &resp, e.SendWebsocketRequest(ctx, perpetualFetchOrderEPL, "futures.order_status", a, params, &resp, 1)
|
||||
}
|
||||
|
||||
// validateFuturesPairAsset enforces that a futures pair's quote currency matches the given asset
|
||||
|
||||
@@ -18,22 +18,22 @@ var (
|
||||
|
||||
func TestWebsocketFuturesSubmitOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketFuturesSubmitOrder(t.Context(), asset.USDTMarginedFutures, &ContractOrderCreateParams{})
|
||||
_, err := e.WebsocketFuturesSubmitOrder(t.Context(), asset.USDTMarginedFutures, &ContractOrderCreateParams{})
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
out := &ContractOrderCreateParams{Contract: BTCUSDT}
|
||||
_, err = g.WebsocketFuturesSubmitOrder(t.Context(), asset.USDTMarginedFutures, out)
|
||||
_, err = e.WebsocketFuturesSubmitOrder(t.Context(), asset.USDTMarginedFutures, out)
|
||||
require.ErrorIs(t, err, errInvalidPrice)
|
||||
out.Price = "40000"
|
||||
_, err = g.WebsocketFuturesSubmitOrder(t.Context(), asset.USDTMarginedFutures, out)
|
||||
_, err = e.WebsocketFuturesSubmitOrder(t.Context(), asset.USDTMarginedFutures, out)
|
||||
require.ErrorIs(t, err, errInvalidAmount)
|
||||
out.Size = 1 // 1 lovely long contract
|
||||
out.AutoSize = "silly_billies"
|
||||
_, err = g.WebsocketFuturesSubmitOrder(t.Context(), asset.USDTMarginedFutures, out)
|
||||
_, err = e.WebsocketFuturesSubmitOrder(t.Context(), asset.USDTMarginedFutures, out)
|
||||
require.ErrorIs(t, err, errInvalidAutoSize)
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Futures) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Futures)
|
||||
out.AutoSize = ""
|
||||
|
||||
got, err := g.WebsocketFuturesSubmitOrder(t.Context(), asset.USDTMarginedFutures, out)
|
||||
@@ -43,36 +43,36 @@ func TestWebsocketFuturesSubmitOrder(t *testing.T) {
|
||||
|
||||
func TestWebsocketFuturesSubmitOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures)
|
||||
_, err := e.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures)
|
||||
require.ErrorIs(t, err, errOrdersEmpty)
|
||||
|
||||
out := &ContractOrderCreateParams{}
|
||||
_, err = g.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures, out)
|
||||
_, err = e.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures, out)
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
out.Contract = BTCUSDT
|
||||
|
||||
_, err = g.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures, out)
|
||||
_, err = e.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures, out)
|
||||
require.ErrorIs(t, err, errInvalidPrice)
|
||||
|
||||
out.Price = "40000"
|
||||
_, err = g.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures, out)
|
||||
_, err = e.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures, out)
|
||||
require.ErrorIs(t, err, errInvalidAmount)
|
||||
|
||||
out.Size = 1 // 1 lovely long contract
|
||||
out.AutoSize = "silly_billies"
|
||||
_, err = g.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures, out)
|
||||
_, err = e.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures, out)
|
||||
require.ErrorIs(t, err, errInvalidAutoSize)
|
||||
|
||||
out.AutoSize = "close_long"
|
||||
_, err = g.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures, out)
|
||||
_, err = e.WebsocketFuturesSubmitOrders(t.Context(), asset.USDTMarginedFutures, out)
|
||||
require.ErrorIs(t, err, errInvalidAmount)
|
||||
|
||||
out.AutoSize = ""
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Futures) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Futures)
|
||||
|
||||
// test single order
|
||||
got, err := g.WebsocketFuturesSubmitOrders(t.Context(), asset.CoinMarginedFutures, out)
|
||||
@@ -87,18 +87,18 @@ func TestWebsocketFuturesSubmitOrders(t *testing.T) {
|
||||
|
||||
func TestWebsocketFuturesCancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketFuturesCancelOrder(t.Context(), "", currency.EMPTYPAIR, asset.Empty)
|
||||
_, err := e.WebsocketFuturesCancelOrder(t.Context(), "", currency.EMPTYPAIR, asset.Empty)
|
||||
require.ErrorIs(t, err, order.ErrOrderIDNotSet)
|
||||
|
||||
_, err = g.WebsocketFuturesCancelOrder(t.Context(), "42069", currency.EMPTYPAIR, asset.Empty)
|
||||
_, err = e.WebsocketFuturesCancelOrder(t.Context(), "42069", currency.EMPTYPAIR, asset.Empty)
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
_, err = g.WebsocketFuturesCancelOrder(t.Context(), "42069", BTCUSDT, asset.Empty)
|
||||
_, err = e.WebsocketFuturesCancelOrder(t.Context(), "42069", BTCUSDT, asset.Empty)
|
||||
require.ErrorIs(t, err, asset.ErrNotSupported)
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Futures) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Futures)
|
||||
|
||||
got, err := g.WebsocketFuturesCancelOrder(t.Context(), "513160761072", BTCUSDT, asset.USDTMarginedFutures)
|
||||
require.NoError(t, err)
|
||||
@@ -107,18 +107,18 @@ func TestWebsocketFuturesCancelOrder(t *testing.T) {
|
||||
|
||||
func TestWebsocketFuturesCancelAllOpenFuturesOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketFuturesCancelAllOpenFuturesOrders(t.Context(), currency.EMPTYPAIR, asset.Empty, "")
|
||||
_, err := e.WebsocketFuturesCancelAllOpenFuturesOrders(t.Context(), currency.EMPTYPAIR, asset.Empty, "")
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
_, err = g.WebsocketFuturesCancelAllOpenFuturesOrders(t.Context(), BTCUSDT, asset.Empty, "bruh")
|
||||
_, err = e.WebsocketFuturesCancelAllOpenFuturesOrders(t.Context(), BTCUSDT, asset.Empty, "bruh")
|
||||
require.ErrorIs(t, err, asset.ErrNotSupported)
|
||||
|
||||
_, err = g.WebsocketFuturesCancelAllOpenFuturesOrders(t.Context(), BTCUSDT, asset.USDTMarginedFutures, "bruh")
|
||||
_, err = e.WebsocketFuturesCancelAllOpenFuturesOrders(t.Context(), BTCUSDT, asset.USDTMarginedFutures, "bruh")
|
||||
require.ErrorIs(t, err, order.ErrSideIsInvalid)
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Futures) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Futures)
|
||||
|
||||
got, err := g.WebsocketFuturesCancelAllOpenFuturesOrders(t.Context(), BTCUSDT, asset.USDTMarginedFutures, "bid")
|
||||
require.NoError(t, err)
|
||||
@@ -127,30 +127,30 @@ func TestWebsocketFuturesCancelAllOpenFuturesOrders(t *testing.T) {
|
||||
|
||||
func TestWebsocketFuturesAmendOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketFuturesAmendOrder(t.Context(), nil)
|
||||
_, err := e.WebsocketFuturesAmendOrder(t.Context(), nil)
|
||||
require.ErrorIs(t, err, common.ErrNilPointer)
|
||||
|
||||
amend := &WebsocketFuturesAmendOrder{}
|
||||
_, err = g.WebsocketFuturesAmendOrder(t.Context(), amend)
|
||||
_, err = e.WebsocketFuturesAmendOrder(t.Context(), amend)
|
||||
require.ErrorIs(t, err, order.ErrOrderIDNotSet)
|
||||
|
||||
amend.OrderID = "1337"
|
||||
_, err = g.WebsocketFuturesAmendOrder(t.Context(), amend)
|
||||
_, err = e.WebsocketFuturesAmendOrder(t.Context(), amend)
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
amend.Contract = BTCUSDT
|
||||
_, err = g.WebsocketFuturesAmendOrder(t.Context(), amend)
|
||||
_, err = e.WebsocketFuturesAmendOrder(t.Context(), amend)
|
||||
require.ErrorIs(t, err, asset.ErrNotSupported)
|
||||
|
||||
amend.Asset = asset.USDTMarginedFutures
|
||||
_, err = g.WebsocketFuturesAmendOrder(t.Context(), amend)
|
||||
_, err = e.WebsocketFuturesAmendOrder(t.Context(), amend)
|
||||
require.ErrorIs(t, err, errInvalidAmount)
|
||||
|
||||
amend.Size = 2
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Futures) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Futures)
|
||||
|
||||
amend.OrderID = "513170215869"
|
||||
got, err := g.WebsocketFuturesAmendOrder(t.Context(), amend)
|
||||
@@ -160,24 +160,24 @@ func TestWebsocketFuturesAmendOrder(t *testing.T) {
|
||||
|
||||
func TestWebsocketFuturesOrderList(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketFuturesOrderList(t.Context(), nil)
|
||||
_, err := e.WebsocketFuturesOrderList(t.Context(), nil)
|
||||
require.ErrorIs(t, err, common.ErrNilPointer)
|
||||
|
||||
list := &WebsocketFutureOrdersList{}
|
||||
_, err = g.WebsocketFuturesOrderList(t.Context(), list)
|
||||
_, err = e.WebsocketFuturesOrderList(t.Context(), list)
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
list.Contract = BTCUSDT
|
||||
_, err = g.WebsocketFuturesOrderList(t.Context(), list)
|
||||
_, err = e.WebsocketFuturesOrderList(t.Context(), list)
|
||||
require.ErrorIs(t, err, asset.ErrNotSupported)
|
||||
|
||||
list.Asset = asset.USDTMarginedFutures
|
||||
_, err = g.WebsocketFuturesOrderList(t.Context(), list)
|
||||
_, err = e.WebsocketFuturesOrderList(t.Context(), list)
|
||||
require.ErrorIs(t, err, errStatusNotSet)
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Futures) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Futures)
|
||||
|
||||
list.Status = statusOpen
|
||||
got, err := g.WebsocketFuturesOrderList(t.Context(), list)
|
||||
@@ -187,18 +187,18 @@ func TestWebsocketFuturesOrderList(t *testing.T) {
|
||||
|
||||
func TestWebsocketFuturesGetOrderStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketFuturesGetOrderStatus(t.Context(), currency.EMPTYPAIR, asset.Empty, "")
|
||||
_, err := e.WebsocketFuturesGetOrderStatus(t.Context(), currency.EMPTYPAIR, asset.Empty, "")
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
_, err = g.WebsocketFuturesGetOrderStatus(t.Context(), BTCUSDT, asset.Empty, "")
|
||||
_, err = e.WebsocketFuturesGetOrderStatus(t.Context(), BTCUSDT, asset.Empty, "")
|
||||
require.ErrorIs(t, err, asset.ErrNotSupported)
|
||||
|
||||
_, err = g.WebsocketFuturesGetOrderStatus(t.Context(), BTCUSDT, asset.USDTMarginedFutures, "")
|
||||
_, err = e.WebsocketFuturesGetOrderStatus(t.Context(), BTCUSDT, asset.USDTMarginedFutures, "")
|
||||
require.ErrorIs(t, err, order.ErrOrderIDNotSet)
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Futures) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Futures)
|
||||
|
||||
got, err := g.WebsocketFuturesGetOrderStatus(t.Context(), BTCUSDT, asset.USDTMarginedFutures, "513170215869")
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -20,13 +20,13 @@ var (
|
||||
)
|
||||
|
||||
// authenticateSpot sends an authentication message to the websocket connection
|
||||
func (g *Gateio) authenticateSpot(ctx context.Context, conn websocket.Connection) error {
|
||||
return g.websocketLogin(ctx, conn, "spot.login")
|
||||
func (e *Exchange) authenticateSpot(ctx context.Context, conn websocket.Connection) error {
|
||||
return e.websocketLogin(ctx, conn, "spot.login")
|
||||
}
|
||||
|
||||
// WebsocketSpotSubmitOrder submits an order via the websocket connection
|
||||
func (g *Gateio) WebsocketSpotSubmitOrder(ctx context.Context, order *CreateOrderRequest) (*WebsocketOrderResponse, error) {
|
||||
resps, err := g.WebsocketSpotSubmitOrders(ctx, order)
|
||||
func (e *Exchange) WebsocketSpotSubmitOrder(ctx context.Context, order *CreateOrderRequest) (*WebsocketOrderResponse, error) {
|
||||
resps, err := e.WebsocketSpotSubmitOrders(ctx, order)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -38,7 +38,7 @@ func (g *Gateio) WebsocketSpotSubmitOrder(ctx context.Context, order *CreateOrde
|
||||
|
||||
// WebsocketSpotSubmitOrders submits orders via the websocket connection. You can
|
||||
// send multiple orders in a single request. But only for one asset route.
|
||||
func (g *Gateio) WebsocketSpotSubmitOrders(ctx context.Context, orders ...*CreateOrderRequest) ([]WebsocketOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketSpotSubmitOrders(ctx context.Context, orders ...*CreateOrderRequest) ([]WebsocketOrderResponse, error) {
|
||||
if len(orders) == 0 {
|
||||
return nil, errOrdersEmpty
|
||||
}
|
||||
@@ -46,7 +46,7 @@ func (g *Gateio) WebsocketSpotSubmitOrders(ctx context.Context, orders ...*Creat
|
||||
for i := range orders {
|
||||
if orders[i].Text == "" {
|
||||
// API requires Text field, or it will be rejected
|
||||
orders[i].Text = "t-" + strconv.FormatInt(g.Counter.IncrementAndGet(), 10)
|
||||
orders[i].Text = "t-" + strconv.FormatInt(e.Counter.IncrementAndGet(), 10)
|
||||
}
|
||||
if orders[i].CurrencyPair.IsEmpty() {
|
||||
return nil, currency.ErrCurrencyPairEmpty
|
||||
@@ -64,14 +64,14 @@ func (g *Gateio) WebsocketSpotSubmitOrders(ctx context.Context, orders ...*Creat
|
||||
|
||||
if len(orders) == 1 {
|
||||
var singleResponse WebsocketOrderResponse
|
||||
return []WebsocketOrderResponse{singleResponse}, g.SendWebsocketRequest(ctx, spotPlaceOrderEPL, "spot.order_place", asset.Spot, orders[0], &singleResponse, 2)
|
||||
return []WebsocketOrderResponse{singleResponse}, e.SendWebsocketRequest(ctx, spotPlaceOrderEPL, "spot.order_place", asset.Spot, orders[0], &singleResponse, 2)
|
||||
}
|
||||
var resp []WebsocketOrderResponse
|
||||
return resp, g.SendWebsocketRequest(ctx, spotBatchOrdersEPL, "spot.order_place", asset.Spot, orders, &resp, 2)
|
||||
return resp, e.SendWebsocketRequest(ctx, spotBatchOrdersEPL, "spot.order_place", asset.Spot, orders, &resp, 2)
|
||||
}
|
||||
|
||||
// WebsocketSpotCancelOrder cancels an order via the websocket connection
|
||||
func (g *Gateio) WebsocketSpotCancelOrder(ctx context.Context, orderID string, pair currency.Pair, account string) (*WebsocketOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketSpotCancelOrder(ctx context.Context, orderID string, pair currency.Pair, account string) (*WebsocketOrderResponse, error) {
|
||||
if orderID == "" {
|
||||
return nil, order.ErrOrderIDNotSet
|
||||
}
|
||||
@@ -82,11 +82,11 @@ func (g *Gateio) WebsocketSpotCancelOrder(ctx context.Context, orderID string, p
|
||||
params := &WebsocketOrderRequest{OrderID: orderID, Pair: pair.String(), Account: account}
|
||||
|
||||
var resp WebsocketOrderResponse
|
||||
return &resp, g.SendWebsocketRequest(ctx, spotCancelSingleOrderEPL, "spot.order_cancel", asset.Spot, params, &resp, 1)
|
||||
return &resp, e.SendWebsocketRequest(ctx, spotCancelSingleOrderEPL, "spot.order_cancel", asset.Spot, params, &resp, 1)
|
||||
}
|
||||
|
||||
// WebsocketSpotCancelAllOrdersByIDs cancels multiple orders via the websocket
|
||||
func (g *Gateio) WebsocketSpotCancelAllOrdersByIDs(ctx context.Context, o []WebsocketOrderBatchRequest) ([]WebsocketCancellAllResponse, error) {
|
||||
func (e *Exchange) WebsocketSpotCancelAllOrdersByIDs(ctx context.Context, o []WebsocketOrderBatchRequest) ([]WebsocketCancellAllResponse, error) {
|
||||
if len(o) == 0 {
|
||||
return nil, errNoOrdersToCancel
|
||||
}
|
||||
@@ -101,11 +101,11 @@ func (g *Gateio) WebsocketSpotCancelAllOrdersByIDs(ctx context.Context, o []Webs
|
||||
}
|
||||
|
||||
var resp []WebsocketCancellAllResponse
|
||||
return resp, g.SendWebsocketRequest(ctx, spotCancelBatchOrdersEPL, "spot.order_cancel_ids", asset.Spot, o, &resp, 2)
|
||||
return resp, e.SendWebsocketRequest(ctx, spotCancelBatchOrdersEPL, "spot.order_cancel_ids", asset.Spot, o, &resp, 2)
|
||||
}
|
||||
|
||||
// WebsocketSpotCancelAllOrdersByPair cancels all orders for a specific pair
|
||||
func (g *Gateio) WebsocketSpotCancelAllOrdersByPair(ctx context.Context, pair currency.Pair, side order.Side, account string) ([]WebsocketOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketSpotCancelAllOrdersByPair(ctx context.Context, pair currency.Pair, side order.Side, account string) ([]WebsocketOrderResponse, error) {
|
||||
if !pair.IsEmpty() && side == order.UnknownSide {
|
||||
// This case will cancel all orders for every pair, this can be introduced later
|
||||
return nil, fmt.Errorf("'%v' %w while pair is set", side, order.ErrSideIsInvalid)
|
||||
@@ -123,11 +123,11 @@ func (g *Gateio) WebsocketSpotCancelAllOrdersByPair(ctx context.Context, pair cu
|
||||
}
|
||||
|
||||
var resp []WebsocketOrderResponse
|
||||
return resp, g.SendWebsocketRequest(ctx, spotCancelAllOpenOrdersEPL, "spot.order_cancel_cp", asset.Spot, params, &resp, 1)
|
||||
return resp, e.SendWebsocketRequest(ctx, spotCancelAllOpenOrdersEPL, "spot.order_cancel_cp", asset.Spot, params, &resp, 1)
|
||||
}
|
||||
|
||||
// WebsocketSpotAmendOrder amends an order via the websocket connection
|
||||
func (g *Gateio) WebsocketSpotAmendOrder(ctx context.Context, amend *WebsocketAmendOrder) (*WebsocketOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketSpotAmendOrder(ctx context.Context, amend *WebsocketAmendOrder) (*WebsocketOrderResponse, error) {
|
||||
if amend == nil {
|
||||
return nil, fmt.Errorf("%w: %T", common.ErrNilPointer, amend)
|
||||
}
|
||||
@@ -145,11 +145,11 @@ func (g *Gateio) WebsocketSpotAmendOrder(ctx context.Context, amend *WebsocketAm
|
||||
}
|
||||
|
||||
var resp WebsocketOrderResponse
|
||||
return &resp, g.SendWebsocketRequest(ctx, spotAmendOrderEPL, "spot.order_amend", asset.Spot, amend, &resp, 1)
|
||||
return &resp, e.SendWebsocketRequest(ctx, spotAmendOrderEPL, "spot.order_amend", asset.Spot, amend, &resp, 1)
|
||||
}
|
||||
|
||||
// WebsocketSpotGetOrderStatus gets the status of an order via the websocket connection
|
||||
func (g *Gateio) WebsocketSpotGetOrderStatus(ctx context.Context, orderID string, pair currency.Pair, account string) (*WebsocketOrderResponse, error) {
|
||||
func (e *Exchange) WebsocketSpotGetOrderStatus(ctx context.Context, orderID string, pair currency.Pair, account string) (*WebsocketOrderResponse, error) {
|
||||
if orderID == "" {
|
||||
return nil, order.ErrOrderIDNotSet
|
||||
}
|
||||
@@ -160,5 +160,5 @@ func (g *Gateio) WebsocketSpotGetOrderStatus(ctx context.Context, orderID string
|
||||
params := &WebsocketOrderRequest{OrderID: orderID, Pair: pair.String(), Account: account}
|
||||
|
||||
var resp WebsocketOrderResponse
|
||||
return &resp, g.SendWebsocketRequest(ctx, spotGetOrdersEPL, "spot.order_status", asset.Spot, params, &resp, 1)
|
||||
return &resp, e.SendWebsocketRequest(ctx, spotGetOrdersEPL, "spot.order_status", asset.Spot, params, &resp, 1)
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@ import (
|
||||
|
||||
func TestWebsocketLogin(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := g.websocketLogin(t.Context(), nil, "")
|
||||
err := e.websocketLogin(t.Context(), nil, "")
|
||||
require.ErrorIs(t, err, common.ErrNilPointer)
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Spot) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Spot)
|
||||
|
||||
c, err := g.Websocket.GetConnection(asset.Spot)
|
||||
require.NoError(t, err)
|
||||
@@ -34,23 +34,23 @@ func TestWebsocketLogin(t *testing.T) {
|
||||
|
||||
func TestWebsocketSpotSubmitOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketSpotSubmitOrder(t.Context(), &CreateOrderRequest{})
|
||||
_, err := e.WebsocketSpotSubmitOrder(t.Context(), &CreateOrderRequest{})
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
out := &CreateOrderRequest{CurrencyPair: currency.NewPair(currency.NewCode("GT"), currency.USDT).Format(currency.PairFormat{Uppercase: true, Delimiter: "_"})}
|
||||
_, err = g.WebsocketSpotSubmitOrder(t.Context(), out)
|
||||
_, err = e.WebsocketSpotSubmitOrder(t.Context(), out)
|
||||
require.ErrorIs(t, err, order.ErrSideIsInvalid)
|
||||
out.Side = strings.ToLower(order.Sell.String())
|
||||
_, err = g.WebsocketSpotSubmitOrder(t.Context(), out)
|
||||
_, err = e.WebsocketSpotSubmitOrder(t.Context(), out)
|
||||
require.ErrorIs(t, err, errInvalidAmount)
|
||||
out.Amount = 1
|
||||
out.Type = "limit"
|
||||
_, err = g.WebsocketSpotSubmitOrder(t.Context(), out)
|
||||
_, err = e.WebsocketSpotSubmitOrder(t.Context(), out)
|
||||
require.ErrorIs(t, err, errInvalidPrice)
|
||||
out.Price = 100
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Spot) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Spot)
|
||||
|
||||
got, err := g.WebsocketSpotSubmitOrder(t.Context(), out)
|
||||
require.NoError(t, err)
|
||||
@@ -59,26 +59,26 @@ func TestWebsocketSpotSubmitOrder(t *testing.T) {
|
||||
|
||||
func TestWebsocketSpotSubmitOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketSpotSubmitOrders(t.Context())
|
||||
_, err := e.WebsocketSpotSubmitOrders(t.Context())
|
||||
require.ErrorIs(t, err, errOrdersEmpty)
|
||||
out := &CreateOrderRequest{}
|
||||
_, err = g.WebsocketSpotSubmitOrders(t.Context(), out)
|
||||
_, err = e.WebsocketSpotSubmitOrders(t.Context(), out)
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
out.CurrencyPair = currency.NewBTCUSDT()
|
||||
_, err = g.WebsocketSpotSubmitOrders(t.Context(), out)
|
||||
_, err = e.WebsocketSpotSubmitOrders(t.Context(), out)
|
||||
require.ErrorIs(t, err, order.ErrSideIsInvalid)
|
||||
out.Side = strings.ToLower(order.Buy.String())
|
||||
_, err = g.WebsocketSpotSubmitOrders(t.Context(), out)
|
||||
_, err = e.WebsocketSpotSubmitOrders(t.Context(), out)
|
||||
require.ErrorIs(t, err, errInvalidAmount)
|
||||
out.Amount = 0.0003
|
||||
out.Type = "limit"
|
||||
_, err = g.WebsocketSpotSubmitOrders(t.Context(), out)
|
||||
_, err = e.WebsocketSpotSubmitOrders(t.Context(), out)
|
||||
require.ErrorIs(t, err, errInvalidPrice)
|
||||
out.Price = 20000
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Spot) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Spot)
|
||||
|
||||
// test single order
|
||||
got, err := g.WebsocketSpotSubmitOrders(t.Context(), out)
|
||||
@@ -93,14 +93,14 @@ func TestWebsocketSpotSubmitOrders(t *testing.T) {
|
||||
|
||||
func TestWebsocketSpotCancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketSpotCancelOrder(t.Context(), "", currency.EMPTYPAIR, "")
|
||||
_, err := e.WebsocketSpotCancelOrder(t.Context(), "", currency.EMPTYPAIR, "")
|
||||
require.ErrorIs(t, err, order.ErrOrderIDNotSet)
|
||||
_, err = g.WebsocketSpotCancelOrder(t.Context(), "1337", currency.EMPTYPAIR, "")
|
||||
_, err = e.WebsocketSpotCancelOrder(t.Context(), "1337", currency.EMPTYPAIR, "")
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Spot) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Spot)
|
||||
|
||||
got, err := g.WebsocketSpotCancelOrder(t.Context(), "644913098758", BTCUSDT, "")
|
||||
require.NoError(t, err)
|
||||
@@ -109,20 +109,20 @@ func TestWebsocketSpotCancelOrder(t *testing.T) {
|
||||
|
||||
func TestWebsocketSpotCancelAllOrdersByIDs(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketSpotCancelAllOrdersByIDs(t.Context(), []WebsocketOrderBatchRequest{})
|
||||
_, err := e.WebsocketSpotCancelAllOrdersByIDs(t.Context(), []WebsocketOrderBatchRequest{})
|
||||
require.ErrorIs(t, err, errNoOrdersToCancel)
|
||||
out := WebsocketOrderBatchRequest{}
|
||||
_, err = g.WebsocketSpotCancelAllOrdersByIDs(t.Context(), []WebsocketOrderBatchRequest{out})
|
||||
_, err = e.WebsocketSpotCancelAllOrdersByIDs(t.Context(), []WebsocketOrderBatchRequest{out})
|
||||
require.ErrorIs(t, err, order.ErrOrderIDNotSet)
|
||||
out.OrderID = "1337"
|
||||
_, err = g.WebsocketSpotCancelAllOrdersByIDs(t.Context(), []WebsocketOrderBatchRequest{out})
|
||||
_, err = e.WebsocketSpotCancelAllOrdersByIDs(t.Context(), []WebsocketOrderBatchRequest{out})
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
out.Pair = BTCUSDT
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Spot) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Spot)
|
||||
|
||||
out.OrderID = "644913101755"
|
||||
got, err := g.WebsocketSpotCancelAllOrdersByIDs(t.Context(), []WebsocketOrderBatchRequest{out})
|
||||
@@ -132,12 +132,12 @@ func TestWebsocketSpotCancelAllOrdersByIDs(t *testing.T) {
|
||||
|
||||
func TestWebsocketSpotCancelAllOrdersByPair(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketSpotCancelAllOrdersByPair(t.Context(), currency.NewPairWithDelimiter("LTC", "USDT", "_"), 0, "")
|
||||
_, err := e.WebsocketSpotCancelAllOrdersByPair(t.Context(), currency.NewPairWithDelimiter("LTC", "USDT", "_"), 0, "")
|
||||
require.ErrorIs(t, err, order.ErrSideIsInvalid)
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Spot) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Spot)
|
||||
|
||||
got, err := g.WebsocketSpotCancelAllOrdersByPair(t.Context(), currency.EMPTYPAIR, order.Buy, "")
|
||||
require.NoError(t, err)
|
||||
@@ -146,27 +146,27 @@ func TestWebsocketSpotCancelAllOrdersByPair(t *testing.T) {
|
||||
|
||||
func TestWebsocketSpotAmendOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketSpotAmendOrder(t.Context(), nil)
|
||||
_, err := e.WebsocketSpotAmendOrder(t.Context(), nil)
|
||||
require.ErrorIs(t, err, common.ErrNilPointer)
|
||||
|
||||
amend := &WebsocketAmendOrder{}
|
||||
_, err = g.WebsocketSpotAmendOrder(t.Context(), amend)
|
||||
_, err = e.WebsocketSpotAmendOrder(t.Context(), amend)
|
||||
require.ErrorIs(t, err, order.ErrOrderIDNotSet)
|
||||
|
||||
amend.OrderID = "1337"
|
||||
_, err = g.WebsocketSpotAmendOrder(t.Context(), amend)
|
||||
_, err = e.WebsocketSpotAmendOrder(t.Context(), amend)
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
amend.Pair = BTCUSDT
|
||||
|
||||
_, err = g.WebsocketSpotAmendOrder(t.Context(), amend)
|
||||
_, err = e.WebsocketSpotAmendOrder(t.Context(), amend)
|
||||
require.ErrorIs(t, err, errInvalidAmount)
|
||||
|
||||
amend.Amount = "0.0004"
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
g := newExchangeWithWebsocket(t, asset.Spot) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
g := newExchangeWithWebsocket(t, asset.Spot)
|
||||
|
||||
amend.OrderID = "645029162673"
|
||||
got, err := g.WebsocketSpotAmendOrder(t.Context(), amend)
|
||||
@@ -176,16 +176,16 @@ func TestWebsocketSpotAmendOrder(t *testing.T) {
|
||||
|
||||
func TestWebsocketSpotGetOrderStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.WebsocketSpotGetOrderStatus(t.Context(), "", currency.EMPTYPAIR, "")
|
||||
_, err := e.WebsocketSpotGetOrderStatus(t.Context(), "", currency.EMPTYPAIR, "")
|
||||
require.ErrorIs(t, err, order.ErrOrderIDNotSet)
|
||||
|
||||
_, err = g.WebsocketSpotGetOrderStatus(t.Context(), "1337", currency.EMPTYPAIR, "")
|
||||
_, err = e.WebsocketSpotGetOrderStatus(t.Context(), "1337", currency.EMPTYPAIR, "")
|
||||
require.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, g, canManipulateRealOrders)
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, e, canManipulateRealOrders)
|
||||
|
||||
testexch.UpdatePairsOnce(t, g)
|
||||
g := newExchangeWithWebsocket(t, asset.Spot) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
testexch.UpdatePairsOnce(t, e)
|
||||
g := newExchangeWithWebsocket(t, asset.Spot)
|
||||
|
||||
got, err := g.WebsocketSpotGetOrderStatus(t.Context(), "644999650452", BTCUSDT, "")
|
||||
require.NoError(t, err)
|
||||
@@ -194,28 +194,28 @@ func TestWebsocketSpotGetOrderStatus(t *testing.T) {
|
||||
|
||||
// getWebsocketInstance returns a websocket instance copy for testing.
|
||||
// This restricts the pairs to a single pair per asset type to reduce test time.
|
||||
func newExchangeWithWebsocket(t *testing.T, a asset.Item) *Gateio {
|
||||
func newExchangeWithWebsocket(t *testing.T, a asset.Item) *Exchange {
|
||||
t.Helper()
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
g := new(Gateio) //nolint:govet // Intentional shadow to avoid future copy/paste mistakes
|
||||
require.NoError(t, testexch.Setup(g), "Test instance Setup must not error")
|
||||
testexch.UpdatePairsOnce(t, g)
|
||||
g.API.AuthenticatedSupport = true
|
||||
g.API.AuthenticatedWebsocketSupport = true
|
||||
g.SetCredentials(apiKey, apiSecret, "", "", "", "")
|
||||
g.Websocket.SetCanUseAuthenticatedEndpoints(true)
|
||||
e := new(Exchange) //nolint:govet // Intentional shadow
|
||||
require.NoError(t, testexch.Setup(e), "Test instance Setup must not error")
|
||||
testexch.UpdatePairsOnce(t, e)
|
||||
e.API.AuthenticatedSupport = true
|
||||
e.API.AuthenticatedWebsocketSupport = true
|
||||
e.SetCredentials(apiKey, apiSecret, "", "", "", "")
|
||||
e.Websocket.SetCanUseAuthenticatedEndpoints(true)
|
||||
switch a {
|
||||
case asset.Spot:
|
||||
avail, err := g.GetAvailablePairs(a)
|
||||
avail, err := e.GetAvailablePairs(a)
|
||||
require.NoError(t, err)
|
||||
if len(avail) > 1 { // reduce pairs to 1 to speed up tests
|
||||
avail = avail[:1]
|
||||
}
|
||||
require.NoError(t, g.SetPairs(avail, a, true))
|
||||
require.NoError(t, e.SetPairs(avail, a, true))
|
||||
case asset.Futures:
|
||||
avail, err := g.GetAvailablePairs(a)
|
||||
avail, err := e.GetAvailablePairs(a)
|
||||
require.NoError(t, err)
|
||||
usdtPairs, err := avail.GetPairsByQuote(currency.USDT) // Get USDT margin pairs
|
||||
require.NoError(t, err)
|
||||
@@ -226,11 +226,11 @@ func newExchangeWithWebsocket(t *testing.T, a asset.Item) *Gateio {
|
||||
avail[0] = usdtPairs[0]
|
||||
avail[1] = btcPairs[0]
|
||||
avail = avail[:2]
|
||||
require.NoError(t, g.SetPairs(avail, a, true))
|
||||
require.NoError(t, e.SetPairs(avail, a, true))
|
||||
default:
|
||||
require.NoError(t, g.CurrencyPairs.SetAssetEnabled(a, false))
|
||||
require.NoError(t, e.CurrencyPairs.SetAssetEnabled(a, false))
|
||||
}
|
||||
|
||||
require.NoError(t, g.Websocket.Connect())
|
||||
return g
|
||||
require.NoError(t, e.Websocket.Connect())
|
||||
return e
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,7 +40,7 @@ func newWsOBUpdateManager(snapshotSyncDelay time.Duration) *wsOBUpdateManager {
|
||||
}
|
||||
|
||||
// ProcessOrderbookUpdate processes an orderbook update by syncing snapshot, caching updates and applying them
|
||||
func (m *wsOBUpdateManager) ProcessOrderbookUpdate(ctx context.Context, g *Gateio, firstUpdateID int64, update *orderbook.Update) error {
|
||||
func (m *wsOBUpdateManager) ProcessOrderbookUpdate(ctx context.Context, g *Exchange, firstUpdateID int64, update *orderbook.Update) error {
|
||||
cache := m.LoadCache(update.Pair, update.Asset)
|
||||
cache.mtx.Lock()
|
||||
defer cache.mtx.Unlock()
|
||||
@@ -97,7 +97,7 @@ func (m *wsOBUpdateManager) LoadCache(p currency.Pair, a asset.Item) *updateCach
|
||||
|
||||
// SyncOrderbook fetches and synchronises an orderbook snapshot to the limit size so that pending updates can be
|
||||
// applied to the orderbook.
|
||||
func (c *updateCache) SyncOrderbook(ctx context.Context, g *Gateio, pair currency.Pair, a asset.Item) error {
|
||||
func (c *updateCache) SyncOrderbook(ctx context.Context, g *Exchange, pair currency.Pair, a asset.Item) error {
|
||||
// TODO: When subscription config is added for all assets update limits to use sub.Levels
|
||||
var limit uint64
|
||||
switch a {
|
||||
@@ -150,7 +150,7 @@ func (c *updateCache) SyncOrderbook(ctx context.Context, g *Gateio, pair currenc
|
||||
}
|
||||
|
||||
// ApplyPendingUpdates applies all pending updates to the orderbook
|
||||
func (c *updateCache) applyPendingUpdates(g *Gateio, a asset.Item) error {
|
||||
func (c *updateCache) applyPendingUpdates(g *Exchange, a asset.Item) error {
|
||||
for _, data := range c.updates {
|
||||
lastUpdateID, err := g.Websocket.Orderbook.LastUpdateID(data.update.Pair, a)
|
||||
if err != nil {
|
||||
@@ -171,7 +171,7 @@ func (c *updateCache) applyPendingUpdates(g *Gateio, a asset.Item) error {
|
||||
}
|
||||
|
||||
// applyOrderbookUpdate applies an orderbook update to the orderbook
|
||||
func applyOrderbookUpdate(g *Gateio, update *orderbook.Update) error {
|
||||
func applyOrderbookUpdate(g *Exchange, update *orderbook.Update) error {
|
||||
if update.Asset != asset.Spot {
|
||||
return g.Websocket.Orderbook.Update(update)
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ func TestProcessOrderbookUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
m := newWsOBUpdateManager(0)
|
||||
err := m.ProcessOrderbookUpdate(t.Context(), g, 1337, &orderbook.Update{})
|
||||
err := m.ProcessOrderbookUpdate(t.Context(), e, 1337, &orderbook.Update{})
|
||||
assert.ErrorIs(t, err, currency.ErrCurrencyPairEmpty)
|
||||
|
||||
pair := currency.NewPair(currency.BABY, currency.BABYDOGE)
|
||||
err = g.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
Exchange: g.Name,
|
||||
err = e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
Exchange: e.Name,
|
||||
Pair: pair,
|
||||
Asset: asset.USDTMarginedFutures,
|
||||
Bids: []orderbook.Level{{Price: 1, Amount: 1}},
|
||||
@@ -34,7 +34,7 @@ func TestProcessOrderbookUpdate(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = m.ProcessOrderbookUpdate(t.Context(), g, 1337, &orderbook.Update{
|
||||
err = m.ProcessOrderbookUpdate(t.Context(), e, 1337, &orderbook.Update{
|
||||
UpdateID: 1338,
|
||||
Pair: pair,
|
||||
Asset: asset.USDTMarginedFutures,
|
||||
@@ -44,7 +44,7 @@ func TestProcessOrderbookUpdate(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test orderbook snapshot is behind update
|
||||
err = m.ProcessOrderbookUpdate(t.Context(), g, 1340, &orderbook.Update{
|
||||
err = m.ProcessOrderbookUpdate(t.Context(), e, 1340, &orderbook.Update{
|
||||
UpdateID: 1341,
|
||||
Pair: pair,
|
||||
Asset: asset.USDTMarginedFutures,
|
||||
@@ -61,7 +61,7 @@ func TestProcessOrderbookUpdate(t *testing.T) {
|
||||
cache.mtx.Unlock()
|
||||
|
||||
// Test orderbook snapshot is behind update
|
||||
err = m.ProcessOrderbookUpdate(t.Context(), g, 1342, &orderbook.Update{
|
||||
err = m.ProcessOrderbookUpdate(t.Context(), e, 1342, &orderbook.Update{
|
||||
UpdateID: 1343,
|
||||
Pair: pair,
|
||||
Asset: asset.USDTMarginedFutures,
|
||||
@@ -100,25 +100,25 @@ func TestLoadCache(t *testing.T) {
|
||||
func TestSyncOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
g := new(Gateio)
|
||||
require.NoError(t, testexch.Setup(g), "Setup must not error")
|
||||
require.NoError(t, g.UpdateTradablePairs(t.Context(), false))
|
||||
e := new(Exchange)
|
||||
require.NoError(t, testexch.Setup(e), "Setup must not error")
|
||||
require.NoError(t, e.UpdateTradablePairs(t.Context(), false))
|
||||
|
||||
// Add dummy subscription so that it can be matched and a limit/level can be extracted for initial orderbook sync spot.
|
||||
err := g.Websocket.AddSubscriptions(nil, &subscription.Subscription{Channel: subscription.OrderbookChannel, Interval: kline.HundredMilliseconds})
|
||||
err := e.Websocket.AddSubscriptions(nil, &subscription.Subscription{Channel: subscription.OrderbookChannel, Interval: kline.HundredMilliseconds})
|
||||
require.NoError(t, err)
|
||||
|
||||
m := newWsOBUpdateManager(defaultWSSnapshotSyncDelay)
|
||||
|
||||
for _, a := range []asset.Item{asset.Spot, asset.USDTMarginedFutures} {
|
||||
pair := currency.NewPair(currency.ETH, currency.USDT)
|
||||
err := g.CurrencyPairs.EnablePair(a, pair)
|
||||
err := e.CurrencyPairs.EnablePair(a, pair)
|
||||
require.NoError(t, err)
|
||||
cache := m.LoadCache(pair, a)
|
||||
|
||||
cache.updates = []pendingUpdate{{update: &orderbook.Update{Pair: pair, Asset: a}}}
|
||||
cache.updating = true
|
||||
err = cache.SyncOrderbook(t.Context(), g, pair, a)
|
||||
err = cache.SyncOrderbook(t.Context(), e, pair, a)
|
||||
require.NoError(t, err)
|
||||
require.False(t, cache.updating)
|
||||
require.Empty(t, cache.updates)
|
||||
@@ -128,7 +128,7 @@ func TestSyncOrderbook(t *testing.T) {
|
||||
expectedLimit = 100
|
||||
}
|
||||
|
||||
b, err := g.Websocket.Orderbook.GetOrderbook(pair, a)
|
||||
b, err := e.Websocket.Orderbook.GetOrderbook(pair, a)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, b.Bids, expectedLimit)
|
||||
require.Len(t, b.Asks, expectedLimit)
|
||||
@@ -138,14 +138,14 @@ func TestSyncOrderbook(t *testing.T) {
|
||||
func TestApplyPendingUpdates(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
g := new(Gateio)
|
||||
require.NoError(t, testexch.Setup(g), "Setup must not error")
|
||||
require.NoError(t, g.UpdateTradablePairs(t.Context(), false))
|
||||
e := new(Exchange)
|
||||
require.NoError(t, testexch.Setup(e), "Setup must not error")
|
||||
require.NoError(t, e.UpdateTradablePairs(t.Context(), false))
|
||||
|
||||
m := newWsOBUpdateManager(defaultWSSnapshotSyncDelay)
|
||||
pair := currency.NewPair(currency.LTC, currency.USDT)
|
||||
err := g.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
Exchange: g.Name,
|
||||
err := e.Websocket.Orderbook.LoadSnapshot(&orderbook.Book{
|
||||
Exchange: e.Name,
|
||||
Pair: pair,
|
||||
Asset: asset.USDTMarginedFutures,
|
||||
Bids: []orderbook.Level{{Price: 1, Amount: 1}},
|
||||
@@ -167,20 +167,20 @@ func TestApplyPendingUpdates(t *testing.T) {
|
||||
}
|
||||
|
||||
cache.updates = []pendingUpdate{{update: update, firstUpdateID: 1337}}
|
||||
err = cache.applyPendingUpdates(g, asset.USDTMarginedFutures)
|
||||
err = cache.applyPendingUpdates(e, asset.USDTMarginedFutures)
|
||||
require.ErrorIs(t, err, errOrderbookSnapshotOutdated)
|
||||
|
||||
cache.updates[0].firstUpdateID = 1336
|
||||
err = cache.applyPendingUpdates(g, asset.USDTMarginedFutures)
|
||||
err = cache.applyPendingUpdates(e, asset.USDTMarginedFutures)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestApplyOrderbookUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
g := new(Gateio)
|
||||
require.NoError(t, testexch.Setup(g), "Setup must not error")
|
||||
require.NoError(t, g.UpdateTradablePairs(t.Context(), false))
|
||||
e := new(Exchange)
|
||||
require.NoError(t, testexch.Setup(e), "Setup must not error")
|
||||
require.NoError(t, e.UpdateTradablePairs(t.Context(), false))
|
||||
|
||||
pair := currency.NewBTCUSDT()
|
||||
|
||||
@@ -191,14 +191,14 @@ func TestApplyOrderbookUpdate(t *testing.T) {
|
||||
UpdateTime: time.Now(),
|
||||
}
|
||||
|
||||
err := applyOrderbookUpdate(g, update)
|
||||
err := applyOrderbookUpdate(e, update)
|
||||
require.ErrorIs(t, err, orderbook.ErrDepthNotFound)
|
||||
|
||||
update.Asset = asset.Spot
|
||||
err = applyOrderbookUpdate(g, update)
|
||||
err = applyOrderbookUpdate(e, update)
|
||||
require.ErrorIs(t, err, orderbook.ErrDepthNotFound)
|
||||
|
||||
update.Pair = currency.NewPair(currency.BABY, currency.BABYDOGE)
|
||||
err = applyOrderbookUpdate(g, update)
|
||||
err = applyOrderbookUpdate(e, update)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user