From c63bc2dd74ea49b69496d99738831488f5a5d6e9 Mon Sep 17 00:00:00 2001 From: dasbd72 Date: Sun, 3 Mar 2024 18:42:37 +0800 Subject: [PATCH] Refactor binance package structure --- binance/client.go | 10 ++ binance/{time_test.go => client_test.go} | 28 ++++++ binance/market_data_service.go | 97 +++---------------- binance/{definition.go => pkg/cast/cast.go} | 2 +- .../cast/cast_test.go} | 2 +- binance/pkg/models/market_data.go | 84 ++++++++++++++++ binance/pkg/models/wallet.go | 16 +++ binance/time.go | 12 --- binance/wallet_service.go | 21 +--- manager/balance.go | 4 +- 10 files changed, 160 insertions(+), 116 deletions(-) rename binance/{time_test.go => client_test.go} (58%) rename binance/{definition.go => pkg/cast/cast.go} (98%) rename binance/{definition_test.go => pkg/cast/cast_test.go} (99%) create mode 100644 binance/pkg/models/market_data.go create mode 100644 binance/pkg/models/wallet.go delete mode 100644 binance/time.go diff --git a/binance/client.go b/binance/client.go index 0a37f8f..35c15c5 100644 --- a/binance/client.go +++ b/binance/client.go @@ -10,6 +10,7 @@ import ( "io" "net/http" "net/url" + "time" ) type Client struct { @@ -149,3 +150,12 @@ func sign(secret, message string) string { mac.Write([]byte(message)) return fmt.Sprintf("%x", mac.Sum(nil)) } + +func currentTimestamp() int64 { + return formatTimestamp(time.Now()) +} + +// formatTimestamp formats a time into Unix timestamp in milliseconds, as requested by Binance. +func formatTimestamp(t time.Time) int64 { + return t.UnixNano() / int64(time.Millisecond) +} diff --git a/binance/time_test.go b/binance/client_test.go similarity index 58% rename from binance/time_test.go rename to binance/client_test.go index 7e22803..c975168 100644 --- a/binance/time_test.go +++ b/binance/client_test.go @@ -5,6 +5,34 @@ import ( "time" ) +func Test_sign(t *testing.T) { + type args struct { + secret string + message string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "testcase 1", + args: args{ + secret: "secret", + message: "message", + }, + want: "8b5f48702995c1598c573db1e21866a9b825d4a794d169d7060a03605796360b", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := sign(tt.args.secret, tt.args.message); got != tt.want { + t.Errorf("sign() = %v, want %v", got, tt.want) + } + }) + } +} + func TestFormatTimestamp(t *testing.T) { t.Parallel() diff --git a/binance/market_data_service.go b/binance/market_data_service.go index e61f435..a953b8e 100644 --- a/binance/market_data_service.go +++ b/binance/market_data_service.go @@ -4,66 +4,11 @@ import ( "context" "encoding/json" "net/http" -) - -type ( - GetPingResponse struct { - } - - GetServerTimeResponse struct { - ServerTime int64 `json:"serverTime"` - } - - GetExchangeInfoResponse struct { - Timezone string `json:"timezone"` - ServerTime int64 `json:"serverTime"` - RateLimits []interface{} - ExchangeFilters []interface{} - Symbols []struct { - Symbol string `json:"symbol"` - Status string `json:"status"` - BaseAsset string `json:"baseAsset"` - BaseAssetPrecision int `json:"baseAssetPrecision"` - QuoteAsset string `json:"quoteAsset"` - QuotePrecision int `json:"quotePrecision"` - QuoteAssetPrecision int `json:"quoteAssetPrecision"` - OrderTypes []string `json:"orderTypes"` - IcebergAllowed bool `json:"icebergAllowed"` - OcoAllowed bool `json:"ocoAllowed"` - QuoteOrderQtyMarketAllowed bool `json:"quoteOrderQtyMarketAllowed"` - AllowTrailingStop bool `json:"allowTrailingStop"` - CancelReplaceAllowed bool `json:"cancelReplaceAllowed"` - IsSpotTradingAllowed bool `json:"isSpotTradingAllowed"` - IsMarginTradingAllowed bool `json:"isMarginTradingAllowed"` - Filters []interface{} `json:"filters"` - Permissions []string `json:"permissions"` - DefaultSelfTradePreventionMode string `json:"defaultSelfTradePreventionMode"` - AllowedSelfTradePreventionModes []string `json:"allowedSelfTradePreventionModes"` - } - } - - GetOrderBookRequest struct { - params map[string]interface{} - } - - GetOrderBookResponse struct { - LastUpdateID int64 `json:"lastUpdateId"` - Bids [][]JSONFloat64 `json:"bids"` - Asks [][]JSONFloat64 `json:"asks"` - } - - GetAveragePriceRequest struct { - params map[string]interface{} - } - GetAveragePriceResponse struct { - Mins int `json:"mins"` - Price JSONFloat64 `json:"price"` - CloseTime int64 `json:"closeTime"` - } + "github.com/dasbd72/go-exchange-sdk/binance/pkg/models" ) -func (c *Client) GetPing(ctx context.Context, opts ...RequestOption) (*GetPingResponse, error) { +func (c *Client) GetPing(ctx context.Context, opts ...RequestOption) (*models.GetPingResponse, error) { res, err := c.CallAPI(ctx, Request_builder{ Method: http.MethodGet, Endpoint: "/api/v3/ping", @@ -72,7 +17,7 @@ func (c *Client) GetPing(ctx context.Context, opts ...RequestOption) (*GetPingRe if err != nil { return nil, err } - data := &GetPingResponse{} + data := &models.GetPingResponse{} err = json.Unmarshal(res, data) if err != nil { return nil, err @@ -80,7 +25,7 @@ func (c *Client) GetPing(ctx context.Context, opts ...RequestOption) (*GetPingRe return data, nil } -func (c *Client) GetServerTime(ctx context.Context, opts ...RequestOption) (*GetServerTimeResponse, error) { +func (c *Client) GetServerTime(ctx context.Context, opts ...RequestOption) (*models.GetServerTimeResponse, error) { res, err := c.CallAPI(ctx, Request_builder{ Method: http.MethodGet, Endpoint: "/api/v3/time", @@ -89,7 +34,7 @@ func (c *Client) GetServerTime(ctx context.Context, opts ...RequestOption) (*Get if err != nil { return nil, err } - data := &GetServerTimeResponse{} + data := &models.GetServerTimeResponse{} err = json.Unmarshal(res, data) if err != nil { return nil, err @@ -97,7 +42,7 @@ func (c *Client) GetServerTime(ctx context.Context, opts ...RequestOption) (*Get return data, nil } -func (c *Client) GetExchangeInfo(ctx context.Context, opts ...RequestOption) (*GetExchangeInfoResponse, error) { +func (c *Client) GetExchangeInfo(ctx context.Context, opts ...RequestOption) (*models.GetExchangeInfoResponse, error) { res, err := c.CallAPI(ctx, Request_builder{ Method: http.MethodGet, Endpoint: "/api/v3/exchangeInfo", @@ -106,7 +51,7 @@ func (c *Client) GetExchangeInfo(ctx context.Context, opts ...RequestOption) (*G if err != nil { return nil, err } - data := &GetExchangeInfoResponse{} + data := &models.GetExchangeInfoResponse{} err = json.Unmarshal(res, data) if err != nil { return nil, err @@ -114,25 +59,17 @@ func (c *Client) GetExchangeInfo(ctx context.Context, opts ...RequestOption) (*G return data, nil } -func NewGetOrderBookRequest(symbol string) *GetOrderBookRequest { - return &GetOrderBookRequest{ - params: map[string]interface{}{ - "symbol": symbol, - }, - } -} - -func (c *Client) GetOrderBook(ctx context.Context, req *GetOrderBookRequest, opts ...RequestOption) (*GetOrderBookResponse, error) { +func (c *Client) GetOrderBook(ctx context.Context, req *models.GetOrderBookRequest, opts ...RequestOption) (*models.GetOrderBookResponse, error) { res, err := c.CallAPI(ctx, Request_builder{ Method: http.MethodGet, Endpoint: "/api/v3/depth", SecType: SecTypeNone, - Params: req.params, + Params: req.Params(), }.Build(), opts...) if err != nil { return nil, err } - data := &GetOrderBookResponse{} + data := &models.GetOrderBookResponse{} err = json.Unmarshal(res, data) if err != nil { return nil, err @@ -140,25 +77,17 @@ func (c *Client) GetOrderBook(ctx context.Context, req *GetOrderBookRequest, opt return data, nil } -func NewGetAveragePriceRequest(symbol string) *GetAveragePriceRequest { - return &GetAveragePriceRequest{ - params: map[string]interface{}{ - "symbol": symbol, - }, - } -} - -func (c *Client) GetAveragePrice(ctx context.Context, req *GetAveragePriceRequest, opts ...RequestOption) (*GetAveragePriceResponse, error) { +func (c *Client) GetAveragePrice(ctx context.Context, req *models.GetAveragePriceRequest, opts ...RequestOption) (*models.GetAveragePriceResponse, error) { res, err := c.CallAPI(ctx, Request_builder{ Method: http.MethodGet, Endpoint: "/api/v3/avgPrice", SecType: SecTypeNone, - Params: req.params, + Params: req.Params(), }.Build(), opts...) if err != nil { return nil, err } - data := &GetAveragePriceResponse{} + data := &models.GetAveragePriceResponse{} err = json.Unmarshal(res, data) if err != nil { return nil, err diff --git a/binance/definition.go b/binance/pkg/cast/cast.go similarity index 98% rename from binance/definition.go rename to binance/pkg/cast/cast.go index ddc5620..e6609f5 100644 --- a/binance/definition.go +++ b/binance/pkg/cast/cast.go @@ -1,4 +1,4 @@ -package binance +package cast import ( "strconv" diff --git a/binance/definition_test.go b/binance/pkg/cast/cast_test.go similarity index 99% rename from binance/definition_test.go rename to binance/pkg/cast/cast_test.go index 4d6b06f..a97217b 100644 --- a/binance/definition_test.go +++ b/binance/pkg/cast/cast_test.go @@ -1,4 +1,4 @@ -package binance +package cast import ( "strconv" diff --git a/binance/pkg/models/market_data.go b/binance/pkg/models/market_data.go new file mode 100644 index 0000000..e76233f --- /dev/null +++ b/binance/pkg/models/market_data.go @@ -0,0 +1,84 @@ +package models + +import "github.com/dasbd72/go-exchange-sdk/binance/pkg/cast" + +type ( + GetPingResponse struct { + } + + GetServerTimeResponse struct { + ServerTime int64 `json:"serverTime"` + } + + GetExchangeInfoResponse struct { + Timezone string `json:"timezone"` + ServerTime int64 `json:"serverTime"` + RateLimits []interface{} + ExchangeFilters []interface{} + Symbols []struct { + Symbol string `json:"symbol"` + Status string `json:"status"` + BaseAsset string `json:"baseAsset"` + BaseAssetPrecision int `json:"baseAssetPrecision"` + QuoteAsset string `json:"quoteAsset"` + QuotePrecision int `json:"quotePrecision"` + QuoteAssetPrecision int `json:"quoteAssetPrecision"` + OrderTypes []string `json:"orderTypes"` + IcebergAllowed bool `json:"icebergAllowed"` + OcoAllowed bool `json:"ocoAllowed"` + QuoteOrderQtyMarketAllowed bool `json:"quoteOrderQtyMarketAllowed"` + AllowTrailingStop bool `json:"allowTrailingStop"` + CancelReplaceAllowed bool `json:"cancelReplaceAllowed"` + IsSpotTradingAllowed bool `json:"isSpotTradingAllowed"` + IsMarginTradingAllowed bool `json:"isMarginTradingAllowed"` + Filters []interface{} `json:"filters"` + Permissions []string `json:"permissions"` + DefaultSelfTradePreventionMode string `json:"defaultSelfTradePreventionMode"` + AllowedSelfTradePreventionModes []string `json:"allowedSelfTradePreventionModes"` + } + } + + GetOrderBookRequest struct { + params map[string]interface{} + } + + GetOrderBookResponse struct { + LastUpdateID int64 `json:"lastUpdateId"` + Bids [][]cast.JSONFloat64 `json:"bids"` + Asks [][]cast.JSONFloat64 `json:"asks"` + } + + GetAveragePriceRequest struct { + params map[string]interface{} + } + + GetAveragePriceResponse struct { + Mins int `json:"mins"` + Price cast.JSONFloat64 `json:"price"` + CloseTime int64 `json:"closeTime"` + } +) + +func NewGetOrderBookRequest(symbol string) *GetOrderBookRequest { + return &GetOrderBookRequest{ + params: map[string]interface{}{ + "symbol": symbol, + }, + } +} + +func (data *GetOrderBookRequest) Params() map[string]interface{} { + return data.params +} + +func NewGetAveragePriceRequest(symbol string) *GetAveragePriceRequest { + return &GetAveragePriceRequest{ + params: map[string]interface{}{ + "symbol": symbol, + }, + } +} + +func (data *GetAveragePriceRequest) Params() map[string]interface{} { + return data.params +} diff --git a/binance/pkg/models/wallet.go b/binance/pkg/models/wallet.go new file mode 100644 index 0000000..788bcfc --- /dev/null +++ b/binance/pkg/models/wallet.go @@ -0,0 +1,16 @@ +package models + +import "github.com/dasbd72/go-exchange-sdk/binance/pkg/cast" + +type ( + GetWalletStatusResponse struct { + Status int `json:"status"` + Msg string `json:"msg"` + } + + GetUserWalletBalanceResponse []struct { + Activate bool `json:"activate"` + Balance cast.JSONFloat64 `json:"balance"` // in BTC + WalletName string `json:"walletName"` + } +) diff --git a/binance/time.go b/binance/time.go deleted file mode 100644 index 9af243a..0000000 --- a/binance/time.go +++ /dev/null @@ -1,12 +0,0 @@ -package binance - -import "time" - -func currentTimestamp() int64 { - return formatTimestamp(time.Now()) -} - -// formatTimestamp formats a time into Unix timestamp in milliseconds, as requested by Binance. -func formatTimestamp(t time.Time) int64 { - return t.UnixNano() / int64(time.Millisecond) -} diff --git a/binance/wallet_service.go b/binance/wallet_service.go index 77815cd..ceff580 100644 --- a/binance/wallet_service.go +++ b/binance/wallet_service.go @@ -4,22 +4,11 @@ import ( "context" "encoding/json" "net/http" -) - -type ( - GetWalletStatusResponse struct { - Status int `json:"status"` - Msg string `json:"msg"` - } - GetUserWalletBalanceResponse []struct { - Activate bool `json:"activate"` - Balance JSONFloat64 `json:"balance"` // in BTC - WalletName string `json:"walletName"` - } + "github.com/dasbd72/go-exchange-sdk/binance/pkg/models" ) -func (c *Client) GetWalletStatus(ctx context.Context, opts ...RequestOption) (*GetWalletStatusResponse, error) { +func (c *Client) GetWalletStatus(ctx context.Context, opts ...RequestOption) (*models.GetWalletStatusResponse, error) { res, err := c.CallAPI(ctx, Request_builder{ Method: http.MethodGet, Endpoint: "/sapi/v1/system/status", @@ -28,7 +17,7 @@ func (c *Client) GetWalletStatus(ctx context.Context, opts ...RequestOption) (*G if err != nil { return nil, err } - data := &GetWalletStatusResponse{} + data := &models.GetWalletStatusResponse{} err = json.Unmarshal(res, data) if err != nil { return nil, err @@ -36,7 +25,7 @@ func (c *Client) GetWalletStatus(ctx context.Context, opts ...RequestOption) (*G return data, nil } -func (c *Client) GetUserWalletBalance(ctx context.Context, opts ...RequestOption) (*GetUserWalletBalanceResponse, error) { +func (c *Client) GetUserWalletBalance(ctx context.Context, opts ...RequestOption) (*models.GetUserWalletBalanceResponse, error) { res, err := c.CallAPI(ctx, Request_builder{ Method: http.MethodGet, Endpoint: "/sapi/v1/asset/wallet/balance", @@ -45,7 +34,7 @@ func (c *Client) GetUserWalletBalance(ctx context.Context, opts ...RequestOption if err != nil { return nil, err } - data := &GetUserWalletBalanceResponse{} + data := &models.GetUserWalletBalanceResponse{} err = json.Unmarshal(res, data) if err != nil { return nil, err diff --git a/manager/balance.go b/manager/balance.go index ea0484b..0e0632e 100644 --- a/manager/balance.go +++ b/manager/balance.go @@ -3,7 +3,7 @@ package manager import ( "context" - "github.com/dasbd72/go-exchange-sdk/binance" + binanceModels "github.com/dasbd72/go-exchange-sdk/binance/pkg/models" "github.com/dasbd72/go-exchange-sdk/max" "github.com/dasbd72/go-exchange-sdk/okx" ) @@ -36,7 +36,7 @@ func (c *Client) GetBalance(ctx context.Context) (*Balance, error) { sum += w.Balance.Float64() } - averagePrice, err := c.binanceClient.GetAveragePrice(ctx, binance.NewGetAveragePriceRequest("BTCUSDT")) + averagePrice, err := c.binanceClient.GetAveragePrice(ctx, binanceModels.NewGetAveragePriceRequest("BTCUSDT")) if err != nil { return err }