Add single time swap + fetch balance cache in AgentGrain
This commit is contained in:
@@ -3,7 +3,6 @@ using Managing.Application.Abstractions.Grains;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Application.Orleans;
|
||||
using Managing.Application.Shared;
|
||||
using Managing.Common;
|
||||
using Managing.Core;
|
||||
using Managing.Domain.Accounts;
|
||||
using Managing.Domain.Bots;
|
||||
@@ -108,19 +107,21 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
{
|
||||
// Registry says stopped, but check database to see if it should be running
|
||||
var databaseStatus = await GetDatabaseBotStatus(botId);
|
||||
|
||||
_logger.LogInformation("LiveTradingBotGrain {GrainId} registry: {RegistryStatus}, database: {DatabaseStatus}",
|
||||
|
||||
_logger.LogInformation(
|
||||
"LiveTradingBotGrain {GrainId} registry: {RegistryStatus}, database: {DatabaseStatus}",
|
||||
botId, registryStatus, databaseStatus);
|
||||
|
||||
if (databaseStatus == BotStatus.Running)
|
||||
{
|
||||
// Database says running but registry says stopped - trust database
|
||||
_logger.LogWarning("Status mismatch detected for bot {BotId}. Registry: {RegistryStatus}, Database: {DatabaseStatus}. Trusting database and updating registry.",
|
||||
_logger.LogWarning(
|
||||
"Status mismatch detected for bot {BotId}. Registry: {RegistryStatus}, Database: {DatabaseStatus}. Trusting database and updating registry.",
|
||||
botId, registryStatus, databaseStatus);
|
||||
|
||||
|
||||
// Update registry to match database (source of truth)
|
||||
await botRegistry.UpdateBotStatus(botId, databaseStatus);
|
||||
|
||||
|
||||
// Now proceed with resuming the bot
|
||||
await ResumeBotInternalAsync(databaseStatus);
|
||||
}
|
||||
@@ -345,69 +346,41 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
return;
|
||||
}
|
||||
|
||||
// Check broker balance before running
|
||||
var balances = await ServiceScopeHelpers.WithScopedService<IExchangeService, List<Balance>>(_scopeFactory,
|
||||
async exchangeService => { return await exchangeService.GetBalances(_tradingBot.Account, false); });
|
||||
|
||||
var usdcBalance = balances.FirstOrDefault(b => b.TokenName == Ticker.USDC.ToString());
|
||||
var ethBalance = balances.FirstOrDefault(b => b.TokenName == Ticker.ETH.ToString());
|
||||
|
||||
// Check USDC balance first
|
||||
if (usdcBalance?.Value < Constants.GMX.Config.MinimumPositionAmount)
|
||||
// Use coordinated balance checking and swap management through AgentGrain
|
||||
try
|
||||
{
|
||||
await _tradingBot.LogWarning(
|
||||
$"USDC balance is below {Constants.GMX.Config.MinimumPositionAmount} USD (actual: {usdcBalance?.Value:F2}). Stopping bot {_tradingBot.Identifier}.");
|
||||
var agentGrain = GrainFactory.GetGrain<IAgentGrain>(_state.State.User.Id);
|
||||
var balanceCheckResult = await agentGrain.CheckAndEnsureEthBalanceAsync(_state.State.Identifier, _tradingBot.Account.Name);
|
||||
|
||||
await StopAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check ETH balance and perform automatic swap if needed
|
||||
var ethValueInUsd = ethBalance?.Value * ethBalance?.Price ?? 0;
|
||||
if (ethValueInUsd < 2) // ETH balance below 2 USD
|
||||
{
|
||||
await _tradingBot.LogWarning(
|
||||
$"ETH balance is below 2 USD (actual: {ethValueInUsd:F2}). Attempting to swap USDC to ETH.");
|
||||
|
||||
// Check if we have enough USDC for the swap
|
||||
if (usdcBalance?.Value >= 5) // Need at least 5 USD for swap
|
||||
if (!balanceCheckResult.IsSuccessful)
|
||||
{
|
||||
try
|
||||
// Log the specific reason for the failure
|
||||
await _tradingBot.LogWarning($"Balance check failed: {balanceCheckResult.Message} (Reason: {balanceCheckResult.FailureReason})");
|
||||
|
||||
// Check if the bot should stop due to this failure
|
||||
if (balanceCheckResult.ShouldStopBot)
|
||||
{
|
||||
var swapInfo = await ServiceScopeHelpers.WithScopedService<IAccountService, SwapInfos>(
|
||||
_scopeFactory,
|
||||
async accountService =>
|
||||
{
|
||||
return await accountService.SwapGmxTokensAsync(_state.State.User,
|
||||
_tradingBot.Account.Name, Ticker.USDC, Ticker.ETH, 5);
|
||||
});
|
||||
|
||||
if (swapInfo.Success)
|
||||
{
|
||||
await NotifyUserAboutSwap(true, 5, swapInfo.Hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
await NotifyUserAboutSwap(false, 5, null, swapInfo.Error ?? swapInfo.Message);
|
||||
await StopAsync();
|
||||
return;
|
||||
}
|
||||
await _tradingBot.LogWarning($"Stopping bot due to balance check failure: {balanceCheckResult.Message}");
|
||||
await StopAsync();
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
else
|
||||
{
|
||||
await NotifyUserAboutSwap(false, 5, null, ex.Message);
|
||||
// Skip this execution cycle but continue running
|
||||
await _tradingBot.LogInformation("Skipping this execution cycle due to balance check failure.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Both USDC and ETH are low - stop the strategy
|
||||
await _tradingBot.LogWarning(
|
||||
$"Both USDC ({usdcBalance?.Value:F2}) and ETH ({ethValueInUsd:F2}) balances are low. Stopping bot {_tradingBot.Identifier}.");
|
||||
|
||||
await StopAsync();
|
||||
return;
|
||||
await _tradingBot.LogInformation($"Balance check successful: {balanceCheckResult.Message}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error during coordinated balance check for bot {BotId}", _state.State.Identifier);
|
||||
// Continue execution to avoid stopping the bot due to coordination errors
|
||||
}
|
||||
|
||||
// Execute the bot's Run method
|
||||
await _tradingBot.Run();
|
||||
@@ -849,7 +822,7 @@ public class LiveTradingBotGrain : Grain, ILiveTradingBotGrain, IRemindable
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Ping received for LiveTradingBotGrain {GrainId}", this.GetPrimaryKey());
|
||||
|
||||
|
||||
// The grain activation (OnActivateAsync) will automatically call ResumeBotIfRequiredAsync()
|
||||
// which handles checking the registry status and re-registering reminders if needed
|
||||
// So we just need to return true to indicate the ping was received
|
||||
|
||||
Reference in New Issue
Block a user