From 13c2f85af3d0bb47f17e3af6a796625465f537c3 Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 23 Jan 2025 13:14:53 +0800 Subject: [PATCH] okexapi: add /api/v5/account/account-position-risk api --- pkg/exchange/okex/okexapi/client_test.go | 10 + .../get_account_position_risk_request.go | 43 +++++ ...ccount_position_risk_request_requestgen.go | 171 ++++++++++++++++++ ...count_spot_borrow_repay_history_request.go | 8 + ...borrow_repay_history_request_requestgen.go | 87 ++++++++- 5 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 pkg/exchange/okex/okexapi/get_account_position_risk_request.go create mode 100644 pkg/exchange/okex/okexapi/get_account_position_risk_request_requestgen.go diff --git a/pkg/exchange/okex/okexapi/client_test.go b/pkg/exchange/okex/okexapi/client_test.go index 4222afc17..8b54d94c7 100644 --- a/pkg/exchange/okex/okexapi/client_test.go +++ b/pkg/exchange/okex/okexapi/client_test.go @@ -440,4 +440,14 @@ func TestClient_Margin(t *testing.T) { } } }) + + t.Run("get history for manual borrow", func(t *testing.T) { + req := client.NewGetAccountSpotBorrowRepayHistoryRequest() + req.Currency("BTC") + req.EventType(MarginEventTypeManualBorrow) + historyResp, err2 := req.Do(ctx) + if assert.NoError(t, err2) { + t.Logf("history response: %+v", historyResp) + } + }) } diff --git a/pkg/exchange/okex/okexapi/get_account_position_risk_request.go b/pkg/exchange/okex/okexapi/get_account_position_risk_request.go new file mode 100644 index 000000000..b59e3866c --- /dev/null +++ b/pkg/exchange/okex/okexapi/get_account_position_risk_request.go @@ -0,0 +1,43 @@ +package okexapi + +import ( + "github.com/c9s/requestgen" +) + +//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data +//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data + +type PositionRiskResponse struct { + AdjEq string `json:"adjEq"` + BalData []struct { + Ccy string `json:"ccy"` + DisEq string `json:"disEq"` + Eq string `json:"eq"` + } `json:"balData"` + PosData []struct { + BaseBal string `json:"baseBal"` + Ccy string `json:"ccy"` + InstId string `json:"instId"` + InstType string `json:"instType"` + MgnMode string `json:"mgnMode"` + NotionalCcy string `json:"notionalCcy"` + NotionalUsd string `json:"notionalUsd"` + Pos string `json:"pos"` + PosCcy string `json:"posCcy"` + PosId string `json:"posId"` + PosSide string `json:"posSide"` + QuoteBal string `json:"quoteBal"` + } `json:"posData"` + Ts string `json:"ts"` +} + +//go:generate GetRequest -url "/api/v5/account/account-position-risk" -type GetAccountPositionRiskRequest -responseDataType []PositionRiskResponse +type GetAccountPositionRiskRequest struct { + client requestgen.AuthenticatedAPIClient +} + +func (c *RestClient) NewGetAccountPositionRiskRequest() *GetAccountPositionRiskRequest { + return &GetAccountPositionRiskRequest{ + client: c, + } +} diff --git a/pkg/exchange/okex/okexapi/get_account_position_risk_request_requestgen.go b/pkg/exchange/okex/okexapi/get_account_position_risk_request_requestgen.go new file mode 100644 index 000000000..278cc84c8 --- /dev/null +++ b/pkg/exchange/okex/okexapi/get_account_position_risk_request_requestgen.go @@ -0,0 +1,171 @@ +// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Data -url /api/v5/account/account-position-risk -type GetAccountPositionRiskRequest -responseDataType []PositionRiskResponse"; DO NOT EDIT. + +package okexapi + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + "reflect" + "regexp" +) + +// GetQueryParameters builds and checks the query parameters and returns url.Values +func (g *GetAccountPositionRiskRequest) 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 *GetAccountPositionRiskRequest) 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 *GetAccountPositionRiskRequest) 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 *GetAccountPositionRiskRequest) 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 *GetAccountPositionRiskRequest) GetSlugParameters() (map[string]interface{}, error) { + var params = map[string]interface{}{} + + return params, nil +} + +func (g *GetAccountPositionRiskRequest) 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 *GetAccountPositionRiskRequest) 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 *GetAccountPositionRiskRequest) isVarSlice(_v interface{}) bool { + rt := reflect.TypeOf(_v) + switch rt.Kind() { + case reflect.Slice: + return true + } + return false +} + +func (g *GetAccountPositionRiskRequest) 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 +} + +// GetPath returns the request path of the API +func (g *GetAccountPositionRiskRequest) GetPath() string { + return "/api/v5/account/account-position-risk" +} + +// Do generates the request object and send the request object to the API endpoint +func (g *GetAccountPositionRiskRequest) Do(ctx context.Context) ([]PositionRiskResponse, error) { + + // no body params + var params interface{} + query := url.Values{} + + var apiURL string + + apiURL = g.GetPath() + + 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 APIResponse + + type responseUnmarshaler interface { + Unmarshal(data []byte) error + } + + if unmarshaler, ok := interface{}(&apiResponse).(responseUnmarshaler); ok { + if err := unmarshaler.Unmarshal(response.Body); err != nil { + return nil, err + } + } else { + // The line below checks the content type, however, some API server might not send the correct content type header, + // Hence, this is commented for backward compatibility + // response.IsJSON() + if err := response.DecodeJSON(&apiResponse); err != nil { + return nil, err + } + } + + type responseValidator interface { + Validate() error + } + + if validator, ok := interface{}(&apiResponse).(responseValidator); ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } + var data []PositionRiskResponse + if err := json.Unmarshal(apiResponse.Data, &data); err != nil { + return nil, err + } + return data, nil +} diff --git a/pkg/exchange/okex/okexapi/get_account_spot_borrow_repay_history_request.go b/pkg/exchange/okex/okexapi/get_account_spot_borrow_repay_history_request.go index ec68b2290..f2f563d76 100644 --- a/pkg/exchange/okex/okexapi/get_account_spot_borrow_repay_history_request.go +++ b/pkg/exchange/okex/okexapi/get_account_spot_borrow_repay_history_request.go @@ -1,6 +1,8 @@ package okexapi import ( + "time" + "github.com/c9s/requestgen" "github.com/c9s/bbgo/pkg/fixedpoint" @@ -32,6 +34,12 @@ type MarginHistoryEntry struct { //go:generate GetRequest -url "/api/v5/account/spot-borrow-repay-history" -type GetAccountSpotBorrowRepayHistoryRequest -responseDataType []MarginHistoryEntry type GetAccountSpotBorrowRepayHistoryRequest struct { client requestgen.AuthenticatedAPIClient + + eventType *MarginEventType `param:"type"` + currency *string `param:"ccy"` + after *time.Time `param:"after,milliseconds"` + before *time.Time `param:"before,milliseconds"` + limit *uint64 `param:"limit" defaultValue:"100"` } func (c *RestClient) NewGetAccountSpotBorrowRepayHistoryRequest() *GetAccountSpotBorrowRepayHistoryRequest { diff --git a/pkg/exchange/okex/okexapi/get_account_spot_borrow_repay_history_request_requestgen.go b/pkg/exchange/okex/okexapi/get_account_spot_borrow_repay_history_request_requestgen.go index 8e65e38c2..3c4f27cf0 100644 --- a/pkg/exchange/okex/okexapi/get_account_spot_borrow_repay_history_request_requestgen.go +++ b/pkg/exchange/okex/okexapi/get_account_spot_borrow_repay_history_request_requestgen.go @@ -9,8 +9,35 @@ import ( "net/url" "reflect" "regexp" + "strconv" + "time" ) +func (g *GetAccountSpotBorrowRepayHistoryRequest) EventType(eventType MarginEventType) *GetAccountSpotBorrowRepayHistoryRequest { + g.eventType = &eventType + return g +} + +func (g *GetAccountSpotBorrowRepayHistoryRequest) Currency(currency string) *GetAccountSpotBorrowRepayHistoryRequest { + g.currency = ¤cy + return g +} + +func (g *GetAccountSpotBorrowRepayHistoryRequest) After(after time.Time) *GetAccountSpotBorrowRepayHistoryRequest { + g.after = &after + return g +} + +func (g *GetAccountSpotBorrowRepayHistoryRequest) Before(before time.Time) *GetAccountSpotBorrowRepayHistoryRequest { + g.before = &before + return g +} + +func (g *GetAccountSpotBorrowRepayHistoryRequest) Limit(limit uint64) *GetAccountSpotBorrowRepayHistoryRequest { + g.limit = &limit + return g +} + // GetQueryParameters builds and checks the query parameters and returns url.Values func (g *GetAccountSpotBorrowRepayHistoryRequest) GetQueryParameters() (url.Values, error) { var params = map[string]interface{}{} @@ -26,6 +53,59 @@ func (g *GetAccountSpotBorrowRepayHistoryRequest) GetQueryParameters() (url.Valu // GetParameters builds and checks the parameters and return the result in a map object func (g *GetAccountSpotBorrowRepayHistoryRequest) GetParameters() (map[string]interface{}, error) { var params = map[string]interface{}{} + // check eventType field -> json key type + if g.eventType != nil { + eventType := *g.eventType + + // TEMPLATE check-valid-values + switch eventType { + case MarginEventTypeAutoBorrow, MarginEventTypeAutoRepay, MarginEventTypeManualBorrow, MarginEventTypeManualRepay: + params["type"] = eventType + + default: + return nil, fmt.Errorf("type value %v is invalid", eventType) + + } + // END TEMPLATE check-valid-values + + // assign parameter of eventType + params["type"] = eventType + } else { + } + // check currency field -> json key ccy + if g.currency != nil { + currency := *g.currency + + // assign parameter of currency + params["ccy"] = currency + } else { + } + // check after field -> json key after + if g.after != nil { + after := *g.after + + // assign parameter of after + // convert time.Time to milliseconds time stamp + params["after"] = strconv.FormatInt(after.UnixNano()/int64(time.Millisecond), 10) + } else { + } + // check before field -> json key before + if g.before != nil { + before := *g.before + + // assign parameter of before + // convert time.Time to milliseconds time stamp + params["before"] = strconv.FormatInt(before.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 } @@ -117,9 +197,12 @@ func (g *GetAccountSpotBorrowRepayHistoryRequest) GetPath() string { // Do generates the request object and send the request object to the API endpoint func (g *GetAccountSpotBorrowRepayHistoryRequest) Do(ctx context.Context) ([]MarginHistoryEntry, error) { - // no body params + // empty params for GET operation var params interface{} - query := url.Values{} + query, err := g.GetParametersQuery() + if err != nil { + return nil, err + } var apiURL string