|
| 1 | +import itertools |
1 | 2 | import os |
2 | 3 | import time |
3 | 4 |
|
|
21 | 22 | provider_url_mainnet = os.getenv("PROVIDER_URL_MAINNET") |
22 | 23 | provider_url_arb = os.getenv("PROVIDER_URL_ARBITRUM") |
23 | 24 |
|
| 25 | +# Round-robin iterator over available Safe API keys. |
| 26 | +_api_keys: list[str] = [k for k in [os.getenv("SAFE_API_KEY"), os.getenv("SAFE_API_KEY_2")] if k] |
| 27 | +if not _api_keys: |
| 28 | + raise ValueError("At least one SAFE_API_KEY must be set.") |
| 29 | +_api_key_cycle = itertools.cycle(_api_keys) |
| 30 | + |
24 | 31 | safe_address_network_prefix = { |
25 | 32 | "mainnet": "eth", |
26 | 33 | "arbitrum-main": "arb1", |
@@ -188,9 +195,7 @@ def get_safe_transactions( |
188 | 195 | if executed is not None: |
189 | 196 | params["executed"] = str(executed).lower() |
190 | 197 |
|
191 | | - api_key = os.getenv("SAFE_API_KEY") |
192 | | - if not api_key: |
193 | | - raise ValueError("SAFE_API_KEY environment variable not set.") |
| 198 | + api_key = next(_api_key_cycle) |
194 | 199 |
|
195 | 200 | headers = { |
196 | 201 | "Authorization": f"Bearer {api_key}", |
@@ -230,36 +235,23 @@ def get_safe_transactions( |
230 | 235 | return [] |
231 | 236 |
|
232 | 237 |
|
233 | | -def get_last_executed_nonce(safe_address: str, network_name: str) -> int: |
234 | | - executed_txs = get_safe_transactions(safe_address, network_name, executed=True, limit=1) |
235 | | - if executed_txs: |
236 | | - return int(executed_txs[0]["nonce"]) |
237 | | - return -1 # Return -1 if no executed transactions found |
238 | | - |
239 | | - |
240 | | -def get_pending_transactions_after_last_executed(safe_address: str, network_name: str) -> list[dict]: |
241 | | - last_executed_nonce = get_last_executed_nonce(safe_address, network_name) |
| 238 | +def get_pending_transactions(safe_address: str, network_name: str) -> list[dict]: |
| 239 | + """Fetch pending transactions with nonce higher than the last cached nonce.""" |
| 240 | + last_cached_nonce = get_last_executed_nonce_from_file(safe_address) |
242 | 241 | pending_txs = get_safe_transactions(safe_address, network_name, executed=False) |
243 | | - |
244 | | - if pending_txs: |
245 | | - return [tx for tx in pending_txs if int(tx["nonce"]) > last_executed_nonce] |
246 | | - return [] |
| 242 | + return [tx for tx in pending_txs if int(tx["nonce"]) > last_cached_nonce] |
247 | 243 |
|
248 | 244 |
|
249 | 245 | def get_safe_url(safe_address: str, network_name: str) -> str: |
250 | 246 | return f"{SAFE_WEBSITE_URL}{safe_address_network_prefix[network_name]}:{safe_address}" |
251 | 247 |
|
252 | 248 |
|
253 | 249 | def check_for_pending_transactions(safe_address: str, network_name: str, protocol: str) -> None: |
254 | | - pending_transactions = get_pending_transactions_after_last_executed(safe_address, network_name) |
| 250 | + pending_transactions = get_pending_transactions(safe_address, network_name) |
255 | 251 |
|
256 | 252 | if pending_transactions: |
257 | 253 | for tx in pending_transactions: |
258 | 254 | nonce = int(tx["nonce"]) |
259 | | - # skip tx if the nonce is already processed |
260 | | - if nonce <= get_last_executed_nonce_from_file(safe_address): |
261 | | - logger.info("Skipping tx with nonce %s as it is already processed.", nonce) |
262 | | - continue |
263 | 255 |
|
264 | 256 | target_contract = tx["to"] |
265 | 257 |
|
@@ -355,7 +347,7 @@ def main(): |
355 | 347 | logger.info("Running for %s on %s", safe[0], safe[1]) |
356 | 348 | last_api_call_time, request_counter = check_api_limit(last_api_call_time, request_counter) |
357 | 349 | run_for_network(safe[1], safe[2], safe[0]) |
358 | | - request_counter += 2 |
| 350 | + request_counter += 1 |
359 | 351 |
|
360 | 352 |
|
361 | 353 | if __name__ == "__main__": |
|
0 commit comments