Trading bot grain (#33)

* Trading bot Grain

* Fix a bit more of the trading bot

* Advance on the tradingbot grain

* Fix build

* Fix db script

* Fix user login

* Fix a bit backtest

* Fix cooldown and backtest

* start fixing bot start

* Fix startup

* Setup local db

* Fix build and update candles and scenario

* Add bot registry

* Add reminder

* Updateing the grains

* fix bootstraping

* Save stats on tick

* Save bot data every tick

* Fix serialization

* fix save bot stats

* Fix get candles

* use dict instead of list for position

* Switch hashset to dict

* Fix a bit

* Fix bot launch and bot view

* add migrations

* Remove the tolist

* Add agent grain

* Save agent summary

* clean

* Add save bot

* Update get bots

* Add get bots

* Fix stop/restart

* fix Update config

* Update scanner table on new backtest saved

* Fix backtestRowDetails.tsx

* Fix agentIndex

* Update agentIndex

* Fix more things

* Update user cache

* Fix

* Fix account load/start/restart/run
This commit is contained in:
Oda
2025-08-04 23:07:06 +02:00
committed by GitHub
parent cd378587aa
commit 082ae8714b
215 changed files with 9562 additions and 14028 deletions

View File

@@ -1,8 +1,10 @@
using System.Text.RegularExpressions;
using Managing.Application.Abstractions.Grains;
using Managing.Application.Abstractions.Repositories;
using Managing.Application.Abstractions.Services;
using Managing.Common;
using Managing.Domain.Accounts;
using Managing.Domain.Statistics;
using Managing.Domain.Users;
using Microsoft.Extensions.Logging;
@@ -15,6 +17,8 @@ public class UserService : IUserService
private readonly IAccountService _accountService;
private readonly ILogger<UserService> _logger;
private readonly ICacheService _cacheService;
private readonly IGrainFactory _grainFactory;
private readonly IAgentSummaryRepository _agentSummaryRepository;
private string[] authorizedAddresses =
[
@@ -33,15 +37,19 @@ public class UserService : IUserService
public UserService(
IEvmManager evmManager,
IUserRepository userRepository,
IAccountService accountService,
IAccountService accountService,
ILogger<UserService> logger,
ICacheService cacheService)
ICacheService cacheService,
IGrainFactory grainFactory,
IAgentSummaryRepository agentSummaryRepository)
{
_evmManager = evmManager;
_userRepository = userRepository;
_accountService = accountService;
_logger = logger;
_cacheService = cacheService;
_grainFactory = grainFactory;
_agentSummaryRepository = agentSummaryRepository;
}
public async Task<User> Authenticate(string name, string address, string message, string signature)
@@ -120,26 +128,32 @@ public class UserService : IUserService
return user;
}
public async Task<User> GetUserByAddressAsync(string address)
public async Task<User> GetUserByAddressAsync(string address, bool useCache = true)
{
var cacheKey = $"user-by-address-{address}";
// Check cache first
var cachedUser = _cacheService.GetValue<User>(cacheKey);
if (cachedUser != null)
// Check cache first if caching is enabled
if (useCache)
{
return cachedUser;
var cachedUser = _cacheService.GetValue<User>(cacheKey);
if (cachedUser != null)
{
return cachedUser;
}
}
// Cache miss - fetch from database
// Fetch from database (either cache miss or cache disabled)
var account = await _accountService.GetAccountByKey(address, true, false);
var user = await _userRepository.GetUserByNameAsync(account.User.Name);
// Use proper async version to avoid DbContext concurrency issues
user.Accounts = (await _accountService.GetAccountsByUserAsync(user)).ToList();
// Save to cache for 10 minutes (JWT middleware calls this on every request)
_cacheService.SaveValue(cacheKey, user, TimeSpan.FromMinutes(10));
// Save to cache for 10 minutes if caching is enabled (JWT middleware calls this on every request)
if (useCache)
{
_cacheService.SaveValue(cacheKey, user, TimeSpan.FromMinutes(10));
}
return user;
}
@@ -154,8 +168,25 @@ public class UserService : IUserService
}
else
{
user = await GetUserByName(user.Name);
user.AgentName = agentName;
await _userRepository.UpdateUser(user);
// Initialize the AgentGrain for this user
try
{
var agentGrain = _grainFactory.GetGrain<IAgentGrain>(user.Id);
await agentGrain.InitializeAsync(user.Id, agentName);
_logger.LogInformation("AgentGrain initialized for user {UserId} with agent name {AgentName}", user.Id,
agentName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to initialize AgentGrain for user {UserId} with agent name {AgentName}",
user.Id, agentName);
// Don't throw here to avoid breaking the user update process
}
return user;
}
}
@@ -176,6 +207,7 @@ public class UserService : IUserService
throw new Exception("URL must point to a JPEG or PNG image");
}
user = await GetUserByName(user.Name);
user.AvatarUrl = avatarUrl;
await _userRepository.UpdateUser(user);
return user;
@@ -193,13 +225,41 @@ public class UserService : IUserService
}
}
user = await GetUserByName(user.Name);
user.TelegramChannel = telegramChannel;
await _userRepository.UpdateUser(user);
return user;
}
public async Task<User> GetUser(string name)
public async Task<User> GetUserByName(string name)
{
return await _userRepository.GetUserByNameAsync(name);
}
public async Task<User> GetUserByAgentName(string agentName)
{
var user = await _userRepository.GetUserByAgentNameAsync(agentName);
if (user == null)
{
throw new Exception($"User with agent name {agentName} not found");
}
return user;
}
public async Task SaveOrUpdateAgentSummary(AgentSummary agentSummary)
{
try
{
await _agentSummaryRepository.SaveOrUpdateAsync(agentSummary);
_logger.LogInformation("AgentSummary saved/updated for user {UserId} with agent name {AgentName}",
agentSummary.UserId, agentSummary.AgentName);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to save/update AgentSummary for user {UserId} with agent name {AgentName}",
agentSummary.UserId, agentSummary.AgentName);
throw;
}
}
}