Search code examples
node.jsblockchainethereumweb3js

web3.eth.subscribe not implemented for web3 version 1.0.0-beta.27


I am on web3 version 1.0.0-beta.27 and I am running a private ethereum blockchain for testing purposes. The blockchain is mining and has two users, now I would like to subscribe to events in the blockchain and perform some actions. The code is below:

var Web3 = require("web3");     

var ether_port = 'http://localhost:8545'
var web3       = new Web3(new Web3.providers.HttpProvider(ether_port));

web3.eth.subscribe("pendingTransactions"
                  , function(err, result){
    if (err){ console.log(err) }
    else { console.log("result: ", result) }
});

I get something like:

Error: The current provider doesn't support subscriptions: HttpProvider
at Subscription.subscribe 

In some sense not surprising since when I do web3.eth.subscribe on the node.js console I get:

{ [Function] call: undefined }

Even though the documentation for web3-1.0.0 states the function can be used: https://web3js.readthedocs.io/en/1.0/web3-eth-subscribe.html.

  1. So is this just a matter of documentation being out of sync with actual implementation? Am I using it wrong?

  2. If it is not implemented, what is the best way to listen to changes in the chain? For example if I want a real time update of a user's account balance? That is aside from the naive implementation of a function that pings the chain every n fraction of a second.


Solution

  • As the error suggests, pub/sub is not available over HTTP. However, you can use it over WS. So, the documentation you referenced is not 100% wrong, it just omits the provider portion of the code.

    Try starting your nodes using web socket connections (geth --ws --wsport 8545 ..., assuming you're using geth), and change to a WebsocketProvider.

    var Web3 = require("web3");     
    
    var ether_port = 'ws://localhost:8545'
    var web3       = new Web3(new Web3.providers.WebsocketProvider(ether_port));
    
    web3.eth.subscribe("pendingTransactions"
                      , function(err, result){
        if (err){ console.log(err) }
        else { console.log("result: ", result) }
    });
    

    See the 4th comment on this discussion ticket.