From de0d042254e983496f706cbaa53cd2e8482e5490 Mon Sep 17 00:00:00 2001 From: cryptooda Date: Sun, 5 Oct 2025 01:36:25 +0700 Subject: [PATCH] Use usdc balance instead usdc value for ensuring balance check --- .../Repositories/IEvmManager.cs | 4 +- .../Bots/Grains/AgentGrain.cs | 6 +-- .../Bots/Models/AgentGrainState.cs | 2 +- .../ManageBot/BotService.cs | 45 +++++++--------- .../Exchanges/EvmProcessor.cs | 40 ++++++--------- .../EvmManager.cs | 51 +++++-------------- .../EvmMappers.cs | 20 ++++++++ 7 files changed, 72 insertions(+), 96 deletions(-) create mode 100644 src/Managing.Infrastructure.Web3/EvmMappers.cs diff --git a/src/Managing.Application.Abstractions/Repositories/IEvmManager.cs b/src/Managing.Application.Abstractions/Repositories/IEvmManager.cs index cd33025e..8a627c02 100644 --- a/src/Managing.Application.Abstractions/Repositories/IEvmManager.cs +++ b/src/Managing.Application.Abstractions/Repositories/IEvmManager.cs @@ -19,7 +19,7 @@ public interface IEvmManager string VerifySignature(string signature, string message); Task> GetBalances(Chain chain, int page, int pageSize, string publicAddress); Task> GetAllBalances(Chain chain, string publicAddress); - Task> GetAllBalancesOnAllChain(string publicAddress); + Task> GetAllBalancesOnAllChain(string publicAddress); Task> GetCandles(Ticker ticker, DateTime startDate, Timeframe interval, bool isFirstCall = false); @@ -68,7 +68,7 @@ public interface IEvmManager Task SignMessageAsync(string embeddedWalletId, string address, string message); Task> GetPositions(Account account); - + /// /// Clears the cached balances for a specific chain and address /// diff --git a/src/Managing.Application/Bots/Grains/AgentGrain.cs b/src/Managing.Application/Bots/Grains/AgentGrain.cs index 6af3ec85..697b7b74 100644 --- a/src/Managing.Application/Bots/Grains/AgentGrain.cs +++ b/src/Managing.Application/Bots/Grains/AgentGrain.cs @@ -590,7 +590,7 @@ public class AgentGrain : Grain, IAgentGrain return null; } - var userAccounts = await _accountService.GetAccountsByUserAsync(user, hideSecrets: true, true); + var userAccounts = await _accountService.GetAccountsByUserAsync(user, hideSecrets: true, false); var account = userAccounts.FirstOrDefault(a => a.Name == accountName); if (account == null) { @@ -604,7 +604,7 @@ public class AgentGrain : Grain, IAgentGrain var usdcBalance = balances.FirstOrDefault(b => b.TokenName?.ToUpper() == "USDC"); var ethValueInUsd = ethBalance?.Amount * ethBalance?.Price ?? 0; - var usdcValue = usdcBalance?.Value ?? 0; + var usdc = usdcBalance?.Amount ?? 0; // Cache the balance data var balanceData = new CachedBalanceData @@ -612,7 +612,7 @@ public class AgentGrain : Grain, IAgentGrain LastFetched = DateTime.UtcNow, AccountName = accountName, EthValueInUsd = ethValueInUsd, - UsdcValue = usdcValue + UsdcValue = usdc }; _state.State.CachedBalanceData = balanceData; diff --git a/src/Managing.Application/Bots/Models/AgentGrainState.cs b/src/Managing.Application/Bots/Models/AgentGrainState.cs index cd5041db..6bd9bc8e 100644 --- a/src/Managing.Application/Bots/Models/AgentGrainState.cs +++ b/src/Managing.Application/Bots/Models/AgentGrainState.cs @@ -67,7 +67,7 @@ namespace Managing.Application.Bots.Models /// /// Whether the cached data is still valid (less than 1 minute old) /// - public bool IsValid => DateTime.UtcNow - LastFetched < TimeSpan.FromMinutes(1.5); + public bool IsValid => DateTime.UtcNow - LastFetched < TimeSpan.FromMinutes(1); } /// diff --git a/src/Managing.Application/ManageBot/BotService.cs b/src/Managing.Application/ManageBot/BotService.cs index d902677d..9327bed5 100644 --- a/src/Managing.Application/ManageBot/BotService.cs +++ b/src/Managing.Application/ManageBot/BotService.cs @@ -394,35 +394,28 @@ namespace Managing.Application.ManageBot var totalAllocatedForAccount = 0m; var usdcBalance = account.Balances.FirstOrDefault(b => b.TokenName == Ticker.USDC.ToString()); - if (botsForUser.Any()) + foreach (var bot in botsForUser) { - foreach (var bot in botsForUser) + if (excludeIdentifier != default && bot.Identifier == excludeIdentifier) { - if (excludeIdentifier != default && bot.Identifier == excludeIdentifier) - { - continue; - } - - var grain = _grainFactory.GetGrain(bot.Identifier); - TradingBotConfig config; - try - { - config = await grain.GetConfiguration(); - } - catch - { - continue; - } - - if (string.Equals(config.AccountName, account.Name, StringComparison.OrdinalIgnoreCase)) - { - totalAllocatedForAccount += config.BotTradingBalance; - } + continue; + } + + var grain = _grainFactory.GetGrain(bot.Identifier); + TradingBotConfig config; + try + { + config = await grain.GetConfiguration(); + } + catch + { + continue; + } + + if (string.Equals(config.AccountName, account.Name, StringComparison.OrdinalIgnoreCase)) + { + totalAllocatedForAccount += config.BotTradingBalance; } - } - else - { - totalAllocatedForAccount = usdcBalance?.Value ?? 0m; } var usdcValue = usdcBalance?.Value ?? 0m; diff --git a/src/Managing.Infrastructure.Exchanges/Exchanges/EvmProcessor.cs b/src/Managing.Infrastructure.Exchanges/Exchanges/EvmProcessor.cs index 5f3e7038..2717ba70 100644 --- a/src/Managing.Infrastructure.Exchanges/Exchanges/EvmProcessor.cs +++ b/src/Managing.Infrastructure.Exchanges/Exchanges/EvmProcessor.cs @@ -2,7 +2,6 @@ using Managing.Common; using Managing.Domain.Accounts; using Managing.Domain.Candles; -using Managing.Domain.Evm; using Managing.Domain.Statistics; using Managing.Domain.Trades; using Microsoft.Extensions.Logging; @@ -45,21 +44,7 @@ public class EvmProcessor : BaseProcessor public override async Task> GetBalances(Account account, bool isForPaperTrading = false) { - var balances = await _evmManager.GetAllBalancesOnAllChain(account.Key); - return Map(balances); - } - - private List Map(List balances) - { - return balances.ConvertAll(balance => new Balance - { - TokenName = balance.TokenName, - Price = balance.Price, - Value = balance.Value, - Amount = balance.Balance, - TokenAdress = balance.TokenAddress, - Chain = balance.Chain - }); + return await _evmManager.GetAllBalancesOnAllChain(account.Key); } public override async Task GetCandle(Account account, Ticker ticker, DateTime date) @@ -73,7 +58,8 @@ public class EvmProcessor : BaseProcessor return await _evmManager.GetCandles(ticker, startDate, interval); } - public async Task> GetCandles(Account account, Ticker ticker, DateTime startDate, Timeframe interval, bool isFirstCall) + public async Task> GetCandles(Account account, Ticker ticker, DateTime startDate, Timeframe interval, + bool isFirstCall) { return await _evmManager.GetCandles(ticker, startDate, interval, isFirstCall); } @@ -86,11 +72,13 @@ public class EvmProcessor : BaseProcessor public override async Task GetPrice(Account account, Ticker ticker, DateTime date) { var candles = await GetCandles(account, ticker, date, Timeframe.OneMinute, true); - + if (candles == null || !candles.Any()) { - _logger.LogError($"No candles available for ticker {ticker} at date {date:yyyy-MM-dd HH:mm:ss}. This could indicate a data source issue or invalid ticker."); - throw new InvalidOperationException($"Cannot get price for {ticker} - no candle data available for the requested date {date:yyyy-MM-dd HH:mm:ss}. Please check if the ticker is valid and data source is accessible."); + _logger.LogError( + $"No candles available for ticker {ticker} at date {date:yyyy-MM-dd HH:mm:ss}. This could indicate a data source issue or invalid ticker."); + throw new InvalidOperationException( + $"Cannot get price for {ticker} - no candle data available for the requested date {date:yyyy-MM-dd HH:mm:ss}. Please check if the ticker is valid and data source is accessible."); } return candles.Last().Close; @@ -110,7 +98,7 @@ public class EvmProcessor : BaseProcessor // Try to get the most recent candle data (last 5 minutes) var recentDate = DateTime.UtcNow.AddMinutes(-5); var candles = await GetCandles(account, ticker, recentDate, Timeframe.OneMinute, true); - + if (candles != null && candles.Any()) { var latestCandle = candles.OrderByDescending(c => c.Date).First(); @@ -121,17 +109,19 @@ public class EvmProcessor : BaseProcessor // Fallback: Try to get price from a broader time range var fallbackDate = DateTime.UtcNow.AddHours(-1); var fallbackCandles = await GetCandles(account, ticker, fallbackDate, Timeframe.OneMinute, true); - + if (fallbackCandles != null && fallbackCandles.Any()) { var latestFallbackCandle = fallbackCandles.OrderByDescending(c => c.Date).First(); - _logger.LogWarning($"Using fallback price {latestFallbackCandle.Close} for {ticker} from 1-hour old data"); + _logger.LogWarning( + $"Using fallback price {latestFallbackCandle.Close} for {ticker} from 1-hour old data"); return latestFallbackCandle.Close; } // If all else fails, throw a descriptive error _logger.LogError($"No price data available for {ticker} from any source"); - throw new InvalidOperationException($"Cannot get current price for {ticker} - no price data available from broker. Please check if the ticker is valid and the broker is accessible."); + throw new InvalidOperationException( + $"Cannot get current price for {ticker} - no price data available from broker. Please check if the ticker is valid and the broker is accessible."); } catch (Exception ex) { @@ -162,7 +152,7 @@ public class EvmProcessor : BaseProcessor public override async Task> GetPositions(Account account) { - return await _evmManager.GetPositions(account); + return await _evmManager.GetPositions(account); } public override decimal GetVolume(Account account, Ticker ticker) diff --git a/src/Managing.Infrastructure.Web3/EvmManager.cs b/src/Managing.Infrastructure.Web3/EvmManager.cs index 27c5ea68..92075411 100644 --- a/src/Managing.Infrastructure.Web3/EvmManager.cs +++ b/src/Managing.Infrastructure.Web3/EvmManager.cs @@ -343,7 +343,7 @@ public class EvmManager : IEvmManager "https://api.coingecko.com/api/v3/simple/price?ids=" + idsCombined + "&vs_currencies=usd"); } - public async Task> GetAllBalancesOnAllChain(string publicAddress) + public async Task> GetAllBalancesOnAllChain(string publicAddress) { try { @@ -352,44 +352,17 @@ public class EvmManager : IEvmManager var chains = new[] { "arbitrum" }; // Get balances from Web3Proxy service - var balances = await _web3ProxyService.GetWalletBalanceAsync(publicAddress, assets, chains); + return await _web3ProxyService.GetWalletBalanceAsync(publicAddress, assets, chains); - // Convert Balance objects to EvmBalance objects - var evmBalances = new List(); - - foreach (var balance in balances) - { - if (balance.Amount > 0) - { - var evmBalance = new EvmBalance - { - Balance = balance.Amount, - TokenName = balance.TokenName ?? "Unknown", - TokenAddress = balance.TokenAdress ?? "", - TokenImage = balance.TokenImage ?? "", - Price = balance.Price, - Value = balance.Value, - Chain = new Chain - { - Id = balance.Chain?.Id ?? "", - Name = balance.Chain?.Name ?? "Unknown", - ChainId = balance.Chain?.ChainId ?? 0, - RpcUrl = balance.Chain?.RpcUrl ?? "" - } - }; - evmBalances.Add(evmBalance); - } - } - - - var othersChains = ChainService.GetChains(); - - foreach (var chain in othersChains) - { - evmBalances.AddRange(await GetAllBalances(chain, publicAddress)); - } - - return evmBalances; + // TODO : Update here to get all different chains + // var othersChains = ChainService.GetChains(); + // + // foreach (var chain in othersChains) + // { + // evmBalances.AddRange(await GetAllBalances(chain, publicAddress)); + // } + // + // return evmBalances; } catch (Exception ex) { @@ -404,7 +377,7 @@ public class EvmManager : IEvmManager chainBalances.AddRange(await GetAllBalances(chain, publicAddress)); } - return chainBalances; + return EvmMappers.Map(chainBalances); } } diff --git a/src/Managing.Infrastructure.Web3/EvmMappers.cs b/src/Managing.Infrastructure.Web3/EvmMappers.cs new file mode 100644 index 00000000..34220c00 --- /dev/null +++ b/src/Managing.Infrastructure.Web3/EvmMappers.cs @@ -0,0 +1,20 @@ +using Managing.Domain.Accounts; +using Managing.Domain.Evm; + +namespace Managing.Infrastructure.Evm; + +public static class EvmMappers +{ + public static List Map(List balances) + { + return balances.ConvertAll(balance => new Balance + { + TokenName = balance.TokenName, + Price = balance.Price, + Value = balance.Value, + Amount = balance.Balance, + TokenAdress = balance.TokenAddress, + Chain = balance.Chain + }); + } +} \ No newline at end of file