Add validation for Kudai strategy staking requirements in StartCopyTradingCommandHandler. Implemented methods in IEvmManager to retrieve staked KUDAI balance and GBC NFT count. Enhanced error handling for staking checks.

This commit is contained in:
2025-11-17 12:57:47 +07:00
parent 4b24a934ad
commit 8697f1598d
4 changed files with 147 additions and 13 deletions

View File

@@ -1,13 +1,14 @@
using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Grains;
using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Services;
using Managing.Application.ManageBot.Commands;
using Managing.Common;
using Managing.Domain.Accounts;
using Managing.Domain.Bots;
using Managing.Domain.Users;
using MediatR;
using static Managing.Common.Enums;
using System;
namespace Managing.Application.ManageBot
{
@@ -17,14 +18,16 @@ namespace Managing.Application.ManageBot
private readonly IGrainFactory _grainFactory;
private readonly IBotService _botService;
private readonly IKaigenService _kaigenService;
private readonly IEvmManager _evmManager;
public StartCopyTradingCommandHandler(
IAccountService accountService, IGrainFactory grainFactory, IBotService botService, IKaigenService kaigenService)
IAccountService accountService, IGrainFactory grainFactory, IBotService botService, IKaigenService kaigenService, IEvmManager evmManager)
{
_accountService = accountService;
_grainFactory = grainFactory;
_botService = botService;
_kaigenService = kaigenService;
_evmManager = evmManager;
}
public async Task<string> Handle(StartCopyTradingCommand request, CancellationToken cancellationToken)
@@ -43,17 +46,23 @@ namespace Managing.Application.ManageBot
throw new ArgumentException($"Master bot with identifier {request.MasterBotIdentifier} not found");
}
// Verify the user owns the keys of the master strategy
var ownedKeys = await _kaigenService.GetOwnedKeysAsync(request.User);
var hasMasterStrategyKey = ownedKeys.Items.Any(key =>
string.Equals(key.AgentName, request.MasterBotIdentifier.ToString(), StringComparison.OrdinalIgnoreCase) &&
key.Owned >= 1);
if (!hasMasterStrategyKey)
// Special validation for Kudai strategy - check staking requirements
if (string.Equals(request.MasterBotIdentifier.ToString(), "Kudai", StringComparison.OrdinalIgnoreCase))
{
throw new UnauthorizedAccessException(
$"You don't own the keys for the master strategy '{request.MasterBotIdentifier}'. " +
"You must own at least 1 key for this strategy to copy trade from it.");
await ValidateKudaiStakingRequirements(request.User);
}else {
// Verify the user owns the keys of the master strategy
var ownedKeys = await _kaigenService.GetOwnedKeysAsync(request.User);
var hasMasterStrategyKey = ownedKeys.Items.Any(key =>
string.Equals(key.AgentName, request.MasterBotIdentifier.ToString(), StringComparison.OrdinalIgnoreCase) &&
key.Owned >= 1);
if (!hasMasterStrategyKey)
{
throw new UnauthorizedAccessException(
$"You don't own the keys for the master strategy '{request.MasterBotIdentifier}'. " +
"You must own at least 1 key for this strategy to copy trade from it.");
}
}
// Get the master bot configuration
@@ -153,5 +162,39 @@ namespace Managing.Application.ManageBot
throw new Exception($"Failed to start copy trading bot: {ex.Message}, {ex.StackTrace}");
}
}
private async Task ValidateKudaiStakingRequirements(User user)
{
// Get user's accounts to find their wallet address
var userAccounts = await _accountService.GetAccountsByUserAsync(user, true, true);
var evmAccount = userAccounts.FirstOrDefault(acc =>
acc.Exchange == TradingExchanges.Evm ||
acc.Exchange == TradingExchanges.GmxV2);
if (evmAccount == null)
{
throw new InvalidOperationException(
"To copy trade the Kudai strategy, you must have an EVM-compatible account (GMX V2 or EVM exchange).");
}
// Check KUDAI staked balance
var kudaiStakedBalance = await _evmManager.GetKudaiStakedBalance(evmAccount.Key);
// Check GBC staked NFT count
var gbcStakedCount = await _evmManager.GetGbcStakedCount(evmAccount.Key);
// Requirements: 100 million KUDAI OR 10 GBC NFTs
const decimal requiredKudaiAmount = 100_000_000m; // 100 million
const int requiredGbcCount = 10;
if (kudaiStakedBalance < requiredKudaiAmount && gbcStakedCount < requiredGbcCount)
{
throw new UnauthorizedAccessException(
$"To copy trade the Kudai strategy, you must have either:\n" +
$"• {requiredKudaiAmount:N0} KUDAI tokens staked (currently have {kudaiStakedBalance:N0})\n" +
$"• OR {requiredGbcCount} GBC NFTs staked (currently have {gbcStakedCount})\n\n" +
$"Please stake the required amount in the Kudai staking contract to copy this strategy.");
}
}
}
}
}