using Predictalytics.Domain.Entities; using Predictalytics.Domain.Enums; using Predictalytics.Domain.Interfaces; using Microsoft.EntityFrameworkCore; namespace Predictalytics.Infrastructure.Data.Repositories; public class TradeRepository : ITradeRepository { private readonly AppDbContext _db; public TradeRepository(AppDbContext db) => _db = db; public async Task GetByPlatformTradeIdAsync(PlatformType platform, string platformTradeId, CancellationToken ct = default) => await _db.Trades.FirstOrDefaultAsync(t => t.Platform == platform && t.PlatformTradeId == platformTradeId, ct); public async Task> GetByTraderIdAsync(int traderId, int skip = 0, int take = 50, CancellationToken ct = default) => await _db.Trades.Include(t => t.Trader).Where(t => t.TraderId == traderId) .OrderByDescending(t => t.ExecutedAt).Skip(skip).Take(take).ToListAsync(ct); public async Task> GetByDbMarketIdAsync(int dbMarketId, int skip = 0, int take = 50, CancellationToken ct = default) => await _db.Trades.Include(t => t.Trader).Where(t => t.DbMarketId == dbMarketId) .OrderByDescending(t => t.ExecutedAt).Skip(skip).Take(take).ToListAsync(ct); public async Task> GetByMarketIdAsync(string platformMarketId, int skip = 0, int take = 50, CancellationToken ct = default) => await _db.Trades.Include(t => t.Trader).Where(t => t.MarketId == platformMarketId) .OrderByDescending(t => t.ExecutedAt).Skip(skip).Take(take).ToListAsync(ct); public async Task> GetRecentAsync(int count = 50, PlatformType? platform = null, CancellationToken ct = default) { var q = _db.Trades.Include(t => t.Trader).AsQueryable(); if (platform.HasValue) q = q.Where(t => t.Platform == platform.Value); return await q.OrderByDescending(t => t.ExecutedAt).Take(count).ToListAsync(ct); } public async Task> GetLargestAsync(int count = 5, DateTime? since = null, CancellationToken ct = default) { var q = _db.Trades.Include(t => t.Trader).AsQueryable(); if (since.HasValue) q = q.Where(t => t.ExecutedAt >= since.Value); return await q.OrderByDescending(t => t.Amount).Take(count).ToListAsync(ct); } public async Task GetCountAsync(int? traderId = null, CancellationToken ct = default) { var q = _db.Trades.AsQueryable(); if (traderId.HasValue) q = q.Where(t => t.TraderId == traderId.Value); return await q.CountAsync(ct); } public async Task AddRangeAsync(IEnumerable trades, CancellationToken ct = default) { foreach (var t in trades) { t.Outcome = StringHelper.Truncate(t.Outcome, 128) ?? ""; t.PlatformTradeId = StringHelper.Truncate(t.PlatformTradeId, 256) ?? ""; t.MarketId = StringHelper.Truncate(t.MarketId, 66) ?? ""; t.AssetId = StringHelper.Truncate(t.AssetId, 80) ?? ""; if (t.TransactionHash != null) t.TransactionHash = StringHelper.Truncate(t.TransactionHash, 66); } try { _db.Trades.AddRange(trades); await _db.SaveChangesAsync(ct); } catch { foreach (var t in trades) { try { _db.Entry(t).State = EntityState.Detached; } catch { } } throw; } } public async Task GetTotalVolumeAsync(DateTime? since = null, CancellationToken ct = default) { var q = _db.Trades.AsQueryable(); if (since.HasValue) q = q.Where(t => t.ExecutedAt >= since.Value); return await q.SumAsync(t => t.Amount, ct); } public async Task> GetOrphanedTradesAsync(int limit, CancellationToken ct = default) { return await _db.Trades .Where(t => t.MarketOutcomeId == null && !string.IsNullOrEmpty(t.AssetId)) .OrderByDescending(t => t.ExecutedAt) .Take(limit) .ToListAsync(ct); } public async Task> GetKnownPlatformTradeIdsAsync(PlatformType platform, int traderId, IEnumerable platformTradeIds, CancellationToken ct = default) { var idList = platformTradeIds.ToList(); if (idList.Count == 0) return new HashSet(); var ids = await _db.Trades .Where(t => t.Platform == platform && t.TraderId == traderId && idList.Contains(t.PlatformTradeId)) .Select(t => t.PlatformTradeId) .ToListAsync(ct); return new HashSet(ids); } public async Task UpdateAsync(Trade trade, CancellationToken ct = default) { trade.Outcome = StringHelper.Truncate(trade.Outcome, 128) ?? ""; trade.PlatformTradeId = StringHelper.Truncate(trade.PlatformTradeId, 256) ?? ""; trade.MarketId = StringHelper.Truncate(trade.MarketId, 66) ?? ""; trade.AssetId = StringHelper.Truncate(trade.AssetId, 80) ?? ""; _db.Trades.Update(trade); await _db.SaveChangesAsync(ct); } }