diff --git a/go.mod b/go.mod index 91eca5f8b..57f0bf099 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/Masterminds/squirrel v1.5.3 github.com/adshao/go-binance/v2 v2.4.2 github.com/c-bata/goptuna v0.8.1 - github.com/c9s/requestgen v1.3.5 + github.com/c9s/requestgen v1.3.6 github.com/c9s/rockhopper v1.2.2-0.20220617053729-ffdc87df194b github.com/cenkalti/backoff/v4 v4.2.0 github.com/cheggaaa/pb/v3 v3.0.8 diff --git a/go.sum b/go.sum index 710eba662..56327767e 100644 --- a/go.sum +++ b/go.sum @@ -86,6 +86,8 @@ github.com/c9s/requestgen v1.3.4 h1:kK2rIO3OAt9JoY5gT0OSkSpq0dy/+JeuI22FwSKpUrY= github.com/c9s/requestgen v1.3.4/go.mod h1:wp4saiPdh0zLF5AkopGCqPQfy9Q5xvRh+TQBOA1l1r4= github.com/c9s/requestgen v1.3.5 h1:iGYAP0rWQW3JOo+Z3S0SoenSt581IQ9mupJxRFCrCJs= github.com/c9s/requestgen v1.3.5/go.mod h1:QwkZudcv84kJ8g9+E0RDTj+13btFXbTvv2aI+zbuLbc= +github.com/c9s/requestgen v1.3.6 h1:ul7dZ2uwGYjNBjreooRfSY10WTXvQmQSjZsHebz6QfE= +github.com/c9s/requestgen v1.3.6/go.mod h1:QwkZudcv84kJ8g9+E0RDTj+13btFXbTvv2aI+zbuLbc= github.com/c9s/rockhopper v1.2.2-0.20220617053729-ffdc87df194b h1:wT8c03PHLv7+nZUIGqxAzRvIfYHNxMCNVWwvdGkOXTs= github.com/c9s/rockhopper v1.2.2-0.20220617053729-ffdc87df194b/go.mod h1:EKObf66Cp7erWxym2de+07qNN5T1N9PXxHdh97N44EQ= github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= diff --git a/pkg/exchange/bybit/bybitapi/cancel_order_request_requestgen.go b/pkg/exchange/bybit/bybitapi/cancel_order_request_requestgen.go index ad168ded9..715bf4214 100644 --- a/pkg/exchange/bybit/bybitapi/cancel_order_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/cancel_order_request_requestgen.go @@ -187,6 +187,12 @@ func (p *CancelOrderRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (p *CancelOrderRequest) GetPath() string { + return "/v5/order/cancel" +} + +// Do generates the request object and send the request object to the API endpoint func (p *CancelOrderRequest) Do(ctx context.Context) (*CancelOrderResponse, error) { params, err := p.GetParameters() @@ -195,7 +201,9 @@ func (p *CancelOrderRequest) Do(ctx context.Context) (*CancelOrderResponse, erro } query := url.Values{} - apiURL := "/v5/order/cancel" + var apiURL string + + apiURL = p.GetPath() req, err := p.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params) if err != nil { @@ -211,6 +219,16 @@ func (p *CancelOrderRequest) Do(ctx context.Context) (*CancelOrderResponse, erro if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } var data CancelOrderResponse if err := json.Unmarshal(apiResponse.Result, &data); err != nil { return nil, err diff --git a/pkg/exchange/bybit/bybitapi/client.go b/pkg/exchange/bybit/bybitapi/client.go index 034d29750..4d9f5818b 100644 --- a/pkg/exchange/bybit/bybitapi/client.go +++ b/pkg/exchange/bybit/bybitapi/client.go @@ -162,10 +162,25 @@ sample: */ type APIResponse struct { - RetCode uint `json:"retCode"` - RetMsg string `json:"retMsg"` - Result json.RawMessage `json:"result"` + // Success/Error code + RetCode uint `json:"retCode"` + // Success/Error msg. OK, success, SUCCESS indicate a successful response + RetMsg string `json:"retMsg"` + // Business data result + Result json.RawMessage `json:"result"` + // Extend info. Most of the time, it is {} RetExtInfo json.RawMessage `json:"retExtInfo"` // Time is current timestamp (ms) Time types.MillisecondTimestamp `json:"time"` } + +func (a APIResponse) Validate() error { + if a.RetCode != 0 { + return a.Error() + } + return nil +} + +func (a APIResponse) Error() error { + return fmt.Errorf("retCode: %d, retMsg: %s, retExtInfo: %q, time: %s", a.RetCode, a.RetMsg, a.RetExtInfo, a.Time) +} diff --git a/pkg/exchange/bybit/bybitapi/get_account_info_request_requestgen.go b/pkg/exchange/bybit/bybitapi/get_account_info_request_requestgen.go index 8d9be7df7..c7907f404 100644 --- a/pkg/exchange/bybit/bybitapi/get_account_info_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/get_account_info_request_requestgen.go @@ -109,13 +109,21 @@ func (g *GetAccountInfoRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (g *GetAccountInfoRequest) GetPath() string { + return "/v5/account/info" +} + +// Do generates the request object and send the request object to the API endpoint func (g *GetAccountInfoRequest) Do(ctx context.Context) (*AccountInfo, error) { // no body params var params interface{} query := url.Values{} - apiURL := "/v5/account/info" + var apiURL string + + apiURL = g.GetPath() req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) if err != nil { @@ -131,6 +139,16 @@ func (g *GetAccountInfoRequest) Do(ctx context.Context) (*AccountInfo, error) { if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } var data AccountInfo if err := json.Unmarshal(apiResponse.Result, &data); err != nil { return nil, err diff --git a/pkg/exchange/bybit/bybitapi/get_fee_rates_request_requestgen.go b/pkg/exchange/bybit/bybitapi/get_fee_rates_request_requestgen.go index ac182c22a..e9db73677 100644 --- a/pkg/exchange/bybit/bybitapi/get_fee_rates_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/get_fee_rates_request_requestgen.go @@ -156,6 +156,12 @@ func (g *GetFeeRatesRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (g *GetFeeRatesRequest) GetPath() string { + return "/v5/account/fee-rate" +} + +// Do generates the request object and send the request object to the API endpoint func (g *GetFeeRatesRequest) Do(ctx context.Context) (*FeeRates, error) { // no body params @@ -165,7 +171,9 @@ func (g *GetFeeRatesRequest) Do(ctx context.Context) (*FeeRates, error) { return nil, err } - apiURL := "/v5/account/fee-rate" + var apiURL string + + apiURL = g.GetPath() req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) if err != nil { @@ -181,6 +189,16 @@ func (g *GetFeeRatesRequest) Do(ctx context.Context) (*FeeRates, error) { if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } var data FeeRates if err := json.Unmarshal(apiResponse.Result, &data); err != nil { return nil, err diff --git a/pkg/exchange/bybit/bybitapi/get_instruments_info_request_requestgen.go b/pkg/exchange/bybit/bybitapi/get_instruments_info_request_requestgen.go index 7e9a6536a..ed2fc884f 100644 --- a/pkg/exchange/bybit/bybitapi/get_instruments_info_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/get_instruments_info_request_requestgen.go @@ -169,6 +169,12 @@ func (g *GetInstrumentsInfoRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (g *GetInstrumentsInfoRequest) GetPath() string { + return "/v5/market/instruments-info" +} + +// Do generates the request object and send the request object to the API endpoint func (g *GetInstrumentsInfoRequest) Do(ctx context.Context) (*InstrumentsInfo, error) { // no body params @@ -178,7 +184,9 @@ func (g *GetInstrumentsInfoRequest) Do(ctx context.Context) (*InstrumentsInfo, e return nil, err } - apiURL := "/v5/market/instruments-info" + var apiURL string + + apiURL = g.GetPath() req, err := g.client.NewRequest(ctx, "GET", apiURL, query, params) if err != nil { @@ -194,6 +202,16 @@ func (g *GetInstrumentsInfoRequest) Do(ctx context.Context) (*InstrumentsInfo, e if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } var data InstrumentsInfo if err := json.Unmarshal(apiResponse.Result, &data); err != nil { return nil, err diff --git a/pkg/exchange/bybit/bybitapi/get_k_lines_request_requestgen.go b/pkg/exchange/bybit/bybitapi/get_k_lines_request_requestgen.go index d6b3d06c3..e08072a7b 100644 --- a/pkg/exchange/bybit/bybitapi/get_k_lines_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/get_k_lines_request_requestgen.go @@ -204,6 +204,12 @@ func (g *GetKLinesRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (g *GetKLinesRequest) GetPath() string { + return "/v5/market/kline" +} + +// Do generates the request object and send the request object to the API endpoint func (g *GetKLinesRequest) Do(ctx context.Context) (*KLinesResponse, error) { // no body params @@ -213,7 +219,9 @@ func (g *GetKLinesRequest) Do(ctx context.Context) (*KLinesResponse, error) { return nil, err } - apiURL := "/v5/market/kline" + var apiURL string + + apiURL = g.GetPath() req, err := g.client.NewRequest(ctx, "GET", apiURL, query, params) if err != nil { @@ -229,6 +237,16 @@ func (g *GetKLinesRequest) Do(ctx context.Context) (*KLinesResponse, error) { if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } var data KLinesResponse if err := json.Unmarshal(apiResponse.Result, &data); err != nil { return nil, err diff --git a/pkg/exchange/bybit/bybitapi/get_open_orders_request_requestgen.go b/pkg/exchange/bybit/bybitapi/get_open_orders_request_requestgen.go index aa9d13cc6..3b7c29ba4 100644 --- a/pkg/exchange/bybit/bybitapi/get_open_orders_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/get_open_orders_request_requestgen.go @@ -258,6 +258,12 @@ func (g *GetOpenOrdersRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (g *GetOpenOrdersRequest) GetPath() string { + return "/v5/order/realtime" +} + +// Do generates the request object and send the request object to the API endpoint func (g *GetOpenOrdersRequest) Do(ctx context.Context) (*OrdersResponse, error) { // no body params @@ -267,7 +273,9 @@ func (g *GetOpenOrdersRequest) Do(ctx context.Context) (*OrdersResponse, error) return nil, err } - apiURL := "/v5/order/realtime" + var apiURL string + + apiURL = g.GetPath() req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) if err != nil { @@ -283,6 +291,16 @@ func (g *GetOpenOrdersRequest) Do(ctx context.Context) (*OrdersResponse, error) if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } var data OrdersResponse if err := json.Unmarshal(apiResponse.Result, &data); err != nil { return nil, err diff --git a/pkg/exchange/bybit/bybitapi/get_order_history_request.go b/pkg/exchange/bybit/bybitapi/get_order_histories_request.go similarity index 100% rename from pkg/exchange/bybit/bybitapi/get_order_history_request.go rename to pkg/exchange/bybit/bybitapi/get_order_histories_request.go diff --git a/pkg/exchange/bybit/bybitapi/get_order_histories_request_requestgen.go b/pkg/exchange/bybit/bybitapi/get_order_histories_request_requestgen.go index 479d9eff4..62b362410 100644 --- a/pkg/exchange/bybit/bybitapi/get_order_histories_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/get_order_histories_request_requestgen.go @@ -262,6 +262,12 @@ func (g *GetOrderHistoriesRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (g *GetOrderHistoriesRequest) GetPath() string { + return "/v5/order/history" +} + +// Do generates the request object and send the request object to the API endpoint func (g *GetOrderHistoriesRequest) Do(ctx context.Context) (*OrdersResponse, error) { // no body params @@ -271,7 +277,9 @@ func (g *GetOrderHistoriesRequest) Do(ctx context.Context) (*OrdersResponse, err return nil, err } - apiURL := "/v5/order/history" + var apiURL string + + apiURL = g.GetPath() req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) if err != nil { @@ -287,6 +295,16 @@ func (g *GetOrderHistoriesRequest) Do(ctx context.Context) (*OrdersResponse, err if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } var data OrdersResponse if err := json.Unmarshal(apiResponse.Result, &data); err != nil { return nil, err diff --git a/pkg/exchange/bybit/bybitapi/get_tickers_request_requestgen.go b/pkg/exchange/bybit/bybitapi/get_tickers_request_requestgen.go index 0f85973d8..59a81a428 100644 --- a/pkg/exchange/bybit/bybitapi/get_tickers_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/get_tickers_request_requestgen.go @@ -143,6 +143,12 @@ func (g *GetTickersRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (g *GetTickersRequest) GetPath() string { + return "/v5/market/tickers" +} + +// Do generates the request object and send the request object to the API endpoint func (g *GetTickersRequest) Do(ctx context.Context) (*APIResponse, error) { // no body params @@ -152,7 +158,9 @@ func (g *GetTickersRequest) Do(ctx context.Context) (*APIResponse, error) { return nil, err } - apiURL := "/v5/market/tickers" + var apiURL string + + apiURL = g.GetPath() req, err := g.client.NewRequest(ctx, "GET", apiURL, query, params) if err != nil { @@ -168,5 +176,15 @@ func (g *GetTickersRequest) Do(ctx context.Context) (*APIResponse, error) { if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } return &apiResponse, nil } diff --git a/pkg/exchange/bybit/bybitapi/get_wallet_balances_request_requestgen.go b/pkg/exchange/bybit/bybitapi/get_wallet_balances_request_requestgen.go index 14ae4029c..601d26ce9 100644 --- a/pkg/exchange/bybit/bybitapi/get_wallet_balances_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/get_wallet_balances_request_requestgen.go @@ -143,6 +143,12 @@ func (g *GetWalletBalancesRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (g *GetWalletBalancesRequest) GetPath() string { + return "/v5/account/wallet-balance" +} + +// Do generates the request object and send the request object to the API endpoint func (g *GetWalletBalancesRequest) Do(ctx context.Context) (*WalletBalancesResponse, error) { // no body params @@ -152,7 +158,9 @@ func (g *GetWalletBalancesRequest) Do(ctx context.Context) (*WalletBalancesRespo return nil, err } - apiURL := "/v5/account/wallet-balance" + var apiURL string + + apiURL = g.GetPath() req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) if err != nil { @@ -168,6 +176,16 @@ func (g *GetWalletBalancesRequest) Do(ctx context.Context) (*WalletBalancesRespo if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } var data WalletBalancesResponse if err := json.Unmarshal(apiResponse.Result, &data); err != nil { return nil, err diff --git a/pkg/exchange/bybit/bybitapi/place_order_request_requestgen.go b/pkg/exchange/bybit/bybitapi/place_order_request_requestgen.go index bb85937ce..95e3aaa0d 100644 --- a/pkg/exchange/bybit/bybitapi/place_order_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/place_order_request_requestgen.go @@ -496,6 +496,12 @@ func (p *PlaceOrderRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (p *PlaceOrderRequest) GetPath() string { + return "/v5/order/create" +} + +// Do generates the request object and send the request object to the API endpoint func (p *PlaceOrderRequest) Do(ctx context.Context) (*PlaceOrderResponse, error) { params, err := p.GetParameters() @@ -504,7 +510,9 @@ func (p *PlaceOrderRequest) Do(ctx context.Context) (*PlaceOrderResponse, error) } query := url.Values{} - apiURL := "/v5/order/create" + var apiURL string + + apiURL = p.GetPath() req, err := p.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params) if err != nil { @@ -520,6 +528,16 @@ func (p *PlaceOrderRequest) Do(ctx context.Context) (*PlaceOrderResponse, error) if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } var data PlaceOrderResponse if err := json.Unmarshal(apiResponse.Result, &data); err != nil { return nil, err diff --git a/pkg/exchange/bybit/bybitapi/v3/get_trades_request_requestgen.go b/pkg/exchange/bybit/bybitapi/v3/get_trades_request_requestgen.go index 00d7dd80a..3336db113 100644 --- a/pkg/exchange/bybit/bybitapi/v3/get_trades_request_requestgen.go +++ b/pkg/exchange/bybit/bybitapi/v3/get_trades_request_requestgen.go @@ -205,6 +205,12 @@ func (g *GetTradesRequest) GetSlugsMap() (map[string]string, error) { return slugs, nil } +// GetPath returns the request path of the API +func (g *GetTradesRequest) GetPath() string { + return "/spot/v3/private/my-trades" +} + +// Do generates the request object and send the request object to the API endpoint func (g *GetTradesRequest) Do(ctx context.Context) (*TradesResponse, error) { // no body params @@ -214,7 +220,9 @@ func (g *GetTradesRequest) Do(ctx context.Context) (*TradesResponse, error) { return nil, err } - apiURL := "/spot/v3/private/my-trades" + var apiURL string + + apiURL = g.GetPath() req, err := g.client.NewAuthenticatedRequest(ctx, "GET", apiURL, query, params) if err != nil { @@ -230,6 +238,16 @@ func (g *GetTradesRequest) Do(ctx context.Context) (*TradesResponse, error) { if err := response.DecodeJSON(&apiResponse); err != nil { return nil, err } + + type responseValidator interface { + Validate() error + } + validator, ok := interface{}(apiResponse).(responseValidator) + if ok { + if err := validator.Validate(); err != nil { + return nil, err + } + } var data TradesResponse if err := json.Unmarshal(apiResponse.Result, &data); err != nil { return nil, err