eth-prototype 1.3.2__tar.gz → 1.3.4__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.
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/PKG-INFO +2 -1
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/setup.cfg +1 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/eth_prototype.egg-info/PKG-INFO +2 -1
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/eth_prototype.egg-info/requires.txt +1 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/aa_bundler.py +15 -6
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/wrappers.py +5 -3
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/test_w3.py +51 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/.coveragerc +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/.github/workflows/publish.yaml +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/.github/workflows/test.yaml +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/.gitignore +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/.isort.cfg +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/.pre-commit-config.yaml +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/.readthedocs.yml +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/AUTHORS.rst +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/CHANGELOG.rst +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/LICENSE.txt +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/README.md +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/docs/Makefile +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/docs/_static/.gitignore +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/docs/authors.rst +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/docs/changelog.rst +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/docs/conf.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/docs/index.rst +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/docs/license.rst +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/docs/readme.rst +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/docs/requirements.txt +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/pyproject.toml +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/setup.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/eth_prototype.egg-info/SOURCES.txt +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/eth_prototype.egg-info/dependency_links.txt +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/eth_prototype.egg-info/not-zip-safe +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/eth_prototype.egg-info/top_level.txt +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/__init__.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/build_artifacts.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/contracts.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/defender_relay.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/test_utils/__init__.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/test_utils/factories.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/test_utils/hardhat.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/test_utils/vcr_utils.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/w3wrappers.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/src/ethproto/wadray.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/__init__.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/cassettes/test_aa_bundler/test_build_user_operation.yaml +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/conftest.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/README.md +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/artifacts2/TestCurrency.sol/TestCurrency.json +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/Count.sol +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/Counter.sol +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/CounterUpgradeable.sol +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/CounterUpgradeableWithLibrary.sol +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/CounterWithLibrary.sol +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/Datatypes.sol +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/EventLauncher.sol +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/TestCurrency.sol +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/TestCurrencyUUPS.sol +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/TestNFT.sol +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/hardhat.config.js +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/package-lock.json +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/package.json +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/verifiable-binaries/@anotherOrg/aPkg/1.0.2/build/contracts/TestCurrency.sol/TestCurrency.json +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/verifiable-binaries/@org/pkg/0.2.1/build/contracts/TestCurrency.json +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/verifiable-binaries/@org/pkg/0.3.0/build/contracts/TestCurrency.json +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/test_aa_bundler.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/test_build_artifacts.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/test_contracts.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/test_defender.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/test_time_control.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/test_wadray.py +0 -0
- {eth_prototype-1.3.2 → eth_prototype-1.3.4}/tox.ini +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: eth-prototype
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.4
|
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
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: eth-prototype
|
3
|
-
Version: 1.3.
|
3
|
+
Version: 1.3.4
|
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
|
@@ -29,6 +29,7 @@ AA_BUNDLER_GAS_LIMIT_FACTOR = env.float("AA_BUNDLER_GAS_LIMIT_FACTOR", 1)
|
|
29
29
|
AA_BUNDLER_PRIORITY_GAS_PRICE_FACTOR = env.float("AA_BUNDLER_PRIORITY_GAS_PRICE_FACTOR", 1)
|
30
30
|
AA_BUNDLER_BASE_GAS_PRICE_FACTOR = env.float("AA_BUNDLER_BASE_GAS_PRICE_FACTOR", 1)
|
31
31
|
AA_BUNDLER_VERIFICATION_GAS_FACTOR = env.float("AA_BUNDLER_VERIFICATION_GAS_FACTOR", 1)
|
32
|
+
AA_BUNDLER_MAX_FEE_PER_GAS = env.int("AA_BUNDLER_MAX_FEE_PER_GAS", 200000000000) # 200 gwei
|
32
33
|
|
33
34
|
AA_BUNDLER_STATE_OVERRIDES = env.json("AA_BUNDLER_STATE_OVERRIDES", default={})
|
34
35
|
|
@@ -329,6 +330,7 @@ class Bundler:
|
|
329
330
|
gas_limit_factor: float = AA_BUNDLER_GAS_LIMIT_FACTOR,
|
330
331
|
priority_gas_price_factor: float = AA_BUNDLER_PRIORITY_GAS_PRICE_FACTOR,
|
331
332
|
base_gas_price_factor: float = AA_BUNDLER_BASE_GAS_PRICE_FACTOR,
|
333
|
+
max_fee_per_gas: int = AA_BUNDLER_MAX_FEE_PER_GAS,
|
332
334
|
executor_pk: HexBytes = AA_BUNDLER_EXECUTOR_PK,
|
333
335
|
overrides: StateOverride = AA_BUNDLER_STATE_OVERRIDES,
|
334
336
|
):
|
@@ -343,6 +345,7 @@ class Bundler:
|
|
343
345
|
self.priority_gas_price_factor = priority_gas_price_factor
|
344
346
|
self.base_gas_price_factor = base_gas_price_factor
|
345
347
|
self.executor_pk = executor_pk
|
348
|
+
self.max_fee_per_gas = max_fee_per_gas
|
346
349
|
|
347
350
|
# stateOverrideSet mapping to use when calling eth_estimateUserOperationGas
|
348
351
|
# https://docs.alchemy.com/reference/eth-estimateuseroperationgas
|
@@ -353,7 +356,7 @@ class Bundler:
|
|
353
356
|
f"Bundler(type={self.bundler_type}, entrypoint={self.entrypoint}, nonce_mode={self.nonce_mode}, "
|
354
357
|
f"fixed_nonce_key={self.fixed_nonce_key}, verification_gas_factor={self.verification_gas_factor}, "
|
355
358
|
f"gas_limit_factor={self.gas_limit_factor}, priority_gas_price_factor={self.priority_gas_price_factor}, "
|
356
|
-
f"base_gas_price_factor={self.base_gas_price_factor})"
|
359
|
+
f"base_gas_price_factor={self.base_gas_price_factor}, max_fee_per_gas={self.max_fee_per_gas})"
|
357
360
|
)
|
358
361
|
|
359
362
|
def get_nonce_and_key(self, tx: Tx, fetch=False):
|
@@ -406,10 +409,17 @@ class Bundler:
|
|
406
409
|
if "error" in resp:
|
407
410
|
raise BundlerRevertError(resp["error"]["message"], response=resp)
|
408
411
|
max_priority_fee_per_gas = int(int(resp["result"], 16) * self.priority_gas_price_factor)
|
409
|
-
max_fee_per_gas = max_priority_fee_per_gas + self.get_base_fee()
|
412
|
+
max_fee_per_gas = min(max_priority_fee_per_gas + self.get_base_fee(), self.max_fee_per_gas)
|
410
413
|
|
411
414
|
return GasPrice(max_priority_fee_per_gas=max_priority_fee_per_gas, max_fee_per_gas=max_fee_per_gas)
|
412
415
|
|
416
|
+
def generic_gas_price(self):
|
417
|
+
base_fee = self.get_base_fee()
|
418
|
+
priority_fee = self.w3.eth.max_priority_fee
|
419
|
+
max_priority_fee_per_gas = int(priority_fee * self.priority_gas_price_factor)
|
420
|
+
max_fee_per_gas = min(max_priority_fee_per_gas + base_fee, self.max_fee_per_gas)
|
421
|
+
return GasPrice(max_priority_fee_per_gas=max_priority_fee_per_gas, max_fee_per_gas=max_fee_per_gas)
|
422
|
+
|
413
423
|
def build_user_operation(self, tx: Tx, retry_nonce=None) -> UserOperation:
|
414
424
|
nonce_key, nonce = self.get_nonce_and_key(tx, fetch=retry_nonce is not None)
|
415
425
|
# Consume the nonce, even if the userop may fail later
|
@@ -422,16 +432,15 @@ class Bundler:
|
|
422
432
|
|
423
433
|
if self.bundler_type == "alchemy":
|
424
434
|
gas_price = self.alchemy_gas_price()
|
425
|
-
user_operation = user_operation.add_gas_price(gas_price)
|
426
435
|
|
427
436
|
elif self.bundler_type == "generic":
|
428
|
-
|
429
|
-
pass
|
437
|
+
gas_price = self.generic_gas_price()
|
430
438
|
|
431
439
|
else:
|
432
440
|
warn(f"Unknown bundler_type: {self.bundler_type}")
|
441
|
+
gas_price = GasPrice(0, 0)
|
433
442
|
|
434
|
-
return user_operation
|
443
|
+
return user_operation.add_gas_price(gas_price)
|
435
444
|
|
436
445
|
def send_transaction(self, tx: Tx, retry_nonce=None):
|
437
446
|
user_operation = self.build_user_operation(tx, retry_nonce).sign(
|
@@ -17,7 +17,7 @@ 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
21
|
AMOUNT_DECIMALS = env.int("AMOUNT_DECIMALS", 18)
|
22
22
|
AMOUNT_CLASSNAME = env.str("AMOUNT_CLASSNAME", None)
|
23
23
|
|
@@ -266,7 +266,9 @@ class BaseProvider(ABC):
|
|
266
266
|
def get_etherscan_url(self):
|
267
267
|
if ETHERSCAN_TOKEN is None:
|
268
268
|
return None
|
269
|
-
return ETHERSCAN_URL.format(
|
269
|
+
return ETHERSCAN_URL.format(
|
270
|
+
token=ETHERSCAN_TOKEN, domain=ETHERSCAN_DOMAIN, chainid=self.w3.eth.chain_id
|
271
|
+
)
|
270
272
|
|
271
273
|
def get_first_block(self, eth_wrapper):
|
272
274
|
etherscan_url = self.get_etherscan_url()
|
@@ -275,7 +277,7 @@ class BaseProvider(ABC):
|
|
275
277
|
address = self.get_contract_address(eth_wrapper)
|
276
278
|
url = (
|
277
279
|
etherscan_url
|
278
|
-
+ f"
|
280
|
+
+ f"module=account&action=txlist&address={address}&startblock=0&"
|
279
281
|
+ "endblock=99999999&page=1&offset=10&sort=asc"
|
280
282
|
)
|
281
283
|
resp = requests.get(url)
|
@@ -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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/CounterUpgradeable.sol
RENAMED
File without changes
|
File without changes
|
{eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/CounterWithLibrary.sol
RENAMED
File without changes
|
File without changes
|
{eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/EventLauncher.sol
RENAMED
File without changes
|
{eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/TestCurrency.sol
RENAMED
File without changes
|
{eth_prototype-1.3.2 → eth_prototype-1.3.4}/tests/hardhat-project/contracts/TestCurrencyUUPS.sol
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|