toorop / go-bittrex

Go binding for the Bittrex crypto-currency exchange API.
MIT License
230 stars 101 forks source link

Bittrex streaming updates #23

Open simongui opened 7 years ago

simongui commented 7 years ago

Does this support the Bittrex socket API for streaming updates? I would like to hook into the live streaming updates :)

saniales commented 7 years ago

In brief. NO. I am trying to reverse engineering the 2.0 API to allow streaming updates. https://github.com/AlessandroSanino1994/golang-bittrex-api I am building a document, if you (and others from this repository too) can help me

themotu commented 7 years ago

Would be amazing if we could stream pricing in and make faster trading decisions.

TimLaMason commented 7 years ago

This is not in Go, but there is a nice paper in regards to the websocket API. I believe it came from Bittrex, not sure where though:

https://github.com/n0mad01/node.bittrex.api/files/1104308/WebSocketAPI_MarketTracking.docx

avdva commented 7 years ago

Hi, here I implemented streaming updates and it's working. Two moments: 1) I had to change the type of Orderb's fields to decimal.Decimal, as with floats it's not very reliable to update an order book, searching an order by price. 2) It may seem excessive to use doAsyncTimeout, but its really what is needed to build a reliable function, that does not hang. github.com/thebotguys/signalr does not support timeouts, and a few times CallHub got stuck somewhere inside it.

If you like it, I'll do a PR.

dezza commented 7 years ago

Yeah that PR would be kindly appreciated :)

simongui commented 7 years ago

Yeah, this would be really nice. Can we get this integrated?

dezza commented 7 years ago

@KLIM8D has some updates for the websocket as well he can explain. We used it together in a project.

brunocassol commented 7 years ago

Is there a way to listen to changes in all markets? Would be nice to have it track all markets if none was specified.

I'm not sure what would be the best way to implement this. Perhaps track all markets if specified market is an empty string ""?

kilpatty commented 7 years ago

Also curious if there is a way to implement listening to all markets.

avdva commented 7 years ago

It looks like it's possible to listen to all markets. I'll review @KLIM8D 's PR, and after it try to implement that listening.

avdva commented 7 years ago

Hi, here I added SubscribeMarkets. So, to sub for several markets, call GetMarketSummary(), get the markets you need, and pass them to SubscribeMarkets. Bug reports or any feedback is appreciated.

kilpatty commented 7 years ago

@avdva Amazing. I will be trying this out today, and let you know how it goes. Just in time for what I need - thanks again!

mightymouse2045 commented 6 years ago

Can we get some examples on streaming please? I can't seem to get this working...

avdva commented 6 years ago

Yes, the sad story is that about 10 days ago they put ws behind Cloudflare, so until they give some open ws endpoint, this won't work.

vlddlv commented 6 years ago

@avdva I created a super quick fork https://github.com/vlddlv/signalr and I tried to solve the bypass using https://github.com/cardigann/go-cloudflare-scraper

While it does work and I'm able to retrieve the signalr connection token, I wasn't able to handshake with the web socket due to unknown reason. Any ideas?

The particular status code for bad handshake was: 503 Service Temporarily Unavailable but interestingly enough, I was able to connect to the web socket using the same URL from a chrome extension.

ybbkrishna commented 6 years ago

@vlddlv I was able to make it working by adding the headers returned from cloudflare scrapper to ws

mightymouse2045 commented 6 years ago

@ybbkrishna can you please provide an example of how you got this working?

KeKs0r commented 6 years ago

@ybbkrishna Care to share your solution? Can this fix be added to this library?

I think 2 things need to be added to the headers: the user-agent and cookie. I think a similar Node module ran into the same issue: https://github.com/n0mad01/node.bittrex.api/issues/67

OpinionatedGeek commented 6 years ago

Hi folks,

I'd really like this to be working and available, so I took a deeper look at it all.

The good news: I have it working.

The bad news: it requires changes to multiple dependencies - signalr and go-cloudflare-scraper. (go-cloudflare-scraper is a new dependency with this change but it also requires a small edit.)

I've put all the changes to all 3 repos up on my Github.

The changes to go-cloudflare-scraper expose the CookieJar so that it can be re-used by the websocket: https://github.com/OpinionatedGeek/go-cloudflare-scraper/commit/c65485b29c3ae21873bb6246a07adc02e491884f

(There's already a similar pull-request for this.)

The changes to signalr allow it to take a *http.Client which provides the scraper transport and the cookie jar: https://github.com/OpinionatedGeek/signalr/commit/e19c5a5788a7c124c5afa8f16f4131ae268bd6d9

The changes to go-bittrex create the scraper transport and pass that to signalr: https://github.com/OpinionatedGeek/go-bittrex/commit/3cdf07f8514782aa1c9af429ecdcd9b4e61105d4

I tried to make the changes as minimal as I could (with the possible exception of the re-use of the user agent in the signalr negotiate() function - it works without that change but I figured it should still be there).

Here's the test program I used:

package main

import (
    "fmt"

    "github.com/OpinionatedGeek/go-bittrex"
)

func main() {
    bt := bittrex.New("", "")
    ch := make(chan bittrex.ExchangeState, 16)
    go func() {
        for st := range ch {
            fmt.Println("Message:", st)
        }
    }()
    bt.SubscribeExchangeUpdate("USDT-BTC", ch, nil)
}

Unfortunately I couldn't see a sensible way of isolating the changes to just go-bittrex. Maybe one of you can see a better way? (The lack of activity on both those dependencies makes me worry that pull requests would be ignored.)

9cat commented 6 years ago

halt on the here as following. what's wrong with it?

USDT-BTC 2018/03/19 07:27:12 Solving challenge for socket.bittrex.com 2018/03/19 07:27:16 Requesting https://socket.bittrex.com/cdn-cgi/l/chk_jschl?jschl_answer=218&jschl_vc=4d3eca6aa8bd15497eecd863335ff469&pass=1521458836.533-OTK4IueTkC

OpinionatedGeek commented 6 years ago

@9cat I'm not sure. When I run it now it seems to go from the Cloudflare page to a Cloudflare CAPTCHA page, which the go-cloudflare package doesn't expect and so it quits.

I should have put in some logging of the error, if there is one, so maybe try this instead:

package main

import (
    "fmt"

    "github.com/OpinionatedGeek/go-bittrex"
)

func main() {
    bt := bittrex.New("", "")
    ch := make(chan bittrex.ExchangeState, 16)
    go func() {
        for st := range ch {
            fmt.Println("Message:", st)
        }
    }()
    err := bt.SubscribeExchangeUpdate("USDT-BTC", ch, nil)
    if err != nil {
        fmt.Println("Error:", err)
    }
}

On my setup it sometimes prints out: Error: invalid character '<' looking for beginning of value It doesn't do so consistently though - sometimes it works fine, sometimes it doesn't.

9cat commented 6 years ago

@OpinionatedGeek Thanks. I encouter the simliar problem. but it works. However, since yesterday, I encouter the problem like:

doAsync Timeout ... %!(EXTRA *url.Error=Get https://socket.bittrex.com/signalr/negotiate: TypeError: Cannot access member 'value' of undefined) 2018/04/05 14:51:15 SubscribeExchangeUpdateing ...

anyone encounter this issues. any ideas?

OpinionatedGeek commented 6 years ago

@9cat Yes, it started happening to me yesterday afternoon/evening.

At that point I gave up and started integrating Binance's API into my code. Sorry.

Geoff

zoh commented 6 years ago

I fix it in https://github.com/zoh/go-cloudflare-scraper and you can use my fork github.com/zoh/go-bittrex. It is work.

thx