diff --git a/binance/spot/margin/client.go b/binance/spot/margin/client.go index 564b184..ccb5fca 100644 --- a/binance/spot/margin/client.go +++ b/binance/spot/margin/client.go @@ -22,7 +22,6 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/hex" - "encoding/json" "log/slog" "net/http" "time" @@ -31,6 +30,7 @@ import ( "github.com/linstohu/nexapi/binance/spot/margin/types" spotutils "github.com/linstohu/nexapi/binance/spot/utils" bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" ) type SpotMarginClient struct { @@ -77,16 +77,18 @@ func NewSpotMarginClient(cfg *SpotMarginClientCfg) (*SpotMarginClient, error) { }, nil } -func (s *SpotMarginClient) GetInterestHistory(ctx context.Context, param types.GetInterestHistoryParam) (*types.InterestHistory, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/margin/interestHistory", - Method: http.MethodGet, +func (s *SpotMarginClient) GetInterestHistory(ctx context.Context, param types.GetInterestHistoryParam) (*types.GetInterestHistoryResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/margin/interestHistory", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -107,7 +109,7 @@ func (s *SpotMarginClient) GetInterestHistory(ctx context.Context, param types.G return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -128,10 +130,15 @@ func (s *SpotMarginClient) GetInterestHistory(ctx context.Context, param types.G return nil, err } - var ret types.InterestHistory - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.InterestHistory + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetInterestHistoryResp{ + Http: resp, + Body: &body, + } + + return data, nil } diff --git a/binance/spot/margin/types/interest_history.go b/binance/spot/margin/types/interest_history.go index a7ff659..bd21af6 100644 --- a/binance/spot/margin/types/interest_history.go +++ b/binance/spot/margin/types/interest_history.go @@ -17,7 +17,10 @@ package types -import "github.com/linstohu/nexapi/binance/utils" +import ( + bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" +) type GetInterestHistoryParam struct { Asset string `url:"asset,omitempty" validate:"omitempty"` @@ -31,7 +34,12 @@ type GetInterestHistoryParam struct { type GetInterestHistoryParams struct { GetInterestHistoryParam - utils.DefaultParam + bnutils.DefaultParam +} + +type GetInterestHistoryResp struct { + Http *utils.ApiResponse + Body *InterestHistory } type InterestHistory struct { diff --git a/binance/spot/marketdata/client.go b/binance/spot/marketdata/client.go index 2313594..bea394f 100644 --- a/binance/spot/marketdata/client.go +++ b/binance/spot/marketdata/client.go @@ -26,6 +26,7 @@ import ( "github.com/go-playground/validator" "github.com/linstohu/nexapi/binance/spot/marketdata/types" spotutils "github.com/linstohu/nexapi/binance/spot/utils" + "github.com/linstohu/nexapi/utils" "github.com/valyala/fastjson" ) @@ -51,7 +52,8 @@ func NewSpotMarketDataClient(cfg *spotutils.SpotClientCfg) (*SpotMarketDataClien } func (s *SpotMarketDataClient) Ping(ctx context.Context) error { - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/ping", Method: http.MethodGet, @@ -71,8 +73,9 @@ func (s *SpotMarketDataClient) Ping(ctx context.Context) error { return nil } -func (s *SpotMarketDataClient) GetServerTime(ctx context.Context) (*types.ServerTime, error) { - req := spotutils.HTTPRequest{ +func (s *SpotMarketDataClient) GetServerTime(ctx context.Context) (*types.ServerTimeResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/time", Method: http.MethodGet, @@ -89,16 +92,23 @@ func (s *SpotMarketDataClient) GetServerTime(ctx context.Context) (*types.Server return nil, err } - var ret types.ServerTime - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.ServerTime + + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.ServerTimeResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetExchangeInfo(ctx context.Context, param types.GetExchangeInfoParam) (*types.ExchangeInfo, error) { - req := spotutils.HTTPRequest{ +func (s *SpotMarketDataClient) GetExchangeInfo(ctx context.Context, param types.GetExchangeInfoParam) (*types.GetExchangeInfoResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/exchangeInfo", Method: http.MethodGet, @@ -132,21 +142,28 @@ func (s *SpotMarketDataClient) GetExchangeInfo(ctx context.Context, param types. return nil, err } - var ret types.ExchangeInfo - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.ExchangeInfo + + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetExchangeInfoResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetOrderbook(ctx context.Context, param types.GetOrderbookParams) (*types.Orderbook, error) { +func (s *SpotMarketDataClient) GetOrderbook(ctx context.Context, param types.GetOrderbookParams) (*types.GetOrderbookResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/depth", Method: http.MethodGet, @@ -164,21 +181,28 @@ func (s *SpotMarketDataClient) GetOrderbook(ctx context.Context, param types.Get return nil, err } - var ret types.Orderbook - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.Orderbook + + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetOrderbookResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetRecentTradeList(ctx context.Context, param types.GetTradeParams) ([]*types.Trade, error) { +func (s *SpotMarketDataClient) GetRecentTradeList(ctx context.Context, param types.GetTradeParams) (*types.GetTradeResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/trades", Method: http.MethodGet, @@ -196,21 +220,27 @@ func (s *SpotMarketDataClient) GetRecentTradeList(ctx context.Context, param typ return nil, err } - var ret []*types.Trade - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.Trade + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetTradeResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetAggTrades(ctx context.Context, param types.GetAggTradesParam) ([]*types.AggTrade, error) { +func (s *SpotMarketDataClient) GetAggTrades(ctx context.Context, param types.GetAggTradesParam) (*types.GetAggTradesResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/aggTrades", Method: http.MethodGet, @@ -228,21 +258,27 @@ func (s *SpotMarketDataClient) GetAggTrades(ctx context.Context, param types.Get return nil, err } - var ret []*types.AggTrade - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.AggTrade + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetAggTradesResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetKlines(ctx context.Context, param types.GetKlineParam) ([]*types.Kline, error) { +func (s *SpotMarketDataClient) GetKlines(ctx context.Context, param types.GetKlineParam) (*types.GetKlineResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/klines", Method: http.MethodGet, @@ -260,8 +296,13 @@ func (s *SpotMarketDataClient) GetKlines(ctx context.Context, param types.GetKli return nil, err } + body, err := resp.ReadBody() + if err != nil { + return nil, err + } + var p fastjson.Parser - js, err := p.ParseBytes(resp) + js, err := p.ParseBytes(body) if err != nil { return nil, err } @@ -297,16 +338,22 @@ func (s *SpotMarketDataClient) GetKlines(ctx context.Context, param types.GetKli }) } - return ret, nil + data := &types.GetKlineResp{ + Http: resp, + Body: ret, + } + + return data, nil } -func (s *SpotMarketDataClient) GetAvgPrice(ctx context.Context, param types.GetAvgPriceParam) (*types.AvgPrice, error) { +func (s *SpotMarketDataClient) GetAvgPrice(ctx context.Context, param types.GetAvgPriceParam) (*types.GetAvgPriceResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/avgPrice", Method: http.MethodGet, @@ -324,21 +371,27 @@ func (s *SpotMarketDataClient) GetAvgPrice(ctx context.Context, param types.GetA return nil, err } - var ret types.AvgPrice - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.AvgPrice + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetAvgPriceResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetTickerForSymbol(ctx context.Context, param types.GetTickerForSymbolParam) (*types.Ticker, error) { +func (s *SpotMarketDataClient) GetTickerForSymbol(ctx context.Context, param types.GetTickerForSymbolParam) (*types.GetTickerForSymbolResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/ticker/24hr", Method: http.MethodGet, @@ -360,21 +413,27 @@ func (s *SpotMarketDataClient) GetTickerForSymbol(ctx context.Context, param typ return nil, err } - var ret types.Ticker - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.Ticker + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetTickerForSymbolResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetTickerForSymbols(ctx context.Context, param types.GetTickerForSymbolsParam) ([]*types.Ticker, error) { +func (s *SpotMarketDataClient) GetTickerForSymbols(ctx context.Context, param types.GetTickerForSymbolsParam) (*types.GetTickerForSymbolsResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/ticker/24hr", Method: http.MethodGet, @@ -399,21 +458,27 @@ func (s *SpotMarketDataClient) GetTickerForSymbols(ctx context.Context, param ty return nil, err } - var ret []*types.Ticker - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.Ticker + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetTickerForSymbolsResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetTickerPriceForSymbol(ctx context.Context, param types.GetTickerPriceForSymbolParam) (*types.TickerPrice, error) { +func (s *SpotMarketDataClient) GetTickerPriceForSymbol(ctx context.Context, param types.GetTickerPriceForSymbolParam) (*types.GetTickerPriceForSymbolResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/ticker/price", Method: http.MethodGet, @@ -435,21 +500,27 @@ func (s *SpotMarketDataClient) GetTickerPriceForSymbol(ctx context.Context, para return nil, err } - var ret types.TickerPrice - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.TickerPrice + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetTickerPriceForSymbolResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetTickerPriceForSymbols(ctx context.Context, param types.GetTickerPriceForSymbolsParam) ([]*types.TickerPrice, error) { +func (s *SpotMarketDataClient) GetTickerPriceForSymbols(ctx context.Context, param types.GetTickerPriceForSymbolsParam) (*types.GetTickerPriceForSymbolsResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/ticker/price", Method: http.MethodGet, @@ -474,21 +545,27 @@ func (s *SpotMarketDataClient) GetTickerPriceForSymbols(ctx context.Context, par return nil, err } - var ret []*types.TickerPrice - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.TickerPrice + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetTickerPriceForSymbolsResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetBookTickerForSymbol(ctx context.Context, param types.GetBookTickerForSymbolParam) (*types.BookTicker, error) { +func (s *SpotMarketDataClient) GetBookTickerForSymbol(ctx context.Context, param types.GetBookTickerForSymbolParam) (*types.GetBookTickerForSymbolResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/ticker/bookTicker", Method: http.MethodGet, @@ -510,21 +587,27 @@ func (s *SpotMarketDataClient) GetBookTickerForSymbol(ctx context.Context, param return nil, err } - var ret types.BookTicker - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.BookTicker + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetBookTickerForSymbolResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotMarketDataClient) GetBookTickerForSymbols(ctx context.Context, param types.GetBookTickerForSymbolsParam) ([]*types.BookTicker, error) { +func (s *SpotMarketDataClient) GetBookTickerForSymbols(ctx context.Context, param types.GetBookTickerForSymbolsParam) (*types.GetBookTickerForSymbolsResp, error) { err := s.validate.Struct(param) if err != nil { return nil, err } - req := spotutils.HTTPRequest{ + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/api/v3/ticker/bookTicker", Method: http.MethodGet, @@ -549,10 +632,15 @@ func (s *SpotMarketDataClient) GetBookTickerForSymbols(ctx context.Context, para return nil, err } - var ret []*types.BookTicker - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.BookTicker + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetBookTickerForSymbolsResp{ + Http: resp, + Body: body, + } + + return data, nil } diff --git a/binance/spot/marketdata/types/agg_trades.go b/binance/spot/marketdata/types/agg_trades.go index 6048dab..618d55b 100644 --- a/binance/spot/marketdata/types/agg_trades.go +++ b/binance/spot/marketdata/types/agg_trades.go @@ -17,6 +17,8 @@ package types +import "github.com/linstohu/nexapi/utils" + type GetAggTradesParam struct { Symbol string `url:"symbol" validate:"required"` FromID string `url:"fromId,omitempty" validate:"omitempty"` @@ -25,6 +27,11 @@ type GetAggTradesParam struct { Limit int `url:"limit,omitempty" validate:"omitempty,max=1000"` } +type GetAggTradesResp struct { + Http *utils.ApiResponse + Body []*AggTrade +} + type AggTrade struct { A int `json:"a"` // Aggregate tradeId P string `json:"p"` // Price diff --git a/binance/spot/marketdata/types/average_price.go b/binance/spot/marketdata/types/average_price.go index f1e371b..dab727a 100644 --- a/binance/spot/marketdata/types/average_price.go +++ b/binance/spot/marketdata/types/average_price.go @@ -17,10 +17,17 @@ package types +import "github.com/linstohu/nexapi/utils" + type GetAvgPriceParam struct { Symbol string `url:"symbol" validate:"required"` } +type GetAvgPriceResp struct { + Http *utils.ApiResponse + Body *AvgPrice +} + type AvgPrice struct { Mins int64 `json:"mins"` Price string `json:"price"` diff --git a/binance/spot/marketdata/types/book_ticker.go b/binance/spot/marketdata/types/book_ticker.go index 6c0afab..1c710a4 100644 --- a/binance/spot/marketdata/types/book_ticker.go +++ b/binance/spot/marketdata/types/book_ticker.go @@ -17,6 +17,8 @@ package types +import "github.com/linstohu/nexapi/utils" + type GetBookTickerForSymbolParam struct { Symbol string `url:"symbol" validate:"required"` } @@ -30,6 +32,16 @@ type BookTickerParams struct { Symbols string `url:"symbols,omitempty" validate:"omitempty"` } +type GetBookTickerForSymbolResp struct { + Http *utils.ApiResponse + Body *BookTicker +} + +type GetBookTickerForSymbolsResp struct { + Http *utils.ApiResponse + Body []*BookTicker +} + type BookTicker struct { Symbol string `json:"symbol"` BidPrice string `json:"bidPrice"` diff --git a/binance/spot/marketdata/types/exchange_info.go b/binance/spot/marketdata/types/exchange_info.go index 3e459b7..9e50312 100644 --- a/binance/spot/marketdata/types/exchange_info.go +++ b/binance/spot/marketdata/types/exchange_info.go @@ -17,6 +17,8 @@ package types +import "github.com/linstohu/nexapi/utils" + type GetExchangeInfoParam struct { Symbols []string Permissions []string @@ -27,6 +29,11 @@ type GetExchangeInfoParams struct { Permissions string `url:"permissions,omitempty" validate:"omitempty"` } +type GetExchangeInfoResp struct { + Http *utils.ApiResponse + Body *ExchangeInfo +} + type ExchangeInfo struct { Timezone string `json:"timezone"` ServerTime int64 `json:"serverTime"` diff --git a/binance/spot/marketdata/types/klines.go b/binance/spot/marketdata/types/klines.go index 108b80f..870839e 100644 --- a/binance/spot/marketdata/types/klines.go +++ b/binance/spot/marketdata/types/klines.go @@ -19,6 +19,7 @@ package types import ( spotutils "github.com/linstohu/nexapi/binance/spot/utils" + "github.com/linstohu/nexapi/utils" ) type GetKlineParam struct { @@ -29,6 +30,11 @@ type GetKlineParam struct { Limit int `url:"limit,omitempty" validate:"omitempty,max=1000"` } +type GetKlineResp struct { + Http *utils.ApiResponse + Body []*Kline +} + type Kline struct { OpenTime int64 `json:"openTime"` OpenPrice string `json:"openPrice"` diff --git a/binance/spot/marketdata/types/orderbook.go b/binance/spot/marketdata/types/orderbook.go index eb554c4..74a2057 100644 --- a/binance/spot/marketdata/types/orderbook.go +++ b/binance/spot/marketdata/types/orderbook.go @@ -17,11 +17,18 @@ package types +import "github.com/linstohu/nexapi/utils" + type GetOrderbookParams struct { Symbol string `url:"symbol" validate:"required"` Limit int `url:"limit,omitempty" validate:"omitempty,max=5000"` } +type GetOrderbookResp struct { + Http *utils.ApiResponse + Body *Orderbook +} + type Orderbook struct { LastUpdateID int64 `json:"lastUpdateId"` Bids [][]string `json:"bids"` diff --git a/binance/spot/marketdata/types/server_time.go b/binance/spot/marketdata/types/server_time.go index 6838532..b91b4d8 100644 --- a/binance/spot/marketdata/types/server_time.go +++ b/binance/spot/marketdata/types/server_time.go @@ -17,6 +17,13 @@ package types +import "github.com/linstohu/nexapi/utils" + +type ServerTimeResp struct { + Http *utils.ApiResponse + Body *ServerTime +} + type ServerTime struct { ServerTime int64 `json:"serverTime"` } diff --git a/binance/spot/marketdata/types/ticker.go b/binance/spot/marketdata/types/ticker.go index ca8541b..66f9631 100644 --- a/binance/spot/marketdata/types/ticker.go +++ b/binance/spot/marketdata/types/ticker.go @@ -17,6 +17,8 @@ package types +import "github.com/linstohu/nexapi/utils" + type GetTickerForSymbolParam struct { Symbol string `url:"symbol" validate:"required"` } @@ -31,6 +33,16 @@ type TickerParams struct { Type string `url:"type,omitempty" validate:"omitempty,oneof=FULL MINI"` } +type GetTickerForSymbolResp struct { + Http *utils.ApiResponse + Body *Ticker +} + +type GetTickerForSymbolsResp struct { + Http *utils.ApiResponse + Body []*Ticker +} + type Ticker struct { Symbol string `json:"symbol"` PriceChange string `json:"priceChange"` diff --git a/binance/spot/marketdata/types/ticker_price.go b/binance/spot/marketdata/types/ticker_price.go index e297967..b04bd6e 100644 --- a/binance/spot/marketdata/types/ticker_price.go +++ b/binance/spot/marketdata/types/ticker_price.go @@ -17,6 +17,8 @@ package types +import "github.com/linstohu/nexapi/utils" + type GetTickerPriceForSymbolParam struct { Symbol string `url:"symbol" validate:"required"` } @@ -30,6 +32,16 @@ type TickerPriceParams struct { Symbols string `url:"symbols,omitempty" validate:"omitempty"` } +type GetTickerPriceForSymbolResp struct { + Http *utils.ApiResponse + Body *TickerPrice +} + +type GetTickerPriceForSymbolsResp struct { + Http *utils.ApiResponse + Body []*TickerPrice +} + type TickerPrice struct { Symbol string `json:"symbol"` Price string `json:"price"` diff --git a/binance/spot/marketdata/types/trades.go b/binance/spot/marketdata/types/trades.go index 270de79..243c766 100644 --- a/binance/spot/marketdata/types/trades.go +++ b/binance/spot/marketdata/types/trades.go @@ -17,11 +17,18 @@ package types +import "github.com/linstohu/nexapi/utils" + type GetTradeParams struct { Symbol string `url:"symbol" validate:"required"` Limit int `url:"limit,omitempty" validate:"omitempty,max=1000"` } +type GetTradeResp struct { + Http *utils.ApiResponse + Body []*Trade +} + type Trade struct { ID int64 `json:"id"` Price string `json:"price"` diff --git a/binance/spot/spotaccount/client.go b/binance/spot/spotaccount/client.go index d554740..7ac9b5e 100644 --- a/binance/spot/spotaccount/client.go +++ b/binance/spot/spotaccount/client.go @@ -22,7 +22,6 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/hex" - "encoding/json" "log/slog" "net/http" "time" @@ -31,6 +30,7 @@ import ( "github.com/linstohu/nexapi/binance/spot/spotaccount/types" spotutils "github.com/linstohu/nexapi/binance/spot/utils" bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" ) type SpotAccountClient struct { @@ -78,15 +78,17 @@ func NewSpotAccountClient(cfg *SpotAccountClientCfg) (*SpotAccountClient, error) } func (s *SpotAccountClient) TestNewOrder(ctx context.Context, param types.NewOrderParam) error { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.TRADE, - BaseURL: s.GetBaseURL(), - Path: "/api/v3/order/test", - Method: http.MethodPost, + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/api/v3/order/test", + Method: http.MethodPost, } + st := spotutils.TRADE + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return err } @@ -107,7 +109,7 @@ func (s *SpotAccountClient) TestNewOrder(ctx context.Context, param types.NewOrd return err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(nil, body) if err != nil { return err @@ -132,15 +134,17 @@ func (s *SpotAccountClient) TestNewOrder(ctx context.Context, param types.NewOrd } func (s *SpotAccountClient) NewOrder(ctx context.Context, param types.NewOrderParam) (*types.NewOrderResp, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.TRADE, - BaseURL: s.GetBaseURL(), - Path: "/api/v3/order", - Method: http.MethodPost, + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/api/v3/order", + Method: http.MethodPost, } + st := spotutils.TRADE + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -161,7 +165,7 @@ func (s *SpotAccountClient) NewOrder(ctx context.Context, param types.NewOrderPa return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(nil, body) if err != nil { return nil, err @@ -182,24 +186,31 @@ func (s *SpotAccountClient) NewOrder(ctx context.Context, param types.NewOrderPa return nil, err } - var ret types.NewOrderResp - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.NewOrderAPIResp + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.NewOrderResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotAccountClient) CancelOrder(ctx context.Context, param types.CancelOrderParam) (*types.OrderInfo, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.TRADE, - BaseURL: s.GetBaseURL(), - Path: "/api/v3/order", - Method: http.MethodDelete, +func (s *SpotAccountClient) CancelOrder(ctx context.Context, param types.CancelOrderParam) (*types.OrderInfoResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/api/v3/order", + Method: http.MethodDelete, } + st := spotutils.TRADE + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -220,7 +231,7 @@ func (s *SpotAccountClient) CancelOrder(ctx context.Context, param types.CancelO return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(nil, body) if err != nil { return nil, err @@ -241,24 +252,31 @@ func (s *SpotAccountClient) CancelOrder(ctx context.Context, param types.CancelO return nil, err } - var ret types.OrderInfo - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.OrderInfo + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.OrderInfoResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotAccountClient) CancelOrdersOnOneSymbol(ctx context.Context, param types.CancelOrdersOnOneSymbolParam) ([]*types.OrderInfo, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.TRADE, - BaseURL: s.GetBaseURL(), - Path: "/api/v3/openOrders", - Method: http.MethodDelete, +func (s *SpotAccountClient) CancelOrdersOnOneSymbol(ctx context.Context, param types.CancelOrdersOnOneSymbolParam) (*types.CancelOrdersResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/api/v3/openOrders", + Method: http.MethodDelete, } + st := spotutils.TRADE + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -279,7 +297,7 @@ func (s *SpotAccountClient) CancelOrdersOnOneSymbol(ctx context.Context, param t return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(nil, body) if err != nil { return nil, err @@ -300,24 +318,31 @@ func (s *SpotAccountClient) CancelOrdersOnOneSymbol(ctx context.Context, param t return nil, err } - var ret []*types.OrderInfo - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.OrderInfo + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.CancelOrdersResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotAccountClient) QueryOrder(ctx context.Context, param types.QueryOrderParam) (*types.Order, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/api/v3/order", - Method: http.MethodGet, +func (s *SpotAccountClient) QueryOrder(ctx context.Context, param types.QueryOrderParam) (*types.QueryOrderResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/api/v3/order", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -338,7 +363,7 @@ func (s *SpotAccountClient) QueryOrder(ctx context.Context, param types.QueryOrd return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -359,24 +384,31 @@ func (s *SpotAccountClient) QueryOrder(ctx context.Context, param types.QueryOrd return nil, err } - var ret types.Order - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.Order + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.QueryOrderResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotAccountClient) GetOpenOrders(ctx context.Context, param types.GetOpenOrdersParam) ([]*types.Order, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/api/v3/openOrders", - Method: http.MethodGet, +func (s *SpotAccountClient) GetOpenOrders(ctx context.Context, param types.GetOpenOrdersParam) (*types.GetOpenOrdersResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/api/v3/openOrders", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -397,7 +429,7 @@ func (s *SpotAccountClient) GetOpenOrders(ctx context.Context, param types.GetOp return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -418,24 +450,31 @@ func (s *SpotAccountClient) GetOpenOrders(ctx context.Context, param types.GetOp return nil, err } - var ret []*types.Order - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.Order + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetOpenOrdersResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotAccountClient) GetAllOrders(ctx context.Context, param types.GetAllOrdersParam) ([]*types.Order, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/api/v3/allOrders", - Method: http.MethodGet, +func (s *SpotAccountClient) GetAllOrders(ctx context.Context, param types.GetAllOrdersParam) (*types.GetAllOrdersResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/api/v3/allOrders", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -456,7 +495,7 @@ func (s *SpotAccountClient) GetAllOrders(ctx context.Context, param types.GetAll return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -477,24 +516,31 @@ func (s *SpotAccountClient) GetAllOrders(ctx context.Context, param types.GetAll return nil, err } - var ret []*types.Order - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.Order + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetAllOrdersResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotAccountClient) GetAccountInfo(ctx context.Context) (*types.AccountInfo, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/api/v3/account", - Method: http.MethodGet, +func (s *SpotAccountClient) GetAccountInfo(ctx context.Context) (*types.GetAccountInfoResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/api/v3/account", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -512,7 +558,7 @@ func (s *SpotAccountClient) GetAccountInfo(ctx context.Context) (*types.AccountI return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -533,24 +579,31 @@ func (s *SpotAccountClient) GetAccountInfo(ctx context.Context) (*types.AccountI return nil, err } - var ret types.AccountInfo - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.AccountInfo + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetAccountInfoResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotAccountClient) GetTradeList(ctx context.Context, param types.GetTradesParam) ([]*types.Trade, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/api/v3/myTrades", - Method: http.MethodGet, +func (s *SpotAccountClient) GetTradeList(ctx context.Context, param types.GetTradesParam) (*types.GetTradesResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/api/v3/myTrades", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -571,7 +624,7 @@ func (s *SpotAccountClient) GetTradeList(ctx context.Context, param types.GetTra return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -592,10 +645,15 @@ func (s *SpotAccountClient) GetTradeList(ctx context.Context, param types.GetTra return nil, err } - var ret []*types.Trade - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.Trade + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetTradesResp{ + Http: resp, + Body: body, + } + + return data, nil } diff --git a/binance/spot/spotaccount/types/account_info.go b/binance/spot/spotaccount/types/account_info.go index 36ea5cd..0c357de 100644 --- a/binance/spot/spotaccount/types/account_info.go +++ b/binance/spot/spotaccount/types/account_info.go @@ -17,6 +17,13 @@ package types +import "github.com/linstohu/nexapi/utils" + +type GetAccountInfoResp struct { + Http *utils.ApiResponse + Body *AccountInfo +} + type AccountInfo struct { MakerCommission int `json:"makerCommission"` TakerCommission int `json:"takerCommission"` diff --git a/binance/spot/spotaccount/types/order.go b/binance/spot/spotaccount/types/order.go index 04b2305..e851950 100644 --- a/binance/spot/spotaccount/types/order.go +++ b/binance/spot/spotaccount/types/order.go @@ -18,7 +18,8 @@ package types import ( - "github.com/linstohu/nexapi/binance/utils" + bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" ) type SideType string @@ -56,6 +57,16 @@ var ( FULL NewOrderRespType = "FULL" ) +type OrderInfoResp struct { + Http *utils.ApiResponse + Body *OrderInfo +} + +type CancelOrdersResp struct { + Http *utils.ApiResponse + Body []*OrderInfo +} + type OrderInfo struct { Symbol string `json:"symbol"` OrigClientOrderID string `json:"origClientOrderId"` @@ -73,6 +84,21 @@ type OrderInfo struct { SelfTradePreventionMode string `json:"selfTradePreventionMode"` } +type QueryOrderResp struct { + Http *utils.ApiResponse + Body *Order +} + +type GetOpenOrdersResp struct { + Http *utils.ApiResponse + Body []*Order +} + +type GetAllOrdersResp struct { + Http *utils.ApiResponse + Body []*Order +} + type Order struct { OrderInfo StopPrice string `json:"stopPrice"` @@ -104,10 +130,15 @@ type NewOrderParam struct { type NewOrderParams struct { NewOrderParam - utils.DefaultParam + bnutils.DefaultParam } type NewOrderResp struct { + Http *utils.ApiResponse + Body *NewOrderAPIResp +} + +type NewOrderAPIResp struct { OrderInfo TransactTime int64 `json:"transactTime"` WorkingTime int64 `json:"workingTime"` @@ -123,7 +154,7 @@ type CancelOrderParam struct { type CancelOrderParams struct { CancelOrderParam - utils.DefaultParam + bnutils.DefaultParam } type CancelOrdersOnOneSymbolParam struct { @@ -132,7 +163,7 @@ type CancelOrdersOnOneSymbolParam struct { type CancelOrdersOnOneSymbolParams struct { CancelOrdersOnOneSymbolParam - utils.DefaultParam + bnutils.DefaultParam } type QueryOrderParam struct { @@ -143,7 +174,7 @@ type QueryOrderParam struct { type QueryOrderParams struct { QueryOrderParam - utils.DefaultParam + bnutils.DefaultParam } type GetOpenOrdersParam struct { @@ -152,7 +183,7 @@ type GetOpenOrdersParam struct { type GetOpenOrdersParams struct { GetOpenOrdersParam - utils.DefaultParam + bnutils.DefaultParam } type GetAllOrdersParam struct { @@ -165,5 +196,5 @@ type GetAllOrdersParam struct { type GetAllOrdersParams struct { GetAllOrdersParam - utils.DefaultParam + bnutils.DefaultParam } diff --git a/binance/spot/spotaccount/types/trade_list.go b/binance/spot/spotaccount/types/trade_list.go index eb5f4d4..ff94eba 100644 --- a/binance/spot/spotaccount/types/trade_list.go +++ b/binance/spot/spotaccount/types/trade_list.go @@ -18,7 +18,8 @@ package types import ( - "github.com/linstohu/nexapi/binance/utils" + bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" ) type GetTradesParam struct { @@ -32,7 +33,12 @@ type GetTradesParam struct { type GetTradesParams struct { GetTradesParam - utils.DefaultParam + bnutils.DefaultParam +} + +type GetTradesResp struct { + Http *utils.ApiResponse + Body []*Trade } type Trade struct { diff --git a/binance/spot/subaccount/client.go b/binance/spot/subaccount/client.go index 74f17c6..d38b367 100644 --- a/binance/spot/subaccount/client.go +++ b/binance/spot/subaccount/client.go @@ -22,7 +22,6 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/hex" - "encoding/json" "log/slog" "net/http" "time" @@ -31,6 +30,7 @@ import ( "github.com/linstohu/nexapi/binance/spot/subaccount/types" spotutils "github.com/linstohu/nexapi/binance/spot/utils" bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" ) type SpotSubAccountClient struct { @@ -77,16 +77,18 @@ func NewSpotSubAccountClient(cfg *SpotSubAccountClientCfg) (*SpotSubAccountClien }, nil } -func (s *SpotSubAccountClient) GetSubAccountTransferHistory(ctx context.Context, param types.GetSubAccountTransferHistoryParam) ([]*types.SubAccountTransferHistory, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/sub-account/transfer/subUserHistory", - Method: http.MethodGet, +func (s *SpotSubAccountClient) GetSubAccountTransferHistory(ctx context.Context, param types.GetSubAccountTransferHistoryParam) (*types.GetSubAccountTransferHistoryResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/sub-account/transfer/subUserHistory", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -107,7 +109,7 @@ func (s *SpotSubAccountClient) GetSubAccountTransferHistory(ctx context.Context, return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -128,10 +130,15 @@ func (s *SpotSubAccountClient) GetSubAccountTransferHistory(ctx context.Context, return nil, err } - var ret []*types.SubAccountTransferHistory - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.SubAccountTransferHistory + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetSubAccountTransferHistoryResp{ + Http: resp, + Body: body, + } + + return data, nil } diff --git a/binance/spot/subaccount/types/sub_account_transfer_history.go b/binance/spot/subaccount/types/sub_account_transfer_history.go index dbe7d1f..8bf4a37 100644 --- a/binance/spot/subaccount/types/sub_account_transfer_history.go +++ b/binance/spot/subaccount/types/sub_account_transfer_history.go @@ -17,7 +17,10 @@ package types -import "github.com/linstohu/nexapi/binance/utils" +import ( + bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" +) type GetSubAccountTransferHistoryParam struct { Asset string `url:"asset,omitempty" validate:"omitempty"` @@ -29,7 +32,12 @@ type GetSubAccountTransferHistoryParam struct { type GetSubAccountTransferHistoryParams struct { GetSubAccountTransferHistoryParam - utils.DefaultParam + bnutils.DefaultParam +} + +type GetSubAccountTransferHistoryResp struct { + Http *utils.ApiResponse + Body []*SubAccountTransferHistory } type SubAccountTransferHistory struct { diff --git a/binance/spot/utils/client.go b/binance/spot/utils/client.go index efe0299..90a6d94 100644 --- a/binance/spot/utils/client.go +++ b/binance/spot/utils/client.go @@ -18,7 +18,6 @@ package spotutils import ( - "bytes" "context" "fmt" "io" @@ -30,6 +29,7 @@ import ( "github.com/go-playground/validator" "github.com/google/go-querystring/query" + "github.com/linstohu/nexapi/utils" ) type SpotClient struct { @@ -101,7 +101,10 @@ func (s *SpotClient) GetRecvWindow() int { } func (s *SpotClient) GenHeaders(t SecurityType) (map[string]string, error) { - headers := DefaultContentType + headers := map[string]string{ + "Content-Type": "application/x-www-form-urlencoded", + "Accept": "application/json", + } // SecurityType each endpoint has a security type that determines how you will interact with it // docs: https://binance-docs.github.io/apidocs/spot/en/#endpoint-security-type @@ -109,7 +112,7 @@ func (s *SpotClient) GenHeaders(t SecurityType) (map[string]string, error) { case TRADE, MARGIN, USER_DATA, USER_STREAM, MARKET_DATA: key := s.GetKey() if key == "" { - return nil, fmt.Errorf("a valid API-Key required") + return nil, fmt.Errorf("valid API-Key required") } headers["X-MBX-APIKEY"] = s.GetKey() @@ -127,7 +130,7 @@ func (s *SpotClient) NeedSignature(t SecurityType) bool { } } -func (s *SpotClient) SendHTTPRequest(ctx context.Context, req HTTPRequest) ([]byte, error) { +func (s *SpotClient) SendHTTPRequest(ctx context.Context, req utils.HTTPRequest) (*utils.ApiResponse, error) { client := http.Client{} var body io.Reader @@ -174,7 +177,6 @@ func (s *SpotClient) SendHTTPRequest(ctx context.Context, req HTTPRequest) ([]by if err != nil { return nil, err } - defer resp.Body.Close() if s.GetDebug() { dump, err := httputil.DumpResponse(resp, true) @@ -184,12 +186,5 @@ func (s *SpotClient) SendHTTPRequest(ctx context.Context, req HTTPRequest) ([]by s.logger.Info(fmt.Sprintf("\n%s\n", string(dump))) } - buf := new(bytes.Buffer) - buf.ReadFrom(resp.Body) - - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("API returned a non-200 status code: [%d] - [%s]", resp.StatusCode, buf.String()) - } - - return buf.Bytes(), nil + return utils.NewApiResponse(&req, resp), nil } diff --git a/binance/spot/utils/request.go b/binance/spot/utils/request.go deleted file mode 100644 index e7cb98b..0000000 --- a/binance/spot/utils/request.go +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2023, LinstoHu - * All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package spotutils - -type HTTPRequest struct { - // SecurityType each endpoint has a security type that determines how you will interact with it - // docs: https://binance-docs.github.io/apidocs/spot/en/#endpoint-security-type - SecurityType SecurityType - - BaseURL string - Path string - Method string - Headers map[string]string - Query any - Body any -} diff --git a/binance/spot/utils/vars.go b/binance/spot/utils/vars.go index d28a88d..d3eeacd 100644 --- a/binance/spot/utils/vars.go +++ b/binance/spot/utils/vars.go @@ -32,11 +32,6 @@ var ( MARKET_DATA SecurityType = "MARKET_DATA" ) -var DefaultContentType = map[string]string{ - "Content-Type": "application/x-www-form-urlencoded", - "Accept": "application/json", -} - type KlineInterval string var ( diff --git a/binance/spot/wallet/client.go b/binance/spot/wallet/client.go index a27f509..1300a9d 100644 --- a/binance/spot/wallet/client.go +++ b/binance/spot/wallet/client.go @@ -22,7 +22,6 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/hex" - "encoding/json" "log/slog" "net/http" "time" @@ -31,6 +30,7 @@ import ( spotutils "github.com/linstohu/nexapi/binance/spot/utils" "github.com/linstohu/nexapi/binance/spot/wallet/types" bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" ) type SpotWalletClient struct { @@ -77,8 +77,9 @@ func NewSpotWalletClient(cfg *SpotWalletClientCfg) (*SpotWalletClient, error) { }, nil } -func (s *SpotWalletClient) GetSystemStatus(ctx context.Context) (*types.SystemStatus, error) { - req := spotutils.HTTPRequest{ +func (s *SpotWalletClient) GetSystemStatus(ctx context.Context) (*types.GetSystemStatusResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), BaseURL: s.GetBaseURL(), Path: "/sapi/v1/system/status", Method: http.MethodGet, @@ -95,24 +96,31 @@ func (s *SpotWalletClient) GetSystemStatus(ctx context.Context) (*types.SystemSt return nil, err } - var ret types.SystemStatus - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.SystemStatus + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetSystemStatusResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotWalletClient) GetAllCoinsInfo(ctx context.Context) ([]*types.CoinInfo, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/capital/config/getall", - Method: http.MethodGet, +func (s *SpotWalletClient) GetAllCoinsInfo(ctx context.Context) (*types.GetCoinInfoResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/capital/config/getall", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -130,7 +138,7 @@ func (s *SpotWalletClient) GetAllCoinsInfo(ctx context.Context) ([]*types.CoinIn return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -151,24 +159,31 @@ func (s *SpotWalletClient) GetAllCoinsInfo(ctx context.Context) ([]*types.CoinIn return nil, err } - var ret []*types.CoinInfo - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.CoinInfo + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetCoinInfoResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotWalletClient) GetAssetDetail(ctx context.Context, param types.GetAssetDetailParam) (map[string]*types.AssetDetail, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/asset/assetDetail", - Method: http.MethodGet, +func (s *SpotWalletClient) GetAssetDetail(ctx context.Context, param types.GetAssetDetailParam) (*types.AssetDetailResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/asset/assetDetail", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -189,7 +204,7 @@ func (s *SpotWalletClient) GetAssetDetail(ctx context.Context, param types.GetAs return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -210,24 +225,31 @@ func (s *SpotWalletClient) GetAssetDetail(ctx context.Context, param types.GetAs return nil, err } - ret := make(map[string]*types.AssetDetail) - if err := json.Unmarshal(resp, &ret); err != nil { + body := make(map[string]*types.AssetDetail) + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.AssetDetailResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotWalletClient) GetTradeFee(ctx context.Context, param types.GetTradeFeeParam) ([]*types.TradeFee, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/asset/tradeFee", - Method: http.MethodGet, +func (s *SpotWalletClient) GetTradeFee(ctx context.Context, param types.GetTradeFeeParam) (*types.GetTradeFeeResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/asset/tradeFee", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -248,7 +270,7 @@ func (s *SpotWalletClient) GetTradeFee(ctx context.Context, param types.GetTrade return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -269,24 +291,31 @@ func (s *SpotWalletClient) GetTradeFee(ctx context.Context, param types.GetTrade return nil, err } - var ret []*types.TradeFee - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.TradeFee + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetTradeFeeResp{ + Http: resp, + Body: body, + } + + return data, nil } func (s *SpotWalletClient) UniversalTransfer(ctx context.Context, param types.UniversalTransferParam) (*types.UniversalTransferResp, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/asset/transfer", - Method: http.MethodPost, + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/asset/transfer", + Method: http.MethodPost, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -307,7 +336,7 @@ func (s *SpotWalletClient) UniversalTransfer(ctx context.Context, param types.Un return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(nil, body) if err != nil { return nil, err @@ -328,24 +357,31 @@ func (s *SpotWalletClient) UniversalTransfer(ctx context.Context, param types.Un return nil, err } - var ret types.UniversalTransferResp - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.UniversalTransferAPIResp + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.UniversalTransferResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotWalletClient) GetUniversalTransferHistory(ctx context.Context, param types.GetUniversalTransferHistoryParam) (*types.GetUniversalTransferHistory, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/asset/transfer", - Method: http.MethodGet, +func (s *SpotWalletClient) GetUniversalTransferHistory(ctx context.Context, param types.GetUniversalTransferHistoryParam) (*types.GetUniversalTransferHistoryResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/asset/transfer", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -366,7 +402,7 @@ func (s *SpotWalletClient) GetUniversalTransferHistory(ctx context.Context, para return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -387,24 +423,31 @@ func (s *SpotWalletClient) GetUniversalTransferHistory(ctx context.Context, para return nil, err } - var ret types.GetUniversalTransferHistory - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.GetUniversalTransferHistory + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetUniversalTransferHistoryResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotWalletClient) GetFundingAsset(ctx context.Context, param types.GetFundingAssetParam) ([]*types.FundingAsset, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/asset/get-funding-asset", - Method: http.MethodPost, +func (s *SpotWalletClient) GetFundingAsset(ctx context.Context, param types.GetFundingAssetParam) (*types.GetFundingAssetResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/asset/get-funding-asset", + Method: http.MethodPost, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -425,7 +468,7 @@ func (s *SpotWalletClient) GetFundingAsset(ctx context.Context, param types.GetF return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(nil, body) if err != nil { return nil, err @@ -446,24 +489,31 @@ func (s *SpotWalletClient) GetFundingAsset(ctx context.Context, param types.GetF return nil, err } - var ret []*types.FundingAsset - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.FundingAsset + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetFundingAssetResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotWalletClient) GetUserAsset(ctx context.Context, param types.GetUserAssetParam) ([]*types.UserAsset, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v3/asset/getUserAsset", - Method: http.MethodPost, +func (s *SpotWalletClient) GetUserAsset(ctx context.Context, param types.GetUserAssetParam) (*types.GetUserAssetResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v3/asset/getUserAsset", + Method: http.MethodPost, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -484,7 +534,7 @@ func (s *SpotWalletClient) GetUserAsset(ctx context.Context, param types.GetUser return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(nil, body) if err != nil { return nil, err @@ -505,24 +555,31 @@ func (s *SpotWalletClient) GetUserAsset(ctx context.Context, param types.GetUser return nil, err } - var ret []*types.UserAsset - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.UserAsset + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetUserAssetResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotWalletClient) GetApiRestrictions(ctx context.Context) (*types.ApiRestrictions, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/account/apiRestrictions", - Method: http.MethodGet, +func (s *SpotWalletClient) GetApiRestrictions(ctx context.Context) (*types.GetApiRestrictionsResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/account/apiRestrictions", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -540,7 +597,7 @@ func (s *SpotWalletClient) GetApiRestrictions(ctx context.Context) (*types.ApiRe return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -561,24 +618,31 @@ func (s *SpotWalletClient) GetApiRestrictions(ctx context.Context) (*types.ApiRe return nil, err } - var ret *types.ApiRestrictions - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.ApiRestrictions + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetApiRestrictionsResp{ + Http: resp, + Body: &body, + } + + return data, nil } -func (s *SpotWalletClient) GetWalletBalance(ctx context.Context) ([]*types.Balance, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/asset/wallet/balance", - Method: http.MethodGet, +func (s *SpotWalletClient) GetWalletBalance(ctx context.Context) (*types.GetWalletBalanceResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/asset/wallet/balance", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -596,7 +660,7 @@ func (s *SpotWalletClient) GetWalletBalance(ctx context.Context) ([]*types.Balan return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -617,24 +681,31 @@ func (s *SpotWalletClient) GetWalletBalance(ctx context.Context) ([]*types.Balan return nil, err } - var ret []*types.Balance - if err := json.Unmarshal(resp, &ret); err != nil { + var body []*types.Balance + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return ret, nil + data := &types.GetWalletBalanceResp{ + Http: resp, + Body: body, + } + + return data, nil } -func (s *SpotWalletClient) GetEarnAccount(ctx context.Context) (*types.EarnAccount, error) { - req := spotutils.HTTPRequest{ - SecurityType: spotutils.USER_DATA, - BaseURL: s.GetBaseURL(), - Path: "/sapi/v1/simple-earn/account", - Method: http.MethodGet, +func (s *SpotWalletClient) GetEarnAccount(ctx context.Context) (*types.GetEarnAccountResp, error) { + req := utils.HTTPRequest{ + Debug: s.GetDebug(), + BaseURL: s.GetBaseURL(), + Path: "/sapi/v1/simple-earn/account", + Method: http.MethodGet, } + st := spotutils.USER_DATA + { - headers, err := s.GenHeaders(req.SecurityType) + headers, err := s.GenHeaders(st) if err != nil { return nil, err } @@ -652,7 +723,7 @@ func (s *SpotWalletClient) GetEarnAccount(ctx context.Context) (*types.EarnAccou return nil, err } - if need := s.NeedSignature(req.SecurityType); need { + if need := s.NeedSignature(st); need { signString, err := bnutils.NormalizeRequestContent(query, nil) if err != nil { return nil, err @@ -673,10 +744,15 @@ func (s *SpotWalletClient) GetEarnAccount(ctx context.Context) (*types.EarnAccou return nil, err } - var ret types.EarnAccount - if err := json.Unmarshal(resp, &ret); err != nil { + var body types.EarnAccount + if err := resp.ReadJsonBody(&body); err != nil { return nil, err } - return &ret, nil + data := &types.GetEarnAccountResp{ + Http: resp, + Body: &body, + } + + return data, nil } diff --git a/binance/spot/wallet/types/all_coins_Info.go b/binance/spot/wallet/types/all_coins_Info.go index 79e6f0e..8f773c2 100644 --- a/binance/spot/wallet/types/all_coins_Info.go +++ b/binance/spot/wallet/types/all_coins_Info.go @@ -17,6 +17,13 @@ package types +import "github.com/linstohu/nexapi/utils" + +type GetCoinInfoResp struct { + Http *utils.ApiResponse + Body []*CoinInfo +} + type CoinInfo struct { Coin string `json:"coin"` DepositAllEnable bool `json:"depositAllEnable"` diff --git a/binance/spot/wallet/types/api_restrictions.go b/binance/spot/wallet/types/api_restrictions.go index 1bd7804..d37b062 100644 --- a/binance/spot/wallet/types/api_restrictions.go +++ b/binance/spot/wallet/types/api_restrictions.go @@ -17,6 +17,13 @@ package types +import "github.com/linstohu/nexapi/utils" + +type GetApiRestrictionsResp struct { + Http *utils.ApiResponse + Body *ApiRestrictions +} + type ApiRestrictions struct { IPRestrict bool `json:"ipRestrict"` CreateTime int64 `json:"createTime"` diff --git a/binance/spot/wallet/types/asset_detail.go b/binance/spot/wallet/types/asset_detail.go index 2fa3ac1..b5316fd 100644 --- a/binance/spot/wallet/types/asset_detail.go +++ b/binance/spot/wallet/types/asset_detail.go @@ -17,7 +17,10 @@ package types -import "github.com/linstohu/nexapi/binance/utils" +import ( + bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" +) type GetAssetDetailParam struct { Asset string `url:"asset,omitempty" validate:"omitempty"` @@ -25,7 +28,12 @@ type GetAssetDetailParam struct { type AssetDetailParams struct { GetAssetDetailParam - utils.DefaultParam + bnutils.DefaultParam +} + +type AssetDetailResp struct { + Http *utils.ApiResponse + Body map[string]*AssetDetail } type AssetDetail struct { diff --git a/binance/spot/wallet/types/balance.go b/binance/spot/wallet/types/balance.go index b079fb6..8a5d93e 100644 --- a/binance/spot/wallet/types/balance.go +++ b/binance/spot/wallet/types/balance.go @@ -17,6 +17,13 @@ package types +import "github.com/linstohu/nexapi/utils" + +type GetWalletBalanceResp struct { + Http *utils.ApiResponse + Body []*Balance +} + type Balance struct { Activate bool `json:"activate"` Balance string `json:"balance"` diff --git a/binance/spot/wallet/types/earn.go b/binance/spot/wallet/types/earn.go index 95e7e18..b36cc93 100644 --- a/binance/spot/wallet/types/earn.go +++ b/binance/spot/wallet/types/earn.go @@ -17,6 +17,13 @@ package types +import "github.com/linstohu/nexapi/utils" + +type GetEarnAccountResp struct { + Http *utils.ApiResponse + Body *EarnAccount +} + type EarnAccount struct { TotalAmountInBTC string `json:"totalAmountInBTC"` TotalAmountInUSDT string `json:"totalAmountInUSDT"` diff --git a/binance/spot/wallet/types/funding_wallet.go b/binance/spot/wallet/types/funding_wallet.go index 24e95d8..bc22c28 100644 --- a/binance/spot/wallet/types/funding_wallet.go +++ b/binance/spot/wallet/types/funding_wallet.go @@ -17,7 +17,10 @@ package types -import "github.com/linstohu/nexapi/binance/utils" +import ( + bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" +) type GetFundingAssetParam struct { Asset string `url:"asset,omitempty" validate:"omitempty"` @@ -26,7 +29,12 @@ type GetFundingAssetParam struct { type GetFundingAssetParams struct { GetFundingAssetParam - utils.DefaultParam + bnutils.DefaultParam +} + +type GetFundingAssetResp struct { + Http *utils.ApiResponse + Body []*FundingAsset } type FundingAsset struct { diff --git a/binance/spot/wallet/types/system_status.go b/binance/spot/wallet/types/system_status.go index 1f7063c..680fd77 100644 --- a/binance/spot/wallet/types/system_status.go +++ b/binance/spot/wallet/types/system_status.go @@ -17,6 +17,13 @@ package types +import "github.com/linstohu/nexapi/utils" + +type GetSystemStatusResp struct { + Http *utils.ApiResponse + Body *SystemStatus +} + type SystemStatus struct { Status int `json:"status"` Msg string `json:"msg"` diff --git a/binance/spot/wallet/types/trade_fee.go b/binance/spot/wallet/types/trade_fee.go index 85c8a0c..74cf501 100644 --- a/binance/spot/wallet/types/trade_fee.go +++ b/binance/spot/wallet/types/trade_fee.go @@ -17,7 +17,10 @@ package types -import "github.com/linstohu/nexapi/binance/utils" +import ( + bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" +) type GetTradeFeeParam struct { Symbol string `url:"symbol,omitempty" validate:"omitempty"` @@ -25,7 +28,12 @@ type GetTradeFeeParam struct { type TradeFeeParams struct { GetTradeFeeParam - utils.DefaultParam + bnutils.DefaultParam +} + +type GetTradeFeeResp struct { + Http *utils.ApiResponse + Body []*TradeFee } type TradeFee struct { diff --git a/binance/spot/wallet/types/universal_transfer.go b/binance/spot/wallet/types/universal_transfer.go index eb547af..077b5fc 100644 --- a/binance/spot/wallet/types/universal_transfer.go +++ b/binance/spot/wallet/types/universal_transfer.go @@ -17,7 +17,10 @@ package types -import "github.com/linstohu/nexapi/binance/utils" +import ( + bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" +) type UniversalTransferParam struct { Type TransferType `url:"type" validate:"required"` @@ -65,10 +68,15 @@ const ( type UniversalTransferParams struct { UniversalTransferParam - utils.DefaultParam + bnutils.DefaultParam } type UniversalTransferResp struct { + Http *utils.ApiResponse + Body *UniversalTransferAPIResp +} + +type UniversalTransferAPIResp struct { TranID int64 `json:"tranId"` } @@ -84,7 +92,12 @@ type GetUniversalTransferHistoryParam struct { type GetUniversalTransferHistoryParams struct { GetUniversalTransferHistoryParam - utils.DefaultParam + bnutils.DefaultParam +} + +type GetUniversalTransferHistoryResp struct { + Http *utils.ApiResponse + Body *GetUniversalTransferHistory } type GetUniversalTransferHistory struct { diff --git a/binance/spot/wallet/types/user_asset.go b/binance/spot/wallet/types/user_asset.go index 326442b..558f738 100644 --- a/binance/spot/wallet/types/user_asset.go +++ b/binance/spot/wallet/types/user_asset.go @@ -17,7 +17,10 @@ package types -import "github.com/linstohu/nexapi/binance/utils" +import ( + bnutils "github.com/linstohu/nexapi/binance/utils" + "github.com/linstohu/nexapi/utils" +) type GetUserAssetParam struct { Asset string `url:"asset,omitempty" validate:"omitempty"` @@ -26,7 +29,12 @@ type GetUserAssetParam struct { type GetUserAssetParams struct { GetUserAssetParam - utils.DefaultParam + bnutils.DefaultParam +} + +type GetUserAssetResp struct { + Http *utils.ApiResponse + Body []*UserAsset } type UserAsset struct { diff --git a/binance/utils/normalization.go b/binance/utils/normalization.go index 3bb3f7f..78eb8e4 100644 --- a/binance/utils/normalization.go +++ b/binance/utils/normalization.go @@ -21,6 +21,8 @@ import ( goquery "github.com/google/go-querystring/query" ) +// NormalizeRequestContent sign endpoint security +// doc: https://binance-docs.github.io/apidocs/spot/en/#signed-trade-user_data-and-margin-endpoint-security func NormalizeRequestContent(query any, body any) (string, error) { var ret string diff --git a/utils/api.go b/utils/api.go new file mode 100644 index 0000000..5f34541 --- /dev/null +++ b/utils/api.go @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023, LinstoHu + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package utils + +import ( + "bytes" + "encoding/json" + "net/http" +) + +type HTTPRequest struct { + Debug bool + BaseURL string + Path string + Method string + Headers map[string]string + Query any + Body any +} + +type ApiResponse struct { + ApiReq *HTTPRequest + ApiRes *http.Response + Body []byte +} + +// NewResponse Creates a new Response +func NewApiResponse(request *HTTPRequest, response *http.Response) *ApiResponse { + return &ApiResponse{ + ApiReq: request, + ApiRes: response, + } +} + +// ReadBody read the response data, then return it. +func (r *ApiResponse) ReadBody() ([]byte, error) { + if r.Body != nil { + return r.Body, nil + } + + r.Body = make([]byte, 0) + defer r.ApiRes.Body.Close() + + buf := new(bytes.Buffer) + buf.ReadFrom(r.ApiRes.Body) + + r.Body = buf.Bytes() + + return r.Body, nil +} + +// ReadJsonBody read the response data as JSON into v. +func (r *ApiResponse) ReadJsonBody(v interface{}) error { + b, err := r.ReadBody() + if err != nil { + return err + } + + return json.Unmarshal(b, v) +}