Skip to content

Commit 3b3f51c

Browse files
committed
Async HTTP Provider
1 parent cfd97bd commit 3b3f51c

File tree

12 files changed

+218
-6
lines changed

12 files changed

+218
-6
lines changed

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
url='https://github.com/ethereum/web3.py',
7373
include_package_data=True,
7474
install_requires=[
75+
"aiohttp>=3.7.4.post0,<4",
7576
"eth-abi>=2.0.0b6,<3.0.0",
7677
"eth-account>=0.5.3,<0.6.0",
7778
"eth-hash[pycryptodome]>=0.2.0,<1.0.0",

tests/integration/go_ethereum/common.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55

66
from web3._utils.module_testing import ( # noqa: F401
7+
AsyncEthModuleTest,
78
EthModuleTest,
89
GoEthereumAdminModuleTest,
910
GoEthereumPersonalModuleTest,
@@ -80,3 +81,7 @@ class GoEthereumAdminModuleTest(GoEthereumAdminModuleTest):
8081

8182
class GoEthereumPersonalModuleTest(GoEthereumPersonalModuleTest):
8283
pass
84+
85+
86+
class GoEthereumAsyncEthModuleTest(AsyncEthModuleTest):
87+
pass

tests/integration/go_ethereum/test_goethereum_http.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,24 @@
44
get_open_port,
55
)
66
from web3 import Web3
7+
from web3.eth import (
8+
AsyncEth,
9+
)
10+
from web3.providers.rpc import (
11+
AsyncHTTPProvider,
12+
)
713

814
from .common import (
915
GoEthereumAdminModuleTest,
16+
GoEthereumAsyncEthModuleTest,
1017
GoEthereumEthModuleTest,
1118
GoEthereumNetModuleTest,
1219
GoEthereumPersonalModuleTest,
1320
GoEthereumTest,
1421
GoEthereumVersionModuleTest,
1522
)
1623
from .utils import (
24+
wait_for_aiohttp,
1725
wait_for_http,
1826
)
1927

@@ -63,6 +71,18 @@ def web3(geth_process, endpoint_uri):
6371
return _web3
6472

6573

74+
@pytest.fixture(scope="module")
75+
async def async_w3_http(geth_process, endpoint_uri):
76+
await wait_for_aiohttp(endpoint_uri)
77+
_web3 = Web3(
78+
AsyncHTTPProvider(endpoint_uri),
79+
middlewares=[],
80+
modules={
81+
'async_eth': (AsyncEth,),
82+
})
83+
return _web3
84+
85+
6686
class TestGoEthereumTest(GoEthereumTest):
6787
pass
6888

@@ -97,3 +117,7 @@ class TestGoEthereumNetModuleTest(GoEthereumNetModuleTest):
97117

98118
class TestGoEthereumPersonalModuleTest(GoEthereumPersonalModuleTest):
99119
pass
120+
121+
122+
class TestGoEthereumAsyncEthModuleTest(GoEthereumAsyncEthModuleTest):
123+
pass

tests/integration/go_ethereum/utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import socket
33
import time
44

5+
import aiohttp
56
import requests
67

78

@@ -29,6 +30,18 @@ def wait_for_http(endpoint_uri, timeout=60):
2930
break
3031

3132

33+
async def wait_for_aiohttp(endpoint_uri, timeout=60):
34+
start = time.time()
35+
while time.time() < start + timeout:
36+
try:
37+
async with aiohttp.ClientSession() as session:
38+
await session.get(endpoint_uri)
39+
except aiohttp.client_exceptions.ClientConnectorError:
40+
time.sleep(0.01)
41+
else:
42+
break
43+
44+
3245
def wait_for_popen(proc, timeout):
3346
start = time.time()
3447
while time.time() < start + timeout:

web3/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
)
1818
from web3.providers.rpc import ( # noqa: E402
1919
HTTPProvider,
20+
AsyncHTTPProvider,
2021
)
2122
from web3.providers.websocket import ( # noqa: E402
2223
WebsocketProvider,
@@ -45,4 +46,5 @@
4546
"TestRPCProvider",
4647
"EthereumTesterProvider",
4748
"Account",
49+
"AsyncHTTPProvider",
4850
]

web3/_utils/module_testing/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .eth_module import ( # noqa: F401
2+
AsyncEthModuleTest,
23
EthModuleTest,
34
)
45
from .go_ethereum_admin_module import ( # noqa: F401

web3/_utils/module_testing/eth_module.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,17 @@
5858
from web3.contract import Contract # noqa: F401
5959

6060

61+
class AsyncEthModuleTest:
62+
@pytest.mark.asyncio
63+
async def test_eth_gas_price(self, async_w3_http: "Web3") -> None:
64+
gas_price = await async_w3_http.async_eth.gas_price
65+
assert gas_price > 0
66+
67+
@pytest.mark.asyncio
68+
async def test_isConnected(self, async_w3_http: "Web3") -> None:
69+
assert await async_w3_http.isConnected() is True
70+
71+
6172
class EthModuleTest:
6273
def test_eth_protocol_version(self, web3: "Web3") -> None:
6374
with pytest.warns(DeprecationWarning,

web3/_utils/request.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
Any,
33
)
44

5+
from aiohttp import (
6+
ClientSession,
7+
ClientTimeout,
8+
)
59
from eth_typing import (
610
URI,
711
)
@@ -40,3 +44,15 @@ def make_post_request(endpoint_uri: URI, data: bytes, *args: Any, **kwargs: Any)
4044
response.raise_for_status()
4145

4246
return response.content
47+
48+
49+
async def async_make_post_request(
50+
endpoint_uri: URI, data: bytes, *args: Any, **kwargs: Any
51+
) -> bytes:
52+
kwargs.setdefault('timeout', ClientTimeout(10))
53+
async with ClientSession(raise_for_status=True) as session:
54+
async with session.post(endpoint_uri,
55+
data=data,
56+
*args,
57+
**kwargs) as response:
58+
return await response.read()

web3/eth.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,23 @@
104104
)
105105

106106

107-
class Eth(Module):
107+
class BaseEth(Module):
108+
_gas_price: Method[Callable[[], Wei]] = Method(
109+
RPC.eth_gasPrice,
110+
mungers=None,
111+
)
112+
113+
114+
class AsyncEth(BaseEth):
115+
is_async = True
116+
117+
@property
118+
async def gas_price(self) -> Wei:
119+
# types ignored b/c mypy conflict with BlockingEth properties
120+
return await self._gas_price() # type: ignore
121+
122+
123+
class Eth(BaseEth, Module):
108124
account = Account()
109125
_default_account: Union[ChecksumAddress, Empty] = empty
110126
_default_block: BlockIdentifier = "latest"
@@ -175,11 +191,6 @@ def mining(self) -> bool:
175191
def hashrate(self) -> int:
176192
return self.get_hashrate()
177193

178-
_gas_price: Method[Callable[[], Wei]] = Method(
179-
RPC.eth_gasPrice,
180-
mungers=None,
181-
)
182-
183194
@property
184195
def gas_price(self) -> Wei:
185196
return self._gas_price()

web3/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
abi_ens_resolver,
5454
)
5555
from web3.eth import (
56+
AsyncEth,
5657
Eth,
5758
)
5859
from web3.geth import (
@@ -157,6 +158,7 @@ class Web3:
157158
parity: Parity
158159
geth: Geth
159160
net: Net
161+
async_eth: AsyncEth
160162

161163
def __init__(
162164
self,

0 commit comments

Comments
 (0)