|
1 | 1 | from dataclasses import dataclass |
2 | | -from typing import List |
| 2 | +from typing import List, Optional |
3 | 3 |
|
4 | 4 | import logging |
5 | 5 | import requests |
@@ -96,3 +96,50 @@ def get_logs(from_block: int, to_block: int, api_key: str) -> List["L1Client.Log |
96 | 96 | ) |
97 | 97 | for result in results |
98 | 98 | ] |
| 99 | + |
| 100 | + @staticmethod |
| 101 | + def get_timestamp_of_block(block_number: int, api_key: str) -> Optional[int]: |
| 102 | + """ |
| 103 | + Get block timestamp by block number using eth_getBlockByNumber RPC method. |
| 104 | + Tries up to RETRIES_COUNT times. On failure, logs an error and returns None. |
| 105 | + """ |
| 106 | + rpc_url = L1Client.L1_MAINNET_URL.format(api_key=api_key) |
| 107 | + |
| 108 | + payload = { |
| 109 | + "jsonrpc": "2.0", |
| 110 | + "method": "eth_getBlockByNumber", |
| 111 | + "params": [hex(block_number), False], |
| 112 | + "id": 1, |
| 113 | + } |
| 114 | + |
| 115 | + for attempt in range(L1Client.RETRIES_COUNT): |
| 116 | + try: |
| 117 | + response = requests.post(rpc_url, json=payload, timeout=10) |
| 118 | + response.raise_for_status() |
| 119 | + result = response.json() |
| 120 | + logger.debug( |
| 121 | + f"get_timestamp_of_block succeeded on attempt {attempt + 1}", |
| 122 | + extra={"url": rpc_url, "block_number": block_number}, |
| 123 | + ) |
| 124 | + break # success -> exit loop |
| 125 | + except (requests.RequestException, ValueError) as exc: |
| 126 | + logger.debug( |
| 127 | + f"get_timestamp_of_block attempt {attempt + 1}/{L1Client.RETRIES_COUNT} failed", |
| 128 | + extra={"url": rpc_url, "block_number": block_number}, |
| 129 | + exc_info=True, |
| 130 | + ) |
| 131 | + |
| 132 | + else: |
| 133 | + logger.error( |
| 134 | + f"get_timestamp_of_block failed after {L1Client.RETRIES_COUNT} attempts, returning None", |
| 135 | + extra={"url": rpc_url, "block_number": block_number}, |
| 136 | + ) |
| 137 | + return None |
| 138 | + |
| 139 | + block = result.get("result") |
| 140 | + if block is None: |
| 141 | + # Block not found |
| 142 | + return None |
| 143 | + |
| 144 | + # Timestamp is hex string, convert to int. |
| 145 | + return int(block["timestamp"], 16) |
0 commit comments