1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-17 04:46:24 +00:00
CryptoExchange.Net/README.md
Jkorf dcb2fa35af Squashed commit of the following:
commit 1ca93ce870468c7effcc69a05b1675f855598f3e
Author: Jkorf <jankorf91@gmail.com>
Date:   Thu Aug 12 13:44:03 2021 +0200

    Version 4.0.0 release

commit f8cefe72cae8b845aa995d16415f160228f5dfc4
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Aug 9 11:46:50 2021 +0200

    Fix for processing a duplicate message in symbol order book

commit f3573e414f80ea622caadb38f9e020f2eab7c834
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Aug 9 11:36:50 2021 +0200

    Updated version

commit 170a3b5c83cd500f0adb5cf74eaaa9c1a8674a10
Merge: 73a0e2c 0d43f6e
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Aug 9 11:33:59 2021 +0200

    Merge branch 'feature/replace-websocket4net' of https://github.com/JKorf/CryptoExchange.Net into feature/replace-websocket4net

commit 73a0e2cb62f8d51b4b8fe1b29fbf16f07ebf13e0
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Aug 9 11:33:45 2021 +0200

    Fixed processing issue in SymbolOrderBook

commit 0d43f6e14e9b61af9bb3250fd72559a5fbf5300a
Author: Jan Korf <jankorf91@gmail.com>
Date:   Sat Jul 31 14:48:23 2021 +0200

    Updated version

commit 037d765fc73740d2aa2159bce6d57f01d989bdc2
Author: Jan Korf <jankorf91@gmail.com>
Date:   Sat Jul 31 11:14:42 2021 +0200

    Socket fixes

commit 13cf3e27b9e91b252368a5dc799363111eed9148
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Jul 26 09:55:51 2021 +0200

    Updated version

commit 333c6c4207cafbfd09b37743fb36008f87939666
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Jul 26 09:50:35 2021 +0200

    Update CryptoExchangeWebSocketClient.cs

commit ad2b6284b042cfa846e55f8b5f53b2397039dff7
Merge: 64bdcdf 2591cc6
Author: Jan Korf <jankorf91@gmail.com>
Date:   Sun Jul 25 22:44:49 2021 +0200

    Merge branch 'feature/replace-websocket4net' of https://github.com/jkorf/CryptoExchange.Net into feature/replace-websocket4net

commit 64bdcdf087d56b8470baedac1ac86d263ad72490
Author: Jan Korf <jankorf91@gmail.com>
Date:   Sun Jul 25 22:44:03 2021 +0200

    Fix for deadlock

commit 2591cc6782e281595c436ccb4b74a9c7c7f5dc57
Author: Jkorf <jankorf91@gmail.com>
Date:   Thu Jul 15 15:10:08 2021 +0200

    Cleanup

commit b3b6235b6edf0ea1a6437239919666d08c274129
Author: Jkorf <jankorf91@gmail.com>
Date:   Fri Jul 9 16:14:33 2021 +0200

    Updated version

commit 12975fd13f7884382fea608d774b1e0ac384cb70
Author: Jkorf <jankorf91@gmail.com>
Date:   Fri Jul 9 16:12:04 2021 +0200

    Async postfix for order book methods

commit d49d59094e18c83de994a1b591f906f7efe916c5
Author: Jkorf <jankorf91@gmail.com>
Date:   Fri Jul 9 15:47:38 2021 +0200

    Renamed async methods with Async post fixes

commit cbe103930ab90378507780cb150596abcb15eb3f
Author: Jkorf <jankorf91@gmail.com>
Date:   Thu Jul 8 09:29:34 2021 +0200

    Added Book property on SymbolOrderBook

commit ecc101aed11bab73c49fadc93d3ca4607094d92a
Merge: 181f942 a172461
Author: Jan Korf <jankorf91@gmail.com>
Date:   Wed Jul 7 23:38:58 2021 +0200

    Merge branch 'feature/replace-websocket4net' of https://github.com/jkorf/CryptoExchange.Net into feature/replace-websocket4net

commit 181f942e2137ff5dfede5365012e24dfb2f07cf9
Author: Jan Korf <jankorf91@gmail.com>
Date:   Wed Jul 7 23:38:49 2021 +0200

    Added CalculateAverageFillPrice to order book

commit a17246153df463aa881e9808ffb87fa25f144d90
Author: Jkorf <jankorf91@gmail.com>
Date:   Wed Jul 7 13:11:39 2021 +0200

    Updated version

commit c60f138ae846a991662e7544d45845decd25cc10
Author: Jkorf <jankorf91@gmail.com>
Date:   Wed Jul 7 13:05:44 2021 +0200

    Fix not logging responses with LogLevel.Debug

commit 91f168fd25150b3048346bcc6acc549ee3685e50
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Jul 5 10:39:48 2021 +0200

    Added ExchangeHelpers to ReadMe

commit ff6c02e574d3f8a270e2960fdda0222c53457868
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Jul 5 10:34:25 2021 +0200

    Added some helper methods, some code comments

commit 55900a3db938f032436303c2399f41b7a3a5fef1
Merge: 9067a8a 7ab6bb0
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Jul 5 09:24:43 2021 +0200

    Merge branch 'master' into feature/replace-websocket4net

commit 9067a8a82c5d8c1e1f6ba0f2600539efd7f1a122
Author: Jkorf <jankorf91@gmail.com>
Date:   Fri Jul 2 16:03:38 2021 +0200

    Update README.md

commit 0f202d69c7e3db71f66dcfef5673b97f56451a40
Author: Jkorf <jankorf91@gmail.com>
Date:   Fri Jun 25 16:37:06 2021 +0200

    Code comments, added console logger

commit 52160c6dc1bbaca3cc498c49ec0dd71310d5102b
Author: Jkorf <jankorf91@gmail.com>
Date:   Thu Jun 24 16:47:04 2021 +0200

    Added/cleaned up code comments

commit 95771c5c4ae3a74963fea5a01e05559596b1b39d
Author: Jkorf <jankorf91@gmail.com>
Date:   Tue Jun 22 14:22:15 2021 +0200

    Additional info socket connection error

commit 6a90e2316d54d42c0f5b7772d60d4861ff340c5a
Author: Jkorf <jankorf91@gmail.com>
Date:   Thu Jun 17 16:10:43 2021 +0200

    Updated version

commit b138c1050372b5d5fbdc3b2a33d3c09b677a669a
Author: Jkorf <jankorf91@gmail.com>
Date:   Thu Jun 17 16:08:19 2021 +0200

    Fix not receiving OriginalData in output

commit 462f44cf45e1bc7ee333e37ad0a778185d84fa58
Author: Jan Korf <jankorf91@gmail.com>
Date:   Wed Jun 16 22:35:03 2021 +0200

    Fix invalidoperation in order book

commit aa7414321b1297487a5133fa0a7e5ede059a6939
Author: Jan Korf <jankorf91@gmail.com>
Date:   Sun Jun 13 20:56:01 2021 +0200

    logging no data task

commit 22aa5928f5cb11ac5877bc4c606d64550aad3f0c
Author: Jan Korf <jankorf91@gmail.com>
Date:   Tue Jun 8 19:13:18 2021 +0200

    Updated version

commit 1ceb22994a5cdf779de8890e39101956728ab80c
Author: Jan Korf <jankorf91@gmail.com>
Date:   Tue Jun 8 19:11:20 2021 +0200

    Fixed exception on .net framework when creating socket

commit 971cab739dd543de0122c9bc12819f57d4df15e3
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Jun 7 14:41:27 2021 +0200

    Updated unit test packages

commit 216213d5ad0e14c6cd7b8e22131b8b07338bacfc
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon Jun 7 10:46:57 2021 +0200

    Updated version

commit ce2c7ddc182599c5ca9ef0eb64e14906c8b734e1
Merge: b219705 55aa77e
Author: Jan Korf <jankorf91@gmail.com>
Date:   Mon Jun 7 09:29:57 2021 +0200

    Merge pull request #96 from ridicoulous/master

    iexchange client improvements

commit b21970552602eb853a061034a5c223a381e7465b
Author: Jkorf <jankorf91@gmail.com>
Date:   Tue Jun 1 14:55:02 2021 +0200

    Updated version

commit dd2cf84c163920e545ec09e1b0d29ab295f2fbe2
Author: Jkorf <jankorf91@gmail.com>
Date:   Tue Jun 1 14:52:55 2021 +0200

    Added tests for LogLevel null

commit 975003284f53094750ec3d4a608d814a6d70f745
Author: Jkorf <jankorf91@gmail.com>
Date:   Tue Jun 1 14:42:59 2021 +0200

    Made LogLevel nullable in options, moved log formatting to the ILogger implementation

commit 1c1de5651e31e9288b4fd125b0545efbfa9098f7
Merge: 34bf986 e7838ab
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon May 31 10:16:52 2021 +0200

    Merge branch 'feature/replace-websocket4net' of https://github.com/JKorf/CryptoExchange.Net into feature/replace-websocket4net

commit 34bf9867dcd2c2b195079094560351d0db2dac0f
Author: Jkorf <jankorf91@gmail.com>
Date:   Mon May 31 10:16:49 2021 +0200

    fixed some axync issues

commit e7838ab9e8310b4ae02c172f0a764aad8ca8fd4e
Author: Jan Korf <jankorf91@gmail.com>
Date:   Wed May 26 13:46:40 2021 +0200

    Added Discord link to ReadMe

commit 502939f57cf8deac1809c4bd2c63af4acc62bd43
Author: Jan Korf <jankorf91@gmail.com>
Date:   Wed May 26 11:12:59 2021 +0200

    Updated version

commit 92b745ca291259eb246572c8029709b87ddbf2d3
Author: Jan Korf <jankorf91@gmail.com>
Date:   Tue May 25 21:52:47 2021 +0200

    Refactored logging to use ILogger

commit b4904b5e4a239ffb29f00b13a314fea33d45d9cb
Author: Jan Korf <jankorf91@gmail.com>
Date:   Tue May 25 14:07:01 2021 +0200

    Added optional json output, added DataEvent for socket updates

commit 55aa77e92647ccdb00abdb35a7ac84f1317b9742
Author: Artem Kurianov <artemkuryanov@gmail.com>
Date:   Fri May 14 13:11:05 2021 +0000

    added order time

commit efe70445ed13228425278e6f57fb17d4156c12f4
Author: Artem Kurianov <artemkuryanov@gmail.com>
Date:   Fri May 14 13:08:58 2021 +0000

    iexchange client improvements

commit 8f0943f0f0469b42f40334257f0f3ca5e39e3bd9
Author: Jkorf <jankorf91@gmail.com>
Date:   Thu May 6 10:24:33 2021 +0200

    Updated version

commit 17d1e5f71bd1986eea0e8273da070f3615d3e378
Author: Jkorf <jankorf91@gmail.com>
Date:   Thu May 6 10:01:24 2021 +0200

    Added missing configureawaits

commit ed748aa474e0d52a78bc15b9b0aa0a9b4d8dd35e
Author: Jan Korf <jankorf91@gmail.com>
Date:   Fri Apr 30 23:00:07 2021 +0200

    Updated version

commit 1ae545563497889c75ed6183377e759da5beed61
Author: Jan Korf <jankorf91@gmail.com>
Date:   Fri Apr 30 21:00:40 2021 +0200

    Updated socket closing

commit 8243ad60dc64f96ed262ec54cbd6c55553c056be
Author: Jkorf <jankorf91@gmail.com>
Date:   Fri Apr 30 15:48:36 2021 +0200

    Updated version

commit 4299f238f3debc2b1b062eb7cde195a3d64dbdfc
Author: Jan Korf <jankorf91@gmail.com>
Date:   Fri Apr 30 15:44:32 2021 +0200

    Fix for closing socket without timeout task

commit 71f49cfe5142cb70fb651936e74b8eef5b7350d4
Author: Jkorf <jankorf91@gmail.com>
Date:   Fri Apr 30 14:59:10 2021 +0200

    Updated version

commit 5d669068ec0a7241daef383c6867c2e22ec21ed3
Author: Jkorf <jankorf91@gmail.com>
Date:   Fri Apr 30 14:56:15 2021 +0200

    Renaming, cleanup

    handler -> subscription
    socket (SocketConnection) -> socketConnection

commit 0fa13e286060cd3b96b808406434092c0e89e89d
Author: Jkorf <jankorf91@gmail.com>
Date:   Thu Apr 29 16:20:41 2021 +0200

    Initial work replacing Websocket4Net with ClientWebSocket
2021-08-12 13:46:39 +02:00

528 lines
26 KiB
Markdown

# CryptoExchange.Net
![Build status](https://travis-ci.org/JKorf/CryptoExchange.Net.svg?branch=master) ![Nuget version](https://img.shields.io/nuget/v/CryptoExchange.Net.svg) ![Nuget downloads](https://img.shields.io/nuget/dt/CryptoExchange.Net.svg)
CryptoExchange.Net is a base package which can be used to easily implement crypto currency exchange API's in C#. This library offers base classes for creating rest and websocket clients, and includes additional features like an automatically synchronizing order book implementation, error handling and automatic reconnects on websocket connections.
## Implementations
By me:
<table>
<tr>
<td><a href="https://github.com/JKorf/Bittrex.Net"><img src="https://github.com/JKorf/Bittrex.Net/blob/master/Bittrex.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/JKorf/Bittrex.Net">Bittrex</a>
</td>
<td><a href="https://github.com/JKorf/Bitfinex.Net"><img src="https://github.com/JKorf/Bitfinex.Net/blob/master/Bitfinex.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/JKorf/Bitfinex.Net">Bitfinex</a>
</td>
<td><a href="https://github.com/JKorf/CoinEx.Net"><img src="https://github.com/JKorf/CoinEx.Net/blob/master/CoinEx.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/JKorf/CoinEx.Net">CoinEx</a>
</td>
<td><a href="https://github.com/JKorf/Huobi.Net"><img src="https://github.com/JKorf/Huobi.Net/blob/master/Huobi.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/JKorf/Huobi.Net">Huobi</a>
</td>
<td><a href="https://github.com/JKorf/Kucoin.Net"><img src="https://github.com/JKorf/Kucoin.Net/blob/master/Kucoin.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/JKorf/Kucoin.Net">Kucoin</a>
</td>
<td><a href="https://github.com/JKorf/Kraken.Net"><img src="https://github.com/JKorf/Kraken.Net/blob/master/Kraken.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/JKorf/Kraken.Net">Kraken</a>
</td>
</tr>
</table>
By third parties:
<table>
<tr>
<td><a href="https://github.com/Zaliro/Switcheo.Net"><img src="https://github.com/Zaliro/Switcheo.Net/blob/master/Resources/switcheo-coin.png?raw=true"></a>
<br />
<a href="https://github.com/Zaliro/Switcheo.Net">Switcheo</a>
</td>
<td><a href="https://github.com/ridicoulous/LiquidQuoine.Net"><img src="https://github.com/ridicoulous/LiquidQuoine.Net/blob/master/Resources/icon.png?raw=true"></a>
<br />
<a href="https://github.com/ridicoulous/LiquidQuoine.Net">Liquid</a>
</td>
<td><a href="https://github.com/ridicoulous/Bitmex.Net"><img src="https://github.com/ridicoulous/Bitmex.Net/blob/master/Bitmex.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/ridicoulous/Bitmex.Net">Bitmex</a>
</td>
<td><a href="https://github.com/intelligences/HitBTC.Net"><img src="https://github.com/intelligences/HitBTC.Net/blob/master/src/HitBTC.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/intelligences/HitBTC.Net">HitBTC</a>
</td>
<td><a href="https://github.com/EricGarnier/LiveCoin.Net"><img src="https://github.com/EricGarnier/LiveCoin.Net/blob/master/LiveCoin.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/EricGarnier/LiveCoin.Net">LiveCoin</a>
</td>
<td><a href="https://github.com/burakoner/OKEx.Net"><img src="https://github.com/burakoner/OKEx.Net/blob/master/Okex.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/burakoner/OKEx.Net">OKEx</a>
</td>
<td><a href="https://github.com/burakoner/Chiliz.Net"><img src="https://github.com/burakoner/Chiliz.Net/blob/master/Chiliz.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/burakoner/Chiliz.Net">Chiliz</a>
</td>
<td><a href="https://github.com/burakoner/BtcTurk.Net"><img src="https://github.com/burakoner/BtcTurk.Net/blob/master/BtcTurk.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/burakoner/BtcTurk.Net">BtcTurk</a>
</td>
<td><a href="https://github.com/burakoner/Thodex.Net"><img src="https://github.com/burakoner/Thodex.Net/blob/master/Thodex.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/burakoner/Thodex.Net">Thodex</a>
</td>
<td><a href="https://github.com/d-ugarov/Exante.Net"><img src="https://github.com/d-ugarov/Exante.Net/blob/master/Exante.Net/Icon/icon.png?raw=true"></a>
<br />
<a href="https://github.com/d-ugarov/Exante.Net">Exante</a>
</td>
<td><a href="https://github.com/rodrigobelo/wootrade-dotnet"><img src="https://github.com/rodrigobelo/wootrade-dotnet/blob/main/wootrade-dotnet-icon.png?raw=true"></a>
<br />
<a href="https://github.com/rodrigobelo/wootrade-dotnet">Wootrade</a>
</td>
</tr>
</table>
## Discord
A Discord server is available [here](https://discord.gg/MSpeEtSY8t). Feel free to join for discussion and/or questions around the CryptoExchange.Net and implementation libraries.
## Donations
I develop and maintain this package on my own for free in my spare time. Donations are greatly appreciated. If you prefer to donate any other currency please contact me.
**Btc**: 12KwZk3r2Y3JZ2uMULcjqqBvXmpDwjhhQS
**Eth**: 0x069176ca1a4b1d6e0b7901a6bc0dbf3bb0bf5cc2
**Nano**: xrb_1ocs3hbp561ef76eoctjwg85w5ugr8wgimkj8mfhoyqbx4s1pbc74zggw7gs
## Implementation usage
### Clients
The CryptoExchange.Net library offers 2 base clients which should be implemented in each implementation library. The `RestClient` and the `SocketClient`.
**RestClient**
The `RestClient`, as the name suggests, handles requests to the exchange REST API. Typically the `RestClient` implementation name is [ExchangeName]Client. So for the Binance exchange this would be called the `BinanceClient`, and for Bittrex the client type name is `BittrexClient`.
The `RestClient` implementations can be used in either a `using` or with a static instance:
````C#
using (var binanceClient = new BinanceClient())
{
var exchangeInfoResult = binanceClient.Spot.System.GetExchangeInfoAsync();
}
````
or
````C#
var client = new BinanceClient();
var exchangeInfoResult = client.Spot.System.GetExchangeInfoAsync();
````
If you're opting for the `using` syntax, a `HttpClient` should be provided in the client options to prevent each client creating it's own `HttpClient` instance.
Calls made on the `RestClient` will return a `WebCallResult<T>` object which will contain the following properties:
|Property|Description|Available when
|---|---|---|
|`Success`|Whether or not the call was successfully executed.|Always
|`Data`|The data the server sent us as response.| When `Success` is `true`
|`Error`|Details on the error that happened during the call.| When `Success` is `false`
|`OriginalData`|The originally received Json data which was received before being deserialized into an object.| When `OutputOriginalData` is enabled in the client options
|`ResponseStatusCode`|The Http status code received as answer on the request.|Always
|`ResponseHeaders`|The headers received in the response.|Always
The `RestClient` implementation should implement the `IExchangeClient` interface, which offers some basic methods for interacting with an exchange without having to know the implementation.
**SocketClient**
The `SocketClient` can be used to connect to websocket streams offered by the API, and receive callbacks whenever new data is received. `SocketClient` implementations are typically named [ExchangeName]SocketClient, so in case of Binance this would be `BinanceSocketClient`.
To use the `SocketClient` to connect to a stream simply call the `SubscribeXXX` method for the data you're interested in and pass in a delegate for handling updates. For example, to subscribe to the Binance ticker stream call `SubscribeToAllSymbolTickerUpdatesAsync` method:
````C#
var socketClient = new BinanceSocketClient();
var subscribeResult = socketClient.Spot.SubscribeToAllSymbolTickerUpdatesAsync(data => {
// Handle updates received here
});
````
or
````C#
var socketClient = new BinanceSocketClient();
var subscribeResult = socketClient.Spot.SubscribeToAllSymbolTickerUpdatesAsync(HandleData);
private void HandleData(DataEvent<IEnumerable<BinanceTick>> data)
{
// Handle updates received here
}
````
Make sure to check the result of the subscribe call to ensure it was successful. The Subscribe methods will return a `CallResult<UpdateSubscription>` object with the following properties:
|Property|Description|Available when
|---|---|---|
|`Success`|Whether or not the call was successfully executed.|Always
|`Data`|The `UpdateSubscription` object for this stream. This can be used to for listening to connection changed events and unsubscribing | When `Success` is `true`
|`Error`|Details on the error that happened during the subscription. | When `Success` is `false`
To unsubscribe from a stream `Unsubscribe()` method can be used, with the `UpdateSubscription` received in the `SubscribeXXX` call as parameter, or use the `UnsubscribeAll()` method to close all subscriptions:
````C#
// Subscribe
var client = new BinanceSocketClient();
var subResult = client.Spot.SubscribeToOrderBookUpdates("BTCUSDT", data => {});
// Unsubscribe
client.Unsubscribe(subResult.Data);
````
The `SocketClient` handles connection management to the server internally and will close a connection if there are no more subscriptions on that connection.
*[WARNING] Do not use `using` statements in combination with constructing a `SocketClient`. Doing so will dispose the `SocketClient` instance when the subscription is done, which will result in the connection getting closed. Instead assign the socket client to a variable outside of the method scope.*
### Client options
Options for a client can be provided in the constructor or using the static SetDefaultOptions method.
````C#
var client = new BinanceClient(new BinanceClientOptions()
{
});
````
or
````C#
BinanceClient.SetDefaultOptions(new BinanceClientOptions()
{
});
````
When providing options in the constructor the options will only apply for that specific client. When using the `SetDefaultOptions` method the options will be applied to any client created after that call which doesn't have any options provided to it via the constructor. Providing options in the constructor means any options set using the `SetDefaultOptions` method will be reset to default unless overwritten in the provided options.
**Options for all clients**
| Property | Description | Default |
| ----------- | ----------- | ---------|
| `LogWriters`| A list of `ILogger`s to handle log messages. | `new List<ILogger> { new DebugLogger() }` |
| `LogLevel`| The minimum log level before passing messages to the `LogWriters`. Messages with a more verbose level than the one specified here will be ignored. Setting this to `null` will pass all messages to the `LogWriters`.| `LogLevel.Information`
|`OutputOriginalData`|If set to `true` the originally received Json data will be output as well as the deserialized object. For `RestClient` calls the data will be in the `WebCallResult<T>.OriginalData` property, for `SocketClient` subscriptions the data will be available in the `DataEvent<T>.OriginalData` property when receiving an update. | `false`
|`BaseAddress`|The base address to the API. All calls to the API will use this base address as basis for the endpoints. This allows for swapping to test API's or swapping to a different cluster for example.| Depends on implementation
|`ApiCredentials`| The API credentials to use for accessing protected endpoints. Typically a key/secret combination.| `null`
|`Proxy`|The proxy to use for connecting to the API.| `null`
**Options for RestClients**
| Property | Description | Default |
| ----------- | ----------- | ---------|
| `RateLimiters`| A list of `IRateLimiter`s to use.| `new List<IRateLimiter>()` |
| `RateLimitingBehaviour`| What should happen when a rate limit is reached.| `RateLimitingBehaviour.Wait` |
| `RequestTimeout`| The time out to use for requests.| `TimeSpan.FromSeconds(30)` |
| `HttpClient`| The `HttpClient` instance to use for making requests. When creating multiple `RestClient` instances a single `HttpClient` should be provided to prevent each client instance from creating its own. *[WARNING] When providing the `HttpClient` instance in the options both the `RequestTimeout` and `Proxy` client options will be ignored and should be set on the provided `HttpClient` instance.*| `null` |
**Options for SocketClients**
| Property | Description | Default |
| ----------- | ----------- | ---------|
|`AutoReconnect`|Whether or not the socket should automatically reconnect when disconnected.|`true`
|`ReconnectInterval`|The time to wait between connection tries when reconnecting.|`TimeSpan.FromSeconds(5)`
|`SocketResponseTimeout`|The time in which a response is expected on a request before giving a timeout.|`TimeSpan.FromSeconds(10)`
|`SocketNoDataTimeout`|If no data is received after this timespan then assume the connection is dropped. This is mainly used for API's which have some sort of ping/keepalive system. For example; the Bitfinex API will sent a heartbeat message every 15 seconds, so the `SocketNoDataTimeout` could be set to 20 seconds. On API's without such a mechanism this might not work because there just might not be any update while still being fully connected. | `default(TimeSpan)` (no timeout)
|`SocketSubscriptionsCombineTarget`|The amount of subscriptions that should be made on a single socket connection. Not all exchanges support multiple subscriptions on a single socket. Setting this to a higher number increases subscription speed because not every subscription needs to connect to the server, but having more subscriptions on a single connection will also increase the amount of traffic on that single connection, potentially leading to issues.| Depends on implementation
### Order book
The library implementations provide a `SymbolOrderBook` implementation. This implementation can be used to keep an updated order book without having to think about synchronization. This example is from the Binance.Net library, but the implementation is similar for each library:
````C#
var orderBook = new BinanceSymbolOrderBook("BTCUSDT", new BinanceOrderBookOptions(20));
orderBook.OnStatusChange += (oldStatus, newStatus) => Console.WriteLine($"Book state changed from {oldStatus} to {newStatus}");
orderBook.OnOrderBookUpdate += ((changedBids, changedAsks)) => Console.WriteLine("Book updated");
var startResult = await orderBook.StartAsync();
if(!startResult.Success)
{
Console.WriteLine("Error starting order book synchronization: " + startResult.Error);
return;
}
var status = orderBook.Status; // The current status. Note that the order book is only up to date when the status is Synced
var askCount = orderBook.AskCount; // The current number of asks in the book
var bidCount = orderBook.BidCount; // The current number of bids in the book
var asks = orderBook.Asks; // All asks
var bids = orderBook.Bids; // All bids
var bestBid = orderBook.BestBid; // The best bid available in the book
var bestAsk = orderBook.BestAsk; // The best ask available in the book
````
The order book will automatically reconnect when the connection is lost and resync if it detects that it is out of sync. Make sure to check the Status property to see it the book is currently in sync.
To stop synchronizing an order book use the `Stop` method.
## Helper methods
The static `ExchangeHelpers` class offers some helper methods for adjusting value like rounding and adjusting values to fit a certain step size or precision.
## Creating an implementation
Implementations should implement at least the following:
**[Exchange]Client based on the RestClient base class**
Containing calls to the different endpoints, internally using the `SendRequest<T>` method of the `RestClient`.
**[Exchange]SocketClient based on the SocketClient base class**
Containing methods to subscribe to different streams using the `Subscribe<T>` method of the `SocketClient`.
Implement exchange specific handling of requests/messages by overriding these methods:
`HandleQueryResponse`: Check if the data received from the websocket matches the sent query.
`HandleSubscriptionResponse`: Check if the data received from the websocket matches the subscription request.
`MessageMatchesHandler`: Check if the data received from the websocket matches the handler/subscription.
`AuthenticateSocket`: Authenticate the connection to be able to subscribe to protected streams.
`Unsubscribe`: Unsubscribe from a stream, typically by sending an Unsubscribe message.
**[Exchange]SymbolOrderBook based on the SymbolOrderBook base class**
An implementation of an automatically synchronized order book. Implement exchange specific behavior by implementing these methods:
`DoStart`: Start the order book and sync process
`DoResync`: Resync the order book after a reconnection
`DoReset`: Reset the state of the orderbook, called when the connection is lost.
`DoChecksum`: [Optional] Validate the order book with a checksum.
**[Exchange]AuthenticationProvider**
An implementation of the AuthenticationProvider base class. Should contain the logic for authenticating requests from the RestClient on protected endpoints. Override these methods as needed:
`AddAuthenticationToParameters`: Will be called before `AddAuthenticationToHeaders`, allows the implementation to add specific parameters to the request which are needed for protected endpoints.
`AddAuthenticationToHeaders`: Will be called after `AddAuthenticationToParameters`, allows the implementation to add specific headers to the request message.
If you have any issues or questions regarding implementing an exchange using CryptoExchange.Net hop into the Discord or open an issue.
## FAQ
**I sometimes get NullReferenceException, what's wrong?**
You probably don't check the result status of a call and just assume the data is always there. `NullReferenceExecption`s will happen when you have code like this `var symbol = client.GetTickersAync().Result.Data.Symbol` because the `Data` property is null when the call fails. Instead check if the call is successful like this:
````C#
var tickerResult = await client.GetTickersAync();
if(!tickerResult.Success)
{
// Handle error
}
else
{
// Handle data, it is now safe to access the data
var symbol = tickerResult.Data.Symbol;
}
````
**The socket client stops sending updates after a little while**
You probably didn't keep a reference to the socket client and it got disposed.
Instead of subscribing like this:
````C#
private void SomeMethod()
{
var socketClient = new BinanceSocketClient();
socketClient.Spot.SubscribeToOrderBookUpdates("BTCUSDT", data => {
// Handle data
});
}
````
Subscribe like this:
````C#
private BinanceSocketClient _socketClient;
// .. rest of the class
private void SomeMethod()
{
if(_socketClient == null)
_socketClient = new BinanceSocketClient();
_socketClient.Spot.SubscribeToOrderBookUpdates("BTCUSDT", data => {
// Handle data
});
}
````
## Release notes
* Version 4.0.0 - 12 Aug 2020
* Release version, summed up changes from previous beta releases:
* Removed `Websocket4Net` dependency in favor of a `ClientWebSocket` native implementation for websocket connections
* Socket events now always come wrapped in a `DataEvent<>` object which contain the timestamp of the data, and optionally the originally received json string
* Implemented usage of the `Microsoft.Extensions.Logging.Abstractions` `ILogger` interface instead of a custom implementation
* Added some properties to the `IExchangeClient` interface
* `ICommonOrder.CommonOrderTime`
* `ICommonOrder.CommonOrderStatus` enum
* `ICommonTrade.CommonTradeTime`
* Added `OnOrderPlaced` and `OnOrderCanceled` events on the `IExchangeClient` interface
* Added `ExchangeHelpers` static class for various helper methods
* Removed non-async methods due to too much overhead in development/maintainance
* If you were previously using non-async methods you can add `.Result` to the end of the async call to get the same result
* Added `Book` property to `SymbolOrderBook` for a book snapshot
* Added `CalculateAverageFillPrice` to `SymbolOrderBook` to calculate the average fill price for an order with the current order book state
* Various fixes
* Version 4.0.0-beta15 - 12 Aug 2021
* Conditional version Logging.Abstractions
* Version 4.0.0-beta14 - 09 Aug 2021
* Fix for bug in processing order in SymbolOrderBook
* Version 4.0.0-beta13 - 31 Jul 2021
* Fix for socket connection
* Version 4.0.0-beta12 - 26 Jul 2021
* Fix for socket connection
* Version 4.0.0-beta11 - 09 Jul 2021
* Added CalculateAverageFillPrice to SymbolOrderBook
* Added Book property to SymbolOrderBook
* Added Async postfix to async methods
* Version 4.0.0-beta10 - 07 Jul 2021
* Updated BaseConverter to be case sensitive
* Added ExchangeHelpers class containing some helper methods
* Fixed responses not being logged on Trace log level
* Added some code docs
* Version 4.0.0-beta9 - 17 Jun 2021
* Small fixes
* Version 4.0.0-beta8 - 08 Jun 2021
* Fixed exception socket buffer size in .net framework
* Version 4.0.0-beta7 - 07 Jun 2021
* Added CommonOrderTime to IOrder
* Added OrderStatus enum for IOrder
* Added OnOrderPlaced and OnOrderCanceled events on IExchangeClient
* Added CommonTradeTime to ICommonTrade
* Version 4.0.0-beta6 - 01 jun 2021
* Some logging adjustments
* Fixed some async issues
* Version 4.0.0-beta5 - 26 May 2021
* Added DataEvent wrapper for socket updates
* Added optional original json output
* Changed logging implementation to use ILogger
* Version 4.0.0-beta4 - 06 mei 2021
* Added analyzers
* Fixed some warnings
* Version 4.0.0-beta3 - 30 Apr 2021
* Updated socket closing
* Version 4.0.0-beta2 - 30 apr 2021
* Fix for closing socket without timeout task
* Version 4.0.0-beta1 - 30 apr 2021
* Removed Websocket4Net dependency
* Added custom ClientWebSocket implementation
* Renamed handler -> subscription internally
* Renamed socket -> socketConenction when type is socketConnection
* Version 3.9.0 - 28 apr 2021
* Added optional JsonSerializer parameter to SendRequest to use during deserialization
* Fix for unhandled message warning when unsubscribing a socket subscription
* Version 3.8.1 - 19 apr 2021
* Added debug logs
* Added ValidateNullOrNotEmpty extension method
* Version 3.8.0 - 30 mrt 2021
* Better handling of json errors while deserializing stream
* Added string datetime converter
* Version 3.7.1 - 10 mrt 2021
* Performance improvemnt for the ArrayConverter
* Version 3.7.0 - 01 mrt 2021
* Changed GetResponse in RestClient to protected
* Added configuration for deterministic build
* Version 3.6.1 - 16 feb 2021
* Fix for timing related exception when stopping an symbol order book
* Version 3.6.0 - 22 jan 2021
* Added CommonVolume and CommonOpenTime to ICommonKline interface
* Version 3.5.0 - 11 jan 2021
* Additional info on exception messages
* Added support for rate limiting using credits
* Version 3.4.0 - 21 dec 2020
* Updated IExchangeClient interface
* Fix for dropping message after timeout on socket
* Added virtual HandleUnhandledMessage method in SocketClient
* Version 3.3.0 - 10 dec 2020
* Added client name
* Added common interfaces
* Fixed api key plain text storing in RateLimitterApiKey
* Version 3.2.1 - 19 nov 2020
* Fixed error code parsing
* Version 3.2.0 - 19 nov 2020
* Fix for multiple socket subscriptions re-using the same socket connection
* Updated errors
* Version 3.1.0 - 08 Oct 2020
* Added CallResult without type parameter for calls which don't return data
* Added GetErrorOrResult method on CallResult to support proper nullability checking
* Fix for reading credentials from file
* Fix for setting custom base addresses in clients
* Version 3.0.15 - 06 Oct 2020
* Changed default ShouldCheckObjects to false to prevent spam in logging
* Version 3.0.14 - 24 Aug 2020
* Updated exception message logging
* Version 3.0.13 - 24 Aug 2020
* Added request tracing id for logging
* Added shared HttpClient option
* Version 3.0.12 - 12 Aug 2020
* Named parameters on SymbolOrderBook events
* Version 3.0.11 - 20 Jun 2020
* Added support for checksum in SymbolOrderBook
* Version 3.0.10 - 16 Jun 2020
* Fix for order book synchronization
* Version 3.0.9 - 07 Jun 2020
* Added arraySerialization and postParameterPosition to AuthenticationProvider interface
* Fixed array serialization in request body
* Version 3.0.8 - 02 Jun 2020
* Added requestBodyEmptyContent setting for rest client
* Added TryParseError for rest implementations to check for error with success status code
* Version 3.0.7 - 20 May 2020
* Added error debug output
* Fix for unsubscribe causing possible deadlock
* Version 3.0.6 - 03 Mar 2020
* Added BestOffer to SymbolOrderBook, removed invalid check on proxy
* Version 3.0.5 - 05 Feb 2020
* Added PausedActivity events on socket subscriptions
* Version 3.0.4 - 29 Jan 2020
* Removed unnecessary json serialization
* Version 3.0.3 - 23 Jan 2020
* Added OnBestOffersChanged event to order book implementations
* Version 3.0.2 - 10 Dec 2019
* Removed invalid check for unauthenticated proxy
* Version 3.0.1 - 14 Nov 2019
* Re-enabled debug response logging
* Version 3.0.0 - 23 Oct 2019
* Updated to C# 8.0
* Added .NetStandard2.1 support
* Added Nullability support
* Now using HttpClient instead of WebRequest, should result in faster consequtive requests
* Added CancellationToken support
* Added bool compare override to CallResult (now possible to `if(callresult)` instead of `if(callresult.Success)`)
* Added input validation methods
* Wrong input will now throw exceptions rather than error results
* OnOrderBookUpdate event added to `SymbolOrderBook`
* Version 2.1.8 - 29 Aug 2019
* Added array serialization options for implementations
* Version 2.1.7 - 07 Aug 2019
* Fixed bug with socket connection not being disposed after lost connection
* Resubscribing after reconnecting socket now in parallel
* Version 2.1.6 - 06 Aug 2019
* Fix for missing subscription events if they are also a request response, added code docs
* Version 2.1.5 - 09 jul 2019
* Updated SymbolOrderBook
* Version 2.1.4 - 24 jun 2019
* Added checks for json deserialization issues
* Version 2.1.3 - 16 may 2019
* Refactored SymbolOrderBook
* Added BestBid/BestAsk properties for order book
* Version 2.1.2 - 14 may 2019
* Added order book base class for easy implementation
* Added additional constructor to ApiCredentials to be able to read from file