web3 7.10.0__py3-none-any.whl → 7.11.0__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.
- ens/exceptions.py +1 -1
- web3/_utils/batching.py +42 -1
- web3/_utils/encoding.py +8 -0
- web3/_utils/ens.py +9 -1
- web3/_utils/method_formatters.py +56 -7
- web3/_utils/module_testing/eth_module.py +153 -64
- web3/_utils/module_testing/module_testing_utils.py +0 -12
- web3/_utils/module_testing/persistent_connection_provider.py +3 -3
- web3/_utils/normalizers.py +1 -1
- web3/_utils/rpc_abi.py +5 -4
- web3/_utils/utility_methods.py +8 -6
- web3/providers/async_base.py +5 -6
- web3/providers/base.py +5 -5
- web3/providers/eth_tester/middleware.py +20 -0
- web3/providers/ipc.py +2 -0
- web3/providers/legacy_websocket.py +2 -0
- web3/providers/persistent/persistent.py +15 -10
- web3/providers/persistent/request_processor.py +10 -1
- web3/providers/rpc/async_rpc.py +2 -0
- web3/providers/rpc/rpc.py +2 -0
- web3/types.py +27 -0
- web3/utils/caching.py +8 -5
- {web3-7.10.0.dist-info → web3-7.11.0.dist-info}/METADATA +5 -5
- {web3-7.10.0.dist-info → web3-7.11.0.dist-info}/RECORD +27 -27
- {web3-7.10.0.dist-info → web3-7.11.0.dist-info}/WHEEL +1 -1
- {web3-7.10.0.dist-info → web3-7.11.0.dist-info}/licenses/LICENSE +0 -0
- {web3-7.10.0.dist-info → web3-7.11.0.dist-info}/top_level.txt +0 -0
|
@@ -57,7 +57,6 @@ from web3._utils.method_formatters import (
|
|
|
57
57
|
from web3._utils.module_testing.module_testing_utils import (
|
|
58
58
|
assert_contains_log,
|
|
59
59
|
async_mock_offchain_lookup_request_response,
|
|
60
|
-
flaky_geth_dev_mining,
|
|
61
60
|
mock_offchain_lookup_request_response,
|
|
62
61
|
)
|
|
63
62
|
from web3._utils.module_testing.utils import (
|
|
@@ -115,27 +114,6 @@ OFFCHAIN_LOOKUP_RETURN_DATA = "0000000000000000000000000000000000000000000000000
|
|
|
115
114
|
# "web3py" as an abi-encoded string
|
|
116
115
|
WEB3PY_AS_HEXBYTES = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000067765623370790000000000000000000000000000000000000000000000000000" # noqa: E501
|
|
117
116
|
|
|
118
|
-
RLP_ACCESS_LIST = [
|
|
119
|
-
(
|
|
120
|
-
"0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae",
|
|
121
|
-
(
|
|
122
|
-
"0x0000000000000000000000000000000000000000000000000000000000000003",
|
|
123
|
-
"0x0000000000000000000000000000000000000000000000000000000000000007",
|
|
124
|
-
),
|
|
125
|
-
),
|
|
126
|
-
("0xbb9bc244d798123fde783fcc1c72d3bb8c189413", ()),
|
|
127
|
-
]
|
|
128
|
-
|
|
129
|
-
RPC_ACCESS_LIST = [
|
|
130
|
-
{
|
|
131
|
-
"address": "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae",
|
|
132
|
-
"storageKeys": (
|
|
133
|
-
"0x0000000000000000000000000000000000000000000000000000000000000003",
|
|
134
|
-
"0x0000000000000000000000000000000000000000000000000000000000000007",
|
|
135
|
-
),
|
|
136
|
-
},
|
|
137
|
-
{"address": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", "storageKeys": ()},
|
|
138
|
-
]
|
|
139
117
|
|
|
140
118
|
if TYPE_CHECKING:
|
|
141
119
|
from _pytest.monkeypatch import MonkeyPatch # noqa: F401
|
|
@@ -454,9 +432,6 @@ class AsyncEthModuleTest:
|
|
|
454
432
|
assert result["tx"]["nonce"] == txn_params["nonce"]
|
|
455
433
|
|
|
456
434
|
@pytest.mark.asyncio
|
|
457
|
-
@pytest.mark.xfail(
|
|
458
|
-
reason="async name_to_address_middleware has not been implemented yet"
|
|
459
|
-
)
|
|
460
435
|
async def test_async_eth_sign_transaction_ens_names(
|
|
461
436
|
self, async_w3: "AsyncWeb3", async_keyfile_account_address: ChecksumAddress
|
|
462
437
|
) -> None:
|
|
@@ -638,9 +613,6 @@ class AsyncEthModuleTest:
|
|
|
638
613
|
assert txn["value"] == 1
|
|
639
614
|
assert txn["gas"] == 21000
|
|
640
615
|
|
|
641
|
-
block = await async_w3.eth.get_block("latest")
|
|
642
|
-
assert txn["maxFeePerGas"] == maxPriorityFeePerGas + 2 * block["baseFeePerGas"]
|
|
643
|
-
|
|
644
616
|
@pytest.mark.asyncio
|
|
645
617
|
async def test_eth_send_transaction_max_fee_less_than_tip(
|
|
646
618
|
self,
|
|
@@ -744,6 +716,86 @@ class AsyncEthModuleTest:
|
|
|
744
716
|
# clean up
|
|
745
717
|
async_w3.middleware_onion.remove("signing")
|
|
746
718
|
|
|
719
|
+
@pytest.mark.asyncio
|
|
720
|
+
async def test_async_sign_authorization_and_send_raw_set_code_transaction(
|
|
721
|
+
self,
|
|
722
|
+
async_w3: "AsyncWeb3",
|
|
723
|
+
keyfile_account_pkey: HexStr,
|
|
724
|
+
async_math_contract: "AsyncContract",
|
|
725
|
+
) -> None:
|
|
726
|
+
keyfile_account = async_w3.eth.account.from_key(keyfile_account_pkey)
|
|
727
|
+
|
|
728
|
+
chain_id = await async_w3.eth.chain_id
|
|
729
|
+
nonce = await async_w3.eth.get_transaction_count(keyfile_account.address)
|
|
730
|
+
|
|
731
|
+
auth = {
|
|
732
|
+
"chainId": chain_id,
|
|
733
|
+
"address": async_math_contract.address,
|
|
734
|
+
"nonce": nonce + 1,
|
|
735
|
+
}
|
|
736
|
+
signed_auth = keyfile_account.sign_authorization(auth)
|
|
737
|
+
|
|
738
|
+
# get current math counter and increase it only in the delegation by n
|
|
739
|
+
math_counter = await async_math_contract.functions.counter().call()
|
|
740
|
+
built_tx = await async_math_contract.functions.incrementCounter(
|
|
741
|
+
math_counter + 1337
|
|
742
|
+
).build_transaction({})
|
|
743
|
+
txn: TxParams = {
|
|
744
|
+
"chainId": chain_id,
|
|
745
|
+
"to": keyfile_account.address,
|
|
746
|
+
"value": Wei(0),
|
|
747
|
+
"gas": 200_000,
|
|
748
|
+
"nonce": nonce,
|
|
749
|
+
"maxPriorityFeePerGas": Wei(10**9),
|
|
750
|
+
"maxFeePerGas": Wei(10**9),
|
|
751
|
+
"data": built_tx["data"],
|
|
752
|
+
"authorizationList": [signed_auth],
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
signed = keyfile_account.sign_transaction(txn)
|
|
756
|
+
tx_hash = await async_w3.eth.send_raw_transaction(signed.raw_transaction)
|
|
757
|
+
get_tx = await async_w3.eth.get_transaction(tx_hash)
|
|
758
|
+
await async_w3.eth.wait_for_transaction_receipt(tx_hash, timeout=10)
|
|
759
|
+
|
|
760
|
+
code = await async_w3.eth.get_code(keyfile_account.address)
|
|
761
|
+
assert code.to_0x_hex() == f"0xef0100{async_math_contract.address[2:].lower()}"
|
|
762
|
+
delegated = async_w3.eth.contract(
|
|
763
|
+
address=keyfile_account.address, abi=async_math_contract.abi
|
|
764
|
+
)
|
|
765
|
+
# assert the math counter is increased by 1337 only in delegated acct
|
|
766
|
+
assert await async_math_contract.functions.counter().call() == math_counter
|
|
767
|
+
delegated_call = await delegated.functions.counter().call()
|
|
768
|
+
assert delegated_call == math_counter + 1337
|
|
769
|
+
|
|
770
|
+
assert len(get_tx["authorizationList"]) == 1
|
|
771
|
+
get_auth = get_tx["authorizationList"][0]
|
|
772
|
+
assert get_auth["chainId"] == chain_id
|
|
773
|
+
assert get_auth["address"] == async_math_contract.address
|
|
774
|
+
assert get_auth["nonce"] == nonce + 1
|
|
775
|
+
assert isinstance(get_auth["yParity"], int)
|
|
776
|
+
assert isinstance(get_auth["r"], HexBytes)
|
|
777
|
+
assert isinstance(get_auth["s"], HexBytes)
|
|
778
|
+
|
|
779
|
+
# reset code
|
|
780
|
+
reset_auth = {
|
|
781
|
+
"chainId": chain_id,
|
|
782
|
+
"address": "0x" + ("00" * 20),
|
|
783
|
+
"nonce": nonce + 3,
|
|
784
|
+
}
|
|
785
|
+
signed_reset_auth = keyfile_account.sign_authorization(reset_auth)
|
|
786
|
+
new_txn = dict(txn)
|
|
787
|
+
new_txn["authorizationList"] = [signed_reset_auth]
|
|
788
|
+
new_txn["nonce"] = nonce + 2
|
|
789
|
+
|
|
790
|
+
signed_reset = keyfile_account.sign_transaction(new_txn)
|
|
791
|
+
reset_tx_hash = await async_w3.eth.send_raw_transaction(
|
|
792
|
+
signed_reset.raw_transaction
|
|
793
|
+
)
|
|
794
|
+
await async_w3.eth.wait_for_transaction_receipt(reset_tx_hash, timeout=10)
|
|
795
|
+
|
|
796
|
+
reset_code = await async_w3.eth.get_code(keyfile_account.address)
|
|
797
|
+
assert reset_code == HexBytes("0x")
|
|
798
|
+
|
|
747
799
|
@pytest.mark.asyncio
|
|
748
800
|
async def test_GasPriceStrategyMiddleware(
|
|
749
801
|
self,
|
|
@@ -1763,7 +1815,6 @@ class AsyncEthModuleTest:
|
|
|
1763
1815
|
assert isinstance(effective_gas_price, int)
|
|
1764
1816
|
assert effective_gas_price > 0
|
|
1765
1817
|
|
|
1766
|
-
@flaky_geth_dev_mining
|
|
1767
1818
|
@pytest.mark.asyncio
|
|
1768
1819
|
async def test_async_eth_get_transaction_receipt_unmined(
|
|
1769
1820
|
self,
|
|
@@ -1829,7 +1880,6 @@ class AsyncEthModuleTest:
|
|
|
1829
1880
|
assert isinstance(effective_gas_price, int)
|
|
1830
1881
|
assert effective_gas_price > 0
|
|
1831
1882
|
|
|
1832
|
-
@flaky_geth_dev_mining
|
|
1833
1883
|
@pytest.mark.asyncio
|
|
1834
1884
|
async def test_async_eth_wait_for_transaction_receipt_unmined(
|
|
1835
1885
|
self,
|
|
@@ -2086,7 +2136,6 @@ class AsyncEthModuleTest:
|
|
|
2086
2136
|
assert bytes(slot_4[:4]) == b"four"
|
|
2087
2137
|
|
|
2088
2138
|
@pytest.mark.asyncio
|
|
2089
|
-
@pytest.mark.xfail
|
|
2090
2139
|
async def test_async_eth_get_storage_at_ens_name(
|
|
2091
2140
|
self, async_w3: "AsyncWeb3", async_storage_contract: "AsyncContract"
|
|
2092
2141
|
) -> None:
|
|
@@ -2238,9 +2287,6 @@ class AsyncEthModuleTest:
|
|
|
2238
2287
|
assert new_signature != signature
|
|
2239
2288
|
|
|
2240
2289
|
@pytest.mark.asyncio
|
|
2241
|
-
@pytest.mark.xfail(
|
|
2242
|
-
reason="Async middleware to convert ENS names to addresses is missing"
|
|
2243
|
-
)
|
|
2244
2290
|
async def test_async_eth_sign_ens_names(
|
|
2245
2291
|
self,
|
|
2246
2292
|
async_w3: "AsyncWeb3",
|
|
@@ -2255,7 +2301,6 @@ class AsyncEthModuleTest:
|
|
|
2255
2301
|
assert is_bytes(signature)
|
|
2256
2302
|
assert len(signature) == 32 + 32 + 1
|
|
2257
2303
|
|
|
2258
|
-
@flaky_geth_dev_mining
|
|
2259
2304
|
@pytest.mark.asyncio
|
|
2260
2305
|
async def test_async_eth_replace_transaction_legacy(
|
|
2261
2306
|
self,
|
|
@@ -2285,7 +2330,6 @@ class AsyncEthModuleTest:
|
|
|
2285
2330
|
assert replace_txn["gas"] == 21000
|
|
2286
2331
|
assert replace_txn["gasPrice"] == txn_params["gasPrice"]
|
|
2287
2332
|
|
|
2288
|
-
@flaky_geth_dev_mining
|
|
2289
2333
|
@pytest.mark.asyncio
|
|
2290
2334
|
async def test_async_eth_replace_transaction(
|
|
2291
2335
|
self,
|
|
@@ -2322,7 +2366,6 @@ class AsyncEthModuleTest:
|
|
|
2322
2366
|
assert replace_txn["maxFeePerGas"] == three_gwei_in_wei
|
|
2323
2367
|
assert replace_txn["maxPriorityFeePerGas"] == two_gwei_in_wei
|
|
2324
2368
|
|
|
2325
|
-
@flaky_geth_dev_mining
|
|
2326
2369
|
@pytest.mark.asyncio
|
|
2327
2370
|
async def test_async_eth_replace_transaction_underpriced(
|
|
2328
2371
|
self,
|
|
@@ -2349,7 +2392,6 @@ class AsyncEthModuleTest:
|
|
|
2349
2392
|
with pytest.raises(Web3RPCError, match="replacement transaction underpriced"):
|
|
2350
2393
|
await async_w3.eth.replace_transaction(txn_hash, txn_params)
|
|
2351
2394
|
|
|
2352
|
-
@flaky_geth_dev_mining
|
|
2353
2395
|
@pytest.mark.asyncio
|
|
2354
2396
|
async def test_async_eth_replace_transaction_non_existing_transaction(
|
|
2355
2397
|
self,
|
|
@@ -2372,7 +2414,6 @@ class AsyncEthModuleTest:
|
|
|
2372
2414
|
txn_params,
|
|
2373
2415
|
)
|
|
2374
2416
|
|
|
2375
|
-
@flaky_geth_dev_mining
|
|
2376
2417
|
@pytest.mark.asyncio
|
|
2377
2418
|
async def test_async_eth_replace_transaction_already_mined(
|
|
2378
2419
|
self,
|
|
@@ -2395,7 +2436,6 @@ class AsyncEthModuleTest:
|
|
|
2395
2436
|
with pytest.raises(Web3ValueError, match="Supplied transaction with hash"):
|
|
2396
2437
|
await async_w3.eth.replace_transaction(txn_hash, txn_params)
|
|
2397
2438
|
|
|
2398
|
-
@flaky_geth_dev_mining
|
|
2399
2439
|
@pytest.mark.asyncio
|
|
2400
2440
|
async def test_async_eth_replace_transaction_incorrect_nonce(
|
|
2401
2441
|
self, async_w3: "AsyncWeb3", async_keyfile_account_address: ChecksumAddress
|
|
@@ -2417,7 +2457,6 @@ class AsyncEthModuleTest:
|
|
|
2417
2457
|
with pytest.raises(Web3ValueError):
|
|
2418
2458
|
await async_w3.eth.replace_transaction(txn_hash, txn_params)
|
|
2419
2459
|
|
|
2420
|
-
@flaky_geth_dev_mining
|
|
2421
2460
|
@pytest.mark.asyncio
|
|
2422
2461
|
async def test_async_eth_replace_transaction_gas_price_too_low(
|
|
2423
2462
|
self,
|
|
@@ -2437,7 +2476,6 @@ class AsyncEthModuleTest:
|
|
|
2437
2476
|
with pytest.raises(Web3ValueError):
|
|
2438
2477
|
await async_w3.eth.replace_transaction(txn_hash, txn_params)
|
|
2439
2478
|
|
|
2440
|
-
@flaky_geth_dev_mining
|
|
2441
2479
|
@pytest.mark.asyncio
|
|
2442
2480
|
async def test_async_eth_replace_transaction_gas_price_defaulting_minimum(
|
|
2443
2481
|
self, async_w3: "AsyncWeb3", async_keyfile_account_address: ChecksumAddress
|
|
@@ -2461,7 +2499,6 @@ class AsyncEthModuleTest:
|
|
|
2461
2499
|
gas_price * 1.125
|
|
2462
2500
|
) # minimum gas price
|
|
2463
2501
|
|
|
2464
|
-
@flaky_geth_dev_mining
|
|
2465
2502
|
@pytest.mark.asyncio
|
|
2466
2503
|
async def test_async_eth_replace_transaction_gas_price_defaulting_strategy_higher(
|
|
2467
2504
|
self, async_w3: "AsyncWeb3", async_keyfile_account_address: ChecksumAddress
|
|
@@ -2490,7 +2527,6 @@ class AsyncEthModuleTest:
|
|
|
2490
2527
|
) # Strategy provides higher gas price
|
|
2491
2528
|
async_w3.eth.set_gas_price_strategy(None) # reset strategy
|
|
2492
2529
|
|
|
2493
|
-
@flaky_geth_dev_mining
|
|
2494
2530
|
@pytest.mark.asyncio
|
|
2495
2531
|
async def test_async_eth_replace_transaction_gas_price_defaulting_strategy_lower(
|
|
2496
2532
|
self, async_w3: "AsyncWeb3", async_keyfile_account_address: ChecksumAddress
|
|
@@ -3464,7 +3500,6 @@ class EthModuleTest:
|
|
|
3464
3500
|
assert txn["gasPrice"] == two_gwei_in_wei
|
|
3465
3501
|
w3.eth.set_gas_price_strategy(None) # reset strategy
|
|
3466
3502
|
|
|
3467
|
-
@flaky_geth_dev_mining
|
|
3468
3503
|
def test_eth_replace_transaction_legacy(
|
|
3469
3504
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
3470
3505
|
) -> None:
|
|
@@ -3493,7 +3528,6 @@ class EthModuleTest:
|
|
|
3493
3528
|
assert replace_txn["gas"] == 21000
|
|
3494
3529
|
assert replace_txn["gasPrice"] == txn_params["gasPrice"]
|
|
3495
3530
|
|
|
3496
|
-
@flaky_geth_dev_mining
|
|
3497
3531
|
def test_eth_replace_transaction(
|
|
3498
3532
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
3499
3533
|
) -> None:
|
|
@@ -3527,7 +3561,6 @@ class EthModuleTest:
|
|
|
3527
3561
|
assert replace_txn["maxFeePerGas"] == three_gwei_in_wei
|
|
3528
3562
|
assert replace_txn["maxPriorityFeePerGas"] == two_gwei_in_wei
|
|
3529
3563
|
|
|
3530
|
-
@flaky_geth_dev_mining
|
|
3531
3564
|
def test_eth_replace_transaction_underpriced(
|
|
3532
3565
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
3533
3566
|
) -> None:
|
|
@@ -3551,7 +3584,6 @@ class EthModuleTest:
|
|
|
3551
3584
|
with pytest.raises(Web3RPCError, match="replacement transaction underpriced"):
|
|
3552
3585
|
w3.eth.replace_transaction(txn_hash, txn_params)
|
|
3553
3586
|
|
|
3554
|
-
@flaky_geth_dev_mining
|
|
3555
3587
|
def test_eth_replace_transaction_non_existing_transaction(
|
|
3556
3588
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
3557
3589
|
) -> None:
|
|
@@ -3571,7 +3603,6 @@ class EthModuleTest:
|
|
|
3571
3603
|
txn_params,
|
|
3572
3604
|
)
|
|
3573
3605
|
|
|
3574
|
-
@flaky_geth_dev_mining
|
|
3575
3606
|
def test_eth_replace_transaction_already_mined(
|
|
3576
3607
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
3577
3608
|
) -> None:
|
|
@@ -3591,7 +3622,6 @@ class EthModuleTest:
|
|
|
3591
3622
|
with pytest.raises(Web3ValueError, match="Supplied transaction with hash"):
|
|
3592
3623
|
w3.eth.replace_transaction(txn_hash, txn_params)
|
|
3593
3624
|
|
|
3594
|
-
@flaky_geth_dev_mining
|
|
3595
3625
|
def test_eth_replace_transaction_incorrect_nonce(
|
|
3596
3626
|
self, w3: "Web3", keyfile_account_address: ChecksumAddress
|
|
3597
3627
|
) -> None:
|
|
@@ -3612,7 +3642,6 @@ class EthModuleTest:
|
|
|
3612
3642
|
with pytest.raises(Web3ValueError):
|
|
3613
3643
|
w3.eth.replace_transaction(txn_hash, txn_params)
|
|
3614
3644
|
|
|
3615
|
-
@flaky_geth_dev_mining
|
|
3616
3645
|
def test_eth_replace_transaction_gas_price_too_low(
|
|
3617
3646
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
3618
3647
|
) -> None:
|
|
@@ -3629,7 +3658,6 @@ class EthModuleTest:
|
|
|
3629
3658
|
with pytest.raises(Web3ValueError):
|
|
3630
3659
|
w3.eth.replace_transaction(txn_hash, txn_params)
|
|
3631
3660
|
|
|
3632
|
-
@flaky_geth_dev_mining
|
|
3633
3661
|
def test_eth_replace_transaction_gas_price_defaulting_minimum(
|
|
3634
3662
|
self, w3: "Web3", keyfile_account_address: ChecksumAddress
|
|
3635
3663
|
) -> None:
|
|
@@ -3652,7 +3680,6 @@ class EthModuleTest:
|
|
|
3652
3680
|
gas_price * 1.125
|
|
3653
3681
|
) # minimum gas price
|
|
3654
3682
|
|
|
3655
|
-
@flaky_geth_dev_mining
|
|
3656
3683
|
def test_eth_replace_transaction_gas_price_defaulting_strategy_higher(
|
|
3657
3684
|
self, w3: "Web3", keyfile_account_address: ChecksumAddress
|
|
3658
3685
|
) -> None:
|
|
@@ -3680,7 +3707,6 @@ class EthModuleTest:
|
|
|
3680
3707
|
) # Strategy provides higher gas price
|
|
3681
3708
|
w3.eth.set_gas_price_strategy(None) # reset strategy
|
|
3682
3709
|
|
|
3683
|
-
@flaky_geth_dev_mining
|
|
3684
3710
|
def test_eth_replace_transaction_gas_price_defaulting_strategy_lower(
|
|
3685
3711
|
self, w3: "Web3", keyfile_account_address: ChecksumAddress
|
|
3686
3712
|
) -> None:
|
|
@@ -3806,6 +3832,79 @@ class EthModuleTest:
|
|
|
3806
3832
|
# cleanup
|
|
3807
3833
|
w3.middleware_onion.remove("signing")
|
|
3808
3834
|
|
|
3835
|
+
def test_sign_authorization_and_send_raw_set_code_transaction(
|
|
3836
|
+
self, w3: "Web3", keyfile_account_pkey: HexStr, math_contract: "Contract"
|
|
3837
|
+
) -> None:
|
|
3838
|
+
keyfile_account = w3.eth.account.from_key(keyfile_account_pkey)
|
|
3839
|
+
|
|
3840
|
+
chain_id = w3.eth.chain_id
|
|
3841
|
+
nonce = w3.eth.get_transaction_count(keyfile_account.address)
|
|
3842
|
+
|
|
3843
|
+
auth = {
|
|
3844
|
+
"chainId": chain_id,
|
|
3845
|
+
"address": math_contract.address,
|
|
3846
|
+
"nonce": nonce + 1,
|
|
3847
|
+
}
|
|
3848
|
+
signed_auth = keyfile_account.sign_authorization(auth)
|
|
3849
|
+
|
|
3850
|
+
# get current math counter and increase it only in the delegation by n
|
|
3851
|
+
math_counter = math_contract.functions.counter().call()
|
|
3852
|
+
data = math_contract.functions.incrementCounter(
|
|
3853
|
+
math_counter + 1337
|
|
3854
|
+
).build_transaction({})["data"]
|
|
3855
|
+
txn: TxParams = {
|
|
3856
|
+
"chainId": chain_id,
|
|
3857
|
+
"to": keyfile_account.address,
|
|
3858
|
+
"value": Wei(0),
|
|
3859
|
+
"gas": 200_000,
|
|
3860
|
+
"nonce": nonce,
|
|
3861
|
+
"maxPriorityFeePerGas": Wei(10**9),
|
|
3862
|
+
"maxFeePerGas": Wei(10**9),
|
|
3863
|
+
"data": data,
|
|
3864
|
+
"authorizationList": [signed_auth],
|
|
3865
|
+
}
|
|
3866
|
+
|
|
3867
|
+
signed = keyfile_account.sign_transaction(txn)
|
|
3868
|
+
tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
|
|
3869
|
+
get_tx = w3.eth.get_transaction(tx_hash)
|
|
3870
|
+
w3.eth.wait_for_transaction_receipt(tx_hash, timeout=10)
|
|
3871
|
+
|
|
3872
|
+
code = w3.eth.get_code(keyfile_account.address)
|
|
3873
|
+
assert code.to_0x_hex() == f"0xef0100{math_contract.address[2:].lower()}"
|
|
3874
|
+
delegated = w3.eth.contract(
|
|
3875
|
+
address=keyfile_account.address, abi=math_contract.abi
|
|
3876
|
+
)
|
|
3877
|
+
# assert the math counter is increased by 1337 only in delegated acct
|
|
3878
|
+
assert math_contract.functions.counter().call() == math_counter
|
|
3879
|
+
assert delegated.functions.counter().call() == math_counter + 1337
|
|
3880
|
+
|
|
3881
|
+
assert len(get_tx["authorizationList"]) == 1
|
|
3882
|
+
get_auth = get_tx["authorizationList"][0]
|
|
3883
|
+
assert get_auth["chainId"] == chain_id
|
|
3884
|
+
assert get_auth["address"] == math_contract.address
|
|
3885
|
+
assert get_auth["nonce"] == nonce + 1
|
|
3886
|
+
assert isinstance(get_auth["yParity"], int)
|
|
3887
|
+
assert isinstance(get_auth["r"], HexBytes)
|
|
3888
|
+
assert isinstance(get_auth["s"], HexBytes)
|
|
3889
|
+
|
|
3890
|
+
# reset storage value and code
|
|
3891
|
+
reset_auth = {
|
|
3892
|
+
"chainId": chain_id,
|
|
3893
|
+
"address": "0x" + ("00" * 20),
|
|
3894
|
+
"nonce": nonce + 3,
|
|
3895
|
+
}
|
|
3896
|
+
signed_reset_auth = keyfile_account.sign_authorization(reset_auth)
|
|
3897
|
+
new_txn = dict(txn)
|
|
3898
|
+
new_txn["authorizationList"] = [signed_reset_auth]
|
|
3899
|
+
new_txn["nonce"] = nonce + 2
|
|
3900
|
+
|
|
3901
|
+
signed_reset = keyfile_account.sign_transaction(new_txn)
|
|
3902
|
+
reset_tx_hash = w3.eth.send_raw_transaction(signed_reset.raw_transaction)
|
|
3903
|
+
w3.eth.wait_for_transaction_receipt(reset_tx_hash, timeout=10)
|
|
3904
|
+
|
|
3905
|
+
reset_code = w3.eth.get_code(keyfile_account.address)
|
|
3906
|
+
assert reset_code == HexBytes("0x")
|
|
3907
|
+
|
|
3809
3908
|
def test_eth_call(self, w3: "Web3", math_contract: "Contract") -> None:
|
|
3810
3909
|
txn_params = math_contract._prepare_transaction(
|
|
3811
3910
|
abi_element_identifier="add",
|
|
@@ -4514,7 +4613,6 @@ class EthModuleTest:
|
|
|
4514
4613
|
assert isinstance(effective_gas_price, int)
|
|
4515
4614
|
assert effective_gas_price > 0
|
|
4516
4615
|
|
|
4517
|
-
@flaky_geth_dev_mining
|
|
4518
4616
|
def test_eth_get_transaction_receipt_unmined(
|
|
4519
4617
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
4520
4618
|
) -> None:
|
|
@@ -4572,7 +4670,6 @@ class EthModuleTest:
|
|
|
4572
4670
|
assert isinstance(effective_gas_price, int)
|
|
4573
4671
|
assert effective_gas_price > 0
|
|
4574
4672
|
|
|
4575
|
-
@flaky_geth_dev_mining
|
|
4576
4673
|
def test_eth_wait_for_transaction_receipt_unmined(
|
|
4577
4674
|
self, w3: "Web3", keyfile_account_address_dual_type: ChecksumAddress
|
|
4578
4675
|
) -> None:
|
|
@@ -4617,14 +4714,6 @@ class EthModuleTest:
|
|
|
4617
4714
|
assert log_entry["transactionIndex"] == 0
|
|
4618
4715
|
assert log_entry["transactionHash"] == HexBytes(txn_hash_with_log)
|
|
4619
4716
|
|
|
4620
|
-
def test_eth_getUncleByBlockHashAndIndex(self, w3: "Web3") -> None:
|
|
4621
|
-
# TODO: how do we make uncles....
|
|
4622
|
-
pass
|
|
4623
|
-
|
|
4624
|
-
def test_eth_getUncleByBlockNumberAndIndex(self, w3: "Web3") -> None:
|
|
4625
|
-
# TODO: how do we make uncles....
|
|
4626
|
-
pass
|
|
4627
|
-
|
|
4628
4717
|
def test_eth_new_filter(self, w3: "Web3") -> None:
|
|
4629
4718
|
filter = w3.eth.filter({})
|
|
4630
4719
|
|
|
@@ -21,9 +21,6 @@ from eth_typing import (
|
|
|
21
21
|
from eth_utils import (
|
|
22
22
|
is_same_address,
|
|
23
23
|
)
|
|
24
|
-
from flaky import (
|
|
25
|
-
flaky,
|
|
26
|
-
)
|
|
27
24
|
from hexbytes import (
|
|
28
25
|
HexBytes,
|
|
29
26
|
)
|
|
@@ -44,20 +41,11 @@ if TYPE_CHECKING:
|
|
|
44
41
|
)
|
|
45
42
|
from requests import Response # noqa: F401
|
|
46
43
|
|
|
47
|
-
from web3 import Web3 # noqa: F401
|
|
48
44
|
from web3._utils.compat import ( # noqa: F401
|
|
49
45
|
Self,
|
|
50
46
|
)
|
|
51
47
|
|
|
52
48
|
|
|
53
|
-
"""
|
|
54
|
-
flaky_geth_dev_mining decorator for tests requiring a pending block
|
|
55
|
-
for the duration of the test. This behavior can be flaky
|
|
56
|
-
due to timing of the test running as a block is mined.
|
|
57
|
-
"""
|
|
58
|
-
flaky_geth_dev_mining = flaky(max_runs=3, min_passes=1)
|
|
59
|
-
|
|
60
|
-
|
|
61
49
|
def assert_contains_log(
|
|
62
50
|
result: Sequence[LogReceipt],
|
|
63
51
|
block_with_txn_with_log: BlockData,
|
|
@@ -655,11 +655,11 @@ class PersistentConnectionProviderTest:
|
|
|
655
655
|
assert all(k in pending.keys() for k in SOME_BLOCK_KEYS)
|
|
656
656
|
|
|
657
657
|
assert isinstance(block_num, int)
|
|
658
|
-
assert latest["number"] == block_num
|
|
659
|
-
|
|
660
658
|
assert isinstance(chain_id, int)
|
|
661
659
|
assert isinstance(chain_id2, int)
|
|
662
660
|
assert isinstance(chain_id3, int)
|
|
661
|
+
# chain id is set in fixture file
|
|
662
|
+
assert chain_id == chain_id2 == chain_id3 == 131277322940537
|
|
663
663
|
|
|
664
664
|
@pytest.mark.asyncio
|
|
665
665
|
async def test_async_public_socket_api(self, async_w3: AsyncWeb3) -> None:
|
|
@@ -854,7 +854,7 @@ class PersistentConnectionProviderTest:
|
|
|
854
854
|
async_w3: AsyncWeb3,
|
|
855
855
|
) -> None:
|
|
856
856
|
async def unsubscribe_subs(
|
|
857
|
-
subs: List[Union[NewHeadsSubscription, LogsSubscription]]
|
|
857
|
+
subs: List[Union[NewHeadsSubscription, LogsSubscription]],
|
|
858
858
|
) -> None:
|
|
859
859
|
for sub in subs:
|
|
860
860
|
await sub.unsubscribe()
|
web3/_utils/normalizers.py
CHANGED
|
@@ -228,7 +228,7 @@ def abi_ens_resolver(
|
|
|
228
228
|
return type_str, validate_name_has_address(_ens, val)
|
|
229
229
|
except NameNotFound as e:
|
|
230
230
|
# TODO: This try/except is to keep backwards compatibility when we
|
|
231
|
-
# removed the mainnet requirement. Remove this in web3.py
|
|
231
|
+
# removed the mainnet requirement. Remove this in web3.py v8 and allow
|
|
232
232
|
# NameNotFound to raise.
|
|
233
233
|
if not isinstance(_ens, StaticENS):
|
|
234
234
|
raise InvalidAddress(f"{e}")
|
web3/_utils/rpc_abi.py
CHANGED
|
@@ -215,11 +215,12 @@ def apply_abi_formatters_to_dict(
|
|
|
215
215
|
fields = list(abi_dict.keys() & data.keys())
|
|
216
216
|
formatted_values = map_abi_data(
|
|
217
217
|
normalizers,
|
|
218
|
-
|
|
219
|
-
|
|
218
|
+
(abi_dict[field] for field in fields),
|
|
219
|
+
(data[field] for field in fields),
|
|
220
220
|
)
|
|
221
|
-
formatted_dict =
|
|
222
|
-
|
|
221
|
+
formatted_dict = data.copy()
|
|
222
|
+
formatted_dict.update(zip(fields, formatted_values))
|
|
223
|
+
return formatted_dict
|
|
223
224
|
|
|
224
225
|
|
|
225
226
|
@to_dict
|
web3/_utils/utility_methods.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import (
|
|
2
2
|
Any,
|
|
3
|
-
Dict,
|
|
4
3
|
Iterable,
|
|
4
|
+
Mapping,
|
|
5
5
|
Set,
|
|
6
6
|
Union,
|
|
7
7
|
)
|
|
@@ -13,7 +13,7 @@ from web3.types import (
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def all_in_dict(
|
|
16
|
-
values: Iterable[Any], d: Union[
|
|
16
|
+
values: Iterable[Any], d: Union[Mapping[Any, Any], TxData, TxParams]
|
|
17
17
|
) -> bool:
|
|
18
18
|
"""
|
|
19
19
|
Returns a bool based on whether ALL of the provided values exist
|
|
@@ -24,11 +24,12 @@ def all_in_dict(
|
|
|
24
24
|
:return: True if ALL values exist in keys;
|
|
25
25
|
False if NOT ALL values exist in keys
|
|
26
26
|
"""
|
|
27
|
-
|
|
27
|
+
d = dict(d)
|
|
28
|
+
return all(_ in d for _ in values)
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def any_in_dict(
|
|
31
|
-
values: Iterable[Any], d: Union[
|
|
32
|
+
values: Iterable[Any], d: Union[Mapping[Any, Any], TxData, TxParams]
|
|
32
33
|
) -> bool:
|
|
33
34
|
"""
|
|
34
35
|
Returns a bool based on whether ANY of the provided values exist
|
|
@@ -39,11 +40,12 @@ def any_in_dict(
|
|
|
39
40
|
:return: True if ANY value exists in keys;
|
|
40
41
|
False if NONE of the values exist in keys
|
|
41
42
|
"""
|
|
42
|
-
|
|
43
|
+
d = dict(d)
|
|
44
|
+
return any(_ in d for _ in values)
|
|
43
45
|
|
|
44
46
|
|
|
45
47
|
def none_in_dict(
|
|
46
|
-
values: Iterable[Any], d: Union[
|
|
48
|
+
values: Iterable[Any], d: Union[Mapping[Any, Any], TxData, TxParams]
|
|
47
49
|
) -> bool:
|
|
48
50
|
"""
|
|
49
51
|
Returns a bool based on whether NONE of the provided values exist
|
web3/providers/async_base.py
CHANGED
|
@@ -75,12 +75,6 @@ class AsyncBaseProvider:
|
|
|
75
75
|
Tuple[Middleware, ...], Callable[..., Coroutine[Any, Any, RPCResponse]]
|
|
76
76
|
] = (None, None)
|
|
77
77
|
|
|
78
|
-
_is_batching: bool = False
|
|
79
|
-
_batch_request_func_cache: Tuple[
|
|
80
|
-
Tuple[Middleware, ...],
|
|
81
|
-
Callable[..., Coroutine[Any, Any, Union[List[RPCResponse], RPCResponse]]],
|
|
82
|
-
] = (None, None)
|
|
83
|
-
|
|
84
78
|
is_async = True
|
|
85
79
|
has_persistent_connection = False
|
|
86
80
|
global_ccip_read_enabled: bool = True
|
|
@@ -100,6 +94,11 @@ class AsyncBaseProvider:
|
|
|
100
94
|
self.cache_allowed_requests = cache_allowed_requests
|
|
101
95
|
self.cacheable_requests = cacheable_requests or CACHEABLE_REQUESTS
|
|
102
96
|
self.request_cache_validation_threshold = request_cache_validation_threshold
|
|
97
|
+
self._is_batching: bool = False
|
|
98
|
+
self._batch_request_func_cache: Tuple[
|
|
99
|
+
Tuple[Middleware, ...],
|
|
100
|
+
Callable[..., Coroutine[Any, Any, Union[List[RPCResponse], RPCResponse]]],
|
|
101
|
+
] = (None, None)
|
|
103
102
|
|
|
104
103
|
async def request_func(
|
|
105
104
|
self, async_w3: "AsyncWeb3", middleware_onion: MiddlewareOnion
|
web3/providers/base.py
CHANGED
|
@@ -116,15 +116,15 @@ class BaseProvider:
|
|
|
116
116
|
class JSONBaseProvider(BaseProvider):
|
|
117
117
|
logger = logging.getLogger("web3.providers.base.JSONBaseProvider")
|
|
118
118
|
|
|
119
|
-
_is_batching: bool = False
|
|
120
|
-
_batch_request_func_cache: Tuple[
|
|
121
|
-
Tuple[Middleware, ...], Callable[..., Union[List[RPCResponse], RPCResponse]]
|
|
122
|
-
] = (None, None)
|
|
123
|
-
|
|
124
119
|
def __init__(self, **kwargs: Any) -> None:
|
|
125
120
|
super().__init__(**kwargs)
|
|
126
121
|
self.request_counter = itertools.count()
|
|
127
122
|
|
|
123
|
+
self._is_batching: bool = False
|
|
124
|
+
self._batch_request_func_cache: Tuple[
|
|
125
|
+
Tuple[Middleware, ...], Callable[..., Union[List[RPCResponse], RPCResponse]]
|
|
126
|
+
] = (None, None)
|
|
127
|
+
|
|
128
128
|
def encode_rpc_request(self, method: RPCEndpoint, params: Any) -> bytes:
|
|
129
129
|
rpc_dict = {
|
|
130
130
|
"jsonrpc": "2.0",
|
|
@@ -78,6 +78,7 @@ TRANSACTION_REQUEST_KEY_MAPPING = {
|
|
|
78
78
|
"maxFeePerGas": "max_fee_per_gas",
|
|
79
79
|
"maxPriorityFeePerGas": "max_priority_fee_per_gas",
|
|
80
80
|
"accessList": "access_list",
|
|
81
|
+
"authorizationList": "authorization_list",
|
|
81
82
|
"chainId": "chain_id",
|
|
82
83
|
}
|
|
83
84
|
transaction_request_remapper = apply_key_map(TRANSACTION_REQUEST_KEY_MAPPING)
|
|
@@ -94,6 +95,20 @@ TRANSACTION_REQUEST_FORMATTERS = {
|
|
|
94
95
|
"accessList": apply_list_to_array_formatter(
|
|
95
96
|
apply_key_map({"storageKeys": "storage_keys"})
|
|
96
97
|
),
|
|
98
|
+
"authorizationList": apply_list_to_array_formatter(
|
|
99
|
+
compose(
|
|
100
|
+
apply_formatters_to_dict(
|
|
101
|
+
{
|
|
102
|
+
"chain_id": to_integer_if_hex,
|
|
103
|
+
"nonce": to_integer_if_hex,
|
|
104
|
+
"y_parity": to_integer_if_hex,
|
|
105
|
+
"r": to_integer_if_hex,
|
|
106
|
+
"s": to_integer_if_hex,
|
|
107
|
+
},
|
|
108
|
+
),
|
|
109
|
+
apply_key_map({"chainId": "chain_id", "yParity": "y_parity"}),
|
|
110
|
+
)
|
|
111
|
+
),
|
|
97
112
|
}
|
|
98
113
|
transaction_request_formatter = apply_formatters_to_dict(TRANSACTION_REQUEST_FORMATTERS)
|
|
99
114
|
|
|
@@ -125,6 +140,7 @@ filter_request_transformer = compose(
|
|
|
125
140
|
|
|
126
141
|
TRANSACTION_RESULT_KEY_MAPPING = {
|
|
127
142
|
"access_list": "accessList",
|
|
143
|
+
"authorization_list": "authorizationList",
|
|
128
144
|
"blob_versioned_hashes": "blobVersionedHashes",
|
|
129
145
|
"block_hash": "blockHash",
|
|
130
146
|
"block_number": "blockNumber",
|
|
@@ -145,6 +161,9 @@ TRANSACTION_RESULT_FORMATTERS = {
|
|
|
145
161
|
"access_list": apply_list_to_array_formatter(
|
|
146
162
|
apply_key_map({"storage_keys": "storageKeys"}),
|
|
147
163
|
),
|
|
164
|
+
"authorization_list": apply_list_to_array_formatter(
|
|
165
|
+
apply_key_map({"chain_id": "chainId", "y_parity": "yParity"}),
|
|
166
|
+
),
|
|
148
167
|
}
|
|
149
168
|
transaction_result_formatter = apply_formatters_to_dict(TRANSACTION_RESULT_FORMATTERS)
|
|
150
169
|
|
|
@@ -195,6 +214,7 @@ BLOCK_RESULT_KEY_MAPPING = {
|
|
|
195
214
|
"parent_beacon_block_root": "parentBeaconBlockRoot",
|
|
196
215
|
"blob_gas_used": "blobGasUsed",
|
|
197
216
|
"excess_blob_gas": "excessBlobGas",
|
|
217
|
+
"requests_hash": "requestsHash",
|
|
198
218
|
}
|
|
199
219
|
block_result_remapper = apply_key_map(BLOCK_RESULT_KEY_MAPPING)
|
|
200
220
|
|
web3/providers/ipc.py
CHANGED
|
@@ -30,6 +30,7 @@ from web3.types import (
|
|
|
30
30
|
)
|
|
31
31
|
|
|
32
32
|
from .._utils.batching import (
|
|
33
|
+
batching_context,
|
|
33
34
|
sort_batch_response_by_response_ids,
|
|
34
35
|
)
|
|
35
36
|
from .._utils.caching import (
|
|
@@ -201,6 +202,7 @@ class IPCProvider(JSONBaseProvider):
|
|
|
201
202
|
request = self.encode_rpc_request(method, params)
|
|
202
203
|
return self._make_request(request)
|
|
203
204
|
|
|
205
|
+
@batching_context
|
|
204
206
|
def make_batch_request(
|
|
205
207
|
self, requests: List[Tuple[RPCEndpoint, Any]]
|
|
206
208
|
) -> List[RPCResponse]:
|