Enhance bot command handlers with GMX wallet initialization

- Updated RestartBotCommandHandler, StartBotCommandHandler, and StartCopyTradingCommandHandler to include ITradingService for GMX wallet initialization.
- Added checks for GMX account initialization status and implemented wallet initialization logic where necessary.
- Improved error handling for wallet initialization failures.
This commit is contained in:
2025-11-21 19:05:51 +07:00
parent 53f81302ba
commit eac13dd5e4
4 changed files with 68 additions and 21 deletions

View File

@@ -1,4 +1,5 @@
using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Services;
using Managing.Application.ManageBot.Commands;
using MediatR;
using static Managing.Common.Enums;
@@ -8,10 +9,14 @@ namespace Managing.Application.ManageBot
public class RestartBotCommandHandler : IRequestHandler<RestartBotCommand, BotStatus>
{
private readonly IBotService _botService;
private readonly IAccountService _accountService;
private readonly ITradingService _tradingService;
public RestartBotCommandHandler(IBotService botService)
public RestartBotCommandHandler(IBotService botService, IAccountService accountService, ITradingService tradingService)
{
_botService = botService;
_accountService = accountService;
_tradingService = tradingService;
}
public async Task<BotStatus> Handle(RestartBotCommand request, CancellationToken cancellationToken)
@@ -37,6 +42,24 @@ namespace Managing.Application.ManageBot
"You cannot restart this bot while you have multiple strategies on the same ticker.");
}
// Get bot configuration to check account initialization status
var botConfig = await _botService.GetBotConfig(request.Identifier);
if (botConfig == null)
{
throw new InvalidOperationException($"Could not retrieve configuration for bot {request.Identifier}");
}
// Get account to check GMX initialization status
var account = await _accountService.GetAccount(botConfig.AccountName, true, true);
if (account.Exchange == TradingExchanges.GmxV2 && !account.IsGmxInitialized)
{
var initResult = await _tradingService.InitPrivyWallet(account.Key, TradingExchanges.GmxV2);
if (!initResult.Success)
{
throw new InvalidOperationException($"Failed to initialize GMX wallet: {initResult.Error}");
}
}
return await _botService.RestartBot(request.Identifier);
}
}

View File

@@ -14,13 +14,15 @@ namespace Managing.Application.ManageBot
private readonly IAccountService _accountService;
private readonly IGrainFactory _grainFactory;
private readonly IBotService _botService;
private readonly ITradingService _tradingService;
public StartBotCommandHandler(
IAccountService accountService, IGrainFactory grainFactory, IBotService botService)
IAccountService accountService, IGrainFactory grainFactory, IBotService botService, ITradingService tradingService)
{
_accountService = accountService;
_grainFactory = grainFactory;
_botService = botService;
_tradingService = tradingService;
}
public async Task<BotStatus> Handle(StartBotCommand request, CancellationToken cancellationToken)
@@ -79,6 +81,16 @@ namespace Managing.Application.ManageBot
}
}
// Check GMX initialization status for GMX V2 accounts
if (account.Exchange == TradingExchanges.GmxV2 && !account.IsGmxInitialized)
{
var initResult = await _tradingService.InitPrivyWallet(account.Key, TradingExchanges.GmxV2);
if (!initResult.Success)
{
throw new InvalidOperationException($"Failed to initialize GMX wallet: {initResult.Error}");
}
}
Balance usdcBalance = null;
// For other exchanges, keep the original USDC balance check
if (account.Exchange != TradingExchanges.Evm && account.Exchange != TradingExchanges.GmxV2)

View File

@@ -19,16 +19,18 @@ namespace Managing.Application.ManageBot
private readonly IBotService _botService;
private readonly IKaigenService _kaigenService;
private readonly IEvmManager _evmManager;
private readonly ITradingService _tradingService;
public StartCopyTradingCommandHandler(
IAccountService accountService, IGrainFactory grainFactory, IBotService botService,
IKaigenService kaigenService, IEvmManager evmManager)
IKaigenService kaigenService, IEvmManager evmManager, ITradingService tradingService)
{
_accountService = accountService;
_grainFactory = grainFactory;
_botService = botService;
_kaigenService = kaigenService;
_evmManager = evmManager;
_tradingService = tradingService;
}
public async Task<string> Handle(StartCopyTradingCommand request, CancellationToken cancellationToken)
@@ -113,6 +115,16 @@ namespace Managing.Application.ManageBot
}
}
// Check GMX initialization status for GMX V2 accounts
if (account.Exchange == TradingExchanges.GmxV2 && !account.IsGmxInitialized)
{
var initResult = await _tradingService.InitPrivyWallet(account.Key, TradingExchanges.GmxV2);
if (!initResult.Success)
{
throw new InvalidOperationException($"Failed to initialize GMX wallet: {initResult.Error}");
}
}
Balance usdcBalance = null;
// For other exchanges, keep the original USDC balance check
if (account.Exchange != TradingExchanges.Evm && account.Exchange != TradingExchanges.GmxV2)

View File

@@ -93,7 +93,7 @@ public class InsufficientFundsException : Exception
/// </summary>
public string UserMessage { get; }
public InsufficientFundsException(string errorMessage, InsufficientFundsType errorType)
public InsufficientFundsException(string errorMessage, InsufficientFundsType errorType)
: base(errorMessage)
{
ErrorType = errorType;
@@ -104,31 +104,31 @@ public class InsufficientFundsException : Exception
{
return errorType switch
{
InsufficientFundsType.InsufficientEth =>
InsufficientFundsType.InsufficientEth =>
"❌ Insufficient ETH for Gas Fees\n" +
"Your wallet doesn't have enough ETH to pay for transaction gas fees.\n" +
"Please add ETH to your wallet and try again.",
// InsufficientFundsType.InsufficientAllowance =>
// "❌ Insufficient Token Allowance\n" +
// "The trading contract doesn't have permission to spend your tokens.\n" +
// "Please approve token spending in your wallet and try again.",
InsufficientFundsType.InsufficientAllowance =>
"❌ High Network Fee\n" +
"The gas fee for this position is too high.\n" +
"Position opening rejected.",
InsufficientFundsType.InsufficientBalance =>
InsufficientFundsType.InsufficientAllowance =>
"❌ Insufficient Token Allowance\n" +
"The trading contract doesn't have permission to spend your tokens, or you don't have enough ETH in your wallet to cover the required amount when using GMX SDK.\n" +
"Please approve token spending in your wallet and ensure you have sufficient ETH for the transaction, then try again.",
// InsufficientFundsType.InsufficientAllowance =>
// "❌ High Network Fee\n" +
// "The gas fee for this position is too high.\n" +
// "Position opening rejected.",
InsufficientFundsType.InsufficientBalance =>
"❌ Insufficient Token Balance\n" +
"Your wallet doesn't have enough tokens for this trade.\n" +
"Please add more tokens to your wallet and try again.",
InsufficientFundsType.HighNetworkFee =>
InsufficientFundsType.HighNetworkFee =>
"❌ High Network Fee\n" +
"The gas fee for this position is too high.\n" +
"Position opening rejected.",
_ => "❌ Transaction Failed\n" +
"The transaction failed due to insufficient funds.\n" +
"Please check your wallet balance and try again."
@@ -145,17 +145,17 @@ public enum InsufficientFundsType
/// Not enough ETH for gas fees
/// </summary>
InsufficientEth,
/// <summary>
/// Token allowance is insufficient (ERC20: transfer amount exceeds allowance)
/// </summary>
InsufficientAllowance,
/// <summary>
/// Token balance is insufficient
/// </summary>
InsufficientBalance,
/// <summary>
/// General insufficient funds error
/// </summary>