Skip to content
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

websocket provider not working #1009

Closed
jfdelgad opened this issue Aug 20, 2018 · 16 comments
Closed

websocket provider not working #1009

jfdelgad opened this issue Aug 20, 2018 · 16 comments

Comments

@jfdelgad
Copy link

  • Version: 4.5
  • Python: 3.5
  • OS: win

What was wrong?

impossible to connect to infura using websockets

I am using this to connect to infura:

from web3 import Web3
web3 = Web3(Web3.WebsocketProvider("wss://ropsten.infura.io/ws"))
web3.eth.blockNumber

No response, the console just become unresponsive. Tried two different computers in different networks, same result. Also used rinkeby and mainnet, same result.

@jfdelgad jfdelgad changed the title websockets websocket provider not working Aug 20, 2018
@voith
Copy link
Contributor

voith commented Aug 21, 2018

thanks for the report @jfdelgad.
firstly, the connection should timeout after sometime instead of just hanging and is noted in #956.
I tested my code on mainnet, rinkeby, ropsten and kovan. Below are the results.

on mainnet
In [31]: w3 = Web3(Web3.WebsocketProvider('wss://mainnet.infura.io/_ws'))

In [32]: w3.eth.blockNumber
Out[32]: 6184928

Notice the _ws in the uri.
However, when I remove the _ws and try wss://mainnet.infura.io/ws, it hangs.

In [33]: w3 = Web3(Web3.WebsocketProvider('wss://mainnet.infura.io/ws'))

In [34]: w3.eth.blockNumber
# hangs

then I tried wscat

➜  ~ wscat -c wss://mainnet.infura.io/ws

connected (press CTRL+C to quit)
> {"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id": 1}
< {"jsonrpc":"2.0","id":1,"result":"0x5e5ff9"}

Next I tried with the websockets library:

import asyncio
import json
import websockets

async def get_eth_blockNumber(uri):
    async with websockets.connect(uri) as websocket:
        request_data = {'jsonrpc': '2.0', 'method': 'eth_blockNumber', 'params': [], 'id': 1}
        await websocket.send(json.dumps(request_data))

        result = await websocket.recv()
        print(result)

In [9]: asyncio.get_event_loop().run_until_complete(get_eth_blockNumber('wss://mainnet.infura.io/_ws'))
{"jsonrpc":"2.0","id":1,"result":"0x5e6076"}

In [10]: asyncio.get_event_loop().run_until_complete(get_eth_blockNumber('wss://mainnet.infura.io/ws'))
{"jsonrpc":"2.0","id":1,"result":"0x5e6077"}


In [11]: asyncio.get_event_loop().run_until_complete(get_eth_blockNumber('wss://ropsten.infura.io/ws'))
{"jsonrpc":"2.0","id":1,"result":"0x3b2f70"}

This is a bug in web3. I don't know when I'll get time to get to this.

@ETH-Pantheon
Copy link

Thanks a lot, this is useful.

@FYJen
Copy link

FYJen commented Aug 28, 2018

Bump!

Same issue here except both ws and _ws hang for me. I am using web3 4.6 and python 3.6.5.

There is an official document from infura that the de facto WebSocket URL should be the one without underscore, ws. See here

I have tried on both mainnet and rinkey (w3.eth.blockNumber), and both networkers hang for ws and _ws.

@ankitchiplunkar
Copy link
Contributor

Yes, I am suffering from the same issue.

@voith
Copy link
Contributor

voith commented Aug 29, 2018

Will try my best to take a look at this tonight. But not promising anything.

@voith
Copy link
Contributor

voith commented Aug 29, 2018

It turns out that this line is creating the problem:

request_data = self.encode_rpc_request(method, params)

encode_rpc_request(method, params) returns bytes which for some reason causes infura to barf.(Not sure yet if the problem is with infura, but the same code works fine with geth and parity)
df465dc seems to fix the issue, but I need to investigate further.

@voith
Copy link
Contributor

voith commented Aug 29, 2018

So this indeed turns out to be a bug in infura.
To be sure about it I tried another websockets library, websocket-client. I have left the results of my tests over here.

Websocket supports input as both string and binary. However, the opcodes for both differ in the DataFrame. You can look at the implementation here or read it up in the docs.
However, when data is sent as bytes(opcode 2), it just hangs.

This is not a bug in web3 but a bug in infura.

We can still fix this in web3 as a temporary workaround, something like df465dc. But let @carver and @pipermerriam make this call.

@carver
Copy link
Collaborator

carver commented Aug 29, 2018

Sure, a decode() in the WebsocketProvider seems reasonable. I think Infura is the primary use case for WS at this point. But it definitely deserves an in-code comment explaining why, and maybe a link to the Infura issue saying that decode() could be removed if they decide to add support.

@voith
Copy link
Contributor

voith commented Aug 30, 2018

Infura decided to fix this on their end: INFURA/infura#134 (comment). I tested it myself, works fine!
@jfdelgad @ETH-Pantheon @ankitchiplunkar @torston @EvertKors @FYJen Can you guys retry again? The issue should be fixed.

@carver We can now close this issue.

@ankitchiplunkar
Copy link
Contributor

@voith checked this on my end works fine.

@carver
Copy link
Collaborator

carver commented Aug 30, 2018

Nice @voith

@Daiiszuki
Copy link

Daiiszuki commented Jan 22, 2022

I'm unable to connect to wss

import brownie
from brownie import *
from web3 import Web3
import json 


from web3 import Web3, AsyncHTTPProvider
from web3.eth import AsyncEth
from web3.net import AsyncNet
import os


infura_url = os.getenv("WEB3_INFURA_PROJECT_ID")
privateKey = os.getenv("PRIVATE_KEY")

web3 = Web3(Web3.WebsocketProvider(infura_url))


def main():

    print(web3.isConnected())

```
`

This returns false 

Please help

@kclowes
Copy link
Collaborator

kclowes commented Jan 24, 2022

@Daiiszuki it looks like you're using an infura project id as your URL. You need a URL that looks something like: wss://mainnet.infura.io/ws/v3/{project id}. Alternatively, if you're connecting to mainnet, you should be able to just do:

from web3.auto.infura import w3
w3.isConnected()

and similarly for a testnet: from web3.auto.infura.goerli import w3

In the future, this kind of usage question is usually best for the web3.py discord channel here. If you think you've found a bug and want to raise an issue, please open a new issue rather than commenting on an old one. Thanks!

@Daiiszuki
Copy link

Thanks for responding but the .env variable actually contains the full infura url.I used this issue because I believe it's the same problem

I've tried the suggestions here, nothing seems to work

@Daiiszuki
Copy link

Daiiszuki commented Jan 25, 2022

And I did try the discord group and no response, but made some improvements to the code:

import brownie
from brownie import accounts, network, config
from web3 import Web3
import json 


from web3 import Web3, AsyncHTTPProvider
from web3.eth import AsyncEth
from web3.net import AsyncNet
import os
import asyncio
from json import loads
from decimal import Decimal
from dotenv import load_dotenv 
load_dotenv()
infura_url = "wss://mainnet.infura.io/ws/v3/"
privateKey = os.getenv("PRIVATE_KEY")

web3 = Web3(Web3.WebsocketProvider(infura_url, websocket_timeout=60))
#web3 = Web3(Web3.AsyncHTTPProvider(infura_url), modules={'eth': (AsyncEth,)}, middlewares=[])
#web3 = Web3(Web3.HTTPProvider(infura_url))
#uniswapFactory address= "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f";
#uniswapFactory = config["networks"][network.show_active()][
       # "uniswapFactory"
    #]

#USDC address 
#usdcAddress = config["networks"][network.show_active()]["usdcAddress"]

#wethAddress address 
#wethAddress = config["networks"][network.show_active()]["wethAddress"]









#liquidityContract = web3.eth.contract(address=web3.toChecksumAddress("0x9ee0a4e21bd333a6bb2ab298194320b8daa26516"), abi=abi)


ETHER = 10 ** 18
factoryABI = json.loads('[{"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"PairCreated","type":"event"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"allPairsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"createPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeToSetter","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getPair","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeTo","type":"address"}],"name":"setFeeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"name":"setFeeToSetter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]')










async def get_account():

    if network.show_active() == "development":
        return accounts[0]
    else:
        return accounts.add(config["wallets"]["from_key"])
    




async def handle_event(event):
    print(event)
    print(web3.eth.block_number)
    uniswapFactory = '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95'
    wethAddress = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
    daiAddress = '0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667'
    
    #print(bid_price, offer_price)
    factory = web3.eth.Contract(factoryABI, uniswapFactory);
    pairAddress = await factory.getPair(wethAddress, daiAddress).call();
    pair = web3.eth.Contract(factory.abi, pairAddress);
    reserves = await pair.getReserves().call();
    print(pairAddress.logs)
    print(reserves.logs)
    print(web3.eth.Eth.get_filter_logs)


    # and whatever

async def log_loop(event_filter, poll_interval):
    while True:
        for event in event_filter.get_new_entries():
            await handle_event(event)
        await asyncio.sleep(poll_interval)

async def main():
    if network.show_active() in ["mainnet-fork"]:
        await get_account()
    block_filter = web3.eth.filter('latest')
    #tx_filter = web3.eth.filter('pending')
    wethAddress = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
    daiAddress = '0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667'
    uniswapFactory = '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95'
    factory = web3.eth.Contract(factoryABI, uniswapFactory);
    pairAddress = await factory.getPair(wethAddress, daiAddress).call();
    event_filter = web3.eth.filter({"address": pairAddress })
    loop = asyncio.get_event_loop()

   
    

    
    try:
        loop.run_until_complete(
            asyncio.gather(
                log_loop(block_filter, 2),
                log_loop(event_filter, 2)
                ))
    finally:
        loop.close()

if __name__ == '__main__':
    asyncio.run(main())


 


**I Need a way to continuously monitor the price of uniswap pair reserves -->To be used in another program

Please if you can link me to an an example implementation.By the way. The above code produces:**

Running 'price.py::main'...
  File "brownie/_cli/run.py", line 50, in main
    return_value, frame = run(
  File "brownie/project/scripts.py", line 91, in run
    func_ast.body[0].body = injected_ast.body + func_ast.body[0].body  # type: ignore
IndexError: list index out of range

@akhanaton
Copy link

And I did try the discord group and no response, but made some improvements to the code:

import brownie
from brownie import accounts, network, config
from web3 import Web3
import json 


from web3 import Web3, AsyncHTTPProvider
from web3.eth import AsyncEth
from web3.net import AsyncNet
import os
import asyncio
from json import loads
from decimal import Decimal
from dotenv import load_dotenv 
load_dotenv()
infura_url = "wss://mainnet.infura.io/ws/v3/"
privateKey = os.getenv("PRIVATE_KEY")

web3 = Web3(Web3.WebsocketProvider(infura_url, websocket_timeout=60))
#web3 = Web3(Web3.AsyncHTTPProvider(infura_url), modules={'eth': (AsyncEth,)}, middlewares=[])
#web3 = Web3(Web3.HTTPProvider(infura_url))
#uniswapFactory address= "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f";
#uniswapFactory = config["networks"][network.show_active()][
       # "uniswapFactory"
    #]

#USDC address 
#usdcAddress = config["networks"][network.show_active()]["usdcAddress"]

#wethAddress address 
#wethAddress = config["networks"][network.show_active()]["wethAddress"]









#liquidityContract = web3.eth.contract(address=web3.toChecksumAddress("0x9ee0a4e21bd333a6bb2ab298194320b8daa26516"), abi=abi)


ETHER = 10 ** 18
factoryABI = json.loads('[{"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"PairCreated","type":"event"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"allPairsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"createPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeToSetter","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getPair","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeTo","type":"address"}],"name":"setFeeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"name":"setFeeToSetter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]')










async def get_account():

    if network.show_active() == "development":
        return accounts[0]
    else:
        return accounts.add(config["wallets"]["from_key"])
    




async def handle_event(event):
    print(event)
    print(web3.eth.block_number)
    uniswapFactory = '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95'
    wethAddress = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
    daiAddress = '0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667'
    
    #print(bid_price, offer_price)
    factory = web3.eth.Contract(factoryABI, uniswapFactory);
    pairAddress = await factory.getPair(wethAddress, daiAddress).call();
    pair = web3.eth.Contract(factory.abi, pairAddress);
    reserves = await pair.getReserves().call();
    print(pairAddress.logs)
    print(reserves.logs)
    print(web3.eth.Eth.get_filter_logs)


    # and whatever

async def log_loop(event_filter, poll_interval):
    while True:
        for event in event_filter.get_new_entries():
            await handle_event(event)
        await asyncio.sleep(poll_interval)

async def main():
    if network.show_active() in ["mainnet-fork"]:
        await get_account()
    block_filter = web3.eth.filter('latest')
    #tx_filter = web3.eth.filter('pending')
    wethAddress = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
    daiAddress = '0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667'
    uniswapFactory = '0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95'
    factory = web3.eth.Contract(factoryABI, uniswapFactory);
    pairAddress = await factory.getPair(wethAddress, daiAddress).call();
    event_filter = web3.eth.filter({"address": pairAddress })
    loop = asyncio.get_event_loop()

   
    

    
    try:
        loop.run_until_complete(
            asyncio.gather(
                log_loop(block_filter, 2),
                log_loop(event_filter, 2)
                ))
    finally:
        loop.close()

if __name__ == '__main__':
    asyncio.run(main())


 

**I Need a way to continuously monitor the price of uniswap pair reserves -->To be used in another program

Please if you can link me to an an example implementation.By the way. The above code produces:**

Running 'price.py::main'...
  File "brownie/_cli/run.py", line 50, in main
    return_value, frame = run(
  File "brownie/project/scripts.py", line 91, in run
    func_ast.body[0].body = injected_ast.body + func_ast.body[0].body  # type: ignore
IndexError: list index out of range

Hey were you able to solve this? I have run into the same error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants