diff --git a/Examples/BlazorClient/BlazorClient.csproj b/Examples/BlazorClient/BlazorClient.csproj index 574dcf3..f07d898 100644 --- a/Examples/BlazorClient/BlazorClient.csproj +++ b/Examples/BlazorClient/BlazorClient.csproj @@ -5,22 +5,23 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/Examples/BlazorClient/Pages/Index.razor b/Examples/BlazorClient/Pages/Index.razor index aa33306..672374c 100644 --- a/Examples/BlazorClient/Pages/Index.razor +++ b/Examples/BlazorClient/Pages/Index.razor @@ -14,6 +14,7 @@ @inject IKucoinRestClient kucoinClient @inject IMexcRestClient mexcClient @inject IOKXRestClient okxClient +@inject IWhiteBitRestClient whitebitClient

BTC-USD prices:

@foreach(var price in _prices.OrderBy(p => p.Key)) @@ -41,12 +42,13 @@ var kucoinTask = kucoinClient.SpotApi.ExchangeData.GetTickerAsync("BTC-USDT"); var mexcTask = mexcClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT"); var okxTask = okxClient.UnifiedApi.ExchangeData.GetTickerAsync("BTCUSDT"); + var whitebitTask = whitebitClient.V4Api.ExchangeData.GetTickersAsync(); await Task.WhenAll(binanceTask, bingXTask, bitfinexTask, bitgetTask, bitmartTask, bybitTask, coinexTask, gateioTask, htxTask, krakenTask, kucoinTask, mexcTask, okxTask); if (binanceTask.Result.Success) _prices.Add("Binance", binanceTask.Result.Data.LastPrice); - + if (bingXTask.Result.Success) _prices.Add("BingX", bingXTask.Result.Data.First().LastPrice); @@ -88,6 +90,12 @@ if (okxTask.Result.Success) _prices.Add("OKX", okxTask.Result.Data.LastPrice ?? 0); + + if (whitebitTask.Result.Success){ + // WhiteBit API doesn't offer an endpoint to filter for a specific ticker, so we have to filter client side + var tickers = whitebitTask.Result.Data; + _prices.Add("WhiteBit", tickers.Single(x => x.Symbol == "BTC_USDT").LastPrice); + } } } \ No newline at end of file diff --git a/Examples/BlazorClient/Pages/LiveData.razor b/Examples/BlazorClient/Pages/LiveData.razor index b51f5a9..2ce2689 100644 --- a/Examples/BlazorClient/Pages/LiveData.razor +++ b/Examples/BlazorClient/Pages/LiveData.razor @@ -14,6 +14,7 @@ @inject IKucoinSocketClient kucoinSocketClient @inject IMexcSocketClient mexcSocketClient @inject IOKXSocketClient okxSocketClient +@inject IWhiteBitSocketClient whitebitSocketClient @using System.Collections.Concurrent @using CryptoExchange.Net.Objects @using CryptoExchange.Net.Objects.Sockets; @@ -49,6 +50,7 @@ kucoinSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETH-BTC", data => UpdateData("Kucoin", data.Data.LastPrice ?? 0)), mexcSocketClient.SpotApi.SubscribeToMiniTickerUpdatesAsync("ETHBTC", data => UpdateData("Mexc", data.Data.LastPrice)), okxSocketClient.UnifiedApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETH-BTC", data => UpdateData("OKX", data.Data.LastPrice ?? 0)), + whitebitSocketClient.V4Api.SubscribeToTickerUpdatesAsync("ETH_BTC", data => UpdateData("WhiteBit", data.Data.Ticker.LastPrice)), }; await Task.WhenAll(tasks); diff --git a/Examples/BlazorClient/Pages/OrderBooks.razor b/Examples/BlazorClient/Pages/OrderBooks.razor index 1c15995..e74125d 100644 --- a/Examples/BlazorClient/Pages/OrderBooks.razor +++ b/Examples/BlazorClient/Pages/OrderBooks.razor @@ -18,6 +18,7 @@ @using Kucoin.Net.Interfaces @using Mexc.Net.Interfaces @using OKX.Net.Interfaces; +@using WhiteBit.Net.Interfaces @inject IBinanceOrderBookFactory binanceFactory @inject IBingXOrderBookFactory bingXFactory @inject IBitfinexOrderBookFactory bitfinexFactory @@ -33,6 +34,7 @@ @inject IKucoinOrderBookFactory kucoinFactory @inject IMexcOrderBookFactory mexcFactory @inject IOKXOrderBookFactory okxFactory +@inject IWhiteBitOrderBookFactory whitebitFactory @implements IDisposable

ETH-BTC books, live updates:

@@ -77,10 +79,11 @@ { "CryptoCom", cryptocomFactory.Create("ETH_BTC") }, { "GateIo", gateioFactory.CreateSpot("ETH_BTC") }, { "HTX", htxFactory.CreateSpot("ethbtc") }, - { "Kraken", krakenFactory.CreateSpot("ETH/XBT") }, + { "Kraken", krakenFactory.CreateSpot("ETH/BTC") }, { "Kucoin", kucoinFactory.CreateSpot("ETH-BTC") }, { "Mexc", mexcFactory.CreateSpot("ETHBTC") }, { "OKX", okxFactory.Create("ETH-BTC") }, + { "WhiteBit", whitebitFactory.CreateV4("ETH_BTC") }, }; await Task.WhenAll(_books.Select(b => b.Value.StartAsync())); diff --git a/Examples/BlazorClient/Pages/Trackers.razor b/Examples/BlazorClient/Pages/Trackers.razor index 1de8fe7..e309305 100644 --- a/Examples/BlazorClient/Pages/Trackers.razor +++ b/Examples/BlazorClient/Pages/Trackers.razor @@ -20,6 +20,7 @@ @using Kucoin.Net.Interfaces @using Mexc.Net.Interfaces @using OKX.Net.Interfaces; +@using WhiteBit.Net.Interfaces @inject IBinanceTrackerFactory binanceFactory @inject IBingXTrackerFactory bingXFactory @inject IBitfinexTrackerFactory bitfinexFactory @@ -35,6 +36,7 @@ @inject IKucoinTrackerFactory kucoinFactory @inject IMexcTrackerFactory mexcFactory @inject IOKXTrackerFactory okxFactory +@inject IWhiteBitTrackerFactory whitebitFactory @implements IDisposable

ETH-BTC trade Trackers, live updates:

@@ -76,6 +78,7 @@ { kucoinFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) }, { mexcFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) }, { okxFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) }, + { whitebitFactory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5)) }, }; await Task.WhenAll(_trackers.Select(b => b.StartAsync())); diff --git a/Examples/BlazorClient/Startup.cs b/Examples/BlazorClient/Startup.cs index 65c1ab3..9ebf284 100644 --- a/Examples/BlazorClient/Startup.cs +++ b/Examples/BlazorClient/Startup.cs @@ -50,6 +50,7 @@ namespace BlazorClient services.AddKucoin(); services.AddMexc(); services.AddOKX(); + services.AddWhiteBit(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/Examples/BlazorClient/_Imports.razor b/Examples/BlazorClient/_Imports.razor index 4b198c2..74ca8f3 100644 --- a/Examples/BlazorClient/_Imports.razor +++ b/Examples/BlazorClient/_Imports.razor @@ -23,4 +23,5 @@ @using Kucoin.Net.Interfaces.Clients; @using Mexc.Net.Interfaces.Clients; @using OKX.Net.Interfaces.Clients; +@using WhiteBit.Net.Interfaces.Clients @using CryptoExchange.Net.Interfaces; \ No newline at end of file diff --git a/Examples/ConsoleClient/ConsoleClient.csproj b/Examples/ConsoleClient/ConsoleClient.csproj index 3576ea8..1f1d060 100644 --- a/Examples/ConsoleClient/ConsoleClient.csproj +++ b/Examples/ConsoleClient/ConsoleClient.csproj @@ -6,20 +6,20 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/Examples/SharedClients/SharedClients.csproj b/Examples/SharedClients/SharedClients.csproj index a39d032..554bb29 100644 --- a/Examples/SharedClients/SharedClients.csproj +++ b/Examples/SharedClients/SharedClients.csproj @@ -8,9 +8,9 @@ - - - + + + diff --git a/README.md b/README.md index 5d76526..03b8f0c 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ The following API's are directly supported. Note that there are 3rd party implem |Kucoin|[JKorf/Kucoin.Net](https://github.com/JKorf/Kucoin.Net)|[![Nuget version](https://img.shields.io/nuget/v/Kucoin.net.svg?style=flat-square)](https://www.nuget.org/packages/Kucoin.Net)| |Mexc|[JKorf/Mexc.Net](https://github.com/JKorf/Mexc.Net)|[![Nuget version](https://img.shields.io/nuget/v/JK.Mexc.net.svg?style=flat-square)](https://www.nuget.org/packages/JK.Mexc.Net)| |OKX|[JKorf/OKX.Net](https://github.com/JKorf/OKX.Net)|[![Nuget version](https://img.shields.io/nuget/v/JK.OKX.net.svg?style=flat-square)](https://www.nuget.org/packages/JK.OKX.Net)| +|WhiteBit|[JKorf/WhiteBit.Net](https://github.com/JKorf/WhiteBit.Net)|[![Nuget version](https://img.shields.io/nuget/v/WhiteBit.net.svg?style=flat-square)](https://www.nuget.org/packages/WhiteBit.Net)| Any of these can be installed independently or install [CryptoClients.Net](https://github.com/jkorf/CryptoClients.Net) which includes all exchange API's. diff --git a/docs/index.html b/docs/index.html index 5b78fed..bcc0f18 100644 --- a/docs/index.html +++ b/docs/index.html @@ -162,6 +162,7 @@ KucoinJKorf/Kucoin.Net MexcJKorf/Mexc.Net OKXJKorf/OKX.Net + WhiteBitJKorf/WhiteBit.Net

Note that there are 3rd party implementations going around, but only the listed ones here are created and supported by me.

When using multiple of these API's the CryptoClients.Net package can be used which combines these packages and allows easy access to all exchange API's.

@@ -277,6 +278,9 @@ +
@@ -340,6 +344,9 @@
dotnet add package JK.OKX.Net
+
+
dotnet add package WhiteBit.Net
+
@@ -405,6 +412,9 @@ +
@@ -458,6 +468,9 @@
builder.Services.AddOKX();
+
+
builder.Services.AddWhiteBit();
+
@@ -515,6 +528,9 @@ +
@@ -530,7 +546,11 @@ IExchangeOrderBookFactory - A factory class for accessing all exchanges SymbolOrderBook (locally synced order books) factory methods + A factory class for accessing all exchanges SymbolOrderBook (locally synced order books) factory methods, (see orderbooks) + + + IExchangeTrackerFactory + A factory class for creating Kline and Trade trackers (see trackers) I[Library]RestClient @@ -565,6 +585,10 @@ IBinanceOrderBookFactory A factory for creating SymbolOrderBook instances for the Binance API + + IBinanceTrackerFactory + A factory for creating kline and trade Tracker instances for the Binance API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -594,6 +618,10 @@ IBingXOrderBookFactory A factory for creating SymbolOrderBook instances for the BingX API + + IBingXTrackerFactory + A factory for creating kline and trade Tracker instances for the BingX API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -623,6 +651,10 @@ IBitfinexOrderBookFactory A factory for creating SymbolOrderBook instances for the Bitfinex API + + IBitfinexTrackerFactory + A factory for creating kline and trade Tracker instances for the Bitfinex API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -651,6 +683,10 @@ IBitgetOrderBookFactory A factory for creating SymbolOrderBook instances for the Bitget API + + + IBitgetTrackerFactory + A factory for creating kline and trade Tracker instances for the Bitget API ICryptoRestClient @@ -681,6 +717,10 @@ IBitMartOrderBookFactory A factory for creating SymbolOrderBook instances for the Bitget API + + IBitMartTrackerFactory + A factory for creating kline and trade Tracker instances for the BitMart API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -710,6 +750,10 @@ IBybitOrderBookFactory A factory for creating SymbolOrderBook instances for the Bybit API + + IBybitTrackerFactory + A factory for creating kline and trade Tracker instances for the Bybit API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -739,6 +783,10 @@ ICoinbaseOrderBookFactory A factory for creating SymbolOrderBook instances for the Coinbase API + + ICoinbaseTrackerFactory + A factory for creating kline and trade Tracker instances for the Coinbase API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -781,6 +829,10 @@ ICoinExOrderBookFactory A factory for creating SymbolOrderBook instances for the CoinEx API + + ICoinExTrackerFactory + A factory for creating kline and trade Tracker instances for the CoinEx API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -810,6 +862,10 @@ ICryptoComOrderBookFactory A factory for creating SymbolOrderBook instances for the Crypto.com API + + ICryptoComTrackerFactory + A factory for creating kline and trade Tracker instances for the Crypto.com API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -839,6 +895,10 @@ IGateIoOrderBookFactory A factory for creating SymbolOrderBook instances for the GateIo API + + IGateIoTrackerFactory + A factory for creating kline and trade Tracker instances for the GateIo API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -868,6 +928,10 @@ IHTXOrderBookFactory A factory for creating SymbolOrderBook instances for the HTX API + + IHTXTrackerFactory + A factory for creating kline and trade Tracker instances for the HTX API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -897,6 +961,10 @@ IKrakenOrderBookFactory A factory for creating SymbolOrderBook instances for the Kraken API + + IKrakenTrackerFactory + A factory for creating kline and trade Tracker instances for the Kraken API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -926,6 +994,10 @@ IKucoinOrderBookFactory A factory for creating SymbolOrderBook instances for the Kucoin API + + IKucoinTrackerFactory + A factory for creating kline and trade Tracker instances for the Kucoin API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -955,6 +1027,10 @@ IMexcOrderBookFactory A factory for creating SymbolOrderBook instances for the Mexc API + + IMexcTrackerFactory + A factory for creating kline and trade Tracker instances for the Mexc API + ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed @@ -984,6 +1060,43 @@ IOKXOrderBookFactory A factory for creating SymbolOrderBook instances for the OKX API + + IOKXTrackerFactory + A factory for creating kline and trade Tracker instances for the OKX API + + + ICryptoRestClient + An aggregating client from which multiple different library REST clients can be accessed + + + ICryptoSocketClient + An aggregating client from which multiple different library Websocket clients can be accessed + + + ISharedClient + Various interfaces deriving from ISharedClient which can be used for common functionality + + +
+
+ + + + + + + + + + + + + + + + + + @@ -1074,6 +1187,9 @@ +
@@ -1276,6 +1392,18 @@ if (!tickersResult.Success) // Handle error, tickersResult.Error contains more information } else +{ + // Handle data, tickersResult.Data will contain the actual data +} +
+
+
var client = new WhiteBitRestClient();
+var tickersResult = await client.V4Api.ExchangeData.GetTickersAsync();
+if (!tickersResult.Success)
+{
+  // Handle error, tickersResult.Error contains more information
+}
+else
 {
   // Handle data, tickersResult.Data will contain the actual data
 }
@@ -1402,6 +1530,9 @@ else +
@@ -1578,6 +1709,17 @@ if (!subscribeResult.Success) { // Handle error, subscribeResult.Error contains more information on why the subscription failed } +// Subscribing was successfull, the data will now be streamed into the data handler +
+
+
var client = new WhiteBitSocketClient();
+var subscribeResult = await client.V4Api.ExchangeData.SubscribeToTickerUpdatesAsync("ETH_USDT", update => {
+    // Handle the data update, update.Data will contain the actual data
+});
+if (!subscribeResult.Success)
+{
+  // Handle error, subscribeResult.Error contains more information on why the subscription failed
+}
 // Subscribing was successfull, the data will now be streamed into the data handler
@@ -1777,6 +1919,9 @@ var binanceTriggered = CheckForTrigger(lastBinanceTicker); +
@@ -1953,6 +2098,13 @@ var spotSharedRestClients = okxRestClient.UnifiedApi.SharedClient; // Futures and Spot API common functionality socket client var spotSharedSocketClient = okxSocketClient.UnifiedApi.SharedClient;
+
+
// Futures and Spot API common functionality rest client
+var spotSharedRestClients = whitebitRestClient.V4Api.SharedClient;
+
+// Futures and Spot API common functionality socket client
+var spotSharedSocketClient = whitebitSocketClient.V4Api.SharedClient;
+

TradingMode

@@ -2236,6 +2388,9 @@ options.ApiCredentials = new ApiCredentials("YOUR PUBLIC KEY", "YOUR PRIVATE KEY +
@@ -2381,6 +2536,15 @@ options.ApiCredentials = new ApiCredentials("YOUR PUBLIC KEY", "YOUR PRIVATE KEY
builder.Services.AddOKX(
+  restOptions => {
+    restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
+  },
+  socketOptions => {
+    socketOptions.RequestTimeout = TimeSpan.FromSeconds(10);
+  });
+
+
+
builder.Services.AddWhiteBit(
   restOptions => {
     restOptions.RequestTimeout = TimeSpan.FromSeconds(30);
   },
@@ -2446,6 +2610,9 @@ options.ApiCredentials = new ApiCredentials("YOUR PUBLIC KEY", "YOUR PRIVATE KEY
 			  
+			  
 			
 			
@@ -2546,6 +2713,12 @@ options.ApiCredentials = new ApiCredentials("YOUR PUBLIC KEY", "YOUR PRIVATE KEY
var client = new OKXRestClient(opts =>
+{
+    opts.RequestTimeout = TimeSpan.FromSeconds(30);
+});
+
+
+
var client = new WhiteBitRestClient(opts =>
 {
     opts.RequestTimeout = TimeSpan.FromSeconds(30);
 });
@@ -2605,6 +2778,9 @@ options.ApiCredentials = new ApiCredentials("YOUR PUBLIC KEY", "YOUR PRIVATE KEY +
@@ -2719,6 +2895,13 @@ var client = new MexcRestClient();
}); var client = new OKXRestClient();
+
+
WhiteBitRestClient.SetDefaultOptions(options =>
+{
+    options.RequestTimeout = TimeSpan.FromSeconds(30);
+});
+var client = new WhiteBitRestClient();
+
@@ -2950,6 +3133,9 @@ var client = new OKXRestClient(); +
@@ -3157,6 +3343,19 @@ if (!startResult.Success) } // Book has successfully started and synchronized +// Once no longer needed you can stop the live sync functionality by calling StopAsync() +await book.StopAsync(); + +
+
+
var book = new WhiteBitSymbolOrderBook("ETH_USDT");
+var startResult = await book.StartAsync();
+if (!startResult.Success)
+{
+  // Handle error, error info available in startResult.Error
+}
+// Book has successfully started and synchronized
+
 // Once no longer needed you can stop the live sync functionality by calling StopAsync()
 await book.StopAsync();
 
@@ -3327,6 +3526,9 @@ foreach (var book in books.Where(b => b.Status == OrderBookStatus.Synced)) +
@@ -3646,6 +3848,26 @@ if (!startResult.Success) // Tracker has successfully started // Note that it might not be fully synced yet, check tracker.Status for this. +// Once no longer needed you can stop the live sync functionality by calling StopAsync() +await tracker.StopAsync(); + +
+
+
// Either create a new factory or inject the IWhiteBitTrackerFactory interface
+var factory = new WhiteBitTrackerFactory();
+
+var symbol = new SharedSymbol(TradingMode.Spot, "ETH", "USDT");
+
+// Create a tracker for ETH/USDT keeping track of trades in the last 5 minutes
+var tracker = factory.CreateTradeTracker(symbol, period: TimeSpan.FromMinutes(5));
+var startResult = await tracker.StartAsync();
+if (!startResult.Success)
+{
+  // Handle error, error info available in startResult.Error
+}
+// Tracker has successfully started
+// Note that it might not be fully synced yet, check tracker.Status for this.
+
 // Once no longer needed you can stop the live sync functionality by calling StopAsync()
 await tracker.StopAsync();
 
@@ -3996,6 +4218,9 @@ var binanceClient = new BinanceRestClient(new HttpClient(), logFactory, options +
@@ -4182,6 +4407,20 @@ var binanceClient = new BinanceRestClient(new HttpClient(), logFactory, options

To be notified of when a rate limit is hit the static OKXExchange.RateLimiter exposes an event which triggers when a rate limit is reached

OKXExchange.RateLimiter.RateLimitTriggered += (rateLimitEvent) => Console.WriteLine("Limit triggered: " + rateLimitEvent);
 
+
+
+
+
services.AddWhiteBit(x =>
+    x.RatelimiterEnabled = true;
+    x.RateLimitingBehaviour = RateLimitingBehaviour.Wait;
+}, x =>
+{
+    x.RatelimiterEnabled = true;
+    x.RateLimitingBehaviour = RateLimitingBehaviour.Wait;
+});
+

To be notified of when a rate limit is hit the static WhiteBitExchange.RateLimiter exposes an event which triggers when a rate limit is reached

+
WhiteBitExchange.RateLimiter.RateLimitTriggered += (rateLimitEvent) => Console.WriteLine("Limit triggered: " + rateLimitEvent);
+
 
@@ -4281,11 +4520,21 @@ var responseSource = result.DataSource; +
-
// This example uses Binance, but can be any exchange support. For example Bybit, Kraken, Kucoin etc
-await exchangeRestClient.Binance.SpotApi.ExchangeData.GetExchangeInfoAsync();
+
// This example uses Binance, but can be any supported exchange. For example Bybit, Kraken, Kucoin etc
+
+// Directly reference the Exchange API:
+await exchangeRestClient.Binance.SpotApi.ExchangeData.GetExchangeInfoAsync();
+
+// Or make it fully dynamic, either request on a single exchange:
+await exchangeRestClient.GetSpotSymbolClient("Binance")!.GetSpotSymbolsAsync(new GetSymbolsRequest());
+// Or request multiple exchanges at the same time:
+await exchangeRestClient.GetSpotSymbolsAsync(new GetSymbolsRequest(), ["Binance", "Kraken", "OKX"]);
await binanceClient.SpotApi.ExchangeData.GetExchangeInfoAsync();
@@ -4297,7 +4546,7 @@ await exchangeRestClient.Binance.SpotApi.ExchangeData.GetExchangeInfoAsync();await bitfinexClient.SpotApi.ExchangeData.GetSymbolsAsync();
-
await bitgetClient.SpotApi.ExchangeData.GetSymbolsAsync();
+
await bitgetClient.SpotApiV2.ExchangeData.GetSymbolsAsync();
await bitMartClient.SpotApi.ExchangeData.GetSymbolsAsync();
@@ -4332,6 +4581,9 @@ await exchangeRestClient.Binance.SpotApi.ExchangeData.GetExchangeInfoAsync();
await okxClient.UnifiedApi.ExchangeData.GetSymbolsAsync(OKXInstrumentType.Spot);
+
+
await whitebitClient.V4Api.ExchangeData.GetSymbolsAsync();
+
@@ -4398,11 +4650,22 @@ await exchangeRestClient.Binance.SpotApi.ExchangeData.GetExchangeInfoAsync(); OKX +
-
// This example uses Binance, but can be any exchange support. For example Bybit, Kraken, Kucoin etc
-await exchangeRestClient.Binance.SpotApi.ExchangeData.GetTickerAsync(spotClient.GetSymbolName("BTC", "USDT"));
+
// This example uses Binance, but can be any supported exchange. For example Bybit, Kraken, Kucoin etc
+
+// Directly reference the Exchange API:
+await exchangeRestClient.Binance.SpotApi.ExchangeData.GetTickerAsync("ETHUSDT");
+
+// Or make it fully dynamic, either request on a single exchange:
+var symbol = new SharedSymbol(TradingMode.Spot, "ETH", "USDT");
+await exchangeRestClient.GetSpotTickerClient("Binance")!.GetSpotTickerAsync(new GetTickerRequest(symbol));
+// Or request multiple exchanges at the same time:
+await exchangeRestClient.GetSpotTickerAsync(new GetTickerRequest(symbol), ["Binance", "Kraken", "OKX"]);
await binanceClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT");
@@ -4414,7 +4677,7 @@ await exchangeRestClient.Binance.SpotApi.ExchangeData.GetTickerAsync(spotClient.
await bitfinexClient.SpotApi.ExchangeData.GetTickerAsync("tBTCUST");
-
await bitgetClient.SpotApi.ExchangeData.GetTickerAsync("BTCUSDT_SPBL");
+
await bitgetClient.SpotApiV2.ExchangeData.GetTickersAsync("BTCUSDT");
await bitMartClient.SpotApi.ExchangeData.GetTickerAsync("BTC_USDT");
@@ -4450,6 +4713,11 @@ await coinbaseClient.AdvancedTradeApi.ExchangeData.GetSymbolAsync("BTC-USDT");
await okxClient.UnifiedApi.ExchangeData.GetTickerAsync("BTC-USDT");
+
+
// WhiteBit API doesn't offer a symbol filter, so we have to filter client side
+var tickersResult = await whitebitClient.V4Api.ExchangeData.GetTickersAsync();
+var ticker = tickersResult.Data.Single(x => x.Symbol == "BTC_USDT");
+
@@ -4516,11 +4784,21 @@ await coinbaseClient.AdvancedTradeApi.ExchangeData.GetSymbolAsync("BTC-USDT"); OKX +
-
// This example uses Binance, but can be any exchange support. For example Bybit, Kraken, Kucoin etc
-await exchangeRestClient.Binance.SpotApi.Account.GetBalancesAsync();
+
// This example uses Binance, but can be any supported exchange. For example Bybit, Kraken, Kucoin etc
+
+// Directly reference the Exchange API:
+await exchangeRestClient.Binance.SpotApi.Account.GetBalancesAsync();
+
+// Or make it fully dynamic, either request on a single exchange:
+await exchangeRestClient.GetBalancesClient(TradingMode.Spot, "Binance")!.GetBalancesAsync(new GetBalancesRequest());
+// Or request multiple exchanges at the same time:
+await exchangeRestClient.GetBalancesAsync(new GetBalancesRequest(TradingMode.Spot), ["Binance", "Kraken", "OKX"]);
await binanceClient.SpotApi.Account.GetBalancesAsync();
@@ -4532,7 +4810,7 @@ await exchangeRestClient.Binance.SpotApi.Account.GetBalancesAsync();await bitfinexClient.SpotApi.Account.GetBalancesAsync();
-
await bitgetClient.SpotApi.Account.GetBalancesAsync();
+
await bitgetClient.SpotApiV2.Account.GetSpotBalancesAsync();
await bitMartClient.SpotApi.Account.GetSpotBalancesAsync();
@@ -4571,6 +4849,9 @@ var result = await htxClient.SpotApi.Account.GetBalancesAsync();
await okxClient.UnifiedApi.Account.GetAccountBalanceAsync();
+
+
await whitebitClient.V4Api.Account.GetSpotBalancesAsync();
+
@@ -4637,11 +4918,19 @@ var result = await htxClient.SpotApi.Account.GetBalancesAsync(); +
-
// This example uses Binance, but can be any exchange support. For example Bybit, Kraken, Kucoin etc
-await exchangeRestClient.Binance.SpotApi.Trading.PlaceOrderAsync("BTCUSDT", OrderSide.Buy, SpotOrderType.Limit, 0.1m, price: 50000, timeInForce: TimeInForce.GoodTillCanceled);
+
// This example uses Binance, but can be any supported exchange. For example Bybit, Kraken, Kucoin etc
+
+// Directly reference the Exchange API:
+await exchangeRestClient.Binance.SpotApi.Trading.PlaceOrderAsync("BTCUSDT", Binance.Net.Enums.OrderSide.Buy, Binance.Net.Enums.SpotOrderType.Limit, 0.1m, price: 50000, timeInForce: Binance.Net.Enums.TimeInForce.GoodTillCanceled);
+
+// Or make it fully dynamic:
+await exchangeRestClient.GetSpotOrderClient("Binance")!.PlaceSpotOrderAsync(new PlaceSpotOrderRequest(new SharedSymbol(TradingMode.Spot, "ETH", "USDT"), SharedOrderSide.Buy, SharedOrderType.Limit, 0.1m, price: 50000));
await binanceClient.SpotApi.Trading.PlaceOrderAsync("BTCUSDT", OrderSide.Buy, SpotOrderType.Limit, 0.1m, price: 50000, timeInForce: TimeInForce.GoodTillCanceled);
@@ -4653,7 +4942,7 @@ await exchangeRestClient.Binance.SpotApi.Trading.PlaceOrderAsync("BTCUSDT", Orde
await bitfinexClient.SpotApi.Trading.PlaceOrderAsync("tBTCUST", OrderSide.Buy, OrderType.Limit, 0.1m, 50000);
-
await bitgetClient.SpotApi.Trading.PlaceOrderAsync("BTCUSDT_SPBL", BitgetOrderSide.Buy, BitgetOrderType.Limit, 0.1m, timeInForce: BitgetTimeInForce.GoodTillCanceled, 50000);
+
await bitgetRestClient.SpotApiV2.Trading.PlaceOrderAsync("BTCUSDT_SPBL", OrderSide.Buy, OrderType.Limit, 0.1m, timeInForce: TimeInForce.GoodTillCanceled, price: 50000);
await bitMartClient.SpotApi.Trading.PlaceOrderAsync("BTC_USDT", OrderSide.Buy, OrderType.Limit, 0.1m, price: 50000);
@@ -4692,6 +4981,9 @@ var result = await htxClient.SpotApi.Trading.PlaceOrderAsync(account.Id, "BTCUSD
await okxClient.UnifiedApi.Trading.PlaceOrderAsync("BTC-USDT", OKXOrderSide.Buy, OKXOrderType.LimitOrder, 0.1m, 50000);
+
+
await whitebitClient.V4Api.Trading.PlaceSpotOrderAsync("BTC_USDT", OrderSide.Buy, NewOrderType.Limit, 0.1m, price: 50000);
+
@@ -4758,13 +5050,28 @@ var result = await htxClient.SpotApi.Trading.PlaceOrderAsync(account.Id, "BTCUSD +
-
// This example uses Binance, but can be any exchange support. For example Bybit, Kraken, Kucoin etc
+		
// This example uses Binance, but can be any supported exchange. For example Bybit, Kraken, Kucoin etc
+
+// Directly reference the Exchange API:
 await exchangeSocketClient.Binance.SpotApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETHUSDT", data => {
     // Handle update
-});
+}); + +// Or make it fully dynamic, either subscribe on a single exchange: +var symbol = new SharedSymbol(TradingMode.Spot, "ETH", "USDT"); +await exchangeSocketClient.GetTickerClient(TradingMode.Spot, "Binance")!.SubscribeToTickerUpdatesAsync(new SubscribeTickerRequest(symbol), data => { + // Handle update +}); +// Or subscribe on multiple exchanges at the same time: +await exchangeSocketClient.SubscribeToTickerUpdatesAsync(new SubscribeTickerRequest(symbol), data => { + // Handle update +}, ["Binance", "Kraken", "OKX"]);
await binanceSocketClient.SpotApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETHUSDT", data => {
@@ -4782,7 +5089,7 @@ await exchangeSocketClient.Binance.SpotApi.ExchangeData.SubscribeToTickerUpdates
 });
-
await bitgetSocketClient.SpotApi.SubscribeToTickerUpdatesAsync("ETHUSDT", data => {
+		
await bitgetSocketClient.SpotApiV2.SubscribeToTickerUpdatesAsync("ETHUSDT", data => {
     // Handle update
 });
@@ -4840,6 +5147,12 @@ await exchangeSocketClient.Binance.SpotApi.ExchangeData.SubscribeToTickerUpdates
await okxSocketClient.UnifiedApi.ExchangeData.SubscribeToTickerUpdatesAsync("ETHUSDT", data => {
     // Handle update
 });
+
+
+
+
await whitebitSocketClient.V4Api.SubscribeToTickerUpdatesAsync("ETH_USDT", data => {
+    // Handle update
+});
 
@@ -4908,27 +5221,35 @@ await exchangeSocketClient.Binance.SpotApi.ExchangeData.SubscribeToTickerUpdates +
// This example uses Binance, but can be any exchange support. For example Bybit, Kraken, Kucoin etc
+// Binance requires a listenkey to start the user stream
 
-// Retrieve the listen key
+//Directly reference the Exchange API:
 var listenKey = await exchangeRestClient.Binance.SpotApi.Account.StartUserStreamAsync();
-
-// Subscribe using the key
-await exchangeSocketClient.Binance.SpotApi.Account.SubscribeToUserDataUpdatesAsync(listenKey.Data, data => {
+await exchangeSocketClient.Binance.SpotApi.Account.SubscribeToUserDataUpdatesAsync(listenKey.Data, data =>
+{
     // Handle update
 }, null, null, null);
 
-// The listen key will stay valid for 60 minutes, after this no updates will be send anymore
-// To extend the life time of the listen key it is recommended to call the KeepAliveUserStreamAsync method every 30 minutes
-_ = Task.Run(async () => {
-    while (true)
-    {
-        await Task.Delay(Timespan.FromMinutes(30));
-        await exchangeRestClient.Binance.SpotApi.Account.KeepAliveUserStreamAsync(listenKey.Data);
-    }
+
+// Or make it fully dynamic:
+string? listenKey = null;
+var listenkeyClient = exchangeRestClient.GetListenKeyClient(TradingMode.Spot, "Binance");
+if (listenkeyClient != null)
+{
+    // Exchange needs a listenkey; so request that
+    var listenKeyResult = await listenkeyClient.StartListenKeyAsync(new StartListenKeyRequest());
+    listenKey = listenKeyResult.Data;
+}
+await exchangeSocketClient.GetSpotOrderClient("Binance")!.SubscribeToSpotOrderUpdatesAsync(new SubscribeSpotOrderRequest(listenKey: listenKey), data =>
+{
+    // Handle update
 });
@@ -4975,7 +5296,7 @@ _ = Task.Run(async () => { });
-
await bitgetSocketClient.SpotApi.SubscribeToOrderUpdatesAsync(data => {
+		
await bitgetSocketClient.SpotApiV2.SubscribeToOrderUpdatesAsync(data => {
     // Handle update
 });
@@ -5051,6 +5372,13 @@ _ = Task.Run(async () => {
await okxSocketClient.UnifiedApi.Trading.SubscribeToOrderUpdatesAsync(OKXInstrumentType.Spot, null, null, data => {
     // Handle update
 });
+
+
+
+
// It's required for the WhiteBit API to specify which symbols to subscribe to
+await whitebitSocketClient.V4Api.SubscribeToOpenOrderUpdatesAsync(["ETH_USDT", "BTC_USDT"], data => {
+    // Handle update
+});
 
InterfaceDescription
IWhiteBitRestClientThe client for accessing the WhiteBit REST API
IWhiteBitSocketClientThe client for accessing the WhiteBit Websocket API
IWhiteBitOrderBookFactoryA factory for creating SymbolOrderBook instances for the WhiteBit API
IWhiteBitTrackerFactoryA factory for creating kline and trade Tracker instances for the WhiteBit API
ICryptoRestClient An aggregating client from which multiple different library REST clients can be accessed