bchavez / Coinbase.Pro

:chart_with_upwards_trend: A .NET/C# implementation of the Coinbase Pro API.
https://docs.pro.coinbase.com/
Other
66 stars 27 forks source link

Cannot connect to webservice feed. #15

Closed salocinx closed 4 years ago

salocinx commented 4 years ago

Hi

Thanks for sharing your work! I am currently trying to connect to the websocket feed. But await socket.ConnectAsync(); never returns and I get not connected. I have double checked the webservice at wss://ws-feed-public.sandbox.pro.coinbase.com on www.websocket.org and the webservice itself seems to be working fine.

Here's my testing code:

using System;
using System.IO;
using System.Collections.Generic;

using WebSocket4Net;

using Coinbase.Pro;
using Coinbase.Pro.Models;
using Coinbase.Pro.WebSockets;

using System.Threading.Tasks;

namespace WebsocketFeed {

    public class Program {

        private bool sandbox = true;

        private string apiKey = "<my-api-key>";
        private string secret = "<my-api-secret>";
        private string passphrase = "<my-api-passphrase>";

        private CoinbaseProWebSocket socket;

        public static void Main(string[] args) {
            Program p = new Program();
            p.InitializeCoinbasePro();
            p.InitializeWebsocketFeed();
            Console.WriteLine("Press any key to exit ...");
            Console.ReadLine();
        }

        private void InitializeCoinbasePro() {
            if(sandbox) {
                this.socket = new CoinbaseProWebSocket(new WebSocketConfig {
                    ApiKey = apiKey,
                    Secret = secret,
                    Passphrase = passphrase,
                    SocketUri = "wss://ws-feed-public.sandbox.pro.coinbase.com"
                });
            } else {
                this.socket = new CoinbaseProWebSocket(new WebSocketConfig {
                    ApiKey = apiKey,
                    Secret = secret,
                    Passphrase = passphrase
                });
            }
        }

        private async Task InitializeWebsocketFeed() {
            // Connect websocket.
            Console.WriteLine("Connecting to websocket feed ... ");
            await socket.ConnectAsync();
            Console.WriteLine("[OK]");
            // Initialize event handler.
            socket.RawSocket.MessageReceived += RawSocket_MessageReceived;
            // Create a subscription of what to listen to.
            var sub = new Subscription {
                ProductIds = {
                    "ETH-USD",
                },
                Channels = {
                    "heartbeat",
                }
            };
            // Send the subscription upstream.
            await socket.SubscribeAsync(sub);
            // Now wait for data.
            await Task.Delay(TimeSpan.FromMinutes(1));
        }

        private void RawSocket_MessageReceived(object sender, MessageReceivedEventArgs e) {
            // Try parsing the e.Message JSON.
            if(WebSocketHelper.TryParse(e.Message, out var msg)) {
                if(msg is HeartbeatEvent hb) {
                    Console.WriteLine($"Last Trade ID: {hb.LastTradeId}");
                }
            }
        }

    }

}

The code line Console.WriteLine("[OK]"); is never executed. The program hangs at await socket.ConnectAsync(); infinitely.

Some idea how to solve this issue?

bchavez commented 4 years ago

Hi @salocinx ,

Can you double-check? I just tried executing your code example and it seems to work fine: image

It did take a few seconds to connect, but connected nonetheless.

bchavez commented 4 years ago

Also, Nicolas, note that ETH-USD fiat market doesn't exist on Sandbox (and consequently, no heartbeat for ETH-USD). Try using BTC-USD for Sandbox if you're looking for a heartbeat. The ETH-USD fiat market you're looking for only exists on Production (currently).

image

Products API on Sandbox: https://api-public.sandbox.pro.coinbase.com/products

{
    "id": "LINK-USDC",
    "base_currency": "LINK",
    "quote_currency": "USDC",
    ...
  },
  {
    "id": "BAT-USDC",
    "base_currency": "BAT",
    "quote_currency": "USDC",
    ...
  },
  {
    "id": "ETH-BTC",
    "base_currency": "ETH",
    "quote_currency": "BTC",
    ...
  },
  {
    "id": "BTC-USD",
    "base_currency": "BTC",
    "quote_currency": "USD",
    ...
  },
  {
    "id": "BTC-GBP",
    "base_currency": "BTC",
    "quote_currency": "GBP",
    ...
  },
  {
    "id": "BTC-EUR",
    "base_currency": "BTC",
    "quote_currency": "EUR",
    ...
  }
]

Changing the product ID to the BTC-USD market on Sandbox shows a heartbeat:

image

Let me know if you continue to have issues.

Thanks, Brian

salocinx commented 4 years ago

Hi Brian

Thank you very much for your detailed answer! I still cannot connect when using the NuGet package 2.0.6. My sample program never outputs [OK], which means that await socket.ConnectAsync(); never returns. I meanwhile also tried to turn off all firewalls from Windows and make sure the web service isn't blocked by the router's firewall as well.

However, I now cloned your master branch and imported my sample program there and it works exactly like you describe in your answer (getting heartbeat messages for BTC-USD on sandbox).

Is there any difference between the NuGet package 2.0.6 and the current master branch on GitHub?

Thanks for your support! Nicolas

bchavez commented 4 years ago

Hi Nicolas,

No there shouldn't be any functional difference between v2.0.6 on NuGet and the master branch here.

The only thing I can think of that might make a difference is that:

It's hard to tell what exactly is going on without more diagnostic information from your machine. If you'd like more help, please provide:

Thanks, Brian

salocinx commented 4 years ago

Hi Brian

I meanwhile did some more testing. I am using Windows 10, Visual Studio 2019 and I have .NET Framework 4.8 installed. You have been pointing to the right direction. The connection problem only occurs when working with a .NET Framework as TFM. When using the same code I posted above using .NET Core 3.1 as TFM, connecting to the web feed works fine.

Could you please re-check if the program posted above works with .NET Framework 4.8 as TFM on your side? If it works, I will provide detailed network records and more information in order to pinpoint the issue.

Thanks for your ongoing support!

bchavez commented 4 years ago

Hi @salocinx, I took a second look at this and was able to reproduce the issue. The problem is, the event that fires .Opened event is the main thread for WebSocket4Net and messages won't be processed when the tread blocks at .ReadLine(). So it's like we stole the thread from WebSocket4Net and it never processes messages again.

I'm going to try to fix the bug and release a new version with a possible bug fix.

bchavez commented 4 years ago

Hi @salocinx

Please try v3.0.1 I think I've included some fixes that might help your situation on .NET Full Framework. https://www.nuget.org/packages/Coinbase.Pro/3.0.1