github.com/bitfinexcom/bitfinex-api-go@v0.0.0-20210608095005-9e0b26f200fb/v2/rest/orders.go (about)

     1  package rest
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"path"
     7  
     8  	"github.com/bitfinexcom/bitfinex-api-go/pkg/models/common"
     9  	"github.com/bitfinexcom/bitfinex-api-go/pkg/models/notification"
    10  	"github.com/bitfinexcom/bitfinex-api-go/pkg/models/order"
    11  	"github.com/bitfinexcom/bitfinex-api-go/pkg/models/tradeexecutionupdate"
    12  )
    13  
    14  // OrderService manages data flow for the Order API endpoint
    15  type OrderService struct {
    16  	requestFactory
    17  	Synchronous
    18  }
    19  
    20  type OrderIDs []int
    21  type GroupOrderIDs []int
    22  type ClientOrderIDs [][]interface{}
    23  type OrderOps [][]interface{}
    24  
    25  // OrderMultiOpsRequest - data structure for constructing order multi ops request payload
    26  type OrderMultiOpsRequest struct {
    27  	Ops OrderOps `json:"ops"`
    28  }
    29  
    30  // CancelOrderMultiRequest - data structure for constructing cancel order multi request payload
    31  type CancelOrderMultiRequest struct {
    32  	OrderIDs       OrderIDs       `json:"id,omitempty"`
    33  	GroupOrderIDs  GroupOrderIDs  `json:"gid,omitempty"`
    34  	ClientOrderIDs ClientOrderIDs `json:"cid,omitempty"`
    35  	All            int            `json:"all,omitempty"`
    36  }
    37  
    38  // Retrieves all of the active orders
    39  // See https://docs.bitfinex.com/reference#rest-auth-orders for more info
    40  func (s *OrderService) All() (*order.Snapshot, error) {
    41  	// use no symbol, this will get all orders
    42  	return s.getActiveOrders("")
    43  }
    44  
    45  // Retrieves all of the active orders with for the given symbol
    46  // See https://docs.bitfinex.com/reference#rest-auth-orders for more info
    47  func (s *OrderService) GetBySymbol(symbol string) (*order.Snapshot, error) {
    48  	// use no symbol, this will get all orders
    49  	return s.getActiveOrders(symbol)
    50  }
    51  
    52  // Retrieve an active order by the given ID
    53  // See https://docs.bitfinex.com/reference#rest-auth-orders for more info
    54  func (s *OrderService) GetByOrderId(orderID int64) (o *order.Order, err error) {
    55  	os, err := s.All()
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	for _, order := range os.Snapshot {
    60  		if order.ID == orderID {
    61  			return order, nil
    62  		}
    63  	}
    64  	return nil, common.ErrNotFound
    65  }
    66  
    67  // Retrieves all past orders
    68  // See https://docs.bitfinex.com/reference#orders-history for more info
    69  func (s *OrderService) AllHistory() (*order.Snapshot, error) {
    70  	// use no symbol, this will get all orders
    71  	return s.getHistoricalOrders("")
    72  }
    73  
    74  // Retrieves all past orders with the given symbol
    75  // See https://docs.bitfinex.com/reference#orders-history for more info
    76  func (s *OrderService) GetHistoryBySymbol(symbol string) (*order.Snapshot, error) {
    77  	// use no symbol, this will get all orders
    78  	return s.getHistoricalOrders(symbol)
    79  }
    80  
    81  // Retrieve a single order in history with the given id
    82  // See https://docs.bitfinex.com/reference#orders-history for more info
    83  func (s *OrderService) GetHistoryByOrderId(orderID int64) (o *order.Order, err error) {
    84  	os, err := s.AllHistory()
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	for _, order := range os.Snapshot {
    89  		if order.ID == orderID {
    90  			return order, nil
    91  		}
    92  	}
    93  	return nil, common.ErrNotFound
    94  }
    95  
    96  // Retrieves the trades generated by an order
    97  // See https://docs.bitfinex.com/reference#orders-history for more info
    98  func (s *OrderService) OrderTrades(symbol string, orderID int64) (*tradeexecutionupdate.Snapshot, error) {
    99  	key := fmt.Sprintf("%s:%d", symbol, orderID)
   100  	req, err := s.requestFactory.NewAuthenticatedRequest(common.PermissionRead, path.Join("order", key, "trades"))
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  	raw, err := s.Request(req)
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  	return tradeexecutionupdate.SnapshotFromRaw(raw)
   109  }
   110  
   111  func (s *OrderService) getActiveOrders(symbol string) (*order.Snapshot, error) {
   112  	req, err := s.requestFactory.NewAuthenticatedRequest(common.PermissionRead, path.Join("orders", symbol))
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  	raw, err := s.Request(req)
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  	os, err := order.SnapshotFromRaw(raw)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  	if os == nil {
   125  		return &order.Snapshot{}, nil
   126  	}
   127  	return os, nil
   128  }
   129  
   130  func (s *OrderService) getHistoricalOrders(symbol string) (*order.Snapshot, error) {
   131  	req, err := s.requestFactory.NewAuthenticatedRequest(common.PermissionRead, path.Join("orders", symbol, "hist"))
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  	raw, err := s.Request(req)
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  	os, err := order.SnapshotFromRaw(raw)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  	if os == nil {
   144  		return &order.Snapshot{}, nil
   145  	}
   146  	return os, nil
   147  }
   148  
   149  // Submit a request to create a new order
   150  // see https://docs.bitfinex.com/reference#submit-order for more info
   151  func (s *OrderService) SubmitOrder(onr *order.NewRequest) (*notification.Notification, error) {
   152  	bytes, err := onr.ToJSON()
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  	req, err := s.requestFactory.NewAuthenticatedRequestWithBytes(common.PermissionWrite, path.Join("order", "submit"), bytes)
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  	raw, err := s.Request(req)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  	return notification.FromRaw(raw)
   165  }
   166  
   167  // Submit a request to update an order with the given id with the given changes
   168  // see https://docs.bitfinex.com/reference#order-update for more info
   169  func (s *OrderService) SubmitUpdateOrder(our *order.UpdateRequest) (*notification.Notification, error) {
   170  	bytes, err := our.ToJSON()
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  	req, err := s.requestFactory.NewAuthenticatedRequestWithBytes(common.PermissionWrite, path.Join("order", "update"), bytes)
   175  	if err != nil {
   176  		return nil, err
   177  	}
   178  	raw, err := s.Request(req)
   179  	if err != nil {
   180  		return nil, err
   181  	}
   182  	return notification.FromRaw(raw)
   183  }
   184  
   185  // Submit a request to cancel an order with the given Id
   186  // see https://docs.bitfinex.com/reference#cancel-order for more info
   187  func (s *OrderService) SubmitCancelOrder(oc *order.CancelRequest) error {
   188  	bytes, err := oc.ToJSON()
   189  	if err != nil {
   190  		return err
   191  	}
   192  	req, err := s.requestFactory.NewAuthenticatedRequestWithBytes(common.PermissionWrite, path.Join("order", "cancel"), bytes)
   193  	if err != nil {
   194  		return err
   195  	}
   196  	_, err = s.Request(req)
   197  	if err != nil {
   198  		return err
   199  	}
   200  	return nil
   201  }
   202  
   203  // CancelOrderMulti cancels multiple orders simultaneously. Orders can be canceled based on the Order ID,
   204  // the combination of Client Order ID and Client Order Date, or the Group Order ID. Alternatively, the body
   205  // param 'all' can be used with a value of 1 to cancel all orders.
   206  // see https://docs.bitfinex.com/reference#rest-auth-order-cancel-multi for more info
   207  func (s *OrderService) CancelOrderMulti(args CancelOrderMultiRequest) (*notification.Notification, error) {
   208  	bytes, err := json.Marshal(args)
   209  	if err != nil {
   210  		return nil, err
   211  	}
   212  
   213  	req, err := s.requestFactory.NewAuthenticatedRequestWithBytes(
   214  		common.PermissionWrite,
   215  		path.Join("order", "cancel", "multi"),
   216  		bytes,
   217  	)
   218  	if err != nil {
   219  		return nil, err
   220  	}
   221  
   222  	raw, err := s.Request(req)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  
   227  	return notification.FromRaw(raw)
   228  }
   229  
   230  // CancelOrdersMultiOp cancels multiple orders simultaneously. Accepts a slice of order ID's to be canceled.
   231  // see https://docs.bitfinex.com/reference#rest-auth-order-multi for more info
   232  func (s *OrderService) CancelOrdersMultiOp(ids OrderIDs) (*notification.Notification, error) {
   233  	pld := OrderMultiOpsRequest{
   234  		Ops: OrderOps{
   235  			{
   236  				"oc_multi",
   237  				map[string][]int{"id": ids},
   238  			},
   239  		},
   240  	}
   241  
   242  	bytes, err := json.Marshal(pld)
   243  	if err != nil {
   244  		return nil, err
   245  	}
   246  
   247  	req, err := s.requestFactory.NewAuthenticatedRequestWithBytes(
   248  		common.PermissionWrite,
   249  		path.Join("order", "multi"),
   250  		bytes,
   251  	)
   252  	if err != nil {
   253  		return nil, err
   254  	}
   255  
   256  	raw, err := s.Request(req)
   257  	if err != nil {
   258  		return nil, err
   259  	}
   260  
   261  	return notification.FromRaw(raw)
   262  }
   263  
   264  // CancelOrderMultiOp cancels order. Accepts orderID to be canceled.
   265  // see https://docs.bitfinex.com/reference#rest-auth-order-multi for more info
   266  func (s *OrderService) CancelOrderMultiOp(orderID int) (*notification.Notification, error) {
   267  	pld := OrderMultiOpsRequest{
   268  		Ops: OrderOps{
   269  			{
   270  				"oc",
   271  				map[string]int{"id": orderID},
   272  			},
   273  		},
   274  	}
   275  
   276  	bytes, err := json.Marshal(pld)
   277  	if err != nil {
   278  		return nil, err
   279  	}
   280  
   281  	req, err := s.requestFactory.NewAuthenticatedRequestWithBytes(
   282  		common.PermissionWrite,
   283  		path.Join("order", "multi"),
   284  		bytes,
   285  	)
   286  	if err != nil {
   287  		return nil, err
   288  	}
   289  
   290  	raw, err := s.Request(req)
   291  	if err != nil {
   292  		return nil, err
   293  	}
   294  
   295  	return notification.FromRaw(raw)
   296  }
   297  
   298  // OrderNewMultiOp creates new order. Accepts instance of order.NewRequest
   299  // see https://docs.bitfinex.com/reference#rest-auth-order-multi for more info
   300  func (s *OrderService) OrderNewMultiOp(onr order.NewRequest) (*notification.Notification, error) {
   301  	pld := OrderMultiOpsRequest{
   302  		Ops: OrderOps{
   303  			{
   304  				"on",
   305  				onr.EnrichedPayload(),
   306  			},
   307  		},
   308  	}
   309  
   310  	bytes, err := json.Marshal(pld)
   311  	if err != nil {
   312  		return nil, err
   313  	}
   314  
   315  	req, err := s.requestFactory.NewAuthenticatedRequestWithBytes(
   316  		common.PermissionWrite,
   317  		path.Join("order", "multi"),
   318  		bytes,
   319  	)
   320  	if err != nil {
   321  		return nil, err
   322  	}
   323  
   324  	raw, err := s.Request(req)
   325  	if err != nil {
   326  		return nil, err
   327  	}
   328  
   329  	return notification.FromRaw(raw)
   330  }
   331  
   332  // OrderUpdateMultiOp updates order. Accepts instance of order.UpdateRequest
   333  // see https://docs.bitfinex.com/reference#rest-auth-order-multi for more info
   334  func (s *OrderService) OrderUpdateMultiOp(our order.UpdateRequest) (*notification.Notification, error) {
   335  	pld := OrderMultiOpsRequest{
   336  		Ops: OrderOps{
   337  			{
   338  				"ou",
   339  				our.EnrichedPayload(),
   340  			},
   341  		},
   342  	}
   343  
   344  	bytes, err := json.Marshal(pld)
   345  	if err != nil {
   346  		return nil, err
   347  	}
   348  
   349  	req, err := s.requestFactory.NewAuthenticatedRequestWithBytes(
   350  		common.PermissionWrite,
   351  		path.Join("order", "multi"),
   352  		bytes,
   353  	)
   354  	if err != nil {
   355  		return nil, err
   356  	}
   357  
   358  	raw, err := s.Request(req)
   359  	if err != nil {
   360  		return nil, err
   361  	}
   362  
   363  	return notification.FromRaw(raw)
   364  }
   365  
   366  // OrderMultiOp - send Multiple order-related operations. Please note the sent object has
   367  // only one property with a value of a slice of slices detailing each order operation.
   368  // see https://docs.bitfinex.com/reference#rest-auth-order-multi for more info
   369  func (s *OrderService) OrderMultiOp(ops OrderOps) (*notification.Notification, error) {
   370  	enrichedOrderOps := OrderOps{}
   371  
   372  	for _, v := range ops {
   373  		if v[0] == "on" {
   374  			o, ok := v[1].(order.NewRequest)
   375  			if !ok {
   376  				return nil, fmt.Errorf("Invalid type for `on` operation. Expected: order.NewRequest")
   377  			}
   378  			v[1] = o.EnrichedPayload()
   379  		}
   380  
   381  		if v[0] == "ou" {
   382  			o, ok := v[1].(order.UpdateRequest)
   383  			if !ok {
   384  				return nil, fmt.Errorf("Invalid type for `ou` operation. Expected: order.UpdateRequest")
   385  			}
   386  			v[1] = o.EnrichedPayload()
   387  		}
   388  
   389  		enrichedOrderOps = append(enrichedOrderOps, v)
   390  	}
   391  
   392  	pld := OrderMultiOpsRequest{Ops: enrichedOrderOps}
   393  	bytes, err := json.Marshal(pld)
   394  	if err != nil {
   395  		return nil, err
   396  	}
   397  
   398  	req, err := s.requestFactory.NewAuthenticatedRequestWithBytes(
   399  		common.PermissionWrite,
   400  		path.Join("order", "multi"),
   401  		bytes,
   402  	)
   403  	if err != nil {
   404  		return nil, err
   405  	}
   406  
   407  	raw, err := s.Request(req)
   408  	if err != nil {
   409  		return nil, err
   410  	}
   411  
   412  	return notification.FromRaw(raw)
   413  }