diff --git a/pkg/exchange/max/convert.go b/pkg/exchange/max/convert.go index 08903f1c4..07b5537ce 100644 --- a/pkg/exchange/max/convert.go +++ b/pkg/exchange/max/convert.go @@ -5,8 +5,6 @@ import ( "strings" "time" - "github.com/pkg/errors" - "github.com/c9s/bbgo/pkg/exchange/max/maxapi" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/types" @@ -168,15 +166,8 @@ func toGlobalOrders(maxOrders []max.Order) (orders []types.Order, err error) { } func toGlobalOrder(maxOrder max.Order) (*types.Order, error) { - executedVolume, err := fixedpoint.NewFromString(maxOrder.ExecutedVolume) - if err != nil { - return nil, errors.Wrapf(err, "parse executed_volume failed: %+v", maxOrder) - } - - remainingVolume, err := fixedpoint.NewFromString(maxOrder.RemainingVolume) - if err != nil { - return nil, errors.Wrapf(err, "parse remaining volume failed: %+v", maxOrder) - } + executedVolume := maxOrder.ExecutedVolume + remainingVolume := maxOrder.RemainingVolume return &types.Order{ SubmitOrder: types.SubmitOrder{ @@ -184,13 +175,13 @@ func toGlobalOrder(maxOrder max.Order) (*types.Order, error) { Symbol: toGlobalSymbol(maxOrder.Market), Side: toGlobalSideType(maxOrder.Side), Type: toGlobalOrderType(maxOrder.OrderType), - Quantity: fixedpoint.MustNewFromString(maxOrder.Volume), - Price: fixedpoint.MustNewFromString(maxOrder.Price), - TimeInForce: "GTC", // MAX only supports GTC + Quantity: maxOrder.Volume, + Price: maxOrder.Price, + TimeInForce: types.TimeInForceGTC, // MAX only supports GTC GroupID: maxOrder.GroupID, }, Exchange: types.ExchangeMax, - IsWorking: maxOrder.State == "wait", + IsWorking: maxOrder.State == max.OrderStateWait, OrderID: maxOrder.ID, Status: toGlobalOrderStatus(maxOrder.State, executedVolume, remainingVolume), ExecutedQuantity: executedVolume, diff --git a/pkg/exchange/max/exchange.go b/pkg/exchange/max/exchange.go index 2a400a762..288db5807 100644 --- a/pkg/exchange/max/exchange.go +++ b/pkg/exchange/max/exchange.go @@ -15,9 +15,9 @@ import ( "golang.org/x/time/rate" maxapi "github.com/c9s/bbgo/pkg/exchange/max/maxapi" + v3 "github.com/c9s/bbgo/pkg/exchange/max/maxapi/v3" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/types" - "github.com/c9s/bbgo/pkg/util" ) // closedOrderQueryLimiter is used for the closed orders query rate limit, 1 request per second @@ -31,8 +31,10 @@ var log = logrus.WithField("exchange", "max") type Exchange struct { types.MarginSettings - client *maxapi.RestClient key, secret string + client *maxapi.RestClient + + v3order *v3.OrderService } func New(key, secret string) *Exchange { @@ -44,9 +46,10 @@ func New(key, secret string) *Exchange { client := maxapi.NewRestClient(baseURL) client.Auth(key, secret) return &Exchange{ - client: client, - key: key, - secret: secret, + client: client, + key: key, + secret: secret, + v3order: &v3.OrderService{Client: client}, } } @@ -168,7 +171,7 @@ func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.O return nil, err } - maxOrder, err := e.client.OrderService.NewGetOrderRequest().Id(uint64(orderID)).Do(ctx) + maxOrder, err := e.v3order.NewGetOrderRequest().Id(uint64(orderID)).Do(ctx) if err != nil { return nil, err } @@ -177,7 +180,13 @@ func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.O } func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error) { - maxOrders, err := e.client.OrderService.Open(toLocalSymbol(symbol), maxapi.QueryOrderOptions{}) + market := toLocalSymbol(symbol) + walletType := maxapi.WalletTypeSpot + if e.MarginSettings.IsMargin { + walletType = maxapi.WalletTypeMargin + } + + maxOrders, err := e.v3order.NewWalletGetOpenOrdersRequest(walletType).Market(market).Do(ctx) if err != nil { return orders, err } @@ -198,14 +207,7 @@ func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders [ func (e *Exchange) QueryClosedOrders(ctx context.Context, symbol string, since, until time.Time, lastOrderID uint64) ([]types.Order, error) { log.Warn("!!!MAX EXCHANGE API NOTICE!!!") log.Warn("the since/until conditions will not be effected on closed orders query, max exchange does not support time-range-based query") - - if v, ok := util.GetEnvVarBool("MAX_QUERY_CLOSED_ORDERS_ALL"); v && ok { - log.Warn("MAX_QUERY_CLOSED_ORDERS_ALL is set, we will fetch all closed orders from the first order") - return e.queryClosedOrdersByLastOrderID(ctx, symbol, 1) - } - return e.queryClosedOrdersByLastOrderID(ctx, symbol, lastOrderID) - // return e.queryRecentlyClosedOrders(ctx, symbol, since, until) } func (e *Exchange) queryClosedOrdersByLastOrderID(ctx context.Context, symbol string, lastOrderID uint64) (orders []types.Order, err error) { @@ -213,13 +215,19 @@ func (e *Exchange) queryClosedOrdersByLastOrderID(ctx context.Context, symbol st return orders, err } - req := e.client.OrderService.NewGetOrderHistoryRequest() - req.Market(toLocalSymbol(symbol)) + market := toLocalSymbol(symbol) + walletType := maxapi.WalletTypeSpot + if e.MarginSettings.IsMargin { + walletType = maxapi.WalletTypeMargin + } + + req := e.v3order.NewWalletGetOrderHistoryRequest(walletType).Market(market) if lastOrderID == 0 { lastOrderID = 1 } req.FromID(lastOrderID) + maxOrders, err := req.Do(ctx) if err != nil { return orders, err @@ -232,92 +240,20 @@ func (e *Exchange) queryClosedOrdersByLastOrderID(ctx context.Context, symbol st continue } - log.Debugf("max order %d %s %v %s %s", order.OrderID, order.Symbol, order.Price, order.Status, order.CreationTime.Time().Format(time.StampMilli)) orders = append(orders, *order) } - // always sort the orders by creation time - sort.Slice(orders, func(i, j int) bool { - return orders[i].CreationTime.Before(orders[j].CreationTime.Time()) - }) - + orders = types.SortOrderAscending(orders) return orders, nil } -// queryRecentlyClosedOrders is deprecated -func (e *Exchange) queryRecentlyClosedOrders(ctx context.Context, symbol string, since time.Time, until time.Time) (orders []types.Order, err error) { - limit := 1000 // max limit = 1000, default 100 - orderIDs := make(map[uint64]struct{}, limit*2) - maxPages := 10 - - if v, ok := util.GetEnvVarInt("MAX_QUERY_CLOSED_ORDERS_LIMIT"); ok { - limit = v - } - - if v, ok := util.GetEnvVarInt("MAX_QUERY_CLOSED_ORDERS_NUM_OF_PAGES"); ok { - maxPages = v - } - - log.Warnf("fetching recently closed orders, maximum %d pages to fetch", maxPages) - log.Warnf("note that, some MAX orders might be missing if you did not sync the closed orders for a while") - -queryRecentlyClosedOrders: - for page := 1; page < maxPages; page++ { - if err := closedOrderQueryLimiter.Wait(ctx); err != nil { - return orders, err - } - - log.Infof("querying %s closed orders from page %d ~ ", symbol, page) - maxOrders, err2 := e.client.OrderService.Closed(toLocalSymbol(symbol), maxapi.QueryOrderOptions{ - Limit: limit, - Page: page, - OrderBy: "desc", - }) - if err2 != nil { - err = multierr.Append(err, err2) - break queryRecentlyClosedOrders - } - - // no recent orders - if len(maxOrders) == 0 { - break queryRecentlyClosedOrders - } - - log.Debugf("fetched %d orders", len(maxOrders)) - for _, maxOrder := range maxOrders { - if maxOrder.CreatedAtMs.Time().Before(since) { - log.Debugf("skip orders with creation time before %s, found %s", since, maxOrder.CreatedAtMs.Time()) - break queryRecentlyClosedOrders - } - - if maxOrder.CreatedAtMs.Time().After(until) { - log.Debugf("skip orders with creation time after %s, found %s", until, maxOrder.CreatedAtMs.Time()) - continue - } - - order, err2 := toGlobalOrder(maxOrder) - if err2 != nil { - err = multierr.Append(err, err2) - continue - } - - if _, ok := orderIDs[order.OrderID]; ok { - log.Debugf("skipping duplicated order: %d", order.OrderID) - } - - log.Debugf("max order %d %s %v %s %s", order.OrderID, order.Symbol, order.Price, order.Status, order.CreationTime.Time().Format(time.StampMilli)) - - orderIDs[order.OrderID] = struct{}{} - orders = append(orders, *order) - } - } - - // ensure everything is ascending ordered - return types.SortOrderAscending(orders), err -} - func (e *Exchange) CancelAllOrders(ctx context.Context) ([]types.Order, error) { - var req = e.client.OrderService.NewOrderCancelAllRequest() + walletType := maxapi.WalletTypeSpot + if e.MarginSettings.IsMargin { + walletType = maxapi.WalletTypeMargin + } + + req := e.v3order.NewWalletOrderCancelAllRequest(walletType) var maxOrders, err = req.Do(ctx) if err != nil { return nil, err @@ -327,10 +263,16 @@ func (e *Exchange) CancelAllOrders(ctx context.Context) ([]types.Order, error) { } func (e *Exchange) CancelOrdersBySymbol(ctx context.Context, symbol string) ([]types.Order, error) { - var req = e.client.OrderService.NewOrderCancelAllRequest() - req.Market(toLocalSymbol(symbol)) + market := toLocalSymbol(symbol) + walletType := maxapi.WalletTypeSpot + if e.MarginSettings.IsMargin { + walletType = maxapi.WalletTypeMargin + } - var maxOrders, err = req.Do(ctx) + req := e.v3order.NewWalletOrderCancelAllRequest(walletType) + req.Market(market) + + maxOrders, err := req.Do(ctx) if err != nil { return nil, err } @@ -339,10 +281,15 @@ func (e *Exchange) CancelOrdersBySymbol(ctx context.Context, symbol string) ([]t } func (e *Exchange) CancelOrdersByGroupID(ctx context.Context, groupID uint32) ([]types.Order, error) { - var req = e.client.OrderService.NewOrderCancelAllRequest() + walletType := maxapi.WalletTypeSpot + if e.MarginSettings.IsMargin { + walletType = maxapi.WalletTypeMargin + } + + req := e.v3order.NewWalletOrderCancelAllRequest(walletType) req.GroupID(groupID) - var maxOrders, err = req.Do(ctx) + maxOrders, err := req.Do(ctx) if err != nil { return nil, err } @@ -351,6 +298,11 @@ func (e *Exchange) CancelOrdersByGroupID(ctx context.Context, groupID uint32) ([ } func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) (err2 error) { + walletType := maxapi.WalletTypeSpot + if e.MarginSettings.IsMargin { + walletType = maxapi.WalletTypeMargin + } + var groupIDs = make(map[uint32]struct{}) var orphanOrders []types.Order for _, o := range orders { @@ -363,7 +315,7 @@ func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) (err if len(groupIDs) > 0 { for groupID := range groupIDs { - var req = e.client.OrderService.NewOrderCancelAllRequest() + req := e.v3order.NewWalletOrderCancelAllRequest(walletType) req.GroupID(groupID) if _, err := req.Do(ctx); err != nil { @@ -374,7 +326,7 @@ func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) (err } for _, o := range orphanOrders { - var req = e.client.OrderService.NewOrderCancelRequest() + req := e.v3order.NewOrderCancelRequest() if o.OrderID > 0 { req.Id(o.OrderID) } else if len(o.ClientOrderID) > 0 && o.ClientOrderID != types.NoClientOrderID { @@ -392,7 +344,7 @@ func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) (err return err2 } -func toMaxSubmitOrder(o types.SubmitOrder) (*maxapi.Order, error) { +func toMaxSubmitOrder(o types.SubmitOrder) (*maxapi.SubmitOrder, error) { symbol := toLocalSymbol(o.Symbol) orderType, err := toLocalOrderType(o.Type) if err != nil { @@ -411,12 +363,11 @@ func toMaxSubmitOrder(o types.SubmitOrder) (*maxapi.Order, error) { quantityString = o.Quantity.String() } - maxOrder := maxapi.Order{ + maxOrder := maxapi.SubmitOrder{ Market: symbol, Side: toLocalSideType(o.Side), OrderType: orderType, - // Price: priceInString, - Volume: quantityString, + Volume: quantityString, } if o.GroupID > 0 { @@ -497,7 +448,7 @@ func (e *Exchange) Withdrawal(ctx context.Context, asset string, amount fixedpoi func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (createdOrders types.OrderSlice, err error) { if len(orders) > 1 && len(orders) < 15 { - var ordersBySymbol = map[string][]maxapi.Order{} + var ordersBySymbol = map[string][]maxapi.SubmitOrder{} for _, o := range orders { maxOrder, err := toMaxSubmitOrder(o) if err != nil { diff --git a/pkg/exchange/max/maxapi/order.go b/pkg/exchange/max/maxapi/order.go index b37a41ca3..52d6eb095 100644 --- a/pkg/exchange/max/maxapi/order.go +++ b/pkg/exchange/max/maxapi/order.go @@ -11,6 +11,7 @@ import ( "github.com/c9s/requestgen" "github.com/pkg/errors" + "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/types" ) @@ -37,6 +38,13 @@ func init() { relUrlV2OrdersMultiOneByOne = mustParseURL("v2/orders/multi/onebyone") } +type WalletType string + +const ( + WalletTypeSpot WalletType = "spot" + WalletTypeMargin WalletType = "m" +) + type OrderStateToQuery int const ( @@ -82,25 +90,37 @@ type OrderService struct { client *RestClient } +type SubmitOrder struct { + Side string `json:"side"` + Market string `json:"market"` + Price string `json:"price"` + StopPrice string `json:"stop_price,omitempty"` + OrderType OrderType `json:"ord_type"` + Volume string `json:"volume"` + GroupID uint32 `json:"group_id,omitempty"` + ClientOID string `json:"client_oid,omitempty"` +} + // Order represents one returned order (POST order/GET order/GET orders) on the max platform. type Order struct { ID uint64 `json:"id,omitempty"` + WalletType string `json:"wallet_type,omitempty"` Side string `json:"side"` OrderType OrderType `json:"ord_type"` - Price string `json:"price,omitempty"` - StopPrice string `json:"stop_price,omitempty"` - AveragePrice string `json:"avg_price,omitempty"` + Price fixedpoint.Value `json:"price,omitempty"` + StopPrice fixedpoint.Value `json:"stop_price,omitempty"` + AveragePrice fixedpoint.Value `json:"avg_price,omitempty"` State OrderState `json:"state,omitempty"` Market string `json:"market,omitempty"` - Volume string `json:"volume"` - RemainingVolume string `json:"remaining_volume,omitempty"` - ExecutedVolume string `json:"executed_volume,omitempty"` + Volume fixedpoint.Value `json:"volume"` + RemainingVolume fixedpoint.Value `json:"remaining_volume,omitempty"` + ExecutedVolume fixedpoint.Value `json:"executed_volume,omitempty"` TradesCount int64 `json:"trades_count,omitempty"` GroupID uint32 `json:"group_id,omitempty"` ClientOID string `json:"client_oid,omitempty"` - CreatedAt time.Time `json:"-" db:"created_at"` + CreatedAt time.Time `json:"-"` CreatedAtMs types.MillisecondTimestamp `json:"created_at_in_ms,omitempty"` - InsertedAt time.Time `json:"-" db:"inserted_at"` + InsertedAt time.Time `json:"-"` } // Open returns open orders @@ -210,7 +230,7 @@ func (s *OrderService) All(market string, limit, page int, states ...OrderState) type Options map[string]interface{} // Create multiple order in a single request -func (s *OrderService) CreateMulti(market string, orders []Order) (*MultiOrderResponse, error) { +func (s *OrderService) CreateMulti(market string, orders []SubmitOrder) (*MultiOrderResponse, error) { req := s.NewCreateMultiOrderRequest() req.Market(market) req.AddOrders(orders...) @@ -271,7 +291,7 @@ type CreateMultiOrderRequest struct { market *string groupID *uint32 - orders []Order + orders []SubmitOrder } func (r *CreateMultiOrderRequest) GroupID(groupID uint32) *CreateMultiOrderRequest { @@ -284,7 +304,7 @@ func (r *CreateMultiOrderRequest) Market(market string) *CreateMultiOrderRequest return r } -func (r *CreateMultiOrderRequest) AddOrders(orders ...Order) *CreateMultiOrderRequest { +func (r *CreateMultiOrderRequest) AddOrders(orders ...SubmitOrder) *CreateMultiOrderRequest { r.orders = append(r.orders, orders...) return r } diff --git a/pkg/exchange/max/maxapi/restapi.go b/pkg/exchange/max/maxapi/restapi.go index 17fde6f6c..cd3f1743a 100644 --- a/pkg/exchange/max/maxapi/restapi.go +++ b/pkg/exchange/max/maxapi/restapi.go @@ -21,7 +21,6 @@ import ( "github.com/pkg/errors" log "github.com/sirupsen/logrus" - v3 "github.com/c9s/bbgo/pkg/exchange/max/maxapi/v3" "github.com/c9s/bbgo/pkg/util" "github.com/c9s/bbgo/pkg/version" ) @@ -102,8 +101,6 @@ type RestClient struct { OrderService *OrderService RewardService *RewardService WithdrawalService *WithdrawalService - - OrderServiceV3 *v3.OrderService } func NewRestClient(baseURL string) *RestClient { @@ -126,8 +123,6 @@ func NewRestClient(baseURL string) *RestClient { client.RewardService = &RewardService{client} client.WithdrawalService = &WithdrawalService{client} - client.OrderServiceV3 = &v3.OrderService{Client: client} - // defaultHttpClient.MaxTokenService = &MaxTokenService{defaultHttpClient} client.initNonce() return client diff --git a/pkg/exchange/max/maxapi/v3/order.go b/pkg/exchange/max/maxapi/v3/order.go index edf4cd783..ed70e7eb6 100644 --- a/pkg/exchange/max/maxapi/v3/order.go +++ b/pkg/exchange/max/maxapi/v3/order.go @@ -10,12 +10,7 @@ import ( maxapi "github.com/c9s/bbgo/pkg/exchange/max/maxapi" ) -type WalletType string - -const ( - WalletTypeSpot WalletType = "spot" - WalletTypeMargin WalletType = "m" -) +type WalletType = maxapi.WalletType type Order = maxapi.Order @@ -28,8 +23,12 @@ func (s *OrderService) NewWalletCreateOrderRequest(walletType WalletType) *Walle return &WalletCreateOrderRequest{client: s.Client, walletType: walletType} } -func (s *OrderService) NewWalletGetOrderRequest(walletType WalletType) *WalletGetOrderRequest { - return &WalletGetOrderRequest{client: s.Client, walletType: walletType} +func (s *OrderService) NewWalletGetOrderHistoryRequest(walletType WalletType) *WalletGetOrderHistoryRequest { + return &WalletGetOrderHistoryRequest{client: s.Client, walletType: walletType} +} + +func (s *OrderService) NewWalletGetOpenOrdersRequest(walletType WalletType) *WalletGetOpenOrdersRequest { + return &WalletGetOpenOrdersRequest{client: s.Client, walletType: walletType} } func (s *OrderService) NewWalletOrderCancelAllRequest(walletType WalletType) *WalletOrderCancelAllRequest { @@ -60,20 +59,23 @@ type WalletCreateOrderRequest struct { groupID *string `param:"group_id"` } -//go:generate GetRequest -url "/api/v3/wallet/:walletType/orders" -type WalletGetOrderRequest -responseType .Order -type WalletGetOrderRequest struct { +//go:generate GetRequest -url "/api/v3/wallet/:walletType/orders/history" -type WalletGetOrderHistoryRequest -responseType []Order +type WalletGetOrderHistoryRequest struct { + client requestgen.AuthenticatedAPIClient + + walletType WalletType `param:"walletType,slug,required"` + + market string `param:"market,required"` + fromID *uint64 `param:"from_id"` + limit *uint `param:"limit"` +} + +//go:generate GetRequest -url "/api/v3/wallet/:walletType/orders/open" -type WalletGetOpenOrdersRequest -responseType []Order +type WalletGetOpenOrdersRequest struct { client requestgen.AuthenticatedAPIClient walletType WalletType `param:"walletType,slug,required"` market string `param:"market,required"` - side string `param:"side,required"` - volume string `param:"volume,required"` - orderType string `param:"ord_type"` - - price *string `param:"price"` - stopPrice *string `param:"stop_price"` - clientOrderID *string `param:"client_oid"` - groupID *string `param:"group_id"` } //go:generate DeleteRequest -url "/api/v3/wallet/:walletType/orders" -type WalletOrderCancelAllRequest -responseType []Order diff --git a/pkg/exchange/max/maxapi/v3/wallet_create_order_request_requestgen.go b/pkg/exchange/max/maxapi/v3/wallet_create_order_request_requestgen.go index 477c8ea9e..c50ac2067 100644 --- a/pkg/exchange/max/maxapi/v3/wallet_create_order_request_requestgen.go +++ b/pkg/exchange/max/maxapi/v3/wallet_create_order_request_requestgen.go @@ -52,7 +52,7 @@ func (w *WalletCreateOrderRequest) GroupID(groupID string) *WalletCreateOrderReq return w } -func (w *WalletCreateOrderRequest) WalletType(walletType WalletType) *WalletCreateOrderRequest { +func (w *WalletCreateOrderRequest) WalletType(walletType max.WalletType) *WalletCreateOrderRequest { w.walletType = walletType return w } @@ -190,17 +190,6 @@ func (w *WalletCreateOrderRequest) GetSlugParameters() (map[string]interface{}, } // END TEMPLATE check-required - // TEMPLATE check-valid-values - switch walletType { - case WalletTypeSpot, WalletTypeMargin: - params["walletType"] = walletType - - default: - return nil, fmt.Errorf("walletType value %v is invalid", walletType) - - } - // END TEMPLATE check-valid-values - // assign parameter of walletType params["walletType"] = walletType diff --git a/pkg/exchange/max/maxapi/v3/wallet_get_open_orders_request_requestgen.go b/pkg/exchange/max/maxapi/v3/wallet_get_open_orders_request_requestgen.go new file mode 100644 index 000000000..a01b91221 --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/wallet_get_open_orders_request_requestgen.go @@ -0,0 +1,177 @@ +// Code generated by "requestgen -method GET -url /api/v3/wallet/:walletType/orders/open -type WalletGetOpenOrdersRequest -responseType []Order"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "github.com/c9s/bbgo/pkg/exchange/max/maxapi" + "net/url" + "reflect" + "regexp" +) + +func (w *WalletGetOpenOrdersRequest) Market(market string) *WalletGetOpenOrdersRequest { + w.market = market + return w +} + +func (w *WalletGetOpenOrdersRequest) WalletType(walletType max.WalletType) *WalletGetOpenOrdersRequest { + w.walletType = walletType + return w +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (w *WalletGetOpenOrdersRequest) GetQueryParameters() (url.Values, error) { + var params = map[string]interface{}{} + + query := url.Values{} + for _k, _v := range params { + query.Add(_k, fmt.Sprintf("%v", _v)) + } + + return query, nil +} + +// GetParameters builds and checks the parameters and return the result in a map object +func (w *WalletGetOpenOrdersRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check market field -> json key market + market := w.market + + // TEMPLATE check-required + if len(market) == 0 { + return nil, fmt.Errorf("market is required, empty string given") + } + // END TEMPLATE check-required + + // assign parameter of market + params["market"] = market + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (w *WalletGetOpenOrdersRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := w.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if w.isVarSlice(_v) { + w.iterateSlice(_v, func(it interface{}) { + query.Add(_k+"[]", fmt.Sprintf("%v", it)) + }) + } else { + query.Add(_k, fmt.Sprintf("%v", _v)) + } + } + + return query, nil +} + +// GetParametersJSON converts the parameters from GetParameters into the JSON format +func (w *WalletGetOpenOrdersRequest) GetParametersJSON() ([]byte, error) { + params, err := w.GetParameters() + if err != nil { + return nil, err + } + + return json.Marshal(params) +} + +// GetSlugParameters builds and checks the slug parameters and return the result in a map object +func (w *WalletGetOpenOrdersRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check walletType field -> json key walletType + walletType := w.walletType + + // TEMPLATE check-required + if len(walletType) == 0 { + return nil, fmt.Errorf("walletType is required, empty string given") + } + // END TEMPLATE check-required + + // assign parameter of walletType + params["walletType"] = walletType + + return params, nil +} + +func (w *WalletGetOpenOrdersRequest) applySlugsToUrl(url string, slugs map[string]string) string { + for _k, _v := range slugs { + needleRE := regexp.MustCompile(":" + _k + "\\b") + url = needleRE.ReplaceAllString(url, _v) + } + + return url +} + +func (w *WalletGetOpenOrdersRequest) iterateSlice(slice interface{}, _f func(it interface{})) { + sliceValue := reflect.ValueOf(slice) + for _i := 0; _i < sliceValue.Len(); _i++ { + it := sliceValue.Index(_i).Interface() + _f(it) + } +} + +func (w *WalletGetOpenOrdersRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (w *WalletGetOpenOrdersRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := w.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (w *WalletGetOpenOrdersRequest) Do(ctx context.Context) ([]max.Order, error) { + + // empty params for GET operation + var params interface{} + query, err := w.GetParametersQuery() + if err != nil { + return nil, err + } + + apiURL := "/api/v3/wallet/:walletType/orders/open" + slugs, err := w.GetSlugsMap() + if err != nil { + return nil, err + } + + apiURL = w.applySlugsToUrl(apiURL, slugs) + + req, err := w.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := w.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse []max.Order + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return apiResponse, nil +} diff --git a/pkg/exchange/max/maxapi/v3/wallet_get_order_history_request_requestgen.go b/pkg/exchange/max/maxapi/v3/wallet_get_order_history_request_requestgen.go new file mode 100644 index 000000000..8a137de41 --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/wallet_get_order_history_request_requestgen.go @@ -0,0 +1,203 @@ +// Code generated by "requestgen -method GET -url /api/v3/wallet/:walletType/orders/history -type WalletGetOrderHistoryRequest -responseType []Order"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "github.com/c9s/bbgo/pkg/exchange/max/maxapi" + "net/url" + "reflect" + "regexp" +) + +func (w *WalletGetOrderHistoryRequest) Market(market string) *WalletGetOrderHistoryRequest { + w.market = market + return w +} + +func (w *WalletGetOrderHistoryRequest) FromID(fromID uint64) *WalletGetOrderHistoryRequest { + w.fromID = &fromID + return w +} + +func (w *WalletGetOrderHistoryRequest) Limit(limit uint) *WalletGetOrderHistoryRequest { + w.limit = &limit + return w +} + +func (w *WalletGetOrderHistoryRequest) WalletType(walletType max.WalletType) *WalletGetOrderHistoryRequest { + w.walletType = walletType + return w +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (w *WalletGetOrderHistoryRequest) GetQueryParameters() (url.Values, error) { + var params = map[string]interface{}{} + + query := url.Values{} + for _k, _v := range params { + query.Add(_k, fmt.Sprintf("%v", _v)) + } + + return query, nil +} + +// GetParameters builds and checks the parameters and return the result in a map object +func (w *WalletGetOrderHistoryRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check market field -> json key market + market := w.market + + // TEMPLATE check-required + if len(market) == 0 { + return nil, fmt.Errorf("market is required, empty string given") + } + // END TEMPLATE check-required + + // assign parameter of market + params["market"] = market + // check fromID field -> json key from_id + if w.fromID != nil { + fromID := *w.fromID + + // assign parameter of fromID + params["from_id"] = fromID + } else { + } + // check limit field -> json key limit + if w.limit != nil { + limit := *w.limit + + // assign parameter of limit + params["limit"] = limit + } else { + } + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (w *WalletGetOrderHistoryRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := w.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if w.isVarSlice(_v) { + w.iterateSlice(_v, func(it interface{}) { + query.Add(_k+"[]", fmt.Sprintf("%v", it)) + }) + } else { + query.Add(_k, fmt.Sprintf("%v", _v)) + } + } + + return query, nil +} + +// GetParametersJSON converts the parameters from GetParameters into the JSON format +func (w *WalletGetOrderHistoryRequest) GetParametersJSON() ([]byte, error) { + params, err := w.GetParameters() + if err != nil { + return nil, err + } + + return json.Marshal(params) +} + +// GetSlugParameters builds and checks the slug parameters and return the result in a map object +func (w *WalletGetOrderHistoryRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check walletType field -> json key walletType + walletType := w.walletType + + // TEMPLATE check-required + if len(walletType) == 0 { + return nil, fmt.Errorf("walletType is required, empty string given") + } + // END TEMPLATE check-required + + // assign parameter of walletType + params["walletType"] = walletType + + return params, nil +} + +func (w *WalletGetOrderHistoryRequest) applySlugsToUrl(url string, slugs map[string]string) string { + for _k, _v := range slugs { + needleRE := regexp.MustCompile(":" + _k + "\\b") + url = needleRE.ReplaceAllString(url, _v) + } + + return url +} + +func (w *WalletGetOrderHistoryRequest) iterateSlice(slice interface{}, _f func(it interface{})) { + sliceValue := reflect.ValueOf(slice) + for _i := 0; _i < sliceValue.Len(); _i++ { + it := sliceValue.Index(_i).Interface() + _f(it) + } +} + +func (w *WalletGetOrderHistoryRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (w *WalletGetOrderHistoryRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := w.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (w *WalletGetOrderHistoryRequest) Do(ctx context.Context) ([]max.Order, error) { + + // empty params for GET operation + var params interface{} + query, err := w.GetParametersQuery() + if err != nil { + return nil, err + } + + apiURL := "/api/v3/wallet/:walletType/orders/history" + slugs, err := w.GetSlugsMap() + if err != nil { + return nil, err + } + + apiURL = w.applySlugsToUrl(apiURL, slugs) + + req, err := w.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := w.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse []max.Order + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return apiResponse, nil +} diff --git a/pkg/exchange/max/maxapi/v3/wallet_get_order_request_requestgen.go b/pkg/exchange/max/maxapi/v3/wallet_get_order_request_requestgen.go deleted file mode 100644 index 181dae703..000000000 --- a/pkg/exchange/max/maxapi/v3/wallet_get_order_request_requestgen.go +++ /dev/null @@ -1,282 +0,0 @@ -// Code generated by "requestgen -method GET -url /api/v3/wallet/:walletType/orders -type WalletGetOrderRequest -responseType .Order"; DO NOT EDIT. - -package v3 - -import ( - "context" - "encoding/json" - "fmt" - "github.com/c9s/bbgo/pkg/exchange/max/maxapi" - "net/url" - "reflect" - "regexp" -) - -func (w *WalletGetOrderRequest) Market(market string) *WalletGetOrderRequest { - w.market = market - return w -} - -func (w *WalletGetOrderRequest) Side(side string) *WalletGetOrderRequest { - w.side = side - return w -} - -func (w *WalletGetOrderRequest) Volume(volume string) *WalletGetOrderRequest { - w.volume = volume - return w -} - -func (w *WalletGetOrderRequest) OrderType(orderType string) *WalletGetOrderRequest { - w.orderType = orderType - return w -} - -func (w *WalletGetOrderRequest) Price(price string) *WalletGetOrderRequest { - w.price = &price - return w -} - -func (w *WalletGetOrderRequest) StopPrice(stopPrice string) *WalletGetOrderRequest { - w.stopPrice = &stopPrice - return w -} - -func (w *WalletGetOrderRequest) ClientOrderID(clientOrderID string) *WalletGetOrderRequest { - w.clientOrderID = &clientOrderID - return w -} - -func (w *WalletGetOrderRequest) GroupID(groupID string) *WalletGetOrderRequest { - w.groupID = &groupID - return w -} - -func (w *WalletGetOrderRequest) WalletType(walletType WalletType) *WalletGetOrderRequest { - w.walletType = walletType - return w -} - -// GetQueryParameters builds and checks the query parameters and returns url.Values -func (w *WalletGetOrderRequest) GetQueryParameters() (url.Values, error) { - var params = map[string]interface{}{} - - query := url.Values{} - for _k, _v := range params { - query.Add(_k, fmt.Sprintf("%v", _v)) - } - - return query, nil -} - -// GetParameters builds and checks the parameters and return the result in a map object -func (w *WalletGetOrderRequest) GetParameters() (map[string]interface{}, error) { - var params = map[string]interface{}{} - // check market field -> json key market - market := w.market - - // TEMPLATE check-required - if len(market) == 0 { - return nil, fmt.Errorf("market is required, empty string given") - } - // END TEMPLATE check-required - - // assign parameter of market - params["market"] = market - // check side field -> json key side - side := w.side - - // TEMPLATE check-required - if len(side) == 0 { - return nil, fmt.Errorf("side is required, empty string given") - } - // END TEMPLATE check-required - - // assign parameter of side - params["side"] = side - // check volume field -> json key volume - volume := w.volume - - // TEMPLATE check-required - if len(volume) == 0 { - return nil, fmt.Errorf("volume is required, empty string given") - } - // END TEMPLATE check-required - - // assign parameter of volume - params["volume"] = volume - // check orderType field -> json key ord_type - orderType := w.orderType - - // assign parameter of orderType - params["ord_type"] = orderType - // check price field -> json key price - if w.price != nil { - price := *w.price - - // assign parameter of price - params["price"] = price - } else { - } - // check stopPrice field -> json key stop_price - if w.stopPrice != nil { - stopPrice := *w.stopPrice - - // assign parameter of stopPrice - params["stop_price"] = stopPrice - } else { - } - // check clientOrderID field -> json key client_oid - if w.clientOrderID != nil { - clientOrderID := *w.clientOrderID - - // assign parameter of clientOrderID - params["client_oid"] = clientOrderID - } else { - } - // check groupID field -> json key group_id - if w.groupID != nil { - groupID := *w.groupID - - // assign parameter of groupID - params["group_id"] = groupID - } else { - } - - return params, nil -} - -// GetParametersQuery converts the parameters from GetParameters into the url.Values format -func (w *WalletGetOrderRequest) GetParametersQuery() (url.Values, error) { - query := url.Values{} - - params, err := w.GetParameters() - if err != nil { - return query, err - } - - for _k, _v := range params { - if w.isVarSlice(_v) { - w.iterateSlice(_v, func(it interface{}) { - query.Add(_k+"[]", fmt.Sprintf("%v", it)) - }) - } else { - query.Add(_k, fmt.Sprintf("%v", _v)) - } - } - - return query, nil -} - -// GetParametersJSON converts the parameters from GetParameters into the JSON format -func (w *WalletGetOrderRequest) GetParametersJSON() ([]byte, error) { - params, err := w.GetParameters() - if err != nil { - return nil, err - } - - return json.Marshal(params) -} - -// GetSlugParameters builds and checks the slug parameters and return the result in a map object -func (w *WalletGetOrderRequest) GetSlugParameters() (map[string]interface{}, error) { - var params = map[string]interface{}{} - // check walletType field -> json key walletType - walletType := w.walletType - - // TEMPLATE check-required - if len(walletType) == 0 { - return nil, fmt.Errorf("walletType is required, empty string given") - } - // END TEMPLATE check-required - - // TEMPLATE check-valid-values - switch walletType { - case WalletTypeSpot, WalletTypeMargin: - params["walletType"] = walletType - - default: - return nil, fmt.Errorf("walletType value %v is invalid", walletType) - - } - // END TEMPLATE check-valid-values - - // assign parameter of walletType - params["walletType"] = walletType - - return params, nil -} - -func (w *WalletGetOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string { - for _k, _v := range slugs { - needleRE := regexp.MustCompile(":" + _k + "\\b") - url = needleRE.ReplaceAllString(url, _v) - } - - return url -} - -func (w *WalletGetOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) { - sliceValue := reflect.ValueOf(slice) - for _i := 0; _i < sliceValue.Len(); _i++ { - it := sliceValue.Index(_i).Interface() - _f(it) - } -} - -func (w *WalletGetOrderRequest) isVarSlice(_v interface{}) bool { - rt := reflect.TypeOf(_v) - switch rt.Kind() { - case reflect.Slice: - return true - } - return false -} - -func (w *WalletGetOrderRequest) GetSlugsMap() (map[string]string, error) { - slugs := map[string]string{} - params, err := w.GetSlugParameters() - if err != nil { - return slugs, nil - } - - for _k, _v := range params { - slugs[_k] = fmt.Sprintf("%v", _v) - } - - return slugs, nil -} - -func (w *WalletGetOrderRequest) Do(ctx context.Context) (*max.Order, error) { - - // empty params for GET operation - var params interface{} - query, err := w.GetParametersQuery() - if err != nil { - return nil, err - } - - apiURL := "/api/v3/wallet/:walletType/orders" - slugs, err := w.GetSlugsMap() - if err != nil { - return nil, err - } - - apiURL = w.applySlugsToUrl(apiURL, slugs) - - req, err := w.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) - if err != nil { - return nil, err - } - - response, err := w.client.SendRequest(req) - if err != nil { - return nil, err - } - - var apiResponse max.Order - if err := response.DecodeJSON(&apiResponse); err != nil { - return nil, err - } - return &apiResponse, nil -} diff --git a/pkg/exchange/max/maxapi/v3/wallet_order_cancel_all_request_requestgen.go b/pkg/exchange/max/maxapi/v3/wallet_order_cancel_all_request_requestgen.go index 8f7e071be..51da14049 100644 --- a/pkg/exchange/max/maxapi/v3/wallet_order_cancel_all_request_requestgen.go +++ b/pkg/exchange/max/maxapi/v3/wallet_order_cancel_all_request_requestgen.go @@ -27,7 +27,7 @@ func (w *WalletOrderCancelAllRequest) GroupID(groupID uint32) *WalletOrderCancel return w } -func (w *WalletOrderCancelAllRequest) WalletType(walletType WalletType) *WalletOrderCancelAllRequest { +func (w *WalletOrderCancelAllRequest) WalletType(walletType max.WalletType) *WalletOrderCancelAllRequest { w.walletType = walletType return w } @@ -119,17 +119,6 @@ func (w *WalletOrderCancelAllRequest) GetSlugParameters() (map[string]interface{ } // END TEMPLATE check-required - // TEMPLATE check-valid-values - switch walletType { - case WalletTypeSpot, WalletTypeMargin: - params["walletType"] = walletType - - default: - return nil, fmt.Errorf("walletType value %v is invalid", walletType) - - } - // END TEMPLATE check-valid-values - // assign parameter of walletType params["walletType"] = walletType