GithubHelp home page GithubHelp logo

bchavez / coinbase.pro Goto Github PK

View Code? Open in Web Editor NEW
67.0 9.0 27.0 375 KB

:chart_with_upwards_trend: A .NET/C# implementation of the Coinbase Pro API.

Home Page: https://docs.pro.coinbase.com/

License: Other

F# 8.98% C# 90.97% Batchfile 0.05%
gdax gdax-api orderbook bitcoin ethereum trading trading-api coinbase coinbase-pro coinbasepro

coinbase.pro's Introduction

Build status Nuget Users

Coinbase.Pro for .NET/C# Library

Project Description

A .NET implementation for the Coinbase Pro API.

๐Ÿ“ข HEY! Be sure to checkout these other Coinbase API integrations:

  • Coinbase - For Coinbase wallet account integration.
  • Coinbase.Commerce - For e-commerce, merchants, and websites selling products or services looking to receive cryptocurrency as payment.

Minimum Requirements

  • .NET Standard 2.0 or later
  • .NET Framework 4.6.1 or later
  • TLS 1.2 or later

Note: If you are using .NET Framework 4.6.1 you will need to ensure your application is using TLS 1.2 or later. This can be configured via the registry (link 1, link 2) or configured at application startup by setting the following value in ServicePointManager:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Crypto Tip Jar

Download & Install

Nuget Package Coinbase.Pro

Install-Package Coinbase.Pro

Getting Started

To get started, simply create a new CoinbaseProClient object as shown below:

var client = new CoinbaseProClient(new Config
   {
      ApiKey = "my-api-key",
      Secret = "my-api-secret",
      Passphrase = "my-api-passphrase",
      //Override the ApiUrl property to use Sandbox.
      //ApiUrl = "https://api-public.sandbox.pro.coinbase.com"
   });

snippet source | anchor

By default, the ApiUrl property is set to use production. If you want to use the sandbox, set the ApiUrl property to https://api-public.sandbox.pro.coinbase.com as described in the documentation here. Setting the ApiUrl property will override the production REST API URL that is set by default.

Once you have a CoinbaseProClient object, you can call any one of the many API endpoints listed here. Extensive examples can be found here. For your reference, a link to the Coinbase Pro developer documentation can be found here.

As an example, to create a limit order on the buy side of the ETH-USD order book for 2 ETH at 100 USD each, do the following:

var order = await client.Orders.PlaceLimitOrderAsync(
   OrderSide.Buy, "ETH-USD", size: 2, limitPrice: 100m);

order.Dump();

snippet source | anchor

The order object returned by the trading engine will have similar values to the following JSON object:

{
  "id": "ba3d3318-d1f0-4f9d-ae6f-1bda6ff370fa",
  "price": 100.00000000,
  "size": 2.00000000,
  "product_id": "ETH-USD",
  "side": "buy",
  "stp": "dc",
  "type": "limit",
  "time_in_force": "GTC",
  "post_only": true,
  "created_at": "2018-11-30T05:11:54.000355+00:00",
  "fill_fees": 0.0000000000000000,
  "filled_size": 0.00000000,
  "executed_value": 0.0000000000000000,
  "status": "pending",
  "settled": false,
  "funds": 0.0,
  "specified_funds": 0.0
}

Full API Support

Private Endpoints
Market Data Endpoints
WebSocket Feed

Error Handling

When errors occur after calling an API, Coinbase Pro delivers error messages in the response body of a failed HTTP call. First wrap your call in a try/catch statement and handle the Exception ex. Next, get the error message of a failed API call by calling GetErrorMessageAsync() extension method on the exception. The GetErrorMessageAsync() extension method will read the response body of the failed HTTP call as shown below:

try
{
   var order = await client.Orders.PlaceLimitOrderAsync(
      OrderSide.Buy, "BTCX-USDX", size: 1, limitPrice: 5000m);
}
catch( Exception ex )
{
   var errorMsg = await ex.GetErrorMessageAsync();
   Console.WriteLine(errorMsg);
}
//OUTPUT: "Product not found"

snippet source | anchor

Pagination

Some Coinbase Pro APIs are paginable. However, Coinbase Pro's paging can be a little confusing at first. So, let's review. Consider the following diagram below that illustrates the Current Point In Time over a paginable set of data with an item size of 5 items per page:

    Five Items Per Page (limit=5)
     
Past                         Future
Older                         Newer
11   15 16   20     21   25 26   30
[items] [items]     [items] [items]
              ^
      After <-|-> Before
              ^
              |
    Current Point In Time

Suppose you grabbed the most recent trades from var trades = client.MarketData.GetTradesAsync("ETH-USD", limit: 5). The data you captured in trades is the Current Point In Time with the most recent trade 20 as shown in the diagram above.

  • To enumerate older trades beyond the initial page:

//Get the initial page, items 16 through 20
var trades = await client.MarketData.GetTradesAsync("ETC-USD", limit: 5);

//Get the next batch of older trades after the current page.
while( trades.After is not null )
{
   trades = await client.MarketData.GetTradesAsync("ETC-USD", limit: 5, after: trades.After);
}

snippet source | anchor

Now suppose time advances, more trades happen in the market. Given the Current Point In Time with the initial page of items 16-20.

  • To enumerate newer trades beyond the initial page:

//Get the initial page, items 16 through 20
var trades = await client.MarketData.GetTradesAsync("ETC-USD", limit: 5);

//Some time advances, trades execute.

//Now, get the next batch of newer trades before the current page.
while( trades.Before is not null )
{
   trades = await client.MarketData.GetTradesAsync("ETC-USD", limit: 5, before: trades.Before);
}

snippet source | anchor

More information about pagination can be found here.

WebSocket Feeds

This library also supports live WebSocket feeds. There are two types Authenticated and Unauthenticated feeds.

Unauthenticated WebSocket

To create an unauthenticated feed, simply do the following:

var socket = new CoinbaseProWebSocket();

snippet source | anchor

Authenticated WebSocket

To create an authenticated feed, doing the following:

//authenticated feed
var socket = new CoinbaseProWebSocket(new WebSocketConfig
   {
      ApiKey = "my-api-key",
      Secret = "my-api-secret",
      Passphrase = "my-api-passphrase",
      //Override the SocketUri property to use Sandbox.
      //SocketUri = "wss://ws-feed-public.sandbox.pro.coinbase.com"
   });

snippet source | anchor

By default, the SocketUri property is set to use production. If you want to use the sandbox, set the SocketUri property to wss://ws-feed-public.sandbox.pro.coinbase.com as described in the documentation here. Setting the SocketUri property will override the production Websocket feed URL that is set by default.

Subscribing to Events over WebSocket

Be sure to check the documentation here to know all the events you can subscribe to. The following example demonstrates how to continue setting up the WebSocket for simple heartbeat events.

//Using authenticated or unauthenticated instance `socket`
//Connect the websocket,
//when this connect method completes, the socket is ready or failure occured.
var result = await socket.ConnectAsync();
if( !result.Success ) throw new Exception("Failed to connect.");

//add an event handler for the message received event on the raw socket
socket.RawSocket.MessageReceived += RawSocket_MessageReceived;

//create a subscription of what to listen to
var sub = new Subscription
   {
      ProductIds =
         {
            "BTC-USD",
         },
      Channels =
         {
            "heartbeat",
         }
   };

//send the subscription upstream
await socket.SubscribeAsync(sub);

//now wait for data.
await Task.Delay(TimeSpan.FromMinutes(1));

snippet source | anchor

Once your subscription is sent upstream, you should start receiving events over the WebSocket. The following example shows how to process incoming messages as they arrive:

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($"Sequence: {hb.Sequence}, Last Trade Id: {hb.LastTradeId}");
      }
   }
}

snippet source | anchor

A complete working example can be found here and here.

If you'd like to use your own WebSocket implementation, the WebSocketHelper is a helpful utility class for creating authenticated JSON subscription messages.


Easy peasy! Happy crypto trading! ๐ŸŽ‰

Reference

Building

  • Download the source code.
  • Run build.cmd.

Upon successful build, the results will be in the \__compile directory. If you want to build NuGet packages, run build.cmd pack and the NuGet packages will be in __package.

Contributors

Created by Brian Chavez.

A big thanks to GitHub and all contributors:


Note: This application/third-party library is not directly supported by Coinbase Inc. Coinbase Inc. makes no claims about this application/third-party library. This application/third-party library is not endorsed or certified by Coinbase Inc.

coinbase.pro's People

Contributors

bchavez avatar devax avatar la4atld avatar lucaswalter avatar msitt avatar nextmove avatar simoncropp avatar vflame avatar vslee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coinbase.pro's Issues

Call failed: An error occured while sending the request get api.pro.coinbase/accounts

Version Information

Software Version(s)
NuGet Package 2.06
.NET Core? 4.5.2
.NET Full Framework?
Windows OS? WIN 10
Linux OS?
Visual Studio?

What's the problem?

I get an error when trying to access the account

The error says Call failed: An error occurred while sending the request get api.pro.coinbase/accounts

I am using the following code:
try
{
client = new CoinbaseProClient(new Config
{
ApiKey = clientForma[0],
Secret = clientForma[1],
Passphrase = clientForma[2],
});
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error: ", MessageBoxButton.OK);
}
try
{
var Account = await client.Accounts.GetAllAccountsAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error: ", MessageBoxButton.OK);
}

I do not receive an error when connecting to the client, but receive an error when accessing the accounts

What possible solutions have you considered?

I tried updating all the nuget packages same error

Do you have sample code to show what you're trying to do?

try
{
client = new CoinbaseProClient(new Config
{
ApiKey = clientForma[0],
Secret = clientForma[1],
Passphrase = clientForma[2],
});
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error: ", MessageBoxButton.OK);
}
try
{
var Account = await client.Accounts.GetAllAccountsAsync();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error: ", MessageBoxButton.OK);
}
(Please be complete. Include any class models necessary to run your code.)

What is the HTTP request JSON and response JSON?

(Use Fiddler to help capture this information)

Parsing Exponential Numbers

Some books return exponential numbers (e.g., "7e-7" for markets like "BCH-BTC") as valid values. Instead of reading as a decimal, it can be read as a string and parsed with decimal.Parse

decimal.Parse("7e-7", System.Globalization.NumberStyles.Any)

Known Newtonsoft.Json issue: JamesNK/Newtonsoft.Json#1711

Unable to use Coinbase.Pro sandbox

Hi,

When fetching the products using the Coinbase.Pro sandbox, I got this error:

Exception non gรฉrรฉeย : Flurl.Http.FlurlParsingException: Response could not be deserialized to JSON: GET https://api-public.sandbox.pro.coinbase.com/products ---> Newtonsoft.Json.JsonSerializationException: Error converting value {null} to type 'System.Decimal'. Path '[0].min_market_funds', line 1, position 250. ---> System.InvalidCastException: Impossible de convertir un objet null en un type valeur.

I could be nice if the sandbox is supported as well !

Cheers,
Christophe

CancelOrderById throws deserialization error

InnerException: {"Error converting value ""830d3571-f86b-4615-87dd-5402a520335d"" to type 'System.Collections.Generic.List`1[System.Guid]'. Path '', line 1, position 38."}
Message: "Response could not be deserialized to JSON: DELETE https://api-public.sandbox.pro.coinbase.com/orders/830d3571-f86b-4615-87dd-5402a520335d"
Source: "Flurl.Http"

support question : how do trap socket exceptions

Just curious if there is a way to trap socket exceptions.
My normal try catch in the ticker_Handlers doesn't seem to stop my program from crashing when I get the following while running in debug:

CoinbasePro.Exceptions.CoinbaseProWebSocketException: 'WebSocket Feed Error: Unable to read data from the transport connection: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. Please check https://status.pro.coinbase.com/ for more details as there may be an outage

Version Information

Software Version(s)
NuGet Package v3.0.5
.NET Core? no
.NET Full Framework? yes
Windows OS? 10
Linux OS? no
Visual Studio? yes 2019 preview

What's the problem?

cant figureout how to handle socket exceptions which cause my application to crash completely

What possible solutions have you considered?

try catch in the ticker and match handlers

Do you have sample code to show what you're trying to do?

Private Sub Websocket_MatchReceived(sender As Object, e As WebSocket.Models.Response.WebfeedEventArgs(Of WebSocket.Models.Response.Match))
Try
catch

(Please be complete. Include any class models necessary to run your code.)

What is the HTTP request JSON and response JSON?

(Use Fiddler to help capture this information)

L2UpdateEvent is missing "Time" -property

Hello and thank you for the great job done with this library!

Coinbase Pro documentation states that l2updates have a time property stating the time of the recorded event.

The library's L2UpdateEvent declaration is following (missing the Time property):

public class L2UpdateEvent : Event
{
	[JsonProperty ("product_id")]
	public string ProductId {
		get;
		set;
	}

	[JsonProperty ("changes", ItemConverterType = typeof(L2UpdateChangeConverter))]
	public List<L2UpdateChange> Changes {
		get;
		set;
	}
}

public class Event : Json
{
	[JsonProperty ("type")]
	public string Type {
		get;
		set;
	}
}

Please let me know if you wish to receive code contributions regarding this issue.

CancelByOrderId exception

Version Information

Software Version(s)
NuGet Package 4.1.2
.NET Core? .net 5
.NET Full Framework?
Windows OS? 10 -1909 18363.1440
Linux OS?
Visual Studio? 2019

What is the expected behavior?

Method CancelOrderById should return the id of the order canceled

What is the actual behavior?

Exception parsing the JSON response. The method appears to be expecting a List to be returned but it's instead getting a single Id

Any possible solutions?

Switch the method to return Guid instead of List and change the JSON deserialization to match

How do you reproduce the issue?

Try to cancel an order by id

Do you have a unit test that can demonstrate the bug?

Can you identify the location in the source code where the problem exists?

CoinBaseProClient.Orders CancelOrderById

If the bug is confirmed, would you be willing to submit a PR?

Yes / No (Help can be provided if you need assistance submitting a PR)

Parsing Nulls

In production data, there are some markets that return with no volume, but are still listed as valid coinbase products. These have null values for the best bid and ask values on the ticker event.

{"type":"ticker","product_id":"ZIL-USDC","price":0,"open_24h":0,"volume_24h":0,"low_24h":0,"high_24h":0,"volume_30d":0,"best_bid":null,"best_ask":null}

This causes a serialization exception.

Newtonsoft.Json.JsonSerializationException: Error converting value {null} to type 'System.Decimal'

Does the socket leak if I don't unsubscribe?

I'm wondering if I need to unsubscribe my socket in addition to unsubscribing my events to prevent leaks.
Take this code for instance:

    protected CoinbaseProWebSocket _socket;
    public TickerFrequencyBasedMetricBase(CoinbaseProWebSocket socket)
    {
        this._socket = socket;
    }

    public async virtual Task InitalizeSubscription()
    {
        var sub = this.GetSubscription();
        //send the subscription upstream
        this._socket.RawSocket.MessageReceived += RawSocket_MessageReceived;
        await this._socket.SubscribeAsync(sub);
    }

Now say I want to implement IDisposable:

    public void Dispose()
    {
            // To Avoid leaking we dispose of the events.
           this._socket.RawSocket.MessageReceived += RawSocket_MessageReceived;
    }

Do I Additionally need to unsubscribe to the subscrition as well:

        var sub = this.GetSubscription();
        this._socket.Unsubscribe(sub);

Also, how does the unsubscribe work, do I have to use an object with the same reference, or does it implement a quality comparer based on the internal json?

Easier Channel Registration

Feature Request:

Fluent Subscription builder for easier channel Registration.

Problem:

The api currently mitigates the responsibility on understanding the API spec to the end user, instead of relying on internal structures to make it easier to register. Take this example I tried using which failed:

    protected Subscription GetDefaultSubscription()
    {
        return new Subscription
        {
            ProductIds = this.SupportedProducts.ToList(),
            Channels = this.GetDefaultChannels()
        };
    }

    private JArray GetDefaultChannels()
    {
        var channels = new JArray
        {
            "level2",
            JObject.FromObject(
            new Channel
            {
                Name = "ticker",
                ProductIds = this.SupportedProducts.ToList()
            }),
            JObject.FromObject(
            new Channel
            {
                Name = "match",
                ProductIds = this.SupportedProducts.ToList()
            })
        };
}

Its really hard to tell here why I couldn't get the matches, and the problem was the fact the the match channel should be called using the name "matches" not "match"

Additional notes

I additionally did another search internal to the project for the term match, there related to obtaining matches. Which could be used as an example.

There are a lot of magic string's being reused in the existing library such as "heartbeat", "matches" that should have a related const file to make it easier for new users to use.

Solution:

Registering for channels might be nicer if we could just do something like this

   //Normally this would be in consts file some where.
  const string BTC_USD_PRODUCT_ID = "BTC-USD";

  var subscription= SubscriptionBuilder.AddCurrencies(BTC_USD_PRODUCT_ID ).AddChannels(ChannelType.Ticker, ChannelType.Matches).Build();

Fills.GetFillsByOrderIdAsync(orderId) returns string for Fill.Size instead of Numeric Type

Version Information

Coinbase.Pro 4.1.2

What is the expected behavior?

Fills should return a Numeric type for Fill.Size

What is the actual behavior?

Fill.Size returns a string

Any possible solutions?

Change the property to a numeric type and parse it from the response.

var fills = _coinbaseProClient.Fills.GetFillsByOrderIdAsync(order.Id).Result.Data;
decimal fillSize = fills.First().Size; // ERROR string != decimal

Websocket issue Unsubscribe

I dont see unit testing.. so I am guessing no one has used this function because it's not right.

  public void Unsubscribe(Subscription subscription)
  {
     /// issue here
     **subscription.ExtraJson.Add("type", JToken.FromObject(MessageType.Unsubscribe));**
     /// I am unsubscribing.. should this be "subscription.ExtraJson.Remove("type" );"

    /// right now its throwing an exception since that subscription already exists


     var json = JsonConvert.SerializeObject(subscription);

     this.RawSocket.Send(json);
  }

CancleOrderById() throw Newtonsoft.Json.JsonSerializationException

Hi!

I get an error when using method Client.Orders.CancleOrderById()

Newtonsoft.Json.JsonSerializationException: 'Error converting value "ac039c99-8bf6-4484-a95b-0d50770c4376" to type 'Coinbase.Pro.Models.JsonResponse'. Path '', line 1, position 38.'

Inner Exception:
ArgumentException: Could not cast or convert from System.String to Coinbase.Pro.Models.JsonResponse.

Simple API calls are refused by target machine

I must be missing something simple, but I'm unable to make even basic API calls out of the box.

Version Information

Software Version(s)
Github Version 4.0.1 build 172
.NET Core 5.0.103
.NET Full Framework? 4.8
Windows OS? 10.0.19041
Visual Studio? 16.8.5

What's the problem?

Unable to make basic API calls. Consistently getting "No connection could be made because the target machine actively refused it"

What possible solutions have you considered?

Ensured all frameworks were up to date. Fresh clone from github. .secrets.txt files in place. Attempted on multiple networks to rule out workplace firewall issues.

Do you have sample code to show what you're trying to do?

Any of the Coinbase.Tests.IntegrationTests, for example
can_create_and_delete_order
Source: GeneralTests.cs line 162
Duration: 4.5 sec

Message:
Flurl.Http.FlurlHttpException : Call failed. An error occurred while sending the request: GET https://api.pro.coinbase.com/time
----> System.Net.Http.HttpRequestException : An error occurred while sending the request.
----> System.Net.WebException : Unable to connect to the remote server

Also in the example program:
Examples\Program.cs:24
Flurl.Http.FlurlHttpException: 'Call failed. No connection could be made because the target machine actively refused it: GET https://api-public.sandbox.pro.coinbase.com/products'

status code 400 (Bad Request): POST https://api.pro.coinbase.com/orders

What's the problem?

Call failed with status code 400 (Bad Request): POST https://api.pro.coinbase.com/orders

Additional information:

  • GET requests for account information work.
  • Here is the code that forms the call: var order2 = await client.Orders.PlaceLimitOrderAsync(side: OrderSide.Sell,
    productId: pStop.Currency, size: dSize, limitPrice: dPriceRound,
    timeInForce: TimeInForce.GoodTillCanceled, postOnly: true, clientOid: orderID);
  • I am using the time api to retrieve the timestamp
  • The json string for body seems to be formed correctly

What am I missing?

What is the HTTP request JSON?

{Method: POST, RequestUri: 'https://api.pro.coinbase.com/orders', Version: 1.1, Content: Flurl.Http.Content.CapturedJsonContent, Headers:
{
CB-ACCESS-KEY: aaaaaaaa
CB-ACCESS-SIGN: aaaaaaaa...
CB-ACCESS-TIMESTAMP: 1621903042
CB-ACCESS-PASSPHRASE: aaaaaaaaa...
User-Agent: Coinbase.Pro/0.0.0
User-Agent: (Coinbase Pro API for .NET; https://github.com/bchavez/Coinbase.Pro)
Content-Type: application/json; charset=utf-8
Content-Length: 178
}}

Body:
{"price":204.93,"size":0.02799028,"time_in_force":"GTC","post_only":true,"client_oid":"91b43f63-0587-461f-b7dd-82b90c87ff80","type":"limit","side":"sell","product_id":"DASH-USD"}

The type or namespace name 'CoinbasePro' could not be found (are you missing a using directive or an assembly reference?))

Version Information

Software Version(s)
NuGet Package current version on nuget , as well as v 2.x
.NET Core? v 3.1 tested
.NET Full Framework? v 4.8 tested
Windows OS? yes
Linux OS? no
Visual Studio? version 2019 16.8.3

What is the expected behavior?

  1. Install nuget package
  2. add using for coinbase and coinbasepro
  3. get going

What is the actual behavior?

I have created a new Project to rebuild my current (working) app entirely. Initially I just wanted to copy my coinbase client code over, as this was the part which does not need a major overhaul.

After createing a new project, installed the nuget packages 'coinbase' and 'coinbasepro' the using directives did not work at all.
I thought it might be a -net targeting issue so I checked the target framework on my old server application -> 4.8. After creating a new fresh project with .net 4.8 I realized that this was not the issue. the behavior is the same.

the same issue appears when creating a new project in visual studio on a second computer.

Steps to reproduce

  1. install nuget package
  2. add usings
  3. ERROR: The type or namespace name 'CoinbasePro' could not be found (are you missing a using directive or an assembly reference?))

Any possible solutions?

?

Error in module OrderSide.Buy

Hi, bChavez,

I have a tiny question and a beginner in C #, anyway during testing with the Coinbase Pro Sandbox and your Coinbase.pro
For the moment I ran into the buy option issues not being accepted:

"Call failed with status code 400 (Bad Request): POST https://api-public.sandbox.pro.coinbase.com/orders"

Code
client.Orders.PlaceLimitOrderAsync(OrderSide.Buy, "BTC-EUR", size: sizeround, limitPrice: limitPriceRound, timeInForce: TimeInForce.GoodTillCanceled);

I assume the API works fine to get Fills & Sell Orders.

Kind Regards,

Cannot connect to webservice feed.

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?

How to get the ticker prices for BTC denominated in USD?

I am really new to WebSockets. The Coinbase Pro API documentation is very sparse and hard to read for newbies such as myself. I tried to go to the link you specified here: https://docs.pro.coinbase.com/?r=1#subscribe but to no avail.

What I want is the realtime(-ish) ticker price of BTC as denominated in USD -- i.e., the BTC-USD exchange rate. I make a new Subscription object in my code thus:

            var sub = new Subscription
            {
                ProductIds =
                {
                    "BTC-USD"
                },
                Channels =
                {
                    "ticker"
                }
            };

Is this not the correct way to do it? I suspect not. I need some help. OK, so let's say I've subscribed it correctly. How do I actually see the ticker prices?

Also, I am confused as just what the level2, heartbeat, and ticker "channels" even are. What is a heartbeat? What is a level2? What is a ticker?

Thanks.

Get all order take very long time

Version Information

Software Version(s)
NuGet Package 4.1.2
.NET Core? 3.1
Windows OS? Windows 10 pro
Visual Studio? Visual Studio 2019

What's the problem?

When I exec the GetAllOrdersAsync() method of the OrderEndpoint, it's take a long time if I don't set the limit less or equal than the number of orders in Coinbase.
If I don't set the limit or set a number greater than the numbers of orders, it's take approximately 40/50 sec.
Else almost instantly.

I try with sandbox api and without, I can get historical rates, take an order, get the current tick rate etc ..
But get all orders don't work in an acceptable time, It freeze my thread

What possible solutions have you considered?

No one for now, I'm trying to find a solution to get around it

Do you have sample code to show what you're trying to do?

My class with my method get all open orders :

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Coinbase.Pro;
using Coinbase.Pro.Models;

namespace CoinbaseTradingBotApp.Class.Entity.CoinbaseUtility
{
    public class CoinbaseProCli
    {
        private CoinbaseProClient cbProClient = null;
        // Default currency
        public string defaultCurrency { get; private set; }
        // Url for sandbox use
        private string sandboxApiUrl = "https://api-public.sandbox.pro.coinbase.com/";

        public CoinbaseProCli(string apiKey, string apiSecret, string passPhrase, 
            string defaultCurrency, bool useSandbox = false)
        {
            //using API Key + Secret authentication
            Coinbase.Pro.Config config = new Coinbase.Pro.Config();
            config.ApiKey = apiKey;
            config.Secret = apiSecret;
            config.Passphrase = passPhrase;
            config.UseTimeApi = false;

            // Use sandbox api ?
            if (useSandbox) config.ApiUrl = this.sandboxApiUrl;

            this.cbProClient = new CoinbaseProClient(config);
            this.defaultCurrency = defaultCurrency;
        }
        
        public async Task<List<Order>> getOpenOrders(int limit = 10)
        {
            List<Order> orders = new List<Order>();

            PagedResponse<Order> lstOrders = await this.cbProClient.Orders.GetAllOrdersAsync();
            orders = lstOrders.Data;

            return orders;
        }
    }
}

I instanciate my object with the apiKey, apiSecret, passphrase, a defaultCurrency (not very important for now), and if I use sandbox, for change the ApiUrl.

I also try with create the URL like you create for get all orders (using Flurl), but don't work too

Have you an idea why I don't make properly, or what cause or what causes this slowness ?

Tell me if you are others questions, I am really blocked by this

Thank you in advance, and please apologize my english please, I'm French :)

Com Server Call results in "The request was aborted: Could not create SSL/TLS secure channel"

Version Information

Software Version(s)
NuGet Package 4.1.2
.NET Core?
.NET Full Framework? 4.71
Windows OS? 10.0.19041
Linux OS? X
Visual Studio? 16.7.532.28833

Note this is in an in-process COM server. The functions work fine when loaded as a dll from a .net application, but when running them from a VBA->COM script, there are issues.

What is the expected behavior?

coinbaseProClient.MarketData.GetProductsAsync(), I should get all of the Products back.

What is the actual behavior?

coinbaseProClient.MarketData.GetProductsAsync() throws an exception "The request was aborted: Could not create SSL/TLS secure channel".

Any possible solutions?

I was able to use the solution from here:
https://stackoverflow.com/questions/2859790/the-request-was-aborted-could-not-create-ssl-tls-secure-channel

// using System.Net;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Use SecurityProtocolType.Ssl3 if needed for compatibility reasons

However, any ssl issues should be handled on the level of the Coinbase.Pro library.

How do you reproduce the issue?

Create a COM server, run GetAllProductsAsync() from a VBA script.

Do you have a unit test that can demonstrate the bug?

No, but I can get you something to reproduce it if need be.

Can you identify the location in the source code where the problem exists?

No.

If the bug is confirmed, would you be willing to submit a PR?

No, this isn't really my expertise.

Retrieving complete price history for a product

Hey y'all!

Not really an issue or question. Just wanted to share an approach I'm taking to retrieve the complete price history for a product (BTC-USD for example).

I have an interactive C# notebook here which demonstrates the approach:

https://github.com/dharmatech/coinbase-pro-bchavez-price-history/blob/master/coinbase-pro-bchavez-price-history.ipynb

Here's a video walkthrough of the notebook:

https://www.youtube.com/watch?v=Xl5vx9XFKyo

If there's a better approach to doing this, feel free to share below.

Thanks!

And thank you @bchavez for the awesome package!

Reference of issue #51

Hello,

I reopen for the #51 issue with more informations (tell me if you want more).

Thank you a lot for this very usefull tool.
I use it with setup

client.EnableFiddlerDebugProxy("http://localhost.:8888");

just before the line

PagedResponse<Order> lstOrders = await this.cbProClient.Orders.GetAllOrdersAsync();

And that's what I see with Fiddler : 36.827 ms of duration

The Fiddler debug screen for get all orders request

Thank you for your time !

Originally posted by @marquito73 in #51 (comment)

Conversion

What's the problem?

I'm trying to use the endpoint for conversion --> response 400
I do have a CoinbasePro account with ETH.

What possible solutions have you considered?

I cant seem to find whats wrong. 400 indicates my parameters are wrong?
Is the format wrong? ID what is that(currency code?), the example I'm looking at is using USDC.
Amount is using datatype decimal, should it have some sort of formating to it ?
The url in the response does not contain any paramters, guessing data is send via the body?
Amount, what currency should this be in ?

Do you have sample code to show what you're trying to do?

FromId: ETH
ToId: BCH
Amount: 10 (also tried with from currency(ETH in this case))

public async Task<Coinbase.Pro.Models.Conversion> Convert(string fromId, string toId, decimal amount)
       {
           //   from:
           //     Currency Id
           //
           //   to:
           //     Currency id
           //
           //   amount:
           //     Amount of from to convert to to
           try
           {
         
               return await client.Conversion.ConvertAsync(fromId, toId, amount);

           }
           catch (Exception ex)
           {
               return null;
           }
       }

What is the HTTP request JSON and response JSON?

Response 400: Call failed with status code 400 (Bad Request): POST https://api.pro.coinbase.com/conversions

Why does subscribe mutate the subscription object

So I decided to look into the subscription methods on the coinbase pro socket to be aware of whether I need to call them from the Dispose method.

I noticed something interesting, that we mutate the options when sending them into the socket.

  public async Task SubscribeAsync(Subscription subscription)
  {
     //...
     //Why do we mutate this instead of creating a Copy?  What happens if someone reuse the same subscription for multiple sockets?
     subscription.ExtraJson.Add("type", JToken.FromObject(MessageType.Subscribe));

     // ...
     this.RawSocket.Send(subJson);
  }

  public void Unsubscribe(Subscription subscription)
  {
     //Is this safe to call if the subscription does not have an unsubscribe token?
     subscription.ExtraJson.Add("type", JToken.FromObject(MessageType.Unsubscribe));

     var json = JsonConvert.SerializeObject(subscription);

     this.RawSocket.Send(json);
  }

Why do we mutate the existing options?
What happens if there is no Unsubscribe JToken to be removed from the subscription?

Before/After are not returned as longs on certain endpoints

Version Information

Software Version(s)
NuGet Package 3.3.0
.NET Core? .NET 5
.NET Full Framework? -
Windows OS? Win 10
Linux OS? -
Visual Studio? 2019

What is the expected behavior?

When calling Client.Orders.GetAllOrdersAsync, the response object should have values set in "After" and "Before" properties.

What is the actual behavior?

The response object has After and Before set to null

Any possible solutions?

Apparently, the endpoint from Coinbase does not return a long value for the orders endpoint. Instead, a DateTime value is returned, that can internally not be parsed to a long value.

How do you reproduce the issue?

Try to fetch more than 100 orders from the API.

Do you have a unit test that can demonstrate the bug?

No.

Can you identify the location in the source code where the problem exists?

Yes. It's in ExtensionsForCoinbaseProClient.GetPagedJsonAsync method, where the Before/After headers are trying to be parsed to a long value.

If the bug is confirmed, would you be willing to submit a PR?

Yes. In fact, I have already tried to fix that locally and succeeded by changing the Before and After properties from long to string.

Unauthorized Response for all Requests

Version Information

Software Version(s)
NuGet Package 4.1.12
.NET Full Framework? 5.0
Windows OS? 10

What's the problem?

I get an unauthorized response for every request with a freshly generated API key.

What possible solutions have you considered?

Using the Sandbox environment.
Creating a new key.
Linking latest Github version.
Adding ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

Do you have sample code to show what you're trying to do?

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var Configuration = config.GetSection("TradingPlatforms:Coinbase");
var cbConf = new Coinbase.Pro.Config()
{
	ApiKey = Configuration.GetValue<string>("ApiKey"),
	Secret = Configuration.GetValue<string>("ApiSecret"),
	Passphrase = Configuration.GetValue<string>("ApiPassphrase"),
	ApiUrl = "https://api-public.sandbox.pro.coinbase.com"
};
var cb = new CoinbaseProClient(cbConf);
(await cb.Orders.GetAllOrdersAsync()).Dump();

(Please be complete. Include any class models necessary to run your code.)

What is the HTTP request JSON and response JSON?

Flurl.Http.FlurlHttpException: Call failed with status code 401 (Unauthorized): GET https://api-public.sandbox.pro.coinbase.com/orders?status=all
   at Flurl.Http.FlurlRequest.HandleExceptionAsync(FlurlCall call, Exception ex, CancellationToken token) in C:\projects\flurl\src\Flurl.Http\FlurlRequest.cs:line 348
   at Flurl.Http.FlurlRequest.SendAsync(HttpMethod verb, HttpContent content, CancellationToken cancellationToken, HttpCompletionOption completionOption) in C:\projects\flurl\src\Flurl.Http\FlurlRequest.cs:line 195
   at Flurl.Http.FlurlRequest.SendAsync(HttpMethod verb, HttpContent content, CancellationToken cancellationToken, HttpCompletionOption completionOption) in C:\projects\flurl\src\Flurl.Http\FlurlRequest.cs:line 201
   at Coinbase.Pro.ExtensionsForCoinbaseProClient.GetPagedJsonAsync[T](IFlurlRequest request, CancellationToken cancellationToken)
   at UserQuery.Main() in C:\Users\poweleit\AppData\Local\Temp\LINQPad6\_ykyykbkq\wpwcee\LINQPadQuery:line 42

(Use Fiddler to help capture this information)

socket.Unsubscribe(sub) not working

I continue receiving heartbeat messages after calling socket.Unsubscribe(sub).

My test code:

var sub = new Subscription
{
ProductIds = { "BTC-USD" },
Channels = { "heartbeat" }
};
socket.Unsubscribe(sub);

I suspect the problem is caused by this unnecessary space character: [EnumMember(Value = "unsubscribe ")]

Would you be able to remove it? It's in file WebSocketObjects.cs.

Thanks!

Security Dependancy Report

Hi, i'm currently using the nugget package in version 4.2.2 (latest stable), this one use dependancy System.Net.Security 4.3.0 who gave me vulnerabilities issues with the following CVE list :

Just upgrade this dependency to System.Net.Security 4.3.2 will resolved this issue. I'll be happy to do a PR myself with the change if nobody disagree with it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.