Search code examples
pythonwebsocketcoinbase-api

Receiving data from Coinbase Exchange API Websocket


I'm trying to build an orderbook snapshot using the Coinbase Exchange API, specifically with the Websocket feed.

https://docs.exchange.coinbase.com/?python#websocket-feed

I believe I'm successful in making the connection and sending the initial subscribe message. After the initial subscribe message, I am expecting onMessage events. But no such messages appear to arrive. Eventually the connection times out and closes.

The code:

from twisted.internet import reactor
from autobahn.twisted.websocket import WebSocketClientFactory, WebSocketClientProtocol, connectWS
import json

class ClientProtocol(WebSocketClientProtocol):
    def onConnect(self, response):
        print("Server connected: {0}".format(response.peer))
    def initMessage(self):
        message_data = [{"type": "subscribe", "product_id": "BTC-USD"}]
        message_json = json.dumps(message_data)
        print "sendMessage: " + message_json
        self.sendMessage(message_json)
    def onOpen(self):
        print "onOpen calls initMessage()"
        self.initMessage()
    def onMessage(self, msg, binary):
        print "Got echo: " + msg
    def onClose(self, wasClean, code, reason):
        print("WebSocket connection closed: {0}".format(reason))

if __name__ == '__main__':
    factory = WebSocketClientFactory("wss://ws-feed.exchange.coinbase.com")
    factory.protocol = ClientProtocol
    connectWS(factory)
    reactor.run()

The output:

python orders_twisted.py 
Server connected: tcp4:190.93.242.231:443
onOpen calls initMessage()
sendMessage: [{"type": "subscribe", "product_id": "BTC-USD"}]
WebSocket connection closed: connection was closed uncleanly (peer dropped the TCP connection without previous WebSocket closing handshake)

Solution

  • You were sending your subscription request as a JSON array of dictionaries, whereas should just be a dictionary. Change the code from:

    def initMessage(self):
        message_data = [{"type": "subscribe", "product_id": "BTC-USD"}]
        message_json = json.dumps(message_data)
        ...
    

    to:

    def initMessage(self):
        message_data = {"type": "subscribe", "product_id": "BTC-USD"}
        message_json = json.dumps(message_data)
        ...
    

    With this change, your code successfully subscribes ...