Skip to content

Commit 56209f0

Browse files
authored
Merge pull request #19 from gnarvaja/etherscan-error-handling
Add etherscan chain id override. Improve etherscan error handling
2 parents c5ec9c2 + f1ee83a commit 56209f0

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

src/ethproto/wrappers.py

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
ETHERSCAN_TOKEN = env.str("ETHERSCAN_TOKEN", None)
1919
ETHERSCAN_DOMAIN = env.str("ETHERSCAN_DOMAIN", "api.etherscan.io")
2020
ETHERSCAN_URL = env.str("ETHERSCAN_URL", "https://{domain}/v2/api?apikey={token}&chainid={chainid}&")
21+
ETHERSCAN_CHAIN_ID = env.int("ETHERSCAN_CHAIN_ID", None)
22+
2123
AMOUNT_DECIMALS = env.int("AMOUNT_DECIMALS", 18)
2224
AMOUNT_CLASSNAME = env.str("AMOUNT_CLASSNAME", None)
2325

@@ -31,6 +33,10 @@
3133
_providers = {}
3234

3335

36+
class EtherscanError(Exception):
37+
...
38+
39+
3440
def get_provider(provider_key=None):
3541
global DEFAULT_PROVIDER
3642
provider_key = provider_key or DEFAULT_PROVIDER
@@ -266,9 +272,8 @@ def get_events(self, eth_wrapper, event_name, filter_kwargs={}):
266272
def get_etherscan_url(self):
267273
if ETHERSCAN_TOKEN is None:
268274
return None
269-
return ETHERSCAN_URL.format(
270-
token=ETHERSCAN_TOKEN, domain=ETHERSCAN_DOMAIN, chainid=self.w3.eth.chain_id
271-
)
275+
chain_id = ETHERSCAN_CHAIN_ID or self.w3.eth.chain_id
276+
return ETHERSCAN_URL.format(token=ETHERSCAN_TOKEN, domain=ETHERSCAN_DOMAIN, chainid=chain_id)
272277

273278
def get_first_block(self, eth_wrapper):
274279
etherscan_url = self.get_etherscan_url()
@@ -283,9 +288,12 @@ def get_first_block(self, eth_wrapper):
283288
resp = requests.get(url)
284289
resp.raise_for_status()
285290
resp = resp.json()
286-
if not resp["result"]:
287-
return -1
288-
return int(resp["result"][0]["blockNumber"])
291+
if resp.get("status") != "1":
292+
raise EtherscanError(f"Failed to get first block from {etherscan_url}: {resp}")
293+
try:
294+
return int(resp["result"][0]["blockNumber"])
295+
except (KeyError, TypeError):
296+
raise EtherscanError(f"Failed to parse first block for {address}: {resp}")
289297

290298
def get_contract_address(self, eth_wrapper):
291299
return eth_wrapper.contract.address

tests/test_aa_bundler.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,21 @@
55

66
import pytest
77
from hexbytes import HexBytes
8-
from web3.auto import w3
8+
from web3 import HTTPProvider, Web3
99
from web3.constants import HASH_ZERO
10+
from web3.middleware import ExtraDataToPOAMiddleware
1011

1112
from ethproto import aa_bundler
1213
from ethproto.test_utils import factories
1314

1415

16+
@pytest.fixture
17+
def w3():
18+
w3 = Web3(HTTPProvider("http://example.org"))
19+
w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
20+
return w3
21+
22+
1523
def test_pack_two():
1624
assert aa_bundler.pack_two(0, 0) == HASH_ZERO
1725
assert aa_bundler.pack_two(1, 2) == "0x0000000000000000000000000000000100000000000000000000000000000002"
@@ -166,8 +174,8 @@ def test_get_nonce_with_local_cache(fetch_nonce_mock, randint_mock):
166174
fetch_nonce_mock.assert_not_called()
167175

168176

169-
def test_send_transaction():
170-
w3 = MagicMock()
177+
def test_send_transaction(w3):
178+
w3.eth = MagicMock()
171179
w3.eth.chain_id = CHAIN_ID
172180

173181
tx = aa_bundler.Tx(
@@ -275,7 +283,8 @@ def worker():
275283

276284

277285
@pytest.mark.vcr
278-
def test_build_user_operation():
286+
def test_build_user_operation(w3):
287+
279288
tx = aa_bundler.Tx(
280289
value=0,
281290
chain_id=137,

0 commit comments

Comments
 (0)