using CryptoExchange.Net.Objects;
using CryptoExchange.Net.Objects.Sockets;
using CryptoExchange.Net.SharedApis;
using CryptoExchange.Net.Trackers.UserData.Objects;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
namespace CryptoExchange.Net.Trackers.UserData.ItemTrackers
{
///
/// Balance tracker implementation
///
public class BalanceTracker : UserDataItemTracker
{
private readonly IGetBalancesRest _restClient;
private readonly ISubscribeBalancesSocket? _socketClient;
private readonly ExchangeParameters? _exchangeParameters;
private readonly SharedAccountType _accountType;
///
/// ctor
///
public BalanceTracker(
ILogger logger,
UserDataSymbolTracker symbolTracker,
IGetBalancesRest restClient,
ISubscribeBalancesSocket? socketClient,
SharedAccountType accountType,
TrackerItemConfig config,
ExchangeParameters? exchangeParameters = null
) : base(logger, symbolTracker, UserDataType.Balances, restClient.Exchange)
{
if (socketClient == null)
config = config with { PollIntervalConnected = config.PollIntervalDisconnected };
SetConfig(config);
_restClient = restClient;
_socketClient = socketClient;
_exchangeParameters = exchangeParameters;
_accountType = accountType;
}
///
protected override bool Update(SharedBalance existingItem, SharedBalance updateItem)
{
var changed = false;
if (existingItem.Total != updateItem.Total)
{
existingItem.Total = updateItem.Total;
changed = true;
}
if (existingItem.Available != updateItem.Available)
{
existingItem.Available = updateItem.Available;
changed = true;
}
return changed;
}
///
protected override string GetKey(SharedBalance item) => item.Asset + item.IsolatedMarginSymbol;
///
protected override bool? CheckIfUpdateShouldBeApplied(SharedBalance existingItem, SharedBalance updateItem) => true;
///
protected override Task> DoSubscribeAsync()
{
if (_socketClient == null)
return Task.FromResult(new WebSocketResult(default!, default!, default));
var accountType = _accountType == SharedAccountType.Spot ? TradingMode.Spot :
_accountType == SharedAccountType.PerpetualInverseFutures ? TradingMode.PerpetualInverse :
_accountType == SharedAccountType.DeliveryLinearFutures ? TradingMode.DeliveryLinear :
_accountType == SharedAccountType.DeliveryInverseFutures ? TradingMode.DeliveryInverse :
TradingMode.PerpetualLinear;
return ExchangeHelpers.ProcessQueuedAsync(
async handler => await _socketClient.SubscribeToBalanceUpdatesAsync(new SubscribeBalancesRequest(accountType, exchangeParameters: _exchangeParameters), handler, ct: _cts!.Token).ConfigureAwait(false),
x => HandleUpdateAsync(UpdateSource.Push, x.Data))!;
}
///
protected override async Task DoPollAsync()
{
var balances = await _restClient.GetBalancesAsync(new GetBalancesRequest(accountType: _accountType, exchangeParameters: _exchangeParameters)).ConfigureAwait(false);
if (balances.Success)
await HandleUpdateAsync(UpdateSource.Poll, balances.Data).ConfigureAwait(false);
else
_initialPollingError ??= balances.Error;
return !balances.Success;
}
}
}