eth-prototype 1.4.1__py3-none-any.whl → 1.5.0b2__py3-none-any.whl
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.4.1.dist-info → eth_prototype-1.5.0b2.dist-info}/METADATA +1 -1
- {eth_prototype-1.4.1.dist-info → eth_prototype-1.5.0b2.dist-info}/RECORD +7 -7
- {eth_prototype-1.4.1.dist-info → eth_prototype-1.5.0b2.dist-info}/WHEEL +1 -1
- ethproto/aa_bundler.py +137 -18
- {eth_prototype-1.4.1.dist-info → eth_prototype-1.5.0b2.dist-info}/licenses/AUTHORS.rst +0 -0
- {eth_prototype-1.4.1.dist-info → eth_prototype-1.5.0b2.dist-info}/licenses/LICENSE.txt +0 -0
- {eth_prototype-1.4.1.dist-info → eth_prototype-1.5.0b2.dist-info}/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
eth_prototype-1.
|
|
2
|
-
eth_prototype-1.
|
|
1
|
+
eth_prototype-1.5.0b2.dist-info/licenses/AUTHORS.rst,sha256=Ui-05yYXtDZxna6o1yNcfdm8Jt68UIDQ01osiLxlYlU,95
|
|
2
|
+
eth_prototype-1.5.0b2.dist-info/licenses/LICENSE.txt,sha256=U_Q6_nDYDwZPIuhttHi37hXZ2qU2-HlV2geo9hzHXFw,1087
|
|
3
3
|
ethproto/__init__.py,sha256=YWkAFysBp4tZjLWWB2FFmp5yG23pUYhQvgQW9b3soXs,579
|
|
4
|
-
ethproto/aa_bundler.py,sha256=
|
|
4
|
+
ethproto/aa_bundler.py,sha256=mzEB0s5DX58wKsi9xb8dB9En9nK3D3ExrI3OOsqJb7M,22521
|
|
5
5
|
ethproto/build_artifacts.py,sha256=3t-MTSFZU1pQtDwf65zNJkceWleLRlzcEo8CFpu4_6s,10031
|
|
6
6
|
ethproto/contracts.py,sha256=R9lWKPe77jkPBXx798qhnVPWSFF2nhz4AaYowipNIBc,22625
|
|
7
7
|
ethproto/defender_relay.py,sha256=05A8TfRZwiBhCpo924Pf9CjfKSir2Wvgg1p_asFxJbw,1777
|
|
@@ -12,7 +12,7 @@ ethproto/test_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
|
|
|
12
12
|
ethproto/test_utils/factories.py,sha256=G8DnUDG_yThRxMTCkymzcjm9lR_ni0_ZmTsb3sEfIdI,1805
|
|
13
13
|
ethproto/test_utils/hardhat.py,sha256=HzTqIznu6zVd_-doL96ftFJ235ktDCQen1QDQbNuwfM,2361
|
|
14
14
|
ethproto/test_utils/vcr_utils.py,sha256=1FH2sgJlElSjWkJLuO3C7E2J-4HKyFvjAqkCnGRZJyk,797
|
|
15
|
-
eth_prototype-1.
|
|
16
|
-
eth_prototype-1.
|
|
17
|
-
eth_prototype-1.
|
|
18
|
-
eth_prototype-1.
|
|
15
|
+
eth_prototype-1.5.0b2.dist-info/METADATA,sha256=AYseONs04OnkUFgVa4t_z0669tv-uS5Nrc-dbeAxZkg,2697
|
|
16
|
+
eth_prototype-1.5.0b2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
17
|
+
eth_prototype-1.5.0b2.dist-info/top_level.txt,sha256=Dl0X7m6N1hxeo4JpGpSNqWC2gtsN0731g-DL1J0mpjc,9
|
|
18
|
+
eth_prototype-1.5.0b2.dist-info/RECORD,,
|
ethproto/aa_bundler.py
CHANGED
|
@@ -7,11 +7,13 @@ from warnings import warn
|
|
|
7
7
|
|
|
8
8
|
from environs import Env
|
|
9
9
|
from eth_abi import encode
|
|
10
|
+
from eth_abi.packed import encode_packed
|
|
10
11
|
from eth_account import Account
|
|
11
12
|
from eth_account.messages import encode_defunct
|
|
12
13
|
from eth_typing import HexAddress
|
|
13
14
|
from eth_utils import add_0x_prefix, function_signature_to_4byte_selector
|
|
14
15
|
from hexbytes import HexBytes
|
|
16
|
+
from requests import HTTPError
|
|
15
17
|
from web3 import Web3
|
|
16
18
|
from web3.constants import ADDRESS_ZERO
|
|
17
19
|
from web3.types import StateOverride, TxParams
|
|
@@ -24,7 +26,7 @@ AA_BUNDLER_URL = env.str("AA_BUNDLER_URL", env.str("WEB3_PROVIDER_URI", "http://
|
|
|
24
26
|
AA_BUNDLER_SENDER = env.str("AA_BUNDLER_SENDER", None)
|
|
25
27
|
AA_BUNDLER_ENTRYPOINT = env.str("AA_BUNDLER_ENTRYPOINT", "0x0000000071727De22E5E9d8BAf0edAc6f37da032")
|
|
26
28
|
AA_BUNDLER_EXECUTOR_PK = env.str("AA_BUNDLER_EXECUTOR_PK", None)
|
|
27
|
-
AA_BUNDLER_PROVIDER = env.str("AA_BUNDLER_PROVIDER", "
|
|
29
|
+
AA_BUNDLER_PROVIDER = env.str("AA_BUNDLER_PROVIDER", "generic")
|
|
28
30
|
AA_BUNDLER_GAS_LIMIT_FACTOR = env.float("AA_BUNDLER_GAS_LIMIT_FACTOR", 1)
|
|
29
31
|
AA_BUNDLER_PRIORITY_GAS_PRICE_FACTOR = env.float("AA_BUNDLER_PRIORITY_GAS_PRICE_FACTOR", 1)
|
|
30
32
|
AA_BUNDLER_BASE_GAS_PRICE_FACTOR = env.float("AA_BUNDLER_BASE_GAS_PRICE_FACTOR", 1)
|
|
@@ -47,7 +49,7 @@ NonceMode = Enum(
|
|
|
47
49
|
AA_BUNDLER_NONCE_MODE = env.enum("AA_BUNDLER_NONCE_MODE", default="FIXED_KEY_LOCAL_NONCE", enum=NonceMode)
|
|
48
50
|
AA_BUNDLER_NONCE_KEY = env.int("AA_BUNDLER_NONCE_KEY", 0)
|
|
49
51
|
AA_BUNDLER_MAX_GETNONCE_RETRIES = env.int("AA_BUNDLER_MAX_GETNONCE_RETRIES", 3)
|
|
50
|
-
|
|
52
|
+
AA_BUNDLER_ALCHEMY_GAS_POLICY_ID = env.str("AA_BUNDLER_ALCHEMY_GAS_POLICY_ID", None)
|
|
51
53
|
|
|
52
54
|
GET_NONCE_ABI = [
|
|
53
55
|
{
|
|
@@ -81,6 +83,10 @@ class BundlerRevertError(RevertError):
|
|
|
81
83
|
self.response = response
|
|
82
84
|
|
|
83
85
|
|
|
86
|
+
class BundlerError(Exception):
|
|
87
|
+
pass
|
|
88
|
+
|
|
89
|
+
|
|
84
90
|
@dataclass(frozen=True)
|
|
85
91
|
class UserOpEstimation:
|
|
86
92
|
"""eth_estimateUserOperationGas response"""
|
|
@@ -97,6 +103,21 @@ class GasPrice:
|
|
|
97
103
|
max_fee_per_gas: int
|
|
98
104
|
|
|
99
105
|
|
|
106
|
+
@dataclass(frozen=True)
|
|
107
|
+
class PaymasterAndData:
|
|
108
|
+
paymaster: HexAddress
|
|
109
|
+
paymaster_data: HexBytes
|
|
110
|
+
paymaster_verification_gas_limit: int
|
|
111
|
+
paymaster_post_op_gas_limit: int
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@dataclass(frozen=True)
|
|
115
|
+
class AlchemyGasAndPaymasterAndData:
|
|
116
|
+
estimation: UserOpEstimation
|
|
117
|
+
gas_price: GasPrice
|
|
118
|
+
paymaster_and_data: PaymasterAndData
|
|
119
|
+
|
|
120
|
+
|
|
100
121
|
@dataclass(frozen=True)
|
|
101
122
|
class Tx:
|
|
102
123
|
target: HexAddress
|
|
@@ -141,7 +162,11 @@ class UserOperation:
|
|
|
141
162
|
signature: HexBytes = DUMMY_SIGNATURE
|
|
142
163
|
|
|
143
164
|
init_code: HexBytes = HexBytes("0x")
|
|
144
|
-
|
|
165
|
+
|
|
166
|
+
paymaster: HexAddress = None
|
|
167
|
+
paymaster_data: HexBytes = HexBytes("0x")
|
|
168
|
+
paymaster_verification_gas_limit: int = 0
|
|
169
|
+
paymaster_post_op_gas_limit: int = 0
|
|
145
170
|
|
|
146
171
|
@classmethod
|
|
147
172
|
def from_tx(cls, tx: Tx, nonce):
|
|
@@ -172,6 +197,10 @@ class UserOperation:
|
|
|
172
197
|
"maxPriorityFeePerGas": "0x%x" % self.max_priority_fee_per_gas,
|
|
173
198
|
"maxFeePerGas": "0x%x" % self.max_fee_per_gas,
|
|
174
199
|
"signature": add_0x_prefix(self.signature.hex()),
|
|
200
|
+
"paymaster": self.paymaster,
|
|
201
|
+
"paymasterData": self.paymaster_data,
|
|
202
|
+
"paymasterVerificationGasLimit": "0x%x" % self.paymaster_verification_gas_limit,
|
|
203
|
+
"paymasterPostOpGasLimit": "0x%x" % self.paymaster_post_op_gas_limit,
|
|
175
204
|
}
|
|
176
205
|
|
|
177
206
|
def add_estimation(self, estimation: UserOpEstimation) -> "UserOperation":
|
|
@@ -189,6 +218,15 @@ class UserOperation:
|
|
|
189
218
|
max_fee_per_gas=gas_price.max_fee_per_gas,
|
|
190
219
|
)
|
|
191
220
|
|
|
221
|
+
def add_paymaster_and_data(self, paymaster_and_data: PaymasterAndData) -> "UserOperation":
|
|
222
|
+
return replace(
|
|
223
|
+
self,
|
|
224
|
+
paymaster=paymaster_and_data.paymaster,
|
|
225
|
+
paymaster_data=paymaster_and_data.paymaster_data,
|
|
226
|
+
paymaster_verification_gas_limit=paymaster_and_data.paymaster_verification_gas_limit,
|
|
227
|
+
paymaster_post_op_gas_limit=paymaster_and_data.paymaster_post_op_gas_limit,
|
|
228
|
+
)
|
|
229
|
+
|
|
192
230
|
def sign(self, private_key: HexBytes, chain_id, entrypoint) -> "UserOperation":
|
|
193
231
|
signature = Account.sign_message(
|
|
194
232
|
encode_defunct(
|
|
@@ -225,7 +263,21 @@ class PackedUserOperation:
|
|
|
225
263
|
pre_verification_gas=user_operation.pre_verification_gas,
|
|
226
264
|
gas_fees=pack_two(user_operation.max_priority_fee_per_gas, user_operation.max_fee_per_gas),
|
|
227
265
|
init_code=user_operation.init_code,
|
|
228
|
-
paymaster_and_data=
|
|
266
|
+
paymaster_and_data=(
|
|
267
|
+
HexBytes(
|
|
268
|
+
encode_packed(
|
|
269
|
+
["address", "uint128", "uint128", "bytes"],
|
|
270
|
+
[
|
|
271
|
+
user_operation.paymaster,
|
|
272
|
+
user_operation.paymaster_verification_gas_limit,
|
|
273
|
+
user_operation.paymaster_post_op_gas_limit,
|
|
274
|
+
user_operation.paymaster_data,
|
|
275
|
+
],
|
|
276
|
+
)
|
|
277
|
+
)
|
|
278
|
+
if user_operation.paymaster is not None
|
|
279
|
+
else HexBytes("0x")
|
|
280
|
+
).to_0x_hex(),
|
|
229
281
|
signature=user_operation.signature,
|
|
230
282
|
)
|
|
231
283
|
|
|
@@ -333,6 +385,7 @@ class Bundler:
|
|
|
333
385
|
max_fee_per_gas: int = AA_BUNDLER_MAX_FEE_PER_GAS,
|
|
334
386
|
executor_pk: HexBytes = AA_BUNDLER_EXECUTOR_PK,
|
|
335
387
|
overrides: StateOverride = AA_BUNDLER_STATE_OVERRIDES,
|
|
388
|
+
alchemy_gas_policy_id: str = AA_BUNDLER_ALCHEMY_GAS_POLICY_ID,
|
|
336
389
|
):
|
|
337
390
|
self.w3 = w3
|
|
338
391
|
self.bundler = Web3(Web3.HTTPProvider(bundler_url), middleware=[])
|
|
@@ -351,6 +404,10 @@ class Bundler:
|
|
|
351
404
|
# https://docs.alchemy.com/reference/eth-estimateuseroperationgas
|
|
352
405
|
self.overrides = overrides
|
|
353
406
|
|
|
407
|
+
if alchemy_gas_policy_id is None and bundler_type == "alchemy":
|
|
408
|
+
raise BundlerError("Must provide alchemy_gas_policy_id when using alchemy bundler_type")
|
|
409
|
+
self.alchemy_gas_policy_id = alchemy_gas_policy_id
|
|
410
|
+
|
|
354
411
|
def __str__(self):
|
|
355
412
|
return (
|
|
356
413
|
f"Bundler(type={self.bundler_type}, entrypoint={self.entrypoint}, nonce_mode={self.nonce_mode}, "
|
|
@@ -404,14 +461,68 @@ class Bundler:
|
|
|
404
461
|
),
|
|
405
462
|
)
|
|
406
463
|
|
|
407
|
-
def
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
464
|
+
def alchemy_estimation(self, user_operation: UserOperation) -> AlchemyGasAndPaymasterAndData:
|
|
465
|
+
try:
|
|
466
|
+
resp = self.bundler.provider.make_request(
|
|
467
|
+
"alchemy_requestGasAndPaymasterAndData",
|
|
468
|
+
[
|
|
469
|
+
{
|
|
470
|
+
"policyId": self.alchemy_gas_policy_id,
|
|
471
|
+
"entryPoint": self.entrypoint,
|
|
472
|
+
"dummySignature": DUMMY_SIGNATURE,
|
|
473
|
+
"userOperation": user_operation.as_reduced_dict(),
|
|
474
|
+
"overrides": {
|
|
475
|
+
"maxFeePerGas": {"multiplier": self.base_gas_price_factor},
|
|
476
|
+
"maxPriorityFeePerGas": {"multiplier": self.priority_gas_price_factor},
|
|
477
|
+
"callGasLimit": {"multiplier": self.gas_limit_factor},
|
|
478
|
+
"verificationGasLimit": {"multiplier": self.verification_gas_factor},
|
|
479
|
+
},
|
|
480
|
+
}
|
|
481
|
+
],
|
|
482
|
+
)
|
|
483
|
+
except HTTPError as e:
|
|
484
|
+
raise BundlerRevertError(
|
|
485
|
+
f"HTTP error while requesting gas and paymaster data: {str(e)}",
|
|
486
|
+
userop=user_operation,
|
|
487
|
+
response=e.response,
|
|
488
|
+
) from e
|
|
413
489
|
|
|
414
|
-
|
|
490
|
+
if "error" in resp:
|
|
491
|
+
raise BundlerRevertError(resp["error"]["message"], userop=user_operation, response=resp)
|
|
492
|
+
|
|
493
|
+
# {
|
|
494
|
+
# "callGasLimit": "0x3dab",
|
|
495
|
+
# "paymasterVerificationGasLimit": "0x9afa",
|
|
496
|
+
# "paymasterPostOpGasLimit": "0x0",
|
|
497
|
+
# "verificationGasLimit": "0xac33",
|
|
498
|
+
# "maxPriorityFeePerGas": "0x7aef40a00",
|
|
499
|
+
# "paymaster": "0x2cc0c7981D846b9F2a16276556f6e8cb52BfB633",
|
|
500
|
+
# "maxFeePerGas": "0xaf9fe62e48",
|
|
501
|
+
# "paymasterData": "0xabcd...",
|
|
502
|
+
# "preVerificationGas": "0xb8ec"
|
|
503
|
+
# }
|
|
504
|
+
|
|
505
|
+
estimation = UserOpEstimation(
|
|
506
|
+
pre_verification_gas=int(resp["result"]["preVerificationGas"], 16),
|
|
507
|
+
verification_gas_limit=int(resp["result"]["verificationGasLimit"], 16),
|
|
508
|
+
call_gas_limit=int(resp["result"]["callGasLimit"], 16),
|
|
509
|
+
paymaster_verification_gas_limit=int(resp["result"]["paymasterVerificationGasLimit"], 16),
|
|
510
|
+
)
|
|
511
|
+
gas_price = GasPrice(
|
|
512
|
+
max_priority_fee_per_gas=int(resp["result"]["maxPriorityFeePerGas"], 16),
|
|
513
|
+
max_fee_per_gas=int(resp["result"]["maxFeePerGas"], 16),
|
|
514
|
+
)
|
|
515
|
+
paymaster_and_data = PaymasterAndData(
|
|
516
|
+
paymaster=resp["result"]["paymaster"],
|
|
517
|
+
paymaster_data=HexBytes(resp["result"]["paymasterData"]),
|
|
518
|
+
paymaster_verification_gas_limit=int(resp["result"]["paymasterVerificationGasLimit"], 16),
|
|
519
|
+
paymaster_post_op_gas_limit=int(resp["result"]["paymasterPostOpGasLimit"], 16),
|
|
520
|
+
)
|
|
521
|
+
return AlchemyGasAndPaymasterAndData(
|
|
522
|
+
estimation=estimation,
|
|
523
|
+
gas_price=gas_price,
|
|
524
|
+
paymaster_and_data=paymaster_and_data,
|
|
525
|
+
)
|
|
415
526
|
|
|
416
527
|
def generic_gas_price(self):
|
|
417
528
|
base_fee = self.get_base_fee()
|
|
@@ -426,21 +537,29 @@ class Bundler:
|
|
|
426
537
|
consume_nonce(nonce_key, nonce)
|
|
427
538
|
|
|
428
539
|
user_operation = UserOperation.from_tx(tx, make_nonce(nonce_key, nonce))
|
|
429
|
-
estimation = self.estimate_user_operation_gas(user_operation)
|
|
430
|
-
|
|
431
|
-
user_operation = user_operation.add_estimation(estimation)
|
|
432
540
|
|
|
433
541
|
if self.bundler_type == "alchemy":
|
|
434
|
-
|
|
542
|
+
estimation_and_paymaster = self.alchemy_estimation(user_operation)
|
|
543
|
+
|
|
544
|
+
user_operation = user_operation.add_estimation(estimation_and_paymaster.estimation)
|
|
545
|
+
user_operation = user_operation.add_gas_price(estimation_and_paymaster.gas_price)
|
|
546
|
+
user_operation = user_operation.add_paymaster_and_data(
|
|
547
|
+
estimation_and_paymaster.paymaster_and_data
|
|
548
|
+
)
|
|
435
549
|
|
|
436
550
|
elif self.bundler_type == "generic":
|
|
551
|
+
estimation = self.estimate_user_operation_gas(user_operation)
|
|
552
|
+
|
|
553
|
+
user_operation = user_operation.add_estimation(estimation)
|
|
554
|
+
|
|
437
555
|
gas_price = self.generic_gas_price()
|
|
438
556
|
|
|
557
|
+
user_operation = user_operation.add_gas_price(gas_price)
|
|
558
|
+
|
|
439
559
|
else:
|
|
440
|
-
|
|
441
|
-
gas_price = GasPrice(0, 0)
|
|
560
|
+
raise BundlerError(f"Unknown bundler_type: {self.bundler_type}")
|
|
442
561
|
|
|
443
|
-
return user_operation
|
|
562
|
+
return user_operation
|
|
444
563
|
|
|
445
564
|
def send_transaction(self, tx: Tx, retry_nonce=None):
|
|
446
565
|
user_operation = self.build_user_operation(tx, retry_nonce).sign(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|