From 411090e9d8a635215007bbb09b193dae22c6c1be Mon Sep 17 00:00:00 2001 From: wuhewuhe Date: Fri, 3 Nov 2023 15:29:17 +0100 Subject: [PATCH] change infra of http client --- bybit_api_client.go | 61 +++++++++++++------ bybit_websocket.go | 2 +- consts.go | 2 +- examples/market/server_time.go | 13 ++-- .../{order_private_ws.go => private_ws.go} | 0 .../{orderbook_ws.go => public_ws.go} | 0 go.mod | 2 +- handlers/errors.go | 8 ++- market.go | 27 +++++--- request.go | 2 +- trade.go | 2 +- 11 files changed, 81 insertions(+), 38 deletions(-) rename examples/websocket/{order_private_ws.go => private_ws.go} (100%) rename examples/websocket/{orderbook_ws.go => public_ws.go} (100%) diff --git a/bybit_api_client.go b/bybit_api_client.go index fae4c17..d9b807d 100644 --- a/bybit_api_client.go +++ b/bybit_api_client.go @@ -1,13 +1,13 @@ -package bybit +package bybit_connector import ( - "bybit.go.api/handlers" "bytes" "context" "crypto/hmac" "crypto/sha256" "encoding/json" "fmt" + handlers "github.com/wuhewuhe/bybit.go.api/handlers" "io" "log" "net/http" @@ -31,6 +31,20 @@ type Client struct { type doFunc func(req *http.Request) (*http.Response, error) +type ClientOption func(*Client) + +func WithDebug(debug bool) ClientOption { + return func(c *Client) { + c.Debug = debug + } +} + +func WithBaseURL(baseURL string) ClientOption { + return func(c *Client) { + c.BaseURL = baseURL + } +} + func currentTimestamp() int64 { return FormatTimestamp(time.Now()) } @@ -40,6 +54,14 @@ func FormatTimestamp(t time.Time) int64 { return t.UnixNano() / int64(time.Millisecond) } +type ServerResponse struct { + RetCode int `json:"retCode"` + RetMsg string `json:"retMsg"` + Result interface{} `json:"result"` + RetExtInfo struct{} `json:"retExtInfo"` + Time int64 `json:"time"` +} + func PrettyPrint(i interface{}) string { s, _ := json.MarshalIndent(i, "", "\t") return string(s) @@ -51,21 +73,22 @@ func (c *Client) debug(format string, v ...interface{}) { } } -// NewClient Create client function for initialising new Bybit client -func NewClient(apiKey string, secretKey string, baseURL ...string) *Client { - url := "https://api.bybit.com" - - if len(baseURL) > 0 { - url = baseURL[0] - } - - return &Client{ +// NewBybitHttpClient NewClient Create client function for initialising new Bybit client +func NewBybitHttpClient(apiKey string, secretKey string, options ...ClientOption) *Client { + c := &Client{ APIKey: apiKey, SecretKey: secretKey, - BaseURL: url, + BaseURL: "https://api.bybit.com", HTTPClient: http.DefaultClient, Logger: log.New(os.Stderr, Name, log.LstdFlags), } + + // Apply the provided options + for _, opt := range options { + opt(c) + } + + return c } func (c *Client) parseRequest(r *request, opts ...RequestOption) (err error) { @@ -120,7 +143,7 @@ func (c *Client) parseRequest(r *request, opts ...RequestOption) (err error) { if queryString != "" { fullURL = fmt.Sprintf("%s?%s", fullURL, queryString) } - // c.debug("full url: %s, body: %s", fullURL, bodyString) + c.debug("full url: %s, body: %s", fullURL, bodyString) r.fullURL = fullURL r.header = header r.body = body @@ -135,7 +158,7 @@ func (c *Client) callAPI(ctx context.Context, r *request, opts ...RequestOption) } req = req.WithContext(ctx) req.Header = r.header - // c.debug("request: %#v", req) + c.debug("request: %#v", req) f := c.do if f == nil { f = c.HTTPClient.Do @@ -156,15 +179,17 @@ func (c *Client) callAPI(ctx context.Context, r *request, opts ...RequestOption) err = cerr } }() - // c.debug("response: %#v", res) + c.debug("response: %#v", res) c.debug("response body: %s", string(data)) - // c.debug("response status code: %d", res.StatusCode) + c.debug("response status code: %d", res.StatusCode) if res.StatusCode >= http.StatusBadRequest { - apiErr := new(handlers.APIError) + var ( + apiErr = new(handlers.APIError) + ) e := json.Unmarshal(data, apiErr) if e != nil { - // c.debug("failed to unmarshal json: %s", e) + c.debug("failed to unmarshal json: %s", e) } return nil, apiErr } diff --git a/bybit_websocket.go b/bybit_websocket.go index 4d63923..e2bc974 100644 --- a/bybit_websocket.go +++ b/bybit_websocket.go @@ -1,4 +1,4 @@ -package bybit +package bybit_connector import ( "crypto/hmac" diff --git a/consts.go b/consts.go index 8a630e5..e8f1889 100644 --- a/consts.go +++ b/consts.go @@ -1,4 +1,4 @@ -package bybit +package bybit_connector const ( Name = "bybit.api.go" diff --git a/examples/market/server_time.go b/examples/market/server_time.go index 77d1d5a..054cb5f 100644 --- a/examples/market/server_time.go +++ b/examples/market/server_time.go @@ -1,9 +1,9 @@ package main import ( - bybit "bybit.go.api" "context" "fmt" + bybit "github.com/wuhewuhe/bybit.go.api" ) func main() { @@ -12,12 +12,13 @@ func main() { func ServerTime() { - client := bybit.NewClient("", "") - - // set to debug mode - client.Debug = true + client := bybit.NewBybitHttpClient("", "") // NewServerTimeService - serverTime := client.NewServerTimeService().Do(context.Background()) + serverTime, err := client.NewServerTimeService().Do(context.Background()) + if err != nil { + fmt.Println(err) + return + } fmt.Println(bybit.PrettyPrint(serverTime)) } diff --git a/examples/websocket/order_private_ws.go b/examples/websocket/private_ws.go similarity index 100% rename from examples/websocket/order_private_ws.go rename to examples/websocket/private_ws.go diff --git a/examples/websocket/orderbook_ws.go b/examples/websocket/public_ws.go similarity index 100% rename from examples/websocket/orderbook_ws.go rename to examples/websocket/public_ws.go diff --git a/go.mod b/go.mod index 22a06bc..653178b 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module bybit.go.api +module github.com/wuhewuhe/bybit.go.api go 1.21 diff --git a/handlers/errors.go b/handlers/errors.go index a2ab602..d354429 100644 --- a/handlers/errors.go +++ b/handlers/errors.go @@ -1,6 +1,9 @@ package handlers -import "fmt" +import ( + "errors" + "fmt" +) // APIError define API error when response status is 4xx or 5xx type APIError struct { @@ -15,6 +18,7 @@ func (e APIError) Error() string { // IsAPIError check if e is an API error func IsAPIError(e error) bool { - _, ok := e.(*APIError) + var APIError *APIError + ok := errors.As(e, &APIError) return ok } diff --git a/market.go b/market.go index 448335b..aba27bd 100644 --- a/market.go +++ b/market.go @@ -1,23 +1,36 @@ -package bybit +package bybit_connector import ( "context" + "encoding/json" "net/http" ) -// Binance Check Server Time endpoint (GET /v5/market/time) +type ServerTimeResult struct { + TimeSecond string `json:"timeSecond"` + TimeNano string `json:"timeNano"` +} + +// ServerTime Binance Check Server Time endpoint (GET /v5/market/time) type ServerTime struct { c *Client } -// Send the request -func (s *ServerTime) Do(ctx context.Context, opts ...RequestOption) (res []byte) { +// Do Send the request +func (s *ServerTime) Do(ctx context.Context, opts ...RequestOption) (res *ServerResponse, err error) { r := &request{ method: http.MethodGet, endpoint: "/v5/market/time", secType: secTypeNone, } - data, _ := s.c.callAPI(ctx, r, opts...) - res = data - return res + data, err := s.c.callAPI(ctx, r, opts...) + if err != nil { + return nil, err + } + res = new(ServerResponse) + err = json.Unmarshal(data, res) + if err != nil { + return nil, err + } + return res, nil } diff --git a/request.go b/request.go index 015bf7d..da54f9a 100644 --- a/request.go +++ b/request.go @@ -1,4 +1,4 @@ -package bybit +package bybit_connector import ( "fmt" diff --git a/trade.go b/trade.go index 2f7bbfd..06c9e41 100644 --- a/trade.go +++ b/trade.go @@ -1 +1 @@ -package bybit +package bybit_connector