eth-prototype 1.3.3__tar.gz → 1.3.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/PKG-INFO +2 -1
  2. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/setup.cfg +1 -0
  3. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/eth_prototype.egg-info/PKG-INFO +2 -1
  4. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/eth_prototype.egg-info/requires.txt +1 -0
  5. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/wrappers.py +16 -6
  6. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/test_aa_bundler.py +13 -4
  7. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/test_w3.py +51 -0
  8. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/.coveragerc +0 -0
  9. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/.github/workflows/publish.yaml +0 -0
  10. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/.github/workflows/test.yaml +0 -0
  11. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/.gitignore +0 -0
  12. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/.isort.cfg +0 -0
  13. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/.pre-commit-config.yaml +0 -0
  14. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/.readthedocs.yml +0 -0
  15. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/AUTHORS.rst +0 -0
  16. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/CHANGELOG.rst +0 -0
  17. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/LICENSE.txt +0 -0
  18. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/README.md +0 -0
  19. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/docs/Makefile +0 -0
  20. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/docs/_static/.gitignore +0 -0
  21. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/docs/authors.rst +0 -0
  22. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/docs/changelog.rst +0 -0
  23. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/docs/conf.py +0 -0
  24. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/docs/index.rst +0 -0
  25. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/docs/license.rst +0 -0
  26. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/docs/readme.rst +0 -0
  27. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/docs/requirements.txt +0 -0
  28. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/pyproject.toml +0 -0
  29. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/setup.py +0 -0
  30. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/eth_prototype.egg-info/SOURCES.txt +0 -0
  31. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/eth_prototype.egg-info/dependency_links.txt +0 -0
  32. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/eth_prototype.egg-info/not-zip-safe +0 -0
  33. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/eth_prototype.egg-info/top_level.txt +0 -0
  34. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/__init__.py +0 -0
  35. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/aa_bundler.py +0 -0
  36. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/build_artifacts.py +0 -0
  37. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/contracts.py +0 -0
  38. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/defender_relay.py +0 -0
  39. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/test_utils/__init__.py +0 -0
  40. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/test_utils/factories.py +0 -0
  41. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/test_utils/hardhat.py +0 -0
  42. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/test_utils/vcr_utils.py +0 -0
  43. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/w3wrappers.py +0 -0
  44. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/src/ethproto/wadray.py +0 -0
  45. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/__init__.py +0 -0
  46. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/cassettes/test_aa_bundler/test_build_user_operation.yaml +0 -0
  47. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/conftest.py +0 -0
  48. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/README.md +0 -0
  49. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/artifacts2/TestCurrency.sol/TestCurrency.json +0 -0
  50. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/contracts/Count.sol +0 -0
  51. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/contracts/Counter.sol +0 -0
  52. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/contracts/CounterUpgradeable.sol +0 -0
  53. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/contracts/CounterUpgradeableWithLibrary.sol +0 -0
  54. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/contracts/CounterWithLibrary.sol +0 -0
  55. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/contracts/Datatypes.sol +0 -0
  56. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/contracts/EventLauncher.sol +0 -0
  57. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/contracts/TestCurrency.sol +0 -0
  58. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/contracts/TestCurrencyUUPS.sol +0 -0
  59. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/contracts/TestNFT.sol +0 -0
  60. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/hardhat.config.js +0 -0
  61. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/package-lock.json +0 -0
  62. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/package.json +0 -0
  63. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/verifiable-binaries/@anotherOrg/aPkg/1.0.2/build/contracts/TestCurrency.sol/TestCurrency.json +0 -0
  64. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/verifiable-binaries/@org/pkg/0.2.1/build/contracts/TestCurrency.json +0 -0
  65. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/hardhat-project/verifiable-binaries/@org/pkg/0.3.0/build/contracts/TestCurrency.json +0 -0
  66. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/test_build_artifacts.py +0 -0
  67. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/test_contracts.py +0 -0
  68. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/test_defender.py +0 -0
  69. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/test_time_control.py +0 -0
  70. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tests/test_wadray.py +0 -0
  71. {eth_prototype-1.3.3 → eth_prototype-1.3.5}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eth-prototype
3
- Version: 1.3.3
3
+ Version: 1.3.5
4
4
  Summary: Prototype Ethereum Smart Contracts in Python
5
5
  Home-page: https://github.com/gnarvaja/eth-prototype
6
6
  Author: Guillermo M. Narvaja
@@ -33,6 +33,7 @@ Requires-Dist: pytest; extra == "testing"
33
33
  Requires-Dist: pytest-cov; extra == "testing"
34
34
  Requires-Dist: pytest-mock; extra == "testing"
35
35
  Requires-Dist: pytest-recording; extra == "testing"
36
+ Requires-Dist: responses; extra == "testing"
36
37
  Requires-Dist: setuptools; extra == "testing"
37
38
  Requires-Dist: web3[tester]==7.*; extra == "testing"
38
39
  Dynamic: license-file
@@ -48,6 +48,7 @@ testing =
48
48
  pytest-cov
49
49
  pytest-mock
50
50
  pytest-recording
51
+ responses
51
52
  setuptools
52
53
  web3[tester]==7.*
53
54
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eth-prototype
3
- Version: 1.3.3
3
+ Version: 1.3.5
4
4
  Summary: Prototype Ethereum Smart Contracts in Python
5
5
  Home-page: https://github.com/gnarvaja/eth-prototype
6
6
  Author: Guillermo M. Narvaja
@@ -33,6 +33,7 @@ Requires-Dist: pytest; extra == "testing"
33
33
  Requires-Dist: pytest-cov; extra == "testing"
34
34
  Requires-Dist: pytest-mock; extra == "testing"
35
35
  Requires-Dist: pytest-recording; extra == "testing"
36
+ Requires-Dist: responses; extra == "testing"
36
37
  Requires-Dist: setuptools; extra == "testing"
37
38
  Requires-Dist: web3[tester]==7.*; extra == "testing"
38
39
  Dynamic: license-file
@@ -20,6 +20,7 @@ pytest
20
20
  pytest-cov
21
21
  pytest-mock
22
22
  pytest-recording
23
+ responses
23
24
  setuptools
24
25
  web3[tester]==7.*
25
26
 
@@ -17,7 +17,9 @@ DEFAULT_PROVIDER = env.str("DEFAULT_PROVIDER", None)
17
17
 
18
18
  ETHERSCAN_TOKEN = env.str("ETHERSCAN_TOKEN", None)
19
19
  ETHERSCAN_DOMAIN = env.str("ETHERSCAN_DOMAIN", "api.etherscan.io")
20
- ETHERSCAN_URL = env.str("ETHERSCAN_URL", "https://{domain}/api?apikey={token}&")
20
+ 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
+
21
23
  AMOUNT_DECIMALS = env.int("AMOUNT_DECIMALS", 18)
22
24
  AMOUNT_CLASSNAME = env.str("AMOUNT_CLASSNAME", None)
23
25
 
@@ -31,6 +33,10 @@ MAXUINT256 = 2**256 - 1
31
33
  _providers = {}
32
34
 
33
35
 
36
+ class EtherscanError(Exception):
37
+ ...
38
+
39
+
34
40
  def get_provider(provider_key=None):
35
41
  global DEFAULT_PROVIDER
36
42
  provider_key = provider_key or DEFAULT_PROVIDER
@@ -266,7 +272,8 @@ class BaseProvider(ABC):
266
272
  def get_etherscan_url(self):
267
273
  if ETHERSCAN_TOKEN is None:
268
274
  return None
269
- return ETHERSCAN_URL.format(token=ETHERSCAN_TOKEN, domain=ETHERSCAN_DOMAIN)
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)
270
277
 
271
278
  def get_first_block(self, eth_wrapper):
272
279
  etherscan_url = self.get_etherscan_url()
@@ -275,15 +282,18 @@ class BaseProvider(ABC):
275
282
  address = self.get_contract_address(eth_wrapper)
276
283
  url = (
277
284
  etherscan_url
278
- + f"&module=account&action=txlist&address={address}&startblock=0&"
285
+ + f"module=account&action=txlist&address={address}&startblock=0&"
279
286
  + "endblock=99999999&page=1&offset=10&sort=asc"
280
287
  )
281
288
  resp = requests.get(url)
282
289
  resp.raise_for_status()
283
290
  resp = resp.json()
284
- if not resp["result"]:
285
- return -1
286
- 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}")
287
297
 
288
298
  def get_contract_address(self, eth_wrapper):
289
299
  return eth_wrapper.contract.address
@@ -5,13 +5,21 @@ from unittest.mock import MagicMock, patch
5
5
 
6
6
  import pytest
7
7
  from hexbytes import HexBytes
8
- from web3.auto import w3
8
+ from web3 import HTTPProvider, Web3
9
9
  from web3.constants import HASH_ZERO
10
+ from web3.middleware import ExtraDataToPOAMiddleware
10
11
 
11
12
  from ethproto import aa_bundler
12
13
  from ethproto.test_utils import factories
13
14
 
14
15
 
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
+
15
23
  def test_pack_two():
16
24
  assert aa_bundler.pack_two(0, 0) == HASH_ZERO
17
25
  assert aa_bundler.pack_two(1, 2) == "0x0000000000000000000000000000000100000000000000000000000000000002"
@@ -166,8 +174,8 @@ def test_get_nonce_with_local_cache(fetch_nonce_mock, randint_mock):
166
174
  fetch_nonce_mock.assert_not_called()
167
175
 
168
176
 
169
- def test_send_transaction():
170
- w3 = MagicMock()
177
+ def test_send_transaction(w3):
178
+ w3.eth = MagicMock()
171
179
  w3.eth.chain_id = CHAIN_ID
172
180
 
173
181
  tx = aa_bundler.Tx(
@@ -275,7 +283,8 @@ def test_random_key_nonces_are_thread_safe():
275
283
 
276
284
 
277
285
  @pytest.mark.vcr
278
- def test_build_user_operation():
286
+ def test_build_user_operation(w3):
287
+
279
288
  tx = aa_bundler.Tx(
280
289
  value=0,
281
290
  chain_id=137,
@@ -1,6 +1,9 @@
1
+ import importlib
1
2
  import os
3
+ import sys
2
4
 
3
5
  import pytest
6
+ import responses
4
7
  from web3 import Web3
5
8
 
6
9
  from ethproto import w3wrappers, wrappers
@@ -11,6 +14,28 @@ pytestmark = [
11
14
  ]
12
15
 
13
16
 
17
+ @pytest.fixture
18
+ def provider_with_etherscan_env(mocker):
19
+ mocker.patch.dict(
20
+ os.environ,
21
+ {"ETHERSCAN_TOKEN": "abc123", "ETHERSCAN_DOMAIN": "api.etherscan.io"},
22
+ )
23
+ sys.modules.pop("ethproto.wrappers", None)
24
+ sys.modules.pop("ethproto.w3wrappers", None)
25
+ wrappers = importlib.import_module("ethproto.wrappers")
26
+ w3wrappers = importlib.import_module("ethproto.w3wrappers")
27
+
28
+ w3wrappers.register_w3_provider("w3_test", Web3(Web3.EthereumTesterProvider()))
29
+ provider = wrappers.get_provider("w3_test")
30
+
31
+ return provider
32
+
33
+
34
+ class DummyWrapper:
35
+ address = "0x8e3aab1fc53e8b0f5d987c20b1899a2db3b2f95c" # random generated address
36
+ contract = type("Contract", (), {"address": address})()
37
+
38
+
14
39
  class Counter(wrappers.ETHWrapper):
15
40
  eth_contract = "Counter"
16
41
  # libraries_required = []
@@ -182,3 +207,29 @@ def test_sign_and_send_interact_with_existing_contract(sign_and_send):
182
207
  assert connected.value() == 1
183
208
 
184
209
  assert counter.value() == 1 # sanity check
210
+
211
+
212
+ def test_get_etherscan_url_v2_format(provider_with_etherscan_env):
213
+ provider = provider_with_etherscan_env
214
+ chainid = provider.w3.eth.chain_id
215
+ assert provider.get_etherscan_url() == f"https://api.etherscan.io/v2/api?apikey=abc123&chainid={chainid}&"
216
+
217
+
218
+ @responses.activate
219
+ def test_get_first_block_makes_request(provider_with_etherscan_env):
220
+ provider = provider_with_etherscan_env
221
+ address = "0x8e3aab1fc53e8b0f5d987c20b1899a2db3b2f95c"
222
+ chainid = provider.w3.eth.chain_id
223
+ responses.get(
224
+ f"https://api.etherscan.io/v2/api?apikey=abc123&chainid={chainid}&"
225
+ f"&module=account&action=txlist&address={address}&startblock=0&"
226
+ "endblock=99999999&page=1&offset=10&sort=asc",
227
+ json={"status": "1", "message": "OK", "result": [{"blockNumber": "1"}]},
228
+ status=200,
229
+ )
230
+
231
+ block = provider.get_first_block(DummyWrapper())
232
+ assert block == 1
233
+
234
+ assert len(responses.calls) == 1
235
+ assert responses.calls[0].request.url.startswith("https://api.etherscan.io")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes