Fix Get agent balance

This commit is contained in:
2025-05-20 22:42:06 +07:00
parent e866ef3303
commit 2ee1322ba0
4 changed files with 59 additions and 25 deletions

View File

@@ -6,9 +6,10 @@ namespace Managing.Application.Abstractions.Services;
public interface IStatisticService
{
Task<IList<AgentBalanceHistory>> GetAgentBalances(string agentName, DateTime start, DateTime? end = null);
Task<AgentBalanceHistory> GetAgentBalances(string agentName, DateTime start, DateTime? end = null);
Task<(IList<AgentBalanceHistory> Agents, int TotalCount)> GetBestAgents(DateTime start, DateTime? end = null, int page = 1,
Task<(IList<AgentBalanceHistory> Agents, int TotalCount)> GetBestAgents(DateTime start, DateTime? end = null,
int page = 1,
int pageSize = 10);
List<Trader> GetBadTraders();

View File

@@ -378,14 +378,14 @@ public class StatisticService : IStatisticService
await _messengerService.SendBadTraders(lastBadTrader);
}
public async Task<IList<AgentBalanceHistory>> GetAgentBalances(string agentName, DateTime start,
public async Task<AgentBalanceHistory> GetAgentBalances(string agentName, DateTime start,
DateTime? end = null)
{
var effectiveEnd = end ?? DateTime.UtcNow;
string cacheKey = $"AgentBalances_{agentName}_{start:yyyyMMdd}_{effectiveEnd:yyyyMMdd}";
// Check if the balances are already cached
var cachedBalances = _cacheService.GetValue<IList<AgentBalanceHistory>>(cacheKey);
var cachedBalances = _cacheService.GetValue<AgentBalanceHistory>(cacheKey);
if (cachedBalances != null)
{
@@ -393,15 +393,12 @@ public class StatisticService : IStatisticService
}
var balances = await _agentBalanceRepository.GetAgentBalances(agentName, start, end);
// Create a single AgentBalanceHistory with all balances
var result = new List<AgentBalanceHistory>
var result = new AgentBalanceHistory
{
new AgentBalanceHistory
{
AgentName = agentName,
AgentBalances = balances.OrderBy(b => b.Time).ToList()
}
AgentName = agentName,
AgentBalances = balances.OrderBy(b => b.Time).ToList()
};
// Cache the results for 5 minutes
@@ -434,7 +431,8 @@ public class StatisticService : IStatisticService
}
// Get all agents with their balance history
var (fetchedAgents, fetchedTotalCount) = await _agentBalanceRepository.GetAllAgentBalancesWithHistory(start, end);
var (fetchedAgents, fetchedTotalCount) =
await _agentBalanceRepository.GetAllAgentBalancesWithHistory(start, end);
// Cache all results for 5 minutes
_cacheService.SaveValue(cacheKey, (fetchedAgents, fetchedTotalCount), TimeSpan.FromMinutes(5));

View File

@@ -49,7 +49,8 @@ public class AgentBalanceRepository : IAgentBalanceRepository
$"|> range(start: {start:s}Z" +
(end.HasValue ? $", stop: {end.Value:s}Z" : "") +
$") " +
$"|> filter(fn: (r) => r[\"agent_name\"] == \"{agentName}\")";
$"|> filter(fn: (r) => r[\"agent_name\"] == \"{agentName}\") " +
$"|> pivot(rowKey: [\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")";
var result = await query.QueryAsync<AgentBalanceDto>(flux, _influxDbRepository.Organization);

View File

@@ -14,6 +14,15 @@ export interface AgentBalanceWithBalances extends AgentBalanceHistory {
}>;
}
const FILTERS = [
{ label: '24H', value: '24H', days: 1 },
{ label: '3D', value: '3D', days: 3 },
{ label: '1W', value: '1W', days: 7 },
{ label: '1M', value: '1M', days: 30 },
{ label: '1Y', value: '1Y', days: 365 },
{ label: 'Total', value: 'Total', days: null },
]
function BestAgents() {
const { apiUrl } = useApiUrlStore()
const [data, setData] = useState<AgentBalanceWithBalances[]>([])
@@ -21,37 +30,52 @@ function BestAgents() {
const [page, setPage] = useState(1)
const [pageSize, setPageSize] = useState(10)
const [totalPages, setTotalPages] = useState(1)
const [expandedAgent, setExpandedAgent] = useState<string | null>(null)
const [selectedFilter, setSelectedFilter] = useState('Total')
useEffect(() => {
setIsLoading(true)
const client = new DataClient({}, apiUrl)
const now = new Date()
const startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 30)
// Calculate start date based on selected filter
const filterObj = FILTERS.find(f => f.value === selectedFilter)
let startDate: Date
if (filterObj?.days) {
// Use the filter's days value to calculate start date
startDate = new Date(now.getTime() - filterObj.days * 24 * 60 * 60 * 1000)
} else {
// For 'Total', fetch from a far past date (e.g., 5 years ago)
startDate = new Date(now.getFullYear() - 5, now.getMonth(), now.getDate())
}
client.data_GetBestAgents(startDate, now, page, pageSize).then((res: BestAgentsResponse) => {
setData(res.agents as AgentBalanceWithBalances[] ?? [])
setTotalPages(res.totalPages ?? 1)
console.log(res)
}).finally(() => setIsLoading(false))
}, [apiUrl, page, pageSize])
}, [apiUrl, page, pageSize, selectedFilter])
// Type guard for agentBalances
function hasAgentBalances(agent: AgentBalanceWithBalances): agent is Required<AgentBalanceWithBalances> {
return Array.isArray(agent.agentBalances) && agent.agentBalances.length > 0;
function filterBalancesByRange(agent: AgentBalanceWithBalances) {
if (!agent.agentBalances || selectedFilter === 'Total') return agent.agentBalances ?? []
const days = FILTERS.find(f => f.value === selectedFilter)?.days
if (!days) return agent.agentBalances ?? []
const now = new Date()
const cutoff = new Date(now.getTime() - days * 24 * 60 * 60 * 1000)
return agent.agentBalances.filter(b => b.time && new Date(b.time) >= cutoff)
}
// Get the latest balance for each agent
const latestBalances = data.map(agent => {
if (hasAgentBalances(agent)) {
const lastBalance = agent.agentBalances[agent.agentBalances.length - 1]
const filteredBalances = filterBalancesByRange(agent)
if (filteredBalances.length > 0) {
const lastBalance = filteredBalances[filteredBalances.length - 1]
return {
agentName: agent.agentName,
originalAgent: agent, // Store the original agent for row details
originalAgent: { ...agent, agentBalances: filteredBalances },
...lastBalance
}
}
// fallback: just agentName
return { agentName: agent.agentName, originalAgent: agent }
return { agentName: agent.agentName, originalAgent: { ...agent, agentBalances: filteredBalances } }
})
const columns = [
@@ -63,10 +87,20 @@ function BestAgents() {
{ Header: 'Last Update', accessor: 'time', Cell: ({ value }: any) => value ? new Date(value).toLocaleString() : '' },
]
return (
<div className="container mx-auto pt-6">
<GridTile title="Best Agents">
<div className="flex gap-2 mb-3">
{FILTERS.map(f => (
<button
key={f.value}
className={`px-2 py-0.5 text-xs rounded ${selectedFilter === f.value ? 'bg-primary text-primary-content' : 'bg-base-200'}`}
onClick={() => setSelectedFilter(f.value)}
>
{f.label}
</button>
))}
</div>
{isLoading ? (
<progress className="progress progress-primary w-56"></progress>
) : (