From c22c92508764a17cae7cfd34fe1dd2c1637d002b Mon Sep 17 00:00:00 2001 From: cryptooda Date: Thu, 24 Apr 2025 19:46:21 +0700 Subject: [PATCH] Add user to position + fix few things --- src/.DS_Store | Bin 14340 -> 12292 bytes src/Managing.Api.Workers/Program.cs | 18 +- .../Workers/PositionManagerWorker.cs | 289 +++++++++++------- .../Controllers/TradingController.cs | 3 +- .../PositionTests.cs | 9 +- .../ProfitAndLossTests.cs | 64 ++-- src/Managing.Application/Bots/TradingBot.cs | 21 +- .../Trading/Commands/OpenPositionRequest.cs | 13 +- .../Trading/OpenPositionCommandHandler.cs | 15 +- .../Workflows/Flows/Trading/OpenPosition.cs | 57 ++-- src/Managing.Domain/Trades/Position.cs | 43 ++- .../MongoDb/MongoMappers.cs | 8 +- .../Discord/DiscordCommands.cs | 3 +- .../Discord/DiscordService.cs | 1 + .../Services/Gmx/GmxV2Mappers.cs | 12 +- .../Services/Web3ProxyService.cs | 37 +-- .../gmxsdk/modules/orders/helpers.ts | 2 +- 17 files changed, 357 insertions(+), 238 deletions(-) diff --git a/src/.DS_Store b/src/.DS_Store index 056bab422f6d27eb79d94bb7206e1e81236f9295..7671fdcb5b89580a070018a19097c4f909319e57 100644 GIT binary patch delta 203 zcmZoEXh~3DU|?W$DortDV9)?EIe-{M3-ADmb_NCo?uiQej206EoF`9KmzexgU2Wq< zD}GiPpse`hh2p}Sl{H>4ZqC#)XPh`eT-A@En4z2@ks;kPCqFqUCqD^f5(5KMIs*f< z-G4A(V3;_;cH%_&%{l_y+?#!6)EF71H}fbQVxO!aVj;!A3e*7v8r(p_71EVuvw delta 306 zcmZokXem%&U|?W$DortDU@!nOIe-{M3-ADmb_NCoo{0+jjMftaoF_L5TQNFrJZH<# zC^ETDSYh)mVQy|yRt7(YVuo^tM22+Foc!dZoctt^ZlIYz85o%D{(}KfgnXt! z4U@0RxQil*l?4~&<>cq3Gcas^Ag9f^S%Gl|6QkN@9)&~flO@!}Cob2TtgR-pSy|u( zBd;$*K0_WuI*@c>NSYj_X1w{WU?}6{hq9iNFUfe}H+2e=BrDiG3m~XG-ik! builder.WebHost.SetupDiscordBot(); // builder.Services.AddHostedService(); -// builder.Services.AddHostedService(); +builder.Services.AddHostedService(); // builder.Services.AddHostedService(); // builder.Services.AddHostedService(); -builder.Services.AddHostedService(); -builder.Services.AddHostedService(); -builder.Services.AddHostedService(); -builder.Services.AddHostedService(); -// builder.Services.AddHostedService(); -// builder.Services.AddHostedService(); -builder.Services.AddHostedService(); -builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); +// // builder.Services.AddHostedService(); +// // builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); +// builder.Services.AddHostedService(); // App var app = builder.Build(); diff --git a/src/Managing.Api.Workers/Workers/PositionManagerWorker.cs b/src/Managing.Api.Workers/Workers/PositionManagerWorker.cs index da909ae..73085b0 100644 --- a/src/Managing.Api.Workers/Workers/PositionManagerWorker.cs +++ b/src/Managing.Api.Workers/Workers/PositionManagerWorker.cs @@ -3,6 +3,7 @@ using Managing.Application.Abstractions.Services; using Managing.Application.Workers; using Managing.Application.Workers.Abstractions; using Managing.Domain.Accounts; +using Managing.Domain.Shared.Helpers; using Managing.Domain.Trades; using Newtonsoft.Json; using static Managing.Common.Enums; @@ -58,51 +59,84 @@ public class PositionManagerWorker : BaseWorker position.Status = PositionStatus.Updating; _tradingService.UpdatePosition(position); - _logger.LogDebug("Processing risk orders for {Direction} position opened at {OpenDate}", + _logger.LogDebug("Verifying position on exchange for {Direction} position opened at {OpenDate}", position.OriginDirection, position.Date.ToString("o")); var account = await _accountService.GetAccount(position.AccountName, false, false); - var success = true; - - // Process and update trades - var updatedSl = await ProcessTrade(account, position.StopLoss, "SL", async () => - await _exchangeService.OpenStopLoss(account, position.Ticker, position.OriginDirection, - position.StopLoss.Price, position.StopLoss.Quantity, false, DateTime.UtcNow)); - if (updatedSl != null) - { - position.StopLoss = updatedSl; - success &= updatedSl.Status.IsActive(); - } - - var updatedTp1 = await ProcessTrade(account, position.TakeProfit1, "TP1", async () => - await _exchangeService.OpenTakeProfit(account, position.Ticker, position.OriginDirection, - position.TakeProfit1.Price, position.TakeProfit1.Quantity, false, DateTime.UtcNow)); + // Get positions directly from broker + var brokerPositions = await _exchangeService.GetBrokerPositions(account); + var exchangePosition = brokerPositions.FirstOrDefault(p => + p.Ticker == position.Ticker && + p.OriginDirection == position.OriginDirection); - if (updatedTp1 != null) + if (exchangePosition == null) { - position.TakeProfit1 = updatedTp1; - success &= updatedTp1.Status.IsActive(); + _logger.LogWarning("Position not found on exchange - marking as canceled"); + position.Status = PositionStatus.Canceled; + _tradingService.UpdatePosition(position); + continue; } - - Trade? updatedTp2 = null; - if (position.TakeProfit2 != null) + + // Update with exchange data if available + if (exchangePosition.StopLoss != null) { - updatedTp2 = await ProcessTrade(account, position.TakeProfit2, "TP2", async () => - await _exchangeService.OpenTakeProfit(account, position.Ticker, position.OriginDirection, - position.TakeProfit2.Price, position.TakeProfit2.Quantity, false, DateTime.UtcNow)); + _logger.LogInformation("Stop Loss found on exchange - ID: {OrderId}", exchangePosition.StopLoss.ExchangeOrderId); + position.StopLoss = exchangePosition.StopLoss; + } + else + { + _logger.LogWarning("Stop Loss not found on exchange - creating new SL order"); + var updatedSl = await _exchangeService.OpenStopLoss(account, position.Ticker, position.OriginDirection, + position.StopLoss.Price, position.StopLoss.Quantity, false, DateTime.UtcNow); - if (updatedTp2 != null) + if (updatedSl != null) { - position.TakeProfit2 = updatedTp2; - success &= updatedTp2.Status.IsActive() || updatedTp2.Status == TradeStatus.Cancelled; + position.StopLoss = updatedSl; } } - // Update position status based on trade states - position.Status = success && AllTradesActive(position) - ? PositionStatus.Filled - : PositionStatus.PartiallyFilled; + if (exchangePosition.TakeProfit1 != null) + { + _logger.LogInformation("Take Profit found on exchange - ID: {OrderId}", exchangePosition.TakeProfit1.ExchangeOrderId); + position.TakeProfit1 = exchangePosition.TakeProfit1; + } + else + { + _logger.LogWarning("Take Profit not found on exchange - creating new TP order"); + var updatedTp1 = await _exchangeService.OpenTakeProfit(account, position.Ticker, position.OriginDirection, + position.TakeProfit1.Price, position.TakeProfit1.Quantity, false, DateTime.UtcNow); + + if (updatedTp1 != null) + { + position.TakeProfit1 = updatedTp1; + } + } + + // Handle TP2 if it exists + if (position.TakeProfit2 != null) + { + if (exchangePosition.TakeProfit2 != null) + { + _logger.LogInformation("Take Profit 2 found on exchange - ID: {OrderId}", exchangePosition.TakeProfit2.ExchangeOrderId); + position.TakeProfit2 = exchangePosition.TakeProfit2; + } + else + { + _logger.LogWarning("Take Profit 2 not found on exchange - creating new TP2 order"); + var updatedTp2 = await _exchangeService.OpenTakeProfit(account, position.Ticker, position.OriginDirection, + position.TakeProfit2.Price, position.TakeProfit2.Quantity, false, DateTime.UtcNow); + + if (updatedTp2 != null) + { + position.TakeProfit2 = updatedTp2; + } + } + } + + // Update position status based on verification results + var success = AllTradesActive(position); + position.Status = success ? PositionStatus.Filled : PositionStatus.PartiallyFilled; _logger.LogInformation("Final position status: {Status}", position.Status); } @@ -119,52 +153,13 @@ public class PositionManagerWorker : BaseWorker } } - private async Task ProcessTrade(Account account, Trade trade, string tradeType, Func> createTrade) - { - try - { - // 1. Check existing status on exchange - var exchangeTrade = await _exchangeService.GetTrade(account, trade.ExchangeOrderId, trade.Ticker); - if (exchangeTrade != null && exchangeTrade.Status.IsActive()) - { - _logger.LogInformation("{TradeType} already exists on exchange - Status: {Status}", - tradeType, exchangeTrade.Status); - return exchangeTrade; - } - - // 2. Only create new order if in pending state - if (trade.Status != TradeStatus.PendingOpen) - { - _logger.LogWarning("{TradeType} creation skipped - Invalid status: {Status}", - tradeType, trade.Status); - return null; - } - - // 3. Create new order - var newTrade = await createTrade(); - if (newTrade?.Status == TradeStatus.Requested) - { - _logger.LogInformation("{TradeType} successfully created - ExchangeID: {ExchangeOrderId}", - tradeType, newTrade.ExchangeOrderId); - return newTrade; - } - - _logger.LogError("{TradeType} creation failed - Null response or invalid status", tradeType); - return null; - } - catch (Exception ex) - { - _logger.LogError(ex, "{TradeType} processing failed", tradeType); - return null; - } - } - private bool AllTradesActive(Position position) { return position.StopLoss.Status.IsActive() && position.TakeProfit1.Status.IsActive() && (position.TakeProfit2?.Status.IsActive() ?? true); } + private async Task ManageFilledPositions() { var positions = GetPositions(PositionStatus.Filled); @@ -181,22 +176,98 @@ public class PositionManagerWorker : BaseWorker position.Status = PositionStatus.Updating; _tradingService.UpdatePosition(position); - _logger.LogInformation("Managing filled position - Direction: {Direction}, Open Since: {OpenDate}", + _logger.LogInformation("Checking position state on exchange - Direction: {Direction}, Open Since: {OpenDate}", position.OriginDirection, position.Date.ToString("yyyy-MM-dd HH:mm:ss")); var account = await GetAccount(position.AccountName); - // Perform position management - var updatedPosition = await _tradingService.ManagePosition(account, position); + // Check if position still exists on broker + var brokerPositions = await _exchangeService.GetBrokerPositions(account); + var exchangePosition = brokerPositions.FirstOrDefault(p => + p.Ticker == position.Ticker && + p.OriginDirection == position.OriginDirection); - // Log status changes if they occurred - if (updatedPosition.Status != position.Status) + if (exchangePosition == null) { - _logger.LogInformation("Position status updated: {OldStatus} → {NewStatus}", - position.Status, updatedPosition.Status); + // Position no longer on exchange - it has been closed + _logger.LogInformation("Position no longer on exchange - marking as finished"); + position.Status = PositionStatus.Finished; + + // Determine if SL or TP was hit by checking which one is missing + if (exchangePosition?.StopLoss == null && position.StopLoss.Status != TradeStatus.Filled) + { + _logger.LogInformation("Stop loss appears to have been hit"); + position.StopLoss.SetStatus(TradeStatus.Filled); + position.ProfitAndLoss = TradingBox.GetProfitAndLoss( + position, + position.StopLoss.Quantity, + position.StopLoss.Price, + position.Open.Leverage); + } + else if (exchangePosition?.TakeProfit1 == null && position.TakeProfit1.Status != TradeStatus.Filled) + { + _logger.LogInformation("Take profit 1 appears to have been hit"); + position.TakeProfit1.SetStatus(TradeStatus.Filled); + position.ProfitAndLoss = TradingBox.GetProfitAndLoss( + position, + position.TakeProfit1.Quantity, + position.TakeProfit1.Price, + position.Open.Leverage); + } + else if (exchangePosition?.TakeProfit2 == null && position.TakeProfit2?.Status != TradeStatus.Filled) + { + _logger.LogInformation("Take profit 2 appears to have been hit"); + position.TakeProfit2.SetStatus(TradeStatus.Filled); + position.ProfitAndLoss = TradingBox.GetProfitAndLoss( + position, + position.TakeProfit2.Quantity, + position.TakeProfit2.Price, + position.Open.Leverage); + } + + // Cancel any remaining orders + await _exchangeService.CancelOrder(account, position.Ticker); + } + else + { + // Position still exists - update with exchange data + _logger.LogInformation("Position still active on exchange with quantity {Quantity}", + exchangePosition.Open?.Quantity ?? 0); + + // Update our position with broker data + if (exchangePosition.Open != null) + position.Open = exchangePosition.Open; + + if (exchangePosition.StopLoss != null) + position.StopLoss = exchangePosition.StopLoss; + + if (exchangePosition.TakeProfit1 != null) + position.TakeProfit1 = exchangePosition.TakeProfit1; + + if (exchangePosition.TakeProfit2 != null) + position.TakeProfit2 = exchangePosition.TakeProfit2; + + if (exchangePosition.ProfitAndLoss != null) + position.ProfitAndLoss = exchangePosition.ProfitAndLoss; + else + { + // Calculate PNL if not provided + var lastPrice = _exchangeService.GetPrice(account, position.Ticker, DateTime.UtcNow); + position.ProfitAndLoss = TradingBox.GetProfitAndLoss( + position, + position.Open.Quantity, + lastPrice, + position.Open.Leverage); + } + + _logger.LogInformation("Updated position from exchange - PNL: {PNL}", + position.ProfitAndLoss?.Net ?? 0); + + // Keep status as Filled + position.Status = PositionStatus.Filled; } - _tradingService.UpdatePosition(updatedPosition); + _tradingService.UpdatePosition(position); } catch (Exception ex) { @@ -243,45 +314,47 @@ public class PositionManagerWorker : BaseWorker _tradingService.UpdatePosition(position); var account = await GetAccount(position.AccountName); - var trade = await _exchangeService.GetTrade(account.Key, position.Open.ExchangeOrderId, position.Ticker); - var openTrade = position.Open; - - if (trade.Status == TradeStatus.PendingOpen || trade.Status == TradeStatus.Requested) + + // Check if position exists on broker + var brokerPositions = await _exchangeService.GetBrokerPositions(account); + var exchangePosition = brokerPositions.FirstOrDefault(p => + p.Ticker == position.Ticker && + p.OriginDirection == position.OriginDirection); + + if (exchangePosition != null) { - // Position staleness check - if (position.Date < DateTime.UtcNow.AddDays(-1)) - { - position.Status = PositionStatus.Canceled; - _tradingService.UpdatePosition(position); - _logger.LogWarning("[{Identifier}] Position canceled - stale since {PositionAge} days", - position.Identifier, - (DateTime.UtcNow - position.Date).TotalDays); - } - else - { - // Reset status for retry - position.Status = PositionStatus.New; - _tradingService.UpdatePosition(position); - _logger.LogInformation("[{Identifier}] Awaiting order fill - {Ticker} (0/{ExpectedQuantity})", - position.Identifier, - position.Ticker, openTrade.Quantity); - } + // Position is confirmed on exchange + position.Status = PositionStatus.PartiallyFilled; + position.Open = exchangePosition.Open; // Use the exchange data + _tradingService.UpdatePosition(position); + + _logger.LogInformation("[{Identifier}] Position found on exchange - moving to partially filled status", + position.Identifier); + continue; + } + + // Position not found on exchange - check for staleness + if (position.Date < DateTime.UtcNow.AddDays(-1)) + { + position.Status = PositionStatus.Canceled; + _tradingService.UpdatePosition(position); + _logger.LogWarning("[{Identifier}] Position canceled - stale since {PositionAge} days", + position.Identifier, + (DateTime.UtcNow - position.Date).TotalDays); } else { - position.Status = PositionStatus.PartiallyFilled; - position.Open = openTrade; - // Position is now open, now waiting to open SLTP + // Reset status to try again + position.Status = PositionStatus.New; _tradingService.UpdatePosition(position); - - _logger.LogInformation("[{Identifier}] Position now open ", + _logger.LogInformation("[{Identifier}] Position not yet found on exchange - awaiting fill", position.Identifier); } } catch (Exception ex) { _logger.LogError(ex, "Error processing position {Identifier}", position.Identifier); - // Consider resetting to New status for retry if needed + // Reset to New status for retry position.Status = PositionStatus.New; _tradingService.UpdatePosition(position); } diff --git a/src/Managing.Api/Controllers/TradingController.cs b/src/Managing.Api/Controllers/TradingController.cs index 8176cce..617c7af 100644 --- a/src/Managing.Api/Controllers/TradingController.cs +++ b/src/Managing.Api/Controllers/TradingController.cs @@ -136,9 +136,9 @@ public class TradingController : BaseController nameof(moneyManagementName)); } + var user = await GetUser(); if (moneyManagement != null) { - var user = await GetUser(); moneyManagement = await _moneyManagementService.GetMoneyMangement(user, moneyManagementName); } @@ -149,6 +149,7 @@ public class TradingController : BaseController ticker, PositionInitiator.User, DateTime.UtcNow, + user, isForPaperTrading: isForPaperTrading, price: openPrice); var result = await _openTradeCommandHandler.Handle(command); diff --git a/src/Managing.Application.Tests/PositionTests.cs b/src/Managing.Application.Tests/PositionTests.cs index d872a97..2445c98 100644 --- a/src/Managing.Application.Tests/PositionTests.cs +++ b/src/Managing.Application.Tests/PositionTests.cs @@ -1,6 +1,7 @@ using Managing.Application.Trading; using Managing.Application.Trading.Commands; using Managing.Domain.Trades; +using Managing.Domain.Users; using Moq; using Xunit; using static Managing.Common.Enums; @@ -23,7 +24,9 @@ public class PositionTests : BaseTests Ticker.BTC, PositionInitiator.User, DateTime.UtcNow, - isForPaperTrading: false); + _account.User, + isForPaperTrading: false, + signalIdentifier: new Guid().ToString()); var handler = new OpenPositionCommandHandler( _exchangeService, _accountService.Object, @@ -41,8 +44,8 @@ public class PositionTests : BaseTests // _ = new GetAccountPositioqwnInfoListOutputDTO().DecodeOutput(hexPositions).d // var openTrade = await _exchangeService.GetTrade(_account, "", Ticker.BTC); - var position = new Position("", TradeDirection.Long, Ticker.BTC, MoneyManagement, PositionInitiator.User, - DateTime.UtcNow) + var position = new Position("", "", TradeDirection.Long, Ticker.BTC, MoneyManagement, PositionInitiator.User, + DateTime.UtcNow, new User()) { Open = openTrade }; diff --git a/src/Managing.Application.Tests/ProfitAndLossTests.cs b/src/Managing.Application.Tests/ProfitAndLossTests.cs index 11752d2..0733bb2 100644 --- a/src/Managing.Application.Tests/ProfitAndLossTests.cs +++ b/src/Managing.Application.Tests/ProfitAndLossTests.cs @@ -1,4 +1,5 @@ using Managing.Domain.Trades; +using Managing.Domain.Users; using Xunit; using static Managing.Common.Enums; @@ -9,7 +10,8 @@ namespace Managing.Application.Tests [Theory] [InlineData(1, 100, 110, 10)] [InlineData(2, 100, 110, 20)] - public void Should_Return_Correct_ProfitAndLoss_Amount(decimal quantity, decimal price, decimal exitPrice, decimal expectedResult) + public void Should_Return_Correct_ProfitAndLoss_Amount(decimal quantity, decimal price, decimal exitPrice, + decimal expectedResult) { // Arrange var init = new List>(); @@ -42,7 +44,8 @@ namespace Managing.Application.Tests position.ProfitAndLoss = new ProfitAndLoss(orders, position.OriginDirection); // Trigger Stop Loss - position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.StopLoss.Price, position.OriginDirection); + position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.StopLoss.Price, + position.OriginDirection); // Assert Assert.Equal(20, position.ProfitAndLoss.Realized); @@ -65,7 +68,8 @@ namespace Managing.Application.Tests position.ProfitAndLoss = new ProfitAndLoss(orders, position.OriginDirection); // Trigger Stop Loss - position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.StopLoss.Price, position.OriginDirection); + position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.StopLoss.Price, + position.OriginDirection); // Assert Assert.Equal(3.97005582759999752M, position.ProfitAndLoss.Realized); @@ -127,8 +131,10 @@ namespace Managing.Application.Tests // Act position.ProfitAndLoss = new ProfitAndLoss(orders, position.OriginDirection); - position.ProfitAndLoss.AddFill(-position.TakeProfit1.Quantity, position.TakeProfit1.Price, TradeDirection.Short); - position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.StopLoss.Price, TradeDirection.Short); + position.ProfitAndLoss.AddFill(-position.TakeProfit1.Quantity, position.TakeProfit1.Price, + TradeDirection.Short); + position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.StopLoss.Price, + TradeDirection.Short); // Assert Assert.Equal(20, position.ProfitAndLoss.Realized); @@ -151,7 +157,8 @@ namespace Managing.Application.Tests position.ProfitAndLoss = new ProfitAndLoss(orders, position.OriginDirection); // Trigger Stop Loss - position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.TakeProfit2.Price, TradeDirection.Short); + position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.TakeProfit2.Price, + TradeDirection.Short); // Assert Assert.Equal(120, position.ProfitAndLoss.Realized); @@ -174,7 +181,8 @@ namespace Managing.Application.Tests position.ProfitAndLoss = new ProfitAndLoss(orders, position.OriginDirection); // Trigger Stop Loss - position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.StopLoss.Price, TradeDirection.Long); + position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.StopLoss.Price, + TradeDirection.Long); // Assert Assert.Equal(20, position.ProfitAndLoss.Realized); @@ -197,7 +205,8 @@ namespace Managing.Application.Tests position.ProfitAndLoss = new ProfitAndLoss(orders, position.OriginDirection); // Trigger Stop Loss - position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.TakeProfit2.Price, TradeDirection.Long); + position.ProfitAndLoss.AddFill(-position.TakeProfit2.Quantity, position.TakeProfit2.Price, + TradeDirection.Long); // Assert Assert.Equal(120, position.ProfitAndLoss.Realized); @@ -205,47 +214,54 @@ namespace Managing.Application.Tests private static Position GetFakeShortPosition() { - return new Position("FakeAccount", TradeDirection.Short, Ticker.BTC, null, PositionInitiator.PaperTrading, DateTime.UtcNow) + return new Position("", "FakeAccount", TradeDirection.Short, Ticker.BTC, null, + PositionInitiator.PaperTrading, DateTime.UtcNow, new User()) { Open = new Trade(DateTime.Now, TradeDirection.Short, TradeStatus.Filled, - TradeType.Market, Ticker.ADA, 10, 100, 1, "OpenOrderId", ""), + TradeType.Market, Ticker.ADA, 10, 100, 1, "OpenOrderId", ""), StopLoss = new Trade(DateTime.Now, TradeDirection.Long, TradeStatus.PendingOpen, - TradeType.StopMarket, Ticker.ADA, 10, 110, 1, "StopLossOrderId", ""), + TradeType.StopMarket, Ticker.ADA, 10, 110, 1, "StopLossOrderId", ""), TakeProfit1 = new Trade(DateTime.Now, TradeDirection.Long, TradeStatus.PendingOpen, - TradeType.TakeProfitLimit, Ticker.ADA, 6, 90, 1, "TakeProfit1OrderId", ""), + TradeType.TakeProfitLimit, Ticker.ADA, 6, 90, 1, "TakeProfit1OrderId", ""), TakeProfit2 = new Trade(DateTime.Now, TradeDirection.Long, TradeStatus.PendingOpen, - TradeType.TakeProfitLimit, Ticker.ADA, 4, 85, 1, "TakeProfit1OrderId", "") + TradeType.TakeProfitLimit, Ticker.ADA, 4, 85, 1, "TakeProfit1OrderId", "") }; } private static Position GetSolanaLongPosition() { - return new Position("FakeAccount", TradeDirection.Long, Ticker.BTC, null, PositionInitiator.PaperTrading, DateTime.UtcNow) + return new Position("", "FakeAccount", TradeDirection.Long, Ticker.BTC, null, + PositionInitiator.PaperTrading, DateTime.UtcNow, new User()) { Open = new Trade(DateTime.Now, TradeDirection.Long, TradeStatus.Filled, - TradeType.Market, Ticker.ADA, (decimal)6.0800904000245037980887037491, (decimal)81.6200, 1, "OpenOrderId", ""), + TradeType.Market, Ticker.ADA, (decimal)6.0800904000245037980887037491, (decimal)81.6200, 1, + "OpenOrderId", ""), StopLoss = new Trade(DateTime.Now, TradeDirection.Short, TradeStatus.PendingOpen, - TradeType.StopMarket, Ticker.ADA, (decimal)3.6480542400147022788532222495, (decimal)79.987600, 1, "StopLossOrderId", ""), + TradeType.StopMarket, Ticker.ADA, (decimal)3.6480542400147022788532222495, (decimal)79.987600, 1, + "StopLossOrderId", ""), TakeProfit1 = new Trade(DateTime.Now, TradeDirection.Short, TradeStatus.PendingOpen, - TradeType.TakeProfitLimit, Ticker.ADA, (decimal)2.4320361600098015192354814996, (decimal)85.701000, 1, "TakeProfit1OrderId", ""), + TradeType.TakeProfitLimit, Ticker.ADA, (decimal)2.4320361600098015192354814996, (decimal)85.701000, + 1, "TakeProfit1OrderId", ""), TakeProfit2 = new Trade(DateTime.Now, TradeDirection.Short, TradeStatus.PendingOpen, - TradeType.TakeProfitLimit, Ticker.ADA, (decimal)3.6480542400147022788532222495, (decimal)89.782000, 1, "TakeProfit1OrderId", "") + TradeType.TakeProfitLimit, Ticker.ADA, (decimal)3.6480542400147022788532222495, (decimal)89.782000, + 1, "TakeProfit1OrderId", "") }; } private static Position GetFakeLongPosition() { - return new Position("FakeAccount", TradeDirection.Long, Ticker.BTC, null, PositionInitiator.PaperTrading, DateTime.UtcNow) + return new Position("", "FakeAccount", TradeDirection.Long, Ticker.BTC, null, + PositionInitiator.PaperTrading, DateTime.UtcNow, new User()) { Open = new Trade(DateTime.Now, TradeDirection.Short, TradeStatus.Filled, - TradeType.Market, Ticker.ADA, 10, 100, 1, "OpenOrderId", ""), + TradeType.Market, Ticker.ADA, 10, 100, 1, "OpenOrderId", ""), StopLoss = new Trade(DateTime.Now, TradeDirection.Long, TradeStatus.PendingOpen, - TradeType.StopMarket, Ticker.ADA, 10, 90, 1, "StopLossOrderId", ""), + TradeType.StopMarket, Ticker.ADA, 10, 90, 1, "StopLossOrderId", ""), TakeProfit1 = new Trade(DateTime.Now, TradeDirection.Long, TradeStatus.PendingOpen, - TradeType.TakeProfitLimit, Ticker.ADA, 6, 110, 1, "TakeProfit1OrderId", ""), + TradeType.TakeProfitLimit, Ticker.ADA, 6, 110, 1, "TakeProfit1OrderId", ""), TakeProfit2 = new Trade(DateTime.Now, TradeDirection.Long, TradeStatus.PendingOpen, - TradeType.TakeProfitLimit, Ticker.ADA, 4, 115, 1, "TakeProfit1OrderId", "") + TradeType.TakeProfitLimit, Ticker.ADA, 4, 115, 1, "TakeProfit1OrderId", "") }; } } -} +} \ No newline at end of file diff --git a/src/Managing.Application/Bots/TradingBot.cs b/src/Managing.Application/Bots/TradingBot.cs index df4cea8..f4e5b7e 100644 --- a/src/Managing.Application/Bots/TradingBot.cs +++ b/src/Managing.Application/Bots/TradingBot.cs @@ -331,7 +331,7 @@ public class TradingBot : Bot, ITradingBot : TradingService.GetPositionByIdentifier(positionForSignal.Identifier); var positionsExchange = IsForBacktest - ? new List{position} + ? new List { position } : await TradingService.GetBrokerPositions(Account); if (!IsForBacktest) @@ -344,11 +344,13 @@ public class TradingBot : Bot, ITradingBot var orders = await ExchangeService.GetOpenOrders(Account, Ticker); if (orders.Any()) { - await LogInformation($"Cannot update Position. Position is still waiting for opening. There is {orders.Count()} open orders."); + await LogInformation( + $"Cannot update Position. Position is still waiting for opening. There is {orders.Count()} open orders."); } else { - await LogWarning($"Cannot update Position. No position on exchange and no orders. Position {signal.Identifier} might be closed already."); + await LogWarning( + $"Cannot update Position. No position on exchange and no orders. Position {signal.Identifier} might be closed already."); await HandleClosedPosition(positionForSignal); } } @@ -446,7 +448,7 @@ public class TradingBot : Bot, ITradingBot Logger.LogInformation($"Try to re-open position"); await OpenPosition(signal); } - } + } } catch (Exception ex) { @@ -525,15 +527,16 @@ public class TradingBot : Bot, ITradingBot Ticker, IsForBacktest ? PositionInitiator.PaperTrading : PositionInitiator.Bot, signal.Date, + User, IsForBacktest, lastPrice, balance: WalletBalances.LastOrDefault().Value, - fee: Fee); + fee: Fee, + signalIdentifier: signal.Identifier); var position = await new OpenPositionCommandHandler(ExchangeService, AccountService, TradingService) .Handle(command); - if (position != null) { position.SignalIdentifier = signal.Identifier; @@ -691,7 +694,7 @@ public class TradingBot : Bot, ITradingBot await ExchangeService.CancelOrder(Account, Ticker); var closePendingOrderStatus = await ExchangeService.CancelOrder(Account, Ticker); Logger.LogInformation($"Closing all {Ticker} orders status : {closePendingOrderStatus}"); - } + } } else { @@ -839,7 +842,7 @@ public class TradingBot : Bot, ITradingBot // Create a fake signal for manual position opening var signal = new Signal(Ticker, direction, Confidence.Low, lastCandle, lastCandle.Date, TradingExchanges.GmxV2, - StrategyType.Stc, SignalType.Signal); + StrategyType.Stc, SignalType.Signal); signal.Status = SignalStatus.WaitingForPosition; // Ensure status is correct signal.User = Account.User; // Assign user @@ -854,7 +857,7 @@ public class TradingBot : Bot, ITradingBot if (position == null) { // Clean up the signal if position creation failed - SetSignalStatus(signal.Identifier, SignalStatus.Expired); + SetSignalStatus(signal.Identifier, SignalStatus.Expired); throw new Exception("Failed to open position"); } diff --git a/src/Managing.Application/Trading/Commands/OpenPositionRequest.cs b/src/Managing.Application/Trading/Commands/OpenPositionRequest.cs index a325214..e0d10b2 100644 --- a/src/Managing.Application/Trading/Commands/OpenPositionRequest.cs +++ b/src/Managing.Application/Trading/Commands/OpenPositionRequest.cs @@ -1,5 +1,6 @@ using Managing.Domain.MoneyManagements; using Managing.Domain.Trades; +using Managing.Domain.Users; using MediatR; using static Managing.Common.Enums; @@ -14,11 +15,13 @@ namespace Managing.Application.Trading.Commands Ticker ticker, PositionInitiator initiator, DateTime date, + User user, bool isForPaperTrading = false, decimal? price = null, decimal? balance = 1000, - decimal? fee = null, - bool? ignoreSLTP = false) + decimal? fee = null, + bool? ignoreSLTP = false, + string signalIdentifier = null) { AccountName = accountName; MoneyManagement = moneyManagement; @@ -31,8 +34,11 @@ namespace Managing.Application.Trading.Commands Initiator = initiator; Fee = fee; IgnoreSLTP = ignoreSLTP; + User = user; + SignalIdentifier = signalIdentifier; } + public string SignalIdentifier { get; set; } public string AccountName { get; } public MoneyManagement MoneyManagement { get; } public TradeDirection Direction { get; } @@ -44,5 +50,6 @@ namespace Managing.Application.Trading.Commands public decimal? Balance { get; } public DateTime Date { get; set; } public PositionInitiator Initiator { get; internal set; } + public User User { get; internal set; } } -} +} \ No newline at end of file diff --git a/src/Managing.Application/Trading/OpenPositionCommandHandler.cs b/src/Managing.Application/Trading/OpenPositionCommandHandler.cs index bffcd51..d628b71 100644 --- a/src/Managing.Application/Trading/OpenPositionCommandHandler.cs +++ b/src/Managing.Application/Trading/OpenPositionCommandHandler.cs @@ -26,8 +26,15 @@ namespace Managing.Application.Trading } var initiator = request.IsForPaperTrading ? PositionInitiator.PaperTrading : request.Initiator; - var position = new Position(request.AccountName, request.Direction, request.Ticker, request.MoneyManagement, - initiator, request.Date); + var position = new Position(new Guid().ToString(), request.AccountName, request.Direction, request.Ticker, + request.MoneyManagement, + initiator, request.Date, request.User); + + if (!string.IsNullOrEmpty(request.SignalIdentifier)) + { + position.SignalIdentifier = request.SignalIdentifier; + } + var balance = request.IsForPaperTrading ? request.Balance.GetValueOrDefault() : exchangeService.GetBalance(account, request.IsForPaperTrading).Result; @@ -63,12 +70,12 @@ namespace Managing.Application.Trading TradeType.Limit, isForPaperTrading: request.IsForPaperTrading, currentDate: request.Date, - stopLossPrice: stopLossPrice, // Pass determined SL price + stopLossPrice: stopLossPrice, // Pass determined SL price takeProfitPrice: takeProfitPrice); // Pass determined TP price //trade.Fee = TradingHelpers.GetFeeAmount(fee, openPrice * quantity, account.Exchange); position.Open = trade; - + var closeDirection = request.Direction == TradeDirection.Long ? TradeDirection.Short : TradeDirection.Long; diff --git a/src/Managing.Application/Workflows/Flows/Trading/OpenPosition.cs b/src/Managing.Application/Workflows/Flows/Trading/OpenPosition.cs index c309fd1..6973cdf 100644 --- a/src/Managing.Application/Workflows/Flows/Trading/OpenPosition.cs +++ b/src/Managing.Application/Workflows/Flows/Trading/OpenPosition.cs @@ -1,4 +1,5 @@ -using Managing.Application.Abstractions; +using InfluxDB.Client.Api.Domain; +using Managing.Application.Abstractions; using Managing.Application.Abstractions.Services; using Managing.Application.Trading.Commands; using Managing.Application.Trading; @@ -63,13 +64,12 @@ public class OpenPosition : FlowBase var Positions = JsonConvert.DeserializeObject>(_cacheService.GetValue(POSITIONS_KEY)); var Signals = JsonConvert.DeserializeObject>(_cacheService.GetValue(POSITIONS_KEY)); - Fee = _cacheService.GetOrSave(FEE_KEY, () => - { - return _tradingService.GetFee(Account, OpenPositionParameters.IsForBacktest); - }, TimeSpan.FromDays(1)); + Fee = _cacheService.GetOrSave(FEE_KEY, + () => { return _tradingService.GetFee(Account, OpenPositionParameters.IsForBacktest); }, + TimeSpan.FromDays(1)); await ExecuteOpenPosition(signal, Positions, Signals, Candles, Account); - + _cacheService.SaveValue(POSITIONS_KEY, JsonConvert.SerializeObject(Positions)); _cacheService.SaveValue(SIGNALS_KEY, JsonConvert.SerializeObject(Signals)); @@ -82,13 +82,16 @@ public class OpenPosition : FlowBase } } - private async Task ExecuteOpenPosition(Signal signal, List positions, HashSet signals, HashSet candles, Account account) + private async Task ExecuteOpenPosition(Signal signal, List positions, HashSet signals, + HashSet candles, Account account) { // Check if a position is already open var openedPosition = positions.FirstOrDefault(p => p.Status == PositionStatus.Filled - && p.SignalIdentifier != signal.Identifier); + && p.SignalIdentifier != signal.Identifier); - var lastPrice = OpenPositionParameters.IsForBacktest ? candles.Last().Close : _exchangeService.GetPrice(account, signal.Ticker, DateTime.UtcNow); + var lastPrice = OpenPositionParameters.IsForBacktest + ? candles.Last().Close + : _exchangeService.GetPrice(account, signal.Ticker, DateTime.UtcNow); // If position open if (openedPosition != null) @@ -110,7 +113,8 @@ public class OpenPosition : FlowBase { //await LogInformation("Try to flip the position because of an opposite direction signal"); //await CloseTrade(previousSignal, openedPosition, openedPosition.Open, lastPrice, true); - positions.FirstOrDefault(s => s.Identifier == previousSignal.Identifier).Status = PositionStatus.Flipped; + positions.FirstOrDefault(s => s.Identifier == previousSignal.Identifier).Status = + PositionStatus.Flipped; await ExecuteOpenPosition(signal, positions, signals, candles, account); //await LogInformation($"Position {previousSignal.Identifier} flipped by {signal.Identifier} at {lastPrice}$"); @@ -134,23 +138,27 @@ public class OpenPosition : FlowBase try { - var moneyManagement = await _settingsRepository.GetMoneyManagement(OpenPositionParameters.MoneyManagementName); - var WalletBalances = JsonConvert.DeserializeObject>(_cacheService.GetValue(WALLET_BALANCES)); + var moneyManagement = + await _settingsRepository.GetMoneyManagement(OpenPositionParameters.MoneyManagementName); + var WalletBalances = + JsonConvert.DeserializeObject>( + _cacheService.GetValue(WALLET_BALANCES)); var command = new OpenPositionRequest( OpenPositionParameters.AccountName, - moneyManagement, + moneyManagement, signal.Direction, - signal.Ticker, + signal.Ticker, PositionInitiator.Bot, signal.Date, + account.User, OpenPositionParameters.IsForBacktest, lastPrice, balance: WalletBalances.LastOrDefault().Value, fee: Fee); var position = await new OpenPositionCommandHandler(_exchangeService, _accountService, _tradingService) - .Handle(command); + .Handle(command); if (position != null) { @@ -158,18 +166,21 @@ public class OpenPosition : FlowBase { position.SignalIdentifier = signal.Identifier; positions.Add(position); - signals.FirstOrDefault(s => s.Identifier == signal.Identifier).Status = SignalStatus.PositionOpen; + signals.FirstOrDefault(s => s.Identifier == signal.Identifier).Status = + SignalStatus.PositionOpen; if (!OpenPositionParameters.IsForBacktest) { await _messengerService.SendPosition(position); } + Output = JsonConvert.SerializeObject(position); //Logger.LogInformation($"Position requested"); } else { - positions.FirstOrDefault(s => s.Identifier == signal.Identifier).Status = PositionStatus.Rejected; + positions.FirstOrDefault(s => s.Identifier == signal.Identifier).Status = + PositionStatus.Rejected; signals.FirstOrDefault(s => s.Identifier == signal.Identifier).Status = SignalStatus.Expired; } } @@ -180,18 +191,18 @@ public class OpenPosition : FlowBase //await LogWarning($"Cannot open trade : {ex.Message}"); } } - } - private bool CanOpenPosition(Signal signal, List positions, HashSet signals, HashSet candles) + private bool CanOpenPosition(Signal signal, List positions, HashSet signals, + HashSet candles) { if (positions.Count == 0) return true; var lastPosition = positions.LastOrDefault(p => p.IsFinished() - && p.SignalIdentifier != signal.Identifier - && p.ProfitAndLoss.Realized < 0 - && p.OriginDirection == signal.Direction); + && p.SignalIdentifier != signal.Identifier + && p.ProfitAndLoss.Realized < 0 + && p.OriginDirection == signal.Direction); if (lastPosition == null) return true; @@ -224,4 +235,4 @@ public class OpenPositionParameters public string AccountName { get; set; } public bool IsForBacktest { get; set; } public bool FlipPosition { get; set; } -} +} \ No newline at end of file diff --git a/src/Managing.Domain/Trades/Position.cs b/src/Managing.Domain/Trades/Position.cs index 6ec798f..d361ab9 100644 --- a/src/Managing.Domain/Trades/Position.cs +++ b/src/Managing.Domain/Trades/Position.cs @@ -7,9 +7,10 @@ namespace Managing.Domain.Trades { public class Position { - public Position(string accountName, TradeDirection originDirection, Ticker ticker, MoneyManagement moneyManagement, PositionInitiator positionInitiator, DateTime date) + public Position(string identifier, string accountName, TradeDirection originDirection, Ticker ticker, + MoneyManagement moneyManagement, PositionInitiator positionInitiator, DateTime date, User user) { - Identifier = Guid.NewGuid().ToString(); + Identifier = identifier; AccountName = accountName; OriginDirection = originDirection; Ticker = ticker; @@ -17,34 +18,24 @@ namespace Managing.Domain.Trades Initiator = positionInitiator; Date = date; Status = Initiator == PositionInitiator.PaperTrading ? PositionStatus.Filled : PositionStatus.New; + User = user; } - [Required] - public string AccountName { get; } - [Required] - public DateTime Date { get; set; } - [Required] - public TradeDirection OriginDirection { get; } - [Required] - public Ticker Ticker { get; } - [Required] - public MoneyManagement MoneyManagement { get; } - [Required] - public Trade Open { get; set; } - [Required] - public Trade StopLoss { get; set; } - [Required] - public Trade TakeProfit1 { get; set; } + [Required] public string AccountName { get; } + [Required] public DateTime Date { get; set; } + [Required] public TradeDirection OriginDirection { get; } + [Required] public Ticker Ticker { get; } + [Required] public MoneyManagement MoneyManagement { get; } + [Required] public Trade Open { get; set; } + [Required] public Trade StopLoss { get; set; } + [Required] public Trade TakeProfit1 { get; set; } public Trade TakeProfit2 { get; set; } public ProfitAndLoss ProfitAndLoss { get; set; } - [Required] - public PositionStatus Status { get; set; } + [Required] public PositionStatus Status { get; set; } public string SignalIdentifier { get; set; } - [Required] - public string Identifier { get; set; } - [Required] - public PositionInitiator Initiator { get; } - public User User { get; set; } + [Required] public string Identifier { get; set; } + [Required] public PositionInitiator Initiator { get; } + [Required] public User User { get; set; } public bool IsFinished() { @@ -56,4 +47,4 @@ namespace Managing.Domain.Trades }; } } -} +} \ No newline at end of file diff --git a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs index 32ae323..e2c8d11 100644 --- a/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs +++ b/src/Managing.Infrastructure.Database/MongoDb/MongoMappers.cs @@ -257,7 +257,7 @@ public static class MongoMappers MoneyManagement = Map(position.MoneyManagement), Initiator = position.Initiator, Ticker = position.Ticker, - User = position.User != null ? Map(position.User) : null + User = Map(position.User) }; if (position.StopLoss != null) @@ -294,8 +294,8 @@ public static class MongoMappers public static Position Map(PositionDto dto) { - var position = new Position(dto.AccountName, originDirection: dto.OriginDirection, dto.Ticker, - Map(dto.MoneyManagement), dto.Initiator, dto.Date) + var position = new Position(dto.Identifier, dto.AccountName, originDirection: dto.OriginDirection, dto.Ticker, + Map(dto.MoneyManagement), dto.Initiator, dto.Date, Map(dto.User)) { Open = new Trade(date: dto.Open.Date, direction: dto.Open.Direction, status: dto.Open.Status, tradeType: dto.Open.TradeType, ticker: dto.Open.Ticker, quantity: dto.Open.Quantity, @@ -305,7 +305,7 @@ public static class MongoMappers Status = dto.Status, SignalIdentifier = dto.SignalIdentifier, Identifier = dto.Identifier, - User = dto.User != null ? Map(dto.User) : null + User = Map(dto.User) }; if (dto.StopLoss != null) diff --git a/src/Managing.Infrastructure.Messengers/Discord/DiscordCommands.cs b/src/Managing.Infrastructure.Messengers/Discord/DiscordCommands.cs index 264bc6b..2a4352b 100644 --- a/src/Managing.Infrastructure.Messengers/Discord/DiscordCommands.cs +++ b/src/Managing.Infrastructure.Messengers/Discord/DiscordCommands.cs @@ -7,6 +7,7 @@ using Managing.Common; using Managing.Core; using Managing.Domain.MoneyManagements; using Managing.Domain.Trades; +using Managing.Domain.Users; using static Managing.Common.Enums; namespace Managing.Infrastructure.Messengers.Discord @@ -73,7 +74,7 @@ namespace Managing.Infrastructure.Messengers.Discord TakeProfit = takeProfit.GetValueOrDefault(), }; var tradeCommand = new OpenPositionRequest(accountName, moneymanagement, direction, ticker, - PositionInitiator.User, DateTime.UtcNow); + PositionInitiator.User, DateTime.UtcNow, new User()); var result = await _openTradeCommandHandler.Handle(tradeCommand); var builder = new ComponentBuilder().WithButton("Close Position", $"{Constants.DiscordButtonAction.ClosePosition}|{result.Open.ExchangeOrderId}"); diff --git a/src/Managing.Infrastructure.Messengers/Discord/DiscordService.cs b/src/Managing.Infrastructure.Messengers/Discord/DiscordService.cs index b0cf1f7..90205c3 100644 --- a/src/Managing.Infrastructure.Messengers/Discord/DiscordService.cs +++ b/src/Managing.Infrastructure.Messengers/Discord/DiscordService.cs @@ -273,6 +273,7 @@ namespace Managing.Infrastructure.Messengers.Discord ticker, initiator, DateTime.UtcNow, + defaultUser, ignoreSLTP: ignoreSLTP); var position = await new OpenPositionCommandHandler(exchangeService, accountService, tradingService) .Handle(tradeCommand); diff --git a/src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Mappers.cs b/src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Mappers.cs index 1c3df10..8c91b64 100644 --- a/src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Mappers.cs +++ b/src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Mappers.cs @@ -8,6 +8,7 @@ using Managing.Infrastructure.Evm.Models.Gmx.v2; using Managing.Infrastructure.Evm.Models.Proxy; using Nethereum.Web3; using Managing.Domain.MoneyManagements; +using Managing.Domain.Users; using static Managing.Common.Enums; namespace Managing.Infrastructure.Evm.Services.Gmx; @@ -161,12 +162,13 @@ internal static class GmxV2Mappers { try { - var position = new Position("", + var position = new Position("", "", MiscExtensions.ParseEnum(gmxPosition.Direction), MiscExtensions.ParseEnum(gmxPosition.Ticker), new MoneyManagement(), PositionInitiator.User, - gmxPosition.Date); + gmxPosition.Date, + new User()); position.Open = Map(gmxPosition.Open); position.TakeProfit1 = Map(gmxPosition.TakeProfit1); position.StopLoss = Map(gmxPosition.StopLoss); @@ -174,15 +176,17 @@ internal static class GmxV2Mappers { Net = (decimal)gmxPosition.Pnl }; - + position.Status = MiscExtensions.ParseEnum(gmxPosition.Status); positions.Add(position); } catch (Exception ex) { - Console.WriteLine($"Error mapping GMX position {gmxPosition?.ExchangeOrderId}: {ex.Message} \n StackTrace: {ex.StackTrace}"); + Console.WriteLine( + $"Error mapping GMX position {gmxPosition?.ExchangeOrderId}: {ex.Message} \n StackTrace: {ex.StackTrace}"); } } + return positions; } diff --git a/src/Managing.Infrastructure.Web3/Services/Web3ProxyService.cs b/src/Managing.Infrastructure.Web3/Services/Web3ProxyService.cs index 6a171fa..6b8aada 100644 --- a/src/Managing.Infrastructure.Web3/Services/Web3ProxyService.cs +++ b/src/Managing.Infrastructure.Web3/Services/Web3ProxyService.cs @@ -35,17 +35,17 @@ namespace Managing.Infrastructure.Evm.Services endpoint = $"/{endpoint}"; } - var url = $"{_settings.BaseUrl}privy{endpoint}"; - + var url = $"{_settings.BaseUrl}/api/privy{endpoint}"; + try { var response = await _httpClient.PostAsJsonAsync(url, payload, _jsonOptions); - + if (!response.IsSuccessStatusCode) { await HandleErrorResponse(response); } - + return await response.Content.ReadFromJsonAsync(_jsonOptions); } catch (Exception ex) when (!(ex is Web3ProxyException)) @@ -62,7 +62,7 @@ namespace Managing.Infrastructure.Evm.Services endpoint = $"/{endpoint}"; } - var url = $"{_settings.BaseUrl}privy{endpoint}"; + var url = $"{_settings.BaseUrl}/api/privy{endpoint}"; if (payload != null) { @@ -72,12 +72,12 @@ namespace Managing.Infrastructure.Evm.Services try { var response = await _httpClient.GetAsync(url); - + if (!response.IsSuccessStatusCode) { await HandleErrorResponse(response); } - + return await response.Content.ReadFromJsonAsync(_jsonOptions); } catch (Exception ex) when (!(ex is Web3ProxyException)) @@ -95,16 +95,16 @@ namespace Managing.Infrastructure.Evm.Services } var url = $"{_settings.BaseUrl}/api/gmx{endpoint}"; - + try { var response = await _httpClient.PostAsJsonAsync(url, payload, _jsonOptions); - + if (!response.IsSuccessStatusCode) { await HandleErrorResponse(response); } - + return await response.Content.ReadFromJsonAsync(_jsonOptions); } catch (Exception ex) when (!(ex is Web3ProxyException)) @@ -131,12 +131,12 @@ namespace Managing.Infrastructure.Evm.Services try { var response = await _httpClient.GetAsync(url); - + if (!response.IsSuccessStatusCode) { await HandleErrorResponse(response); } - + return await response.Content.ReadFromJsonAsync(_jsonOptions); } catch (Exception ex) when (!(ex is Web3ProxyException)) @@ -149,25 +149,26 @@ namespace Managing.Infrastructure.Evm.Services private async Task HandleErrorResponse(HttpResponseMessage response) { var statusCode = (int)response.StatusCode; - + try { // Try to parse as the Web3Proxy error format (success: false, error: string) var content = await response.Content.ReadAsStringAsync(); var errorResponse = await response.Content.ReadFromJsonAsync(_jsonOptions); - + if (errorResponse != null && !errorResponse.Success && !string.IsNullOrEmpty(errorResponse.Error)) { // Handle the standard Web3Proxy error format throw new Web3ProxyException(errorResponse.Error); } - + // Fallback for other error formats - try + try { // Try to parse as structured error if it doesn't match the simple format - var structuredErrorResponse = await response.Content.ReadFromJsonAsync(_jsonOptions); - + var structuredErrorResponse = + await response.Content.ReadFromJsonAsync(_jsonOptions); + if (structuredErrorResponse?.ErrorDetails != null) { structuredErrorResponse.ErrorDetails.StatusCode = statusCode; diff --git a/src/Managing.Web3Proxy/src/generated/gmxsdk/modules/orders/helpers.ts b/src/Managing.Web3Proxy/src/generated/gmxsdk/modules/orders/helpers.ts index 4a9e5fb..adf8eea 100644 --- a/src/Managing.Web3Proxy/src/generated/gmxsdk/modules/orders/helpers.ts +++ b/src/Managing.Web3Proxy/src/generated/gmxsdk/modules/orders/helpers.ts @@ -321,7 +321,7 @@ export async function increaseOrderHelper( referralCodeForTxn: params.referralCodeForTxn, triggerPrice: params.limitPrice, collateralTokenAddress: collateralToken.address, - isLong: true, + isLong: params.isLong, receiveTokenAddress: collateralTokenAddress, indexToken: marketInfo.indexToken, marketInfo,