@@ -233,10 +233,14 @@ def __init__(self, options: dict[str, str | int | list[dict[str, str]]] | None =
233233 else :
234234 self .api_keys = []
235235
236+ if not self .api_keys :
237+ msg = "API keys are required"
238+ raise ValueError (msg )
239+
236240 # Current API key index - options take precedence
237241 self .current_api_key_index : int = 0
238242
239- # Rate limiting per API key (keyless has index -1)
243+ # Rate limiting per API key
240244 self .rate_limits : dict [int , dict [str , int | ms ]] = {}
241245 # Get default rate limit from options or settings
242246 default_rate_limit_option = _options .get ("DEFAULT_RATE_LIMIT" , bitvavo_upgraded_settings .DEFAULT_RATE_LIMIT )
@@ -246,7 +250,6 @@ def __init__(self, options: dict[str, str | int | list[dict[str, str]]] | None =
246250 else bitvavo_upgraded_settings .DEFAULT_RATE_LIMIT
247251 )
248252
249- self .rate_limits [- 1 ] = {"remaining" : default_rate_limit , "resetAt" : ms (0 )} # keyless
250253 for i in range (len (self .api_keys )):
251254 self .rate_limits [i ] = {"remaining" : default_rate_limit , "resetAt" : ms (0 )}
252255
@@ -262,36 +265,21 @@ def __init__(self, options: dict[str, str | int | list[dict[str, str]]] | None =
262265 self .debugging : bool = bool (_options .get ("DEBUGGING" , bitvavo_settings .DEBUGGING ))
263266
264267 def get_best_api_key_config (self , rateLimitingWeight : int = 1 ) -> tuple [str , str , int ]:
265- """
266- Get the best API key configuration to use for a request.
267-
268- Returns:
269- tuple: (api_key, api_secret, key_index) where key_index is -1 for keyless
270- """
271- # If keyless has enough rate limit, use keyless
272- if self ._has_rate_limit_available (- 1 , rateLimitingWeight ):
273- return "" , "" , - 1
268+ """Get the best API key configuration to use for a request."""
274269
275- # Try to find an API key with enough rate limit
276270 for i in range (len (self .api_keys )):
277271 if self ._has_rate_limit_available (i , rateLimitingWeight ):
278272 return self .api_keys [i ]["key" ], self .api_keys [i ]["secret" ], i
279273
280- # If keyless is available, use it as fallback
281- if self ._has_rate_limit_available (- 1 , rateLimitingWeight ):
282- return "" , "" , - 1
283-
284- # No keys available, use current key and let rate limiting handle the wait
285- if self .api_keys :
286- return (
287- self .api_keys [self .current_api_key_index ]["key" ],
288- self .api_keys [self .current_api_key_index ]["secret" ],
289- self .current_api_key_index ,
290- )
291- return "" , "" , - 1
274+ # No keys have available budget, use current key and let rate limiting handle the wait
275+ return (
276+ self .api_keys [self .current_api_key_index ]["key" ],
277+ self .api_keys [self .current_api_key_index ]["secret" ],
278+ self .current_api_key_index ,
279+ )
292280
293281 def _has_rate_limit_available (self , key_index : int , weight : int ) -> bool :
294- """Check if a specific API key (or keyless) has enough rate limit."""
282+ """Check if a specific API key has enough rate limit."""
295283 if key_index not in self .rate_limits :
296284 return False
297285 remaining = self .rate_limits [key_index ]["remaining" ]
@@ -317,7 +305,7 @@ def _update_rate_limit_for_key(self, key_index: int, response: anydict | errordi
317305 self .rate_limits [key_index ]["resetAt" ] = ms (time_ms () + 60000 )
318306
319307 timeToWait = time_to_wait (ms (self .rate_limits [key_index ]["resetAt" ]))
320- key_name = f"API_KEY_{ key_index } " if key_index >= 0 else "KEYLESS"
308+ key_name = f"API_KEY_{ key_index } "
321309 logger .warning (
322310 "api-key-banned" ,
323311 info = {
@@ -527,46 +515,33 @@ def public_request(
527515 list[list[str]]
528516 ```
529517 """
530- # Get the best API key configuration (keyless preferred, then available keys)
518+ # Get the best API key configuration
531519 api_key , api_secret , key_index = self .get_best_api_key_config (rateLimitingWeight )
532520
533521 # Check if we need to wait for rate limit
534522 if not self ._has_rate_limit_available (key_index , rateLimitingWeight ):
535523 self ._sleep_for_key (key_index )
536524
537525 # Update current API key for legacy compatibility
538- if api_key :
539- self ._current_api_key = api_key
540- self ._current_api_secret = api_secret
541- self .current_api_key_index = key_index
542- else :
543- # Using keyless
544- self ._current_api_key = ""
545- self ._current_api_secret = ""
526+ self ._current_api_key = api_key
527+ self ._current_api_secret = api_secret
528+ self .current_api_key_index = key_index
546529
547530 if self .debugging :
548531 logger .debug (
549532 "api-request" ,
550- info = {
551- "url" : url ,
552- "with_api_key" : bool (api_key != "" ),
553- "public_or_private" : "public" ,
554- "key_index" : key_index ,
555- },
533+ info = {"url" : url , "key_index" : key_index },
556534 )
557535
558- if api_key :
559- now = time_ms () + bitvavo_upgraded_settings .LAG
560- sig = create_signature (now , "GET" , url .replace (self .base , "" ), None , api_secret )
561- headers = {
562- "bitvavo-access-key" : api_key ,
563- "bitvavo-access-signature" : sig ,
564- "bitvavo-access-timestamp" : str (now ),
565- "bitvavo-access-window" : str (self .ACCESSWINDOW ),
566- }
567- r = get (url , headers = headers , timeout = (self .ACCESSWINDOW / 1000 ))
568- else :
569- r = get (url , timeout = (self .ACCESSWINDOW / 1000 ))
536+ now = time_ms () + bitvavo_upgraded_settings .LAG
537+ sig = create_signature (now , "GET" , url .replace (self .base , "" ), None , api_secret )
538+ headers = {
539+ "bitvavo-access-key" : api_key ,
540+ "bitvavo-access-signature" : sig ,
541+ "bitvavo-access-timestamp" : str (now ),
542+ "bitvavo-access-window" : str (self .ACCESSWINDOW ),
543+ }
544+ r = get (url , headers = headers , timeout = (self .ACCESSWINDOW / 1000 ))
570545
571546 # Update rate limit for the specific key used
572547 if "error" in r .json ():
@@ -2368,7 +2343,7 @@ def remove_api_key(self, api_key: str) -> bool:
23682343 # Update rate limit tracking indices (shift them down)
23692344 new_rate_limits = {}
23702345 for key_idx , limits in self .rate_limits .items ():
2371- if key_idx == - 1 or key_idx < i : # keyless
2346+ if key_idx < i :
23722347 new_rate_limits [key_idx ] = limits
23732348 elif key_idx > i :
23742349 new_rate_limits [key_idx - 1 ] = limits
@@ -2386,19 +2361,10 @@ def get_api_key_status(self) -> dict[str, dict[str, int | str | bool]]:
23862361 """Get the current status of all API keys including rate limits.
23872362
23882363 Returns:
2389- dict: Status information for keyless and all API keys
2364+ dict: Status information for all API keys
23902365 """
23912366 status = {}
23922367
2393- # Keyless status
2394- keyless_limits = self .rate_limits .get (- 1 , {"remaining" : 0 , "resetAt" : ms (0 )})
2395- status ["keyless" ] = {
2396- "remaining" : int (keyless_limits ["remaining" ]),
2397- "resetAt" : int (keyless_limits ["resetAt" ]),
2398- "available" : self ._has_rate_limit_available (- 1 , 1 ),
2399- }
2400-
2401- # API key status
24022368 for i , key_data in enumerate (self .api_keys ):
24032369 key_limits = self .rate_limits .get (i , {"remaining" : 0 , "resetAt" : ms (0 )})
24042370 KEY_LENGTH = 12
0 commit comments