diff --git a/cmd/exchange_template/wrapper_file.tmpl b/cmd/exchange_template/wrapper_file.tmpl index 0c723628..7d810d4c 100644 --- a/cmd/exchange_template/wrapper_file.tmpl +++ b/cmd/exchange_template/wrapper_file.tmpl @@ -403,7 +403,7 @@ func ({{.Variable}} *{{.CapitalName}}) SubmitOrder(ctx context.Context, s *order // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func ({{.Variable}} *{{.CapitalName}}) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Modify, error) { +func ({{.Variable}} *{{.CapitalName}}) ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) { // if err := action.Validate(); err != nil { // return "", err // } diff --git a/engine/order_manager.go b/engine/order_manager.go index b3bcaf91..57b2e9e1 100644 --- a/engine/order_manager.go +++ b/engine/order_manager.go @@ -405,9 +405,9 @@ func (m *OrderManager) Modify(ctx context.Context, mod *order.Modify) (*order.Mo } m.orderStore.commsManager.PushEvent(base.Event{ Type: "order", - Message: fmt.Sprintf(message, mod.Exchange, res.ID), + Message: fmt.Sprintf(message, mod.Exchange, res.OrderID), }) - return &order.ModifyResponse{OrderID: res.ID}, err + return &order.ModifyResponse{OrderID: res.OrderID}, err } // Submit will take in an order struct, send it to the exchange and @@ -892,7 +892,7 @@ func (s *store) updateExisting(od *order.Detail) error { // modifyExisting depends on mod.Exchange and given ID to uniquely identify an order and // modify it. -func (s *store) modifyExisting(id string, mod *order.Modify) error { +func (s *store) modifyExisting(id string, mod *order.ModifyResponse) error { s.m.Lock() defer s.m.Unlock() r, ok := s.Orders[strings.ToLower(mod.Exchange)] @@ -903,7 +903,7 @@ func (s *store) modifyExisting(id string, mod *order.Modify) error { if r[x].ID != id { continue } - r[x].UpdateOrderFromModify(mod) + r[x].UpdateOrderFromModifyResponse(mod) if !r[x].AssetType.IsFutures() { return nil } diff --git a/engine/order_manager_test.go b/engine/order_manager_test.go index b3b09a9c..2fff8c07 100644 --- a/engine/order_manager_test.go +++ b/engine/order_manager_test.go @@ -83,10 +83,13 @@ func (f omfExchange) GetActiveOrders(ctx context.Context, req *order.GetOrdersRe }}, nil } -func (f omfExchange) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Modify, error) { - ans := *action - ans.ID = "modified_order_id" - return &ans, nil +func (f omfExchange) ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) { + ans, err := action.DeriveModifyResponse() + if err != nil { + return nil, err + } + ans.OrderID = "modified_order_id" + return ans, nil } func TestSetupOrderManager(t *testing.T) { @@ -317,12 +320,12 @@ func TestStore_modifyOrder(t *testing.T) { t.Error(err) } - err = m.orderStore.modifyExisting("fake_order_id", &order.Modify{ + err = m.orderStore.modifyExisting("fake_order_id", &order.ModifyResponse{ Exchange: testExchange, - ID: "another_fake_order_id", - Price: 16, - Amount: 256, + OrderID: "another_fake_order_id", + Price: 16, + Amount: 256, }) if err != nil { t.Error(err) diff --git a/engine/websocketroutine_manager.go b/engine/websocketroutine_manager.go index f361c135..217a030a 100644 --- a/engine/websocketroutine_manager.go +++ b/engine/websocketroutine_manager.go @@ -233,12 +233,12 @@ func (m *websocketRoutineManager) websocketDataHandler(exchName string, data int } m.syncer.PrintOrderbookSummary(base, "websocket", nil) case *order.Detail: - m.printOrderSummary(d) if !m.orderManager.Exists(d) { err := m.orderManager.Add(d) if err != nil { return err } + m.printOrderSummary(d, false) } else { od, err := m.orderManager.GetByExchangeAndID(d.Exchange, d.ID) if err != nil { @@ -250,17 +250,7 @@ func (m *websocketRoutineManager) websocketDataHandler(exchName string, data int if err != nil { return err } - } - case *order.Modify: - m.printOrderChangeSummary(d) - od, err := m.orderManager.GetByExchangeAndID(d.Exchange, d.ID) - if err != nil { - return err - } - od.UpdateOrderFromModify(d) - err = m.orderManager.UpdateExistingOrder(od) - if err != nil { - return err + m.printOrderSummary(d, true) } case order.ClassificationError: return fmt.Errorf("%w %s", d.Err, d.Error()) @@ -299,37 +289,21 @@ func (m *websocketRoutineManager) FormatCurrency(p currency.Pair) currency.Pair m.currencyConfig.CurrencyPairFormat.Uppercase) } -// printOrderChangeSummary this function will be deprecated when a order manager -// update is done. -func (m *websocketRoutineManager) printOrderChangeSummary(o *order.Modify) { - if m == nil || atomic.LoadInt32(&m.started) == 0 || o == nil { - return - } - - log.Debugf(log.WebsocketMgr, - "Order Change: %s %s %s %s %s %s OrderID:%s ClientOrderID:%s Price:%f Amount:%f Executed Amount:%f Remaining Amount:%f", - o.Exchange, - o.AssetType, - o.Pair, - o.Status, - o.Type, - o.Side, - o.ID, - o.ClientOrderID, - o.Price, - o.Amount, - o.ExecutedAmount, - o.RemainingAmount) -} - // printOrderSummary this function will be deprecated when a order manager // update is done. -func (m *websocketRoutineManager) printOrderSummary(o *order.Detail) { +func (m *websocketRoutineManager) printOrderSummary(o *order.Detail, isUpdate bool) { if m == nil || atomic.LoadInt32(&m.started) == 0 || o == nil { return } + + orderNotif := "New Order:" + if isUpdate { + orderNotif = "Order Change:" + } + log.Debugf(log.WebsocketMgr, - "New Order: %s %s %s %s %s %s OrderID:%s ClientOrderID:%s Price:%f Amount:%f Executed Amount:%f Remaining Amount:%f", + "%s %s %s %s %s %s %s OrderID:%s ClientOrderID:%s Price:%f Amount:%f Executed Amount:%f Remaining Amount:%f", + orderNotif, o.Exchange, o.AssetType, o.Pair, diff --git a/engine/websocketroutine_manager_test.go b/engine/websocketroutine_manager_test.go index 1938aa7a..dcd482ab 100644 --- a/engine/websocketroutine_manager_test.go +++ b/engine/websocketroutine_manager_test.go @@ -199,7 +199,7 @@ func TestWebsocketRoutineManagerHandleData(t *testing.T) { t.Error("Bad pipeline") } - err = m.websocketDataHandler(exchName, &order.Modify{ + err = m.websocketDataHandler(exchName, &order.Detail{ Exchange: "Bitstamp", ID: orderID, Status: order.Active, diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 9270a2ec..40d4716f 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -1063,7 +1063,7 @@ func (b *Binance) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submi // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (b *Binance) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (b *Binance) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index 1a3fb87a..9d611ce8 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -675,35 +675,33 @@ func (b *Bitfinex) SubmitOrder(ctx context.Context, o *order.Submit) (order.Subm // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (b *Bitfinex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Modify, error) { +func (b *Bitfinex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) { + if !b.Websocket.CanUseAuthenticatedWebsocketForWrapper() { + return nil, common.ErrNotYetImplemented + } + if err := action.Validate(); err != nil { return nil, err } orderIDInt, err := strconv.ParseInt(action.ID, 10, 64) if err != nil { - return &order.Modify{ID: action.ID}, err + return &order.ModifyResponse{OrderID: action.ID}, err } - if b.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - request := WsUpdateOrderRequest{ - OrderID: orderIDInt, - Price: action.Price, - Amount: action.Amount, - } - if action.Side == order.Sell && action.Amount > 0 { - request.Amount *= -1 - } - err = b.WsModifyOrder(&request) - return &order.Modify{ - Exchange: action.Exchange, - AssetType: action.AssetType, - Pair: action.Pair, - ID: action.ID, - Price: action.Price, - Amount: action.Amount, - }, err + + wsRequest := WsUpdateOrderRequest{ + OrderID: orderIDInt, + Price: action.Price, + Amount: action.Amount, } - return nil, common.ErrNotYetImplemented + if action.Side == order.Sell && action.Amount > 0 { + wsRequest.Amount *= -1 + } + err = b.WsModifyOrder(&wsRequest) + if err != nil { + return nil, err + } + return action.DeriveModifyResponse() } // CancelOrder cancels an order by its corresponding ID number diff --git a/exchanges/bitflyer/bitflyer_wrapper.go b/exchanges/bitflyer/bitflyer_wrapper.go index 0758accf..a0a52cd3 100644 --- a/exchanges/bitflyer/bitflyer_wrapper.go +++ b/exchanges/bitflyer/bitflyer_wrapper.go @@ -395,7 +395,7 @@ func (b *Bitflyer) SubmitOrder(_ context.Context, _ *order.Submit) (order.Submit // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (b *Bitflyer) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (b *Bitflyer) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/bithumb/bithumb.go b/exchanges/bithumb/bithumb.go index 365c5716..7b3af521 100644 --- a/exchanges/bithumb/bithumb.go +++ b/exchanges/bithumb/bithumb.go @@ -387,22 +387,6 @@ func (b *Bithumb) PlaceTrade(ctx context.Context, orderCurrency, transactionType b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, privatePlaceTrade, params, &response) } -// ModifyTrade modifies an order already on the exchange books -func (b *Bithumb) ModifyTrade(ctx context.Context, orderID, orderCurrency, transactionType string, units float64, price int64) (OrderPlace, error) { - response := OrderPlace{} - - params := url.Values{} - params.Set("order_currency", strings.ToUpper(orderCurrency)) - params.Set("payment_currency", "KRW") - params.Set("type", strings.ToUpper(transactionType)) - params.Set("units", strconv.FormatFloat(units, 'f', -1, 64)) - params.Set("price", strconv.FormatInt(price, 10)) - params.Set("order_id", orderID) - - return response, - b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, privatePlaceTrade, params, &response) -} - // GetOrderDetails returns specific order details // // orderID: Order number registered for purchase/sales diff --git a/exchanges/bithumb/bithumb_wrapper.go b/exchanges/bithumb/bithumb_wrapper.go index beede051..05ad80aa 100644 --- a/exchanges/bithumb/bithumb_wrapper.go +++ b/exchanges/bithumb/bithumb_wrapper.go @@ -89,7 +89,6 @@ func (b *Bithumb) SetDefaults() { GetOrder: true, CancelOrder: true, SubmitOrder: true, - ModifyOrder: true, DepositHistory: true, WithdrawalHistory: true, UserTradeHistory: true, @@ -512,30 +511,8 @@ func (b *Bithumb) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submi // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (b *Bithumb) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Modify, error) { - if err := action.Validate(); err != nil { - return nil, err - } - - o, err := b.ModifyTrade(ctx, - action.ID, - action.Pair.Base.String(), - action.Side.Lower(), - action.Amount, - int64(action.Price)) - if err != nil { - return nil, err - } - - return &order.Modify{ - Exchange: action.Exchange, - AssetType: action.AssetType, - Pair: action.Pair, - ID: o.Data[0].ContID, - Price: float64(int64(action.Price)), - Amount: action.Amount, - Side: action.Side, - }, nil +func (b *Bithumb) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { + return nil, common.ErrFunctionNotSupported } // CancelOrder cancels an order by its corresponding ID number diff --git a/exchanges/bitmex/bitmex_websocket.go b/exchanges/bitmex/bitmex_websocket.go index f62b7575..1d8cfa85 100644 --- a/exchanges/bitmex/bitmex_websocket.go +++ b/exchanges/bitmex/bitmex_websocket.go @@ -313,7 +313,7 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error { Err: err, } } - b.Websocket.DataHandler <- &order.Modify{ + b.Websocket.DataHandler <- &order.Detail{ Exchange: b.Name, ID: response.Data[i].OrderID, AccountID: strconv.FormatInt(response.Data[i].Account, 10), @@ -424,7 +424,7 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error { Err: err, } } - b.Websocket.DataHandler <- &order.Modify{ + b.Websocket.DataHandler <- &order.Detail{ Price: response.Data[x].Price, Amount: response.Data[x].OrderQuantity, Exchange: b.Name, diff --git a/exchanges/bitmex/bitmex_wrapper.go b/exchanges/bitmex/bitmex_wrapper.go index f470258a..7f538865 100644 --- a/exchanges/bitmex/bitmex_wrapper.go +++ b/exchanges/bitmex/bitmex_wrapper.go @@ -609,34 +609,32 @@ func (b *Bitmex) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submit // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (b *Bitmex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Modify, error) { +func (b *Bitmex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) { if err := action.Validate(); err != nil { return nil, err } - var params OrderAmendParams - if math.Mod(action.Amount, 1) != 0 { return nil, errors.New("contract amount can not have decimals") } - params.OrderID = action.ID - params.OrderQty = int32(action.Amount) - params.Price = action.Price - - o, err := b.AmendOrder(ctx, ¶ms) + o, err := b.AmendOrder(ctx, &OrderAmendParams{ + OrderID: action.ID, + OrderQty: int32(action.Amount), + Price: action.Price}) if err != nil { return nil, err } - return &order.Modify{ - Exchange: action.Exchange, - AssetType: action.AssetType, - Pair: action.Pair, - ID: o.OrderID, - Price: action.Price, - Amount: float64(params.OrderQty), - }, nil + resp, err := action.DeriveModifyResponse() + if err != nil { + return nil, err + } + + resp.OrderID = o.OrderID + resp.RemainingAmount = o.OrderQty + resp.LastUpdated = o.TransactTime + return resp, nil } // CancelOrder cancels an order by its corresponding ID number diff --git a/exchanges/bitstamp/bitstamp_wrapper.go b/exchanges/bitstamp/bitstamp_wrapper.go index 638921a8..89f6d2ef 100644 --- a/exchanges/bitstamp/bitstamp_wrapper.go +++ b/exchanges/bitstamp/bitstamp_wrapper.go @@ -561,7 +561,7 @@ func (b *Bitstamp) SubmitOrder(ctx context.Context, s *order.Submit) (order.Subm // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (b *Bitstamp) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (b *Bitstamp) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/bittrex/bittrex_websocket.go b/exchanges/bittrex/bittrex_websocket.go index b9fceaf6..1c28ae3f 100644 --- a/exchanges/bittrex/bittrex_websocket.go +++ b/exchanges/bittrex/bittrex_websocket.go @@ -615,7 +615,7 @@ func (b *Bittrex) WsProcessUpdateOrder(data *OrderUpdateMessage) error { } } - b.Websocket.DataHandler <- &order.Modify{ + b.Websocket.DataHandler <- &order.Detail{ ImmediateOrCancel: data.Delta.TimeInForce == string(ImmediateOrCancel), FillOrKill: data.Delta.TimeInForce == string(GoodTilCancelled), PostOnly: data.Delta.TimeInForce == string(PostOnlyGoodTilCancelled), diff --git a/exchanges/bittrex/bittrex_wrapper.go b/exchanges/bittrex/bittrex_wrapper.go index 0315d172..94660a90 100644 --- a/exchanges/bittrex/bittrex_wrapper.go +++ b/exchanges/bittrex/bittrex_wrapper.go @@ -587,7 +587,7 @@ func (b *Bittrex) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submi // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (b *Bittrex) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (b *Bittrex) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/btcmarkets/btcmarkets_wrapper.go b/exchanges/btcmarkets/btcmarkets_wrapper.go index b92701e0..557f5261 100644 --- a/exchanges/btcmarkets/btcmarkets_wrapper.go +++ b/exchanges/btcmarkets/btcmarkets_wrapper.go @@ -580,7 +580,7 @@ func (b *BTCMarkets) SubmitOrder(ctx context.Context, s *order.Submit) (order.Su // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (b *BTCMarkets) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Modify, error) { +func (b *BTCMarkets) ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) { if err := action.Validate(); err != nil { return nil, err } @@ -588,33 +588,32 @@ func (b *BTCMarkets) ModifyOrder(ctx context.Context, action *order.Modify) (*or if err != nil { return nil, err } - pair, err := currency.NewPairFromString(resp.MarketID) + mod, err := action.DeriveModifyResponse() if err != nil { return nil, err } - side, err := order.StringToOrderSide(resp.Side) + mod.Pair, err = currency.NewPairFromString(resp.MarketID) if err != nil { return nil, err } - orderT, err := order.StringToOrderType(resp.Type) + mod.Side, err = order.StringToOrderSide(resp.Side) if err != nil { return nil, err } - status, err := order.StringToOrderStatus(resp.Status) + mod.Type, err = order.StringToOrderType(resp.Type) if err != nil { return nil, err } - return &order.Modify{ - ID: resp.OrderID, - Pair: pair, - Side: side, - Type: orderT, - Date: resp.CreationTime, - Price: resp.Price, - Amount: resp.Amount, - RemainingAmount: resp.OpenAmount, - Status: status, - }, nil + mod.Status, err = order.StringToOrderStatus(resp.Status) + if err != nil { + return nil, err + } + mod.OrderID = resp.OrderID + mod.LastUpdated = resp.CreationTime + mod.Price = resp.Price + mod.Amount = resp.Amount + mod.RemainingAmount = resp.OpenAmount + return mod, nil } // CancelOrder cancels an order by its corresponding ID number diff --git a/exchanges/btse/btse_wrapper.go b/exchanges/btse/btse_wrapper.go index 44896ab5..bb261a2a 100644 --- a/exchanges/btse/btse_wrapper.go +++ b/exchanges/btse/btse_wrapper.go @@ -551,7 +551,7 @@ func (b *BTSE) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitRe // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (b *BTSE) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (b *BTSE) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/coinbasepro/coinbasepro_wrapper.go b/exchanges/coinbasepro/coinbasepro_wrapper.go index 557bb89b..96d8e987 100644 --- a/exchanges/coinbasepro/coinbasepro_wrapper.go +++ b/exchanges/coinbasepro/coinbasepro_wrapper.go @@ -578,7 +578,7 @@ func (c *CoinbasePro) SubmitOrder(ctx context.Context, s *order.Submit) (order.S // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (c *CoinbasePro) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (c *CoinbasePro) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/coinut/coinut_websocket.go b/exchanges/coinut/coinut_websocket.go index 1caba426..c797c223 100644 --- a/exchanges/coinut/coinut_websocket.go +++ b/exchanges/coinut/coinut_websocket.go @@ -194,7 +194,7 @@ func (c *COINUT) wsHandleData(ctx context.Context, respRaw []byte) error { if err != nil { return err } - c.Websocket.DataHandler <- &order.Modify{ + c.Websocket.DataHandler <- &order.Detail{ Exchange: c.Name, ID: strconv.FormatInt(cancel.OrderID, 10), Status: order.Cancelled, @@ -208,7 +208,7 @@ func (c *COINUT) wsHandleData(ctx context.Context, respRaw []byte) error { return err } for i := range cancels.Results { - c.Websocket.DataHandler <- &order.Modify{ + c.Websocket.DataHandler <- &order.Detail{ Exchange: c.Name, ID: strconv.FormatInt(cancels.Results[i].OrderID, 10), Status: order.Cancelled, diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index 87a51f4f..0a86e1bc 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -679,7 +679,7 @@ func (c *COINUT) SubmitOrder(ctx context.Context, o *order.Submit) (order.Submit // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (c *COINUT) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (c *COINUT) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/exmo/exmo_wrapper.go b/exchanges/exmo/exmo_wrapper.go index 44c4d43d..72992f84 100644 --- a/exchanges/exmo/exmo_wrapper.go +++ b/exchanges/exmo/exmo_wrapper.go @@ -500,7 +500,7 @@ func (e *EXMO) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitRe // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (e *EXMO) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (e *EXMO) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/ftx/ftx_wrapper.go b/exchanges/ftx/ftx_wrapper.go index 78ef1731..5fdb4738 100644 --- a/exchanges/ftx/ftx_wrapper.go +++ b/exchanges/ftx/ftx_wrapper.go @@ -682,12 +682,16 @@ func (f *FTX) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitRes // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (f *FTX) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Modify, error) { +func (f *FTX) ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) { if err := action.Validate(); err != nil { return nil, err } - if action.TriggerPrice != 0 { + var id string + var remainingAmount float64 + switch { + case action.TriggerPrice != 0: + var a TriggerOrderData a, err := f.ModifyTriggerOrder(ctx, action.ID, action.Type.String(), @@ -698,21 +702,10 @@ func (f *FTX) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Mod if err != nil { return nil, err } - return &order.Modify{ - Exchange: action.Exchange, - AssetType: action.AssetType, - Pair: action.Pair, - ID: strconv.FormatInt(a.ID, 10), - Price: action.Price, - Amount: action.Amount, - TriggerPrice: action.TriggerPrice, - Type: action.Type, - }, err - } - var o OrderData - var err error - if action.ID == "" { - o, err = f.ModifyOrderByClientID(ctx, + id = strconv.FormatInt(a.ID, 10) + remainingAmount = a.Size - a.FilledSize + case action.ID == "": + o, err := f.ModifyOrderByClientID(ctx, action.ClientOrderID, action.ClientOrderID, action.Price, @@ -720,8 +713,10 @@ func (f *FTX) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Mod if err != nil { return nil, err } - } else { - o, err = f.ModifyPlacedOrder(ctx, + id = strconv.FormatInt(o.ID, 10) + remainingAmount = o.RemainingSize + default: + o, err := f.ModifyPlacedOrder(ctx, action.ID, action.ClientOrderID, action.Price, @@ -729,15 +724,16 @@ func (f *FTX) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Mod if err != nil { return nil, err } + id = strconv.FormatInt(o.ID, 10) + remainingAmount = o.RemainingSize } - return &order.Modify{ - Exchange: action.Exchange, - AssetType: action.AssetType, - Pair: action.Pair, - ID: strconv.FormatInt(o.ID, 10), - Price: action.Price, - Amount: action.Amount, - }, err + resp, err := action.DeriveModifyResponse() + if err != nil { + return nil, err + } + resp.OrderID = id + resp.RemainingAmount = remainingAmount + return resp, nil } // CancelOrder cancels an order by its corresponding ID number diff --git a/exchanges/gateio/gateio_wrapper.go b/exchanges/gateio/gateio_wrapper.go index 0cb5ce82..697d3445 100644 --- a/exchanges/gateio/gateio_wrapper.go +++ b/exchanges/gateio/gateio_wrapper.go @@ -544,7 +544,7 @@ func (g *Gateio) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submit // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (g *Gateio) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (g *Gateio) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/gemini/gemini_wrapper.go b/exchanges/gemini/gemini_wrapper.go index e76a87ca..62ecc49f 100644 --- a/exchanges/gemini/gemini_wrapper.go +++ b/exchanges/gemini/gemini_wrapper.go @@ -573,7 +573,7 @@ func (g *Gemini) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submit // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (g *Gemini) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (g *Gemini) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go index ffaae397..ce7a8a72 100644 --- a/exchanges/hitbtc/hitbtc_wrapper.go +++ b/exchanges/hitbtc/hitbtc_wrapper.go @@ -602,7 +602,7 @@ func (h *HitBTC) SubmitOrder(ctx context.Context, o *order.Submit) (order.Submit // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (h *HitBTC) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (h *HitBTC) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index abfd880f..d4d53dba 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -999,7 +999,7 @@ func (h *HUOBI) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitR // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (h *HUOBI) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (h *HUOBI) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/interfaces.go b/exchanges/interfaces.go index 159b2ebd..351197c4 100644 --- a/exchanges/interfaces.go +++ b/exchanges/interfaces.go @@ -52,7 +52,6 @@ type IBotExchange interface { GetDepositAddress(ctx context.Context, cryptocurrency currency.Code, accountID, chain string) (*deposit.Address, error) GetAvailableTransferChains(ctx context.Context, cryptocurrency currency.Code) ([]string, error) GetWithdrawalsHistory(ctx context.Context, code currency.Code) ([]WithdrawalHistory, error) - WithdrawCryptocurrencyFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) WithdrawFiatFunds(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) WithdrawFiatFundsToInternationalBank(ctx context.Context, withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) @@ -93,7 +92,7 @@ type IBotExchange interface { // OrderManagement defines functionality for order management type OrderManagement interface { SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitResponse, error) - ModifyOrder(ctx context.Context, action *order.Modify) (*order.Modify, error) + ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) CancelOrder(ctx context.Context, o *order.Cancel) error CancelBatchOrders(ctx context.Context, o []order.Cancel) (order.CancelBatchResponse, error) CancelAllOrders(ctx context.Context, orders *order.Cancel) (order.CancelAllResponse, error) diff --git a/exchanges/itbit/itbit_wrapper.go b/exchanges/itbit/itbit_wrapper.go index 87de8ad3..0f6c7271 100644 --- a/exchanges/itbit/itbit_wrapper.go +++ b/exchanges/itbit/itbit_wrapper.go @@ -431,7 +431,7 @@ func (i *ItBit) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitR // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (i *ItBit) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (i *ItBit) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/kraken/kraken_websocket.go b/exchanges/kraken/kraken_websocket.go index 6db06aed..7f0c3197 100644 --- a/exchanges/kraken/kraken_websocket.go +++ b/exchanges/kraken/kraken_websocket.go @@ -593,7 +593,7 @@ func (k *Kraken) wsProcessOpenOrders(ownOrders interface{}) error { if err != nil { return err } - k.Websocket.DataHandler <- &order.Modify{ + k.Websocket.DataHandler <- &order.Detail{ Leverage: val.Description.Leverage, Price: val.Price, Amount: val.Volume, @@ -611,7 +611,7 @@ func (k *Kraken) wsProcessOpenOrders(ownOrders interface{}) error { Pair: p, } } else { - k.Websocket.DataHandler <- &order.Modify{ + k.Websocket.DataHandler <- &order.Detail{ Exchange: k.Name, ID: key, Status: oStatus, diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index 4fdd9c04..ef315b65 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -786,7 +786,7 @@ func (k *Kraken) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submit // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (k *Kraken) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (k *Kraken) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/lbank/lbank_wrapper.go b/exchanges/lbank/lbank_wrapper.go index a6ba9247..7e7c8086 100644 --- a/exchanges/lbank/lbank_wrapper.go +++ b/exchanges/lbank/lbank_wrapper.go @@ -485,7 +485,7 @@ func (l *Lbank) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitR // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (l *Lbank) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (l *Lbank) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/localbitcoins/localbitcoins_wrapper.go b/exchanges/localbitcoins/localbitcoins_wrapper.go index 1853594f..2253d26b 100644 --- a/exchanges/localbitcoins/localbitcoins_wrapper.go +++ b/exchanges/localbitcoins/localbitcoins_wrapper.go @@ -445,7 +445,7 @@ func (l *LocalBitcoins) SubmitOrder(ctx context.Context, s *order.Submit) (order // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (l *LocalBitcoins) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (l *LocalBitcoins) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/okgroup/okgroup_wrapper.go b/exchanges/okgroup/okgroup_wrapper.go index 6d16adb1..d1841a1b 100644 --- a/exchanges/okgroup/okgroup_wrapper.go +++ b/exchanges/okgroup/okgroup_wrapper.go @@ -316,7 +316,7 @@ func (o *OKGroup) SubmitOrder(ctx context.Context, s *order.Submit) (order.Submi // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (o *OKGroup) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (o *OKGroup) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/order/order_test.go b/exchanges/order/order_test.go index 8c9043a5..3d75d870 100644 --- a/exchanges/order/order_test.go +++ b/exchanges/order/order_test.go @@ -843,7 +843,6 @@ func BenchmarkStringToOrderStatus(b *testing.B) { } func TestUpdateOrderFromModify(t *testing.T) { - var leet = "1337" od := Detail{ID: "1"} updated := time.Now() @@ -852,94 +851,50 @@ func TestUpdateOrderFromModify(t *testing.T) { t.Fatal(err) } - om := Modify{ + om := ModifyResponse{ ImmediateOrCancel: true, - HiddenOrder: true, - FillOrKill: true, PostOnly: true, - Leverage: 1.0, Price: 1, Amount: 1, - LimitPriceUpper: 1, - LimitPriceLower: 1, TriggerPrice: 1, - QuoteAmount: 1, - ExecutedAmount: 1, RemainingAmount: 1, - Fee: 1, Exchange: "1", - InternalOrderID: "1", - ID: "1", - AccountID: "1", - ClientID: "1", - WalletAddress: "1", Type: 1, Side: 1, Status: 1, AssetType: 1, LastUpdated: updated, Pair: pair, - Trades: []TradeHistory{}, } - od.UpdateOrderFromModify(&om) + od.UpdateOrderFromModifyResponse(&om) if od.InternalOrderID == "1" { t.Error("Should not be able to update the internal order ID") } if !od.ImmediateOrCancel { t.Error("Failed to update") } - if !od.HiddenOrder { - t.Error("Failed to update") - } - if !od.FillOrKill { - t.Error("Failed to update") - } if !od.PostOnly { t.Error("Failed to update") } - if od.Leverage != 1 { - t.Error("Failed to update") - } if od.Price != 1 { t.Error("Failed to update") } if od.Amount != 1 { t.Error("Failed to update") } - if od.LimitPriceLower != 1 { - t.Error("Failed to update") - } - if od.LimitPriceUpper != 1 { - t.Error("Failed to update") - } if od.TriggerPrice != 1 { t.Error("Failed to update") } - if od.QuoteAmount != 1 { - t.Error("Failed to update") - } - if od.ExecutedAmount != 1 { - t.Error("Failed to update") - } if od.RemainingAmount != 1 { t.Error("Failed to update") } - if od.Fee != 1 { - t.Error("Failed to update") - } if od.Exchange != "" { t.Error("Should not be able to update exchange via modify") } if od.ID != "1" { t.Error("Failed to update") } - if od.ClientID != "1" { - t.Error("Failed to update") - } - if od.WalletAddress != "1" { - t.Error("Failed to update") - } if od.Type != 1 { t.Error("Failed to update") } @@ -961,49 +916,6 @@ func TestUpdateOrderFromModify(t *testing.T) { if od.Trades != nil { t.Error("Failed to update") } - - om.Trades = append(om.Trades, TradeHistory{TID: "1"}, TradeHistory{TID: "2"}) - od.UpdateOrderFromModify(&om) - if len(od.Trades) != 2 { - t.Error("Failed to add trades") - } - om.Trades[0].Exchange = leet - om.Trades[0].Price = 1337 - om.Trades[0].Fee = 1337 - om.Trades[0].IsMaker = true - om.Trades[0].Timestamp = updated - om.Trades[0].Description = leet - om.Trades[0].Side = UnknownSide - om.Trades[0].Type = UnknownType - om.Trades[0].Amount = 1337 - od.UpdateOrderFromModify(&om) - if od.Trades[0].Exchange == leet { - t.Error("Should not be able to update exchange from update") - } - if od.Trades[0].Price != 1337 { - t.Error("Failed to update trades") - } - if od.Trades[0].Fee != 1337 { - t.Error("Failed to update trades") - } - if !od.Trades[0].IsMaker { - t.Error("Failed to update trades") - } - if od.Trades[0].Timestamp != updated { - t.Error("Failed to update trades") - } - if od.Trades[0].Description != leet { - t.Error("Failed to update trades") - } - if od.Trades[0].Side != UnknownSide { - t.Error("Failed to update trades") - } - if od.Trades[0].Type != UnknownType { - t.Error("Failed to update trades") - } - if od.Trades[0].Amount != 1337 { - t.Error("Failed to update trades") - } } func TestUpdateOrderFromDetail(t *testing.T) { @@ -1635,6 +1547,84 @@ func TestDetail_CopyPointerOrderSlice(t *testing.T) { } } +func TestDeriveModify(t *testing.T) { + t.Parallel() + var o *Detail + if _, err := o.DeriveModify(); !errors.Is(err, errOrderDetailIsNil) { + t.Fatalf("received: '%v' but expected: '%v'", err, errOrderDetailIsNil) + } + + pair := currency.NewPair(currency.BTC, currency.AUD) + + o = &Detail{ + Exchange: "wow", + ID: "wow2", + ClientOrderID: "wow3", + Type: Market, + Side: Long, + AssetType: asset.Futures, + Pair: pair, + } + + mod, err := o.DeriveModify() + if !errors.Is(err, nil) { + t.Fatalf("received: '%v' but expected: '%v'", err, nil) + } + + if mod == nil { + t.Fatal("should not be nil") + } + + if mod.Exchange != "wow" || + mod.ID != "wow2" || + mod.ClientOrderID != "wow3" || + mod.Type != Market || + mod.Side != Long || + mod.AssetType != asset.Futures || + !mod.Pair.Equal(pair) { + t.Fatal("unexpected values") + } +} + +func TestDeriveModifyResponse(t *testing.T) { + t.Parallel() + var mod *Modify + if _, err := mod.DeriveModifyResponse(); !errors.Is(err, errOrderDetailIsNil) { + t.Fatalf("received: '%v' but expected: '%v'", err, errOrderDetailIsNil) + } + + pair := currency.NewPair(currency.BTC, currency.AUD) + + mod = &Modify{ + Exchange: "wow", + ID: "wow2", + ClientOrderID: "wow3", + Type: Market, + Side: Long, + AssetType: asset.Futures, + Pair: pair, + } + + modresp, err := mod.DeriveModifyResponse() + if !errors.Is(err, nil) { + t.Fatalf("received: '%v' but expected: '%v'", err, nil) + } + + if modresp == nil { + t.Fatal("should not be nil") + } + + if modresp.Exchange != "wow" || + modresp.OrderID != "wow2" || + modresp.ClientOrderID != "wow3" || + modresp.Type != Market || + modresp.Side != Long || + modresp.AssetType != asset.Futures || + !modresp.Pair.Equal(pair) { + t.Fatal("unexpected values") + } +} + func TestDeriveCancel(t *testing.T) { t.Parallel() var o *Detail @@ -1660,7 +1650,6 @@ func TestDeriveCancel(t *testing.T) { if !errors.Is(err, nil) { t.Fatalf("received: '%v' but expected: '%v'", err, nil) } - if cancel.Exchange != "wow" || cancel.ID != "wow1" || cancel.AccountID != "wow2" || @@ -1671,6 +1660,6 @@ func TestDeriveCancel(t *testing.T) { cancel.Side != Long || !cancel.Pair.Equal(pair) || cancel.AssetType != asset.Futures { - t.Fatal("unexpected values") + t.Fatalf("unexpected values %+v", cancel) } } diff --git a/exchanges/order/order_types.go b/exchanges/order/order_types.go index b9771cf1..b13715b8 100644 --- a/exchanges/order/order_types.go +++ b/exchanges/order/order_types.go @@ -83,40 +83,47 @@ type SubmitResponse struct { // Each exchange has their own requirements, so not all fields // are required to be populated type Modify struct { + // Order Identifiers + Exchange string + ID string + ClientOrderID string + Type Type + Side Side + AssetType asset.Item + Pair currency.Pair + + // Change fields ImmediateOrCancel bool - HiddenOrder bool - FillOrKill bool PostOnly bool - Leverage float64 Price float64 Amount float64 - LimitPriceUpper float64 - LimitPriceLower float64 TriggerPrice float64 - QuoteAmount float64 - ExecutedAmount float64 - RemainingAmount float64 - Fee float64 - Exchange string - InternalOrderID string - ID string - ClientOrderID string - AccountID string - ClientID string - WalletAddress string - Type Type - Side Side - Status Status - AssetType asset.Item - Date time.Time - LastUpdated time.Time - Pair currency.Pair - Trades []TradeHistory } // ModifyResponse is an order modifying return type type ModifyResponse struct { - OrderID string + // Order Identifiers + Exchange string + OrderID string + ClientOrderID string + Pair currency.Pair + Type Type + Side Side + Status Status + AssetType asset.Item + + // Fields that will be copied over from Modify + ImmediateOrCancel bool + PostOnly bool + Price float64 + Amount float64 + TriggerPrice float64 + + // Fields that need to be handled in scope after DeriveModifyResponse() + // if applicable + RemainingAmount float64 + Date time.Time + LastUpdated time.Time } // Detail contains all properties of an order diff --git a/exchanges/order/orders.go b/exchanges/order/orders.go index b5b669b4..e0405fc0 100644 --- a/exchanges/order/orders.go +++ b/exchanges/order/orders.go @@ -242,26 +242,18 @@ func (d *Detail) UpdateOrderFromDetail(m *Detail) { } } -// UpdateOrderFromModify Will update an order detail (used in order management) +// UpdateOrderFromModifyResponse Will update an order detail (used in order management) // by comparing passed in and existing values -func (d *Detail) UpdateOrderFromModify(m *Modify) { +func (d *Detail) UpdateOrderFromModifyResponse(m *ModifyResponse) { var updated bool - if m.ID != "" && d.ID != m.ID { - d.ID = m.ID + if m.OrderID != "" && d.ID != m.OrderID { + d.ID = m.OrderID updated = true } if d.ImmediateOrCancel != m.ImmediateOrCancel { d.ImmediateOrCancel = m.ImmediateOrCancel updated = true } - if d.HiddenOrder != m.HiddenOrder { - d.HiddenOrder = m.HiddenOrder - updated = true - } - if d.FillOrKill != m.FillOrKill { - d.FillOrKill = m.FillOrKill - updated = true - } if m.Price > 0 && m.Price != d.Price { d.Price = m.Price updated = true @@ -270,34 +262,10 @@ func (d *Detail) UpdateOrderFromModify(m *Modify) { d.Amount = m.Amount updated = true } - if m.LimitPriceUpper > 0 && m.LimitPriceUpper != d.LimitPriceUpper { - d.LimitPriceUpper = m.LimitPriceUpper - updated = true - } - if m.LimitPriceLower > 0 && m.LimitPriceLower != d.LimitPriceLower { - d.LimitPriceLower = m.LimitPriceLower - updated = true - } if m.TriggerPrice > 0 && m.TriggerPrice != d.TriggerPrice { d.TriggerPrice = m.TriggerPrice updated = true } - if m.QuoteAmount > 0 && m.QuoteAmount != d.QuoteAmount { - d.QuoteAmount = m.QuoteAmount - updated = true - } - if m.ExecutedAmount > 0 && m.ExecutedAmount != d.ExecutedAmount { - d.ExecutedAmount = m.ExecutedAmount - updated = true - } - if m.Fee > 0 && m.Fee != d.Fee { - d.Fee = m.Fee - updated = true - } - if m.AccountID != "" && m.AccountID != d.AccountID { - d.AccountID = m.AccountID - updated = true - } if m.PostOnly != d.PostOnly { d.PostOnly = m.PostOnly updated = true @@ -308,18 +276,6 @@ func (d *Detail) UpdateOrderFromModify(m *Modify) { d.Pair = m.Pair updated = true } - if m.Leverage != 0 && m.Leverage != d.Leverage { - d.Leverage = m.Leverage - updated = true - } - if m.ClientID != "" && m.ClientID != d.ClientID { - d.ClientID = m.ClientID - updated = true - } - if m.WalletAddress != "" && m.WalletAddress != d.WalletAddress { - d.WalletAddress = m.WalletAddress - updated = true - } if m.Type != UnknownType && m.Type != d.Type { d.Type = m.Type updated = true @@ -336,52 +292,6 @@ func (d *Detail) UpdateOrderFromModify(m *Modify) { d.AssetType = m.AssetType updated = true } - for x := range m.Trades { - var found bool - for y := range d.Trades { - if d.Trades[y].TID != m.Trades[x].TID { - continue - } - found = true - if d.Trades[y].Fee != m.Trades[x].Fee { - d.Trades[y].Fee = m.Trades[x].Fee - updated = true - } - if m.Trades[x].Price != 0 && d.Trades[y].Price != m.Trades[x].Price { - d.Trades[y].Price = m.Trades[x].Price - updated = true - } - if d.Trades[y].Side != m.Trades[x].Side { - d.Trades[y].Side = m.Trades[x].Side - updated = true - } - if d.Trades[y].Type != m.Trades[x].Type { - d.Trades[y].Type = m.Trades[x].Type - updated = true - } - if d.Trades[y].Description != m.Trades[x].Description { - d.Trades[y].Description = m.Trades[x].Description - updated = true - } - if m.Trades[x].Amount != 0 && d.Trades[y].Amount != m.Trades[x].Amount { - d.Trades[y].Amount = m.Trades[x].Amount - updated = true - } - if d.Trades[y].Timestamp != m.Trades[x].Timestamp { - d.Trades[y].Timestamp = m.Trades[x].Timestamp - updated = true - } - if d.Trades[y].IsMaker != m.Trades[x].IsMaker { - d.Trades[y].IsMaker = m.Trades[x].IsMaker - updated = true - } - } - if !found { - d.Trades = append(d.Trades, m.Trades[x]) - updated = true - } - m.RemainingAmount -= m.Trades[x].Amount - } if m.RemainingAmount > 0 && m.RemainingAmount != d.RemainingAmount { d.RemainingAmount = m.RemainingAmount updated = true @@ -494,6 +404,47 @@ func CopyPointerOrderSlice(old []*Detail) []*Detail { return copySlice } +// DeriveModify populates a modify struct by the managed order details. Note: +// Price, Amount, Trigger price and order execution bools need to be changed +// in scope. This only derives identifiers for ease. +func (d *Detail) DeriveModify() (*Modify, error) { + if d == nil { + return nil, errOrderDetailIsNil + } + return &Modify{ + Exchange: d.Exchange, + ID: d.ID, + ClientOrderID: d.ClientOrderID, + Type: d.Type, + Side: d.Side, + AssetType: d.AssetType, + Pair: d.Pair, + }, nil +} + +// DeriveModifyResponse populates a modify response with its identifiers for +// cross exchange standard. NOTE: New OrderID and/or ClientOrderID plus any +// changes *might* need to be populated in scope. +func (m *Modify) DeriveModifyResponse() (*ModifyResponse, error) { + if m == nil { + return nil, errOrderDetailIsNil + } + return &ModifyResponse{ + Exchange: m.Exchange, + OrderID: m.ID, + ClientOrderID: m.ClientOrderID, + Type: m.Type, + Side: m.Side, + AssetType: m.AssetType, + Pair: m.Pair, + ImmediateOrCancel: m.ImmediateOrCancel, + PostOnly: m.PostOnly, + Price: m.Price, + Amount: m.Amount, + TriggerPrice: m.TriggerPrice, + }, nil +} + // DeriveCancel populates a cancel struct by the managed order details func (d *Detail) DeriveCancel() (*Cancel, error) { if d == nil { diff --git a/exchanges/poloniex/poloniex_websocket.go b/exchanges/poloniex/poloniex_websocket.go index 1de2061b..5b98a374 100644 --- a/exchanges/poloniex/poloniex_websocket.go +++ b/exchanges/poloniex/poloniex_websocket.go @@ -822,7 +822,7 @@ func (p *Poloniex) processAccountOrderUpdate(notification []interface{}) error { // null returned so ok check is not needed clientOrderID, _ := notification[4].(string) - p.Websocket.DataHandler <- &order.Modify{ + p.Websocket.DataHandler <- &order.Detail{ Exchange: p.Name, RemainingAmount: cancelledAmount, Amount: amount + cancelledAmount, @@ -1048,7 +1048,7 @@ func (p *Poloniex) processAccountTrades(notification []interface{}) error { return err } - p.Websocket.DataHandler <- &order.Modify{ + p.Websocket.DataHandler <- &order.Detail{ Exchange: p.Name, ID: strconv.FormatFloat(orderID, 'f', -1, 64), Fee: totalFee, @@ -1080,7 +1080,7 @@ func (p *Poloniex) processAccountKilledOrder(notification []interface{}) error { // null returned so ok check is not needed clientOrderID, _ := notification[2].(string) - p.Websocket.DataHandler <- &order.Modify{ + p.Websocket.DataHandler <- &order.Detail{ Exchange: p.Name, ID: strconv.FormatFloat(orderID, 'f', -1, 64), Status: order.Cancelled, diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go index a1ff81b6..f0feb125 100644 --- a/exchanges/poloniex/poloniex_wrapper.go +++ b/exchanges/poloniex/poloniex_wrapper.go @@ -567,7 +567,7 @@ func (p *Poloniex) SubmitOrder(ctx context.Context, s *order.Submit) (order.Subm // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (p *Poloniex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Modify, error) { +func (p *Poloniex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) { if err := action.Validate(); err != nil { return nil, err } @@ -587,16 +587,12 @@ func (p *Poloniex) ModifyOrder(ctx context.Context, action *order.Modify) (*orde return nil, err } - return &order.Modify{ - Exchange: action.Exchange, - AssetType: action.AssetType, - Pair: action.Pair, - ID: strconv.FormatInt(resp.OrderNumber, 10), - Price: action.Price, - Amount: action.Amount, - PostOnly: action.PostOnly, - ImmediateOrCancel: action.ImmediateOrCancel, - }, nil + modResp, err := action.DeriveModifyResponse() + if err != nil { + return nil, err + } + modResp.OrderID = strconv.FormatInt(resp.OrderNumber, 10) + return modResp, nil } // CancelOrder cancels an order by its corresponding ID number diff --git a/exchanges/sharedtestvalues/customex.go b/exchanges/sharedtestvalues/customex.go index 908e288b..d685c1ac 100644 --- a/exchanges/sharedtestvalues/customex.go +++ b/exchanges/sharedtestvalues/customex.go @@ -146,7 +146,7 @@ func (c *CustomEx) SubmitOrder(ctx context.Context, s *order.Submit) (order.Subm return order.SubmitResponse{}, nil } -func (c *CustomEx) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (c *CustomEx) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, nil } diff --git a/exchanges/yobit/yobit_wrapper.go b/exchanges/yobit/yobit_wrapper.go index 05105d0a..836b9ba0 100644 --- a/exchanges/yobit/yobit_wrapper.go +++ b/exchanges/yobit/yobit_wrapper.go @@ -439,7 +439,7 @@ func (y *Yobit) SubmitOrder(ctx context.Context, s *order.Submit) (order.SubmitR // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (y *Yobit) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (y *Yobit) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported } diff --git a/exchanges/zb/zb_websocket.go b/exchanges/zb/zb_websocket.go index 5c257894..2979730c 100644 --- a/exchanges/zb/zb_websocket.go +++ b/exchanges/zb/zb_websocket.go @@ -219,7 +219,7 @@ func (z *ZB) wsHandleData(respRaw []byte) error { return err } - z.Websocket.DataHandler <- &order.Modify{ + z.Websocket.DataHandler <- &order.Detail{ Exchange: z.Name, ID: strconv.FormatInt(o.Data.EntrustID, 10), Pair: p, diff --git a/exchanges/zb/zb_wrapper.go b/exchanges/zb/zb_wrapper.go index 6dbf7b85..d693c839 100644 --- a/exchanges/zb/zb_wrapper.go +++ b/exchanges/zb/zb_wrapper.go @@ -528,7 +528,7 @@ func (z *ZB) SubmitOrder(ctx context.Context, o *order.Submit) (order.SubmitResp // ModifyOrder will allow of changing orderbook placement and limit to // market conversion -func (z *ZB) ModifyOrder(_ context.Context, _ *order.Modify) (*order.Modify, error) { +func (z *ZB) ModifyOrder(_ context.Context, _ *order.Modify) (*order.ModifyResponse, error) { return nil, common.ErrFunctionNotSupported }