From 22594a9a0ab4ef07cc86f33043a722039b74e3e3 Mon Sep 17 00:00:00 2001 From: larscom Date: Sun, 3 Dec 2023 00:38:57 +0100 Subject: [PATCH] fix buffsize, add query params --- README.md | 16 ++++++++-------- examples/http/account/main.go | 4 ++-- httpc/client.go | 12 ++++++++++-- httpc/httpclient.go | 26 ++++++++++++++++++-------- httpc/httpclientauth.go | 33 +++++++++++++++++++++++++++------ wsc/account.go | 26 ++++++++++++++++---------- wsc/book.go | 6 ++++-- wsc/candles.go | 11 +++++++---- wsc/ticker.go | 6 ++++-- wsc/ticker24h.go | 6 ++++-- wsc/trades.go | 6 ++++-- wsc/wsclient.go | 4 ++-- 12 files changed, 106 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 271d156..50868a8 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ type CandlesEvent struct { #### Book -Subscribe to book events for market: `ETH-EUR` with buffer size `0` +Subscribe to book events for market: `ETH-EUR` ```go func main() { @@ -93,7 +93,7 @@ func main() { log.Fatal(err) } - bookchn, err := ws.Book().Subscribe("ETH-EUR", 0) + bookchn, err := ws.Book().Subscribe("ETH-EUR") if err != nil { log.Fatal(err) } @@ -126,7 +126,7 @@ type BookEvent struct { #### Ticker -Subscribe to ticker events for market: `ETH-EUR` with buffer size `0` +Subscribe to ticker events for market: `ETH-EUR` ```go func main() { @@ -135,7 +135,7 @@ func main() { log.Fatal(err) } - tickerchn, err := ws.Ticker().Subscribe("ETH-EUR", 0) + tickerchn, err := ws.Ticker().Subscribe("ETH-EUR") if err != nil { log.Fatal(err) } @@ -168,7 +168,7 @@ type TickerEvent struct { #### Ticker 24H -Subscribe to ticker24h events for market: `ETH-EUR` with buffer size `0` +Subscribe to ticker24h events for market: `ETH-EUR` ```go func main() { @@ -177,7 +177,7 @@ func main() { log.Fatal(err) } - ticker24hchn, err := ws.Ticker24h().Subscribe("ETH-EUR", 0) + ticker24hchn, err := ws.Ticker24h().Subscribe("ETH-EUR") if err != nil { log.Fatal(err) } @@ -210,7 +210,7 @@ type Ticker24hEvent struct { #### Trades -Subscribe to trades events for market: `ETH-EUR` with buffer size `0` +Subscribe to trades events for market: `ETH-EUR` ```go func main() { @@ -219,7 +219,7 @@ func main() { log.Fatal(err) } - tradeschn, err := ws.Trades().Subscribe("ETH-EUR", 0) + tradeschn, err := ws.Trades().Subscribe("ETH-EUR") if err != nil { log.Fatal(err) } diff --git a/examples/http/account/main.go b/examples/http/account/main.go index 59c493a..972f9c1 100644 --- a/examples/http/account/main.go +++ b/examples/http/account/main.go @@ -17,10 +17,10 @@ func main() { key = os.Getenv("API_KEY") secret = os.Getenv("API_SECRET") client = bitvavo.NewHttpClient(httpc.WithDebug(false)) - authClient = client.ToAuthClient(key, secret, 0) + authClient = client.ToAuthClient(key, secret) ) - balance, err := authClient.GetBalance() + balance, err := authClient.GetBalance("ETH") if err != nil { log.Fatal(err) } diff --git a/httpc/client.go b/httpc/client.go index 249191e..78945ae 100644 --- a/httpc/client.go +++ b/httpc/client.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/http" + "net/url" "strings" "time" @@ -20,18 +21,22 @@ var ( func httpGet[T any]( url string, + params url.Values, updateRateLimit func(ratelimit int64), updateRateLimitResetAt func(resetAt time.Time), logDebug func(message string, args ...any), config *authConfig, ) (T, error) { - req, _ := http.NewRequest("GET", url, nil) + reqUrl := util.IfOrElse(len(params) > 0, func() string { return fmt.Sprintf("%s?%s", url, params.Encode()) }, url) + req, _ := http.NewRequest("GET", reqUrl, nil) + return httpDo[T](req, updateRateLimit, updateRateLimitResetAt, logDebug, config) } func httpPost[T any]( url string, body T, + params url.Values, updateRateLimit func(ratelimit int64), updateRateLimitResetAt func(resetAt time.Time), logDebug func(message string, args ...any), @@ -41,7 +46,9 @@ func httpPost[T any]( if err != nil { return body, err } - req, _ := http.NewRequest("POST", url, bytes.NewBuffer(payload)) + + reqUrl := util.IfOrElse(len(params) > 0, func() string { return fmt.Sprintf("%s?%s", url, params.Encode()) }, url) + req, _ := http.NewRequest("POST", reqUrl, bytes.NewBuffer(payload)) return httpDo[T](req, updateRateLimit, updateRateLimitResetAt, logDebug, config) } @@ -93,6 +100,7 @@ func httpDo[T any]( } defer response.Body.Close() + bytes, err := io.ReadAll(response.Body) if err != nil { return data, err diff --git a/httpc/httpclient.go b/httpc/httpclient.go index 162ebca..b670c22 100644 --- a/httpc/httpclient.go +++ b/httpc/httpclient.go @@ -2,10 +2,12 @@ package httpc import ( "fmt" + "net/url" "sync" "time" "github.com/larscom/go-bitvavo/v2/log" + "github.com/larscom/go-bitvavo/v2/util" ) const ( @@ -30,7 +32,7 @@ type HttpClient interface { // // If you set the value to 0, the default value of 10000 will be set. // Whenever you go higher than the max value of 60000 the value will be set to 60000. - ToAuthClient(apiKey string, apiSecret string, windowTimeMs uint64) HttpClientAuth + ToAuthClient(apiKey string, apiSecret string, windowTimeMs ...uint64) HttpClientAuth // GetTime returns the current server time in milliseconds since 1 Jan 1970 GetTime() (int64, error) @@ -77,20 +79,21 @@ func WithDebug(debug bool) Option { } } -func (c *httpClient) ToAuthClient(apiKey string, apiSecret string, windowTimeMs uint64) HttpClientAuth { +func (c *httpClient) ToAuthClient(apiKey string, apiSecret string, windowTimeMs ...uint64) HttpClientAuth { if c.hasAuthClient() { return c.authClient } - if windowTimeMs == 0 { - windowTimeMs = DefaultWindowTimeMs + windowTime := util.IfOrElse(len(windowTimeMs) > 0, func() uint64 { return windowTimeMs[0] }, 0) + if windowTime == 0 { + windowTime = DefaultWindowTimeMs } - if windowTimeMs > maxWindowTimeMs { - windowTimeMs = maxWindowTimeMs + if windowTime > maxWindowTimeMs { + windowTime = maxWindowTimeMs } config := &authConfig{ - windowTimeMs: windowTimeMs, + windowTimeMs: windowTime, apiKey: apiKey, apiSecret: apiSecret, } @@ -108,7 +111,14 @@ func (c *httpClient) GetRateLimitResetAt() time.Time { } func (c *httpClient) GetTime() (int64, error) { - resp, err := httpGet[map[string]float64](fmt.Sprintf("%s/time", httpUrl), c.updateRateLimit, c.updateRateLimitResetAt, c.logDebug, nil) + resp, err := httpGet[map[string]float64]( + fmt.Sprintf("%s/time", httpUrl), + make(url.Values), + c.updateRateLimit, + c.updateRateLimitResetAt, + c.logDebug, + nil, + ) if err != nil { return 0, err } diff --git a/httpc/httpclientauth.go b/httpc/httpclientauth.go index b203b03..a7df4b9 100644 --- a/httpc/httpclientauth.go +++ b/httpc/httpclientauth.go @@ -4,14 +4,17 @@ import ( "fmt" "time" + neturl "net/url" + "github.com/larscom/go-bitvavo/v2/jsond" ) type HttpClientAuth interface { - // GetBalance returns the balance on the account - GetBalance() ([]jsond.Balance, error) + // GetBalance returns the balance on the account. + // Optionally provide the symbol to filter for. + GetBalance(symbol ...string) ([]jsond.Balance, error) - // GetAccount returns trading volume and fees for account + // GetAccount returns trading volume and fees for account. GetAccount() (jsond.Account, error) } @@ -42,10 +45,28 @@ func newHttpClientAuth( } } -func (c *httpClientAuth) GetBalance() ([]jsond.Balance, error) { - return httpGet[[]jsond.Balance](fmt.Sprintf("%s/balance", httpUrl), c.updateRateLimit, c.updateRateLimitResetAt, c.logDebug, c.config) +func (c *httpClientAuth) GetBalance(symbol ...string) ([]jsond.Balance, error) { + params := make(neturl.Values) + if len(symbol) > 0 { + params.Add("symbol", symbol[0]) + } + return httpGet[[]jsond.Balance]( + fmt.Sprintf("%s/balance", httpUrl), + params, + c.updateRateLimit, + c.updateRateLimitResetAt, + c.logDebug, + c.config, + ) } func (c *httpClientAuth) GetAccount() (jsond.Account, error) { - return httpGet[jsond.Account](fmt.Sprintf("%s/account", httpUrl), c.updateRateLimit, c.updateRateLimitResetAt, c.logDebug, c.config) + return httpGet[jsond.Account]( + fmt.Sprintf("%s/account", httpUrl), + make(neturl.Values), + c.updateRateLimit, + c.updateRateLimitResetAt, + c.logDebug, + c.config, + ) } diff --git a/wsc/account.go b/wsc/account.go index da3af99..1c92545 100644 --- a/wsc/account.go +++ b/wsc/account.go @@ -135,13 +135,13 @@ func (f *FillEvent) UnmarshalJSON(bytes []byte) error { } type AccountSub interface { - // Order channel to receive order events - // You can set the buffSize for this channel, 0 for no buffer - Order(buffSize uint64) <-chan OrderEvent + // Order channel to receive order events. + // You can set the buffSize for this channel. + Order(buffSize ...uint64) <-chan OrderEvent - // Order channel to receive fill events - // You can set the buffSize for this channel, 0 for no buffer - Fill(buffSize uint64) <-chan FillEvent + // Order channel to receive fill events. + // You can set the buffSize for this channel. + Fill(buffSize ...uint64) <-chan FillEvent } type accountSub struct { @@ -149,15 +149,21 @@ type accountSub struct { fillchn chan<- FillEvent } -func (a *accountSub) Order(buffSize uint64) <-chan OrderEvent { - orderchn := make(chan OrderEvent, buffSize) +func (a *accountSub) Order(buffSize ...uint64) <-chan OrderEvent { + size := util.IfOrElse(len(buffSize) > 0, func() uint64 { return buffSize[0] }, 0) + + orderchn := make(chan OrderEvent, size) a.orderchn = orderchn + return orderchn } -func (a *accountSub) Fill(buffSize uint64) <-chan FillEvent { - fillchn := make(chan FillEvent, buffSize) +func (a *accountSub) Fill(buffSize ...uint64) <-chan FillEvent { + size := util.IfOrElse(len(buffSize) > 0, func() uint64 { return buffSize[0] }, 0) + + fillchn := make(chan FillEvent, size) a.fillchn = fillchn + return fillchn } diff --git a/wsc/book.go b/wsc/book.go index 7d8e4e6..f78bc1a 100644 --- a/wsc/book.go +++ b/wsc/book.go @@ -82,14 +82,16 @@ func newBookEventHandler(writechn chan<- WebSocketMessage) *bookEventHandler { } } -func (t *bookEventHandler) Subscribe(market string, buffSize uint64) (<-chan BookEvent, error) { +func (t *bookEventHandler) Subscribe(market string, buffSize ...uint64) (<-chan BookEvent, error) { if t.subs.Has(market) { return nil, fmt.Errorf("subscription already active for market: %s", market) } t.writechn <- newWebSocketMessage(actionSubscribe, channelNameBook, market) - chn := make(chan BookEvent, buffSize) + size := util.IfOrElse(len(buffSize) > 0, func() uint64 { return buffSize[0] }, 0) + + chn := make(chan BookEvent, size) t.subs.Set(market, chn) return chn, nil diff --git a/wsc/candles.go b/wsc/candles.go index 675622a..c488c92 100644 --- a/wsc/candles.go +++ b/wsc/candles.go @@ -6,6 +6,7 @@ import ( "github.com/larscom/go-bitvavo/v2/jsond" "github.com/larscom/go-bitvavo/v2/log" + "github.com/larscom/go-bitvavo/v2/util" "github.com/goccy/go-json" "github.com/smallnest/safemap" @@ -27,8 +28,8 @@ type CandlesEvent struct { type CandlesEventHandler interface { // Subscribe to market with interval. - // You can set the buffSize for this channel, 0 for no buffer - Subscribe(market string, interval string, buffSize uint64) (<-chan CandlesEvent, error) + // You can set the buffSize for this channel. + Subscribe(market string, interval string, buffSize ...uint64) (<-chan CandlesEvent, error) // Unsubscribe from market with interval Unsubscribe(market string, interval string) error @@ -62,7 +63,7 @@ func newCandleWebSocketMessage(action Action, market string, interval string) We } } -func (c *candlesEventHandler) Subscribe(market string, interval string, buffSize uint64) (<-chan CandlesEvent, error) { +func (c *candlesEventHandler) Subscribe(market string, interval string, buffSize ...uint64) (<-chan CandlesEvent, error) { key := getMapKey(market, interval) if c.subs.Has(key) { @@ -71,7 +72,9 @@ func (c *candlesEventHandler) Subscribe(market string, interval string, buffSize c.writechn <- newCandleWebSocketMessage(actionSubscribe, market, interval) - chn := make(chan CandlesEvent, buffSize) + size := util.IfOrElse(len(buffSize) > 0, func() uint64 { return buffSize[0] }, 0) + + chn := make(chan CandlesEvent, size) c.subs.Set(key, chn) return chn, nil diff --git a/wsc/ticker.go b/wsc/ticker.go index f10052e..d3efbf0 100644 --- a/wsc/ticker.go +++ b/wsc/ticker.go @@ -63,14 +63,16 @@ func newTickerEventHandler(writechn chan<- WebSocketMessage) *tickerEventHandler } } -func (t *tickerEventHandler) Subscribe(market string, buffSize uint64) (<-chan TickerEvent, error) { +func (t *tickerEventHandler) Subscribe(market string, buffSize ...uint64) (<-chan TickerEvent, error) { if t.subs.Has(market) { return nil, fmt.Errorf("subscription already active for market: %s", market) } t.writechn <- newWebSocketMessage(actionSubscribe, channelNameTicker, market) - chn := make(chan TickerEvent, buffSize) + size := util.IfOrElse(len(buffSize) > 0, func() uint64 { return buffSize[0] }, 0) + + chn := make(chan TickerEvent, size) t.subs.Set(market, chn) return chn, nil diff --git a/wsc/ticker24h.go b/wsc/ticker24h.go index 5cdc47f..0fedf8f 100644 --- a/wsc/ticker24h.go +++ b/wsc/ticker24h.go @@ -90,14 +90,16 @@ func newTicker24hEventHandler(writechn chan<- WebSocketMessage) *ticker24hEventH } } -func (t *ticker24hEventHandler) Subscribe(market string, buffSize uint64) (<-chan Ticker24hEvent, error) { +func (t *ticker24hEventHandler) Subscribe(market string, buffSize ...uint64) (<-chan Ticker24hEvent, error) { if t.subs.Has(market) { return nil, fmt.Errorf("subscription already active for market: %s", market) } t.writechn <- newWebSocketMessage(actionSubscribe, channelNameTicker24h, market) - chn := make(chan Ticker24hEvent, buffSize) + size := util.IfOrElse(len(buffSize) > 0, func() uint64 { return buffSize[0] }, 0) + + chn := make(chan Ticker24hEvent, size) t.subs.Set(market, chn) return chn, nil diff --git a/wsc/trades.go b/wsc/trades.go index ccf611d..ab87e81 100644 --- a/wsc/trades.go +++ b/wsc/trades.go @@ -65,14 +65,16 @@ func newTradesEventHandler(writechn chan<- WebSocketMessage) *tradesEventHandler } } -func (t *tradesEventHandler) Subscribe(market string, buffSize uint64) (<-chan TradesEvent, error) { +func (t *tradesEventHandler) Subscribe(market string, buffSize ...uint64) (<-chan TradesEvent, error) { if t.subs.Has(market) { return nil, fmt.Errorf("subscription already active for market: %s", market) } t.writechn <- newWebSocketMessage(actionSubscribe, channelNameTrades, market) - chn := make(chan TradesEvent, buffSize) + size := util.IfOrElse(len(buffSize) > 0, func() uint64 { return buffSize[0] }, 0) + + chn := make(chan TradesEvent, size) t.subs.Set(market, chn) return chn, nil diff --git a/wsc/wsclient.go b/wsc/wsclient.go index 562724b..f63c343 100644 --- a/wsc/wsclient.go +++ b/wsc/wsclient.go @@ -19,8 +19,8 @@ const ( type EventHandler[T any] interface { // Subscribe to market. - // You can set the buffSize for the underlying channel, 0 for no buffer. - Subscribe(market string, buffSize uint64) (<-chan T, error) + // You can set the buffSize for the channel. + Subscribe(market string, buffSize ...uint64) (<-chan T, error) // Unsubscribe from market. Unsubscribe(market string) error