1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-08 16:36:15 +00:00
This commit is contained in:
Jkorf 2022-01-17 13:44:45 +01:00
parent e51b863242
commit b65669659d
9 changed files with 83 additions and 38 deletions

View File

@ -1,3 +1,8 @@
---
title: General usage
nav_order: 2
---
Each implementation generally provides two different clients, which will be the access point for the API's. First of the rest client, which is typically available via [ExchangeName]Client, and a socket client, which is generally named [ExchangeName]SocketClient. For example `BinanceClient` and `BinanceSocketClient`. Each implementation generally provides two different clients, which will be the access point for the API's. First of the rest client, which is typically available via [ExchangeName]Client, and a socket client, which is generally named [ExchangeName]SocketClient. For example `BinanceClient` and `BinanceSocketClient`.
## Rest client ## Rest client
@ -15,10 +20,10 @@ The rest client gives access to the Rest endpoint of the API. Rest endpoints are
This rest client has 2 different API clients, the `SpotApi` and the `FuturesApi`, each offering their own set of endpoints. This rest client has 2 different API clients, the `SpotApi` and the `FuturesApi`, each offering their own set of endpoints.
*Requesting ticker info on the spot API* *Requesting ticker info on the spot API*
````C# ```csharp
var client = new KucoinClient(); var client = new KucoinClient();
var tickersResult = kucoinClient.SpotApi.ExchangeData.GetTickersAsync(); var tickersResult = kucoinClient.SpotApi.ExchangeData.GetTickersAsync();
```` ```
Structuring the client like this should make it easier to find endpoints and allows for separate options and functionality for different API clients. For example, some API's have totally separate API's for futures, with different base addresses and different API credentials, while other API's have implemented this in the same API. Either way, this structure can facilitate a similar interface. Structuring the client like this should make it easier to find endpoints and allows for separate options and functionality for different API clients. For example, some API's have totally separate API's for futures, with different base addresses and different API credentials, while other API's have implemented this in the same API. Either way, this structure can facilitate a similar interface.
@ -46,7 +51,7 @@ Each request will return a WebCallResult<T> with the following properties:
When processing the result of a call it should always be checked for success. Not doing so will result in `NullReference` exceptions. When processing the result of a call it should always be checked for success. Not doing so will result in `NullReference` exceptions.
*Check call result* *Check call result*
````C# ```csharp
var callResult = await kucoinClient.SpotApi.ExchangeData.GetTickersAsync(); var callResult = await kucoinClient.SpotApi.ExchangeData.GetTickersAsync();
if(!callResult.Success) if(!callResult.Success)
{ {
@ -55,43 +60,43 @@ if(!callResult.Success)
} }
Console.WriteLine("Result: " + callResult.Data); Console.WriteLine("Result: " + callResult.Data);
```` ```
## Socket client ## Socket client
The socket client gives access to the websocket API of an exchange. Websocket API's offer streams to which updates are pushed to which a client can listen. Some exchanges also offer some degree of functionality by allowing clients to give commands via the websocket, but most exchanges only allow this via the Rest API. The socket client gives access to the websocket API of an exchange. Websocket API's offer streams to which updates are pushed to which a client can listen. Some exchanges also offer some degree of functionality by allowing clients to give commands via the websocket, but most exchanges only allow this via the Rest API.
Just like the Rest client is divided in Rest Api clients, the Socket client is divided into Socket Api clients, each with their own range of API functionality. Socket Api clients are generally not divided into topics since the number of methods isn't as big as with the Rest client. To use the Kucoin client as example again, it looks like this: Just like the Rest client is divided in Rest Api clients, the Socket client is divided into Socket Api clients, each with their own range of API functionality. Socket Api clients are generally not divided into topics since the number of methods isn't as big as with the Rest client. To use the Kucoin client as example again, it looks like this:
````C# ```csharp
- KucoinSocketClient - KucoinSocketClient
- SpotStreams - SpotStreams
- FuturesStreams - FuturesStreams
```` ```
*Subscribing to updates for all tickers on the Spot Api* *Subscribing to updates for all tickers on the Spot Api*
````C# ```csharp
var subscribeResult = kucoinSocketClient.SpotStreams.SubscribeToAllTickerUpdatesAsync(DataHandler); var subscribeResult = kucoinSocketClient.SpotStreams.SubscribeToAllTickerUpdatesAsync(DataHandler);
```` ```
Subscribe methods require a data handler parameter, which is the method which will be called when an update is received from the server. This can be the name of a method or a lambda expression. Subscribe methods require a data handler parameter, which is the method which will be called when an update is received from the server. This can be the name of a method or a lambda expression.
*Method reference* *Method reference*
````C# ```csharp
await kucoinSocketClient.SpotStreams.SubscribeToAllTickerUpdatesAsync(DataHandler); await kucoinSocketClient.SpotStreams.SubscribeToAllTickerUpdatesAsync(DataHandler);
private static void DataHandler(DataEvent<KucoinStreamTick> updateData) private static void DataHandler(DataEvent<KucoinStreamTick> updateData)
{ {
// Process updateData // Process updateData
} }
```` ```
*Lambda* *Lambda*
````C# ```csharp
await kucoinSocketClient.SpotStreams.SubscribeToAllTickerUpdatesAsync(updateData => await kucoinSocketClient.SpotStreams.SubscribeToAllTickerUpdatesAsync(updateData =>
{ {
// Process updateData // Process updateData
}); });
```` ```
All updates are wrapped in a `DataEvent<>` object, which contain a `Timestamp`, `OriginalData`, `Topic`, and a `Data` property. The `Timestamp` is the timestamp when the data was received (not send!). `OriginalData` will contain the originally received data if this has been enabled in the client options. `Topic` will contain the topic of the update, which is typically the symbol or asset the update is for. The `Data` property contains the received update data. All updates are wrapped in a `DataEvent<>` object, which contain a `Timestamp`, `OriginalData`, `Topic`, and a `Data` property. The `Timestamp` is the timestamp when the data was received (not send!). `OriginalData` will contain the originally received data if this has been enabled in the client options. `Topic` will contain the topic of the update, which is typically the symbol or asset the update is for. The `Data` property contains the received update data.
@ -99,7 +104,7 @@ All updates are wrapped in a `DataEvent<>` object, which contain a `Timestamp`,
### Processing subscribe responses ### Processing subscribe responses
Subscribing to a stream will return a `CallResult<UpdateSubscription>` object. This should be checked for success the same was as the [rest client](#processing-request-responses). The `UpdateSubscription` object can be used to listen for connection events of the socket connection. Subscribing to a stream will return a `CallResult<UpdateSubscription>` object. This should be checked for success the same was as the [rest client](#processing-request-responses). The `UpdateSubscription` object can be used to listen for connection events of the socket connection.
````C# ```csharp
var subscriptionResult = await kucoinSocketClient.SpotStreams.SubscribeToAllTickerUpdatesAsync(DataHandler); var subscriptionResult = await kucoinSocketClient.SpotStreams.SubscribeToAllTickerUpdatesAsync(DataHandler);
if(!subscriptionResult.Success) if(!subscriptionResult.Success)
@ -116,44 +121,44 @@ subscriptionResult.Data.ConnectionRestored += (time) =>
Console.WriteLine("Connection restored"); Console.WriteLine("Connection restored");
}; };
```` ```
### Unsubscribing ### Unsubscribing
When no longer interested in specific updates there are a few ways to unsubscribe. When no longer interested in specific updates there are a few ways to unsubscribe.
**Close subscription** **Close subscription**
Subscribing to an update stream will respond with an `UpdateSubscription` object. You can call the `CloseAsync()` method on this to no longer receive updates from that subscription: Subscribing to an update stream will respond with an `UpdateSubscription` object. You can call the `CloseAsync()` method on this to no longer receive updates from that subscription:
````C# ```csharp
var subscriptionResult = await kucoinSocketClient.SpotStreams.SubscribeToAllTickerUpdatesAsync(DataHandler); var subscriptionResult = await kucoinSocketClient.SpotStreams.SubscribeToAllTickerUpdatesAsync(DataHandler);
await subscriptionResult.Data.CloseAsync(); await subscriptionResult.Data.CloseAsync();
```` ```
**Cancellation token** **Cancellation token**
Passing in a `CancellationToken` as parameter in the subscribe method will allow you to cancel subscriptions by canceling the token. This can be useful when you need to cancel some streams but not others. In this example, both `BTC-USDT` and `ETH-USDT` streams get canceled, while the `KCS-USDT` stream remains active. Passing in a `CancellationToken` as parameter in the subscribe method will allow you to cancel subscriptions by canceling the token. This can be useful when you need to cancel some streams but not others. In this example, both `BTC-USDT` and `ETH-USDT` streams get canceled, while the `KCS-USDT` stream remains active.
````C# ```csharp
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
var subscriptionResult1 = await kucoinSocketClient.SpotStreams.SubscribeToTickerUpdatesAsync("BTC-USDT", DataHandler, cts.Token); var subscriptionResult1 = await kucoinSocketClient.SpotStreams.SubscribeToTickerUpdatesAsync("BTC-USDT", DataHandler, cts.Token);
var subscriptionResult2 = await kucoinSocketClient.SpotStreams.SubscribeToTickerUpdatesAsync("ETH-USDT", DataHandler, cts.Token); var subscriptionResult2 = await kucoinSocketClient.SpotStreams.SubscribeToTickerUpdatesAsync("ETH-USDT", DataHandler, cts.Token);
var subscriptionResult3 = await kucoinSocketClient.SpotStreams.SubscribeToTickerUpdatesAsync("KCS-USDT", DataHandler); var subscriptionResult3 = await kucoinSocketClient.SpotStreams.SubscribeToTickerUpdatesAsync("KCS-USDT", DataHandler);
Console.ReadLine(); Console.ReadLine();
cts.Cancel(); cts.Cancel();
```` ```
**Client unsubscribe** **Client unsubscribe**
Subscriptions can also be closed by calling the `UnsubscribeAsync` method on the client, while providing either the `UpdateSubscription` object or the subscription id: Subscriptions can also be closed by calling the `UnsubscribeAsync` method on the client, while providing either the `UpdateSubscription` object or the subscription id:
````C# ```csharp
var subscriptionResult = await kucoinSocketClient.SpotStreams.SubscribeToTickerUpdatesAsync("BTC-USDT", DataHandler); var subscriptionResult = await kucoinSocketClient.SpotStreams.SubscribeToTickerUpdatesAsync("BTC-USDT", DataHandler);
await kucoinSocketClient.UnsubscribeAsync(subscriptionResult.Data); await kucoinSocketClient.UnsubscribeAsync(subscriptionResult.Data);
// OR // OR
await kucoinSocketClient.UnsubscribeAsync(subscriptionResult.Data.Id); await kucoinSocketClient.UnsubscribeAsync(subscriptionResult.Data.Id);
```` ```
When you need to unsubscribe all current subscriptions on a client you can call `UnsubscribeAllAsync` on the client to unsubscribe all streams and close all connections. When you need to unsubscribe all current subscriptions on a client you can call `UnsubscribeAllAsync` on the client to unsubscribe all streams and close all connections.
## Dependency injection ## Dependency injection
Each library offers a `Add[Library]` extension method for `IServiceCollection`, which allows you to add the clients to the service collection. It also provides a callback for setting the client options. See this example for adding the `BinanceClient`: Each library offers a `Add[Library]` extension method for `IServiceCollection`, which allows you to add the clients to the service collection. It also provides a callback for setting the client options. See this example for adding the `BinanceClient`:
````C# ```csharp
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
services.AddBinance((restClientOptions, socketClientOptions) => { services.AddBinance((restClientOptions, socketClientOptions) => {
@ -163,11 +168,11 @@ public void ConfigureServices(IServiceCollection services)
socketClientOptions.ApiCredentials = new ApiCredentials("KEY", "SECRET"); socketClientOptions.ApiCredentials = new ApiCredentials("KEY", "SECRET");
}); });
} }
```` ```
Doing client registration this way will add the `IBinanceClient` as a transient service, and the `IBinanceSocketClient` as a scoped service. Doing client registration this way will add the `IBinanceClient` as a transient service, and the `IBinanceSocketClient` as a scoped service.
Alternatively, the clients can be registered manually: Alternatively, the clients can be registered manually:
````C# ```csharp
BinanceClient.SetDefaultOptions(new BinanceClientOptions BinanceClient.SetDefaultOptions(new BinanceClientOptions
{ {
ApiCredentials = new ApiCredentials("KEY", "SECRET"), ApiCredentials = new ApiCredentials("KEY", "SECRET"),
@ -181,4 +186,4 @@ BinanceSocketClient.SetDefaultOptions(new BinanceSocketClientOptions
services.AddTransient<IBinanceClient, BinanceClient>(); services.AddTransient<IBinanceClient, BinanceClient>();
services.AddScoped<IBinanceSocketClient, BinanceSocketClient>(); services.AddScoped<IBinanceSocketClient, BinanceSocketClient>();
```` ```

View File

@ -1,6 +1,11 @@
---
title: FAQ
nav_order: 9
---
### I occasionally get a NullReferenceException, what's wrong? ### I occasionally get a 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: 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# ```csharp
var tickerResult = await client.GetTickersAync(); var tickerResult = await client.GetTickersAync();
if(!tickerResult.Success) if(!tickerResult.Success)
{ {
@ -11,12 +16,12 @@ else
// Handle result, it is now safe to access the Data property // Handle result, it is now safe to access the Data property
var symbol = tickerResult.Data.Symbol; var symbol = tickerResult.Data.Symbol;
} }
```` ```
### The socket client stops sending updates after a little while ### 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. You probably didn't keep a reference to the socket client and it got disposed.
Instead of subscribing like this: Instead of subscribing like this:
````C# ```csharp
private void SomeMethod() private void SomeMethod()
{ {
var socketClient = new BinanceSocketClient(); var socketClient = new BinanceSocketClient();
@ -24,9 +29,9 @@ private void SomeMethod()
// Handle data // Handle data
}); });
} }
```` ```
Subscribe like this: Subscribe like this:
````C# ```csharp
private BinanceSocketClient _socketClient = new BinanceSocketClient(); private BinanceSocketClient _socketClient = new BinanceSocketClient();
// .. rest of the class // .. rest of the class
@ -38,4 +43,4 @@ private void SomeMethod()
}); });
} }
```` ```

View File

@ -1,3 +1,8 @@
---
title: Glossary
nav_order: 8
---
|Definition|Synonyms|Meaning| |Definition|Synonyms|Meaning|
|----------|--------|-------| |----------|--------|-------|
|Symbol|Market|An asset pair, for example `BTC-ETH`| |Symbol|Market|An asset pair, for example `BTC-ETH`|

View File

@ -1,3 +1,8 @@
---
title: Common interfaces
nav_order: 5
---
## ISpotClient ## ISpotClient
TODO TODO

View File

@ -1,3 +1,8 @@
---
title: Log config
nav_order: 4
---
The library offers extensive logging, for which you can supply your own logging implementation. The logging can be configured via the client options (see [Client options](https://github.com/JKorf/CryptoExchange.Net/wiki/Options)). The examples here are using the `BinanceClient` but they should be the same for each implementation. The library offers extensive logging, for which you can supply your own logging implementation. The logging can be configured via the client options (see [Client options](https://github.com/JKorf/CryptoExchange.Net/wiki/Options)). The examples here are using the `BinanceClient` but they should be the same for each implementation.
Logging is based on the `Microsoft.Extensions.Logging.ILogger` interface. This should provide ease of use when connecting the library logging to your existing logging implementation. Logging is based on the `Microsoft.Extensions.Logging.ILogger` interface. This should provide ease of use when connecting the library logging to your existing logging implementation.

View File

@ -1,3 +1,8 @@
---
title: Migrate v4 to v5
nav_order: 7
---
Changes from 4.x to 5.x: Changes from 4.x to 5.x:
## Client structure ## Client structure

View File

@ -1,3 +1,8 @@
---
title: Client options
nav_order: 3
---
## Setting options ## Setting options
Each implementation can be configured using client options. There are 2 ways to provide these, either via `[client].SetDefaultOptions([options]);`, or in the constructor of the client. The examples here use the `BinanceClient`, but usage is the same for each client. Each implementation can be configured using client options. There are 2 ways to provide these, either via `[client].SetDefaultOptions([options]);`, or in the constructor of the client. The examples here use the `BinanceClient`, but usage is the same for each client.

View File

@ -1,3 +1,8 @@
---
title: Order books
nav_order: 6
---
Each implementation provides an order book implementation. These implementations will provide a client side order book and will take care of synchronization with the server, and will handle reconnecting and resynchronizing in case of a dropped connection. Each implementation provides an order book implementation. These implementations will provide a client side order book and will take care of synchronization with the server, and will handle reconnecting and resynchronizing in case of a dropped connection.
Order book implementations are named as `[ExchangeName][Type]SymbolOrderBook`, for example `BinanceSpotSymbolOrderBook`. Order book implementations are named as `[ExchangeName][Type]SymbolOrderBook`, for example `BinanceSpotSymbolOrderBook`.

View File

@ -1,17 +1,22 @@
---
title: Home
nav_order: 1
---
The CryptoExchange.Net library is a base package for exchange API implementations. The CryptoExchange.Net library is a base package for exchange API implementations.
[Client usage](https://github.com/JKorf/CryptoExchange.Net/wiki/Clients) [Client usage](Clients.html)
[Client options](https://github.com/JKorf/CryptoExchange.Net/wiki/Options) [Client options](Options.html)
[Configure logging](https://github.com/JKorf/CryptoExchange.Net/wiki/Logging) [Configure logging](Logging.html)
[Order book implementations](https://github.com/JKorf/CryptoExchange.Net/wiki/Orderbooks) [Order book implementations](Orderbooks.html)
[Common interfaces](https://github.com/JKorf/CryptoExchange.Net/wiki/Interfaces) [Common interfaces](Interfaces.html)
[Implementing a new exchange](https://github.com/JKorf/CryptoExchange.Net/wiki/Implementations) [Implementing a new exchange](Implementations.html)
[Glossary](https://github.com/JKorf/CryptoExchange.Net/wiki/Glossary) [Glossary](Glossary.html)
[FAQ](https://github.com/JKorf/CryptoExchange.Net/wiki/FAQ) [FAQ](FAQ.html)