mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-10-04 10:21:13 +00:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c1af97dd4a | |||
| ecfe3cf392 | |||
| ac1e9cf2ab | |||
| 4987e6be70 | |||
| 9100c0d7f3 | |||
| 5b1ae30e4b | |||
| 36a06e8a9a | |||
| e7eb559074 | |||
| 79e2efec70 | |||
| c8c6d14329 | |||
| b8bd30a09d | |||
| c2b58ab19a | |||
| 90a031c595 | |||
| 860d753ad6 | |||
| e16c91792c | |||
| a3d95da9fa | |||
| 907399b878 | |||
| 9eab0d967e | |||
| 0dee68e8ae | |||
| d838d3377f | |||
| 2141ad9061 | |||
| 9be8798ccf | |||
| 4803ed91cd | |||
| 20bddd5c37 | |||
| 0e75ddb3d0 | |||
| 0e5b46002c | |||
| 8f7c71f9ce |
@@ -38,6 +38,14 @@ After calling `GetSpotSymbolsAsync`, `ISpotSymbolRestClient.SpotSymbolCatalog` m
|
|||||||
|
|
||||||
When implementing an exchange library, use `LibraryHelpers.IsStableCoin`, `IsCommodity`, and `IsEquity` only as best-effort classifiers and supply exchange-specific additions where needed.
|
When implementing an exchange library, use `LibraryHelpers.IsStableCoin`, `IsCommodity`, and `IsEquity` only as best-effort classifiers and supply exchange-specific additions where needed.
|
||||||
|
|
||||||
|
## Shared market-data quantities
|
||||||
|
|
||||||
|
In 12.4.0, use `SharedOrderQuantity`-valued `Volumes` on shared spot/futures tickers and klines, and `Quantities` on shared trades. The scalar `Volume`, `QuoteVolume`, and `Quantity` members are obsolete.
|
||||||
|
|
||||||
|
## WebSocket order commands
|
||||||
|
|
||||||
|
In 12.5.0, `ISpotOrderManagementSocketClient` and `IFuturesOrderManagementSocketClient` optionally provide place/cancel order commands over WebSocket. Their methods return `QueryResult<SharedId>`, not `WebSocketResult<UpdateSubscription>`. Check whether the exchange implements the interface.
|
||||||
|
|
||||||
## Result pattern
|
## Result pattern
|
||||||
|
|
||||||
REST methods return `HttpResult<T>` and websocket subscription methods return `WebSocketResult<UpdateSubscription>`. Always check `.Success`. `.Exchange` property identifies which exchange responded — useful for logging.
|
REST methods return `HttpResult<T>` and websocket subscription methods return `WebSocketResult<UpdateSubscription>`. Always check `.Success`. `.Exchange` property identifies which exchange responded — useful for logging.
|
||||||
@@ -45,7 +53,7 @@ REST methods return `HttpResult<T>` and websocket subscription methods return `W
|
|||||||
## Available shared interfaces
|
## Available shared interfaces
|
||||||
|
|
||||||
- REST tickers/symbols/orderbook/klines/trades, orders (spot/futures, regular/trigger/TP-SL), balances, positions, fees, deposits/withdrawals, transfers
|
- REST tickers/symbols/orderbook/klines/trades, orders (spot/futures, regular/trigger/TP-SL), balances, positions, fees, deposits/withdrawals, transfers
|
||||||
- WebSocket tickers, book tickers, order book, trades, klines, user data
|
- WebSocket tickers, book tickers, order book, trades, klines, user data, and optional spot/futures order management
|
||||||
|
|
||||||
Each exchange documents which it implements. Not every exchange supports every operation.
|
Each exchange documents which it implements. Not every exchange supports every operation.
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,14 @@ CryptoExchange.Net 12.2.0 classifies the base and quote sides of `SharedSpotSymb
|
|||||||
|
|
||||||
`ISpotSymbolRestClient.SpotSymbolCatalog` is populated by `GetSpotSymbolsAsync`; `IFuturesSymbolRestClient.FuturesSymbolCatalog` is populated by `GetFuturesSymbolsAsync`. Do not assume a catalog is available before that request. For exchange-library implementations, `LibraryHelpers.IsStableCoin`, `IsCommodity`, and `IsEquity` offer best-effort classification and can be extended with exchange-specific values.
|
`ISpotSymbolRestClient.SpotSymbolCatalog` is populated by `GetSpotSymbolsAsync`; `IFuturesSymbolRestClient.FuturesSymbolCatalog` is populated by `GetFuturesSymbolsAsync`. Do not assume a catalog is available before that request. For exchange-library implementations, `LibraryHelpers.IsStableCoin`, `IsCommodity`, and `IsEquity` offer best-effort classification and can be extended with exchange-specific values.
|
||||||
|
|
||||||
|
## Shared market-data quantities
|
||||||
|
|
||||||
|
CryptoExchange.Net 12.4.0 uses `SharedOrderQuantity` for market-data quantities. Prefer `Volumes` on `SharedSpotTicker`, `SharedFuturesTicker`, and `SharedKline`, and `Quantities` on `SharedTrade`; the scalar `Volume`, `QuoteVolume`, and `Quantity` members are obsolete.
|
||||||
|
|
||||||
|
## WebSocket order commands
|
||||||
|
|
||||||
|
CryptoExchange.Net 12.5.0 adds optional `ISpotOrderManagementSocketClient` and `IFuturesOrderManagementSocketClient` interfaces for placing and canceling orders over WebSocket. These command methods return `QueryResult<SharedId>` rather than a subscription result. Check exchange support before relying on either interface.
|
||||||
|
|
||||||
## Single-exchange code uses the exchange's own client
|
## Single-exchange code uses the exchange's own client
|
||||||
|
|
||||||
For Binance-only code, use `BinanceRestClient` directly (see Binance.Net repo `AGENTS.md`). SharedApis is for portability — use it when you need that.
|
For Binance-only code, use `BinanceRestClient` directly (see Binance.Net repo `AGENTS.md`). SharedApis is for portability — use it when you need that.
|
||||||
@@ -41,7 +49,7 @@ REST methods return `HttpResult<T>` and websocket subscription methods return `W
|
|||||||
## Available shared interfaces
|
## Available shared interfaces
|
||||||
|
|
||||||
REST: tickers, symbols, orderbook, klines, trades, orders (spot/futures, trigger, TP-SL), balances, positions, fees, deposits/withdrawals, transfers.
|
REST: tickers, symbols, orderbook, klines, trades, orders (spot/futures, trigger, TP-SL), balances, positions, fees, deposits/withdrawals, transfers.
|
||||||
WebSocket: tickers, book tickers, orderbook, trades, klines, user data.
|
WebSocket: tickers, book tickers, orderbook, trades, klines, user data, and optional spot/futures order management.
|
||||||
|
|
||||||
Each exchange library implements a subset. Check exchange docs for support matrix.
|
Each exchange library implements a subset. Check exchange docs for support matrix.
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,14 @@ After calling `GetSpotSymbolsAsync` or `GetFuturesSymbolsAsync`, use the client'
|
|||||||
|
|
||||||
For exchange-library implementations, `LibraryHelpers.IsStableCoin`, `IsCommodity`, and `IsEquity` provide best-effort classification of known assets and accept exchange-specific additions. These helpers are heuristics, not an exhaustive source of truth.
|
For exchange-library implementations, `LibraryHelpers.IsStableCoin`, `IsCommodity`, and `IsEquity` provide best-effort classification of known assets and accept exchange-specific additions. These helpers are heuristics, not an exhaustive source of truth.
|
||||||
|
|
||||||
|
## Shared Market-Data Quantities
|
||||||
|
|
||||||
|
Since CryptoExchange.Net 12.4.0, shared market-data models use `SharedOrderQuantity` so base-asset, quote-asset, and contract quantities remain explicit. Read `SharedSpotTicker.Volumes`, `SharedFuturesTicker.Volumes`, and `SharedKline.Volumes`; read `SharedTrade.Quantities`. The former scalar `Volume`, `QuoteVolume`, and `Quantity` members are obsolete.
|
||||||
|
|
||||||
|
## WebSocket Order Management
|
||||||
|
|
||||||
|
Since CryptoExchange.Net 12.5.0, exchanges can implement `ISpotOrderManagementSocketClient` and `IFuturesOrderManagementSocketClient` to place and cancel orders over WebSocket. These are command interfaces, not subscription interfaces: `Place*OrderAsync` and `Cancel*OrderAsync` return `QueryResult<SharedId>`. Check exchange support before using them.
|
||||||
|
|
||||||
## Available Shared Interfaces
|
## Available Shared Interfaces
|
||||||
|
|
||||||
**REST:**
|
**REST:**
|
||||||
@@ -98,6 +106,7 @@ For exchange-library implementations, `LibraryHelpers.IsStableCoin`, `IsCommodit
|
|||||||
- `ITickerSocketClient`, `IBookTickerSocketClient`
|
- `ITickerSocketClient`, `IBookTickerSocketClient`
|
||||||
- `IOrderBookSocketClient`, `ITradeSocketClient`, `IKlineSocketClient`
|
- `IOrderBookSocketClient`, `ITradeSocketClient`, `IKlineSocketClient`
|
||||||
- `IUserTradeSocketClient`, `ISpotOrderSocketClient`, `IFuturesOrderSocketClient`, `IPositionSocketClient`, `IBalanceSocketClient`
|
- `IUserTradeSocketClient`, `ISpotOrderSocketClient`, `IFuturesOrderSocketClient`, `IPositionSocketClient`, `IBalanceSocketClient`
|
||||||
|
- Order commands: `ISpotOrderManagementSocketClient`, `IFuturesOrderManagementSocketClient`
|
||||||
|
|
||||||
Each exchange documents which interfaces it implements (some exchanges don't support every operation).
|
Each exchange documents which interfaces it implements (some exchanges don't support every operation).
|
||||||
|
|
||||||
|
|||||||
@@ -96,23 +96,20 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
waiters.Add(evnt.WaitAsync());
|
waiters.Add(evnt.WaitAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<bool>? results = null;
|
var remaining = waiters.ToList();
|
||||||
var resultsWaiter = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await Task.WhenAll(waiters);
|
|
||||||
results = waiters.Select(w => w.Result).ToList();
|
|
||||||
});
|
|
||||||
|
|
||||||
for(var i = 1; i <= 10; i++)
|
for (var i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
evnt.Set();
|
evnt.Set();
|
||||||
await Task.Delay(1); // Wait for the continuation.
|
|
||||||
Assert.That(10 - i == waiters.Count(w => w.Status != TaskStatus.RanToCompletion));
|
var completed = await Task.WhenAny(remaining);
|
||||||
|
Assert.That(await completed, Is.True);
|
||||||
|
|
||||||
|
remaining.Remove(completed);
|
||||||
|
Assert.That(remaining.Count(w => w.IsCompleted), Is.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
await resultsWaiter;
|
Assert.That(remaining, Is.Empty);
|
||||||
|
|
||||||
Assert.That(10 == results?.Count(r => r));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using CryptoExchange.Net.Objects.Errors;
|
||||||
|
using CryptoExchange.Net.Objects.Sockets;
|
||||||
|
using CryptoExchange.Net.Sockets.Default;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.UnitTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class ManualUpdateSubscriptionTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void Constructor_Should_CreateSubscribedVirtualSubscription()
|
||||||
|
{
|
||||||
|
var controller = new ManualUpdateSubscription(socketId: 12);
|
||||||
|
|
||||||
|
Assert.That(controller.Subscription.SocketId, Is.EqualTo(12));
|
||||||
|
Assert.That(controller.Subscription.Id, Is.GreaterThan(0));
|
||||||
|
Assert.That(controller.Subscription.SocketStatus, Is.EqualTo(SocketStatus.Connected));
|
||||||
|
Assert.That(controller.Subscription.SubscriptionStatus, Is.EqualTo(SubscriptionStatus.Subscribed));
|
||||||
|
Assert.That(controller.Subscription.LastReceiveTime, Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StateChanges_Should_BeVisibleOnSubscription()
|
||||||
|
{
|
||||||
|
var controller = new ManualUpdateSubscription();
|
||||||
|
var timestamp = new DateTime(2026, 8, 5, 12, 0, 0, DateTimeKind.Utc);
|
||||||
|
var statuses = new List<SubscriptionStatus>();
|
||||||
|
controller.Subscription.SubscriptionStatusChanged += statuses.Add;
|
||||||
|
|
||||||
|
controller.SetLastReceiveTime(timestamp);
|
||||||
|
controller.SetSocketStatus(SocketStatus.Reconnecting);
|
||||||
|
controller.SetSubscriptionStatus(SubscriptionStatus.Subscribing);
|
||||||
|
controller.SetSubscriptionStatus(SubscriptionStatus.Subscribed);
|
||||||
|
|
||||||
|
Assert.That(controller.Subscription.LastReceiveTime, Is.EqualTo(timestamp));
|
||||||
|
Assert.That(controller.Subscription.SocketStatus, Is.EqualTo(SocketStatus.Reconnecting));
|
||||||
|
Assert.That(controller.Subscription.SubscriptionStatus, Is.EqualTo(SubscriptionStatus.Subscribed));
|
||||||
|
Assert.That(statuses, Is.EqualTo(new[]
|
||||||
|
{
|
||||||
|
SubscriptionStatus.Subscribing,
|
||||||
|
SubscriptionStatus.Subscribed
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void LifecycleMethods_Should_InvokeSubscriptionEvents()
|
||||||
|
{
|
||||||
|
var controller = new ManualUpdateSubscription();
|
||||||
|
var error = new ServerError("Test error", ErrorInfo.Unknown);
|
||||||
|
var exception = new InvalidOperationException("Test exception");
|
||||||
|
var disconnectedPeriod = TimeSpan.FromMinutes(2);
|
||||||
|
var lost = 0;
|
||||||
|
var restored = TimeSpan.Zero;
|
||||||
|
Error? resubscribeError = null;
|
||||||
|
var paused = 0;
|
||||||
|
var unpaused = 0;
|
||||||
|
Exception? receivedException = null;
|
||||||
|
|
||||||
|
controller.Subscription.ConnectionLost += () => lost++;
|
||||||
|
controller.Subscription.ConnectionRestored += x => restored = x;
|
||||||
|
controller.Subscription.ResubscribingFailed += x => resubscribeError = x;
|
||||||
|
controller.Subscription.ActivityPaused += () => paused++;
|
||||||
|
controller.Subscription.ActivityUnpaused += () => unpaused++;
|
||||||
|
controller.Subscription.Exception += x => receivedException = x;
|
||||||
|
|
||||||
|
controller.InvokeConnectionLost();
|
||||||
|
controller.InvokeConnectionRestored(disconnectedPeriod);
|
||||||
|
controller.InvokeResubscribingFailed(error);
|
||||||
|
controller.InvokeActivityPaused();
|
||||||
|
controller.InvokeActivityUnpaused();
|
||||||
|
controller.InvokeException(exception);
|
||||||
|
|
||||||
|
Assert.That(lost, Is.EqualTo(1));
|
||||||
|
Assert.That(restored, Is.EqualTo(disconnectedPeriod));
|
||||||
|
Assert.That(resubscribeError, Is.SameAs(error));
|
||||||
|
Assert.That(paused, Is.EqualTo(1));
|
||||||
|
Assert.That(unpaused, Is.EqualTo(1));
|
||||||
|
Assert.That(receivedException, Is.SameAs(exception));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void InvokeConnectionClosed_Should_CloseAndOnlyInvokeOnce()
|
||||||
|
{
|
||||||
|
var controller = new ManualUpdateSubscription();
|
||||||
|
var closed = 0;
|
||||||
|
controller.Subscription.ConnectionClosed += () => closed++;
|
||||||
|
|
||||||
|
controller.InvokeConnectionClosed();
|
||||||
|
controller.InvokeConnectionClosed();
|
||||||
|
|
||||||
|
Assert.That(closed, Is.EqualTo(1));
|
||||||
|
Assert.That(controller.Subscription.SocketStatus, Is.EqualTo(SocketStatus.Closed));
|
||||||
|
Assert.That(controller.Subscription.SubscriptionStatus, Is.EqualTo(SubscriptionStatus.Closed));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task SubscriptionOperations_Should_InvokeCallbacks()
|
||||||
|
{
|
||||||
|
var closes = 0;
|
||||||
|
var reconnects = 0;
|
||||||
|
var resubscribes = 0;
|
||||||
|
var controller = new ManualUpdateSubscription(
|
||||||
|
closeAsync: () =>
|
||||||
|
{
|
||||||
|
closes++;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
},
|
||||||
|
reconnectAsync: () =>
|
||||||
|
{
|
||||||
|
reconnects++;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
},
|
||||||
|
resubscribeAsync: () =>
|
||||||
|
{
|
||||||
|
resubscribes++;
|
||||||
|
return Task.FromResult(CallResult.Ok());
|
||||||
|
});
|
||||||
|
|
||||||
|
await controller.Subscription.ReconnectAsync();
|
||||||
|
var resubscribeResult = await controller.Subscription.ResubscribeAsync();
|
||||||
|
await controller.Subscription.CloseAsync();
|
||||||
|
await controller.Subscription.CloseAsync();
|
||||||
|
|
||||||
|
Assert.That(reconnects, Is.EqualTo(1));
|
||||||
|
Assert.That(resubscribes, Is.EqualTo(1));
|
||||||
|
Assert.That(resubscribeResult.Success, Is.True);
|
||||||
|
Assert.That(closes, Is.EqualTo(1));
|
||||||
|
Assert.That(controller.Subscription.SubscriptionStatus, Is.EqualTo(SubscriptionStatus.Closed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -97,6 +97,11 @@ namespace CryptoExchange.Net.Clients
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected bool AllowTopicsOnTheSameConnection { get; set; } = true;
|
protected bool AllowTopicsOnTheSameConnection { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to allow usage of a current public WebSocket connection for an authenticated request
|
||||||
|
/// </summary>
|
||||||
|
protected bool UsePublicConnectionForAuth { get; set; } = false;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public double IncomingKbps
|
public double IncomingKbps
|
||||||
{
|
{
|
||||||
@@ -688,7 +693,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
_logger.WaitedForReconnectingSocket((long)(DateTime.UtcNow - delayStart).TotalMilliseconds);
|
_logger.WaitedForReconnectingSocket((long)(DateTime.UtcNow - delayStart).TotalMilliseconds);
|
||||||
|
|
||||||
socketQuery = socketQuery.Where(s => (s.Status == SocketStatus.None || s.Status == SocketStatus.Connected)
|
socketQuery = socketQuery.Where(s => (s.Status == SocketStatus.None || s.Status == SocketStatus.Connected)
|
||||||
&& (s.Authenticated == authenticated || !authenticated)
|
&& (s.Authenticated == authenticated || !authenticated || UsePublicConnectionForAuth)
|
||||||
&& s.Connected).ToList();
|
&& s.Connected).ToList();
|
||||||
|
|
||||||
bool maxConnectionsReached = _socketConnections.Count >= (ApiOptions.MaxSocketConnections ?? ClientOptions.MaxSocketConnections);
|
bool maxConnectionsReached = _socketConnections.Count >= (ApiOptions.MaxSocketConnections ?? ClientOptions.MaxSocketConnections);
|
||||||
@@ -702,12 +707,14 @@ namespace CryptoExchange.Net.Clients
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (connection == null)
|
if (connection == null)
|
||||||
|
{
|
||||||
// Use an eligible non-dedicated connection for subscriptions, or as fallback when no dedicated request connection is available
|
// Use an eligible non-dedicated connection for subscriptions, or as fallback when no dedicated request connection is available
|
||||||
connection = socketQuery
|
connection = socketQuery
|
||||||
.Where(s => !s.DedicatedRequestConnection.IsDedicatedRequestConnection)
|
.Where(s => !s.DedicatedRequestConnection.IsDedicatedRequestConnection)
|
||||||
.Where(s => IsConnectionEligible(s, individualSubscriptionCount, maxConnectionsReached))
|
.Where(s => IsConnectionEligible(s, individualSubscriptionCount, maxConnectionsReached))
|
||||||
.OrderBy(s => s.UserSubscriptionCount)
|
.OrderBy(s => s.UserSubscriptionCount)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
return CallResult.Ok(connection);
|
return CallResult.Ok(connection);
|
||||||
@@ -786,7 +793,9 @@ namespace CryptoExchange.Net.Clients
|
|||||||
|
|
||||||
if ((!lessThanBatchSubCombineTarget || !lessThanIndividualSubCombineTarget)
|
if ((!lessThanBatchSubCombineTarget || !lessThanIndividualSubCombineTarget)
|
||||||
&& !maxConnectionsReached)
|
&& !maxConnectionsReached)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return MaxIndividualSubscriptionsPerConnection == null
|
return MaxIndividualSubscriptionsPerConnection == null
|
||||||
|| currentIndividualSubscriptionCount + individualSubscriptionCount <= MaxIndividualSubscriptionsPerConnection;
|
|| currentIndividualSubscriptionCount + individualSubscriptionCount <= MaxIndividualSubscriptionsPerConnection;
|
||||||
|
|||||||
@@ -14,21 +14,19 @@ using System.Text;
|
|||||||
namespace CryptoExchange.Net.Clients
|
namespace CryptoExchange.Net.Clients
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract class UserClientProvider<TRestClient, TSocketClient, TRestOptions, TSocketOptions, TCredentials, TEnvironment>
|
public abstract class UserClientProvider<TRestClient, TRestOptions, TCredentials, TEnvironment>
|
||||||
where TRestClient : IRestClient<TCredentials>
|
where TRestClient : IRestClient<TCredentials>
|
||||||
where TSocketClient : ISocketClient<TCredentials>
|
|
||||||
where TRestOptions : RestExchangeOptions<TEnvironment, TCredentials>, new()
|
where TRestOptions : RestExchangeOptions<TEnvironment, TCredentials>, new()
|
||||||
where TSocketOptions : SocketExchangeOptions<TEnvironment, TCredentials>, new()
|
|
||||||
where TCredentials : ApiCredentials
|
where TCredentials : ApiCredentials
|
||||||
where TEnvironment : TradeEnvironment
|
where TEnvironment : TradeEnvironment
|
||||||
{
|
{
|
||||||
private ConcurrentDictionary<string, TRestClient> _restClients = new ConcurrentDictionary<string, TRestClient>();
|
private ConcurrentDictionary<string, TRestClient> _restClients = new ConcurrentDictionary<string, TRestClient>();
|
||||||
private ConcurrentDictionary<string, TSocketClient> _socketClients = new ConcurrentDictionary<string, TSocketClient>();
|
|
||||||
|
|
||||||
private readonly IOptions<TRestOptions> _restOptions;
|
private readonly IOptions<TRestOptions> _restOptions;
|
||||||
private readonly IOptions<TSocketOptions> _socketOptions;
|
|
||||||
private readonly HttpClient _httpClient;
|
private readonly HttpClient _httpClient;
|
||||||
private readonly ILoggerFactory? _loggerFactory;
|
/// <summary>
|
||||||
|
/// Logger factory
|
||||||
|
/// </summary>
|
||||||
|
protected readonly ILoggerFactory? _loggerFactory;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public abstract string ExchangeName { get; }
|
public abstract string ExchangeName { get; }
|
||||||
@@ -39,17 +37,14 @@ namespace CryptoExchange.Net.Clients
|
|||||||
public UserClientProvider(
|
public UserClientProvider(
|
||||||
HttpClient? httpClient,
|
HttpClient? httpClient,
|
||||||
ILoggerFactory? loggerFactory,
|
ILoggerFactory? loggerFactory,
|
||||||
IOptions<TRestOptions> restOptions,
|
IOptions<TRestOptions> restOptions)
|
||||||
IOptions<TSocketOptions> socketOptions)
|
|
||||||
{
|
{
|
||||||
_httpClient = httpClient ?? new HttpClient();
|
_httpClient = httpClient ?? new HttpClient();
|
||||||
_httpClient.Timeout = restOptions.Value.RequestTimeout;
|
_httpClient.Timeout = restOptions.Value.RequestTimeout;
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
_restOptions = restOptions;
|
_restOptions = restOptions;
|
||||||
_socketOptions = socketOptions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private IOptions<TRestOptions> SetRestEnvironment(IOptions<TRestOptions> options, TEnvironment? environment)
|
private IOptions<TRestOptions> SetRestEnvironment(IOptions<TRestOptions> options, TEnvironment? environment)
|
||||||
{
|
{
|
||||||
if (environment == null)
|
if (environment == null)
|
||||||
@@ -61,22 +56,10 @@ namespace CryptoExchange.Net.Clients
|
|||||||
return Options.Create(newRestClientOptions);
|
return Options.Create(newRestClientOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IOptions<TSocketOptions> SetSocketEnvironment(IOptions<TSocketOptions> options, TEnvironment? environment)
|
|
||||||
{
|
|
||||||
if (environment == null)
|
|
||||||
return options;
|
|
||||||
|
|
||||||
var newSocketClientOptions = new TSocketOptions();
|
|
||||||
options.Value.Set(newSocketClientOptions);
|
|
||||||
newSocketClientOptions.Environment = environment;
|
|
||||||
return Options.Create(newSocketClientOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void InitializeUserClient(string userIdentifier, TCredentials credentials, TEnvironment? environment = null)
|
public virtual void InitializeUserClient(string userIdentifier, TCredentials credentials, TEnvironment? environment = null)
|
||||||
{
|
{
|
||||||
CreateRestClient(userIdentifier, credentials, environment);
|
CreateRestClient(userIdentifier, credentials, environment);
|
||||||
CreateSocketClient(userIdentifier, credentials, environment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -88,15 +71,6 @@ namespace CryptoExchange.Net.Clients
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public TSocketClient GetSocketClient(string userIdentifier, TCredentials? credentials = null, TEnvironment? environment = null)
|
|
||||||
{
|
|
||||||
if (!_socketClients.TryGetValue(userIdentifier, out var client) || client.Disposed)
|
|
||||||
client = CreateSocketClient(userIdentifier, credentials, environment);
|
|
||||||
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TRestClient CreateRestClient(string userIdentifier, TCredentials? credentials, TEnvironment? environment)
|
private TRestClient CreateRestClient(string userIdentifier, TCredentials? credentials, TEnvironment? environment)
|
||||||
{
|
{
|
||||||
var clientRestOptions = SetRestEnvironment(_restOptions, environment);
|
var clientRestOptions = SetRestEnvironment(_restOptions, environment);
|
||||||
@@ -109,6 +83,94 @@ namespace CryptoExchange.Net.Clients
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new instance of the rest client
|
||||||
|
/// </summary>
|
||||||
|
protected abstract TRestClient ConstructRestClient(
|
||||||
|
HttpClient client,
|
||||||
|
ILoggerFactory? loggerFactory,
|
||||||
|
IOptions<TRestOptions> options);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual void ClearUserClients(string userIdentifier)
|
||||||
|
{
|
||||||
|
_restClients.TryRemove(userIdentifier, out var restClient);
|
||||||
|
restClient?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual void Clear()
|
||||||
|
{
|
||||||
|
foreach (var client in _restClients.Values)
|
||||||
|
client.Dispose();
|
||||||
|
_restClients.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the provided options delegate to a new instance of the specified type.
|
||||||
|
/// </summary>
|
||||||
|
protected static T ApplyOptionsDelegate<T>(Action<T>? del) where T : new()
|
||||||
|
{
|
||||||
|
var opts = new T();
|
||||||
|
del?.Invoke(opts);
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public abstract class UserClientProvider<TRestClient, TSocketClient, TRestOptions, TSocketOptions, TCredentials, TEnvironment>
|
||||||
|
: UserClientProvider<TRestClient, TRestOptions, TCredentials, TEnvironment>
|
||||||
|
where TRestClient : IRestClient<TCredentials>
|
||||||
|
where TSocketClient : ISocketClient<TCredentials>
|
||||||
|
where TRestOptions : RestExchangeOptions<TEnvironment, TCredentials>, new()
|
||||||
|
where TSocketOptions : SocketExchangeOptions<TEnvironment, TCredentials>, new()
|
||||||
|
where TCredentials : ApiCredentials
|
||||||
|
where TEnvironment : TradeEnvironment
|
||||||
|
{
|
||||||
|
private ConcurrentDictionary<string, TSocketClient> _socketClients = new ConcurrentDictionary<string, TSocketClient>();
|
||||||
|
private readonly IOptions<TSocketOptions> _socketOptions;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
public UserClientProvider(
|
||||||
|
HttpClient? httpClient,
|
||||||
|
ILoggerFactory? loggerFactory,
|
||||||
|
IOptions<TRestOptions> restOptions,
|
||||||
|
IOptions<TSocketOptions> socketOptions)
|
||||||
|
: base(httpClient, loggerFactory, restOptions)
|
||||||
|
{
|
||||||
|
_socketOptions = socketOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IOptions<TSocketOptions> SetSocketEnvironment(IOptions<TSocketOptions> options, TEnvironment? environment)
|
||||||
|
{
|
||||||
|
if (environment == null)
|
||||||
|
return options;
|
||||||
|
|
||||||
|
var newSocketClientOptions = new TSocketOptions();
|
||||||
|
options.Value.Set(newSocketClientOptions);
|
||||||
|
newSocketClientOptions.Environment = environment;
|
||||||
|
return Options.Create(newSocketClientOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override void InitializeUserClient(string userIdentifier, TCredentials credentials, TEnvironment? environment = null)
|
||||||
|
{
|
||||||
|
base.InitializeUserClient(userIdentifier, credentials, environment);
|
||||||
|
CreateSocketClient(userIdentifier, credentials, environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public TSocketClient GetSocketClient(string userIdentifier, TCredentials? credentials = null, TEnvironment? environment = null)
|
||||||
|
{
|
||||||
|
if (!_socketClients.TryGetValue(userIdentifier, out var client) || client.Disposed)
|
||||||
|
client = CreateSocketClient(userIdentifier, credentials, environment);
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
private TSocketClient CreateSocketClient(string userIdentifier, TCredentials? credentials, TEnvironment? environment)
|
private TSocketClient CreateSocketClient(string userIdentifier, TCredentials? credentials, TEnvironment? environment)
|
||||||
{
|
{
|
||||||
var clientSocketOptions = SetSocketEnvironment(_socketOptions, environment);
|
var clientSocketOptions = SetSocketEnvironment(_socketOptions, environment);
|
||||||
@@ -121,15 +183,6 @@ namespace CryptoExchange.Net.Clients
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructs a new instance of the rest client
|
|
||||||
/// </summary>
|
|
||||||
protected abstract TRestClient ConstructRestClient(
|
|
||||||
HttpClient client,
|
|
||||||
ILoggerFactory? loggerFactory,
|
|
||||||
IOptions<TRestOptions> options);
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new instance of the socket client
|
/// Constructs a new instance of the socket client
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -137,36 +190,23 @@ namespace CryptoExchange.Net.Clients
|
|||||||
ILoggerFactory? loggerFactory,
|
ILoggerFactory? loggerFactory,
|
||||||
IOptions<TSocketOptions> options);
|
IOptions<TSocketOptions> options);
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void ClearUserClients(string userIdentifier)
|
public override void ClearUserClients(string userIdentifier)
|
||||||
{
|
{
|
||||||
_restClients.TryRemove(userIdentifier, out var restClient);
|
base.ClearUserClients(userIdentifier);
|
||||||
|
|
||||||
_socketClients.TryRemove(userIdentifier, out var socketClient);
|
_socketClients.TryRemove(userIdentifier, out var socketClient);
|
||||||
restClient?.Dispose();
|
|
||||||
socketClient?.Dispose();
|
socketClient?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Clear()
|
public override void Clear()
|
||||||
{
|
{
|
||||||
foreach (var client in _restClients.Values)
|
base.Clear();
|
||||||
client.Dispose();
|
|
||||||
_restClients.Clear();
|
|
||||||
|
|
||||||
foreach (var client in _socketClients.Values)
|
foreach (var client in _socketClients.Values)
|
||||||
client.Dispose();
|
client.Dispose();
|
||||||
_socketClients.Clear();
|
_socketClients.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Applies the provided options delegate to a new instance of the specified type.
|
|
||||||
/// </summary>
|
|
||||||
protected static T ApplyOptionsDelegate<T>(Action<T>? del) where T : new()
|
|
||||||
{
|
|
||||||
var opts = new T();
|
|
||||||
del?.Invoke(opts);
|
|
||||||
return opts;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -88,7 +88,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson.MessageHandlers
|
|||||||
stream.Seek(0, SeekOrigin.Begin);
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
var written = new StreamReader(stream).ReadBlock(dataSnippet, 0, _errorResponseSnippetLimit);
|
var written = new StreamReader(stream).ReadBlock(dataSnippet, 0, _errorResponseSnippetLimit);
|
||||||
var data = new string(dataSnippet, 0, written);
|
var data = new string(dataSnippet, 0, written);
|
||||||
errorMsg += $": {data}";
|
errorMsg += $": {(string.IsNullOrEmpty(data) ? "(empty)" : data)}";
|
||||||
if (data.Length == _errorResponseSnippetLimit)
|
if (data.Length == _errorResponseSnippetLimit)
|
||||||
errorMsg += " (truncated)";
|
errorMsg += " (truncated)";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
<PackageId>CryptoExchange.Net</PackageId>
|
<PackageId>CryptoExchange.Net</PackageId>
|
||||||
<Authors>JKorf</Authors>
|
<Authors>JKorf</Authors>
|
||||||
<Description>CryptoExchange.Net is a base library which is used to implement different cryptocurrency (exchange) API's. It provides a standardized way of implementing different API's, which results in a very similar experience for users of the API implementations.</Description>
|
<Description>CryptoExchange.Net is a base library which is used to implement different cryptocurrency (exchange) API's. It provides a standardized way of implementing different API's, which results in a very similar experience for users of the API implementations.</Description>
|
||||||
<PackageVersion>12.3.0</PackageVersion>
|
<PackageVersion>12.5.0</PackageVersion>
|
||||||
<AssemblyVersion>12.3.0</AssemblyVersion>
|
<AssemblyVersion>12.5.0</AssemblyVersion>
|
||||||
<FileVersion>12.3.0</FileVersion>
|
<FileVersion>12.5.0</FileVersion>
|
||||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||||
<PackageTags>OKX;OKX.Net;Mexc;Mexc.Net;Kucoin;Kucoin.Net;Kraken;Kraken.Net;Huobi;Huobi.Net;CoinEx;CoinEx.Net;Bybit;Bybit.Net;Bitget;Bitget.Net;Bitfinex;Bitfinex.Net;Binance;Binance.Net;CryptoCurrency;CryptoCurrency Exchange;CryptoExchange.Net</PackageTags>
|
<PackageTags>OKX;OKX.Net;Mexc;Mexc.Net;Kucoin;Kucoin.Net;Kraken;Kraken.Net;Huobi;Huobi.Net;CoinEx;CoinEx.Net;Bybit;Bybit.Net;Bitget;Bitget.Net;Bitfinex;Bitfinex.Net;Binance;Binance.Net;CryptoCurrency;CryptoCurrency Exchange;CryptoExchange.Net</PackageTags>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
|
|||||||
@@ -461,11 +461,15 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
if (typeof(ISpotOrderSocketClient).IsAssignableFrom(typeof(T)))
|
if (typeof(ISpotOrderSocketClient).IsAssignableFrom(typeof(T)))
|
||||||
services.AddTransient(x => (ISpotOrderSocketClient)client(x)!);
|
services.AddTransient(x => (ISpotOrderSocketClient)client(x)!);
|
||||||
|
if (typeof(ISpotOrderManagementSocketClient).IsAssignableFrom(typeof(T)))
|
||||||
|
services.AddTransient(x => (ISpotOrderManagementSocketClient)client(x)!);
|
||||||
|
|
||||||
if (typeof(IFuturesOrderSocketClient).IsAssignableFrom(typeof(T)))
|
if (typeof(IFuturesOrderSocketClient).IsAssignableFrom(typeof(T)))
|
||||||
services.AddTransient(x => (IFuturesOrderSocketClient)client(x)!);
|
services.AddTransient(x => (IFuturesOrderSocketClient)client(x)!);
|
||||||
if (typeof(IPositionSocketClient).IsAssignableFrom(typeof(T)))
|
if (typeof(IPositionSocketClient).IsAssignableFrom(typeof(T)))
|
||||||
services.AddTransient(x => (IPositionSocketClient)client(x)!);
|
services.AddTransient(x => (IPositionSocketClient)client(x)!);
|
||||||
|
if (typeof(IFuturesOrderManagementSocketClient).IsAssignableFrom(typeof(T)))
|
||||||
|
services.AddTransient(x => (IFuturesOrderManagementSocketClient)client(x)!);
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ namespace CryptoExchange.Net.Logging.Extensions
|
|||||||
_receivedMessageNotMatchedToAnyListener = LoggerMessage.Define<int, string, string, string>(
|
_receivedMessageNotMatchedToAnyListener = LoggerMessage.Define<int, string, string, string>(
|
||||||
LogLevel.Warning,
|
LogLevel.Warning,
|
||||||
new EventId(2029, "ReceivedMessageNotMatchedToAnyListener"),
|
new EventId(2029, "ReceivedMessageNotMatchedToAnyListener"),
|
||||||
"[Sckt {SocketId}] received message not matched to any listener. TypeIdentifier: {TypeIdentifier}, ListenId: {ListenId}, current listeners: [{ListenIds}]");
|
"[Sckt {SocketId}] received message not matched to any listener. TypeIdentifier: {TypeIdentifier}, TopicFilter: {ListenId}, registered TopicFilters for type: [{TopicFilters}]");
|
||||||
|
|
||||||
_failedToParse = LoggerMessage.Define<int, string>(
|
_failedToParse = LoggerMessage.Define<int, string>(
|
||||||
LogLevel.Warning,
|
LogLevel.Warning,
|
||||||
@@ -326,9 +326,9 @@ namespace CryptoExchange.Net.Logging.Extensions
|
|||||||
_sendingData(logger, socketId, requestId, data, null);
|
_sendingData(logger, socketId, requestId, data, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ReceivedMessageNotMatchedToAnyListener(this ILogger logger, int socketId, string typeIdentifier, string listenId, string listenIds)
|
public static void ReceivedMessageNotMatchedToAnyListener(this ILogger logger, int socketId, string typeIdentifier, string topicFilter, string topicFilters)
|
||||||
{
|
{
|
||||||
_receivedMessageNotMatchedToAnyListener(logger, socketId, typeIdentifier, listenId, listenIds, null);
|
_receivedMessageNotMatchedToAnyListener(logger, socketId, typeIdentifier, topicFilter, topicFilters, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SendingByteData(this ILogger logger, int socketId, int requestId, int length)
|
public static void SendingByteData(this ILogger logger, int socketId, int requestId, int length)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -8,8 +9,11 @@ namespace CryptoExchange.Net.Objects;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Call result
|
/// Call result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{DebugView,nq}")]
|
||||||
public record CallResult : ICallResult
|
public record CallResult : ICallResult
|
||||||
{
|
{
|
||||||
|
private string DebugView => Success ? "Success" : $"Error: {Error}";
|
||||||
|
|
||||||
private static CallResult _successResult = new CallResult();
|
private static CallResult _successResult = new CallResult();
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using CryptoExchange.Net.SharedApis;
|
using CryptoExchange.Net.SharedApis;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
@@ -12,8 +13,11 @@ namespace CryptoExchange.Net.Objects;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// HTTP call result
|
/// HTTP call result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{DebugView,nq}")]
|
||||||
public record HttpResult : IHttpResult
|
public record HttpResult : IHttpResult
|
||||||
{
|
{
|
||||||
|
private string DebugView => $"[Req {RequestId}] " + (Success ? "Success" : $"Error: {Error}");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new success HTTP result
|
/// Create a new success HTTP result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -251,8 +255,32 @@ public record HttpResult : IHttpResult
|
|||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
[DebuggerDisplay("{DebugView,nq}")]
|
||||||
public record HttpResult<T> : HttpResult, IHttpResult<T>
|
public record HttpResult<T> : HttpResult, IHttpResult<T>
|
||||||
{
|
{
|
||||||
|
private string DebugView
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var result = new StringBuilder($"[Req {RequestId}] " + (Success ? "Success" : $"Error: {Error}"));
|
||||||
|
if (Data != null)
|
||||||
|
{
|
||||||
|
result.Append(", ");
|
||||||
|
var typeName = typeof(T).Name;
|
||||||
|
if (Data is Array ar)
|
||||||
|
{
|
||||||
|
result.Append($"{ar.Length} {typeName.Substring(0, typeName.Length - 2)}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Append(typeName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -8,8 +9,11 @@ namespace CryptoExchange.Net.Objects;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// WebSocket call result
|
/// WebSocket call result
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{DebugView,nq}")]
|
||||||
public record WebSocketResult : IWebSocketResult
|
public record WebSocketResult : IWebSocketResult
|
||||||
{
|
{
|
||||||
|
private string DebugView => $"[Sckt {ConnectionId}] " + (RequestId == null ? "" : $"[Req {RequestId}] ") + (Success ? "Success" : $"Error: {Error}");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -183,7 +187,7 @@ public record WebSocketResult<T> : WebSocketResult, IWebSocketResult<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public record QueryResult : WebSocketResult
|
public record QueryResult : WebSocketResult, IQueryResult
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
@@ -208,6 +212,8 @@ public record QueryResult : WebSocketResult
|
|||||||
Url = result.Url,
|
Url = result.Url,
|
||||||
RequestId = result.RequestId,
|
RequestId = result.RequestId,
|
||||||
ResponseTime = result.ResponseTime,
|
ResponseTime = result.ResponseTime,
|
||||||
|
OriginalData = result.OriginalData,
|
||||||
|
RequestBody = result.RequestBody
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -288,6 +294,9 @@ public record QueryResult : WebSocketResult
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string? RequestBody { get; init; }
|
public string? RequestBody { get; init; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string? OriginalData { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -314,7 +323,4 @@ public record QueryResult<T> : QueryResult, IQueryResult<T>
|
|||||||
public new bool Success => Error == null;
|
public new bool Success => Error == null;
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public T? Data { get; set; }
|
public T? Data { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public string? OriginalData { get; init; }
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,209 @@
|
|||||||
|
using CryptoExchange.Net.Sockets;
|
||||||
|
using CryptoExchange.Net.Sockets.Default;
|
||||||
|
using CryptoExchange.Net.Sockets.Default.Routing;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.Objects.Sockets
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Controller for an update subscription which isn't backed by a websocket connection. Can be used for testing.
|
||||||
|
/// </summary>
|
||||||
|
public class ManualUpdateSubscription
|
||||||
|
{
|
||||||
|
private readonly Func<Task> _closeAsync;
|
||||||
|
private readonly Func<Task> _reconnectAsync;
|
||||||
|
private readonly Func<Task<CallResult>> _resubscribeAsync;
|
||||||
|
private readonly ManualSubscription _manualSubscription;
|
||||||
|
private int _closedEventInvoked;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The update subscription
|
||||||
|
/// </summary>
|
||||||
|
public UpdateSubscription Subscription { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The virtual socket id
|
||||||
|
/// </summary>
|
||||||
|
public int SocketId { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The last timestamp anything was received by the subscription
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? LastReceiveTime { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current virtual websocket status
|
||||||
|
/// </summary>
|
||||||
|
public SocketStatus SocketStatus { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a manually controlled update subscription
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="socketId">The virtual socket id</param>
|
||||||
|
/// <param name="closeAsync">Callback when the subscription is closed</param>
|
||||||
|
/// <param name="reconnectAsync">Callback when a reconnect is requested</param>
|
||||||
|
/// <param name="resubscribeAsync">Callback when a resubscribe is requested</param>
|
||||||
|
public ManualUpdateSubscription(
|
||||||
|
int socketId = 0,
|
||||||
|
Func<Task>? closeAsync = null,
|
||||||
|
Func<Task>? reconnectAsync = null,
|
||||||
|
Func<Task<CallResult>>? resubscribeAsync = null)
|
||||||
|
{
|
||||||
|
SocketId = socketId;
|
||||||
|
SocketStatus = SocketStatus.Connected;
|
||||||
|
_closeAsync = closeAsync ?? (() => Task.CompletedTask);
|
||||||
|
_reconnectAsync = reconnectAsync ?? (() => Task.CompletedTask);
|
||||||
|
_resubscribeAsync = resubscribeAsync ?? (() => Task.FromResult(CallResult.Ok()));
|
||||||
|
|
||||||
|
_manualSubscription = new ManualSubscription();
|
||||||
|
_manualSubscription.Status = SubscriptionStatus.Subscribed;
|
||||||
|
Subscription = new UpdateSubscription(this, _manualSubscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the last timestamp anything was received by the subscription
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="timestamp">The receive timestamp</param>
|
||||||
|
public void SetLastReceiveTime(DateTime? timestamp)
|
||||||
|
{
|
||||||
|
LastReceiveTime = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the virtual websocket status
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="status">The status</param>
|
||||||
|
public void SetSocketStatus(SocketStatus status)
|
||||||
|
{
|
||||||
|
SocketStatus = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the subscription status
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="status">The status</param>
|
||||||
|
public void SetSubscriptionStatus(SubscriptionStatus status)
|
||||||
|
{
|
||||||
|
_manualSubscription.Status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoke the connection lost event
|
||||||
|
/// </summary>
|
||||||
|
public void InvokeConnectionLost()
|
||||||
|
{
|
||||||
|
Subscription.HandleConnectionLostEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoke the connection restored event
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disconnectedPeriod">The period the connection was disconnected</param>
|
||||||
|
public void InvokeConnectionRestored(TimeSpan disconnectedPeriod)
|
||||||
|
{
|
||||||
|
Subscription.HandleConnectionRestoredEvent(disconnectedPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoke the connection closed event
|
||||||
|
/// </summary>
|
||||||
|
public void InvokeConnectionClosed()
|
||||||
|
{
|
||||||
|
if (Interlocked.Exchange(ref _closedEventInvoked, 1) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SocketStatus = SocketStatus.Closed;
|
||||||
|
_manualSubscription.Status = SubscriptionStatus.Closed;
|
||||||
|
Subscription.HandleConnectionClosedEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoke the resubscribing failed event
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="error">The resubscribe error</param>
|
||||||
|
public void InvokeResubscribingFailed(Error error)
|
||||||
|
{
|
||||||
|
if (error == null)
|
||||||
|
throw new ArgumentNullException(nameof(error));
|
||||||
|
|
||||||
|
Subscription.HandleResubscribeFailedEvent(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoke the activity paused event
|
||||||
|
/// </summary>
|
||||||
|
public void InvokeActivityPaused()
|
||||||
|
{
|
||||||
|
Subscription.HandlePausedEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoke the activity unpaused event
|
||||||
|
/// </summary>
|
||||||
|
public void InvokeActivityUnpaused()
|
||||||
|
{
|
||||||
|
Subscription.HandleUnpausedEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invoke the exception event
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">The exception</param>
|
||||||
|
public void InvokeException(Exception exception)
|
||||||
|
{
|
||||||
|
if (exception == null)
|
||||||
|
throw new ArgumentNullException(nameof(exception));
|
||||||
|
|
||||||
|
_manualSubscription.InvokeExceptionHandler(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task CloseAsync()
|
||||||
|
{
|
||||||
|
if (_manualSubscription.Status == SubscriptionStatus.Closed
|
||||||
|
|| _manualSubscription.Status == SubscriptionStatus.Closing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_manualSubscription.Status = SubscriptionStatus.Closing;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _closeAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_manualSubscription.Status = SubscriptionStatus.Closed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Task ReconnectAsync()
|
||||||
|
{
|
||||||
|
return _reconnectAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Task<CallResult> ResubscribeAsync()
|
||||||
|
{
|
||||||
|
return _resubscribeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ManualSubscription : Subscription
|
||||||
|
{
|
||||||
|
public ManualSubscription()
|
||||||
|
: base(NullLogger.Instance, false)
|
||||||
|
{
|
||||||
|
MessageRouter = MessageRouter.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Query? GetSubQuery(SocketConnection connection)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Query? GetUnsubQuery(SocketConnection connection)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,8 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class UpdateSubscription
|
public class UpdateSubscription
|
||||||
{
|
{
|
||||||
private readonly SocketConnection _connection;
|
private readonly SocketConnection? _connection;
|
||||||
|
private readonly ManualUpdateSubscription? _manualSubscription;
|
||||||
internal readonly Subscription _subscription;
|
internal readonly Subscription _subscription;
|
||||||
|
|
||||||
#if NET9_0_OR_GREATER
|
#if NET9_0_OR_GREATER
|
||||||
@@ -102,7 +103,7 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The id of the socket
|
/// The id of the socket
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int SocketId => _connection.SocketId;
|
public int SocketId => _connection?.SocketId ?? _manualSubscription!.SocketId;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The id of the subscription
|
/// The id of the subscription
|
||||||
@@ -112,12 +113,12 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The last timestamp anything was received from the server
|
/// The last timestamp anything was received from the server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public DateTime? LastReceiveTime => _connection.LastReceiveTime;
|
public DateTime? LastReceiveTime => _connection?.LastReceiveTime ?? _manualSubscription!.LastReceiveTime;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current websocket status
|
/// The current websocket status
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SocketStatus SocketStatus => _connection.Status;
|
public SocketStatus SocketStatus => _connection?.Status ?? _manualSubscription!.SocketStatus;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The current subscription status
|
/// The current subscription status
|
||||||
@@ -143,6 +144,18 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
_subscription.StatusChanged += (x) => SubscriptionStatusChanged?.Invoke(x);
|
_subscription.StatusChanged += (x) => SubscriptionStatusChanged?.Invoke(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="manualSubscription">The manual subscription for controlling events and data</param>
|
||||||
|
/// <param name="subscription">The subscription</param>
|
||||||
|
internal UpdateSubscription(ManualUpdateSubscription manualSubscription, Subscription subscription)
|
||||||
|
{
|
||||||
|
_manualSubscription = manualSubscription;
|
||||||
|
_subscription = subscription;
|
||||||
|
_subscription.StatusChanged += (x) => SubscriptionStatusChanged?.Invoke(x);
|
||||||
|
}
|
||||||
|
|
||||||
private void UnsubscribeConnectionEvents()
|
private void UnsubscribeConnectionEvents()
|
||||||
{
|
{
|
||||||
lock (_eventLock)
|
lock (_eventLock)
|
||||||
@@ -150,22 +163,26 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
if (!_connectionEventsSubscribed)
|
if (!_connectionEventsSubscribed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (_connection != null)
|
||||||
|
{
|
||||||
_connection.ConnectionClosed -= HandleConnectionClosedEvent;
|
_connection.ConnectionClosed -= HandleConnectionClosedEvent;
|
||||||
_connection.ConnectionLost -= HandleConnectionLostEvent;
|
_connection.ConnectionLost -= HandleConnectionLostEvent;
|
||||||
_connection.ConnectionRestored -= HandleConnectionRestoredEvent;
|
_connection.ConnectionRestored -= HandleConnectionRestoredEvent;
|
||||||
_connection.ResubscribingFailed -= HandleResubscribeFailedEvent;
|
_connection.ResubscribingFailed -= HandleResubscribeFailedEvent;
|
||||||
_connection.ActivityPaused -= HandlePausedEvent;
|
_connection.ActivityPaused -= HandlePausedEvent;
|
||||||
_connection.ActivityUnpaused -= HandleUnpausedEvent;
|
_connection.ActivityUnpaused -= HandleUnpausedEvent;
|
||||||
|
}
|
||||||
|
|
||||||
_connectionEventsSubscribed = false;
|
_connectionEventsSubscribed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleConnectionClosedEvent()
|
internal void HandleConnectionClosedEvent()
|
||||||
{
|
{
|
||||||
UnsubscribeConnectionEvents();
|
UnsubscribeConnectionEvents();
|
||||||
|
|
||||||
// If we're not the subscription closing this connection don't bother emitting
|
// If we're not the subscription closing this connection don't bother emitting
|
||||||
if (!_subscription.IsClosingConnection)
|
if (_connection != null && !_subscription.IsClosingConnection)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
List<Action> handlers;
|
List<Action> handlers;
|
||||||
@@ -176,7 +193,7 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleConnectionLostEvent()
|
internal void HandleConnectionLostEvent()
|
||||||
{
|
{
|
||||||
if (!_subscription.Active)
|
if (!_subscription.Active)
|
||||||
{
|
{
|
||||||
@@ -192,7 +209,7 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleConnectionRestoredEvent(TimeSpan period)
|
internal void HandleConnectionRestoredEvent(TimeSpan period)
|
||||||
{
|
{
|
||||||
if (!_subscription.Active)
|
if (!_subscription.Active)
|
||||||
{
|
{
|
||||||
@@ -208,7 +225,7 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
callback(period);
|
callback(period);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleResubscribeFailedEvent(Error error)
|
internal void HandleResubscribeFailedEvent(Error error)
|
||||||
{
|
{
|
||||||
if (!_subscription.Active)
|
if (!_subscription.Active)
|
||||||
{
|
{
|
||||||
@@ -224,7 +241,7 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
callback(error);
|
callback(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandlePausedEvent()
|
internal void HandlePausedEvent()
|
||||||
{
|
{
|
||||||
if (!_subscription.Active)
|
if (!_subscription.Active)
|
||||||
{
|
{
|
||||||
@@ -240,7 +257,7 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleUnpausedEvent()
|
internal void HandleUnpausedEvent()
|
||||||
{
|
{
|
||||||
if (!_subscription.Active)
|
if (!_subscription.Active)
|
||||||
{
|
{
|
||||||
@@ -262,7 +279,10 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task CloseAsync()
|
public Task CloseAsync()
|
||||||
{
|
{
|
||||||
|
if (_connection != null)
|
||||||
return _connection.CloseAsync(_subscription);
|
return _connection.CloseAsync(_subscription);
|
||||||
|
|
||||||
|
return _manualSubscription!.CloseAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -271,7 +291,10 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public Task ReconnectAsync()
|
public Task ReconnectAsync()
|
||||||
{
|
{
|
||||||
|
if (_connection != null)
|
||||||
return _connection.TriggerReconnectAsync();
|
return _connection.TriggerReconnectAsync();
|
||||||
|
|
||||||
|
return _manualSubscription!.ReconnectAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -279,8 +302,14 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal async Task UnsubscribeAsync()
|
internal async Task UnsubscribeAsync()
|
||||||
|
{
|
||||||
|
if (_connection != null)
|
||||||
{
|
{
|
||||||
await _connection.UnsubscribeAsync(_subscription).ConfigureAwait(false);
|
await _connection.UnsubscribeAsync(_subscription).ConfigureAwait(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _manualSubscription!.CloseAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -289,7 +318,10 @@ namespace CryptoExchange.Net.Objects.Sockets
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
internal async Task<CallResult> ResubscribeAsync()
|
internal async Task<CallResult> ResubscribeAsync()
|
||||||
{
|
{
|
||||||
|
if (_connection != null)
|
||||||
return await _connection.ResubscribeAsync(_subscription).ConfigureAwait(false);
|
return await _connection.ResubscribeAsync(_subscription).ConfigureAwait(false);
|
||||||
|
|
||||||
|
return await _manualSubscription!.ResubscribeAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
PlaceSpotOrderOptions PlaceSpotOrderOptions { get; }
|
PlaceSpotOrderOptions PlaceSpotOrderOptions { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Place a new spot order, see <see cref="PlaceSpotOrderOptions"/> for request options and exchange specific required/optional parameters. <br />
|
/// Place a new spot order, see <see cref="PlaceSpotOrderOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||||
/// The result is paginated, if there are more results to be retrieved, the `NextPageRequest` property of the result will contain the pagination request to be used for the next request to continue pagination.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="request">Request info</param>
|
/// <param name="request">Request info</param>
|
||||||
/// <param name="ct">Cancellation token</param>
|
/// <param name="ct">Cancellation token</param>
|
||||||
|
|||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Client for placing and managing futures orders
|
||||||
|
/// </summary>
|
||||||
|
public interface IFuturesOrderManagementSocketClient : ISharedClient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// How the trading fee is deducted
|
||||||
|
/// </summary>
|
||||||
|
SharedFeeDeductionType FuturesFeeDeductionType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// How the asset is determined in which the trading fee is paid
|
||||||
|
/// </summary>
|
||||||
|
SharedFeeAssetType FuturesFeeAssetType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Supported order types for futures orders
|
||||||
|
/// </summary>
|
||||||
|
SharedOrderType[] FuturesSupportedOrderTypes { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Supported time in force types for futures orders
|
||||||
|
/// </summary>
|
||||||
|
SharedTimeInForce[] FuturesSupportedTimeInForce { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Supported quantity types for futures orders
|
||||||
|
/// </summary>
|
||||||
|
SharedQuantitySupport FuturesSupportedOrderQuantity { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate a new random client order id
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
string GenerateClientOrderId();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Futures place order request options.<br />
|
||||||
|
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||||
|
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||||
|
/// </summary>
|
||||||
|
PlaceFuturesOrderSocketOptions PlaceFuturesOrderOptions { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Place a new futures order, see <see cref="PlaceFuturesOrderOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Request info</param>
|
||||||
|
/// <param name="ct">Cancellation token</param>
|
||||||
|
Task<QueryResult<SharedId>> PlaceFuturesOrderAsync(PlaceFuturesOrderRequest request, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Futures cancel order request options.<br />
|
||||||
|
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||||
|
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||||
|
/// </summary>
|
||||||
|
CancelFuturesOrderSocketOptions CancelFuturesOrderOptions { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Cancel a futures order, see <see cref="CancelFuturesOrderOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Request info</param>
|
||||||
|
/// <param name="ct">Cancellation token</param>
|
||||||
|
Task<QueryResult<SharedId>> CancelFuturesOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
|
||||||
|
}
|
||||||
|
}
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Client for placing and managing spot orders
|
||||||
|
/// </summary>
|
||||||
|
public interface ISpotOrderManagementSocketClient : ISharedClient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// How the trading fee is deducted
|
||||||
|
/// </summary>
|
||||||
|
SharedFeeDeductionType SpotFeeDeductionType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// How the asset is determined in which the trading fee is paid
|
||||||
|
/// </summary>
|
||||||
|
SharedFeeAssetType SpotFeeAssetType { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Supported order types for spot orders
|
||||||
|
/// </summary>
|
||||||
|
SharedOrderType[] SpotSupportedOrderTypes { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Supported time in force types for placing spot orders
|
||||||
|
/// </summary>
|
||||||
|
SharedTimeInForce[] SpotSupportedTimeInForce { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Supported quantity types for placing spot orders
|
||||||
|
/// </summary>
|
||||||
|
SharedQuantitySupport SpotSupportedOrderQuantity { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate a new random client order id
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
string GenerateClientOrderId();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Spot place order request options.<br />
|
||||||
|
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||||
|
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||||
|
/// </summary>
|
||||||
|
PlaceSpotOrderSocketOptions PlaceSpotOrderOptions { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Place a new spot order, see <see cref="PlaceSpotOrderOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Request info</param>
|
||||||
|
/// <param name="ct">Cancellation token</param>
|
||||||
|
Task<QueryResult<SharedId>> PlaceSpotOrderAsync(PlaceSpotOrderRequest request, CancellationToken ct = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Spot cancel order request options.<br />
|
||||||
|
/// Use <see cref="EndpointOptions.RequiredExchangeParameters"/> and <see cref="EndpointOptions.OptionalExchangeParameters"/> to check for required and optional parameters for the request. <br />
|
||||||
|
/// Exchange specific parameters can be added to the request via the `ExchangeParameters` property of the request object.
|
||||||
|
/// </summary>
|
||||||
|
CancelSpotOrderSocketOptions CancelSpotOrderOptions { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Cancel a spot order, see <see cref="CancelSpotOrderOptions"/> for request options and exchange specific required/optional parameters. <br />
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">Request info</param>
|
||||||
|
/// <param name="ct">Cancellation token</param>
|
||||||
|
Task<QueryResult<SharedId>> CancelSpotOrderAsync(CancelOrderRequest request, CancellationToken ct = default);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -5,6 +5,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CancelFuturesOrderByClientOrderIdOptions : EndpointOptions<CancelOrderRequest, IFuturesOrderClientIdRestClient>
|
public class CancelFuturesOrderByClientOrderIdOptions : EndpointOptions<CancelOrderRequest, IFuturesOrderClientIdRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Cancel a futures order by its client order id";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CancelFuturesOrderOptions : EndpointOptions<CancelOrderRequest, IFuturesOrderRestClient>
|
public class CancelFuturesOrderOptions : EndpointOptions<CancelOrderRequest, IFuturesOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Cancel a futures order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Options for canceling a futures order
|
||||||
|
/// </summary>
|
||||||
|
public class CancelFuturesOrderSocketOptions : EndpointOptions<CancelOrderRequest, IFuturesOrderManagementSocketClient>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Cancel a futures order over a socket connection";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
public CancelFuturesOrderSocketOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(IFuturesOrderManagementSocketClient.CancelFuturesOrderAsync))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CancelFuturesTpSlOptions : EndpointOptions<CancelTpSlRequest, IFuturesTpSlRestClient>
|
public class CancelFuturesTpSlOptions : EndpointOptions<CancelTpSlRequest, IFuturesTpSlRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Cancel a take profit or stop loss order for a futures position";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CancelFuturesTriggerOrderOptions : EndpointOptions<CancelOrderRequest, IFuturesTriggerOrderRestClient>
|
public class CancelFuturesTriggerOrderOptions : EndpointOptions<CancelOrderRequest, IFuturesTriggerOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Cancel a futures trigger order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+14
-1
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,11 +10,23 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CancelSpotOrderByClientOrderIdOptions : EndpointOptions<CancelOrderRequest, ISpotOrderClientIdRestClient>
|
public class CancelSpotOrderByClientOrderIdOptions : EndpointOptions<CancelOrderRequest, ISpotOrderClientIdRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Cancel a spot order by its client order id";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CancelSpotOrderByClientOrderIdOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderClientIdRestClient.CancelSpotOrderByClientOrderIdAsync))
|
public CancelSpotOrderByClientOrderIdOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderClientIdRestClient.CancelSpotOrderByClientOrderIdAsync))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(CancelOrderRequest request, ISpotOrderClientIdRestClient client)
|
||||||
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,11 +10,23 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CancelSpotOrderOptions : EndpointOptions<CancelOrderRequest, ISpotOrderRestClient>
|
public class CancelSpotOrderOptions : EndpointOptions<CancelOrderRequest, ISpotOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Cancel a spot order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CancelSpotOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderRestClient.CancelSpotOrderAsync))
|
public CancelSpotOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderRestClient.CancelSpotOrderAsync))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(CancelOrderRequest request, ISpotOrderRestClient client)
|
||||||
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Options for canceling a spot order
|
||||||
|
/// </summary>
|
||||||
|
public class CancelSpotOrderSocketOptions : EndpointOptions<CancelOrderRequest, ISpotOrderManagementSocketClient>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Cancel a spot order over a socket connection";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
public CancelSpotOrderSocketOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderManagementSocketClient.CancelSpotOrderAsync))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(CancelOrderRequest request, ISpotOrderManagementSocketClient client)
|
||||||
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
-1
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,11 +10,23 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class CancelSpotTriggerOrderOptions : EndpointOptions<CancelOrderRequest, ISpotTriggerOrderRestClient>
|
public class CancelSpotTriggerOrderOptions : EndpointOptions<CancelOrderRequest, ISpotTriggerOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Cancel a spot trigger order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CancelSpotTriggerOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotTriggerOrderRestClient.CancelSpotTriggerOrderAsync))
|
public CancelSpotTriggerOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotTriggerOrderRestClient.CancelSpotTriggerOrderAsync))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(CancelOrderRequest request, ISpotTriggerOrderRestClient client)
|
||||||
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ClosePositionOptions : EndpointOptions<ClosePositionRequest, IFuturesOrderRestClient>
|
public class ClosePositionOptions : EndpointOptions<ClosePositionRequest, IFuturesOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Close an open futures position";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// Whether the call is supported. If false the exchange API does not support this operation.
|
/// Whether the call is supported. If false the exchange API does not support this operation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool Supported { get; set; } = true;
|
public bool Supported { get; set; } = true;
|
||||||
|
/// <summary>
|
||||||
|
/// Description of the endpoint
|
||||||
|
/// </summary>
|
||||||
|
public abstract string Description { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
@@ -87,7 +91,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TRequest">Type of data</typeparam>
|
/// <typeparam name="TRequest">Type of data</typeparam>
|
||||||
#if NET5_0_OR_GREATER
|
#if NET5_0_OR_GREATER
|
||||||
public class EndpointOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] TRequest> : EndpointOptions
|
public abstract class EndpointOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] TRequest> : EndpointOptions
|
||||||
where TRequest : SharedRequest
|
where TRequest : SharedRequest
|
||||||
#else
|
#else
|
||||||
public abstract class EndpointOptions<TRequest> : EndpointOptions
|
public abstract class EndpointOptions<TRequest> : EndpointOptions
|
||||||
@@ -181,14 +185,20 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
if (!Supported)
|
|
||||||
return $"{Exchange} {EndpointName} NOT SUPPORTED";
|
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine($"{Exchange} {EndpointName}");
|
sb.AppendLine($"{EndpointName}");
|
||||||
sb.AppendLine($"Needs authentication: {NeedsAuthentication}");
|
if (!Supported)
|
||||||
|
{
|
||||||
|
sb.AppendLine(" NOT SUPPORTED");
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine($"{Description}");
|
||||||
if (!string.IsNullOrEmpty(RequestNotes))
|
if (!string.IsNullOrEmpty(RequestNotes))
|
||||||
|
{
|
||||||
|
sb.Append(" Notes: ");
|
||||||
sb.AppendLine(RequestNotes);
|
sb.AppendLine(RequestNotes);
|
||||||
|
}
|
||||||
if (RequiredOptionalParameters.Any())
|
if (RequiredOptionalParameters.Any())
|
||||||
{
|
{
|
||||||
sb.AppendLine($" Required optional parameters:");
|
sb.AppendLine($" Required optional parameters:");
|
||||||
@@ -207,6 +217,8 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
foreach (var param in OptionalExchangeParameters)
|
foreach (var param in OptionalExchangeParameters)
|
||||||
sb.AppendLine($" {param}");
|
sb.AppendLine($" {param}");
|
||||||
}
|
}
|
||||||
|
sb.Append(" Needs authentication: ");
|
||||||
|
sb.AppendLine($"{NeedsAuthentication}");
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetAssetOptions : EndpointOptions<GetAssetRequest, IAssetsRestClient>
|
public class GetAssetOptions : EndpointOptions<GetAssetRequest, IAssetsRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve basic info for a single asset and networks it supports for withdrawals/deposits";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetAssetsOptions : EndpointOptions<GetAssetsRequest, IAssetsRestClient>
|
public class GetAssetsOptions : EndpointOptions<GetAssetsRequest, IAssetsRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve basic info for all assets and the networks they support for withdrawals/deposits";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
@@ -8,6 +8,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetBalancesOptions : EndpointOptions<GetBalancesRequest, IBalanceRestClient>
|
public class GetBalancesOptions : EndpointOptions<GetBalancesRequest, IBalanceRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve account balances";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supported account types
|
/// Supported account types
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetBookTickerOptions : EndpointOptions<GetBookTickerRequest, IBookTickerRestClient>
|
public class GetBookTickerOptions : EndpointOptions<GetBookTickerRequest, IBookTickerRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve the best bid and ask price for a symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetDepositAddressesOptions : EndpointOptions<GetDepositAddressesRequest, IDepositRestClient>
|
public class GetDepositAddressesOptions : EndpointOptions<GetDepositAddressesRequest, IDepositRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve deposit addresses for an asset";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetDepositsOptions : PaginatedEndpointOptions<GetDepositsRequest, IDepositRestClient>
|
public class GetDepositsOptions : PaginatedEndpointOptions<GetDepositsRequest, IDepositRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve deposit history";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFeeOptions : EndpointOptions<GetFeeRequest, IFeeRestClient>
|
public class GetFeeOptions : EndpointOptions<GetFeeRequest, IFeeRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve trading fee information";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFundingRateHistoryOptions : PaginatedEndpointOptions<GetFundingRateHistoryRequest, IFundingRateRestClient>
|
public class GetFundingRateHistoryOptions : PaginatedEndpointOptions<GetFundingRateHistoryRequest, IFundingRateRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve historical funding rates for a futures symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFuturesClosedOrdersOptions : PaginatedEndpointOptions<GetClosedOrdersRequest, IFuturesOrderRestClient>
|
public class GetFuturesClosedOrdersOptions : PaginatedEndpointOptions<GetClosedOrdersRequest, IFuturesOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve closed futures orders";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFuturesOrderByClientOrderIdOptions : EndpointOptions<GetOrderRequest, IFuturesOrderClientIdRestClient>
|
public class GetFuturesOrderByClientOrderIdOptions : EndpointOptions<GetOrderRequest, IFuturesOrderClientIdRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve a futures order by its client order id";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFuturesOrderOptions : EndpointOptions<GetOrderRequest, IFuturesOrderRestClient>
|
public class GetFuturesOrderOptions : EndpointOptions<GetOrderRequest, IFuturesOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve a futures order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFuturesOrderTradesOptions : EndpointOptions<GetOrderTradesRequest, IFuturesOrderRestClient>
|
public class GetFuturesOrderTradesOptions : EndpointOptions<GetOrderTradesRequest, IFuturesOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve trades for a futures order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -10,6 +10,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFuturesSymbolsOptions : EndpointOptions<GetSymbolsRequest, IFuturesSymbolRestClient>
|
public class GetFuturesSymbolsOptions : EndpointOptions<GetSymbolsRequest, IFuturesSymbolRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve supported futures symbols and their trading rules";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -7,6 +7,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFuturesTickerOptions : EndpointOptions<GetTickerRequest, IFuturesTickerRestClient>
|
public class GetFuturesTickerOptions : EndpointOptions<GetTickerRequest, IFuturesTickerRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve price ticker information for a futures symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of ticker calculation
|
/// Type of ticker calculation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -7,6 +7,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFuturesTickersOptions : EndpointOptions<GetTickersRequest, IFuturesTickerRestClient>
|
public class GetFuturesTickersOptions : EndpointOptions<GetTickersRequest, IFuturesTickerRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve price ticker information for all futures symbols";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of ticker calculation
|
/// Type of ticker calculation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFuturesTriggerOrderOptions : EndpointOptions<GetOrderRequest, IFuturesTriggerOrderRestClient>
|
public class GetFuturesTriggerOrderOptions : EndpointOptions<GetOrderRequest, IFuturesTriggerOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve a futures trigger order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetFuturesUserTradesOptions : PaginatedEndpointOptions<GetUserTradesRequest, IFuturesOrderRestClient>
|
public class GetFuturesUserTradesOptions : PaginatedEndpointOptions<GetUserTradesRequest, IFuturesOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve futures user trade history";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+5
-2
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -10,6 +10,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetIndexPriceKlinesOptions : PaginatedEndpointOptions<GetKlinesRequest, IIndexPriceKlineRestClient>
|
public class GetIndexPriceKlinesOptions : PaginatedEndpointOptions<GetKlinesRequest, IIndexPriceKlineRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve index price candlestick data";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The supported kline intervals
|
/// The supported kline intervals
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -108,7 +111,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder(base.ToString());
|
var sb = new StringBuilder(base.ToString());
|
||||||
sb.AppendLine($"Supported SharedKlineInterval values: {string.Join(", ", SupportIntervals)}");
|
sb.AppendLine($" Supported intervals: {string.Join(", ", SupportIntervals)}");
|
||||||
if (MaxTotalDataPoints != null)
|
if (MaxTotalDataPoints != null)
|
||||||
sb.AppendLine($" Max total data points available: {MaxTotalDataPoints}");
|
sb.AppendLine($" Max total data points available: {MaxTotalDataPoints}");
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -10,6 +10,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetKlinesOptions : PaginatedEndpointOptions<GetKlinesRequest, IKlineRestClient>
|
public class GetKlinesOptions : PaginatedEndpointOptions<GetKlinesRequest, IKlineRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve candlestick data for a symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The supported kline intervals
|
/// The supported kline intervals
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -108,7 +111,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder(base.ToString());
|
var sb = new StringBuilder(base.ToString());
|
||||||
sb.AppendLine($"Supported SharedKlineInterval values: {string.Join(", ", SupportIntervals)}");
|
sb.AppendLine($" Supported intervals: {string.Join(", ", SupportIntervals)}");
|
||||||
if (MaxTotalDataPoints != null)
|
if (MaxTotalDataPoints != null)
|
||||||
sb.AppendLine($" Max total data points available: {MaxTotalDataPoints}");
|
sb.AppendLine($" Max total data points available: {MaxTotalDataPoints}");
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetLeverageOptions : EndpointOptions<GetLeverageRequest, ILeverageRestClient>
|
public class GetLeverageOptions : EndpointOptions<GetLeverageRequest, ILeverageRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve the current leverage for a futures symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -10,6 +10,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetMarkPriceKlinesOptions : PaginatedEndpointOptions<GetKlinesRequest, IMarkPriceKlineRestClient>
|
public class GetMarkPriceKlinesOptions : PaginatedEndpointOptions<GetKlinesRequest, IMarkPriceKlineRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve mark price candlestick data";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The supported kline intervals
|
/// The supported kline intervals
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -108,7 +111,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder(base.ToString());
|
var sb = new StringBuilder(base.ToString());
|
||||||
sb.AppendLine($"Supported SharedKlineInterval values: {string.Join(", ", SupportIntervals)}");
|
sb.AppendLine($" Supported intervals: {string.Join(", ", SupportIntervals)}");
|
||||||
if (MaxTotalDataPoints != null)
|
if (MaxTotalDataPoints != null)
|
||||||
sb.AppendLine($" Max total data points available: {MaxTotalDataPoints}");
|
sb.AppendLine($" Max total data points available: {MaxTotalDataPoints}");
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetOpenFuturesOrdersOptions : EndpointOptions<GetOpenOrdersRequest, IFuturesOrderRestClient>
|
public class GetOpenFuturesOrdersOptions : EndpointOptions<GetOpenOrdersRequest, IFuturesOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve open futures orders";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetOpenInterestOptions : EndpointOptions<GetOpenInterestRequest, IOpenInterestRestClient>
|
public class GetOpenInterestOptions : EndpointOptions<GetOpenInterestRequest, IOpenInterestRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve open interest for a futures symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetOpenSpotOrdersOptions : EndpointOptions<GetOpenOrdersRequest, ISpotOrderRestClient>
|
public class GetOpenSpotOrdersOptions : EndpointOptions<GetOpenOrdersRequest, ISpotOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve open spot orders";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -10,6 +10,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetOrderBookOptions : EndpointOptions<GetOrderBookRequest, IOrderBookRestClient>
|
public class GetOrderBookOptions : EndpointOptions<GetOrderBookRequest, IOrderBookRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve the current order book for a symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supported order book depths
|
/// Supported order book depths
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetPositionHistoryOptions : PaginatedEndpointOptions<GetPositionHistoryRequest, IPositionHistoryRestClient>
|
public class GetPositionHistoryOptions : PaginatedEndpointOptions<GetPositionHistoryRequest, IPositionHistoryRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve historical futures positions";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options for requesting current position mode
|
/// Options for requesting current position mode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetPositionModeOptions : EndpointOptions<GetPositionModeRequest, IPositionModeRestClient>
|
public class GetPositionModeOptions : EndpointOptions<GetPositionModeRequest, IPositionModeRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve the current futures position mode";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetPositionsOptions : EndpointOptions<GetPositionsRequest, IFuturesOrderRestClient>
|
public class GetPositionsOptions : EndpointOptions<GetPositionsRequest, IFuturesOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve open futures positions";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
@@ -8,6 +8,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetRecentTradesOptions : EndpointOptions<GetRecentTradesRequest, IRecentTradeRestClient>
|
public class GetRecentTradesOptions : EndpointOptions<GetRecentTradesRequest, IRecentTradeRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve recent public trades for a symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The max number of trades that can be requested
|
/// The max number of trades that can be requested
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+7
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetSpotClosedOrdersOptions : PaginatedEndpointOptions<GetClosedOrdersRequest, ISpotOrderRestClient>
|
public class GetSpotClosedOrdersOptions : PaginatedEndpointOptions<GetClosedOrdersRequest, ISpotOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve closed spot orders";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -20,6 +23,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetClosedOrdersRequest request, ISpotOrderRestClient client)
|
public override Error? ValidateRequest(GetClosedOrdersRequest request, ISpotOrderRestClient client)
|
||||||
{
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetClosedOrdersRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetClosedOrdersRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
|
|||||||
+14
-1
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,11 +10,23 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetSpotOrderByClientOrderIdOptions : EndpointOptions<GetOrderRequest, ISpotOrderClientIdRestClient>
|
public class GetSpotOrderByClientOrderIdOptions : EndpointOptions<GetOrderRequest, ISpotOrderClientIdRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve a spot order by its client order id";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GetSpotOrderByClientOrderIdOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderClientIdRestClient.GetSpotOrderByClientOrderIdAsync))
|
public GetSpotOrderByClientOrderIdOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderClientIdRestClient.GetSpotOrderByClientOrderIdAsync))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(GetOrderRequest request, ISpotOrderClientIdRestClient client)
|
||||||
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,11 +10,23 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetSpotOrderOptions : EndpointOptions<GetOrderRequest, ISpotOrderRestClient>
|
public class GetSpotOrderOptions : EndpointOptions<GetOrderRequest, ISpotOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve a spot order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GetSpotOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderRestClient.GetSpotOrderAsync))
|
public GetSpotOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderRestClient.GetSpotOrderAsync))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(GetOrderRequest request, ISpotOrderRestClient client)
|
||||||
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-1
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,11 +10,23 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetSpotOrderTradesOptions : EndpointOptions<GetOrderTradesRequest, ISpotOrderRestClient>
|
public class GetSpotOrderTradesOptions : EndpointOptions<GetOrderTradesRequest, ISpotOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve trades for a spot order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GetSpotOrderTradesOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderRestClient.GetSpotOrderTradesAsync))
|
public GetSpotOrderTradesOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotOrderRestClient.GetSpotOrderTradesAsync))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(GetOrderTradesRequest request, ISpotOrderRestClient client)
|
||||||
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -10,6 +10,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetSpotSymbolsOptions : EndpointOptions<GetSymbolsRequest, ISpotSymbolRestClient>
|
public class GetSpotSymbolsOptions : EndpointOptions<GetSymbolsRequest, ISpotSymbolRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve supported spot symbols and their trading rules";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -7,6 +7,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetSpotTickerOptions : EndpointOptions<GetTickerRequest, ISpotTickerRestClient>
|
public class GetSpotTickerOptions : EndpointOptions<GetTickerRequest, ISpotTickerRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve price ticker information for a spot symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of ticker calculation
|
/// Type of ticker calculation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -7,6 +7,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetSpotTickersOptions : EndpointOptions<GetTickersRequest, ISpotTickerRestClient>
|
public class GetSpotTickersOptions : EndpointOptions<GetTickersRequest, ISpotTickerRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve price ticker information for all spot symbols";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of ticker calculation
|
/// Type of ticker calculation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+14
-1
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,11 +10,23 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetSpotTriggerOrderOptions : EndpointOptions<GetOrderRequest, ISpotTriggerOrderRestClient>
|
public class GetSpotTriggerOrderOptions : EndpointOptions<GetOrderRequest, ISpotTriggerOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve a spot trigger order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public GetSpotTriggerOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotTriggerOrderRestClient.GetSpotTriggerOrderAsync))
|
public GetSpotTriggerOrderOptions(string exchange, bool authenticated) : base(exchange, authenticated, nameof(ISpotTriggerOrderRestClient.GetSpotTriggerOrderAsync))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Error? ValidateRequest(GetOrderRequest request, ISpotTriggerOrderRestClient client)
|
||||||
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetSpotUserTradesOptions : PaginatedEndpointOptions<GetUserTradesRequest, ISpotOrderRestClient>
|
public class GetSpotUserTradesOptions : PaginatedEndpointOptions<GetUserTradesRequest, ISpotOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve spot user trade history";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -20,6 +23,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Error? ValidateRequest(GetUserTradesRequest request, ISpotOrderRestClient client)
|
public override Error? ValidateRequest(GetUserTradesRequest request, ISpotOrderRestClient client)
|
||||||
{
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
if (!SupportsAscending && request.Direction == DataDirection.Ascending)
|
||||||
return ArgumentError.Invalid(nameof(GetUserTradesRequest.Direction), $"Ascending direction is not supported");
|
return ArgumentError.Invalid(nameof(GetUserTradesRequest.Direction), $"Ascending direction is not supported");
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetTradeHistoryOptions : PaginatedEndpointOptions<GetTradeHistoryRequest, ITradeHistoryRestClient>
|
public class GetTradeHistoryOptions : PaginatedEndpointOptions<GetTradeHistoryRequest, ITradeHistoryRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve public trade history for a symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetWithdrawalsOptions : PaginatedEndpointOptions<GetWithdrawalsRequest, IWithdrawalRestClient>
|
public class GetWithdrawalsOptions : PaginatedEndpointOptions<GetWithdrawalsRequest, IWithdrawalRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Retrieve withdrawal history";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -8,7 +8,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// Options for paginated endpoints
|
/// Options for paginated endpoints
|
||||||
/// </summary>
|
/// </summary>
|
||||||
#if NET5_0_OR_GREATER
|
#if NET5_0_OR_GREATER
|
||||||
public class PaginatedEndpointOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] TRequest, TClient> : EndpointOptions<TRequest, TClient>
|
public abstract class PaginatedEndpointOptions<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] TRequest, TClient> : EndpointOptions<TRequest, TClient>
|
||||||
where TRequest : SharedRequest
|
where TRequest : SharedRequest
|
||||||
where TClient : ISharedClient
|
where TClient : ISharedClient
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PlaceFuturesOrderOptions : EndpointOptions<PlaceFuturesOrderRequest, IFuturesOrderRestClient>
|
public class PlaceFuturesOrderOptions : EndpointOptions<PlaceFuturesOrderRequest, IFuturesOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Place a new futures order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether or not the API supports setting take profit / stop loss with the order
|
/// Whether or not the API supports setting take profit / stop loss with the order
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Options for placing a new futures order
|
||||||
|
/// </summary>
|
||||||
|
public class PlaceFuturesOrderSocketOptions : EndpointOptions<PlaceFuturesOrderRequest, IFuturesOrderManagementSocketClient>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Place a new futures order over a socket connection";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not the API supports setting take profit / stop loss with the order
|
||||||
|
/// </summary>
|
||||||
|
public bool SupportsTpSl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
public PlaceFuturesOrderSocketOptions(string exchange, bool supportsTpSl) : base(exchange, true, nameof(IFuturesOrderManagementSocketClient.PlaceFuturesOrderAsync))
|
||||||
|
{
|
||||||
|
SupportsTpSl = supportsTpSl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validate a request
|
||||||
|
/// </summary>
|
||||||
|
public override Error? ValidateRequest(
|
||||||
|
PlaceFuturesOrderRequest request,
|
||||||
|
IFuturesOrderManagementSocketClient client
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!SupportsTpSl && (request.StopLossPrice != null || request.TakeProfitPrice != null))
|
||||||
|
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.StopLossPrice) + " / " + nameof(PlaceFuturesOrderRequest.TakeProfitPrice), "Tp/Sl parameters not supported");
|
||||||
|
|
||||||
|
if (request.OrderType == SharedOrderType.Other)
|
||||||
|
throw new ArgumentException("OrderType can't be `Other`", nameof(request.OrderType));
|
||||||
|
|
||||||
|
if (!client.FuturesSupportedOrderTypes.Contains(request.OrderType))
|
||||||
|
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.OrderType), "Order type not supported");
|
||||||
|
|
||||||
|
if (request.TimeInForce != null && !client.FuturesSupportedTimeInForce.Contains(request.TimeInForce.Value))
|
||||||
|
return ArgumentError.Invalid(nameof(PlaceFuturesOrderRequest.TimeInForce), "Order time in force not supported");
|
||||||
|
|
||||||
|
var quantityError = client.FuturesSupportedOrderQuantity.Validate(request.Side, request.OrderType, request.Quantity);
|
||||||
|
if (quantityError != null)
|
||||||
|
return quantityError;
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-15
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -7,6 +7,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PlaceFuturesTriggerOrderOptions : EndpointOptions<PlaceFuturesTriggerOrderRequest, IFuturesTriggerOrderRestClient>
|
public class PlaceFuturesTriggerOrderOptions : EndpointOptions<PlaceFuturesTriggerOrderRequest, IFuturesTriggerOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Place a new futures trigger order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When true the API holds the funds until the order is triggered or canceled. When false the funds will only be required when the order is triggered and will fail if the funds are not available at that time.
|
/// When true the API holds the funds until the order is triggered or canceled. When false the funds will only be required when the order is triggered and will fail if the funds are not available at that time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -19,19 +22,5 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
{
|
{
|
||||||
HoldsFunds = holdsFunds;
|
HoldsFunds = holdsFunds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Validate a request
|
|
||||||
/// </summary>
|
|
||||||
public override Error? ValidateRequest(
|
|
||||||
PlaceFuturesTriggerOrderRequest request,
|
|
||||||
IFuturesTriggerOrderRestClient client)
|
|
||||||
{
|
|
||||||
//var quantityError = client.FuturesSupportedOrderQuantity.Validate(request.OrderDirection, request.OrderPrice == null ? SharedOrderType.Market : SharedOrderType.Limit, request.Quantity);
|
|
||||||
//if (quantityError != null)
|
|
||||||
// return quantityError;
|
|
||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PlaceSpotOrderOptions : EndpointOptions<PlaceSpotOrderRequest, ISpotOrderRestClient>
|
public class PlaceSpotOrderOptions : EndpointOptions<PlaceSpotOrderRequest, ISpotOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Place a new spot order";
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
@@ -24,6 +27,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
PlaceSpotOrderRequest request,
|
PlaceSpotOrderRequest request,
|
||||||
ISpotOrderRestClient client)
|
ISpotOrderRestClient client)
|
||||||
{
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
if (request.OrderType == SharedOrderType.Other)
|
if (request.OrderType == SharedOrderType.Other)
|
||||||
throw new ArgumentException("OrderType can't be `Other`", nameof(request.OrderType));
|
throw new ArgumentException("OrderType can't be `Other`", nameof(request.OrderType));
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using CryptoExchange.Net.Objects;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Options for placing a new spot order
|
||||||
|
/// </summary>
|
||||||
|
public class PlaceSpotOrderSocketOptions : EndpointOptions<PlaceSpotOrderRequest, ISpotOrderManagementSocketClient>
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Place a new spot order over a socket connection";
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ctor
|
||||||
|
/// </summary>
|
||||||
|
public PlaceSpotOrderSocketOptions(string exchange) : base(exchange, true, nameof(ISpotOrderManagementSocketClient.PlaceSpotOrderAsync))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validate a request
|
||||||
|
/// </summary>
|
||||||
|
public override Error? ValidateRequest(
|
||||||
|
PlaceSpotOrderRequest request,
|
||||||
|
ISpotOrderManagementSocketClient client)
|
||||||
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
|
if (request.OrderType == SharedOrderType.Other)
|
||||||
|
throw new ArgumentException("OrderType can't be `Other`", nameof(request.OrderType));
|
||||||
|
|
||||||
|
if (!client.SpotSupportedOrderTypes.Contains(request.OrderType))
|
||||||
|
return ArgumentError.Invalid(nameof(PlaceSpotOrderRequest.OrderType), "Order type not supported");
|
||||||
|
|
||||||
|
if (request.TimeInForce != null && !client.SpotSupportedTimeInForce.Contains(request.TimeInForce.Value))
|
||||||
|
return ArgumentError.Invalid(nameof(PlaceSpotOrderRequest.TimeInForce), "Order time in force not supported");
|
||||||
|
|
||||||
|
var quantityError = client.SpotSupportedOrderQuantity.Validate(request.Side, request.OrderType, request.Quantity);
|
||||||
|
if (quantityError != null)
|
||||||
|
return quantityError;
|
||||||
|
|
||||||
|
return base.ValidateRequest(request, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -7,6 +7,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PlaceSpotTriggerOrderOptions : EndpointOptions<PlaceSpotTriggerOrderRequest, ISpotOrderRestClient>
|
public class PlaceSpotTriggerOrderOptions : EndpointOptions<PlaceSpotTriggerOrderRequest, ISpotOrderRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Place a new spot trigger order";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// When true the API holds the funds until the order is triggered or canceled. When false the funds will only be required when the order is triggered and will fail if the funds are not available at that time.
|
/// When true the API holds the funds until the order is triggered or canceled. When false the funds will only be required when the order is triggered and will fail if the funds are not available at that time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -27,6 +30,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
PlaceSpotTriggerOrderRequest request,
|
PlaceSpotTriggerOrderRequest request,
|
||||||
ISpotOrderRestClient client)
|
ISpotOrderRestClient client)
|
||||||
{
|
{
|
||||||
|
if (request.Symbol!.TradingMode != TradingMode.Spot)
|
||||||
|
return ArgumentError.Invalid("TradingMode", $"TradingMode.{request.Symbol!.TradingMode} is not supported, should be Spot");
|
||||||
|
|
||||||
var quantityError = client.SpotSupportedOrderQuantity.Validate(request.OrderSide, request.OrderPrice == null ? SharedOrderType.Market : SharedOrderType.Limit, request.Quantity);
|
var quantityError = client.SpotSupportedOrderQuantity.Validate(request.OrderSide, request.OrderPrice == null ? SharedOrderType.Market : SharedOrderType.Limit, request.Quantity);
|
||||||
if (quantityError != null)
|
if (quantityError != null)
|
||||||
return quantityError;
|
return quantityError;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SetFuturesTpSlOptions : EndpointOptions<SetTpSlRequest, IFuturesTpSlRestClient>
|
public class SetFuturesTpSlOptions : EndpointOptions<SetTpSlRequest, IFuturesTpSlRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Set take profit or stop loss values for a futures position";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options for setting leverage
|
/// Options for setting leverage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SetLeverageOptions : EndpointOptions<SetLeverageRequest, ILeverageRestClient>
|
public class SetLeverageOptions : EndpointOptions<SetLeverageRequest, ILeverageRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Set the leverage for a futures symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options for setting position mode
|
/// Options for setting position mode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SetPositionModeOptions : EndpointOptions<SetPositionModeRequest, IPositionModeRestClient>
|
public class SetPositionModeOptions : EndpointOptions<SetPositionModeRequest, IPositionModeRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Set the futures position mode";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -8,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class TransferOptions : EndpointOptions<TransferRequest, ITransferRestClient>
|
public class TransferOptions : EndpointOptions<TransferRequest, ITransferRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Transfer funds between account types";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Supported account types
|
/// Supported account types
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -36,5 +40,13 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
|
|
||||||
return base.ValidateRequest(request, client);
|
return base.ValidateRequest(request, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder(base.ToString());
|
||||||
|
sb.AppendLine($" Supported accounts: {string.Join(", ", SupportedAccountTypes)}");
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options for requesting a withdrawal
|
/// Options for requesting a withdrawal
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class WithdrawOptions : EndpointOptions<WithdrawRequest, IWithdrawRestClient>
|
public class WithdrawOptions : EndpointOptions<WithdrawRequest, IWithdrawRestClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Withdraw an asset";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribeBalanceOptions : EndpointOptions<SubscribeBalancesRequest, IBalanceSocketClient>
|
public class SubscribeBalanceOptions : EndpointOptions<SubscribeBalancesRequest, IBalanceSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to balance updates";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribeBookTickerOptions : EndpointOptions<SubscribeBookTickerRequest, IBookTickerSocketClient>
|
public class SubscribeBookTickerOptions : EndpointOptions<SubscribeBookTickerRequest, IBookTickerSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to best bid and ask price updates";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribeFuturesOrderOptions : EndpointOptions<SubscribeFuturesOrderRequest, IFuturesOrderSocketClient>
|
public class SubscribeFuturesOrderOptions : EndpointOptions<SubscribeFuturesOrderRequest, IFuturesOrderSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to futures order updates";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribeKlineOptions : EndpointOptions<SubscribeKlineRequest, IKlineSocketClient>
|
public class SubscribeKlineOptions : EndpointOptions<SubscribeKlineRequest, IKlineSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to candlestick updates for a symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Kline intervals supported for updates
|
/// Kline intervals supported for updates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribeOrderBookOptions : EndpointOptions<SubscribeOrderBookRequest, IOrderBookSocketClient>
|
public class SubscribeOrderBookOptions : EndpointOptions<SubscribeOrderBookRequest, IOrderBookSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to order book updates for a symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Order book depths supported for updates
|
/// Order book depths supported for updates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribePositionOptions : EndpointOptions<SubscribePositionRequest, IPositionSocketClient>
|
public class SubscribePositionOptions : EndpointOptions<SubscribePositionRequest, IPositionSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to futures position updates";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribeSpotOrderOptions : EndpointOptions<SubscribeSpotOrderRequest, ISpotOrderSocketClient>
|
public class SubscribeSpotOrderOptions : EndpointOptions<SubscribeSpotOrderRequest, ISpotOrderSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to spot order updates";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,10 +1,13 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options for subscribing to ticker updates
|
/// Options for subscribing to ticker updates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribeTickerOptions : EndpointOptions<SubscribeTickerRequest, ITickerSocketClient>
|
public class SubscribeTickerOptions : EndpointOptions<SubscribeTickerRequest, ITickerSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to price ticker updates for a symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of ticker calculation
|
/// Type of ticker calculation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,10 +1,13 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Options for subscribing to ticker updates
|
/// Options for subscribing to ticker updates
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribeTickersOptions : EndpointOptions<SubscribeAllTickersRequest, ITickersSocketClient>
|
public class SubscribeTickersOptions : EndpointOptions<SubscribeAllTickersRequest, ITickersSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to price ticker updates for all symbols";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Type of ticker calculation
|
/// Type of ticker calculation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribeTradeOptions : EndpointOptions<SubscribeTradeRequest, ITradeSocketClient>
|
public class SubscribeTradeOptions : EndpointOptions<SubscribeTradeRequest, ITradeSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to public trade updates for a symbol";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
+4
-1
@@ -1,4 +1,4 @@
|
|||||||
using CryptoExchange.Net.Objects;
|
using CryptoExchange.Net.Objects;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class SubscribeUserTradeOptions : EndpointOptions<SubscribeUserTradeRequest, IUserTradeSocketClient>
|
public class SubscribeUserTradeOptions : EndpointOptions<SubscribeUserTradeRequest, IUserTradeSocketClient>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override string Description => "Subscribe to user trade updates";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.SharedApis
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
@@ -15,26 +16,44 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Quantity of the best ask
|
/// Quantity of the best ask
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal BestAskQuantity { get; set; }
|
[Obsolete("Use `BestAskQuantities` instead")]
|
||||||
|
public decimal BestAskQuantity => BestAskQuantities.QuantityInBaseAsset ?? BestAskQuantities.QuantityInContracts ?? 0;
|
||||||
|
/// <summary>
|
||||||
|
/// Quantities of the best ask
|
||||||
|
/// </summary>
|
||||||
|
public SharedOrderQuantity BestAskQuantities { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Price of the best bid
|
/// Price of the best bid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal BestBidPrice { get; set; }
|
public decimal BestBidPrice { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Quantity of the best bid
|
/// Quantity of the best bid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal BestBidQuantity { get; set; }
|
[Obsolete("Use `BestBidQuantities` instead")]
|
||||||
|
public decimal BestBidQuantity => BestBidQuantities.QuantityInBaseAsset ?? BestBidQuantities.QuantityInContracts ?? 0;
|
||||||
|
/// <summary>
|
||||||
|
/// Quantities of the best bid
|
||||||
|
/// </summary>
|
||||||
|
public SharedOrderQuantity BestBidQuantities { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SharedBookTicker(SharedSymbol? sharedSymbol, string symbol, decimal bestAskPrice, decimal bestAskQuantity, decimal bestBidPrice, decimal bestBidQuantity)
|
public SharedBookTicker(
|
||||||
|
SharedSymbol? sharedSymbol,
|
||||||
|
string symbol,
|
||||||
|
decimal bestAskPrice,
|
||||||
|
SharedOrderQuantity bestAskQuantity,
|
||||||
|
decimal bestBidPrice,
|
||||||
|
SharedOrderQuantity bestBidQuantity)
|
||||||
: base(sharedSymbol, symbol)
|
: base(sharedSymbol, symbol)
|
||||||
{
|
{
|
||||||
BestAskPrice = bestAskPrice;
|
BestAskPrice = bestAskPrice;
|
||||||
BestAskQuantity = bestAskQuantity;
|
BestAskQuantities = bestAskQuantity.WithCalculatedQuantities(bestAskPrice, null);
|
||||||
BestBidPrice = bestBidPrice;
|
BestBidPrice = bestBidPrice;
|
||||||
BestBidQuantity = bestBidQuantity;
|
BestBidQuantities = bestBidQuantity.WithCalculatedQuantities(bestBidPrice, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// Max long leverage setting
|
/// Max long leverage setting
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal? MaxLongLeverage { get; set; }
|
public decimal? MaxLongLeverage { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Upper funding rate cap
|
||||||
|
/// </summary>
|
||||||
|
public decimal? UpperFundingCap { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Lower funding rate cap, negative value
|
||||||
|
/// </summary>
|
||||||
|
public decimal? LowerFundingCap { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
|
|||||||
@@ -24,7 +24,24 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The volume in the last 24h
|
/// The volume in the last 24h
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal Volume { get; set; }
|
public SharedOrderQuantity Volumes { get; set; }
|
||||||
|
|
||||||
|
private decimal? _volume;
|
||||||
|
/// <summary>
|
||||||
|
/// The volume in the last 24h
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("Use `Volumes` instead")]
|
||||||
|
public decimal Volume
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_volume.HasValue)
|
||||||
|
return _volume.Value;
|
||||||
|
|
||||||
|
return Volumes.QuantityInBaseAsset ?? Volumes.QuantityInContracts ?? 0;
|
||||||
|
}
|
||||||
|
set => _volume = value;
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Change percentage in the last 24h
|
/// Change percentage in the last 24h
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -49,13 +66,20 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SharedFuturesTicker(SharedSymbol? sharedSymbol, string symbol, decimal? lastPrice, decimal? highPrice, decimal? lowPrice, decimal volume, decimal? changePercentage)
|
public SharedFuturesTicker(
|
||||||
|
SharedSymbol? sharedSymbol,
|
||||||
|
string symbol,
|
||||||
|
decimal? lastPrice,
|
||||||
|
decimal? highPrice,
|
||||||
|
decimal? lowPrice,
|
||||||
|
SharedOrderQuantity volumes,
|
||||||
|
decimal? changePercentage)
|
||||||
:base(sharedSymbol, symbol)
|
:base(sharedSymbol, symbol)
|
||||||
{
|
{
|
||||||
LastPrice = lastPrice;
|
LastPrice = lastPrice;
|
||||||
HighPrice = highPrice;
|
HighPrice = highPrice;
|
||||||
LowPrice = lowPrice;
|
LowPrice = lowPrice;
|
||||||
Volume = volume;
|
Volumes = volumes;
|
||||||
ChangePercentage = changePercentage;
|
ChangePercentage = changePercentage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,14 @@
|
|||||||
public record SharedId
|
public record SharedId
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The id
|
/// The id, note that this can be null or empty if the API doesn't return an ID.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Id { get; set; }
|
public string? Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Id
|
/// Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SharedId(string id)
|
public SharedId(string? id)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Kline info
|
/// Kline info
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DebuggerDisplay("[{OpenTime}] O: {OpenPrice} H: {HighPrice} L: {LowPrice} C: {ClosePrice} V: {Volume}")]
|
[DebuggerDisplay("[{OpenTime}] O: {OpenPrice} H: {HighPrice} L: {LowPrice} C: {ClosePrice} V: {Volumes}")]
|
||||||
public record SharedKline : SharedSymbolModel
|
public record SharedKline : SharedSymbolModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -29,15 +29,40 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// Open price
|
/// Open price
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal OpenPrice { get; set; }
|
public decimal OpenPrice { get; set; }
|
||||||
|
|
||||||
|
private decimal? _volume;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Volume in the base asset
|
/// Volume in the base asset
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal Volume { get; set; }
|
[Obsolete("Use `Volumes` instead")]
|
||||||
|
public decimal Volume
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_volume.HasValue)
|
||||||
|
return _volume.Value;
|
||||||
|
|
||||||
|
return Volumes.QuantityInBaseAsset ?? Volumes.QuantityInContracts ?? 0;
|
||||||
|
}
|
||||||
|
set => _volume = value;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// The volume in the last 24h
|
||||||
|
/// </summary>
|
||||||
|
public SharedOrderQuantity Volumes { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SharedKline(SharedSymbol? sharedSymbol, string symbol, DateTime openTime, decimal closePrice, decimal highPrice, decimal lowPrice, decimal openPrice, decimal volume)
|
public SharedKline(
|
||||||
|
SharedSymbol? sharedSymbol,
|
||||||
|
string symbol,
|
||||||
|
DateTime openTime,
|
||||||
|
decimal closePrice,
|
||||||
|
decimal highPrice,
|
||||||
|
decimal lowPrice,
|
||||||
|
decimal openPrice,
|
||||||
|
SharedOrderQuantity volumes)
|
||||||
: base(sharedSymbol, symbol)
|
: base(sharedSymbol, symbol)
|
||||||
{
|
{
|
||||||
OpenTime = openTime;
|
OpenTime = openTime;
|
||||||
@@ -45,7 +70,7 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
HighPrice = highPrice;
|
HighPrice = highPrice;
|
||||||
LowPrice = lowPrice;
|
LowPrice = lowPrice;
|
||||||
OpenPrice = openPrice;
|
OpenPrice = openPrice;
|
||||||
Volume = volume;
|
Volumes = volumes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace CryptoExchange.Net.SharedApis
|
using System;
|
||||||
|
|
||||||
|
namespace CryptoExchange.Net.SharedApis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Open interest
|
/// Open interest
|
||||||
@@ -8,14 +10,19 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Current open interest
|
/// Current open interest
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public decimal OpenInterest { get; set; }
|
[Obsolete("Use `OpenInterests` instead")]
|
||||||
|
public decimal OpenInterest => OpenInterests.QuantityInBaseAsset ?? OpenInterests.QuantityInContracts ?? 0;
|
||||||
|
/// <summary>
|
||||||
|
/// Current open interest
|
||||||
|
/// </summary>
|
||||||
|
public SharedOrderQuantity OpenInterests { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SharedOpenInterest(decimal openInterest)
|
public SharedOpenInterest(SharedOrderQuantity openInterest)
|
||||||
{
|
{
|
||||||
OpenInterest = openInterest;
|
OpenInterests = openInterest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public record SharedOrderBook
|
public record SharedOrderBook
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The quantity notation the order book is in, either BaseAsset or Contract
|
||||||
|
/// </summary>
|
||||||
|
public SharedQuantityType QuantityType { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Asks list
|
/// Asks list
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -19,8 +23,9 @@ namespace CryptoExchange.Net.SharedApis
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ctor
|
/// ctor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public SharedOrderBook(ISymbolOrderBookEntry[] asks, ISymbolOrderBookEntry[] bids)
|
public SharedOrderBook(SharedQuantityType quantityType, ISymbolOrderBookEntry[] asks, ISymbolOrderBookEntry[] bids)
|
||||||
{
|
{
|
||||||
|
QuantityType = quantityType;
|
||||||
Asks = asks;
|
Asks = asks;
|
||||||
Bids = bids;
|
Bids = bids;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user