using System; using MongoDB.Driver; using PolyTraderSharp.Extensions; using System.Net.Http; using System.Threading.Channels; using System.Windows.Forms; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using PolyTrader.Core.Configuration; using PolyTrader.Core.DependencyInjection; using PolyTrader.Core.Streaming; using PolyTrader.Core.Modularity; using PolyTrader.Modules.CopyTrading; using PolyTrader.Modules.CopyTrading.Persistence; using PolyTraderSharp.Models; using PolyTraderSharp.Services; namespace PolyTraderSharp; internal static class Program { public static IHost? AppHost { get; private set; } [STAThread] private static void Main() { ApplicationConfiguration.Initialize(); var modules = new System.Collections.Generic.List { new CopyTradingModule() }; AppHost = Host.CreateDefaultBuilder().ConfigureServices(delegate(HostBuilderContext context, IServiceCollection services) { services.Configure(context.Configuration.GetSection(DatabaseOptions.SectionName)); services.AddSingleton((IServiceProvider sp) => { var dbOptions = sp.GetRequiredService>().Value; var client = new MongoClient(dbOptions.ConnectionString); return client.GetDatabase(dbOptions.DatabaseName); }); services.AddCorePersistence(); services.AddSingleton(); services.AddSingleton((IServiceProvider sp) => ServerSettings.Load("server_settings.xml")); services.AddSingleton(); services.AddSingleton(delegate(IServiceProvider sp) { TerminalLogger requiredService2 = sp.GetRequiredService(); var httpHandler = new SocketsHttpHandler { PooledConnectionLifetime = TimeSpan.FromMinutes(2), MaxConnectionsPerServer = 100 }; return new PolymarketApiService(requiredService2, new HttpClient(httpHandler) { DefaultRequestHeaders = { { "User-Agent", "py_clob_client" }, { "Accept", "*/*" } } }); }); services.AddSingleton(delegate(IServiceProvider sp) { TerminalLogger requiredService2 = sp.GetRequiredService(); var httpHandler = new SocketsHttpHandler { PooledConnectionLifetime = TimeSpan.FromMinutes(2), MaxConnectionsPerServer = 100 }; return new PolymarketClobClient(requiredService2, new HttpClient(httpHandler) { DefaultRequestHeaders = { { "User-Agent", "py_clob_client" }, { "Accept", "*/*" } } }); }); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); // MUSS als erster HostedService laufen: hydriert den State, bevor die // Trading-Services gegen einen leeren State anlaufen. services.AddHostedService(); // Module registrieren ihre eigenen Services/Channels/State selbst. foreach (var module in modules) { services.AddSingleton(module); module.RegisterServices(services, context.Configuration); } services.AddHostedService(); services.AddHostedService(); services.AddHostedService(); services.AddHostedService(); services.AddHostedService(); services.AddHostedService((IServiceProvider sp) => sp.GetRequiredService()); services.AddHostedService((IServiceProvider sp) => sp.GetRequiredService()); services.AddTransient(); services.AddSingleton(); services.AddTransient(); }).Build(); try { var db = AppHost.Services.GetRequiredService(); // Einmal-Bereinigung (Alt-Bug): entferne closed_trades mit ObjectId-_id. // Das _id muss die int-TradeId sein; fehlerhafte Auto-ObjectIds werden verworfen. // Läuft jetzt über die konfigurierte DB statt über einen hart codierten Client. try { var cleanupCol = db.GetCollection("closed_trades"); cleanupCol.DeleteMany(Builders.Filter.Type("_id", MongoDB.Bson.BsonType.ObjectId)); } catch { } var copyState = AppHost.Services.GetRequiredService(); var maxTradeDoc = db.GetCollection("closed_trades") .Find(Builders.Filter.Empty) .SortByDescending(d => d["_id"]) .Limit(1) .FirstOrDefault(); if (maxTradeDoc != null && maxTradeDoc.Contains("_id")) { copyState.TotalCopyTrades = maxTradeDoc["_id"].AsInt32; } } catch { } AppHost.Start(); // Shell-Views registrieren (Core-App-Views; Module folgen via module.RegisterUi). var uiHost = AppHost.Services.GetRequiredService(); var viewServices = AppHost.Services; uiHost.RegisterView(new PolyTrader.Core.Modularity.ModuleView { Id = "core.terminal", Title = "Terminal", Group = "Core", Order = 10, CreateForm = () => { var view = new PolyTraderSharp.Ui.Views.TerminalView(); view.Initialize(viewServices.GetRequiredService()); return view; } }); uiHost.RegisterView(new PolyTrader.Core.Modularity.ModuleView { Id = "core.settings", Title = "Server Settings", Group = "Core", Order = 20, CreateForm = () => { var view = new PolyTraderSharp.Ui.Views.SettingsView(); view.Initialize( viewServices.GetRequiredService(), viewServices.GetRequiredService(), viewServices.GetRequiredService(), viewServices.GetRequiredService(), viewServices.GetRequiredService()); return view; } }); uiHost.RegisterView(new PolyTrader.Core.Modularity.ModuleView { Id = "core.jobs", Title = "Server Jobs", Group = "Core", Order = 30, CreateForm = () => { var view = new PolyTraderSharp.Ui.Views.JobsView(); view.Initialize(viewServices.GetRequiredService()); return view; } }); uiHost.RegisterView(new PolyTrader.Core.Modularity.ModuleView { Id = "core.dashboard", Title = "Dashboard", Group = "Core", Order = 5, CreateForm = () => { var view = new PolyTraderSharp.Ui.Views.DashboardView(); view.Initialize( viewServices.GetRequiredService(), viewServices.GetRequiredService()); return view; } }); // Modul-UI registrieren (Module steuern ihre Views selbst bei). foreach (var module in modules) { module.RegisterUi(uiHost); } var launcher = AppHost.Services.GetRequiredService(); Application.Run(launcher); AppHost.StopAsync().GetAwaiter().GetResult(); } }