Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CoinEx.Net/Clients/CoinExUserClientProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public void ClearUserClients(string userIdentifier)
/// <inheritdoc />
public ICoinExRestClient GetRestClient(string userIdentifier, ApiCredentials? credentials = null, CoinExEnvironment? environment = null)
{
if (!_restClients.TryGetValue(userIdentifier, out var client))
if (!_restClients.TryGetValue(userIdentifier, out var client) || client.Disposed)
client = CreateRestClient(userIdentifier, credentials, environment);

return client;
Expand All @@ -75,7 +75,7 @@ public ICoinExRestClient GetRestClient(string userIdentifier, ApiCredentials? cr
/// <inheritdoc />
public ICoinExSocketClient GetSocketClient(string userIdentifier, ApiCredentials? credentials = null, CoinExEnvironment? environment = null)
{
if (!_socketClients.TryGetValue(userIdentifier, out var client))
if (!_socketClients.TryGetValue(userIdentifier, out var client) || client.Disposed)
client = CreateSocketClient(userIdentifier, credentials, environment);

return client;
Expand Down
38 changes: 38 additions & 0 deletions CoinEx.Net/Clients/FuturesApi/CoinExRestClientFuturesApiShared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,44 @@ async Task<ExchangeWebResult<SharedFuturesSymbol[]>> IFuturesSymbolRestClient.Ge
ExchangeSymbolCache.UpdateSymbolInfo(_topicId, response.Data);
return response;
}
async Task<ExchangeResult<SharedSymbol[]>> IFuturesSymbolRestClient.GetFuturesSymbolsForBaseAssetAsync(string baseAsset)
{
if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((IFuturesSymbolRestClient)this).GetFuturesSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<SharedSymbol[]>(Exchange, symbols.Error!);
}

return new ExchangeResult<SharedSymbol[]>(Exchange, ExchangeSymbolCache.GetSymbolsForBaseAsset(_topicId, baseAsset));
}

async Task<ExchangeResult<bool>> IFuturesSymbolRestClient.SupportsFuturesSymbolAsync(SharedSymbol symbol)
{
if (symbol.TradingMode == TradingMode.Spot)
throw new ArgumentException(nameof(symbol), "Spot symbols not allowed");

if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((IFuturesSymbolRestClient)this).GetFuturesSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<bool>(Exchange, symbols.Error!);
}

return new ExchangeResult<bool>(Exchange, ExchangeSymbolCache.SupportsSymbol(_topicId, symbol));
}

async Task<ExchangeResult<bool>> IFuturesSymbolRestClient.SupportsFuturesSymbolAsync(string symbolName)
{
if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((IFuturesSymbolRestClient)this).GetFuturesSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<bool>(Exchange, symbols.Error!);
}

return new ExchangeResult<bool>(Exchange, ExchangeSymbolCache.SupportsSymbol(_topicId, symbolName));
}
#endregion

#region Futures Order Client
Expand Down Expand Up @@ -440,6 +477,7 @@ async Task<ExchangeWebResult<SharedPosition[]>> IFuturesOrderRestClient.GetPosit
Leverage = x.Leverage,
StopLossPrice = x.StopLossPrice == 0 ? null : x.StopLossPrice,
TakeProfitPrice = x.TakeProfitPrice == 0 ? null : x.TakeProfitPrice,
PositionMode = SharedPositionMode.OneWay,
PositionSide = x.Side == PositionSide.Short ? SharedPositionSide.Short : SharedPositionSide.Long
}).ToArray());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ async Task<ExchangeResult<UpdateSubscription>> IPositionSocketClient.SubscribeTo
update => handler(update.ToType<SharedPosition[]>(new[] { new SharedPosition(ExchangeSymbolCache.ParseSymbol(_topicId, update.Data.Position.Symbol), update.Data.Position.Symbol, update.Data.Position.OpenInterest, update.Data.Position.UpdateTime)
{
AverageOpenPrice = update.Data.Position.AverageEntryPrice,
PositionMode = SharedPositionMode.OneWay,
PositionSide = update.Data.Position.Side == Enums.PositionSide.Short ? SharedPositionSide.Short : SharedPositionSide.Long,
LiquidationPrice = update.Data.Position.LiquidationPrice,
Leverage = update.Data.Position.Leverage,
Expand Down
47 changes: 46 additions & 1 deletion CoinEx.Net/Clients/SpotApiV2/CoinExRestClientSpotApiShared.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,44 @@ async Task<ExchangeWebResult<SharedSpotSymbol[]>> ISpotSymbolRestClient.GetSpotS
ExchangeSymbolCache.UpdateSymbolInfo(_topicId, response.Data);
return response;
}
async Task<ExchangeResult<SharedSymbol[]>> ISpotSymbolRestClient.GetSpotSymbolsForBaseAssetAsync(string baseAsset)
{
if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((ISpotSymbolRestClient)this).GetSpotSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<SharedSymbol[]>(Exchange, symbols.Error!);
}

return new ExchangeResult<SharedSymbol[]>(Exchange, ExchangeSymbolCache.GetSymbolsForBaseAsset(_topicId, baseAsset));
}

async Task<ExchangeResult<bool>> ISpotSymbolRestClient.SupportsSpotSymbolAsync(SharedSymbol symbol)
{
if (symbol.TradingMode != TradingMode.Spot)
throw new ArgumentException(nameof(symbol), "Only Spot symbols allowed");

if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((ISpotSymbolRestClient)this).GetSpotSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<bool>(Exchange, symbols.Error!);
}

return new ExchangeResult<bool>(Exchange, ExchangeSymbolCache.SupportsSymbol(_topicId, symbol));
}

async Task<ExchangeResult<bool>> ISpotSymbolRestClient.SupportsSpotSymbolAsync(string symbolName)
{
if (!ExchangeSymbolCache.HasCached(_topicId))
{
var symbols = await ((ISpotSymbolRestClient)this).GetSpotSymbolsAsync(new GetSymbolsRequest()).ConfigureAwait(false);
if (!symbols)
return new ExchangeResult<bool>(Exchange, symbols.Error!);
}

return new ExchangeResult<bool>(Exchange, ExchangeSymbolCache.SupportsSymbol(_topicId, symbolName));
}
#endregion

#region Ticker client
Expand Down Expand Up @@ -728,7 +765,15 @@ async Task<ExchangeWebResult<SharedDeposit[]>> IDepositRestClient.GetDepositsAsy
if (deposits.Data.HasNext == true)
nextToken = new PageToken(page + 1, pageSize);

return deposits.AsExchangeResult<SharedDeposit[]>(Exchange, TradingMode.Spot, deposits.Data.Items.Select(x => new SharedDeposit(x.Asset, x.Quantity, x.Status == DepositStatus.Finished, x.CreateTime)
return deposits.AsExchangeResult<SharedDeposit[]>(Exchange, TradingMode.Spot, deposits.Data.Items.Select(x =>
new SharedDeposit(
x.Asset,
x.Quantity,
x.Status == DepositStatus.Finished,
x.CreateTime,
x.Status == DepositStatus.Finished ? SharedTransferStatus.Completed
: x.Status == DepositStatus.Processing || x.Status == DepositStatus.Confirming ? SharedTransferStatus.InProgress
: SharedTransferStatus.Failed)
{
Id = x.Id.ToString(),
Confirmations = x.Confirmations,
Expand Down
2 changes: 1 addition & 1 deletion CoinEx.Net/CoinEx.Net.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Crc32.NET" Version="1.2.0" />
<PackageReference Include="CryptoExchange.Net" Version="10.3.0" />
<PackageReference Include="CryptoExchange.Net" Version="10.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.101">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
61 changes: 61 additions & 0 deletions CoinEx.Net/CoinEx.Net.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 62 additions & 0 deletions CoinEx.Net/CoinExTrackerFactory.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
using CoinEx.Net.Clients;
using CoinEx.Net.Interfaces;
using CoinEx.Net.Interfaces.Clients;
using CryptoExchange.Net.Authentication;
using CryptoExchange.Net.SharedApis;
using CryptoExchange.Net.Trackers.Klines;
using CryptoExchange.Net.Trackers.Trades;
using CryptoExchange.Net.Trackers.UserData.Interfaces;
using CryptoExchange.Net.Trackers.UserData.Objects;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System;

namespace CoinEx.Net
Expand Down Expand Up @@ -70,5 +74,63 @@ public ITradeTracker CreateTradeTracker(SharedSymbol symbol, int? limit = null,
period
);
}

/// <inheritdoc />
public IUserSpotDataTracker CreateUserSpotDataTracker(SpotUserDataTrackerConfig? config = null)
{
var restClient = _serviceProvider?.GetRequiredService<ICoinExRestClient>() ?? new CoinExRestClient();
var socketClient = _serviceProvider?.GetRequiredService<ICoinExSocketClient>() ?? new CoinExSocketClient();
return new CoinExUserSpotDataTracker(
_serviceProvider?.GetRequiredService<ILogger<CoinExUserSpotDataTracker>>() ?? new NullLogger<CoinExUserSpotDataTracker>(),
restClient,
socketClient,
null,
config
);
}

/// <inheritdoc />
public IUserSpotDataTracker CreateUserSpotDataTracker(string userIdentifier, ApiCredentials credentials, SpotUserDataTrackerConfig? config = null, CoinExEnvironment? environment = null)
{
var clientProvider = _serviceProvider?.GetRequiredService<ICoinExUserClientProvider>() ?? new CoinExUserClientProvider();
var restClient = clientProvider.GetRestClient(userIdentifier, credentials, environment);
var socketClient = clientProvider.GetSocketClient(userIdentifier, credentials, environment);
return new CoinExUserSpotDataTracker(
_serviceProvider?.GetRequiredService<ILogger<CoinExUserSpotDataTracker>>() ?? new NullLogger<CoinExUserSpotDataTracker>(),
restClient,
socketClient,
userIdentifier,
config
);
}

/// <inheritdoc />
public IUserFuturesDataTracker CreateUserFuturesDataTracker(FuturesUserDataTrackerConfig? config = null)
{
var restClient = _serviceProvider?.GetRequiredService<ICoinExRestClient>() ?? new CoinExRestClient();
var socketClient = _serviceProvider?.GetRequiredService<ICoinExSocketClient>() ?? new CoinExSocketClient();
return new CoinExUserFuturesDataTracker(
_serviceProvider?.GetRequiredService<ILogger<CoinExUserFuturesDataTracker>>() ?? new NullLogger<CoinExUserFuturesDataTracker>(),
restClient,
socketClient,
null,
config
);
}

/// <inheritdoc />
public IUserFuturesDataTracker CreateUserFuturesDataTracker(string userIdentifier, ApiCredentials credentials, FuturesUserDataTrackerConfig? config = null, CoinExEnvironment? environment = null)
{
var clientProvider = _serviceProvider?.GetRequiredService<ICoinExUserClientProvider>() ?? new CoinExUserClientProvider();
var restClient = clientProvider.GetRestClient(userIdentifier, credentials, environment);
var socketClient = clientProvider.GetSocketClient(userIdentifier, credentials, environment);
return new CoinExUserFuturesDataTracker(
_serviceProvider?.GetRequiredService<ILogger<CoinExUserFuturesDataTracker>>() ?? new NullLogger<CoinExUserFuturesDataTracker>(),
restClient,
socketClient,
userIdentifier,
config
);
}
}
}
63 changes: 63 additions & 0 deletions CoinEx.Net/CoinExUserDataTracker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using CoinEx.Net.Interfaces.Clients;
using CryptoExchange.Net.SharedApis;
using CryptoExchange.Net.Trackers.UserData;
using CryptoExchange.Net.Trackers.UserData.Objects;
using Microsoft.Extensions.Logging;

namespace CoinEx.Net
{
/// <inheritdoc/>
public class CoinExUserSpotDataTracker : UserSpotDataTracker
{
/// <summary>
/// ctor
/// </summary>
public CoinExUserSpotDataTracker(
ILogger<CoinExUserSpotDataTracker> logger,
ICoinExRestClient restClient,
ICoinExSocketClient socketClient,
string? userIdentifier,
SpotUserDataTrackerConfig? config) : base(
logger,
restClient.SpotApiV2.SharedClient,
null,
restClient.SpotApiV2.SharedClient,
socketClient.SpotApiV2.SharedClient,
restClient.SpotApiV2.SharedClient,
socketClient.SpotApiV2.SharedClient,
socketClient.SpotApiV2.SharedClient,
userIdentifier,
config ?? new SpotUserDataTrackerConfig())
{
}
}

/// <inheritdoc/>
public class CoinExUserFuturesDataTracker : UserFuturesDataTracker
{
/// <inheritdoc/>
protected override bool WebsocketPositionUpdatesAreFullSnapshots => false;

/// <summary>
/// ctor
/// </summary>
public CoinExUserFuturesDataTracker(
ILogger<CoinExUserFuturesDataTracker> logger,
ICoinExRestClient restClient,
ICoinExSocketClient socketClient,
string? userIdentifier,
FuturesUserDataTrackerConfig? config) : base(logger,
restClient.FuturesApi.SharedClient,
null,
restClient.FuturesApi.SharedClient,
socketClient.FuturesApi.SharedClient,
restClient.FuturesApi.SharedClient,
socketClient.FuturesApi.SharedClient,
socketClient.FuturesApi.SharedClient,
socketClient.FuturesApi.SharedClient,
userIdentifier,
config ?? new FuturesUserDataTrackerConfig())
{
}
}
}
Loading