using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; using PolyTraderSharp.Models; namespace PolyTrader.Modules.CopyTrading.Persistence.Ef { /// /// EF-Core-Kontext für die Entitäten des Copytrading-Moduls (gleiche MySQL-DB wie der /// Core, eigene Tabellen mit Präfix mod_copytrading_). /// public class CopyTradingDbContext : DbContext { public CopyTradingDbContext(DbContextOptions options) : base(options) { } public DbSet ClosedTrades => Set(); public DbSet Traders => Set(); public DbSet AccountSettings => Set(); public DbSet History => Set(); protected override void OnModelCreating(ModelBuilder b) { b.Ignore(); // reine UI-Anzeige-Klasse b.Entity(e => { e.ToTable("mod_copytrading_closed_trades"); e.HasKey(x => x.TradeId); e.Property(x => x.TradeId).ValueGeneratedNever(); e.Property(x => x.TokenId).HasMaxLength(120); e.Property(x => x.MarketSlug).HasMaxLength(300); e.Property(x => x.MarketQuestion).HasMaxLength(1000); e.Property(x => x.Outcome).HasMaxLength(200); e.Property(x => x.Side).HasMaxLength(10); e.Property(x => x.ExitReason).HasMaxLength(200); e.Property(x => x.EntryPrice).HasPrecision(18, 6); e.Property(x => x.ExitPrice).HasPrecision(18, 6); e.Property(x => x.Size).HasPrecision(18, 6); e.Property(x => x.RealizedPnl).HasPrecision(18, 6); e.Property(x => x.PnlPercent).HasPrecision(18, 6); e.Property(x => x.TotalFees).HasPrecision(18, 6); e.HasIndex(x => x.AccountId); e.HasIndex(x => x.TokenId); e.HasIndex(x => x.SourceTraderId); }); b.Entity(e => { e.ToTable("mod_copytrading_traders"); e.HasKey(x => x.Id); e.Property(x => x.Id).ValueGeneratedNever(); e.Property(x => x.WalletAddress).HasMaxLength(128); e.Property(x => x.DisplayName).HasMaxLength(200); e.Property(x => x.Category).HasMaxLength(64); e.Property(x => x.Description).HasMaxLength(1000); e.Property(x => x.Reasoning).HasMaxLength(1000); var comparer = new ValueComparer>( (a, c) => (a == null && c == null) || (a != null && c != null && a.SetEquals(c)), v => v.Aggregate(0, (h, i) => HashCode.Combine(h, i)), v => new HashSet(v)); e.Property(x => x.AssignedAccountIds) .HasConversion( v => JsonSerializer.Serialize(v, (JsonSerializerOptions?)null), v => string.IsNullOrEmpty(v) ? new HashSet() : (JsonSerializer.Deserialize>(v, (JsonSerializerOptions?)null) ?? new HashSet())) .HasColumnType("text"); e.Property(x => x.AssignedAccountIds).Metadata.SetValueComparer(comparer); }); b.Entity(e => { e.ToTable("mod_copytrading_account_settings"); e.HasKey(x => x.AccountId); e.Property(x => x.AccountId).ValueGeneratedNever(); e.Property(x => x.PerMarketLimit).HasPrecision(18, 6); e.Property(x => x.MaxPriceDifference).HasPrecision(18, 6); e.Property(x => x.MaxBuyPrice).HasPrecision(18, 6); e.Property(x => x.ProfitTarget).HasPrecision(18, 6); e.Property(x => x.PreRedeemLimit).HasPrecision(18, 6); e.Property(x => x.PerMasterLimit).HasPrecision(18, 6); e.Property(x => x.perMaxTime6h).HasPrecision(18, 6); e.Property(x => x.perMaxTime24h).HasPrecision(18, 6); e.Property(x => x.perMaxTime72h).HasPrecision(18, 6); e.Property(x => x.perMaxTimeNone).HasPrecision(18, 6); e.Property(x => x.SellFloorPct).HasPrecision(18, 6); e.Property(x => x.MaxSpreadPct).HasPrecision(18, 6); e.Property(x => x.MinSellRatioPct).HasPrecision(18, 6); }); b.Entity(e => { e.ToTable("mod_copytrading_mt_history"); e.HasKey(x => x.Id); e.Property(x => x.Id).HasMaxLength(64); e.Property(x => x.TokenId).HasMaxLength(120); e.Property(x => x.RealizedPnl).HasPrecision(18, 6); e.HasIndex(x => x.TraderId); e.HasIndex(x => x.ClosedAt); }); } } }