From a66bae47fee25c16b8dfceddcc88d58aed3a280e Mon Sep 17 00:00:00 2001 From: c9s Date: Mon, 23 May 2022 18:34:08 +0800 Subject: [PATCH 01/24] add v3 order endpoint --- .../maxapi/create_order_request_requestgen.go | 36 +-- .../get_order_history_request_requestgen.go | 36 +-- .../maxapi/get_order_request_requestgen.go | 36 +-- .../maxapi/get_orders_request_requestgen.go | 36 +-- pkg/exchange/max/maxapi/order.go | 42 ++- .../order_cancel_all_request_requestgen.go | 36 +-- .../maxapi/order_cancel_request_requestgen.go | 36 +-- .../v_3_create_order_request_requestgen.go | 270 ++++++++++++++++++ 8 files changed, 419 insertions(+), 109 deletions(-) create mode 100644 pkg/exchange/max/maxapi/v_3_create_order_request_requestgen.go diff --git a/pkg/exchange/max/maxapi/create_order_request_requestgen.go b/pkg/exchange/max/maxapi/create_order_request_requestgen.go index 300b9fe9f..62d0572d6 100644 --- a/pkg/exchange/max/maxapi/create_order_request_requestgen.go +++ b/pkg/exchange/max/maxapi/create_order_request_requestgen.go @@ -56,8 +56,8 @@ func (c *CreateOrderRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} query := url.Values{} - for k, v := range params { - query.Add(k, fmt.Sprintf("%v", v)) + for _k, _v := range params { + query.Add(_k, fmt.Sprintf("%v", _v)) } return query, nil @@ -149,13 +149,13 @@ func (c *CreateOrderRequest) GetParametersQuery() (url.Values, error) { return query, err } - for k, v := range params { - if c.isVarSlice(v) { - c.iterateSlice(v, func(it interface{}) { - query.Add(k+"[]", fmt.Sprintf("%v", it)) + for _k, _v := range params { + if c.isVarSlice(_v) { + c.iterateSlice(_v, func(it interface{}) { + query.Add(_k+"[]", fmt.Sprintf("%v", it)) }) } else { - query.Add(k, fmt.Sprintf("%v", v)) + query.Add(_k, fmt.Sprintf("%v", _v)) } } @@ -180,24 +180,24 @@ func (c *CreateOrderRequest) GetSlugParameters() (map[string]interface{}, error) } func (c *CreateOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string { - for k, v := range slugs { - needleRE := regexp.MustCompile(":" + k + "\\b") - url = needleRE.ReplaceAllString(url, v) + for _k, _v := range slugs { + needleRE := regexp.MustCompile(":" + _k + "\\b") + url = needleRE.ReplaceAllString(url, _v) } return url } -func (c *CreateOrderRequest) iterateSlice(slice interface{}, f func(it interface{})) { +func (c *CreateOrderRequest) 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) + for _i := 0; _i < sliceValue.Len(); _i++ { + it := sliceValue.Index(_i).Interface() + _f(it) } } -func (c *CreateOrderRequest) isVarSlice(v interface{}) bool { - rt := reflect.TypeOf(v) +func (c *CreateOrderRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) switch rt.Kind() { case reflect.Slice: return true @@ -212,8 +212,8 @@ func (c *CreateOrderRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } - for k, v := range params { - slugs[k] = fmt.Sprintf("%v", v) + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) } return slugs, nil diff --git a/pkg/exchange/max/maxapi/get_order_history_request_requestgen.go b/pkg/exchange/max/maxapi/get_order_history_request_requestgen.go index 51ef9e0bb..7cb15cf0b 100644 --- a/pkg/exchange/max/maxapi/get_order_history_request_requestgen.go +++ b/pkg/exchange/max/maxapi/get_order_history_request_requestgen.go @@ -31,8 +31,8 @@ func (g *GetOrderHistoryRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} query := url.Values{} - for k, v := range params { - query.Add(k, fmt.Sprintf("%v", v)) + for _k, _v := range params { + query.Add(_k, fmt.Sprintf("%v", _v)) } return query, nil @@ -75,13 +75,13 @@ func (g *GetOrderHistoryRequest) GetParametersQuery() (url.Values, error) { return query, err } - for k, v := range params { - if g.isVarSlice(v) { - g.iterateSlice(v, func(it interface{}) { - query.Add(k+"[]", fmt.Sprintf("%v", it)) + for _k, _v := range params { + if g.isVarSlice(_v) { + g.iterateSlice(_v, func(it interface{}) { + query.Add(_k+"[]", fmt.Sprintf("%v", it)) }) } else { - query.Add(k, fmt.Sprintf("%v", v)) + query.Add(_k, fmt.Sprintf("%v", _v)) } } @@ -106,24 +106,24 @@ func (g *GetOrderHistoryRequest) GetSlugParameters() (map[string]interface{}, er } func (g *GetOrderHistoryRequest) applySlugsToUrl(url string, slugs map[string]string) string { - for k, v := range slugs { - needleRE := regexp.MustCompile(":" + k + "\\b") - url = needleRE.ReplaceAllString(url, v) + for _k, _v := range slugs { + needleRE := regexp.MustCompile(":" + _k + "\\b") + url = needleRE.ReplaceAllString(url, _v) } return url } -func (g *GetOrderHistoryRequest) iterateSlice(slice interface{}, f func(it interface{})) { +func (g *GetOrderHistoryRequest) 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) + for _i := 0; _i < sliceValue.Len(); _i++ { + it := sliceValue.Index(_i).Interface() + _f(it) } } -func (g *GetOrderHistoryRequest) isVarSlice(v interface{}) bool { - rt := reflect.TypeOf(v) +func (g *GetOrderHistoryRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) switch rt.Kind() { case reflect.Slice: return true @@ -138,8 +138,8 @@ func (g *GetOrderHistoryRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } - for k, v := range params { - slugs[k] = fmt.Sprintf("%v", v) + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) } return slugs, nil diff --git a/pkg/exchange/max/maxapi/get_order_request_requestgen.go b/pkg/exchange/max/maxapi/get_order_request_requestgen.go index 4f495fbe0..c29ef52cd 100644 --- a/pkg/exchange/max/maxapi/get_order_request_requestgen.go +++ b/pkg/exchange/max/maxapi/get_order_request_requestgen.go @@ -26,8 +26,8 @@ func (g *GetOrderRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} query := url.Values{} - for k, v := range params { - query.Add(k, fmt.Sprintf("%v", v)) + for _k, _v := range params { + query.Add(_k, fmt.Sprintf("%v", _v)) } return query, nil @@ -65,13 +65,13 @@ func (g *GetOrderRequest) GetParametersQuery() (url.Values, error) { return query, err } - for k, v := range params { - if g.isVarSlice(v) { - g.iterateSlice(v, func(it interface{}) { - query.Add(k+"[]", fmt.Sprintf("%v", it)) + for _k, _v := range params { + if g.isVarSlice(_v) { + g.iterateSlice(_v, func(it interface{}) { + query.Add(_k+"[]", fmt.Sprintf("%v", it)) }) } else { - query.Add(k, fmt.Sprintf("%v", v)) + query.Add(_k, fmt.Sprintf("%v", _v)) } } @@ -96,24 +96,24 @@ func (g *GetOrderRequest) GetSlugParameters() (map[string]interface{}, error) { } func (g *GetOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string { - for k, v := range slugs { - needleRE := regexp.MustCompile(":" + k + "\\b") - url = needleRE.ReplaceAllString(url, v) + for _k, _v := range slugs { + needleRE := regexp.MustCompile(":" + _k + "\\b") + url = needleRE.ReplaceAllString(url, _v) } return url } -func (g *GetOrderRequest) iterateSlice(slice interface{}, f func(it interface{})) { +func (g *GetOrderRequest) 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) + for _i := 0; _i < sliceValue.Len(); _i++ { + it := sliceValue.Index(_i).Interface() + _f(it) } } -func (g *GetOrderRequest) isVarSlice(v interface{}) bool { - rt := reflect.TypeOf(v) +func (g *GetOrderRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) switch rt.Kind() { case reflect.Slice: return true @@ -128,8 +128,8 @@ func (g *GetOrderRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } - for k, v := range params { - slugs[k] = fmt.Sprintf("%v", v) + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) } return slugs, nil diff --git a/pkg/exchange/max/maxapi/get_orders_request_requestgen.go b/pkg/exchange/max/maxapi/get_orders_request_requestgen.go index 36ef44701..de914deb9 100644 --- a/pkg/exchange/max/maxapi/get_orders_request_requestgen.go +++ b/pkg/exchange/max/maxapi/get_orders_request_requestgen.go @@ -56,8 +56,8 @@ func (g *GetOrdersRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} query := url.Values{} - for k, v := range params { - query.Add(k, fmt.Sprintf("%v", v)) + for _k, _v := range params { + query.Add(_k, fmt.Sprintf("%v", _v)) } return query, nil @@ -141,13 +141,13 @@ func (g *GetOrdersRequest) GetParametersQuery() (url.Values, error) { return query, err } - for k, v := range params { - if g.isVarSlice(v) { - g.iterateSlice(v, func(it interface{}) { - query.Add(k+"[]", fmt.Sprintf("%v", it)) + for _k, _v := range params { + if g.isVarSlice(_v) { + g.iterateSlice(_v, func(it interface{}) { + query.Add(_k+"[]", fmt.Sprintf("%v", it)) }) } else { - query.Add(k, fmt.Sprintf("%v", v)) + query.Add(_k, fmt.Sprintf("%v", _v)) } } @@ -172,24 +172,24 @@ func (g *GetOrdersRequest) GetSlugParameters() (map[string]interface{}, error) { } func (g *GetOrdersRequest) applySlugsToUrl(url string, slugs map[string]string) string { - for k, v := range slugs { - needleRE := regexp.MustCompile(":" + k + "\\b") - url = needleRE.ReplaceAllString(url, v) + for _k, _v := range slugs { + needleRE := regexp.MustCompile(":" + _k + "\\b") + url = needleRE.ReplaceAllString(url, _v) } return url } -func (g *GetOrdersRequest) iterateSlice(slice interface{}, f func(it interface{})) { +func (g *GetOrdersRequest) 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) + for _i := 0; _i < sliceValue.Len(); _i++ { + it := sliceValue.Index(_i).Interface() + _f(it) } } -func (g *GetOrdersRequest) isVarSlice(v interface{}) bool { - rt := reflect.TypeOf(v) +func (g *GetOrdersRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) switch rt.Kind() { case reflect.Slice: return true @@ -204,8 +204,8 @@ func (g *GetOrdersRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } - for k, v := range params { - slugs[k] = fmt.Sprintf("%v", v) + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) } return slugs, nil diff --git a/pkg/exchange/max/maxapi/order.go b/pkg/exchange/max/maxapi/order.go index a412ce7c7..4d75252b1 100644 --- a/pkg/exchange/max/maxapi/order.go +++ b/pkg/exchange/max/maxapi/order.go @@ -147,7 +147,7 @@ func (s *OrderService) Open(market string, options QueryOrderOptions) ([]Order, type GetOrderHistoryRequest struct { client requestgen.AuthenticatedAPIClient - market string `param:"market"` + market string `param:"market"` fromID *uint64 `param:"from_id"` limit *uint `param:"limit"` } @@ -353,3 +353,43 @@ type CreateOrderRequest struct { func (s *OrderService) NewCreateOrderRequest() *CreateOrderRequest { return &CreateOrderRequest{client: s.client} } + +//go:generate PostRequest -url "/api/v3/wallet/:walletType/orders" -type V3CreateOrderRequest -responseType .Order +type V3CreateOrderRequest struct { + client requestgen.AuthenticatedAPIClient + + walletType string `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"` +} + +func (s *OrderService) NewV3CreateOrderRequest() *V3CreateOrderRequest { + return &V3CreateOrderRequest{client: s.client} +} + +//go:generate GetRequest -url "/api/v3/wallet/:walletType/orders" -type V3GetOrderRequest -responseType .Order +type V3GetOrderRequest struct { + client requestgen.AuthenticatedAPIClient + + walletType string `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"` +} + +func (s *OrderService) NewV3GetOrderRequest() *V3GetOrderRequest { + return &V3GetOrderRequest{client: s.client} +} diff --git a/pkg/exchange/max/maxapi/order_cancel_all_request_requestgen.go b/pkg/exchange/max/maxapi/order_cancel_all_request_requestgen.go index f1fdac327..ec160f80c 100644 --- a/pkg/exchange/max/maxapi/order_cancel_all_request_requestgen.go +++ b/pkg/exchange/max/maxapi/order_cancel_all_request_requestgen.go @@ -31,8 +31,8 @@ func (o *OrderCancelAllRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} query := url.Values{} - for k, v := range params { - query.Add(k, fmt.Sprintf("%v", v)) + for _k, _v := range params { + query.Add(_k, fmt.Sprintf("%v", _v)) } return query, nil @@ -78,13 +78,13 @@ func (o *OrderCancelAllRequest) GetParametersQuery() (url.Values, error) { return query, err } - for k, v := range params { - if o.isVarSlice(v) { - o.iterateSlice(v, func(it interface{}) { - query.Add(k+"[]", fmt.Sprintf("%v", it)) + for _k, _v := range params { + if o.isVarSlice(_v) { + o.iterateSlice(_v, func(it interface{}) { + query.Add(_k+"[]", fmt.Sprintf("%v", it)) }) } else { - query.Add(k, fmt.Sprintf("%v", v)) + query.Add(_k, fmt.Sprintf("%v", _v)) } } @@ -109,24 +109,24 @@ func (o *OrderCancelAllRequest) GetSlugParameters() (map[string]interface{}, err } func (o *OrderCancelAllRequest) applySlugsToUrl(url string, slugs map[string]string) string { - for k, v := range slugs { - needleRE := regexp.MustCompile(":" + k + "\\b") - url = needleRE.ReplaceAllString(url, v) + for _k, _v := range slugs { + needleRE := regexp.MustCompile(":" + _k + "\\b") + url = needleRE.ReplaceAllString(url, _v) } return url } -func (o *OrderCancelAllRequest) iterateSlice(slice interface{}, f func(it interface{})) { +func (o *OrderCancelAllRequest) 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) + for _i := 0; _i < sliceValue.Len(); _i++ { + it := sliceValue.Index(_i).Interface() + _f(it) } } -func (o *OrderCancelAllRequest) isVarSlice(v interface{}) bool { - rt := reflect.TypeOf(v) +func (o *OrderCancelAllRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) switch rt.Kind() { case reflect.Slice: return true @@ -141,8 +141,8 @@ func (o *OrderCancelAllRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } - for k, v := range params { - slugs[k] = fmt.Sprintf("%v", v) + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) } return slugs, nil diff --git a/pkg/exchange/max/maxapi/order_cancel_request_requestgen.go b/pkg/exchange/max/maxapi/order_cancel_request_requestgen.go index 1854837c5..552bad901 100644 --- a/pkg/exchange/max/maxapi/order_cancel_request_requestgen.go +++ b/pkg/exchange/max/maxapi/order_cancel_request_requestgen.go @@ -26,8 +26,8 @@ func (o *OrderCancelRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} query := url.Values{} - for k, v := range params { - query.Add(k, fmt.Sprintf("%v", v)) + for _k, _v := range params { + query.Add(_k, fmt.Sprintf("%v", _v)) } return query, nil @@ -65,13 +65,13 @@ func (o *OrderCancelRequest) GetParametersQuery() (url.Values, error) { return query, err } - for k, v := range params { - if o.isVarSlice(v) { - o.iterateSlice(v, func(it interface{}) { - query.Add(k+"[]", fmt.Sprintf("%v", it)) + for _k, _v := range params { + if o.isVarSlice(_v) { + o.iterateSlice(_v, func(it interface{}) { + query.Add(_k+"[]", fmt.Sprintf("%v", it)) }) } else { - query.Add(k, fmt.Sprintf("%v", v)) + query.Add(_k, fmt.Sprintf("%v", _v)) } } @@ -96,24 +96,24 @@ func (o *OrderCancelRequest) GetSlugParameters() (map[string]interface{}, error) } func (o *OrderCancelRequest) applySlugsToUrl(url string, slugs map[string]string) string { - for k, v := range slugs { - needleRE := regexp.MustCompile(":" + k + "\\b") - url = needleRE.ReplaceAllString(url, v) + for _k, _v := range slugs { + needleRE := regexp.MustCompile(":" + _k + "\\b") + url = needleRE.ReplaceAllString(url, _v) } return url } -func (o *OrderCancelRequest) iterateSlice(slice interface{}, f func(it interface{})) { +func (o *OrderCancelRequest) 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) + for _i := 0; _i < sliceValue.Len(); _i++ { + it := sliceValue.Index(_i).Interface() + _f(it) } } -func (o *OrderCancelRequest) isVarSlice(v interface{}) bool { - rt := reflect.TypeOf(v) +func (o *OrderCancelRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) switch rt.Kind() { case reflect.Slice: return true @@ -128,8 +128,8 @@ func (o *OrderCancelRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } - for k, v := range params { - slugs[k] = fmt.Sprintf("%v", v) + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) } return slugs, nil diff --git a/pkg/exchange/max/maxapi/v_3_create_order_request_requestgen.go b/pkg/exchange/max/maxapi/v_3_create_order_request_requestgen.go new file mode 100644 index 000000000..196ca299c --- /dev/null +++ b/pkg/exchange/max/maxapi/v_3_create_order_request_requestgen.go @@ -0,0 +1,270 @@ +// Code generated by "requestgen -method GET -url /api/v3/wallet/:walletType/orders -type V3CreateOrderRequest -responseType .Order"; DO NOT EDIT. + +package max + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" +) + +func (v *V3CreateOrderRequest) Market(market string) *V3CreateOrderRequest { + v.market = market + return v +} + +func (v *V3CreateOrderRequest) Side(side string) *V3CreateOrderRequest { + v.side = side + return v +} + +func (v *V3CreateOrderRequest) Volume(volume string) *V3CreateOrderRequest { + v.volume = volume + return v +} + +func (v *V3CreateOrderRequest) OrderType(orderType string) *V3CreateOrderRequest { + v.orderType = orderType + return v +} + +func (v *V3CreateOrderRequest) Price(price string) *V3CreateOrderRequest { + v.price = &price + return v +} + +func (v *V3CreateOrderRequest) StopPrice(stopPrice string) *V3CreateOrderRequest { + v.stopPrice = &stopPrice + return v +} + +func (v *V3CreateOrderRequest) ClientOrderID(clientOrderID string) *V3CreateOrderRequest { + v.clientOrderID = &clientOrderID + return v +} + +func (v *V3CreateOrderRequest) GroupID(groupID string) *V3CreateOrderRequest { + v.groupID = &groupID + return v +} + +func (v *V3CreateOrderRequest) WalletType(walletType string) *V3CreateOrderRequest { + v.walletType = walletType + return v +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (v *V3CreateOrderRequest) 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 (v *V3CreateOrderRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check market field -> json key market + market := v.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 := v.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 := v.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 := v.orderType + + // assign parameter of orderType + params["ord_type"] = orderType + // check price field -> json key price + if v.price != nil { + price := *v.price + + // assign parameter of price + params["price"] = price + } else { + } + // check stopPrice field -> json key stop_price + if v.stopPrice != nil { + stopPrice := *v.stopPrice + + // assign parameter of stopPrice + params["stop_price"] = stopPrice + } else { + } + // check clientOrderID field -> json key client_oid + if v.clientOrderID != nil { + clientOrderID := *v.clientOrderID + + // assign parameter of clientOrderID + params["client_oid"] = clientOrderID + } else { + } + // check groupID field -> json key group_id + if v.groupID != nil { + groupID := *v.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 (v *V3CreateOrderRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := v.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if v.isVarSlice(_v) { + v.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 (v *V3CreateOrderRequest) GetParametersJSON() ([]byte, error) { + params, err := v.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 (v *V3CreateOrderRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check walletType field -> json key walletType + walletType := v.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 (v *V3CreateOrderRequest) 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 (v *V3CreateOrderRequest) 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 (v *V3CreateOrderRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (v *V3CreateOrderRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := v.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (v *V3CreateOrderRequest) Do(ctx context.Context) (*Order, error) { + + // empty params for GET operation + var params interface{} + query, err := v.GetParametersQuery() + if err != nil { + return nil, err + } + + apiURL := "/api/v3/wallet/:walletType/orders" + slugs, err := v.GetSlugsMap() + if err != nil { + return nil, err + } + + apiURL = v.applySlugsToUrl(apiURL, slugs) + + req, err := v.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := v.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse Order + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return &apiResponse, nil +} From c6ede883cebe0d5190cb9b5b91091eacb82d168a Mon Sep 17 00:00:00 2001 From: c9s Date: Tue, 24 May 2022 17:40:00 +0800 Subject: [PATCH 02/24] add max v3 api --- pkg/exchange/max/maxapi/order.go | 40 --- pkg/exchange/max/maxapi/restapi.go | 184 ++---------- .../v3/create_order_request_requestgen.go | 270 ++++++++++++++++++ .../get_order_request_requestgen.go} | 127 ++++---- pkg/exchange/max/maxapi/v3/order.go | 84 ++++++ .../v3/order_cancel_all_request_requestgen.go | 199 +++++++++++++ .../v3/order_cancel_request_requestgen.go | 164 +++++++++++ 7 files changed, 808 insertions(+), 260 deletions(-) create mode 100644 pkg/exchange/max/maxapi/v3/create_order_request_requestgen.go rename pkg/exchange/max/maxapi/{v_3_create_order_request_requestgen.go => v3/get_order_request_requestgen.go} (59%) create mode 100644 pkg/exchange/max/maxapi/v3/order.go create mode 100644 pkg/exchange/max/maxapi/v3/order_cancel_all_request_requestgen.go create mode 100644 pkg/exchange/max/maxapi/v3/order_cancel_request_requestgen.go diff --git a/pkg/exchange/max/maxapi/order.go b/pkg/exchange/max/maxapi/order.go index 4d75252b1..b37a41ca3 100644 --- a/pkg/exchange/max/maxapi/order.go +++ b/pkg/exchange/max/maxapi/order.go @@ -353,43 +353,3 @@ type CreateOrderRequest struct { func (s *OrderService) NewCreateOrderRequest() *CreateOrderRequest { return &CreateOrderRequest{client: s.client} } - -//go:generate PostRequest -url "/api/v3/wallet/:walletType/orders" -type V3CreateOrderRequest -responseType .Order -type V3CreateOrderRequest struct { - client requestgen.AuthenticatedAPIClient - - walletType string `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"` -} - -func (s *OrderService) NewV3CreateOrderRequest() *V3CreateOrderRequest { - return &V3CreateOrderRequest{client: s.client} -} - -//go:generate GetRequest -url "/api/v3/wallet/:walletType/orders" -type V3GetOrderRequest -responseType .Order -type V3GetOrderRequest struct { - client requestgen.AuthenticatedAPIClient - - walletType string `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"` -} - -func (s *OrderService) NewV3GetOrderRequest() *V3GetOrderRequest { - return &V3GetOrderRequest{client: s.client} -} diff --git a/pkg/exchange/max/maxapi/restapi.go b/pkg/exchange/max/maxapi/restapi.go index ef26fd1ed..597d65e9b 100644 --- a/pkg/exchange/max/maxapi/restapi.go +++ b/pkg/exchange/max/maxapi/restapi.go @@ -1,7 +1,6 @@ package max import ( - "bytes" "context" "crypto/hmac" "crypto/sha256" @@ -9,11 +8,9 @@ import ( "encoding/hex" "encoding/json" "fmt" - "io/ioutil" "math" "net" "net/http" - "net/http/httputil" "net/url" "regexp" "strings" @@ -40,18 +37,11 @@ const ( TimestampSince = 1535760000 ) -var debugRequestDump = false -var debugMaxRequestPayload = false -var addUserAgentHeader = true - var httpTransportMaxIdleConnsPerHost = http.DefaultMaxIdleConnsPerHost var httpTransportMaxIdleConns = 100 var httpTransportIdleConnTimeout = 90 * time.Second func init() { - debugMaxRequestPayload, _ = util.GetEnvVarBool("DEBUG_MAX_REQUEST_PAYLOAD") - debugRequestDump, _ = util.GetEnvVarBool("DEBUG_MAX_REQUEST") - addUserAgentHeader, _ = util.GetEnvVarBool("DISABLE_MAX_USER_AGENT_HEADER") if val, ok := util.GetEnvVarInt("HTTP_TRANSPORT_MAX_IDLE_CONNS_PER_HOST"); ok { httpTransportMaxIdleConnsPerHost = val @@ -81,9 +71,7 @@ var serverTimestamp = time.Now().Unix() var reqCount int64 = 1 type RestClient struct { - client *http.Client - - BaseURL *url.URL + requestgen.BaseAPIClient // Authentication APIKey string @@ -108,8 +96,10 @@ func NewRestClientWithHttpClient(baseURL string, httpClient *http.Client) *RestC } var client = &RestClient{ - client: httpClient, - BaseURL: u, + BaseAPIClient: requestgen.BaseAPIClient{ + HttpClient: httpClient, + BaseURL: u, + }, } client.AccountService = &AccountService{client} @@ -175,45 +165,20 @@ func (c *RestClient) getNonce() int64 { return (seconds+timeOffset)*1000 - 1 + int64(math.Mod(float64(rc), 1000.0)) } -// NewRequest create new API request. Relative url can be provided in refURL. -func (c *RestClient) NewRequest(ctx context.Context, method string, refURL string, params url.Values, payload interface{}) (*http.Request, error) { - rel, err := url.Parse(refURL) - if err != nil { - return nil, err - } - - if params != nil { - rel.RawQuery = params.Encode() - } - - var req *http.Request - u := c.BaseURL.ResolveReference(rel) - - body, err := castPayload(payload) - if err != nil { - return nil, err - } - - req, err = http.NewRequest(method, u.String(), bytes.NewReader(body)) - if err != nil { - return nil, err - } - - req = req.WithContext(ctx) - - if addUserAgentHeader { - req.Header.Add("User-Agent", UserAgent) - } - - return req, nil -} - func (c *RestClient) NewAuthenticatedRequest(ctx context.Context, m string, refURL string, params url.Values, payload interface{}) (*http.Request, error) { return c.newAuthenticatedRequest(ctx, m, refURL, params, payload, nil) } // newAuthenticatedRequest creates new http request for authenticated routes. func (c *RestClient) newAuthenticatedRequest(ctx context.Context, m string, refURL string, params url.Values, data interface{}, rel *url.URL) (*http.Request, error) { + if len(c.APIKey) == 0 { + return nil, errors.New("empty api key") + } + + if len(c.APISecret) == 0 { + return nil, errors.New("empty api secret") + } + var err error if rel == nil { rel, err = url.Parse(refURL) @@ -223,22 +188,13 @@ func (c *RestClient) newAuthenticatedRequest(ctx context.Context, m string, refU } var p []byte - var payload map[string]interface{} + var payload = map[string]interface{}{ + "nonce": c.getNonce(), + "path": c.BaseURL.ResolveReference(rel).Path, + } switch d := data.(type) { - - case nil: - payload = map[string]interface{}{ - "nonce": c.getNonce(), - "path": c.BaseURL.ResolveReference(rel).Path, - } - case map[string]interface{}: - payload = map[string]interface{}{ - "nonce": c.getNonce(), - "path": c.BaseURL.ResolveReference(rel).Path, - } - for k, v := range d { payload[k] = v } @@ -258,22 +214,6 @@ func (c *RestClient) newAuthenticatedRequest(ctx context.Context, m string, refU return nil, err } - if debugMaxRequestPayload { - log.Infof("request payload: %s", p) - } - - if err != nil { - return nil, err - } - - if len(c.APIKey) == 0 { - return nil, errors.New("empty api key") - } - - if len(c.APISecret) == 0 { - return nil, errors.New("empty api secret") - } - req, err := c.NewRequest(ctx, m, refURL, params, p) if err != nil { return nil, err @@ -286,95 +226,16 @@ func (c *RestClient) newAuthenticatedRequest(ctx context.Context, m string, refU req.Header.Add("X-MAX-PAYLOAD", encoded) req.Header.Add("X-MAX-SIGNATURE", signPayload(encoded, c.APISecret)) - if debugRequestDump { - dump, err2 := httputil.DumpRequestOut(req, true) - if err2 != nil { - log.Errorf("dump request error: %v", err2) - } else { - fmt.Printf("REQUEST:\n%s", dump) - } - } - return req, nil } -func signPayload(payload string, secret string) string { - var sig = hmac.New(sha256.New, []byte(secret)) - _, err := sig.Write([]byte(payload)) - if err != nil { - return "" - } - return hex.EncodeToString(sig.Sum(nil)) -} - -func (c *RestClient) Do(req *http.Request) (resp *http.Response, err error) { - return c.client.Do(req) -} - -// SendRequest sends the request to the API server and handle the response -func (c *RestClient) SendRequest(req *http.Request) (*requestgen.Response, error) { - resp, err := c.client.Do(req) - if err != nil { - return nil, err - } - - // newResponse reads the response body and return a new Response object - response, err := requestgen.NewResponse(resp) - if err != nil { - return response, err - } - - // Check error, if there is an error, return the ErrorResponse struct type - if response.IsError() { - errorResponse, err := ToErrorResponse(response) - if err != nil { - return response, err - } - return response, errorResponse - } - - return response, nil -} - func (c *RestClient) sendAuthenticatedRequest(m string, refURL string, data map[string]interface{}) (*requestgen.Response, error) { req, err := c.newAuthenticatedRequest(nil, m, refURL, nil, data, nil) if err != nil { return nil, err } - response, err := c.SendRequest(req) - if err != nil { - return nil, err - } - return response, err -} -// get sends GET http request to the api endpoint, the urlPath must start with a slash '/' -func (c *RestClient) get(urlPath string, values url.Values) ([]byte, error) { - var reqURL = c.BaseURL.String() + urlPath - - // Create request - req, err := http.NewRequest("GET", reqURL, nil) - if err != nil { - return nil, fmt.Errorf("could not init request: %s", err.Error()) - } - - req.URL.RawQuery = values.Encode() - req.Header.Add("User-Agent", UserAgent) - - // Execute request - resp, err := c.client.Do(req) - if err != nil { - return nil, fmt.Errorf("could not execute request: %s", err.Error()) - } - defer resp.Body.Close() - - // Load request - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("could not read response: %s", err.Error()) - } - - return body, nil + return c.SendRequest(req) } // ErrorResponse is the custom error type that is returned if the API returns an @@ -439,3 +300,12 @@ func castPayload(payload interface{}) ([]byte, error) { body, err := json.Marshal(payload) return body, err } + +func signPayload(payload string, secret string) string { + var sig = hmac.New(sha256.New, []byte(secret)) + _, err := sig.Write([]byte(payload)) + if err != nil { + return "" + } + return hex.EncodeToString(sig.Sum(nil)) +} diff --git a/pkg/exchange/max/maxapi/v3/create_order_request_requestgen.go b/pkg/exchange/max/maxapi/v3/create_order_request_requestgen.go new file mode 100644 index 000000000..4ab6bbfe8 --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/create_order_request_requestgen.go @@ -0,0 +1,270 @@ +// Code generated by "requestgen -method POST -url /api/v3/wallet/:walletType/orders -type CreateOrderRequest -responseType .Order -debug"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "github.com/c9s/bbgo/pkg/exchange/max/maxapi" + "net/url" + "reflect" + "regexp" +) + +func (c *CreateOrderRequest) Market(market string) *CreateOrderRequest { + c.market = market + return c +} + +func (c *CreateOrderRequest) Side(side string) *CreateOrderRequest { + c.side = side + return c +} + +func (c *CreateOrderRequest) Volume(volume string) *CreateOrderRequest { + c.volume = volume + return c +} + +func (c *CreateOrderRequest) OrderType(orderType string) *CreateOrderRequest { + c.orderType = orderType + return c +} + +func (c *CreateOrderRequest) Price(price string) *CreateOrderRequest { + c.price = &price + return c +} + +func (c *CreateOrderRequest) StopPrice(stopPrice string) *CreateOrderRequest { + c.stopPrice = &stopPrice + return c +} + +func (c *CreateOrderRequest) ClientOrderID(clientOrderID string) *CreateOrderRequest { + c.clientOrderID = &clientOrderID + return c +} + +func (c *CreateOrderRequest) GroupID(groupID string) *CreateOrderRequest { + c.groupID = &groupID + return c +} + +func (c *CreateOrderRequest) WalletType(walletType string) *CreateOrderRequest { + c.walletType = walletType + return c +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (c *CreateOrderRequest) 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 (c *CreateOrderRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check market field -> json key market + market := c.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 := c.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 := c.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 := c.orderType + + // assign parameter of orderType + params["ord_type"] = orderType + // check price field -> json key price + if c.price != nil { + price := *c.price + + // assign parameter of price + params["price"] = price + } else { + } + // check stopPrice field -> json key stop_price + if c.stopPrice != nil { + stopPrice := *c.stopPrice + + // assign parameter of stopPrice + params["stop_price"] = stopPrice + } else { + } + // check clientOrderID field -> json key client_oid + if c.clientOrderID != nil { + clientOrderID := *c.clientOrderID + + // assign parameter of clientOrderID + params["client_oid"] = clientOrderID + } else { + } + // check groupID field -> json key group_id + if c.groupID != nil { + groupID := *c.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 (c *CreateOrderRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := c.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if c.isVarSlice(_v) { + c.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 (c *CreateOrderRequest) GetParametersJSON() ([]byte, error) { + params, err := c.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 (c *CreateOrderRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check walletType field -> json key walletType + walletType := c.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 (c *CreateOrderRequest) 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 (c *CreateOrderRequest) 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 (c *CreateOrderRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (c *CreateOrderRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := c.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (c *CreateOrderRequest) Do(ctx context.Context) (*max.Order, error) { + + params, err := c.GetParameters() + if err != nil { + return nil, err + } + query := url.Values{} + + apiURL := "/api/v3/wallet/:walletType/orders" + slugs, err := c.GetSlugsMap() + if err != nil { + return nil, err + } + + apiURL = c.applySlugsToUrl(apiURL, slugs) + + req, err := c.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := c.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/v_3_create_order_request_requestgen.go b/pkg/exchange/max/maxapi/v3/get_order_request_requestgen.go similarity index 59% rename from pkg/exchange/max/maxapi/v_3_create_order_request_requestgen.go rename to pkg/exchange/max/maxapi/v3/get_order_request_requestgen.go index 196ca299c..60c18dea7 100644 --- a/pkg/exchange/max/maxapi/v_3_create_order_request_requestgen.go +++ b/pkg/exchange/max/maxapi/v3/get_order_request_requestgen.go @@ -1,63 +1,64 @@ -// Code generated by "requestgen -method GET -url /api/v3/wallet/:walletType/orders -type V3CreateOrderRequest -responseType .Order"; DO NOT EDIT. +// Code generated by "requestgen -method GET -url /api/v3/wallet/:walletType/orders -type GetOrderRequest -responseType .Order"; DO NOT EDIT. -package max +package v3 import ( "context" "encoding/json" "fmt" + "github.com/c9s/bbgo/pkg/exchange/max/maxapi" "net/url" "reflect" "regexp" ) -func (v *V3CreateOrderRequest) Market(market string) *V3CreateOrderRequest { - v.market = market - return v +func (g *GetOrderRequest) Market(market string) *GetOrderRequest { + g.market = market + return g } -func (v *V3CreateOrderRequest) Side(side string) *V3CreateOrderRequest { - v.side = side - return v +func (g *GetOrderRequest) Side(side string) *GetOrderRequest { + g.side = side + return g } -func (v *V3CreateOrderRequest) Volume(volume string) *V3CreateOrderRequest { - v.volume = volume - return v +func (g *GetOrderRequest) Volume(volume string) *GetOrderRequest { + g.volume = volume + return g } -func (v *V3CreateOrderRequest) OrderType(orderType string) *V3CreateOrderRequest { - v.orderType = orderType - return v +func (g *GetOrderRequest) OrderType(orderType string) *GetOrderRequest { + g.orderType = orderType + return g } -func (v *V3CreateOrderRequest) Price(price string) *V3CreateOrderRequest { - v.price = &price - return v +func (g *GetOrderRequest) Price(price string) *GetOrderRequest { + g.price = &price + return g } -func (v *V3CreateOrderRequest) StopPrice(stopPrice string) *V3CreateOrderRequest { - v.stopPrice = &stopPrice - return v +func (g *GetOrderRequest) StopPrice(stopPrice string) *GetOrderRequest { + g.stopPrice = &stopPrice + return g } -func (v *V3CreateOrderRequest) ClientOrderID(clientOrderID string) *V3CreateOrderRequest { - v.clientOrderID = &clientOrderID - return v +func (g *GetOrderRequest) ClientOrderID(clientOrderID string) *GetOrderRequest { + g.clientOrderID = &clientOrderID + return g } -func (v *V3CreateOrderRequest) GroupID(groupID string) *V3CreateOrderRequest { - v.groupID = &groupID - return v +func (g *GetOrderRequest) GroupID(groupID string) *GetOrderRequest { + g.groupID = &groupID + return g } -func (v *V3CreateOrderRequest) WalletType(walletType string) *V3CreateOrderRequest { - v.walletType = walletType - return v +func (g *GetOrderRequest) WalletType(walletType string) *GetOrderRequest { + g.walletType = walletType + return g } // GetQueryParameters builds and checks the query parameters and returns url.Values -func (v *V3CreateOrderRequest) GetQueryParameters() (url.Values, error) { +func (g *GetOrderRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} query := url.Values{} @@ -69,10 +70,10 @@ func (v *V3CreateOrderRequest) GetQueryParameters() (url.Values, error) { } // GetParameters builds and checks the parameters and return the result in a map object -func (v *V3CreateOrderRequest) GetParameters() (map[string]interface{}, error) { +func (g *GetOrderRequest) GetParameters() (map[string]interface{}, error) { var params = map[string]interface{}{} // check market field -> json key market - market := v.market + market := g.market // TEMPLATE check-required if len(market) == 0 { @@ -83,7 +84,7 @@ func (v *V3CreateOrderRequest) GetParameters() (map[string]interface{}, error) { // assign parameter of market params["market"] = market // check side field -> json key side - side := v.side + side := g.side // TEMPLATE check-required if len(side) == 0 { @@ -94,7 +95,7 @@ func (v *V3CreateOrderRequest) GetParameters() (map[string]interface{}, error) { // assign parameter of side params["side"] = side // check volume field -> json key volume - volume := v.volume + volume := g.volume // TEMPLATE check-required if len(volume) == 0 { @@ -105,37 +106,37 @@ func (v *V3CreateOrderRequest) GetParameters() (map[string]interface{}, error) { // assign parameter of volume params["volume"] = volume // check orderType field -> json key ord_type - orderType := v.orderType + orderType := g.orderType // assign parameter of orderType params["ord_type"] = orderType // check price field -> json key price - if v.price != nil { - price := *v.price + if g.price != nil { + price := *g.price // assign parameter of price params["price"] = price } else { } // check stopPrice field -> json key stop_price - if v.stopPrice != nil { - stopPrice := *v.stopPrice + if g.stopPrice != nil { + stopPrice := *g.stopPrice // assign parameter of stopPrice params["stop_price"] = stopPrice } else { } // check clientOrderID field -> json key client_oid - if v.clientOrderID != nil { - clientOrderID := *v.clientOrderID + if g.clientOrderID != nil { + clientOrderID := *g.clientOrderID // assign parameter of clientOrderID params["client_oid"] = clientOrderID } else { } // check groupID field -> json key group_id - if v.groupID != nil { - groupID := *v.groupID + if g.groupID != nil { + groupID := *g.groupID // assign parameter of groupID params["group_id"] = groupID @@ -146,17 +147,17 @@ func (v *V3CreateOrderRequest) GetParameters() (map[string]interface{}, error) { } // GetParametersQuery converts the parameters from GetParameters into the url.Values format -func (v *V3CreateOrderRequest) GetParametersQuery() (url.Values, error) { +func (g *GetOrderRequest) GetParametersQuery() (url.Values, error) { query := url.Values{} - params, err := v.GetParameters() + params, err := g.GetParameters() if err != nil { return query, err } for _k, _v := range params { - if v.isVarSlice(_v) { - v.iterateSlice(_v, func(it interface{}) { + if g.isVarSlice(_v) { + g.iterateSlice(_v, func(it interface{}) { query.Add(_k+"[]", fmt.Sprintf("%v", it)) }) } else { @@ -168,8 +169,8 @@ func (v *V3CreateOrderRequest) GetParametersQuery() (url.Values, error) { } // GetParametersJSON converts the parameters from GetParameters into the JSON format -func (v *V3CreateOrderRequest) GetParametersJSON() ([]byte, error) { - params, err := v.GetParameters() +func (g *GetOrderRequest) GetParametersJSON() ([]byte, error) { + params, err := g.GetParameters() if err != nil { return nil, err } @@ -178,10 +179,10 @@ func (v *V3CreateOrderRequest) GetParametersJSON() ([]byte, error) { } // GetSlugParameters builds and checks the slug parameters and return the result in a map object -func (v *V3CreateOrderRequest) GetSlugParameters() (map[string]interface{}, error) { +func (g *GetOrderRequest) GetSlugParameters() (map[string]interface{}, error) { var params = map[string]interface{}{} // check walletType field -> json key walletType - walletType := v.walletType + walletType := g.walletType // TEMPLATE check-required if len(walletType) == 0 { @@ -195,7 +196,7 @@ func (v *V3CreateOrderRequest) GetSlugParameters() (map[string]interface{}, erro return params, nil } -func (v *V3CreateOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string { +func (g *GetOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string { for _k, _v := range slugs { needleRE := regexp.MustCompile(":" + _k + "\\b") url = needleRE.ReplaceAllString(url, _v) @@ -204,7 +205,7 @@ func (v *V3CreateOrderRequest) applySlugsToUrl(url string, slugs map[string]stri return url } -func (v *V3CreateOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) { +func (g *GetOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) { sliceValue := reflect.ValueOf(slice) for _i := 0; _i < sliceValue.Len(); _i++ { it := sliceValue.Index(_i).Interface() @@ -212,7 +213,7 @@ func (v *V3CreateOrderRequest) iterateSlice(slice interface{}, _f func(it interf } } -func (v *V3CreateOrderRequest) isVarSlice(_v interface{}) bool { +func (g *GetOrderRequest) isVarSlice(_v interface{}) bool { rt := reflect.TypeOf(_v) switch rt.Kind() { case reflect.Slice: @@ -221,9 +222,9 @@ func (v *V3CreateOrderRequest) isVarSlice(_v interface{}) bool { return false } -func (v *V3CreateOrderRequest) GetSlugsMap() (map[string]string, error) { +func (g *GetOrderRequest) GetSlugsMap() (map[string]string, error) { slugs := map[string]string{} - params, err := v.GetSlugParameters() + params, err := g.GetSlugParameters() if err != nil { return slugs, nil } @@ -235,34 +236,34 @@ func (v *V3CreateOrderRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } -func (v *V3CreateOrderRequest) Do(ctx context.Context) (*Order, error) { +func (g *GetOrderRequest) Do(ctx context.Context) (*max.Order, error) { // empty params for GET operation var params interface{} - query, err := v.GetParametersQuery() + query, err := g.GetParametersQuery() if err != nil { return nil, err } apiURL := "/api/v3/wallet/:walletType/orders" - slugs, err := v.GetSlugsMap() + slugs, err := g.GetSlugsMap() if err != nil { return nil, err } - apiURL = v.applySlugsToUrl(apiURL, slugs) + apiURL = g.applySlugsToUrl(apiURL, slugs) - req, err := v.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) + req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) if err != nil { return nil, err } - response, err := v.client.SendRequest(req) + response, err := g.client.SendRequest(req) if err != nil { return nil, err } - var apiResponse Order + var apiResponse max.Order if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } diff --git a/pkg/exchange/max/maxapi/v3/order.go b/pkg/exchange/max/maxapi/v3/order.go new file mode 100644 index 000000000..3809274ab --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/order.go @@ -0,0 +1,84 @@ +package v3 + +//go:generate -command GetRequest requestgen -method GET +//go:generate -command PostRequest requestgen -method POST +//go:generate -command DeleteRequest requestgen -method DELETE + +import ( + "github.com/c9s/requestgen" + + maxapi "github.com/c9s/bbgo/pkg/exchange/max/maxapi" +) + +type Order = maxapi.Order + +// OrderService manages the Order endpoint. +type OrderService struct { + client *maxapi.RestClient +} + +func (s *OrderService) NewCreateOrderRequest() *CreateOrderRequest { + return &CreateOrderRequest{client: s.client} +} + +func (s *OrderService) NewGetOrderRequest() *GetOrderRequest { + return &GetOrderRequest{client: s.client} +} + +func (s *OrderService) NewOrderCancelAllRequest() *OrderCancelAllRequest { + return &OrderCancelAllRequest{client: s.client} +} + +func (s *OrderService) NewOrderCancelRequest() *OrderCancelRequest { + return &OrderCancelRequest{client: s.client} +} + +//go:generate PostRequest -url "/api/v3/wallet/:walletType/orders" -type CreateOrderRequest -responseType .Order -debug +type CreateOrderRequest struct { + client requestgen.AuthenticatedAPIClient + + walletType string `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 GetRequest -url "/api/v3/wallet/:walletType/orders" -type GetOrderRequest -responseType .Order +type GetOrderRequest struct { + client requestgen.AuthenticatedAPIClient + + walletType string `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 OrderCancelAllRequest -responseType []Order +type OrderCancelAllRequest struct { + client requestgen.AuthenticatedAPIClient + + walletType string `param:"walletType,slug,required"` + side *string `param:"side"` + market *string `param:"market"` + groupID *uint32 `param:"groupID"` +} + +//go:generate PostRequest -url "/api/v3/order" -type OrderCancelRequest -responseType .Order +type OrderCancelRequest struct { + client requestgen.AuthenticatedAPIClient + + id *uint64 `param:"id,omitempty"` + clientOrderID *string `param:"client_oid,omitempty"` +} diff --git a/pkg/exchange/max/maxapi/v3/order_cancel_all_request_requestgen.go b/pkg/exchange/max/maxapi/v3/order_cancel_all_request_requestgen.go new file mode 100644 index 000000000..ec13e9a5f --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/order_cancel_all_request_requestgen.go @@ -0,0 +1,199 @@ +// Code generated by "requestgen -method DELETE -url /api/v3/wallet/:walletType/orders -type OrderCancelAllRequest -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 (o *OrderCancelAllRequest) Side(side string) *OrderCancelAllRequest { + o.side = &side + return o +} + +func (o *OrderCancelAllRequest) Market(market string) *OrderCancelAllRequest { + o.market = &market + return o +} + +func (o *OrderCancelAllRequest) GroupID(groupID uint32) *OrderCancelAllRequest { + o.groupID = &groupID + return o +} + +func (o *OrderCancelAllRequest) WalletType(walletType string) *OrderCancelAllRequest { + o.walletType = walletType + return o +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (o *OrderCancelAllRequest) 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 (o *OrderCancelAllRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check side field -> json key side + if o.side != nil { + side := *o.side + + // assign parameter of side + params["side"] = side + } else { + } + // check market field -> json key market + if o.market != nil { + market := *o.market + + // assign parameter of market + params["market"] = market + } else { + } + // check groupID field -> json key groupID + if o.groupID != nil { + groupID := *o.groupID + + // assign parameter of groupID + params["groupID"] = groupID + } else { + } + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (o *OrderCancelAllRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := o.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if o.isVarSlice(_v) { + o.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 (o *OrderCancelAllRequest) GetParametersJSON() ([]byte, error) { + params, err := o.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 (o *OrderCancelAllRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check walletType field -> json key walletType + walletType := o.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 (o *OrderCancelAllRequest) 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 (o *OrderCancelAllRequest) 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 (o *OrderCancelAllRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (o *OrderCancelAllRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := o.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (o *OrderCancelAllRequest) Do(ctx context.Context) ([]max.Order, error) { + + params, err := o.GetParameters() + if err != nil { + return nil, err + } + query := url.Values{} + + apiURL := "/api/v3/wallet/:walletType/orders" + slugs, err := o.GetSlugsMap() + if err != nil { + return nil, err + } + + apiURL = o.applySlugsToUrl(apiURL, slugs) + + req, err := o.client.NewAuthenticatedRequest(ctx, "DELETE", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := o.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/order_cancel_request_requestgen.go b/pkg/exchange/max/maxapi/v3/order_cancel_request_requestgen.go new file mode 100644 index 000000000..ca6ad96fd --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/order_cancel_request_requestgen.go @@ -0,0 +1,164 @@ +// Code generated by "requestgen -method POST -url /api/v3/order -type OrderCancelRequest -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 (o *OrderCancelRequest) Id(id uint64) *OrderCancelRequest { + o.id = &id + return o +} + +func (o *OrderCancelRequest) ClientOrderID(clientOrderID string) *OrderCancelRequest { + o.clientOrderID = &clientOrderID + return o +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (o *OrderCancelRequest) 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 (o *OrderCancelRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check id field -> json key id + if o.id != nil { + id := *o.id + + // assign parameter of id + params["id"] = id + } else { + } + // check clientOrderID field -> json key client_oid + if o.clientOrderID != nil { + clientOrderID := *o.clientOrderID + + // assign parameter of clientOrderID + params["client_oid"] = clientOrderID + } else { + } + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (o *OrderCancelRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := o.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if o.isVarSlice(_v) { + o.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 (o *OrderCancelRequest) GetParametersJSON() ([]byte, error) { + params, err := o.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 (o *OrderCancelRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + + return params, nil +} + +func (o *OrderCancelRequest) 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 (o *OrderCancelRequest) 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 (o *OrderCancelRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (o *OrderCancelRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := o.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (o *OrderCancelRequest) Do(ctx context.Context) (*max.Order, error) { + + params, err := o.GetParameters() + if err != nil { + return nil, err + } + query := url.Values{} + + apiURL := "/api/v3/order" + + req, err := o.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := o.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 +} From 79893f4b8850aaa0f19685e1ba4d764aea58d737 Mon Sep 17 00:00:00 2001 From: c9s Date: Tue, 24 May 2022 17:48:08 +0800 Subject: [PATCH 03/24] define wallet type and separate wallet order api --- .../maxapi/v3/get_order_request_requestgen.go | 124 +------- pkg/exchange/max/maxapi/v3/order.go | 71 +++-- ...wallet_create_order_request_requestgen.go} | 122 ++++---- .../v3/wallet_get_order_request_requestgen.go | 271 ++++++++++++++++++ ...et_order_cancel_all_request_requestgen.go} | 80 +++--- 5 files changed, 426 insertions(+), 242 deletions(-) rename pkg/exchange/max/maxapi/v3/{create_order_request_requestgen.go => wallet_create_order_request_requestgen.go} (58%) create mode 100644 pkg/exchange/max/maxapi/v3/wallet_get_order_request_requestgen.go rename pkg/exchange/max/maxapi/v3/{order_cancel_all_request_requestgen.go => wallet_order_cancel_all_request_requestgen.go} (58%) diff --git a/pkg/exchange/max/maxapi/v3/get_order_request_requestgen.go b/pkg/exchange/max/maxapi/v3/get_order_request_requestgen.go index 60c18dea7..ae8c39e01 100644 --- a/pkg/exchange/max/maxapi/v3/get_order_request_requestgen.go +++ b/pkg/exchange/max/maxapi/v3/get_order_request_requestgen.go @@ -1,4 +1,4 @@ -// Code generated by "requestgen -method GET -url /api/v3/wallet/:walletType/orders -type GetOrderRequest -responseType .Order"; DO NOT EDIT. +// Code generated by "requestgen -method GET -url /api/v3/order -type GetOrderRequest -responseType .Order"; DO NOT EDIT. package v3 @@ -12,33 +12,8 @@ import ( "regexp" ) -func (g *GetOrderRequest) Market(market string) *GetOrderRequest { - g.market = market - return g -} - -func (g *GetOrderRequest) Side(side string) *GetOrderRequest { - g.side = side - return g -} - -func (g *GetOrderRequest) Volume(volume string) *GetOrderRequest { - g.volume = volume - return g -} - -func (g *GetOrderRequest) OrderType(orderType string) *GetOrderRequest { - g.orderType = orderType - return g -} - -func (g *GetOrderRequest) Price(price string) *GetOrderRequest { - g.price = &price - return g -} - -func (g *GetOrderRequest) StopPrice(stopPrice string) *GetOrderRequest { - g.stopPrice = &stopPrice +func (g *GetOrderRequest) Id(id uint64) *GetOrderRequest { + g.id = &id return g } @@ -47,16 +22,6 @@ func (g *GetOrderRequest) ClientOrderID(clientOrderID string) *GetOrderRequest { return g } -func (g *GetOrderRequest) GroupID(groupID string) *GetOrderRequest { - g.groupID = &groupID - return g -} - -func (g *GetOrderRequest) WalletType(walletType string) *GetOrderRequest { - g.walletType = walletType - return g -} - // GetQueryParameters builds and checks the query parameters and returns url.Values func (g *GetOrderRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} @@ -72,58 +37,12 @@ func (g *GetOrderRequest) GetQueryParameters() (url.Values, error) { // GetParameters builds and checks the parameters and return the result in a map object func (g *GetOrderRequest) GetParameters() (map[string]interface{}, error) { var params = map[string]interface{}{} - // check market field -> json key market - market := g.market + // check id field -> json key id + if g.id != nil { + id := *g.id - // 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 := g.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 := g.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 := g.orderType - - // assign parameter of orderType - params["ord_type"] = orderType - // check price field -> json key price - if g.price != nil { - price := *g.price - - // assign parameter of price - params["price"] = price - } else { - } - // check stopPrice field -> json key stop_price - if g.stopPrice != nil { - stopPrice := *g.stopPrice - - // assign parameter of stopPrice - params["stop_price"] = stopPrice + // assign parameter of id + params["id"] = id } else { } // check clientOrderID field -> json key client_oid @@ -134,14 +53,6 @@ func (g *GetOrderRequest) GetParameters() (map[string]interface{}, error) { params["client_oid"] = clientOrderID } else { } - // check groupID field -> json key group_id - if g.groupID != nil { - groupID := *g.groupID - - // assign parameter of groupID - params["group_id"] = groupID - } else { - } return params, nil } @@ -181,17 +92,6 @@ func (g *GetOrderRequest) GetParametersJSON() ([]byte, error) { // GetSlugParameters builds and checks the slug parameters and return the result in a map object func (g *GetOrderRequest) GetSlugParameters() (map[string]interface{}, error) { var params = map[string]interface{}{} - // check walletType field -> json key walletType - walletType := g.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 } @@ -245,13 +145,7 @@ func (g *GetOrderRequest) Do(ctx context.Context) (*max.Order, error) { return nil, err } - apiURL := "/api/v3/wallet/:walletType/orders" - slugs, err := g.GetSlugsMap() - if err != nil { - return nil, err - } - - apiURL = g.applySlugsToUrl(apiURL, slugs) + apiURL := "/api/v3/order" req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) if err != nil { diff --git a/pkg/exchange/max/maxapi/v3/order.go b/pkg/exchange/max/maxapi/v3/order.go index 3809274ab..9ebc8bebf 100644 --- a/pkg/exchange/max/maxapi/v3/order.go +++ b/pkg/exchange/max/maxapi/v3/order.go @@ -10,6 +10,13 @@ import ( maxapi "github.com/c9s/bbgo/pkg/exchange/max/maxapi" ) +type WalletType string + +const ( + WalletTypeSpot = WalletType("spot") + WalletTypeMargin = WalletType("m") +) + type Order = maxapi.Order // OrderService manages the Order endpoint. @@ -17,31 +24,35 @@ type OrderService struct { client *maxapi.RestClient } -func (s *OrderService) NewCreateOrderRequest() *CreateOrderRequest { - return &CreateOrderRequest{client: s.client} +func (s *OrderService) NewWalletCreateOrderRequest(walletType WalletType) *WalletCreateOrderRequest { + return &WalletCreateOrderRequest{client: s.client, walletType: walletType} } -func (s *OrderService) NewGetOrderRequest() *GetOrderRequest { - return &GetOrderRequest{client: s.client} +func (s *OrderService) NewWalletGetOrderRequest(walletType WalletType) *WalletGetOrderRequest { + return &WalletGetOrderRequest{client: s.client, walletType: walletType} } -func (s *OrderService) NewOrderCancelAllRequest() *OrderCancelAllRequest { - return &OrderCancelAllRequest{client: s.client} +func (s *OrderService) NewWalletOrderCancelAllRequest(walletType WalletType) *WalletOrderCancelAllRequest { + return &WalletOrderCancelAllRequest{client: s.client, walletType: walletType} } func (s *OrderService) NewOrderCancelRequest() *OrderCancelRequest { return &OrderCancelRequest{client: s.client} } -//go:generate PostRequest -url "/api/v3/wallet/:walletType/orders" -type CreateOrderRequest -responseType .Order -debug -type CreateOrderRequest struct { +func (s *OrderService) NewGetOrderRequest() *GetOrderRequest { + return &GetOrderRequest{client: s.client} +} + +//go:generate PostRequest -url "/api/v3/wallet/:walletType/orders" -type WalletCreateOrderRequest -responseType .Order -debug +type WalletCreateOrderRequest struct { client requestgen.AuthenticatedAPIClient - walletType string `param:"walletType,slug,required"` - market string `param:"market,required"` - side string `param:"side,required"` - volume string `param:"volume,required"` - orderType string `param:"ord_type"` + 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"` @@ -49,15 +60,15 @@ type CreateOrderRequest struct { groupID *string `param:"group_id"` } -//go:generate GetRequest -url "/api/v3/wallet/:walletType/orders" -type GetOrderRequest -responseType .Order -type GetOrderRequest struct { +//go:generate GetRequest -url "/api/v3/wallet/:walletType/orders" -type WalletGetOrderRequest -responseType .Order +type WalletGetOrderRequest struct { client requestgen.AuthenticatedAPIClient - walletType string `param:"walletType,slug,required"` - market string `param:"market,required"` - side string `param:"side,required"` - volume string `param:"volume,required"` - orderType string `param:"ord_type"` + 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"` @@ -65,14 +76,14 @@ type GetOrderRequest struct { groupID *string `param:"group_id"` } -//go:generate DeleteRequest -url "/api/v3/wallet/:walletType/orders" -type OrderCancelAllRequest -responseType []Order -type OrderCancelAllRequest struct { +//go:generate DeleteRequest -url "/api/v3/wallet/:walletType/orders" -type WalletOrderCancelAllRequest -responseType []Order +type WalletOrderCancelAllRequest struct { client requestgen.AuthenticatedAPIClient - walletType string `param:"walletType,slug,required"` - side *string `param:"side"` - market *string `param:"market"` - groupID *uint32 `param:"groupID"` + walletType WalletType `param:"walletType,slug,required"` + side *string `param:"side"` + market *string `param:"market"` + groupID *uint32 `param:"groupID"` } //go:generate PostRequest -url "/api/v3/order" -type OrderCancelRequest -responseType .Order @@ -82,3 +93,11 @@ type OrderCancelRequest struct { id *uint64 `param:"id,omitempty"` clientOrderID *string `param:"client_oid,omitempty"` } + +//go:generate GetRequest -url "/api/v3/order" -type GetOrderRequest -responseType .Order +type GetOrderRequest struct { + client requestgen.AuthenticatedAPIClient + + id *uint64 `param:"id,omitempty"` + clientOrderID *string `param:"client_oid,omitempty"` +} diff --git a/pkg/exchange/max/maxapi/v3/create_order_request_requestgen.go b/pkg/exchange/max/maxapi/v3/wallet_create_order_request_requestgen.go similarity index 58% rename from pkg/exchange/max/maxapi/v3/create_order_request_requestgen.go rename to pkg/exchange/max/maxapi/v3/wallet_create_order_request_requestgen.go index 4ab6bbfe8..b6d1535ca 100644 --- a/pkg/exchange/max/maxapi/v3/create_order_request_requestgen.go +++ b/pkg/exchange/max/maxapi/v3/wallet_create_order_request_requestgen.go @@ -1,4 +1,4 @@ -// Code generated by "requestgen -method POST -url /api/v3/wallet/:walletType/orders -type CreateOrderRequest -responseType .Order -debug"; DO NOT EDIT. +// Code generated by "requestgen -method POST -url /api/v3/wallet/:walletType/orders -type WalletCreateOrderRequest -responseType .Order -debug"; DO NOT EDIT. package v3 @@ -12,53 +12,53 @@ import ( "regexp" ) -func (c *CreateOrderRequest) Market(market string) *CreateOrderRequest { - c.market = market - return c +func (w *WalletCreateOrderRequest) Market(market string) *WalletCreateOrderRequest { + w.market = market + return w } -func (c *CreateOrderRequest) Side(side string) *CreateOrderRequest { - c.side = side - return c +func (w *WalletCreateOrderRequest) Side(side string) *WalletCreateOrderRequest { + w.side = side + return w } -func (c *CreateOrderRequest) Volume(volume string) *CreateOrderRequest { - c.volume = volume - return c +func (w *WalletCreateOrderRequest) Volume(volume string) *WalletCreateOrderRequest { + w.volume = volume + return w } -func (c *CreateOrderRequest) OrderType(orderType string) *CreateOrderRequest { - c.orderType = orderType - return c +func (w *WalletCreateOrderRequest) OrderType(orderType string) *WalletCreateOrderRequest { + w.orderType = orderType + return w } -func (c *CreateOrderRequest) Price(price string) *CreateOrderRequest { - c.price = &price - return c +func (w *WalletCreateOrderRequest) Price(price string) *WalletCreateOrderRequest { + w.price = &price + return w } -func (c *CreateOrderRequest) StopPrice(stopPrice string) *CreateOrderRequest { - c.stopPrice = &stopPrice - return c +func (w *WalletCreateOrderRequest) StopPrice(stopPrice string) *WalletCreateOrderRequest { + w.stopPrice = &stopPrice + return w } -func (c *CreateOrderRequest) ClientOrderID(clientOrderID string) *CreateOrderRequest { - c.clientOrderID = &clientOrderID - return c +func (w *WalletCreateOrderRequest) ClientOrderID(clientOrderID string) *WalletCreateOrderRequest { + w.clientOrderID = &clientOrderID + return w } -func (c *CreateOrderRequest) GroupID(groupID string) *CreateOrderRequest { - c.groupID = &groupID - return c +func (w *WalletCreateOrderRequest) GroupID(groupID string) *WalletCreateOrderRequest { + w.groupID = &groupID + return w } -func (c *CreateOrderRequest) WalletType(walletType string) *CreateOrderRequest { - c.walletType = walletType - return c +func (w *WalletCreateOrderRequest) WalletType(walletType WalletType) *WalletCreateOrderRequest { + w.walletType = walletType + return w } // GetQueryParameters builds and checks the query parameters and returns url.Values -func (c *CreateOrderRequest) GetQueryParameters() (url.Values, error) { +func (w *WalletCreateOrderRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} query := url.Values{} @@ -70,10 +70,10 @@ func (c *CreateOrderRequest) GetQueryParameters() (url.Values, error) { } // GetParameters builds and checks the parameters and return the result in a map object -func (c *CreateOrderRequest) GetParameters() (map[string]interface{}, error) { +func (w *WalletCreateOrderRequest) GetParameters() (map[string]interface{}, error) { var params = map[string]interface{}{} // check market field -> json key market - market := c.market + market := w.market // TEMPLATE check-required if len(market) == 0 { @@ -84,7 +84,7 @@ func (c *CreateOrderRequest) GetParameters() (map[string]interface{}, error) { // assign parameter of market params["market"] = market // check side field -> json key side - side := c.side + side := w.side // TEMPLATE check-required if len(side) == 0 { @@ -95,7 +95,7 @@ func (c *CreateOrderRequest) GetParameters() (map[string]interface{}, error) { // assign parameter of side params["side"] = side // check volume field -> json key volume - volume := c.volume + volume := w.volume // TEMPLATE check-required if len(volume) == 0 { @@ -106,37 +106,37 @@ func (c *CreateOrderRequest) GetParameters() (map[string]interface{}, error) { // assign parameter of volume params["volume"] = volume // check orderType field -> json key ord_type - orderType := c.orderType + orderType := w.orderType // assign parameter of orderType params["ord_type"] = orderType // check price field -> json key price - if c.price != nil { - price := *c.price + if w.price != nil { + price := *w.price // assign parameter of price params["price"] = price } else { } // check stopPrice field -> json key stop_price - if c.stopPrice != nil { - stopPrice := *c.stopPrice + if w.stopPrice != nil { + stopPrice := *w.stopPrice // assign parameter of stopPrice params["stop_price"] = stopPrice } else { } // check clientOrderID field -> json key client_oid - if c.clientOrderID != nil { - clientOrderID := *c.clientOrderID + if w.clientOrderID != nil { + clientOrderID := *w.clientOrderID // assign parameter of clientOrderID params["client_oid"] = clientOrderID } else { } // check groupID field -> json key group_id - if c.groupID != nil { - groupID := *c.groupID + if w.groupID != nil { + groupID := *w.groupID // assign parameter of groupID params["group_id"] = groupID @@ -147,17 +147,17 @@ func (c *CreateOrderRequest) GetParameters() (map[string]interface{}, error) { } // GetParametersQuery converts the parameters from GetParameters into the url.Values format -func (c *CreateOrderRequest) GetParametersQuery() (url.Values, error) { +func (w *WalletCreateOrderRequest) GetParametersQuery() (url.Values, error) { query := url.Values{} - params, err := c.GetParameters() + params, err := w.GetParameters() if err != nil { return query, err } for _k, _v := range params { - if c.isVarSlice(_v) { - c.iterateSlice(_v, func(it interface{}) { + if w.isVarSlice(_v) { + w.iterateSlice(_v, func(it interface{}) { query.Add(_k+"[]", fmt.Sprintf("%v", it)) }) } else { @@ -169,8 +169,8 @@ func (c *CreateOrderRequest) GetParametersQuery() (url.Values, error) { } // GetParametersJSON converts the parameters from GetParameters into the JSON format -func (c *CreateOrderRequest) GetParametersJSON() ([]byte, error) { - params, err := c.GetParameters() +func (w *WalletCreateOrderRequest) GetParametersJSON() ([]byte, error) { + params, err := w.GetParameters() if err != nil { return nil, err } @@ -179,10 +179,10 @@ func (c *CreateOrderRequest) GetParametersJSON() ([]byte, error) { } // GetSlugParameters builds and checks the slug parameters and return the result in a map object -func (c *CreateOrderRequest) GetSlugParameters() (map[string]interface{}, error) { +func (w *WalletCreateOrderRequest) GetSlugParameters() (map[string]interface{}, error) { var params = map[string]interface{}{} // check walletType field -> json key walletType - walletType := c.walletType + walletType := w.walletType // TEMPLATE check-required if len(walletType) == 0 { @@ -196,7 +196,7 @@ func (c *CreateOrderRequest) GetSlugParameters() (map[string]interface{}, error) return params, nil } -func (c *CreateOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string { +func (w *WalletCreateOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string { for _k, _v := range slugs { needleRE := regexp.MustCompile(":" + _k + "\\b") url = needleRE.ReplaceAllString(url, _v) @@ -205,7 +205,7 @@ func (c *CreateOrderRequest) applySlugsToUrl(url string, slugs map[string]string return url } -func (c *CreateOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) { +func (w *WalletCreateOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) { sliceValue := reflect.ValueOf(slice) for _i := 0; _i < sliceValue.Len(); _i++ { it := sliceValue.Index(_i).Interface() @@ -213,7 +213,7 @@ func (c *CreateOrderRequest) iterateSlice(slice interface{}, _f func(it interfac } } -func (c *CreateOrderRequest) isVarSlice(_v interface{}) bool { +func (w *WalletCreateOrderRequest) isVarSlice(_v interface{}) bool { rt := reflect.TypeOf(_v) switch rt.Kind() { case reflect.Slice: @@ -222,9 +222,9 @@ func (c *CreateOrderRequest) isVarSlice(_v interface{}) bool { return false } -func (c *CreateOrderRequest) GetSlugsMap() (map[string]string, error) { +func (w *WalletCreateOrderRequest) GetSlugsMap() (map[string]string, error) { slugs := map[string]string{} - params, err := c.GetSlugParameters() + params, err := w.GetSlugParameters() if err != nil { return slugs, nil } @@ -236,28 +236,28 @@ func (c *CreateOrderRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } -func (c *CreateOrderRequest) Do(ctx context.Context) (*max.Order, error) { +func (w *WalletCreateOrderRequest) Do(ctx context.Context) (*max.Order, error) { - params, err := c.GetParameters() + params, err := w.GetParameters() if err != nil { return nil, err } query := url.Values{} apiURL := "/api/v3/wallet/:walletType/orders" - slugs, err := c.GetSlugsMap() + slugs, err := w.GetSlugsMap() if err != nil { return nil, err } - apiURL = c.applySlugsToUrl(apiURL, slugs) + apiURL = w.applySlugsToUrl(apiURL, slugs) - req, err := c.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params) + req, err := w.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params) if err != nil { return nil, err } - response, err := c.client.SendRequest(req) + response, err := w.client.SendRequest(req) if err != nil { return nil, err } 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 new file mode 100644 index 000000000..71c501206 --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/wallet_get_order_request_requestgen.go @@ -0,0 +1,271 @@ +// 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 + + // 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/order_cancel_all_request_requestgen.go b/pkg/exchange/max/maxapi/v3/wallet_order_cancel_all_request_requestgen.go similarity index 58% rename from pkg/exchange/max/maxapi/v3/order_cancel_all_request_requestgen.go rename to pkg/exchange/max/maxapi/v3/wallet_order_cancel_all_request_requestgen.go index ec13e9a5f..373320a4c 100644 --- a/pkg/exchange/max/maxapi/v3/order_cancel_all_request_requestgen.go +++ b/pkg/exchange/max/maxapi/v3/wallet_order_cancel_all_request_requestgen.go @@ -1,4 +1,4 @@ -// Code generated by "requestgen -method DELETE -url /api/v3/wallet/:walletType/orders -type OrderCancelAllRequest -responseType []Order"; DO NOT EDIT. +// Code generated by "requestgen -method DELETE -url /api/v3/wallet/:walletType/orders -type WalletOrderCancelAllRequest -responseType []Order"; DO NOT EDIT. package v3 @@ -12,28 +12,28 @@ import ( "regexp" ) -func (o *OrderCancelAllRequest) Side(side string) *OrderCancelAllRequest { - o.side = &side - return o +func (w *WalletOrderCancelAllRequest) Side(side string) *WalletOrderCancelAllRequest { + w.side = &side + return w } -func (o *OrderCancelAllRequest) Market(market string) *OrderCancelAllRequest { - o.market = &market - return o +func (w *WalletOrderCancelAllRequest) Market(market string) *WalletOrderCancelAllRequest { + w.market = &market + return w } -func (o *OrderCancelAllRequest) GroupID(groupID uint32) *OrderCancelAllRequest { - o.groupID = &groupID - return o +func (w *WalletOrderCancelAllRequest) GroupID(groupID uint32) *WalletOrderCancelAllRequest { + w.groupID = &groupID + return w } -func (o *OrderCancelAllRequest) WalletType(walletType string) *OrderCancelAllRequest { - o.walletType = walletType - return o +func (w *WalletOrderCancelAllRequest) WalletType(walletType WalletType) *WalletOrderCancelAllRequest { + w.walletType = walletType + return w } // GetQueryParameters builds and checks the query parameters and returns url.Values -func (o *OrderCancelAllRequest) GetQueryParameters() (url.Values, error) { +func (w *WalletOrderCancelAllRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} query := url.Values{} @@ -45,27 +45,27 @@ func (o *OrderCancelAllRequest) GetQueryParameters() (url.Values, error) { } // GetParameters builds and checks the parameters and return the result in a map object -func (o *OrderCancelAllRequest) GetParameters() (map[string]interface{}, error) { +func (w *WalletOrderCancelAllRequest) GetParameters() (map[string]interface{}, error) { var params = map[string]interface{}{} // check side field -> json key side - if o.side != nil { - side := *o.side + if w.side != nil { + side := *w.side // assign parameter of side params["side"] = side } else { } // check market field -> json key market - if o.market != nil { - market := *o.market + if w.market != nil { + market := *w.market // assign parameter of market params["market"] = market } else { } // check groupID field -> json key groupID - if o.groupID != nil { - groupID := *o.groupID + if w.groupID != nil { + groupID := *w.groupID // assign parameter of groupID params["groupID"] = groupID @@ -76,17 +76,17 @@ func (o *OrderCancelAllRequest) GetParameters() (map[string]interface{}, error) } // GetParametersQuery converts the parameters from GetParameters into the url.Values format -func (o *OrderCancelAllRequest) GetParametersQuery() (url.Values, error) { +func (w *WalletOrderCancelAllRequest) GetParametersQuery() (url.Values, error) { query := url.Values{} - params, err := o.GetParameters() + params, err := w.GetParameters() if err != nil { return query, err } for _k, _v := range params { - if o.isVarSlice(_v) { - o.iterateSlice(_v, func(it interface{}) { + if w.isVarSlice(_v) { + w.iterateSlice(_v, func(it interface{}) { query.Add(_k+"[]", fmt.Sprintf("%v", it)) }) } else { @@ -98,8 +98,8 @@ func (o *OrderCancelAllRequest) GetParametersQuery() (url.Values, error) { } // GetParametersJSON converts the parameters from GetParameters into the JSON format -func (o *OrderCancelAllRequest) GetParametersJSON() ([]byte, error) { - params, err := o.GetParameters() +func (w *WalletOrderCancelAllRequest) GetParametersJSON() ([]byte, error) { + params, err := w.GetParameters() if err != nil { return nil, err } @@ -108,10 +108,10 @@ func (o *OrderCancelAllRequest) GetParametersJSON() ([]byte, error) { } // GetSlugParameters builds and checks the slug parameters and return the result in a map object -func (o *OrderCancelAllRequest) GetSlugParameters() (map[string]interface{}, error) { +func (w *WalletOrderCancelAllRequest) GetSlugParameters() (map[string]interface{}, error) { var params = map[string]interface{}{} // check walletType field -> json key walletType - walletType := o.walletType + walletType := w.walletType // TEMPLATE check-required if len(walletType) == 0 { @@ -125,7 +125,7 @@ func (o *OrderCancelAllRequest) GetSlugParameters() (map[string]interface{}, err return params, nil } -func (o *OrderCancelAllRequest) applySlugsToUrl(url string, slugs map[string]string) string { +func (w *WalletOrderCancelAllRequest) applySlugsToUrl(url string, slugs map[string]string) string { for _k, _v := range slugs { needleRE := regexp.MustCompile(":" + _k + "\\b") url = needleRE.ReplaceAllString(url, _v) @@ -134,7 +134,7 @@ func (o *OrderCancelAllRequest) applySlugsToUrl(url string, slugs map[string]str return url } -func (o *OrderCancelAllRequest) iterateSlice(slice interface{}, _f func(it interface{})) { +func (w *WalletOrderCancelAllRequest) iterateSlice(slice interface{}, _f func(it interface{})) { sliceValue := reflect.ValueOf(slice) for _i := 0; _i < sliceValue.Len(); _i++ { it := sliceValue.Index(_i).Interface() @@ -142,7 +142,7 @@ func (o *OrderCancelAllRequest) iterateSlice(slice interface{}, _f func(it inter } } -func (o *OrderCancelAllRequest) isVarSlice(_v interface{}) bool { +func (w *WalletOrderCancelAllRequest) isVarSlice(_v interface{}) bool { rt := reflect.TypeOf(_v) switch rt.Kind() { case reflect.Slice: @@ -151,9 +151,9 @@ func (o *OrderCancelAllRequest) isVarSlice(_v interface{}) bool { return false } -func (o *OrderCancelAllRequest) GetSlugsMap() (map[string]string, error) { +func (w *WalletOrderCancelAllRequest) GetSlugsMap() (map[string]string, error) { slugs := map[string]string{} - params, err := o.GetSlugParameters() + params, err := w.GetSlugParameters() if err != nil { return slugs, nil } @@ -165,28 +165,28 @@ func (o *OrderCancelAllRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } -func (o *OrderCancelAllRequest) Do(ctx context.Context) ([]max.Order, error) { +func (w *WalletOrderCancelAllRequest) Do(ctx context.Context) ([]max.Order, error) { - params, err := o.GetParameters() + params, err := w.GetParameters() if err != nil { return nil, err } query := url.Values{} apiURL := "/api/v3/wallet/:walletType/orders" - slugs, err := o.GetSlugsMap() + slugs, err := w.GetSlugsMap() if err != nil { return nil, err } - apiURL = o.applySlugsToUrl(apiURL, slugs) + apiURL = w.applySlugsToUrl(apiURL, slugs) - req, err := o.client.NewAuthenticatedRequest(ctx, "DELETE", apiURL, query, params) + req, err := w.client.NewAuthenticatedRequest(ctx, "DELETE", apiURL, query, params) if err != nil { return nil, err } - response, err := o.client.SendRequest(req) + response, err := w.client.SendRequest(req) if err != nil { return nil, err } From 9d459612a42751789fc0f22988c9fe1507736ad3 Mon Sep 17 00:00:00 2001 From: c9s Date: Tue, 24 May 2022 18:00:52 +0800 Subject: [PATCH 04/24] maxapi: add wallet type validation --- pkg/exchange/max/maxapi/account.go | 1 + pkg/exchange/max/maxapi/v3/order.go | 4 ++-- .../v3/wallet_create_order_request_requestgen.go | 11 +++++++++++ .../maxapi/v3/wallet_get_order_request_requestgen.go | 11 +++++++++++ .../v3/wallet_order_cancel_all_request_requestgen.go | 11 +++++++++++ 5 files changed, 36 insertions(+), 2 deletions(-) diff --git a/pkg/exchange/max/maxapi/account.go b/pkg/exchange/max/maxapi/account.go index b1c4d4d13..51e12ceab 100644 --- a/pkg/exchange/max/maxapi/account.go +++ b/pkg/exchange/max/maxapi/account.go @@ -2,6 +2,7 @@ package max //go:generate -command GetRequest requestgen -method GET //go:generate -command PostRequest requestgen -method POST +//go:generate -command DeleteRequest requestgen -method DELETE import ( "github.com/c9s/requestgen" diff --git a/pkg/exchange/max/maxapi/v3/order.go b/pkg/exchange/max/maxapi/v3/order.go index 9ebc8bebf..ddcbc7217 100644 --- a/pkg/exchange/max/maxapi/v3/order.go +++ b/pkg/exchange/max/maxapi/v3/order.go @@ -13,8 +13,8 @@ import ( type WalletType string const ( - WalletTypeSpot = WalletType("spot") - WalletTypeMargin = WalletType("m") + WalletTypeSpot WalletType = "spot" + WalletTypeMargin WalletType = "m" ) type Order = maxapi.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 b6d1535ca..477c8ea9e 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 @@ -190,6 +190,17 @@ 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_order_request_requestgen.go b/pkg/exchange/max/maxapi/v3/wallet_get_order_request_requestgen.go index 71c501206..181dae703 100644 --- a/pkg/exchange/max/maxapi/v3/wallet_get_order_request_requestgen.go +++ b/pkg/exchange/max/maxapi/v3/wallet_get_order_request_requestgen.go @@ -190,6 +190,17 @@ func (w *WalletGetOrderRequest) GetSlugParameters() (map[string]interface{}, err } // 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_order_cancel_all_request_requestgen.go b/pkg/exchange/max/maxapi/v3/wallet_order_cancel_all_request_requestgen.go index 373320a4c..8f7e071be 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 @@ -119,6 +119,17 @@ 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 From 680231e0c570421c9e4439f153b9d1431407c187 Mon Sep 17 00:00:00 2001 From: c9s Date: Tue, 24 May 2022 18:04:33 +0800 Subject: [PATCH 05/24] max: drop legacy queryAllClosedOrders method --- pkg/exchange/max/exchange.go | 57 ------------------------------------ 1 file changed, 57 deletions(-) diff --git a/pkg/exchange/max/exchange.go b/pkg/exchange/max/exchange.go index a5a615090..73aa4e9c9 100644 --- a/pkg/exchange/max/exchange.go +++ b/pkg/exchange/max/exchange.go @@ -317,63 +317,6 @@ queryRecentlyClosedOrders: return orders, err } -func (e *Exchange) queryAllClosedOrders(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) - page := 1 - for { - if err := closedOrderQueryLimiter.Wait(ctx); err != nil { - return nil, err - } - - log.Infof("querying %s closed orders from page %d ~ ", symbol, page) - maxOrders, err := e.client.OrderService.Closed(toLocalSymbol(symbol), maxapi.QueryOrderOptions{ - Limit: limit, - Page: page, - }) - if err != nil { - return orders, err - } - - if len(maxOrders) == 0 { - return orders, err - } - - // ensure everything is ascending ordered - sort.Slice(maxOrders, func(i, j int) bool { - return maxOrders[i].CreatedAtMs.Time().Before(maxOrders[j].CreatedAtMs.Time()) - }) - - log.Debugf("%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()) - continue - } - - if maxOrder.CreatedAtMs.Time().After(until) { - return orders, err - } - - order, err := toGlobalOrder(maxOrder) - if err != nil { - return orders, err - } - - if _, ok := orderIDs[order.OrderID]; ok { - log.Debugf("skipping duplicated order: %d", order.OrderID) - } - - orderIDs[order.OrderID] = struct{}{} - orders = append(orders, *order) - log.Debugf("order %+v", order) - } - page++ - } - - return orders, err -} - func (e *Exchange) CancelAllOrders(ctx context.Context) ([]types.Order, error) { var req = e.client.OrderService.NewOrderCancelAllRequest() var maxOrders, err = req.Do(ctx) From 0ee23e0ce4fd6d197d5289da024cdc257e60a398 Mon Sep 17 00:00:00 2001 From: c9s Date: Tue, 24 May 2022 18:07:34 +0800 Subject: [PATCH 06/24] max: refactor order sort method into the types package --- pkg/exchange/max/exchange.go | 7 +------ pkg/types/sort.go | 7 +++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pkg/exchange/max/exchange.go b/pkg/exchange/max/exchange.go index 73aa4e9c9..20c69513b 100644 --- a/pkg/exchange/max/exchange.go +++ b/pkg/exchange/max/exchange.go @@ -309,12 +309,7 @@ queryRecentlyClosedOrders: } // ensure everything is ascending ordered - log.Debugf("sorting %d orders", len(orders)) - sort.Slice(orders, func(i, j int) bool { - return orders[i].CreationTime.Time().Before(orders[j].CreationTime.Time()) - }) - - return orders, err + return types.SortOrderAscending(orders), err } func (e *Exchange) CancelAllOrders(ctx context.Context) ([]types.Order, error) { diff --git a/pkg/types/sort.go b/pkg/types/sort.go index 3da34dc7c..d72b76d0e 100644 --- a/pkg/types/sort.go +++ b/pkg/types/sort.go @@ -11,3 +11,10 @@ func SortTradesAscending(trades []Trade) []Trade { }) return trades } + +func SortOrderAscending(orders []Order) []Order { + sort.Slice(orders, func(i, j int) bool { + return orders[i].CreationTime.Time().Before(orders[j].CreationTime.Time()) + }) + return orders +} From eccee460ca6816dd32036b3f5f71978d814a3129 Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 25 May 2022 13:51:24 +0800 Subject: [PATCH 07/24] max: add filters field to the auth message --- pkg/exchange/max/maxapi/auth.go | 11 ++++++----- pkg/exchange/max/maxapi/websocket.go | 2 -- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/pkg/exchange/max/maxapi/auth.go b/pkg/exchange/max/maxapi/auth.go index c353c56dd..15629dca8 100644 --- a/pkg/exchange/max/maxapi/auth.go +++ b/pkg/exchange/max/maxapi/auth.go @@ -1,11 +1,12 @@ package max type AuthMessage struct { - Action string `json:"action"` - APIKey string `json:"apiKey"` - Nonce int64 `json:"nonce"` - Signature string `json:"signature"` - ID string `json:"id"` + Action string `json:"action,omitempty"` + APIKey string `json:"apiKey,omitempty"` + Nonce int64 `json:"nonce,omitempty"` + Signature string `json:"signature,omitempty"` + ID string `json:"id,omitempty"` + Filters []string `json:"filters,omitempty"` } type AuthEvent struct { diff --git a/pkg/exchange/max/maxapi/websocket.go b/pkg/exchange/max/maxapi/websocket.go index 1008138c4..c0af3c597 100644 --- a/pkg/exchange/max/maxapi/websocket.go +++ b/pkg/exchange/max/maxapi/websocket.go @@ -29,5 +29,3 @@ type WebsocketCommand struct { Subscriptions []Subscription `json:"subscriptions,omitempty"` } -var SubscribeAction = "subscribe" -var UnsubscribeAction = "unsubscribe" From e5e505d65e2fdbac99c449420782a558bebddb59 Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 25 May 2022 14:38:09 +0800 Subject: [PATCH 08/24] max: apply margin settings struct --- pkg/exchange/max/exchange.go | 6 +++++- pkg/exchange/max/stream.go | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/exchange/max/exchange.go b/pkg/exchange/max/exchange.go index 20c69513b..2a400a762 100644 --- a/pkg/exchange/max/exchange.go +++ b/pkg/exchange/max/exchange.go @@ -29,6 +29,8 @@ var marketDataLimiter = rate.NewLimiter(rate.Every(2*time.Second), 10) var log = logrus.WithField("exchange", "max") type Exchange struct { + types.MarginSettings + client *maxapi.RestClient key, secret string } @@ -155,7 +157,9 @@ func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) { } func (e *Exchange) NewStream() types.Stream { - return NewStream(e.key, e.secret) + stream := NewStream(e.key, e.secret) + stream.MarginSettings = e.MarginSettings + return stream } func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.Order, error) { diff --git a/pkg/exchange/max/stream.go b/pkg/exchange/max/stream.go index d6d1e646c..dad1ae2ae 100644 --- a/pkg/exchange/max/stream.go +++ b/pkg/exchange/max/stream.go @@ -18,6 +18,7 @@ import ( //go:generate callbackgen -type Stream type Stream struct { types.StandardStream + types.MarginSettings key, secret string From 9f0d975b57cffa2f204f546bfe559cba48e75b4c Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 25 May 2022 14:40:43 +0800 Subject: [PATCH 09/24] max: add filters when margin is on --- pkg/exchange/max/stream.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pkg/exchange/max/stream.go b/pkg/exchange/max/stream.go index dad1ae2ae..1ac320908 100644 --- a/pkg/exchange/max/stream.go +++ b/pkg/exchange/max/stream.go @@ -97,8 +97,22 @@ func (s *Stream) handleConnect() { }) } - s.Conn.WriteJSON(cmd) + if err := s.Conn.WriteJSON(cmd); err != nil { + log.WithError(err).Error("failed to send subscription request") + } + } else { + var filters []string + if s.MarginSettings.IsMargin { + filters = []string{ + "mwallet_order", + "mwallet_trade", + "mwallet_account", + "ad_ratio", + "borrowing", + } + } + nonce := time.Now().UnixNano() / int64(time.Millisecond) auth := &max.AuthMessage{ Action: "auth", @@ -106,7 +120,9 @@ func (s *Stream) handleConnect() { Nonce: nonce, Signature: signPayload(fmt.Sprintf("%d", nonce), s.secret), ID: uuid.New().String(), + Filters: filters, } + if err := s.Conn.WriteJSON(auth); err != nil { log.WithError(err).Error("failed to send auth request") } From f65821d4fd7f9a48664ca3a70ab383530ce552f7 Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 25 May 2022 14:42:45 +0800 Subject: [PATCH 10/24] max: add mwallet message type to parser --- pkg/exchange/max/maxapi/userdata.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/exchange/max/maxapi/userdata.go b/pkg/exchange/max/maxapi/userdata.go index b2ade6600..a07c2fb77 100644 --- a/pkg/exchange/max/maxapi/userdata.go +++ b/pkg/exchange/max/maxapi/userdata.go @@ -201,19 +201,19 @@ func parseAuthEvent(v *fastjson.Value) (*AuthEvent, error) { func ParseUserEvent(v *fastjson.Value) (interface{}, error) { eventType := string(v.GetStringBytes("e")) switch eventType { - case "order_snapshot": + case "order_snapshot", "mwallet_order_snapshot": return parserOrderSnapshotEvent(v), nil - case "order_update": + case "order_update", "mwallet_order_update": return parseOrderUpdateEvent(v), nil - case "trade_snapshot": + case "trade_snapshot", "mwallet_trade_snapshot": return parseTradeSnapshotEvent(v), nil - case "trade_update": + case "trade_update", "mwallet_trade_update": return parseTradeUpdateEvent(v), nil - case "account_snapshot", "account_update": + case "account_snapshot", "account_update", "mwallet_account_snapshot", "mwallet_account_update": var e AccountUpdateEvent o := v.String() err := json.Unmarshal([]byte(o), &e) From 83abf14f3bb18cc5d721e84c57879145f09c77d0 Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 25 May 2022 19:52:29 +0800 Subject: [PATCH 11/24] max: add updateTime field parse --- pkg/exchange/max/maxapi/userdata.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/exchange/max/maxapi/userdata.go b/pkg/exchange/max/maxapi/userdata.go index a07c2fb77..78a58412f 100644 --- a/pkg/exchange/max/maxapi/userdata.go +++ b/pkg/exchange/max/maxapi/userdata.go @@ -38,6 +38,7 @@ type OrderUpdate struct { GroupID uint32 `json:"gi"` ClientOID string `json:"ci"` CreatedAtMs int64 `json:"T"` + UpdateTime int64 `json:"TU"` } type OrderUpdateEvent struct { @@ -64,6 +65,7 @@ func parserOrderUpdate(v *fastjson.Value) OrderUpdate { GroupID: uint32(v.GetInt("gi")), ClientOID: string(v.GetStringBytes("ci")), CreatedAtMs: v.GetInt64("T"), + UpdateTime: v.GetInt64("TU"), } } @@ -109,6 +111,7 @@ type TradeUpdate struct { Fee string `json:"f"` FeeCurrency string `json:"fc"` Timestamp int64 `json:"T"` + UpdateTime int64 `json:"TU"` OrderID uint64 `json:"oi"` @@ -125,6 +128,7 @@ func parseTradeUpdate(v *fastjson.Value) TradeUpdate { Fee: string(v.GetStringBytes("f")), FeeCurrency: string(v.GetStringBytes("fc")), Timestamp: v.GetInt64("T"), + UpdateTime: v.GetInt64("TU"), OrderID: v.GetUint64("oi"), Maker: v.GetBool("m"), } From a74ad31ea028793a200871e5de32a3f0e02c6107 Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 25 May 2022 20:06:17 +0800 Subject: [PATCH 12/24] max: parse ADRatio message --- pkg/exchange/max/maxapi/userdata.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/pkg/exchange/max/maxapi/userdata.go b/pkg/exchange/max/maxapi/userdata.go index 78a58412f..e4ec53cac 100644 --- a/pkg/exchange/max/maxapi/userdata.go +++ b/pkg/exchange/max/maxapi/userdata.go @@ -202,6 +202,27 @@ func parseAuthEvent(v *fastjson.Value) (*AuthEvent, error) { return &e, err } +type ADRatio struct { + ADRatio fixedpoint.Value `json:"ad"` + AssetInUSDT fixedpoint.Value `json:"as"` + DebtInUSDT fixedpoint.Value `json:"db"` + IndexPrices []struct { + Market string `json:"M"` + Price fixedpoint.Value `json:"p"` + } `json:"idxp"` + TU types.MillisecondTimestamp `json:"TU"` +} + +func parseADRatio(v *fastjson.Value) (*ADRatio, error) { + o, err := v.StringBytes() + if err != nil { + return nil, err + } + adRatio := ADRatio{} + err = json.Unmarshal(o, &adRatio) + return &adRatio, err +} + func ParseUserEvent(v *fastjson.Value) (interface{}, error) { eventType := string(v.GetStringBytes("e")) switch eventType { @@ -217,6 +238,9 @@ func ParseUserEvent(v *fastjson.Value) (interface{}, error) { case "trade_update", "mwallet_trade_update": return parseTradeUpdateEvent(v), nil + case "ad_ratio_snapshot": + return parseADRatio(v) + case "account_snapshot", "account_update", "mwallet_account_snapshot", "mwallet_account_update": var e AccountUpdateEvent o := v.String() From 2ffbb2ed82eec5645e5f49c3a1d79c263285448e Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 25 May 2022 20:06:51 +0800 Subject: [PATCH 13/24] max: add ad_ratio_update type --- pkg/exchange/max/maxapi/userdata.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/exchange/max/maxapi/userdata.go b/pkg/exchange/max/maxapi/userdata.go index e4ec53cac..9e804df24 100644 --- a/pkg/exchange/max/maxapi/userdata.go +++ b/pkg/exchange/max/maxapi/userdata.go @@ -238,7 +238,7 @@ func ParseUserEvent(v *fastjson.Value) (interface{}, error) { case "trade_update", "mwallet_trade_update": return parseTradeUpdateEvent(v), nil - case "ad_ratio_snapshot": + case "ad_ratio_snapshot", "ad_ratio_update": return parseADRatio(v) case "account_snapshot", "account_update", "mwallet_account_snapshot", "mwallet_account_update": From 459d839c1a2a79957fe11ca4b9a4cec110d361a2 Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 25 May 2022 20:12:16 +0800 Subject: [PATCH 14/24] max: parse debt --- pkg/exchange/max/maxapi/userdata.go | 38 ++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/pkg/exchange/max/maxapi/userdata.go b/pkg/exchange/max/maxapi/userdata.go index 9e804df24..6c90d1413 100644 --- a/pkg/exchange/max/maxapi/userdata.go +++ b/pkg/exchange/max/maxapi/userdata.go @@ -218,9 +218,32 @@ func parseADRatio(v *fastjson.Value) (*ADRatio, error) { if err != nil { return nil, err } - adRatio := ADRatio{} + + adRatio := struct { + ADRatio ADRatio `json:"ad"` + }{} err = json.Unmarshal(o, &adRatio) - return &adRatio, err + return &adRatio.ADRatio, err +} + +type Debt struct { + Currency string `json:"cu"` + DebtPrincipal fixedpoint.Value `json:"dbp"` + DebtInterest fixedpoint.Value `json:"dbi"` + TU types.MillisecondTimestamp `json:"TU"` +} + +func parseDebts(v *fastjson.Value) ([]Debt, error) { + o, err := v.StringBytes() + if err != nil { + return nil, err + } + + m := struct { + Debts []Debt `json:"db"` + }{} + err = json.Unmarshal(o, &m) + return m.Debts, err } func ParseUserEvent(v *fastjson.Value) (interface{}, error) { @@ -241,10 +264,17 @@ func ParseUserEvent(v *fastjson.Value) (interface{}, error) { case "ad_ratio_snapshot", "ad_ratio_update": return parseADRatio(v) + case "borrowing_snapshot", "borrowing_update": + return parseDebts(v) + case "account_snapshot", "account_update", "mwallet_account_snapshot", "mwallet_account_update": var e AccountUpdateEvent - o := v.String() - err := json.Unmarshal([]byte(o), &e) + o, err := v.StringBytes() + if err != nil { + return nil, err + } + + err = json.Unmarshal(o, &e) return &e, err case "error": From 4d8ea7d9799f05734c7acfb44f0cdcb2212c7398 Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 25 May 2022 20:34:25 +0800 Subject: [PATCH 15/24] max: log adratio --- config/binance-margin.yaml | 15 ++++++++ config/max-margin.yaml | 13 +++++++ pkg/exchange/max/maxapi/public.go | 28 +++++---------- pkg/exchange/max/maxapi/userdata.go | 51 +++++++++++++--------------- pkg/exchange/max/stream.go | 8 +++-- pkg/exchange/max/stream_callbacks.go | 20 +++++++++++ 6 files changed, 86 insertions(+), 49 deletions(-) create mode 100644 config/binance-margin.yaml create mode 100644 config/max-margin.yaml diff --git a/config/binance-margin.yaml b/config/binance-margin.yaml new file mode 100644 index 000000000..169f2e58f --- /dev/null +++ b/config/binance-margin.yaml @@ -0,0 +1,15 @@ +--- +sessions: + binance_margin_linkusdt: + exchange: binance + margin: true + isolatedMargin: true + isolatedMarginSymbol: LINKUSDT + +exchangeStrategies: + +- on: binance_margin_linkusdt + dummy: + symbol: LINKUSDT + interval: 1m + diff --git a/config/max-margin.yaml b/config/max-margin.yaml new file mode 100644 index 000000000..1ce868952 --- /dev/null +++ b/config/max-margin.yaml @@ -0,0 +1,13 @@ +--- +sessions: + max_margin: + exchange: max + margin: true + +exchangeStrategies: + +- on: max_margin + pricealert: + symbol: LINKUSDT + interval: 1m + diff --git a/pkg/exchange/max/maxapi/public.go b/pkg/exchange/max/maxapi/public.go index 6b228a8bc..20b03535f 100644 --- a/pkg/exchange/max/maxapi/public.go +++ b/pkg/exchange/max/maxapi/public.go @@ -3,7 +3,6 @@ package max import ( "context" "fmt" - "io/ioutil" "net/url" "strconv" "strings" @@ -21,12 +20,12 @@ type PublicService struct { } type Market struct { - ID string `json:"id"` - Name string `json:"name"` - BaseUnit string `json:"base_unit"` - BaseUnitPrecision int `json:"base_unit_precision"` - QuoteUnit string `json:"quote_unit"` - QuoteUnitPrecision int `json:"quote_unit_precision"` + ID string `json:"id"` + Name string `json:"name"` + BaseUnit string `json:"base_unit"` + BaseUnitPrecision int `json:"base_unit_precision"` + QuoteUnit string `json:"quote_unit"` + QuoteUnitPrecision int `json:"quote_unit_precision"` MinBaseAmount fixedpoint.Value `json:"min_base_amount"` MinQuoteAmount fixedpoint.Value `json:"min_quote_amount"` } @@ -256,23 +255,12 @@ func (s *PublicService) KLines(symbol string, resolution string, start time.Time return nil, fmt.Errorf("request build error: %s", err.Error()) } - resp, err := s.client.Do(req) + resp, err := s.client.SendRequest(req) if err != nil { return nil, fmt.Errorf("request failed: %s", err.Error()) } - defer func() { - if err := resp.Body.Close(); err != nil { - logger.WithError(err).Error("failed to close resp body") - } - }() - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - return parseKLines(body, symbol, resolution, interval) + return parseKLines(resp.Body, symbol, resolution, interval) } func parseKLines(payload []byte, symbol, resolution string, interval Interval) (klines []KLine, err error) { diff --git a/pkg/exchange/max/maxapi/userdata.go b/pkg/exchange/max/maxapi/userdata.go index 6c90d1413..2c9501edd 100644 --- a/pkg/exchange/max/maxapi/userdata.go +++ b/pkg/exchange/max/maxapi/userdata.go @@ -2,6 +2,7 @@ package max import ( "encoding/json" + "fmt" "strings" "github.com/pkg/errors" @@ -213,17 +214,19 @@ type ADRatio struct { TU types.MillisecondTimestamp `json:"TU"` } -func parseADRatio(v *fastjson.Value) (*ADRatio, error) { - o, err := v.StringBytes() - if err != nil { - return nil, err - } +func (r *ADRatio) String() string { + return fmt.Sprintf("ADRatio: %v Asset: %v USDT, Debt: %v USDT (Mark Prices: %+v)", r.ADRatio, r.AssetInUSDT, r.DebtInUSDT, r.IndexPrices) +} - adRatio := struct { - ADRatio ADRatio `json:"ad"` - }{} - err = json.Unmarshal(o, &adRatio) - return &adRatio.ADRatio, err +type ADRatioEvent struct { + ADRatio ADRatio `json:"ad"` +} + +func parseADRatioEvent(v *fastjson.Value) (*ADRatioEvent, error) { + o := v.String() + e := ADRatioEvent{} + err := json.Unmarshal([]byte(o), &e) + return &e, err } type Debt struct { @@ -233,17 +236,15 @@ type Debt struct { TU types.MillisecondTimestamp `json:"TU"` } -func parseDebts(v *fastjson.Value) ([]Debt, error) { - o, err := v.StringBytes() - if err != nil { - return nil, err - } +type DebtEvent struct { + Debts []Debt `json:"db"` +} - m := struct { - Debts []Debt `json:"db"` - }{} - err = json.Unmarshal(o, &m) - return m.Debts, err +func parseDebts(v *fastjson.Value) (*DebtEvent, error) { + o := v.String() + e := DebtEvent{} + err := json.Unmarshal([]byte(o), &e) + return &e, err } func ParseUserEvent(v *fastjson.Value) (interface{}, error) { @@ -262,19 +263,15 @@ func ParseUserEvent(v *fastjson.Value) (interface{}, error) { return parseTradeUpdateEvent(v), nil case "ad_ratio_snapshot", "ad_ratio_update": - return parseADRatio(v) + return parseADRatioEvent(v) case "borrowing_snapshot", "borrowing_update": return parseDebts(v) case "account_snapshot", "account_update", "mwallet_account_snapshot", "mwallet_account_update": var e AccountUpdateEvent - o, err := v.StringBytes() - if err != nil { - return nil, err - } - - err = json.Unmarshal(o, &e) + o := v.String() + err := json.Unmarshal([]byte(o), &e) return &e, err case "error": diff --git a/pkg/exchange/max/stream.go b/pkg/exchange/max/stream.go index 1ac320908..b504b522e 100644 --- a/pkg/exchange/max/stream.go +++ b/pkg/exchange/max/stream.go @@ -33,6 +33,8 @@ type Stream struct { tradeSnapshotEventCallbacks []func(e max.TradeSnapshotEvent) orderUpdateEventCallbacks []func(e max.OrderUpdateEvent) orderSnapshotEventCallbacks []func(e max.OrderSnapshotEvent) + adRatioEventCallbacks []func(e max.ADRatioEvent) + debtEventCallbacks []func(e max.DebtEvent) accountSnapshotEventCallbacks []func(e max.AccountSnapshotEvent) accountUpdateEventCallbacks []func(e max.AccountUpdateEvent) @@ -47,7 +49,6 @@ func NewStream(key, secret string) *Stream { stream.SetEndpointCreator(stream.getEndpoint) stream.SetParser(max.ParseMessage) stream.SetDispatcher(stream.dispatchEvent) - stream.OnConnect(stream.handleConnect) stream.OnKLineEvent(stream.handleKLineEvent) stream.OnOrderSnapshotEvent(stream.handleOrderSnapshotEvent) @@ -257,8 +258,11 @@ func (s *Stream) dispatchEvent(e interface{}) { case *max.OrderUpdateEvent: s.EmitOrderUpdateEvent(*e) + case *max.ADRatioEvent: + log.Info(e.ADRatio.String()) + default: - log.Errorf("unsupported %T event: %+v", e, e) + log.Warnf("unhandled %T event: %+v", e, e) } } diff --git a/pkg/exchange/max/stream_callbacks.go b/pkg/exchange/max/stream_callbacks.go index 9c37eae0b..3f556ef3c 100644 --- a/pkg/exchange/max/stream_callbacks.go +++ b/pkg/exchange/max/stream_callbacks.go @@ -106,6 +106,26 @@ func (s *Stream) EmitOrderSnapshotEvent(e max.OrderSnapshotEvent) { } } +func (s *Stream) OnAdRatioEvent(cb func(e max.ADRatioEvent)) { + s.adRatioEventCallbacks = append(s.adRatioEventCallbacks, cb) +} + +func (s *Stream) EmitAdRatioEvent(e max.ADRatioEvent) { + for _, cb := range s.adRatioEventCallbacks { + cb(e) + } +} + +func (s *Stream) OnDebtEvent(cb func(e max.DebtEvent)) { + s.debtEventCallbacks = append(s.debtEventCallbacks, cb) +} + +func (s *Stream) EmitDebtEvent(e max.DebtEvent) { + for _, cb := range s.debtEventCallbacks { + cb(e) + } +} + func (s *Stream) OnAccountSnapshotEvent(cb func(e max.AccountSnapshotEvent)) { s.accountSnapshotEventCallbacks = append(s.accountSnapshotEventCallbacks, cb) } From c1ba270d7678161f6662be711ab7735660ae3104 Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 26 May 2022 18:07:17 +0800 Subject: [PATCH 16/24] max: log max.DebtEvent --- pkg/exchange/max/maxapi/userdata.go | 4 ++++ pkg/exchange/max/stream.go | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pkg/exchange/max/maxapi/userdata.go b/pkg/exchange/max/maxapi/userdata.go index 2c9501edd..5d3978ddd 100644 --- a/pkg/exchange/max/maxapi/userdata.go +++ b/pkg/exchange/max/maxapi/userdata.go @@ -236,6 +236,10 @@ type Debt struct { TU types.MillisecondTimestamp `json:"TU"` } +func (d *Debt) String() string { + return fmt.Sprintf("Debt %s %v (Interest %v)", d.Currency, d.DebtPrincipal, d.DebtInterest) +} + type DebtEvent struct { Debts []Debt `json:"db"` } diff --git a/pkg/exchange/max/stream.go b/pkg/exchange/max/stream.go index b504b522e..b5a96212f 100644 --- a/pkg/exchange/max/stream.go +++ b/pkg/exchange/max/stream.go @@ -259,7 +259,10 @@ func (s *Stream) dispatchEvent(e interface{}) { s.EmitOrderUpdateEvent(*e) case *max.ADRatioEvent: - log.Info(e.ADRatio.String()) + log.Infof("adRatio: %+v", e.ADRatio) + + case *max.DebtEvent: + log.Infof("debtEvent: %+v", e.Debts) default: log.Warnf("unhandled %T event: %+v", e, e) From 2d20083244d811cd39b85fef22c7128f4ee8f43d Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 26 May 2022 18:49:18 +0800 Subject: [PATCH 17/24] max: pull out http transport and register order service v3 --- pkg/exchange/max/maxapi/restapi.go | 61 ++++++++++++++--------------- pkg/exchange/max/maxapi/v3/order.go | 12 +++--- pkg/types/active_book.go | 1 - 3 files changed, 36 insertions(+), 38 deletions(-) delete mode 100644 pkg/types/active_book.go diff --git a/pkg/exchange/max/maxapi/restapi.go b/pkg/exchange/max/maxapi/restapi.go index 597d65e9b..b9f8c5dee 100644 --- a/pkg/exchange/max/maxapi/restapi.go +++ b/pkg/exchange/max/maxapi/restapi.go @@ -21,6 +21,7 @@ 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" ) @@ -70,12 +71,30 @@ var serverTimestamp = time.Now().Unix() // reqCount is used for nonce, this variable counts the API request count. var reqCount int64 = 1 +// create an isolated http httpTransport rather than the default one +var httpTransport = &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: (&net.Dialer{ + Timeout: 10 * time.Second, + KeepAlive: 30 * time.Second, + }).DialContext, + ForceAttemptHTTP2: true, + MaxIdleConns: httpTransportMaxIdleConns, + MaxIdleConnsPerHost: httpTransportMaxIdleConnsPerHost, + IdleConnTimeout: httpTransportIdleConnTimeout, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, +} + +var defaultHttpClient = &http.Client{ + Timeout: defaultHTTPTimeout, + Transport: httpTransport, +} + type RestClient struct { requestgen.BaseAPIClient - // Authentication - APIKey string - APISecret string + APIKey, APISecret string AccountService *AccountService PublicService *PublicService @@ -83,13 +102,11 @@ type RestClient struct { OrderService *OrderService RewardService *RewardService WithdrawalService *WithdrawalService - // OrderBookService *OrderBookService - // MaxTokenService *MaxTokenService - // MaxKLineService *KLineService - // CreditService *CreditService + + OrderServiceV3 *v3.OrderService } -func NewRestClientWithHttpClient(baseURL string, httpClient *http.Client) *RestClient { +func NewRestClientWithHttpClient(baseURL string) *RestClient { u, err := url.Parse(baseURL) if err != nil { panic(err) @@ -97,7 +114,7 @@ func NewRestClientWithHttpClient(baseURL string, httpClient *http.Client) *RestC var client = &RestClient{ BaseAPIClient: requestgen.BaseAPIClient{ - HttpClient: httpClient, + HttpClient: defaultHttpClient, BaseURL: u, }, } @@ -109,33 +126,15 @@ func NewRestClientWithHttpClient(baseURL string, httpClient *http.Client) *RestC client.RewardService = &RewardService{client} client.WithdrawalService = &WithdrawalService{client} - // client.MaxTokenService = &MaxTokenService{client} + client.OrderServiceV3 = &v3.OrderService{Client: client} + + // defaultHttpClient.MaxTokenService = &MaxTokenService{defaultHttpClient} client.initNonce() return client } func NewRestClient(baseURL string) *RestClient { - // create an isolated http transport rather than the default one - transport := &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: (&net.Dialer{ - Timeout: 10 * time.Second, - KeepAlive: 30 * time.Second, - }).DialContext, - ForceAttemptHTTP2: true, - MaxIdleConns: httpTransportMaxIdleConns, - MaxIdleConnsPerHost: httpTransportMaxIdleConnsPerHost, - IdleConnTimeout: httpTransportIdleConnTimeout, - TLSHandshakeTimeout: 10 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - } - - client := &http.Client{ - Timeout: defaultHTTPTimeout, - Transport: transport, - } - - return NewRestClientWithHttpClient(baseURL, client) + return NewRestClientWithHttpClient(baseURL) } // Auth sets api key and secret for usage is requests that requires authentication. diff --git a/pkg/exchange/max/maxapi/v3/order.go b/pkg/exchange/max/maxapi/v3/order.go index ddcbc7217..edf4cd783 100644 --- a/pkg/exchange/max/maxapi/v3/order.go +++ b/pkg/exchange/max/maxapi/v3/order.go @@ -21,27 +21,27 @@ type Order = maxapi.Order // OrderService manages the Order endpoint. type OrderService struct { - client *maxapi.RestClient + Client *maxapi.RestClient } func (s *OrderService) NewWalletCreateOrderRequest(walletType WalletType) *WalletCreateOrderRequest { - return &WalletCreateOrderRequest{client: s.client, walletType: walletType} + return &WalletCreateOrderRequest{client: s.Client, walletType: walletType} } func (s *OrderService) NewWalletGetOrderRequest(walletType WalletType) *WalletGetOrderRequest { - return &WalletGetOrderRequest{client: s.client, walletType: walletType} + return &WalletGetOrderRequest{client: s.Client, walletType: walletType} } func (s *OrderService) NewWalletOrderCancelAllRequest(walletType WalletType) *WalletOrderCancelAllRequest { - return &WalletOrderCancelAllRequest{client: s.client, walletType: walletType} + return &WalletOrderCancelAllRequest{client: s.Client, walletType: walletType} } func (s *OrderService) NewOrderCancelRequest() *OrderCancelRequest { - return &OrderCancelRequest{client: s.client} + return &OrderCancelRequest{client: s.Client} } func (s *OrderService) NewGetOrderRequest() *GetOrderRequest { - return &GetOrderRequest{client: s.client} + return &GetOrderRequest{client: s.Client} } //go:generate PostRequest -url "/api/v3/wallet/:walletType/orders" -type WalletCreateOrderRequest -responseType .Order -debug diff --git a/pkg/types/active_book.go b/pkg/types/active_book.go deleted file mode 100644 index ab1254f4c..000000000 --- a/pkg/types/active_book.go +++ /dev/null @@ -1 +0,0 @@ -package types From 6ca71cf9f1e2945e50f47a8a7fdb1858094224b7 Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 26 May 2022 18:49:50 +0800 Subject: [PATCH 18/24] max: simplify constructor --- pkg/exchange/max/maxapi/restapi.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkg/exchange/max/maxapi/restapi.go b/pkg/exchange/max/maxapi/restapi.go index b9f8c5dee..17fde6f6c 100644 --- a/pkg/exchange/max/maxapi/restapi.go +++ b/pkg/exchange/max/maxapi/restapi.go @@ -106,7 +106,7 @@ type RestClient struct { OrderServiceV3 *v3.OrderService } -func NewRestClientWithHttpClient(baseURL string) *RestClient { +func NewRestClient(baseURL string) *RestClient { u, err := url.Parse(baseURL) if err != nil { panic(err) @@ -133,10 +133,6 @@ func NewRestClientWithHttpClient(baseURL string) *RestClient { return client } -func NewRestClient(baseURL string) *RestClient { - return NewRestClientWithHttpClient(baseURL) -} - // Auth sets api key and secret for usage is requests that requires authentication. func (c *RestClient) Auth(key string, secret string) *RestClient { c.APIKey = key From d9e10b7fcde066141b9da9e5df03985f30a9ce13 Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 26 May 2022 19:52:38 +0800 Subject: [PATCH 19/24] max: integrate v3 orders api --- pkg/exchange/max/convert.go | 21 +- pkg/exchange/max/exchange.go | 165 ++++------ pkg/exchange/max/maxapi/order.go | 42 ++- pkg/exchange/max/maxapi/restapi.go | 5 - pkg/exchange/max/maxapi/v3/order.go | 38 +-- .../wallet_create_order_request_requestgen.go | 13 +- ...llet_get_open_orders_request_requestgen.go | 177 +++++++++++ ...et_get_order_history_request_requestgen.go | 203 +++++++++++++ .../v3/wallet_get_order_request_requestgen.go | 282 ------------------ ...let_order_cancel_all_request_requestgen.go | 13 +- 10 files changed, 497 insertions(+), 462 deletions(-) create mode 100644 pkg/exchange/max/maxapi/v3/wallet_get_open_orders_request_requestgen.go create mode 100644 pkg/exchange/max/maxapi/v3/wallet_get_order_history_request_requestgen.go delete mode 100644 pkg/exchange/max/maxapi/v3/wallet_get_order_request_requestgen.go 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 From 8721679f7461d11d43a80184b0943d9d1f40036a Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 26 May 2022 20:32:25 +0800 Subject: [PATCH 20/24] max: update market struct fields --- pkg/exchange/max/maxapi/public.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/exchange/max/maxapi/public.go b/pkg/exchange/max/maxapi/public.go index 20b03535f..31ff4ad94 100644 --- a/pkg/exchange/max/maxapi/public.go +++ b/pkg/exchange/max/maxapi/public.go @@ -22,12 +22,14 @@ type PublicService struct { type Market struct { ID string `json:"id"` Name string `json:"name"` + Status string `json:"market_status"` // active BaseUnit string `json:"base_unit"` BaseUnitPrecision int `json:"base_unit_precision"` QuoteUnit string `json:"quote_unit"` QuoteUnitPrecision int `json:"quote_unit_precision"` MinBaseAmount fixedpoint.Value `json:"min_base_amount"` MinQuoteAmount fixedpoint.Value `json:"min_quote_amount"` + SupportMargin bool `json:"m_wallet_supported"` } type Ticker struct { From 37ef5c4b97873c4269fe04caecb73777362552c9 Mon Sep 17 00:00:00 2001 From: c9s Date: Fri, 27 May 2022 15:04:47 +0800 Subject: [PATCH 21/24] max: add margin api (liquidation history and interest history) --- ...gin_borrowing_limits_request_requestgen.go | 135 ++++++++++++ ...gin_interest_history_request_requestgen.go | 203 ++++++++++++++++++ ...argin_interest_rates_request_requestgen.go | 135 ++++++++++++ ..._liquidation_history_request_requestgen.go | 181 ++++++++++++++++ pkg/exchange/max/maxapi/v3/margin.go | 87 ++++++++ 5 files changed, 741 insertions(+) create mode 100644 pkg/exchange/max/maxapi/v3/get_margin_borrowing_limits_request_requestgen.go create mode 100644 pkg/exchange/max/maxapi/v3/get_margin_interest_history_request_requestgen.go create mode 100644 pkg/exchange/max/maxapi/v3/get_margin_interest_rates_request_requestgen.go create mode 100644 pkg/exchange/max/maxapi/v3/get_margin_liquidation_history_request_requestgen.go create mode 100644 pkg/exchange/max/maxapi/v3/margin.go diff --git a/pkg/exchange/max/maxapi/v3/get_margin_borrowing_limits_request_requestgen.go b/pkg/exchange/max/maxapi/v3/get_margin_borrowing_limits_request_requestgen.go new file mode 100644 index 000000000..4c631eab9 --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/get_margin_borrowing_limits_request_requestgen.go @@ -0,0 +1,135 @@ +// Code generated by "requestgen -method GET -url /api/v3/wallet/m/limits -type GetMarginBorrowingLimitsRequest -responseType .MarginBorrowingLimitMap"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" +) + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (g *GetMarginBorrowingLimitsRequest) 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 (g *GetMarginBorrowingLimitsRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (g *GetMarginBorrowingLimitsRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := g.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if g.isVarSlice(_v) { + g.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 (g *GetMarginBorrowingLimitsRequest) GetParametersJSON() ([]byte, error) { + params, err := g.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 (g *GetMarginBorrowingLimitsRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + + return params, nil +} + +func (g *GetMarginBorrowingLimitsRequest) 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 (g *GetMarginBorrowingLimitsRequest) 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 (g *GetMarginBorrowingLimitsRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (g *GetMarginBorrowingLimitsRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := g.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (g *GetMarginBorrowingLimitsRequest) Do(ctx context.Context) (*MarginBorrowingLimitMap, error) { + + // no body params + var params interface{} + query := url.Values{} + + apiURL := "/api/v3/wallet/m/limits" + + req, err := g.client.NewRequest(ctx, "GET", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := g.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse MarginBorrowingLimitMap + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return &apiResponse, nil +} diff --git a/pkg/exchange/max/maxapi/v3/get_margin_interest_history_request_requestgen.go b/pkg/exchange/max/maxapi/v3/get_margin_interest_history_request_requestgen.go new file mode 100644 index 000000000..60002d36b --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/get_margin_interest_history_request_requestgen.go @@ -0,0 +1,203 @@ +// Code generated by "requestgen -method GET -url /api/v3/wallet/m/interests/history/:currency -type GetMarginInterestHistoryRequest -responseType []MarginInterestRecord"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" + "strconv" + "time" +) + +func (g *GetMarginInterestHistoryRequest) StartTime(startTime time.Time) *GetMarginInterestHistoryRequest { + g.startTime = &startTime + return g +} + +func (g *GetMarginInterestHistoryRequest) EndTime(endTime time.Time) *GetMarginInterestHistoryRequest { + g.endTime = &endTime + return g +} + +func (g *GetMarginInterestHistoryRequest) Limit(limit int) *GetMarginInterestHistoryRequest { + g.limit = &limit + return g +} + +func (g *GetMarginInterestHistoryRequest) Currency(currency string) *GetMarginInterestHistoryRequest { + g.currency = currency + return g +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (g *GetMarginInterestHistoryRequest) 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 (g *GetMarginInterestHistoryRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check startTime field -> json key startTime + if g.startTime != nil { + startTime := *g.startTime + + // assign parameter of startTime + // convert time.Time to milliseconds time stamp + params["startTime"] = strconv.FormatInt(startTime.UnixNano()/int64(time.Millisecond), 10) + } else { + } + // check endTime field -> json key endTime + if g.endTime != nil { + endTime := *g.endTime + + // assign parameter of endTime + // convert time.Time to milliseconds time stamp + params["endTime"] = strconv.FormatInt(endTime.UnixNano()/int64(time.Millisecond), 10) + } else { + } + // check limit field -> json key limit + if g.limit != nil { + limit := *g.limit + + // assign parameter of limit + params["limit"] = limit + } else { + } + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (g *GetMarginInterestHistoryRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := g.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if g.isVarSlice(_v) { + g.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 (g *GetMarginInterestHistoryRequest) GetParametersJSON() ([]byte, error) { + params, err := g.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 (g *GetMarginInterestHistoryRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check currency field -> json key currency + currency := g.currency + + // TEMPLATE check-required + if len(currency) == 0 { + return nil, fmt.Errorf("currency is required, empty string given") + } + // END TEMPLATE check-required + + // assign parameter of currency + params["currency"] = currency + + return params, nil +} + +func (g *GetMarginInterestHistoryRequest) 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 (g *GetMarginInterestHistoryRequest) 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 (g *GetMarginInterestHistoryRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (g *GetMarginInterestHistoryRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := g.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (g *GetMarginInterestHistoryRequest) Do(ctx context.Context) ([]MarginInterestRecord, error) { + + // empty params for GET operation + var params interface{} + query, err := g.GetParametersQuery() + if err != nil { + return nil, err + } + + apiURL := "/api/v3/wallet/m/interests/history/:currency" + slugs, err := g.GetSlugsMap() + if err != nil { + return nil, err + } + + apiURL = g.applySlugsToUrl(apiURL, slugs) + + req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := g.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse []MarginInterestRecord + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return apiResponse, nil +} diff --git a/pkg/exchange/max/maxapi/v3/get_margin_interest_rates_request_requestgen.go b/pkg/exchange/max/maxapi/v3/get_margin_interest_rates_request_requestgen.go new file mode 100644 index 000000000..6de0e5eaa --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/get_margin_interest_rates_request_requestgen.go @@ -0,0 +1,135 @@ +// Code generated by "requestgen -method GET -url /api/v3/wallet/m/interest_rates -type GetMarginInterestRatesRequest -responseType .MarginInterestRateMap"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" +) + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (g *GetMarginInterestRatesRequest) 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 (g *GetMarginInterestRatesRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (g *GetMarginInterestRatesRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := g.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if g.isVarSlice(_v) { + g.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 (g *GetMarginInterestRatesRequest) GetParametersJSON() ([]byte, error) { + params, err := g.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 (g *GetMarginInterestRatesRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + + return params, nil +} + +func (g *GetMarginInterestRatesRequest) 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 (g *GetMarginInterestRatesRequest) 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 (g *GetMarginInterestRatesRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (g *GetMarginInterestRatesRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := g.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (g *GetMarginInterestRatesRequest) Do(ctx context.Context) (*MarginInterestRateMap, error) { + + // no body params + var params interface{} + query := url.Values{} + + apiURL := "/api/v3/wallet/m/interest_rates" + + req, err := g.client.NewRequest(ctx, "GET", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := g.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse MarginInterestRateMap + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return &apiResponse, nil +} diff --git a/pkg/exchange/max/maxapi/v3/get_margin_liquidation_history_request_requestgen.go b/pkg/exchange/max/maxapi/v3/get_margin_liquidation_history_request_requestgen.go new file mode 100644 index 000000000..257b8c8e7 --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/get_margin_liquidation_history_request_requestgen.go @@ -0,0 +1,181 @@ +// Code generated by "requestgen -method GET -url /api/v3/wallet/m/liquidations -type GetMarginLiquidationHistoryRequest -responseType []LiquidationRecord"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" + "strconv" + "time" +) + +func (g *GetMarginLiquidationHistoryRequest) StartTime(startTime time.Time) *GetMarginLiquidationHistoryRequest { + g.startTime = &startTime + return g +} + +func (g *GetMarginLiquidationHistoryRequest) EndTime(endTime time.Time) *GetMarginLiquidationHistoryRequest { + g.endTime = &endTime + return g +} + +func (g *GetMarginLiquidationHistoryRequest) Limit(limit int) *GetMarginLiquidationHistoryRequest { + g.limit = &limit + return g +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (g *GetMarginLiquidationHistoryRequest) 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 (g *GetMarginLiquidationHistoryRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check startTime field -> json key startTime + if g.startTime != nil { + startTime := *g.startTime + + // assign parameter of startTime + // convert time.Time to milliseconds time stamp + params["startTime"] = strconv.FormatInt(startTime.UnixNano()/int64(time.Millisecond), 10) + } else { + } + // check endTime field -> json key endTime + if g.endTime != nil { + endTime := *g.endTime + + // assign parameter of endTime + // convert time.Time to milliseconds time stamp + params["endTime"] = strconv.FormatInt(endTime.UnixNano()/int64(time.Millisecond), 10) + } else { + } + // check limit field -> json key limit + if g.limit != nil { + limit := *g.limit + + // assign parameter of limit + params["limit"] = limit + } else { + } + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (g *GetMarginLiquidationHistoryRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := g.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if g.isVarSlice(_v) { + g.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 (g *GetMarginLiquidationHistoryRequest) GetParametersJSON() ([]byte, error) { + params, err := g.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 (g *GetMarginLiquidationHistoryRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + + return params, nil +} + +func (g *GetMarginLiquidationHistoryRequest) 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 (g *GetMarginLiquidationHistoryRequest) 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 (g *GetMarginLiquidationHistoryRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (g *GetMarginLiquidationHistoryRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := g.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (g *GetMarginLiquidationHistoryRequest) Do(ctx context.Context) ([]LiquidationRecord, error) { + + // empty params for GET operation + var params interface{} + query, err := g.GetParametersQuery() + if err != nil { + return nil, err + } + + apiURL := "/api/v3/wallet/m/liquidations" + + req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := g.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse []LiquidationRecord + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return apiResponse, nil +} diff --git a/pkg/exchange/max/maxapi/v3/margin.go b/pkg/exchange/max/maxapi/v3/margin.go new file mode 100644 index 000000000..47c91674f --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/margin.go @@ -0,0 +1,87 @@ +package v3 + +//go:generate -command GetRequest requestgen -method GET +//go:generate -command PostRequest requestgen -method POST +//go:generate -command DeleteRequest requestgen -method DELETE + +import ( + "time" + + "github.com/c9s/requestgen" + + maxapi "github.com/c9s/bbgo/pkg/exchange/max/maxapi" + "github.com/c9s/bbgo/pkg/fixedpoint" + "github.com/c9s/bbgo/pkg/types" +) + +type MarginService struct { + Client *maxapi.RestClient +} + +func (s *MarginService) NewGetMarginInterestRatesRequest() *GetMarginInterestRatesRequest { + return &GetMarginInterestRatesRequest{client: s.Client} +} + +func (s *MarginService) NewGetMarginBorrowingLimitsRequest() *GetMarginBorrowingLimitsRequest { + return &GetMarginBorrowingLimitsRequest{client: s.Client} +} + +func (s *MarginService) NewGetMarginInterestHistoryRequest(currency string) *GetMarginInterestHistoryRequest { + return &GetMarginInterestHistoryRequest{client: s.Client, currency: currency} +} + +func (s *MarginService) NewGetMarginLiquidationHistoryRequest() *GetMarginLiquidationHistoryRequest { + return &GetMarginLiquidationHistoryRequest{client: s.Client} +} + +type MarginInterestRate struct { + HourlyInterestRate fixedpoint.Value `json:"hourly_interest_rate"` + NextHourlyInterestRate fixedpoint.Value `json:"next_hourly_interest_rate"` +} + +type MarginInterestRateMap map[string]MarginInterestRate + +//go:generate GetRequest -url "/api/v3/wallet/m/interest_rates" -type GetMarginInterestRatesRequest -responseType .MarginInterestRateMap +type GetMarginInterestRatesRequest struct { + client requestgen.APIClient +} + +type MarginBorrowingLimitMap map[string]fixedpoint.Value + +//go:generate GetRequest -url "/api/v3/wallet/m/limits" -type GetMarginBorrowingLimitsRequest -responseType .MarginBorrowingLimitMap +type GetMarginBorrowingLimitsRequest struct { + client requestgen.APIClient +} + +type MarginInterestRecord struct { + Currency string `json:"currency"` + Amount fixedpoint.Value `json:"amount"` + InterestRate fixedpoint.Value `json:"interest_rate"` + CreatedAt types.MillisecondTimestamp `json:"created_at"` +} + +//go:generate GetRequest -url "/api/v3/wallet/m/interests/history/:currency" -type GetMarginInterestHistoryRequest -responseType []MarginInterestRecord +type GetMarginInterestHistoryRequest struct { + client requestgen.AuthenticatedAPIClient + + currency string `param:"currency,slug,required"` + startTime *time.Time `param:"startTime,milliseconds"` + endTime *time.Time `param:"endTime,milliseconds"` + limit *int `param:"limit"` +} + +type LiquidationRecord struct { + Sn string `json:"sn"` + AdRatio string `json:"ad_ratio"` + ExpectedAdRatio string `json:"expected_ad_ratio"` + CreatedAt int64 `json:"created_at"` + State string `json:"state"` +} + +//go:generate GetRequest -url "/api/v3/wallet/m/liquidations" -type GetMarginLiquidationHistoryRequest -responseType []LiquidationRecord +type GetMarginLiquidationHistoryRequest struct { + client requestgen.AuthenticatedAPIClient + startTime *time.Time `param:"startTime,milliseconds"` + endTime *time.Time `param:"endTime,milliseconds"` + limit *int `param:"limit"` +} From 410a9610c96ee97fd2c5d5db760df282aade32c8 Mon Sep 17 00:00:00 2001 From: c9s Date: Fri, 27 May 2022 16:13:01 +0800 Subject: [PATCH 22/24] max: add margin api (loan, repay, ad ratio) --- pkg/exchange/max/maxapi/v3/margin.go | 98 ++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 5 deletions(-) diff --git a/pkg/exchange/max/maxapi/v3/margin.go b/pkg/exchange/max/maxapi/v3/margin.go index 47c91674f..508df6801 100644 --- a/pkg/exchange/max/maxapi/v3/margin.go +++ b/pkg/exchange/max/maxapi/v3/margin.go @@ -34,6 +34,22 @@ func (s *MarginService) NewGetMarginLiquidationHistoryRequest() *GetMarginLiquid return &GetMarginLiquidationHistoryRequest{client: s.Client} } +func (s *MarginService) NewGetMarginLoanHistoryRequest() *GetMarginLoanHistoryRequest { + return &GetMarginLoanHistoryRequest{client: s.Client} +} + +func (s *MarginService) NewGetMarginADRatioRequest() *GetMarginADRatioRequest { + return &GetMarginADRatioRequest{client: s.Client} +} + +func (s *MarginService) NewMarginRepayRequest() *MarginRepayRequest { + return &MarginRepayRequest{client: s.Client} +} + +func (s *MarginService) NewMarginLoanRequest() *MarginLoanRequest { + return &MarginLoanRequest{client: s.Client} +} + type MarginInterestRate struct { HourlyInterestRate fixedpoint.Value `json:"hourly_interest_rate"` NextHourlyInterestRate fixedpoint.Value `json:"next_hourly_interest_rate"` @@ -71,13 +87,21 @@ type GetMarginInterestHistoryRequest struct { } type LiquidationRecord struct { - Sn string `json:"sn"` - AdRatio string `json:"ad_ratio"` - ExpectedAdRatio string `json:"expected_ad_ratio"` - CreatedAt int64 `json:"created_at"` - State string `json:"state"` + SN string `json:"sn"` + AdRatio fixedpoint.Value `json:"ad_ratio"` + ExpectedAdRatio fixedpoint.Value `json:"expected_ad_ratio"` + CreatedAt types.MillisecondTimestamp `json:"created_at"` + State LiquidationState `json:"state"` } +type LiquidationState string + +const ( + LiquidationStateProcessing LiquidationState = "processing" + LiquidationStateDebt LiquidationState = "debt" + LiquidationStateLiquidated LiquidationState = "liquidated" +) + //go:generate GetRequest -url "/api/v3/wallet/m/liquidations" -type GetMarginLiquidationHistoryRequest -responseType []LiquidationRecord type GetMarginLiquidationHistoryRequest struct { client requestgen.AuthenticatedAPIClient @@ -85,3 +109,67 @@ type GetMarginLiquidationHistoryRequest struct { endTime *time.Time `param:"endTime,milliseconds"` limit *int `param:"limit"` } + +type RepaymentRecord struct { + SN string `json:"sn"` + Currency string `json:"currency"` + Amount fixedpoint.Value `json:"amount"` + Principal fixedpoint.Value `json:"principal"` + Interest fixedpoint.Value `json:"interest"` + CreatedAt types.MillisecondTimestamp `json:"created_at"` + State string `json:"state"` +} + +//go:generate GetRequest -url "/api/v3/wallet/m/repayments/:currency" -type GetMarginRepaymentHistoryRequest -responseType []RepaymentRecord +type GetMarginRepaymentHistoryRequest struct { + client requestgen.AuthenticatedAPIClient + currency string `param:"currency,slug,required"` + + startTime *time.Time `param:"startTime,milliseconds"` + endTime *time.Time `param:"endTime,milliseconds"` + limit *int `param:"limit"` +} + +type LoanRecord struct { + SN string `json:"sn"` + Currency string `json:"currency"` + Amount fixedpoint.Value `json:"amount"` + State string `json:"state"` + CreatedAt types.MillisecondTimestamp `json:"created_at"` + InterestRate fixedpoint.Value `json:"interest_rate"` +} + +//go:generate GetRequest -url "/api/v3/wallet/m/loans/:currency" -type GetMarginLoanHistoryRequest -responseType []LoanRecord +type GetMarginLoanHistoryRequest struct { + client requestgen.AuthenticatedAPIClient + currency string `param:"currency,slug,required"` + + startTime *time.Time `param:"startTime,milliseconds"` + endTime *time.Time `param:"endTime,milliseconds"` + limit *int `param:"limit"` +} + +//go:generate PostRequest -url "/api/v3/wallet/m/loans/:currency" -type MarginLoanRequest -responseType .LoanRecord +type MarginLoanRequest struct { + client requestgen.AuthenticatedAPIClient + currency string `param:"currency,slug,required"` + amount string `param:"amount"` +} + +//go:generate PostRequest -url "/api/v3/wallet/m/repayments/:currency" -type MarginRepayRequest -responseType .RepaymentRecord +type MarginRepayRequest struct { + client requestgen.AuthenticatedAPIClient + currency string `param:"currency,slug,required"` + amount string `param:"amount"` +} + +type ADRatio struct { + AdRatio fixedpoint.Value `json:"ad_ratio"` + AssetInUsdt fixedpoint.Value `json:"asset_in_usdt"` + DebtInUsdt fixedpoint.Value `json:"debt_in_usdt"` +} + +//go:generate GetRequest -url "/api/v3/wallet/m/ad_ratio" -type GetMarginADRatioRequest -responseType .ADRatio +type GetMarginADRatioRequest struct { + client requestgen.AuthenticatedAPIClient +} From 60d65a390fdfb2d9cb972841d71cb27ff3e3589b Mon Sep 17 00:00:00 2001 From: c9s Date: Fri, 27 May 2022 16:40:56 +0800 Subject: [PATCH 23/24] max: add margin api (liquidation history and interest history) --- .../get_margin_ad_ratio_request_requestgen.go | 135 ++++++++++++ ..._margin_loan_history_request_requestgen.go | 203 ++++++++++++++++++ ...in_repayment_history_request_requestgen.go | 203 ++++++++++++++++++ .../v3/margin_loan_request_requestgen.go | 169 +++++++++++++++ .../v3/margin_repay_request_requestgen.go | 169 +++++++++++++++ 5 files changed, 879 insertions(+) create mode 100644 pkg/exchange/max/maxapi/v3/get_margin_ad_ratio_request_requestgen.go create mode 100644 pkg/exchange/max/maxapi/v3/get_margin_loan_history_request_requestgen.go create mode 100644 pkg/exchange/max/maxapi/v3/get_margin_repayment_history_request_requestgen.go create mode 100644 pkg/exchange/max/maxapi/v3/margin_loan_request_requestgen.go create mode 100644 pkg/exchange/max/maxapi/v3/margin_repay_request_requestgen.go diff --git a/pkg/exchange/max/maxapi/v3/get_margin_ad_ratio_request_requestgen.go b/pkg/exchange/max/maxapi/v3/get_margin_ad_ratio_request_requestgen.go new file mode 100644 index 000000000..cf54325a9 --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/get_margin_ad_ratio_request_requestgen.go @@ -0,0 +1,135 @@ +// Code generated by "requestgen -method GET -url /api/v3/wallet/m/ad_ratio -type GetMarginADRatioRequest -responseType .ADRatio"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" +) + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (g *GetMarginADRatioRequest) 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 (g *GetMarginADRatioRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (g *GetMarginADRatioRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := g.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if g.isVarSlice(_v) { + g.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 (g *GetMarginADRatioRequest) GetParametersJSON() ([]byte, error) { + params, err := g.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 (g *GetMarginADRatioRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + + return params, nil +} + +func (g *GetMarginADRatioRequest) 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 (g *GetMarginADRatioRequest) 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 (g *GetMarginADRatioRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (g *GetMarginADRatioRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := g.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (g *GetMarginADRatioRequest) Do(ctx context.Context) (*ADRatio, error) { + + // no body params + var params interface{} + query := url.Values{} + + apiURL := "/api/v3/wallet/m/ad_ratio" + + req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := g.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse ADRatio + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return &apiResponse, nil +} diff --git a/pkg/exchange/max/maxapi/v3/get_margin_loan_history_request_requestgen.go b/pkg/exchange/max/maxapi/v3/get_margin_loan_history_request_requestgen.go new file mode 100644 index 000000000..e0ca63db0 --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/get_margin_loan_history_request_requestgen.go @@ -0,0 +1,203 @@ +// Code generated by "requestgen -method GET -url /api/v3/wallet/m/loans/:currency -type GetMarginLoanHistoryRequest -responseType []LoanRecord"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" + "strconv" + "time" +) + +func (g *GetMarginLoanHistoryRequest) StartTime(startTime time.Time) *GetMarginLoanHistoryRequest { + g.startTime = &startTime + return g +} + +func (g *GetMarginLoanHistoryRequest) EndTime(endTime time.Time) *GetMarginLoanHistoryRequest { + g.endTime = &endTime + return g +} + +func (g *GetMarginLoanHistoryRequest) Limit(limit int) *GetMarginLoanHistoryRequest { + g.limit = &limit + return g +} + +func (g *GetMarginLoanHistoryRequest) Currency(currency string) *GetMarginLoanHistoryRequest { + g.currency = currency + return g +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (g *GetMarginLoanHistoryRequest) 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 (g *GetMarginLoanHistoryRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check startTime field -> json key startTime + if g.startTime != nil { + startTime := *g.startTime + + // assign parameter of startTime + // convert time.Time to milliseconds time stamp + params["startTime"] = strconv.FormatInt(startTime.UnixNano()/int64(time.Millisecond), 10) + } else { + } + // check endTime field -> json key endTime + if g.endTime != nil { + endTime := *g.endTime + + // assign parameter of endTime + // convert time.Time to milliseconds time stamp + params["endTime"] = strconv.FormatInt(endTime.UnixNano()/int64(time.Millisecond), 10) + } else { + } + // check limit field -> json key limit + if g.limit != nil { + limit := *g.limit + + // assign parameter of limit + params["limit"] = limit + } else { + } + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (g *GetMarginLoanHistoryRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := g.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if g.isVarSlice(_v) { + g.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 (g *GetMarginLoanHistoryRequest) GetParametersJSON() ([]byte, error) { + params, err := g.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 (g *GetMarginLoanHistoryRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check currency field -> json key currency + currency := g.currency + + // TEMPLATE check-required + if len(currency) == 0 { + return nil, fmt.Errorf("currency is required, empty string given") + } + // END TEMPLATE check-required + + // assign parameter of currency + params["currency"] = currency + + return params, nil +} + +func (g *GetMarginLoanHistoryRequest) 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 (g *GetMarginLoanHistoryRequest) 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 (g *GetMarginLoanHistoryRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (g *GetMarginLoanHistoryRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := g.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (g *GetMarginLoanHistoryRequest) Do(ctx context.Context) ([]LoanRecord, error) { + + // empty params for GET operation + var params interface{} + query, err := g.GetParametersQuery() + if err != nil { + return nil, err + } + + apiURL := "/api/v3/wallet/m/loans/:currency" + slugs, err := g.GetSlugsMap() + if err != nil { + return nil, err + } + + apiURL = g.applySlugsToUrl(apiURL, slugs) + + req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := g.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse []LoanRecord + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return apiResponse, nil +} diff --git a/pkg/exchange/max/maxapi/v3/get_margin_repayment_history_request_requestgen.go b/pkg/exchange/max/maxapi/v3/get_margin_repayment_history_request_requestgen.go new file mode 100644 index 000000000..83edcd7fd --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/get_margin_repayment_history_request_requestgen.go @@ -0,0 +1,203 @@ +// Code generated by "requestgen -method GET -url /api/v3/wallet/m/repayments/:currency -type GetMarginRepaymentHistoryRequest -responseType []RepaymentRecord"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" + "strconv" + "time" +) + +func (g *GetMarginRepaymentHistoryRequest) StartTime(startTime time.Time) *GetMarginRepaymentHistoryRequest { + g.startTime = &startTime + return g +} + +func (g *GetMarginRepaymentHistoryRequest) EndTime(endTime time.Time) *GetMarginRepaymentHistoryRequest { + g.endTime = &endTime + return g +} + +func (g *GetMarginRepaymentHistoryRequest) Limit(limit int) *GetMarginRepaymentHistoryRequest { + g.limit = &limit + return g +} + +func (g *GetMarginRepaymentHistoryRequest) Currency(currency string) *GetMarginRepaymentHistoryRequest { + g.currency = currency + return g +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (g *GetMarginRepaymentHistoryRequest) 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 (g *GetMarginRepaymentHistoryRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check startTime field -> json key startTime + if g.startTime != nil { + startTime := *g.startTime + + // assign parameter of startTime + // convert time.Time to milliseconds time stamp + params["startTime"] = strconv.FormatInt(startTime.UnixNano()/int64(time.Millisecond), 10) + } else { + } + // check endTime field -> json key endTime + if g.endTime != nil { + endTime := *g.endTime + + // assign parameter of endTime + // convert time.Time to milliseconds time stamp + params["endTime"] = strconv.FormatInt(endTime.UnixNano()/int64(time.Millisecond), 10) + } else { + } + // check limit field -> json key limit + if g.limit != nil { + limit := *g.limit + + // assign parameter of limit + params["limit"] = limit + } else { + } + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (g *GetMarginRepaymentHistoryRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := g.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if g.isVarSlice(_v) { + g.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 (g *GetMarginRepaymentHistoryRequest) GetParametersJSON() ([]byte, error) { + params, err := g.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 (g *GetMarginRepaymentHistoryRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check currency field -> json key currency + currency := g.currency + + // TEMPLATE check-required + if len(currency) == 0 { + return nil, fmt.Errorf("currency is required, empty string given") + } + // END TEMPLATE check-required + + // assign parameter of currency + params["currency"] = currency + + return params, nil +} + +func (g *GetMarginRepaymentHistoryRequest) 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 (g *GetMarginRepaymentHistoryRequest) 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 (g *GetMarginRepaymentHistoryRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (g *GetMarginRepaymentHistoryRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := g.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (g *GetMarginRepaymentHistoryRequest) Do(ctx context.Context) ([]RepaymentRecord, error) { + + // empty params for GET operation + var params interface{} + query, err := g.GetParametersQuery() + if err != nil { + return nil, err + } + + apiURL := "/api/v3/wallet/m/repayments/:currency" + slugs, err := g.GetSlugsMap() + if err != nil { + return nil, err + } + + apiURL = g.applySlugsToUrl(apiURL, slugs) + + req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := g.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse []RepaymentRecord + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return apiResponse, nil +} diff --git a/pkg/exchange/max/maxapi/v3/margin_loan_request_requestgen.go b/pkg/exchange/max/maxapi/v3/margin_loan_request_requestgen.go new file mode 100644 index 000000000..39c69ff63 --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/margin_loan_request_requestgen.go @@ -0,0 +1,169 @@ +// Code generated by "requestgen -method POST -url /api/v3/wallet/m/loans/:currency -type MarginLoanRequest -responseType .LoanRecord"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" +) + +func (m *MarginLoanRequest) Amount(amount string) *MarginLoanRequest { + m.amount = amount + return m +} + +func (m *MarginLoanRequest) Currency(currency string) *MarginLoanRequest { + m.currency = currency + return m +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (m *MarginLoanRequest) 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 (m *MarginLoanRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check amount field -> json key amount + amount := m.amount + + // assign parameter of amount + params["amount"] = amount + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (m *MarginLoanRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := m.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if m.isVarSlice(_v) { + m.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 (m *MarginLoanRequest) GetParametersJSON() ([]byte, error) { + params, err := m.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 (m *MarginLoanRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check currency field -> json key currency + currency := m.currency + + // TEMPLATE check-required + if len(currency) == 0 { + return nil, fmt.Errorf("currency is required, empty string given") + } + // END TEMPLATE check-required + + // assign parameter of currency + params["currency"] = currency + + return params, nil +} + +func (m *MarginLoanRequest) 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 (m *MarginLoanRequest) 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 (m *MarginLoanRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (m *MarginLoanRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := m.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (m *MarginLoanRequest) Do(ctx context.Context) (*LoanRecord, error) { + + params, err := m.GetParameters() + if err != nil { + return nil, err + } + query := url.Values{} + + apiURL := "/api/v3/wallet/m/loans/:currency" + slugs, err := m.GetSlugsMap() + if err != nil { + return nil, err + } + + apiURL = m.applySlugsToUrl(apiURL, slugs) + + req, err := m.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := m.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse LoanRecord + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return &apiResponse, nil +} diff --git a/pkg/exchange/max/maxapi/v3/margin_repay_request_requestgen.go b/pkg/exchange/max/maxapi/v3/margin_repay_request_requestgen.go new file mode 100644 index 000000000..a221db7c0 --- /dev/null +++ b/pkg/exchange/max/maxapi/v3/margin_repay_request_requestgen.go @@ -0,0 +1,169 @@ +// Code generated by "requestgen -method POST -url /api/v3/wallet/m/repayments/:currency -type MarginRepayRequest -responseType .RepaymentRecord"; DO NOT EDIT. + +package v3 + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" +) + +func (m *MarginRepayRequest) Amount(amount string) *MarginRepayRequest { + m.amount = amount + return m +} + +func (m *MarginRepayRequest) Currency(currency string) *MarginRepayRequest { + m.currency = currency + return m +} + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (m *MarginRepayRequest) 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 (m *MarginRepayRequest) GetParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check amount field -> json key amount + amount := m.amount + + // assign parameter of amount + params["amount"] = amount + + return params, nil +} + +// GetParametersQuery converts the parameters from GetParameters into the url.Values format +func (m *MarginRepayRequest) GetParametersQuery() (url.Values, error) { + query := url.Values{} + + params, err := m.GetParameters() + if err != nil { + return query, err + } + + for _k, _v := range params { + if m.isVarSlice(_v) { + m.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 (m *MarginRepayRequest) GetParametersJSON() ([]byte, error) { + params, err := m.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 (m *MarginRepayRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + // check currency field -> json key currency + currency := m.currency + + // TEMPLATE check-required + if len(currency) == 0 { + return nil, fmt.Errorf("currency is required, empty string given") + } + // END TEMPLATE check-required + + // assign parameter of currency + params["currency"] = currency + + return params, nil +} + +func (m *MarginRepayRequest) 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 (m *MarginRepayRequest) 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 (m *MarginRepayRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (m *MarginRepayRequest) GetSlugsMap() (map[string]string, error) { + slugs := map[string]string{} + params, err := m.GetSlugParameters() + if err != nil { + return slugs, nil + } + + for _k, _v := range params { + slugs[_k] = fmt.Sprintf("%v", _v) + } + + return slugs, nil +} + +func (m *MarginRepayRequest) Do(ctx context.Context) (*RepaymentRecord, error) { + + params, err := m.GetParameters() + if err != nil { + return nil, err + } + query := url.Values{} + + apiURL := "/api/v3/wallet/m/repayments/:currency" + slugs, err := m.GetSlugsMap() + if err != nil { + return nil, err + } + + apiURL = m.applySlugsToUrl(apiURL, slugs) + + req, err := m.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params) + if err != nil { + return nil, err + } + + response, err := m.client.SendRequest(req) + if err != nil { + return nil, err + } + + var apiResponse RepaymentRecord + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + return &apiResponse, nil +} From d792f3b83b667931e5d3253e9995bf351a555d68 Mon Sep 17 00:00:00 2001 From: c9s Date: Fri, 27 May 2022 16:46:29 +0800 Subject: [PATCH 24/24] max: drop unused url ref vars --- pkg/exchange/max/maxapi/order.go | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pkg/exchange/max/maxapi/order.go b/pkg/exchange/max/maxapi/order.go index 52d6eb095..6d88ec767 100644 --- a/pkg/exchange/max/maxapi/order.go +++ b/pkg/exchange/max/maxapi/order.go @@ -15,11 +15,10 @@ import ( "github.com/c9s/bbgo/pkg/types" ) -var relUrlV2Order *url.URL -var relUrlV2Orders *url.URL -var relUrlV2OrdersClear *url.URL -var relUrlV2OrdersDelete *url.URL -var relUrlV2OrdersMultiOneByOne, relUrlV2OrderDelete *url.URL +var ( + relUrlV2Orders *url.URL + relUrlV2OrdersMultiOneByOne *url.URL +) func mustParseURL(s string) *url.URL { u, err := url.Parse(s) @@ -30,11 +29,7 @@ func mustParseURL(s string) *url.URL { } func init() { - relUrlV2Order = mustParseURL("v2/order") - relUrlV2OrderDelete = mustParseURL("v2/order/delete") relUrlV2Orders = mustParseURL("v2/orders") - relUrlV2OrdersClear = mustParseURL("v2/orders/clear") - relUrlV2OrdersDelete = mustParseURL("v2/orders/delete") relUrlV2OrdersMultiOneByOne = mustParseURL("v2/orders/multi/onebyone") }