Block user to create strategy with over allocation

This commit is contained in:
2025-10-03 16:14:24 +07:00
parent 83ee4f633c
commit 6928770da7
3 changed files with 80 additions and 0 deletions

View File

@@ -115,6 +115,14 @@ namespace Managing.Application.ManageBot
if (account.Exchange == TradingExchanges.Evm || account.Exchange == TradingExchanges.GmxV2)
{
// Allocation guard: ensure this bot's configured balance fits in remaining allocation
var availableAllocation = await GetAvailableAllocationUsdAsync(account, identifier);
if (botConfig.BotTradingBalance > availableAllocation)
{
throw new InvalidOperationException(
$"Insufficient available allocation on account '{account.Name}'. Requested: {botConfig.BotTradingBalance:F2} USDC, Available: {availableAllocation:F2} USDC.");
}
var balanceCheckResult = await CheckAccountBalancesAsync(account);
if (!balanceCheckResult.IsSuccessful)
{
@@ -370,6 +378,60 @@ namespace Managing.Application.ManageBot
}
}
public async Task<decimal> GetAvailableAllocationUsdAsync(Account account, Guid excludeIdentifier = default)
{
try
{
return await ServiceScopeHelpers.WithScopedService<IBotRepository, decimal>(
_scopeFactory,
async repo =>
{
// Get all bots for the account's user
var botsForUser = await repo.GetBotsByUserIdAsync(account.User.Id);
// Sum allocations for bots using this account name, excluding the requested identifier
decimal totalAllocatedForAccount = 0m;
foreach (var bot in botsForUser)
{
if (excludeIdentifier != default && bot.Identifier == excludeIdentifier)
{
continue;
}
var grain = _grainFactory.GetGrain<ILiveTradingBotGrain>(bot.Identifier);
TradingBotConfig config;
try
{
config = await grain.GetConfiguration();
}
catch
{
continue;
}
if (string.Equals(config.AccountName, account.Name, StringComparison.OrdinalIgnoreCase))
{
totalAllocatedForAccount += config.BotTradingBalance;
}
}
// Current USDC balance for the account
var balances = await ServiceScopeHelpers.WithScopedService<IExchangeService, IEnumerable<Balance>>(
_scopeFactory, async exchangeService => await exchangeService.GetBalances(account));
var usdc = balances.FirstOrDefault(b => b.TokenName?.ToUpper() == "USDC");
var usdcValue = usdc?.Value ?? 0m;
var available = usdcValue - totalAllocatedForAccount;
return available < 0m ? 0m : available;
});
}
catch
{
// On failure, be safe and return 0 to block over-allocation
return 0m;
}
}
public async Task<(IEnumerable<Bot> Bots, int TotalCount)> GetBotsPaginatedAsync(
int pageNumber,
int pageSize,