Coinigy / api

Coinigy API Examples
161 stars 65 forks source link

[Question] Python websocket client example #6

Open devonhk opened 7 years ago

devonhk commented 7 years ago

I'm having trouble establishing a websocket connection on this endpoint wss://sc-02.coinigy.com/socketcluster/. I'm using a socketcluster compatible client https://github.com/sacOO7/socketcluster-client-python.

Here is a short code snippet I'm using to connect to the websocket endpoint.

from socketclusterclient import Socketcluster
import logging

logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)

def onconnect(socket):
    logging.info("on connect got called")
    socket.emit('auth', {'apiKey': 'blabla',
                         'apiSecret': 'dsadasdasdas34r'})

def ondisconnect(socket):
    logging.info("on disconnect got called")

def onConnectError(socket, error):
    logging.info("On connect error got called")

def onSetAuthentication(socket, token):
    logging.info("Token received " + token)
    socket.setAuthtoken(token)

def onAuthentication(socket, isauthenticated):
    logging.info("Authenticated is " + str(isauthenticated))

if __name__ == "__main__":
    socket = Socketcluster.socket("wss://sc-02.coinigy.com/socketcluster/")
    socket.setBasicListener(onconnect, ondisconnect, onConnectError)
    socket.setAuthenticationListener(onSetAuthentication, onAuthentication)
    socket.connect()

Steps to reproduce

  1. Install websocket client pip install git+git://github.com/sacOO7/socketcluster-client-python.git
  2. Add api credentials to the script
  3. Execute the python script python ws.py

Expected behavior The websocket client successfully authenticates with the server and establishes a websocket connection

Actual behavior The websocket client does not authenticate with the server and never establishes a websocket connection

Potential solution I think a python websocket client example would solve my problem and be a great addition to this repo.

Thanks in advance.

MaxHoefl commented 7 years ago

+1 here

ByronAP commented 7 years ago

what OS are you guys using and what version of py?

MaxHoefl commented 7 years ago

I am on mac OSX 10.11, python 2.7 (conda environment). The code above gives me INFO:on connect got called INFO:Emit data is {"data": {"apiKey": "xxxx", "apiSecret": "xxxx"}, "event": "auth"} INFO:{"rid":1,"data":{"id":"xxxx-xxxx","pingTimeout":20000,"isAuthenticated":false}} INFO:Authenticated is False

Thanks!

MaxHoefl commented 7 years ago

Hi, what's wrong with the above code is that emit() is called before onAuthentication(). (source: https://github.com/sacOO7/socketcluster-client-python/issues/2?_pjax=%23js-repo-pjax-container)

I tried again with this slight modification:

import logging
logging.basicConfig(format="%s(levelname)s:%(message)s", level=logging.DEBUG)

def onconnect(socket):
    logging.info("on connect got called")

def ondisconnect(socket):
    logging.info("on disconnect got called")

def onConnectError(socket, error):
    logging.info("On connect error got called")

def onConnected(socket):
    logging.info("Calling onConnected")

def onSetAuthentication(socket, token):
    logging.info("Token received " + token)
    socket.setAuthtoken(token)

def onAuthentication(socket, isauthenticated):
    logging.info("Authenticated is " + str(isauthenticated))

    def ack(eventname, error, object):
        logging.info(str(error["errorCode"]) + " " + str(error["errorMsg"]))

    socket.emitack("auth", "{'apiKey': '{xxx}', 'apiSecret': '{xxx}'}", ack)

if __name__ == "__main__":
    socket = Socketcluster.socket("wss://sc-02.coinigy.com/socketcluster/")
    socket.setBasicListener(onconnect, ondisconnect, onConnectError)
    socket.setAuthenticationListener(onSetAuthentication, onAuthentication)
    socket.connect()

But I get a "403 Key/Secret Pair Failed". I just created that key/secret pair on coinigy.

This is the full output:

INFO:on connect got called
INFO:{"rid":1,"data":{"id":"xxx","pingTimeout":20000,"isAuthenticated":false}}
INFO:Authenticated is False
INFO:{"rid":2,"error":{"errorCode":403,"errorMsg":"Key/Secret Pair Failed"},"data":"Key/Secret Pair Failed"}
INFO:Ack receive got called
INFO:403 Key/Secret Pair Failed

Thanks for the help!

ByronAP commented 7 years ago

I just tried Maxs code with my key and it worked

mutterkorn commented 7 years ago

Had the same problem. Once I bought a paid coinigy subscription, it started working.

ebagjones commented 7 years ago

I can authenticate, but I can't find any examples on how to actually do anything. Would someone be kind enough to show how to subscribe (and print, for example) the data from a ticker pair, or the private channel, or ... well, anything really.

ByronAP commented 7 years ago

After you have authenticated you can emit the same commands used in all the other examples regardless of programming language such as "subscribe"

ebagjones commented 7 years ago

Thanks ByronAP, but I'm pretty new to this stuff. I'm pretty sure I've subscribed, but I'm not sure on how to receive the data/object. For example if I have socket.subscribe("channels", "OK") how is the data returned to me? do I have to write something for onMessage, or do I utilize socket.watch(), or ... ?

ebagjones commented 7 years ago

If anyone would be kind enough to send me an example of this code doing something (subscribing, using the emitted data to log the prices, etc.) I'd be more than happy to tip them a bit of BTC or ETH...

AymanEG commented 7 years ago

Any updates guys for a full working example ?! and if possible to add different channels to same socket connection ?!

regards Ayman

ChrisFullerAstro commented 7 years ago
from socketclusterclient import Socketcluster
import json

logging.basicConfig(format="%s(levelname)s:%(message)s", level=logging.DEBUG)

api_credentials = json.loads('{}')
api_credentials["apiKey"]="xxx"
api_credentials["apiSecret"]="xxx"

def onconnect(socket):
    logging.info("onconnect: on connect got called")

def ondisconnect(socket):
    logging.info("ondisconnect: on disconnect got called")

def onConnectError(socket, error):
    logging.info("onConnectError: On connect error got called")

def onSetAuthentication(socket, token):
    logging.info("onSetAuthentication: Token received " + token)
    socket.setAuthtoken(token)

    socket.subscribeack('ORDER-GDAX--BTC--USD', suback)
    socket.onchannel('ORDER-GDAX--BTC--USD', channelmessage)

def onAuthentication(socket, isauthenticated):
    logging.info("Authenticated is " + str(isauthenticated))
    def ack(eventname, error, data):
        logging.info("onAuthentication: eventname is "+eventname)
        logging.info("onAuthentication: token is "+ json.dumps(data, sort_keys=True))
    socket.emitack("auth", api_credentials, ack)

    logging.info('onAuthentication: function call finished')

def suback(channel, error, object):
    if error is '':
        logging.info( "Subscribed successfully to channel " + channel)

def puback(channel, error, object):
    if error is '':
        logging.info( "Publish sent successfully to channel " + channel)

def channelmessage(key, object):
    logging.info( "Got data " + json.dumps(object) + " from key " + key)

def unsuback(channel, error, object):
    if error is '':
        logging.info( "Unsubscribed to channel " + channel)

if __name__ == "__main__":
    socket = Socketcluster.socket("wss://sc-02.coinigy.com/socketcluster/")
    socket.setBasicListener(onconnect, ondisconnect, onConnectError)
    socket.setAuthenticationListener(onSetAuthentication, onAuthentication)
    socket.connect()
ChrisFullerAstro commented 7 years ago

The above works for me using python 3.6. Hope that helps :)

efrister commented 6 years ago

Anyone who finds this because they were searching for how to do the auth with Java (using the io.github.sac library), pulling their hair out in frustration as to why it works in every language except Java, desperate for help, please feel free to profit from my 16h debugging marathon.

You need to actually send an "org.json.JSONObject" as the second parameter to auth, like so (below code is Scala, feel free to adjust for Java):

var auth = new org.json.JSONObject()
auth.put("apiKey", "XXX")
auth.put("apiSecret", "YYY")

socket.emit(
          "auth",
          auth,
          (name: String, error: scala.Any, data: scala.Any) => {
            logger.info(s"Got message: $name, data is $error, data is $data")
          }
 )

Sending a Json String yourself does not work. Sending a Map<String,String> does not work either. What works is sending the JSONObject.