diff --git a/src/Managing.Api/Program.cs b/src/Managing.Api/Program.cs index d775f74..9b92f34 100644 --- a/src/Managing.Api/Program.cs +++ b/src/Managing.Api/Program.cs @@ -1,7 +1,9 @@ using System.Text; using System.Text.Json.Serialization; +using HealthChecks.UI.Client; using Managing.Api.Authorization; using Managing.Api.Filters; +using Managing.Api.HealthChecks; using Managing.Api.Workers; using Managing.Application.Hubs; using Managing.Bootstrap; @@ -11,6 +13,8 @@ using Managing.Infrastructure.Databases.InfluxDb.Models; using Managing.Infrastructure.Databases.MongoDb.Configurations; using Managing.Infrastructure.Evm.Models.Privy; using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using NSwag; @@ -18,15 +22,8 @@ using NSwag.Generation.Processors.Security; using Serilog; using Serilog.Events; using Serilog.Sinks.Elasticsearch; -using Microsoft.Extensions.ServiceDiscovery; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Diagnostics.HealthChecks; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Hosting; -using HealthChecks.UI.Client; using OpenApiSecurityRequirement = Microsoft.OpenApi.Models.OpenApiSecurityRequirement; using OpenApiSecurityScheme = NSwag.OpenApiSecurityScheme; -using Sentry; // Builder var builder = WebApplication.CreateBuilder(args); @@ -69,17 +66,35 @@ SentrySdk.Init(options => // Add Service Defaults - using extension methods directly builder.Services.AddServiceDiscovery(); builder.Services.AddHealthChecks() - .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + .AddCheck("self", () => HealthCheckResult.Healthy(), ["api"]); var mongoConnectionString = builder.Configuration.GetSection(Constants.Databases.MongoDb)["ConnectionString"]; var influxUrl = builder.Configuration.GetSection(Constants.Databases.InfluxDb)["Url"]; var web3ProxyUrl = builder.Configuration.GetSection("Web3Proxy")["BaseUrl"]; +// Add HTTP client for Web3Proxy health check with detailed response +builder.Services.AddHttpClient("Web3ProxyHealthCheck") + .ConfigureHttpClient(client => { + client.Timeout = TimeSpan.FromSeconds(15); + }); + +// Add HTTP client for GMX API health check +builder.Services.AddHttpClient("GmxHealthCheck") + .ConfigureHttpClient(client => { + client.Timeout = TimeSpan.FromSeconds(10); + }); + +// Register Web3ProxyHealthCheck with the web3ProxyUrl +builder.Services.AddSingleton(sp => + new Web3ProxyHealthCheck(sp.GetRequiredService(), web3ProxyUrl)); + // Add specific health checks for databases and other services builder.Services.AddHealthChecks() .AddMongoDb(mongoConnectionString, name: "mongodb", tags: ["database"]) .AddUrlGroup(new Uri($"{influxUrl}/health"), name: "influxdb", tags: ["database"]) - .AddUrlGroup(new Uri($"{web3ProxyUrl}/health"), name: "web3proxy", tags: ["api"]); + .AddCheck("web3proxy", tags: ["api", "external"]) + .AddCheck("candle-data", tags: ["database", "candles"]) + .AddCheck("gmx-connectivity", tags: ["api", "external"]); builder.Host.UseSerilog((hostBuilder, loggerConfiguration) => { @@ -185,7 +200,7 @@ builder.Services.AddSwaggerGen(options => }); builder.WebHost.SetupDiscordBot(); -// builder.Services.AddHostedService(); +builder.Services.AddHostedService(); // App var app = builder.Build(); @@ -238,6 +253,24 @@ app.UseEndpoints(endpoints => Predicate = r => r.Tags.Contains("live"), ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse }); + + endpoints.MapHealthChecks("/health/candles", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("candles"), + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + + endpoints.MapHealthChecks("/health/gmx", new HealthCheckOptions + { + Predicate = r => r.Name == "gmx-connectivity", + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); + + endpoints.MapHealthChecks("/health/web3proxy", new HealthCheckOptions + { + Predicate = r => r.Name == "web3proxy", + ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse + }); }); app.Run(); \ No newline at end of file diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index 32ba51b..d995036 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -593,7 +593,6 @@ public class TradingBot : Bot, ITradingBot var lastPosition = Positions.LastOrDefault(p => p.IsFinished() && p.SignalIdentifier != signal.Identifier - && p.ProfitAndLoss.Realized < 0 && p.OriginDirection == signal.Direction); if (lastPosition == null) @@ -665,13 +664,9 @@ public class TradingBot : Bot, ITradingBot { if (Positions.Any(p => p.Identifier == position.Identifier)) { - var previousPosition = Positions.First(p => p.Identifier == position.Identifier); - var positionIndex = Positions.IndexOf(previousPosition); - position.SignalIdentifier = previousPosition.SignalIdentifier; - Positions[positionIndex] = position; - SetSignalStatus(position.SignalIdentifier, SignalStatus.Expired); + await SetPositionStatus(position.SignalIdentifier, PositionStatus.Finished); Logger.LogInformation( - $"Position {position.SignalIdentifier} type correctly close. Pnl on position : {position.ProfitAndLoss.Realized}"); + $"Position {position.SignalIdentifier} type correctly close. Pnl on position : {position.ProfitAndLoss?.Realized}"); } else { @@ -719,6 +714,7 @@ public class TradingBot : Bot, ITradingBot catch (Exception ex) { Logger.LogError(ex, "Error during cancelOrders"); + SentrySdk.CaptureException(ex); } } } diff --git a/src/Managing.Web3Proxy/src/plugins/custom/gmx.ts b/src/Managing.Web3Proxy/src/plugins/custom/gmx.ts index 3f7d50f..6178b1e 100644 --- a/src/Managing.Web3Proxy/src/plugins/custom/gmx.ts +++ b/src/Managing.Web3Proxy/src/plugins/custom/gmx.ts @@ -139,10 +139,6 @@ export const openGmxPositionImpl = async ( throw new Error("No markets or tokens info data"); } - console.log('price', price) - console.log('stopLossPrice', stopLossPrice) - console.log('takeProfitPrice', takeProfitPrice) - const marketInfo = getMarketInfoFromTicker(ticker, marketsInfoData); const collateralToken = getTokenDataFromTicker("USDC", tokensData); // Using USDC as collateral console.log('collateralToken', collateralToken)