-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebsocketsProviderV2 AttributeError: 'NoneType' object has no attribute 'method'
#3075
Comments
Hey @dmkulazhenko, thanks for the bug report. That |
@fselmo, Im using ankr node. Code import asyncio
import time
from eth_typing import HexStr
from web3 import AsyncWeb3
from web3.providers import WebsocketProviderV2
start = time.time()
async def ws_v2_subscription_context_manager_example():
async with AsyncWeb3.persistent_websocket(
WebsocketProviderV2(
"wss://rpc.ankr.com/eth/ws/<token>"
)
) as w3:
subscription = await w3.eth.subscribe("newHeads")
print(f"Subscription full: {subscription}")
# noinspection PyTypeChecker
subscription_id: HexStr = subscription["result"]
print(f"subscribed: {subscription_id}")
unsubscribed = False
while not unsubscribed:
async for response in w3.listen_to_websocket():
try:
print(
"block_number",
int(response["params"]["result"]["number"], 16),
)
except Exception as e:
print("ERROR", str(e))
if time.time() - start > 30:
print("unsubscribing...")
unsubscribed = await w3.eth.unsubscribe(subscription_id)
print("unsubscribed:", unsubscribed)
break
async def main():
await ws_v2_subscription_context_manager_example()
if __name__ == "__main__":
asyncio.run(main()) Stdout:
Also, let me test on my own node. |
@fselmo, so I tested it with my own node (erigon version 2.42.0-stable-808225f7), and results are interesting: import asyncio
import time
from web3 import AsyncWeb3
from web3.providers import WebsocketProviderV2
start = time.time()
async def ws_v2_subscription_context_manager_example():
async with AsyncWeb3.persistent_websocket(
WebsocketProviderV2(
"<node_url>"
)
) as w3:
subscription = await w3.eth.subscribe("newHeads")
print(f"Subscription full: {subscription}")
try:
subscription_id = subscription["result"]
except TypeError:
subscription_id = subscription
unsubscribed = False
while not unsubscribed:
async for response in w3.listen_to_websocket():
try:
print(response)
except Exception as e:
print("ERROR", str(e))
if time.time() - start > 30:
print("unsubscribing...")
unsubscribed = await w3.eth.unsubscribe(subscription_id)
print("unsubscribed:", unsubscribed)
break
async def main():
await ws_v2_subscription_context_manager_example()
if __name__ == "__main__":
asyncio.run(main()) Erigon:
Ankr:
Seems to be Ankr node (don't know what they are using geth/erigon/besu) and Erigon have different API. |
@fselmo I see the issue already. As per the JSON-RPC 2.0 spec, each request has an Perhaps there is an ankr node that follows the spec that you might be able to use. I can add some details about this to the documentation but this doesn't seem to be an issue with the library at this point. |
Sounds good. Thanks again for reporting 👍🏼 |
6.8.0
3.9.16
Linux 6.1.31-2-MANJARO
What was wrong?
I'm just trying to subscribe to a node using WS and
eth_subscribe
to get notifications about new blocks.Took code from docs.
Modified it a little bit, so came up with:
It crashes:
How can it be fixed?
Seems to be in https://github.com/ethereum/web3.py/blob/main/web3/manager.py#L296
should look like
To be honest, I dont have a lot of time to invest in this problem 😞.
But
self._provider._get_request_information_for_response
tries to look for some cache bymd5hash(subscription_id)
. I haven't digged in this caching mechanism and why is it needed, but seems to be ifrequest_info is None
— result should be yielded right away without something like applying of result_formatters and re-yielding after returning of scope to generator.btw, after this dirty fix, at least for me, code works as expected 😄
Also, there is another minor issues https://github.com/ethereum/web3.py/blob/main/web3/eth/async_eth.py#L680
async def subscribe(...) -> HexStr
returns full-response (dict
), but notHexStr
as expected to besubscription_id
.The text was updated successfully, but these errors were encountered: