jkorf / cryptoexchange.net Goto Github PK
View Code? Open in Web Editor NEWA C# .netstandard base library used for implementing cryptocurrency exchange API's.
Home Page: https://jkorf.github.io/CryptoExchange.Net/
License: MIT License
A C# .netstandard base library used for implementing cryptocurrency exchange API's.
Home Page: https://jkorf.github.io/CryptoExchange.Net/
License: MIT License
I am developing a SDK for bitmax.io. I have a problem with websocket client. Because bitmax.io ws feed url doesnt end with a slash and It give 404 error if I put slash. But on ClientOptions (CryptoExchange.Net.Objects.ClientOptions) there is a rule for ending with slash.
Is there a way to remove ending slash in BaseAddress?
Working Url: wss://bitmax.io/1/api/pro/v1/stream
Not Working Url: wss://bitmax.io/1/api/pro/v1/stream/
Using the Binance.NET 5.1.14 with CryptoExchange.Net 3.0.14 I get messages such as:
[8] Local object doesn't have property `permissions` expected in type `BinanceAccountInfo`
[8] Local object has property `` but was not found in received object of type `BinanceAccountInfo`
Not exactly sure what is causing them though.
Hi,
I'm trying to implement ftx exchange API, I inspired a lot from the existing implementations and get it almost working.
My problem is about the authenticated requests, I cannot get them, still getting "Server error: Received error from server...:{
"error": "Not logged in",
"success": false
} "
This sample is working fine :
httpClient = new HttpClient
{
BaseAddress = new Uri("https://ftx.com/"),
Timeout = TimeSpan.FromSeconds(30)
};
_hashMaker = new HMACSHA256(Encoding.UTF8.GetBytes("api-secret"));
var account = GetAccountInfoAsync();
public async Task GetAccountInfoAsync()
{
var resultString = $"api/account";
var sign = GenerateSignature(HttpMethod.Get, "/api/account", "");
var result = await CallAsyncSign(HttpMethod.Get, resultString, sign);
return ParseResponce(result);
}
private dynamic ParseResponce(string responce)
{
return (dynamic)responce;
}
private async Task<string> CallAsyncSign(HttpMethod method, string endpoint, string sign, string body = null)
{
var request = new HttpRequestMessage(method, endpoint);
if (body != null)
{
request.Content = new StringContent(body, Encoding.UTF8, "application/json");
}
request.Headers.Add("FTX-KEY", "api-key");
request.Headers.Add("FTX-SIGN", sign);
request.Headers.Add("FTX-TS", _nonce.ToString());
var response = await _httpClient.SendAsync(request).ConfigureAwait(false);
var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return result;
}
private string GenerateSignature(HttpMethod method, string url, string requestBody)
{
_nonce = GetNonce();
var signature = $"{_nonce}{method.ToString().ToUpper()}{url}{requestBody}";
var hash = _hashMaker.ComputeHash(Encoding.UTF8.GetBytes(signature));
var hashStringBase64 = BitConverter.ToString(hash).Replace("-", string.Empty);
return hashStringBase64.ToLower();
}
private readonly HMACSHA256 _hashMaker;
private long _nonce;
private HttpClient _httpClient;
private long GetNonce()
{
return Util.GetMillisecondsFromEpochStart();
}
And my implementation for the FtxAuthenticationProvider cryptoexchange.net is the following:
`internal class FtxAuthenticationProvider : AuthenticationProvider
{
private readonly HMACSHA256 _hashMaker;
private long _nonce;
public FtxAuthenticationProvider(ApiCredentials credentials) : base(credentials)
{
if (credentials.Secret == null)
throw new ArgumentException("No valid API credentials provided. Key/Secret needed.");
string secret = new System.Net.NetworkCredential(string.Empty, Credentials.Secret).Password;
_hashMaker = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
}
public override Dictionary<string, object> AddAuthenticationToParameters(string uri, HttpMethod method, Dictionary<string, object> parameters, bool signed, PostParameters postParameterPosition, ArrayParametersSerialization arraySerialization)
{
//Nothing
return parameters;
}
private string GenerateSignature(HttpMethod method, string url, string requestBody)
{
_nonce = GetNonce();
var signature = $"{_nonce}{method.ToString().ToUpper()}{url}{requestBody}";
var hash = _hashMaker.ComputeHash(Encoding.UTF8.GetBytes(signature));
var hashStringBase64 = BitConverter.ToString(hash).Replace("-", string.Empty);
return hashStringBase64.ToLower();
}
private long GetNonce()
{
return Util.Util.GetMillisecondsFromEpochStart();
}
public override Dictionary<string, string> AddAuthenticationToHeaders(string uri, HttpMethod method, Dictionary<string, object> parameters, bool signed, PostParameters postParameterPosition, ArrayParametersSerialization arraySerialization)
{
if (Credentials.Key == null)
throw new ArgumentException("No valid API credentials provided. Key/Secret needed.");
string key = new System.Net.NetworkCredential(string.Empty, Credentials.Key).Password;
string signature = GenerateSignature(method, uri, "");
return new Dictionary<string, string>
{
{ "FTX-KEY", key },
{ "FTX-SIGN",signature },
{ "FTX-TS",_nonce.ToString() }
};
}
}`
Does someone already realized that or have any idea from where the problem could be ?
Would it be possible to strong sign the release DLL as part of creating the nuget package? I am having to recompile this and sign it myself, before I can load the combined assembly into Microsoft Excel.
I also have to do this for Binance.Net, and will probably need to sign Bitfinex.Net, when I add.
The events returned have a TransactionTime of DateTime.Min
Hi.
How is it that I create a request earlier but send it later? because of this, there is a problem with nonce
2019.10.14 01:07:04:236 | Debug | Creating request for https://btc-trade.com.ua/api/remove/order/88213808
2019.10.14 01:07:04:268 | Debug | Creating request for https://btc-trade.com.ua/api/sell/btc_uah
2019.10.14 01:07:04:314 | Debug | Sending POST signed request to https://btc-trade.com.ua/api/sell/btc_uah with request body count=0.002467&nonce=637066120242682189&out_order_id=330&price=202655.22965311
2019.10.14 01:07:04:580 | Debug | Sending POST signed request to https://btc-trade.com.ua/api/remove/order/88213808 with request body nonce=637066120242362125&out_order_id=612
nonce I only use once
private static long nonce => DateTime.Now.Ticks;
public override Dictionary<string, object> AddAuthenticationToParameters(string uri, string method, Dictionary<string, object> parameters, bool signed)
{
if (!signed)
return parameters;
lock (locker)
{
parameters.Add("out_order_id", new Random().Next(1000));
parameters.Add("nonce", nonce);
}
return parameters = parameters.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
}
public event Action OnOpen
{
add => _openhandlers.Add(value);
remove => _closehandlers.Remove(value);
}
I suppose on remove it should be also _openhandlers
Hello,
thank you for your amazing work on the API wrappers.
I know it's a bit different from exchanges like Binance etc., but do you have any plans on doing a wrapper for the Bitstamp API?
https://www.bitstamp.net/api/
Greetings
Alexander
Hey! I'm wondering if it was done intentionally to keep API key as a plain text in the RateLimiterAPIKey.history dictionary?
It looks like the RateLimiter has the same lifetime as the ApiCredentials having the string unsecure here might be an issue.
My suggestion would be using either hash of the key or SecureString instance as a key.
With the BinanceClient there is a function like:
binanceClient.SetApiCredentials
But with the KuCoin client there is no such option available, only the 'SetDefaultOptions'.
I want to use the kucoinclient for multiple background workers each with a different API connection.
What function can I use to use a similair SetApiCredentials function for KuCoin?
First: Great library! Awesome work!
Is anybody currently working on a Kraken version? If so, need any help?
In the update of 3.0.14, the KUCOIN ordebook stopped working, and Kraken is giving an error in the Orderbook too, I had to go back to version 3.0.12 where everything works normally.
Hi,
I encountered an deserialization error while executing GetOpenPositionsAsync().
The issue is the field "maxNotionalValue" from the "positionRisk" endpoint.
For some reasons binance could return a string value here with the value "inf" (perhaps if the value is infinity).
Here is the json payload where one of the positions contains this value. The other positions have an integer value:
"[{\"symbol\":\"BTCUSDT\",\"positionAmt\":\"0.000\",\"entryPrice\":\"0.00000\",\"markPrice\":\"6129.77693896\",\"unRealizedProfit\":\"0.00000000\",\"liquidationPrice\":\"0\",\"leverage\":\"10\",\"maxNotionalValue\":\"20000000\",\"marginType\":\"isolated\",\"isolatedMargin\":\"0.00000000\",\"isAutoAddMargin\":\"false\",\"positionSide\":\"BOTH\"},{\"symbol\":\"XRPUSDT\",\"positionAmt\":\"0.0\",\"entryPrice\":\"0.00000\",\"markPrice\":\"0.17314956\",\"unRealizedProfit\":\"0.00000000\",\"liquidationPrice\":\"0\",\"leverage\":\"20\",\"maxNotionalValue\":\"250000\",\"marginType\":\"cross\",\"isolatedMargin\":\"0.00000000\",\"isAutoAddMargin\":\"false\",\"positionSide\":\"BOTH\"},{\"symbol\":\"EOSUSDT\",\"positionAmt\":\"0.0\",\"entryPrice\":\"0.0000\",\"markPrice\":\"2.17963976\",\"unRealizedProfit\":\"0.00000000\",\"liquidationPrice\":\"0\",\"leverage\":\"10\",\"maxNotionalValue\":\"1000000\",\"marginType\":\"isolated\",\"isolatedMargin\":\"0.00000000\",\"isAutoAddMargin\":\"false\",\"positionSide\":\"BOTH\"},{\"sy mbol\":\"LTCUSDT\",\"positionAmt\":\"0.000\",\"entryPrice\":\"0.00000\",\"markPrice\":\"38.36273888\",\"unRealizedProfit\":\"0.00000000\",\"liquidationPrice\":\"0\",\"leverage\":\"2\",\"maxNotionalValue\":\"inf\",\"marginType\":\"isolated\",\"isolatedMargin\":\"0.00000000\",\"isAutoAddMargin\":\"false\",\"positionSide\":\"BOTH\"},{\"symbol\":\"TRXUSDT\",\"positionAmt\":\"50\",\"entryPrice\":\"0.01111\",\"markPrice\":\"0.01111154\",\"unRealizedProfit\":\"0.00007700\",\"liquidationPrice\":\"0.01007\",\"leverage\":\"10\",\"maxNotionalValue\":\"1000000\",\"marginType\":\"isolated\",\"isolatedMargin\":\"0.05540480\",\"isAutoAddMargin\":\"false\",\"positionSide\":\"BOTH\"},{\"symbol\":\"ADAUSDT\",\"positionAmt\":\"0\",\"entryPrice\":\"0.00000\",\"markPrice\":\"0.02927060\",\"unRealizedProfit\":\"0.00000000\",\"liquidationPrice\":\"0\",\"leverage\":\"10\",\"maxNotionalValue\":\"1000000\",\"marginType\":\"isolated\",\"isolatedMargin\":\"0.00000000\",\"isAutoAddMargin\":\"false\",\"positionSide\":\"BOTH\"},{\"symbol\": \"BATUSDT\",\"positionAmt\":\"0.0\",\"entryPrice\":\"0.00000\",\"markPrice\":\"0.13558396\",\"unRealizedProfit\":\"0.00000000\",\"liquidationPrice\":\"0\",\"leverage\":\"10\",\"maxNotionalValue\":\"100000\",\"marginType\":\"isolated\",\"isolatedMargin\":\"0.00000000\",\"isAutoAddMargin\":\"false\",\"positionSide\":\"BOTH\"}]"
I fixed the issue in my version by changing the property "MaxNotionalValue" from decimal to string
EDIT:
This issue occurs in the method "ChangeMarginTypeAsync()" too, because the result type contains the "MaxNotionalValue" as well. A change to string fix that.
Hi,
In SocketConnection
, when a message is not handled, it produce an entry in the log: https://github.com/JKorf/CryptoExchange.Net/blob/master/CryptoExchange.Net/Sockets/SocketConnection.cs#L163
if (!HandleData(tokenData) && !handledResponse)
{
log.Write(LogVerbosity.Debug, "Message not handled: " + tokenData);
}
I would like to have a more elaborate handling. Typically log as an error, not debug, and expand the message, as message in my case are json wrapper around base64 encoded binary format.
Is is possible to have either an event or a protected method in SocketClient
for this?
Can you imagine a better way to achieve this result?
Thanks.
Eric
Using the OkEx wrapper (from here) built on top of this library, I observe very high CPU usage when subscribed to updates for relatively few order books (~20, while OkEx has hundreds of instruments available). This really limits the scalability of any system using this library for handling a large number of messages.
Profiling shows that over half our market data recorder's total CPU time is spent inside ArrayConverter.ParseObject(), and mostly calling System.Attribute.GetCustomAttributes() (see highlighted line in below screenshot).
Custom attributes do not change at runtime, hence a cache is likely to hugely improve performance here. I'll have a go at it.
First of all I would like to thank you for this amazing project.
I try to fetch all the orderbooks for different exchanges using SymbolOrderBook. In order to achieve that, I get all the symbols for an exchange and for each of them I do a SymbolOrderBook.StartAsync().
I keep getting a "Can't connect to the server" error message which I don't get when I try to retrieve retrieve a small number (10) of SymbolOrderBook. In the output window of VS I start getting messages for sockets closed.
Let me know if you need any more information or have any suggestion/solution.
If my internet connection goes down, after a while i can get data from client socket. But when i check logs, i see that it tries to reconnect all the time even i can get data.
Here is the log after i get connected :
2020.12.10 23:37:40.3886 : Binance - 2020.12.10 23:37:40:388 | Info | Socket 27 reconnected after 00:00:06.0993857
2020.12.10 23:37:44.8641 : Binance - 2020.12.10 23:37:44:864 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:37:45.1965 : Binance - 2020.12.10 23:37:45:196 | Info | Socket 1 Connection lost, will try to reconnect after 00:00:05
2020.12.10 23:37:45.8805 : Binance - 2020.12.10 23:37:45:880 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:37:45.9036 : Binance - 2020.12.10 23:37:45:903 | Info | Socket 7 reconnected after 00:00:06.1142623
2020.12.10 23:37:46.2538 : Binance - 2020.12.10 23:37:46:253 | Info | Socket 5 Connection lost, will try to reconnect after 00:00:05
2020.12.10 23:37:50.9244 : Binance - 2020.12.10 23:37:50:924 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:37:51.2017 : Binance - 2020.12.10 23:37:51:201 | Info | Socket 2 Connection lost, will try to reconnect after 00:00:05
2020.12.10 23:37:51.3551 : Binance - 2020.12.10 23:37:51:355 | Info | Socket 1 reconnected after 00:00:06.1586506
2020.12.10 23:37:52.4126 : Binance - 2020.12.10 23:37:52:412 | Info | Socket 5 reconnected after 00:00:06.1587551
2020.12.10 23:37:55.6912 : Binance - 2020.12.10 23:37:55:691 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:37:56.0367 : Binance - 2020.12.10 23:37:56:036 | Info | Socket 26 Connection lost, will try to reconnect after 00:00:05
2020.12.10 23:37:57.1593 : Binance - 2020.12.10 23:37:57:159 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:37:57.3122 : Binance - 2020.12.10 23:37:57:312 | Info | Socket 2 reconnected after 00:00:06.1104772
2020.12.10 23:37:57.4667 : Binance - 2020.12.10 23:37:57:466 | Info | Socket 3 Connection lost, will try to reconnect after 00:00:05
2020.12.10 23:38:00.4735 : Binance - 2020.12.10 23:38:00:473 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:38:00.7467 : Binance - 2020.12.10 23:38:00:746 | Info | Socket 6 Connection lost, will try to reconnect after 00:00:05
2020.12.10 23:38:02.2421 : Binance - 2020.12.10 23:38:02:242 | Info | Socket 26 reconnected after 00:00:06.2054164
2020.12.10 23:38:03.6086 : Binance - 2020.12.10 23:38:03:608 | Info | Socket 3 reconnected after 00:00:06.1419027
2020.12.10 23:38:06.0329 : Binance - 2020.12.10 23:38:06:032 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:38:06.4585 : Binance - 2020.12.10 23:38:06:458 | Info | Socket 7 Connection lost, will try to reconnect after 00:00:05
2020.12.10 23:38:06.8372 : Binance - 2020.12.10 23:38:06:837 | Info | Socket 6 reconnected after 00:00:06.0904978
2020.12.10 23:38:12.5472 : Binance - 2020.12.10 23:38:12:547 | Info | Socket 7 reconnected after 00:00:06.0886499
2020.12.10 23:38:12.5962 : Binance - 2020.12.10 23:38:12:596 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:38:12.9971 : Binance - 2020.12.10 23:38:12:997 | Info | Socket 5 Connection lost, will try to reconnect after 00:00:05
2020.12.10 23:38:19.1650 : Binance - 2020.12.10 23:38:19:165 | Info | Socket 5 reconnected after 00:00:06.1680516
2020.12.10 23:38:22.7089 : Binance - 2020.12.10 23:38:22:708 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:38:22.7782 : Binance - 2020.12.10 23:38:22:778 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:38:22.9988 : Binance - 2020.12.10 23:38:22:998 | Info | Socket 26 Connection lost, will try to reconnect after 00:00:05
2020.12.10 23:38:23.0680 : Binance - 2020.12.10 23:38:23:068 | Info | Socket 1 Connection lost, will try to reconnect after 00:00:05
2020.12.10 23:38:23.8011 : Binance - 2020.12.10 23:38:23:800 | Warning | No data received for 00:00:20, reconnecting socket
2020.12.10 23:38:24.1686 : Binance - 2020.12.10 23:38:24:168 | Info | Socket 3 Connection lost, will try to reconnect after 00:00:05
Hi, anyone is planning to bring Bybit on board?
Hi,
I need to create custom POST responce instead of SendRequest with both PostParameters.InUri and PostParameters.Post parameters. I can use ConstructRequest and WriteParamBody, However, it will be nice to move RestClient.GetResponse to protected to use it after ConstructRequest
Thanks
Code (this is basicly from the examples):
KrakenSymbolOrderBook orderBook = new KrakenSymbolOrderBook("XXBTZEUR", 1, new KrakenOrderBookOptions(20));
Gives an error message:
CS1503 Argument 1: cannot convert from 'int' to 'Kraken.Net.Interfaces.IKrakenSocketClient'
When i change it like this:
var client = new KrakenSocketClient(options);
KrakenSymbolOrderBook orderBook = new KrakenSymbolOrderBook("XXBTZEUR", 1, new KrakenOrderBookOptions(client));
The error is gone But now when connecting using the following:
var startResult = await orderBook.StartAsync();
if (!startResult.Success)
{
Console.WriteLine("Error starting order book synchronization: " + startResult.Error);
return;
}
It stops, because startResult.Error is:
{3: Server error: Subscription depth not supported}
Which makes sense because a client is not a depth :)
Is this an issue, or a user error ?
hi there,
lately i am getting lots of messages like this:
| Warning | Price duplication detected
where this warning is fired. trying to clean the orderbook and refetch the complete orderbook if something like this is happening.
kind regards
Hi! Awesome library! Maybe create Abstractions project with all interfaces to easy register in IOC?
Hey.
How can I write logs (log.Write(LogVerbosity.Debug, message);
) to a file?
System.AggregateException: One or more errors occurred. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at CryptoExchange.Net.Sockets.BaseSocket.b__72_0()
at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at CryptoExchange.Net.Sockets.BaseSocket.d__72.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at CryptoExchange.Net.Sockets.SocketConnection.d__57.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at CryptoExchange.Net.SocketClient.<b__59_1>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
at CryptoExchange.Net.SocketClient.d__59.MoveNext()
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait()
at CryptoExchange.Net.SocketClient.Dispose()
Hi again,
do we have a public list of projects where CryptoExchange is used?
Have you already thought about building a community? (discord, telegram, or other?)
On a socket client, when a request time out, the next message is not properly processed.
To reproduce, the scenario is the following.
SocketConnection
send a request with SendAndWait
. This add a PendingRequest
to the pendingRequests
list, and return a pending.Event.WaitOneAsync(timeout)
var pending = new PendingRequest(handler, timeout);
pendingRequests.Add(pending);
Send(obj);
return pending.Event.WaitOneAsync(timeout);
the server never respond, so the pending.Event.WaitOneAsync(timeout)
return, and the normal processing continue. But the PendingRequest
is still in the pendingRequests
list;
the server send an unrelated message. This message is passed to the Check
method of the PendingRequest
still in the pendingRequests
list. This method detects the timeout condition, and return true.
if (DateTime.UtcNow - startTime > Timeout)
{
// Timed out
Event.Set();
return true;
}
the controlling loop in ProcessMessage
break, and stop processing the message. It is lost.
foreach (var pendingRequest in pendingRequests.ToList())
{
if (pendingRequest.Check(tokenData))
{
pendingRequests.Remove(pendingRequest);
if (!socketClient.ContinueOnQueryResponse)
return;
handledResponse = true;
break;
I will try to propose a fix for this. #72
Eric
Is the hedge mode (Binance API update of 2020-5-18) supported?
they added a new field to:
POST /fapi/v1/order
POST /fapi/v1/batchOrders
GET /fapi/v1/order
DELETE /fapi/v1/order
DELETE /fapi/v1/batchOrders
GET /fapi/v1/openOrder
GET /fapi/v1/openOrders
GET /fapi/v1/allOrders
so that we can hold several independent positions on the same instruments, and close them independently.
Hi,
Im trying to maintain a synchronized orderbook using the SocketClient provided in your API wrapper however there is no Nonce information in KrakenStreamOrderBook or KrakenOrderBook and no clear indication on how this might work without one. I cannot find any documentation on the Kraken API FAQs etc that help. Have you got this working and if so could you please provide a little information on the flow or point me at existing documentation that might help.
Good work with the .Net wrappers I am already using your Binance and Bittrex offerings. Once my application is up and running I will make a donation.
Many thanks
Ben
Hi there!
I am an avid consumer of both CryptoExchange.NET and the derivative projects. I first would like to say that I enjoy using them and appreciate the work very much.
My app depends on several of them. I understand that you maintain most implementations, but some, such as OKEx.NET depend on CryptoExchange.Net.
As you are no doubt aware, there were breaking changes from NuGet package version 3.0.5
to version 3.0.14
. Might I suggest that API-breaking changes result in an increment of the major number in the NuGet package?
Also, while we are on the topic of versioning, .NET ambiguously allows NuGet package versions to differ from assembly versions. Please can you also enforce semantic versioning of the assembly version? It does not appear to be set by default, and is 1.0.0.0
across multiple, incompatible versions.
This is exactly the type of thing I'm looking for, spent all day trying to get an API working.
You must of spent hours writing this code, and I would LOVE to donate, but it seems you don't want anyone to use your code unless they are professional programmers.
I as a trader would of donated, but you havent even spent an hour putting up a video on how to get started or anything.
Hi @JKorf ,
Is is possible to add an extra rate limiter option for Api Key? It's more important than Total or EndPoint in Huobi.
Have a nice day
Hello - I am trying to use KrakenSymbolOrderBook (see code below).
The problem is, that "ob.LastSequenceNumber" is not changing (in fact, I can see that I have a data flow of around 20kByte/s into my app, but no data gets updatet in the "ob" object).
In main, I am doing this:
var api = new Kraken(
"...",
"..."
);
api.subscribe( "ETH/EUR" );
What is going on? - Am I using your class in a wrong way?
Please help me and point out my error - or have I found a bug?
Many thanks in advance,
Andreas Pfeil
Kraken.cs:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
// https://github.com/JKorf/Kraken.Net
// Install-Package KrakenExchange.Net
using Kraken.Net;
using CryptoExchange.Net.Authentication;
namespace KrakenLink {
class Kraken {
KrakenClient rest;
KrakenSocketClient ws;
public Kraken( string key, string secret ) {
rest = new KrakenClient( new KrakenClientOptions {
ApiCredentials = new ApiCredentials( key, secret )
} );
if( rest.Ping().Success ) {
Console.WriteLine( $"Connected to Kraken Server at: {rest.GetServerTime().Data}" );
ws = new KrakenSocketClient( new KrakenSocketClientOptions {
ApiCredentials = new ApiCredentials( key, secret )
} );
return;
}
rest = null;
ws = null;
throw new Exception();
}
public async Task<bool> subscribe( string pair, int limit = 100 ) {
if( ws == null ) return false;
var ob = new KrakenSymbolOrderBook( pair, limit, new KrakenOrderBookOptions( ws ) );
ob.OnStatusChange += ( oldStatus, newStatus ) => Console.WriteLine( $"Book state changed from {oldStatus} to {newStatus}" );
ob.OnOrderBookUpdate += ( changedBids ) => Console.WriteLine( "Book updated" );
ob.OnBestOffersChanged += ( changedOfferes ) => {
Console.WriteLine( changedOfferes.BestAsk.Price + " " + changedOfferes.BestAsk.Quantity );
Console.WriteLine( changedOfferes.BestBid.Price + " " + changedOfferes.BestBid.Quantity );
};
var startResult = await ob.StartAsync();
if( !startResult.Success ) {
Console.WriteLine( "Error starting order book synchronization: " + startResult.Error );
return false;
}
// I do not get any new data updates...
while( true ) {
Console.WriteLine( ob.LastSequenceNumber );
System.Threading.Thread.Sleep( 500 );
}
return true;
}
}
}
Hi,
I have been using SymbolOrderBook cache to maintain a local order book but Im getting exceptions like the one below...
2020/02/10 10:01:12:320 | Info | Socket 133 error: Microsoft.AspNet.SignalR.Client.Infrastructure.SlowCallbackException: Possible deadlock detected. A callback registered with "HubProxy.On" or "Connection.Received" has been executing for at least 10 seconds.
Im starting a little digging of my own but wanted to know if this is something you have seen or are working on?
Thanks
Ben
Hi,
I'm curious about this line:
What would happen when one of those subscriptions is Binance User Data Stream? I'm asking because for that subscription you have to first obtain a listen key (string) via REST request and the listen key is valid only 60 minutes. I guess that if connection is lost at minute 61, then re-subscription must fail and it can never succeed, right? Will current implementation lead to infinite re-connecting or am I missing something?
We are developping a websocket api for Livecoin.net marketplace.
The messages are based on google's protocol buffer messages : https://developers.google.com/protocol-buffers
Are there any plans to integrate protocol buffer messages as part of CryptoExchange.net ?
What would be the best route for this implementation (based on CryptoExchange.net)
Hi
I would use the CryptoExchange.Net.Authentication.ApiCredentials with file json list:
{ "binanceKey":"actualBinanceApiKey", "binanceSecret":"actualBinanceApiSecret", "bittrexKey":"actualBittrexApiKey", "bittrexSecret":"actualBittrexApiSecret" }
but he tells me that an invalid json format. I debug the
using var reader = new StreamReader(inputStream, Encoding.ASCII, false, 512, true);
var stringData = reader.ReadToEnd(); <--- the stringdata conatains three ??? at first signs
var jsonData = stringData.ToJToken();
Using default value for WebRequest can cause for the requests to never complete.
Can you use some standard timeout value when creating the request?
It looks like this commit 47a1e0b breaks https://github.com/JKorf/Binance.Net/blob/5231d56006c1c26a107cbf9f3f6bf5302cb476a0/Binance.Net/BinanceClient.cs#L264.
Hi,
during the development of LiveCoin.NET, I needed to return a value from the subscribe call. This is du to the API design of LiveCoin.
So I created this type UpdateSubscription< T >
public class UpdateSubscription<T> : CryptoExchange.Net.Sockets.UpdateSubscription where T : class
with a property
/// <summary>
/// Server answer
/// </summary>
public T? SubscriptionResponse { get; set; }
Maybe it would be a good idea to move this in CryptoExchange.Net.
Have a look here : https://github.com/EricGarnier/LiveCoin.Net/blob/master/LiveCoin.Net/Sockets/UpdateSubscription.cs
Thanks.
Eric
The mentioned endpoints are currently not working because the library calls them with a GET request but this are POST endpoints. Change this line:
return await SendRequest<BinanceFuturesChangeMarginTypeResult>(GetUrl(ChangeMarginTypeEndpoint, Api, SignedVersion), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false);
return await SendRequest<BinanceFuturesInitialLeverageChangeResult>(GetUrl(ChangeInitialLeverageEndpoint, Api, SignedVersion), HttpMethod.Get, ct, parameters, true).ConfigureAwait(false);
to
return await SendRequest<BinanceFuturesChangeMarginTypeResult>(GetUrl(ChangeMarginTypeEndpoint, Api, SignedVersion), HttpMethod.Post, ct, parameters, true).ConfigureAwait(false);
return await SendRequest<BinanceFuturesInitialLeverageChangeResult>(GetUrl(ChangeInitialLeverageEndpoint, Api, SignedVersion), HttpMethod.Post, ct, parameters, true).ConfigureAwait(false);
and it works!
Encountered while working with Binance.Net 5.0.7 Nuget package, but the problem is within CryptoExchange.Net, thus submitting to CryptoExchange.Net issues.
Same problem with the lastest version cloned from master branch.
ApiProxy ctor requires host parameter to start with "http". From ApiProxy.cs:
if (!host.StartsWith("http")) throw new ArgumentException("Proxy host should start with either http:// or https://");
It works fine for BinanceClient, but BinanceSocketClient attempts to DNS resolve this host value (starting with "http") and fails since "http://x.x.x.x" is not a valid host name.
Either ApiProxy shouldn't require host to start with "http" or BinanceSocketClient should properly chop protocol prefix from specified host value.
My current workaround is to add a fake host name to hosts file which starts with "http" and is resolved to HTTP proxy's IP.
Following your example at CryptoExchange.Net the following code does not work:
using Kraken.Net;
using CryptoExchange.Net;
using CryptoExchange.Net.Authentication;
KrakenClient.SetDefaultOptions(new KrakenClientOptions
{
ApiCredentials = new ApiCredentials("apiKey", "apiSecret")
});
SetDefaultOptions is not available or missing.
Thanks for this nice API wrapper, love your work thus far.
parameters.AddOptionalParameter("startAt", startTime.HasValue ? JsonConvert.SerializeObject(startTime, new TimestampSecondsConverter()) : null);
parameters.AddOptionalParameter("endAt", startTime.HasValue ? JsonConvert.SerializeObject(endTime, new TimestampSecondsConverter()) : null);
Hi, KuCoin wants Unix time in milliseconds, not seconds.
When i try to use:
var startResult = await orderBook.StartAsync();
i get an error: "CS4033 The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'. "
It seems that the KrakenSymbolOrderBook.StartAsync() method is not async.
Describe the bug
2021/02/17 11:46:02:124 | Binance | Debug | [3] Sending POST signed request to https://api.binance.com/sapi/v1/margin/order with request body isIsolated=True&price=55000&quantity=0.000181&recvWindow=5000&side=SELL&signature=XXX&symbol=BTCUSDT×tamp=1613562362923&type=LIMIT
2021/02/17 11:46:02:423 | Binance | Debug | [3] Error received: {"code":-1102,"msg":"A mandatory parameter was not sent, was empty/null, or malformed."}
Hey. There are some questions.
client.AddRateLimiter() a limit on the number of requests? for example, for Binance I need to declare it as a client.AddRateLimiter(new RateLimiterTotal (20, TimeSpan.FromSeconds (1))) ?
And if that's all right, can you add an event to the number of requests executed per second?
you can add to client.Ping() ping time. For example client.Ping(out int ping)
I'm trying to update CryptoExchange.Net to v0.0.36 but I can't. Because dependencies cannot be resolved. "CryptoExchange.Net 0.0.36" not compatible with Binance.Net 3.1.15 limitation: CryptoExchange.Net (=0.0.31). Is it supposed to?
Hi @JKorf,
I'm getting the following error (using screenshot since I can't copy/paste in this case):
I'm using Binance.Net 4.09 & Bittrex.Net 3.0.7
Hello there,
I hope you are well,
I am dealing with a marketdata issue using KrakenSymbolOrderBook
.
I found a significant discrepancy between the Spread.bid & ask and the OrderBook BestAsk & BestBid.
The spread is relevant with the true kraken bid-ask marketdata, unfortunatly the Orderbook is not.
Here is an example :
KrakenSocketClient KrakenSocketClient = new KrakenSocketClient();
await KrakenSocketClient.SubscribeToSpreadUpdatesAsync("BTC/EUR", data => spread = data.Data);
var orderBook = new KrakenSymbolOrderBook("BTC/EUR", 100);
orderBook.OnStatusChange += (oldStatus, newStatus) => Console.WriteLine($"Book state changed from {oldStatus} to {newStatus}");
await orderBook.StartAsync();
while (true) {
var bestBid = orderBook.BestBid;
var bestAsk = orderBook.BestAsk;
Console.WriteLine(DateTime.UtcNow + "Spread Ask=" + spread.Ask + " Bid=" + spread.Bid);
Console.WriteLine(DateTime.UtcNow + "OrderBook Ask=" + bestAsk.Price + " Bid=" + bestBid.Price);
Console.WriteLine(DateTime.UtcNow + "Diff " + (spread.Ask - bestAsk.Price) + " Bid=" + (spread.Bid-bestBid.Price));
if (bestAsk.Price < bestBid.Price) {
Console.WriteLine(DateTime.UtcNow + " ERROR orderBook Crossed Ask=" + bestAsk.Price + " Bid=" + bestBid.Price);
}
}
Your help would be welcome :)
Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.