Add agent balance fetch from proxy
This commit is contained in:
@@ -15,5 +15,7 @@ namespace Managing.Application.Abstractions.Services
|
|||||||
string orderType = "market", double? triggerRatio = null, double allowedSlippage = 0.5);
|
string orderType = "market", double? triggerRatio = null, double allowedSlippage = 0.5);
|
||||||
|
|
||||||
Task<SwapInfos> SendTokenAsync(string senderAddress, string recipientAddress, Ticker ticker, decimal amount, int? chainId = null);
|
Task<SwapInfos> SendTokenAsync(string senderAddress, string recipientAddress, Ticker ticker, decimal amount, int? chainId = null);
|
||||||
|
|
||||||
|
Task<List<Balance>> GetWalletBalanceAsync(string address, Ticker[] assets, string[] chains);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ public class AccountService : IAccountService
|
|||||||
throw new ArgumentException($"Account '{name}' not found");
|
throw new ArgumentException($"Account '{name}' not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
ManageProperties(hideSecrets, getBalance, account);
|
await ManagePropertiesAsync(hideSecrets, getBalance, account);
|
||||||
|
|
||||||
if (account.User == null && account.User != null)
|
if (account.User == null && account.User != null)
|
||||||
{
|
{
|
||||||
@@ -119,7 +119,7 @@ public class AccountService : IAccountService
|
|||||||
public async Task<Account> GetAccountByKey(string key, bool hideSecrets, bool getBalance)
|
public async Task<Account> GetAccountByKey(string key, bool hideSecrets, bool getBalance)
|
||||||
{
|
{
|
||||||
var account = await _accountRepository.GetAccountByKeyAsync(key);
|
var account = await _accountRepository.GetAccountByKeyAsync(key);
|
||||||
ManageProperties(hideSecrets, getBalance, account);
|
await ManagePropertiesAsync(hideSecrets, getBalance, account);
|
||||||
|
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ public class AccountService : IAccountService
|
|||||||
public async Task<Account> GetAccountByUser(User user, string name, bool hideSecrets, bool getBalance)
|
public async Task<Account> GetAccountByUser(User user, string name, bool hideSecrets, bool getBalance)
|
||||||
{
|
{
|
||||||
var account = await _accountRepository.GetAccountByNameAsync(name);
|
var account = await _accountRepository.GetAccountByNameAsync(name);
|
||||||
ManageProperties(hideSecrets, getBalance, account);
|
await ManagePropertiesAsync(hideSecrets, getBalance, account);
|
||||||
|
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ public class AccountService : IAccountService
|
|||||||
|
|
||||||
if (account != null)
|
if (account != null)
|
||||||
{
|
{
|
||||||
ManageProperties(hideSecrets, getBalance, account);
|
await ManagePropertiesAsync(hideSecrets, getBalance, account);
|
||||||
if (account.User != null)
|
if (account.User != null)
|
||||||
{
|
{
|
||||||
account.User = await _userRepository.GetUserByNameAsync(account.User.Name);
|
account.User = await _userRepository.GetUserByNameAsync(account.User.Name);
|
||||||
@@ -161,7 +161,7 @@ public class AccountService : IAccountService
|
|||||||
|
|
||||||
foreach (var account in result)
|
foreach (var account in result)
|
||||||
{
|
{
|
||||||
ManageProperties(hideSecrets, getBalance, account);
|
await ManagePropertiesAsync(hideSecrets, getBalance, account);
|
||||||
accounts.Add(account);
|
accounts.Add(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ public class AccountService : IAccountService
|
|||||||
|
|
||||||
foreach (var account in result.Where(a => a.User.Name == user.Name))
|
foreach (var account in result.Where(a => a.User.Name == user.Name))
|
||||||
{
|
{
|
||||||
ManageProperties(hideSecrets, getBalance, account);
|
await ManagePropertiesAsync(hideSecrets, getBalance, account);
|
||||||
accounts.Add(account);
|
accounts.Add(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +333,7 @@ public class AccountService : IAccountService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ManageProperties(bool hideSecrets, bool getBalance, Account account)
|
private async Task ManagePropertiesAsync(bool hideSecrets, bool getBalance, Account account)
|
||||||
{
|
{
|
||||||
if (account != null)
|
if (account != null)
|
||||||
{
|
{
|
||||||
@@ -341,7 +341,7 @@ public class AccountService : IAccountService
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
account.Balances = _exchangeService.GetBalances(account).Result;
|
account.Balances = await _exchangeService.GetBalances(account);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
1435
src/Managing.Infrastructure.Database/Migrations/20250815134309_AddTotalBalanceToAgent.Designer.cs
generated
Normal file
1435
src/Managing.Infrastructure.Database/Migrations/20250815134309_AddTotalBalanceToAgent.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Managing.Infrastructure.Databases.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddTotalBalanceToAgent : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<decimal>(
|
||||||
|
name: "TotalBalance",
|
||||||
|
table: "AgentSummaries",
|
||||||
|
type: "numeric(18,8)",
|
||||||
|
precision: 18,
|
||||||
|
scale: 8,
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0m);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "TotalBalance",
|
||||||
|
table: "AgentSummaries");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -90,6 +90,10 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Property<DateTime?>("Runtime")
|
b.Property<DateTime?>("Runtime")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<decimal>("TotalBalance")
|
||||||
|
.HasPrecision(18, 8)
|
||||||
|
.HasColumnType("numeric(18,8)");
|
||||||
|
|
||||||
b.Property<decimal>("TotalPnL")
|
b.Property<decimal>("TotalPnL")
|
||||||
.HasColumnType("decimal(18,8)");
|
.HasColumnType("decimal(18,8)");
|
||||||
|
|
||||||
|
|||||||
@@ -545,6 +545,7 @@ public class ManagingDbContext : DbContext
|
|||||||
entity.Property(e => e.UpdatedAt).IsRequired();
|
entity.Property(e => e.UpdatedAt).IsRequired();
|
||||||
entity.Property(e => e.ActiveStrategiesCount).IsRequired();
|
entity.Property(e => e.ActiveStrategiesCount).IsRequired();
|
||||||
entity.Property(e => e.TotalVolume).HasPrecision(18, 8);
|
entity.Property(e => e.TotalVolume).HasPrecision(18, 8);
|
||||||
|
entity.Property(e => e.TotalBalance).HasPrecision(18, 8);
|
||||||
|
|
||||||
// Create indexes for common queries
|
// Create indexes for common queries
|
||||||
entity.HasIndex(e => e.UserId).IsUnique();
|
entity.HasIndex(e => e.UserId).IsUnique();
|
||||||
|
|||||||
@@ -325,15 +325,59 @@ public class EvmManager : IEvmManager
|
|||||||
|
|
||||||
public async Task<List<EvmBalance>> GetAllBalancesOnAllChain(string publicAddress)
|
public async Task<List<EvmBalance>> GetAllBalancesOnAllChain(string publicAddress)
|
||||||
{
|
{
|
||||||
var chainBalances = new List<EvmBalance>();
|
try
|
||||||
var chains = ChainService.GetChains();
|
|
||||||
|
|
||||||
foreach (var chain in chains)
|
|
||||||
{
|
{
|
||||||
chainBalances.AddRange(await GetAllBalances(chain, publicAddress));
|
// Define the assets and chains we want to query
|
||||||
}
|
var assets = new[] { Ticker.USDC, Ticker.ETH };
|
||||||
|
var chains = new[] { "arbitrum", "ethereum" };
|
||||||
|
|
||||||
return chainBalances;
|
// Get balances from Web3Proxy service
|
||||||
|
var balances = await _web3ProxyService.GetWalletBalanceAsync(publicAddress, assets, chains);
|
||||||
|
|
||||||
|
// Convert Balance objects to EvmBalance objects
|
||||||
|
var evmBalances = new List<EvmBalance>();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return evmBalances;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Log the exception and fallback to original implementation if Web3Proxy fails
|
||||||
|
Console.WriteLine($"Web3Proxy balance retrieval failed: {ex.Message}");
|
||||||
|
|
||||||
|
var chainBalances = new List<EvmBalance>();
|
||||||
|
var chains = ChainService.GetChains();
|
||||||
|
|
||||||
|
foreach (var chain in chains)
|
||||||
|
{
|
||||||
|
chainBalances.AddRange(await GetAllBalances(chain, publicAddress));
|
||||||
|
}
|
||||||
|
|
||||||
|
return chainBalances;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Candle>> GetCandles(Ticker ticker, DateTime startDate, Timeframe timeframe,
|
public async Task<List<Candle>> GetCandles(Ticker ticker, DateTime startDate, Timeframe timeframe,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using Managing.Domain.Accounts;
|
||||||
|
|
||||||
namespace Managing.Infrastructure.Evm.Models.Proxy
|
namespace Managing.Infrastructure.Evm.Models.Proxy
|
||||||
{
|
{
|
||||||
@@ -138,4 +139,16 @@ namespace Managing.Infrastructure.Evm.Models.Proxy
|
|||||||
[JsonPropertyName("hash")]
|
[JsonPropertyName("hash")]
|
||||||
public string Hash { get; set; }
|
public string Hash { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Response for wallet balance operations
|
||||||
|
/// </summary>
|
||||||
|
public class Web3ProxyBalanceResponse : Web3ProxyResponse
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// List of wallet balances if successful
|
||||||
|
/// </summary>
|
||||||
|
[JsonPropertyName("balances")]
|
||||||
|
public List<Balance> Balances { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Collections;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -181,7 +182,8 @@ namespace Managing.Infrastructure.Evm.Services
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SwapInfos> SwapGmxTokensAsync(string account, Ticker fromTicker, Ticker toTicker, double amount, string orderType = "market", double? triggerRatio = null, double allowedSlippage = 0.5)
|
public async Task<SwapInfos> SwapGmxTokensAsync(string account, Ticker fromTicker, Ticker toTicker,
|
||||||
|
double amount, string orderType = "market", double? triggerRatio = null, double allowedSlippage = 0.5)
|
||||||
{
|
{
|
||||||
var payload = new
|
var payload = new
|
||||||
{
|
{
|
||||||
@@ -213,7 +215,8 @@ namespace Managing.Infrastructure.Evm.Services
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<SwapInfos> SendTokenAsync(string senderAddress, string recipientAddress, Ticker ticker, decimal amount, int? chainId = null)
|
public async Task<SwapInfos> SendTokenAsync(string senderAddress, string recipientAddress, Ticker ticker,
|
||||||
|
decimal amount, int? chainId = null)
|
||||||
{
|
{
|
||||||
var payload = new
|
var payload = new
|
||||||
{
|
{
|
||||||
@@ -243,6 +246,30 @@ namespace Managing.Infrastructure.Evm.Services
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<List<Balance>> GetWalletBalanceAsync(string address, Ticker[] assets, string[] chains)
|
||||||
|
{
|
||||||
|
var payload = new
|
||||||
|
{
|
||||||
|
address,
|
||||||
|
asset = assets,
|
||||||
|
chain = chains
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await GetPrivyServiceAsync<Web3ProxyBalanceResponse>("/wallet-balance", payload);
|
||||||
|
|
||||||
|
if (response == null)
|
||||||
|
{
|
||||||
|
throw new Web3ProxyException("Wallet balance response is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.Success)
|
||||||
|
{
|
||||||
|
throw new Web3ProxyException($"Wallet balance request failed: {response.Error}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Balances ?? new List<Balance>();
|
||||||
|
}
|
||||||
|
|
||||||
private async Task HandleErrorResponse(HttpResponseMessage response)
|
private async Task HandleErrorResponse(HttpResponseMessage response)
|
||||||
{
|
{
|
||||||
var statusCode = (int)response.StatusCode;
|
var statusCode = (int)response.StatusCode;
|
||||||
@@ -303,20 +330,42 @@ namespace Managing.Infrastructure.Evm.Services
|
|||||||
var value = prop.GetValue(payload);
|
var value = prop.GetValue(payload);
|
||||||
if (value != null)
|
if (value != null)
|
||||||
{
|
{
|
||||||
if (!isFirst)
|
|
||||||
{
|
|
||||||
queryString.Append("&");
|
|
||||||
}
|
|
||||||
|
|
||||||
var paramName = prop.Name;
|
var paramName = prop.Name;
|
||||||
// Apply camelCase to match JSON property naming
|
// Apply camelCase to match JSON property naming
|
||||||
paramName = char.ToLowerInvariant(paramName[0]) + paramName.Substring(1);
|
paramName = char.ToLowerInvariant(paramName[0]) + paramName.Substring(1);
|
||||||
|
|
||||||
queryString.Append(HttpUtility.UrlEncode(paramName));
|
// Check if the value is an array or enumerable (but not string)
|
||||||
queryString.Append("=");
|
if (value is IEnumerable enumerable && !(value is string))
|
||||||
queryString.Append(HttpUtility.UrlEncode(value.ToString()));
|
{
|
||||||
|
// Handle arrays by creating multiple query parameters with the same name
|
||||||
|
foreach (var item in enumerable)
|
||||||
|
{
|
||||||
|
if (!isFirst)
|
||||||
|
{
|
||||||
|
queryString.Append("&");
|
||||||
|
}
|
||||||
|
|
||||||
isFirst = false;
|
queryString.Append(HttpUtility.UrlEncode(paramName));
|
||||||
|
queryString.Append("=");
|
||||||
|
queryString.Append(HttpUtility.UrlEncode(item?.ToString() ?? ""));
|
||||||
|
|
||||||
|
isFirst = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Handle single values
|
||||||
|
if (!isFirst)
|
||||||
|
{
|
||||||
|
queryString.Append("&");
|
||||||
|
}
|
||||||
|
|
||||||
|
queryString.Append(HttpUtility.UrlEncode(paramName));
|
||||||
|
queryString.Append("=");
|
||||||
|
queryString.Append(HttpUtility.UrlEncode(value.ToString()));
|
||||||
|
|
||||||
|
isFirst = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user