-
Notifications
You must be signed in to change notification settings - Fork 0
feat: remove deprecated BaseScan, integrate Base via Etherscan V2 #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Remove BaseScanV1 scanner implementation - Integrate Base network support via Etherscan V2 with chain_id 8453 - Update UrlBuilder to use etherscan.io for Base network - Update configuration and tests to reflect Base via Etherscan V2 - Fix EtherscanV2 authentication to use query parameter instead of header - Update documentation to show Base network via Etherscan V2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting
| @pytest.mark.asyncio | ||
| async def test_blockscout_two_chains_live() -> None: | ||
| # BlockScout typically doesn't require API keys | ||
| tests = [ | ||
| ('blockscout', 'v1', 'blockscout_eth', 'eth'), | ||
| ('blockscout', 'v1', 'blockscout_polygon', 'polygon'), | ||
| ] | ||
|
|
||
| for scanner_name, version, scanner_id, network in tests: | ||
| client = ChainscanClient.from_config(scanner_name, version, scanner_id, network) | ||
| await _assert_balance_ok(client, TEST_ADDRESS) | ||
| await client.close() | ||
| # Gentle pacing between providers | ||
| await asyncio.sleep(0.2) | ||
|
|
||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_etherscan_two_chains_live() -> None: | ||
| # Requires ETHERSCAN_KEY in env | ||
| etherscan_key = os.getenv('ETHERSCAN_KEY') | ||
| if not etherscan_key or 'YOUR_' in etherscan_key or len(etherscan_key) < 10: | ||
| pytest.skip('ETHERSCAN_KEY not configured for live Etherscan tests') | ||
|
|
||
| tests = [ | ||
| ('etherscan', 'v2', 'eth', 'main'), | ||
| ('etherscan', 'v2', 'arbitrum', 'main'), | ||
| ('etherscan', 'v2', 'base', 'main'), # Base network via Etherscan V2 | ||
| ] | ||
|
|
||
| for scanner_name, version, scanner_id, network in tests: | ||
| # Etherscan V2 scanners use ETHERSCAN_KEY | ||
| if scanner_id in ('eth', 'arbitrum', 'bsc', 'polygon', 'optimism', 'base'): | ||
| if not _has_etherscan_key(): | ||
| pytest.skip(f'ETHERSCAN_KEY not configured for {scanner_id}') | ||
| elif not _has_api_key(scanner_id): | ||
| pytest.skip(f'Missing API key for {scanner_id}') | ||
|
|
||
| client = ChainscanClient.from_config(scanner_name, version, scanner_id, network) | ||
| try: | ||
| await _assert_balance_ok(client, TEST_ADDRESS) | ||
| except ChainscanClientApiError as e: # pragma: no cover - live guardrail | ||
| # Gracefully skip if the environment key is invalid/rate-limited | ||
| msg = str(e) | ||
| if ( | ||
| 'Invalid API Key' in msg | ||
| or 'Missing/Invalid API Key' in msg | ||
| or 'rate limit' in msg.lower() | ||
| ): | ||
| pytest.skip(f'Etherscan live test skipped due to API key/limits: {msg}') | ||
| raise | ||
| finally: | ||
| await client.close() | ||
| await asyncio.sleep(0.2) | ||
|
|
||
|
|
||
| # Base network is now supported through Etherscan V2 with chain_id | ||
| # No need for separate BaseScan scanner | ||
|
|
||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_moralis_two_chains_live() -> None: | ||
| # Moralis requires MORALIS_API_KEY | ||
| tests = [ | ||
| ('moralis', 'v1', 'moralis', 'eth'), | ||
| ('moralis', 'v1', 'moralis', 'arbitrum'), | ||
| ] | ||
|
|
||
| for scanner_name, version, scanner_id, network in tests: | ||
| if not _has_api_key(scanner_id): | ||
| pytest.skip('Missing MORALIS_API_KEY') | ||
| client = ChainscanClient.from_config(scanner_name, version, scanner_id, network) | ||
| await _assert_balance_ok(client, TEST_ADDRESS) | ||
| await client.close() | ||
| await asyncio.sleep(0.2) | ||
|
|
||
|
|
||
| @pytest.mark.asyncio | ||
| async def test_routscan_mode_live() -> None: | ||
| # RoutScan supports Mode only (one network) | ||
| # RoutScan may not be registered in config in all environments; skip if unknown | ||
| try: | ||
| scanner_name, version, scanner_id, network = ('routscan', 'v1', 'routscan_mode', 'mode') | ||
| client = ChainscanClient.from_config(scanner_name, version, scanner_id, network) | ||
| except Exception as e: | ||
| pytest.skip(f'RoutScan not available in this build: {e}') | ||
| # Address may be zero on Mode; we still validate shape | ||
| await _assert_balance_ok(client, TEST_ADDRESS) | ||
| await client.close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard live balance tests behind opt‑in flag
The new tests/test_e2e_balances_live.py runs real HTTP calls to BlockScout, Moralis, RoutScan, and Etherscan every time pytest is executed. Aside from skipping when API keys are missing, these tests are always enabled and perform network I/O (ChainscanClient.from_config(...); await _assert_balance_ok(...)). In environments without Internet access or when rate limits are hit, the default test suite will now fail rather than being skipped. Consider gating these tests behind an explicit marker or environment flag so the regular unit test run remains deterministic and offline-friendly.
Useful? React with 👍 / 👎.
🎯 Changes Summary
This PR removes the deprecated BaseScan scanner and integrates Base network support through Etherscan V2 API.
✅ What was done:
🚀 Benefits:
📋 Technical Details:
ChainscanClient.from_config('etherscan', 'v2', 'base', 'main')https://api.etherscan.io/v2/api?chainid=8453🧪 Testing:
🔄 Migration:
Existing code using BaseScan will need to be updated to use Etherscan V2: