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 }