Fix bots + positions managements
This commit is contained in:
@@ -720,6 +720,21 @@ public class EvmManager : IEvmManager
|
||||
return await GetTrade(account.Key, chainName, ticker);
|
||||
}
|
||||
|
||||
public async Task<List<Position>> GetPositions(Account account)
|
||||
{
|
||||
if (account.IsPrivyWallet)
|
||||
{
|
||||
var result = await _web3ProxyService.GetGmxServiceAsync<GetGmxPositionsResponse>(
|
||||
"/positions",
|
||||
new { account = account.Key });
|
||||
|
||||
|
||||
return GmxV2Mappers.Map(result.Positions);
|
||||
}
|
||||
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public async Task<Trade> GetTrade(string reference, string chainName, Ticker ticker)
|
||||
{
|
||||
@@ -757,7 +772,7 @@ public class EvmManager : IEvmManager
|
||||
var result = await _web3ProxyService.GetGmxServiceAsync<GetGmxTradesResponse>("/trades",
|
||||
new { account = account.Key, ticker = ticker.ToString() });
|
||||
|
||||
return result.Trades;
|
||||
return GmxV2Mappers.Map(result.Trades);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -45,11 +45,11 @@ public class GmxPosition
|
||||
|
||||
[JsonProperty("liquidationPrice")] public double LiquidationPrice { get; set; }
|
||||
|
||||
[JsonProperty("stopLoss")] public StopLoss StopLoss { get; set; }
|
||||
[JsonProperty("stopLoss")] public GmxTrade StopLoss { get; set; }
|
||||
|
||||
[JsonProperty("takeProfit1")] public TakeProfit1 TakeProfit1 { get; set; }
|
||||
[JsonProperty("takeProfit1")] public GmxTrade TakeProfit1 { get; set; }
|
||||
|
||||
[JsonProperty("open")] public Open Open { get; set; }
|
||||
[JsonProperty("open")] public GmxTrade Open { get; set; }
|
||||
}
|
||||
|
||||
public class GetGmxPositionsResponse : Web3ProxyBaseResponse
|
||||
|
||||
@@ -1,10 +1,56 @@
|
||||
using Managing.Domain.Trades;
|
||||
using System.Text.Json.Serialization;
|
||||
using Managing.Domain.Trades;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Managing.Infrastructure.Evm.Models.Proxy;
|
||||
|
||||
public class GetGmxTradesResponse : Web3ProxyBaseResponse
|
||||
{
|
||||
|
||||
[JsonProperty("trades")]
|
||||
public List<Trade> Trades { get; set; }
|
||||
}
|
||||
[JsonPropertyName("trades")]
|
||||
public List<GmxTrade> Trades { get; set; }
|
||||
}
|
||||
|
||||
public class GmxTrade
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
[JsonPropertyName("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("ticker")]
|
||||
[JsonPropertyName("ticker")]
|
||||
public string Ticker { get; set; }
|
||||
|
||||
[JsonProperty("direction")]
|
||||
[JsonPropertyName("direction")]
|
||||
public string Direction { get; set; }
|
||||
|
||||
[JsonProperty("price")]
|
||||
[JsonPropertyName("price")]
|
||||
public double Price { get; set; }
|
||||
|
||||
[JsonProperty("quantity")]
|
||||
[JsonPropertyName("quantity")]
|
||||
public double Quantity { get; set; }
|
||||
|
||||
[JsonProperty("leverage")]
|
||||
[JsonPropertyName("leverage")]
|
||||
public decimal Leverage { get; set; }
|
||||
|
||||
[JsonProperty("status")]
|
||||
[JsonPropertyName("status")]
|
||||
public string Status { get; set; }
|
||||
|
||||
[JsonProperty("tradeType")]
|
||||
[JsonPropertyName("tradeType")]
|
||||
public string TradeType { get; set; }
|
||||
|
||||
[JsonProperty("date")]
|
||||
[JsonPropertyName("date")]
|
||||
public DateTime Date { get; set; }
|
||||
|
||||
[JsonProperty("exchangeOrderId")]
|
||||
[JsonPropertyName("exchangeOrderId")]
|
||||
public string ExchangeOrderId { get; set; }
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@ using Managing.Core;
|
||||
using Managing.Domain.Candles;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Evm.Models.Gmx.v2;
|
||||
using Managing.Infrastructure.Evm.Models.Proxy;
|
||||
using Nethereum.Web3;
|
||||
using Managing.Domain.MoneyManagements;
|
||||
using static Managing.Common.Enums;
|
||||
|
||||
namespace Managing.Infrastructure.Evm.Services.Gmx;
|
||||
|
||||
@@ -48,14 +51,14 @@ internal static class GmxV2Mappers
|
||||
var quantity = sizeDelta / triggerPrice;
|
||||
var initialCollateral =
|
||||
GmxV2Helpers.ParseContractPrice(order.InitialCollateralDeltaAmount, shortToken.Decimals);
|
||||
var leverage = sizeDelta / initialCollateral;
|
||||
var leverage = sizeDelta == 0 || initialCollateral == 0 ? 0 : sizeDelta / initialCollateral;
|
||||
|
||||
var trade = new Trade(
|
||||
order.Date,
|
||||
order.IsLong ? Enums.TradeDirection.Long : Enums.TradeDirection.Short,
|
||||
Enums.TradeStatus.PendingOpen,
|
||||
GmxV2Helpers.GetTradeType(order.OrderType),
|
||||
GmxV2Helpers.GetTicker(order.MarketAddress),
|
||||
ticker,
|
||||
Convert.ToDecimal(quantity),
|
||||
Convert.ToDecimal(triggerPrice),
|
||||
leverage,
|
||||
@@ -91,9 +94,10 @@ internal static class GmxV2Mappers
|
||||
BigInteger collateralAmount)
|
||||
{
|
||||
if (collateralAmount == 0) return (0m, 0m);
|
||||
const int collateralDecimals = 6;
|
||||
var size = Web3.Convert.FromWei(sizeInUsd, 30);
|
||||
var collateral = Web3.Convert.FromWei(collateralAmount, 6); // USDC decimals
|
||||
return (collateral, Math.Round(size / collateral));
|
||||
var collateral = Web3.Convert.FromWei(collateralAmount, collateralDecimals);
|
||||
return (collateral, collateral == 0 ? 0 : Math.Round(size / collateral));
|
||||
}
|
||||
|
||||
public static List<MarketPrices> Map(List<ABI.GmxV2.Reader.ContractDefinition.MarketPrices> marketPrices)
|
||||
@@ -134,10 +138,75 @@ internal static class GmxV2Mappers
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
Console.WriteLine($"Could not parse ticker for symbol {t.Symbol}: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps raw GMX positions fetched from the proxy/contract to domain Position objects.
|
||||
/// </summary>
|
||||
/// <param name="resultPositions">List of GmxPosition objects from the proxy.</param>
|
||||
/// <returns>List of domain Position objects.</returns>
|
||||
/// <remarks>
|
||||
/// Assumes GmxPosition contains necessary details like Account, Market, CollateralToken, IsLong, etc.
|
||||
/// Requires resolution of MoneyManagement dependency.
|
||||
/// </remarks>
|
||||
public static List<Position> Map(List<GmxPosition> resultPositions)
|
||||
{
|
||||
var positions = new List<Position>();
|
||||
foreach (var gmxPosition in resultPositions)
|
||||
{
|
||||
try
|
||||
{
|
||||
var position = new Position("",
|
||||
MiscExtensions.ParseEnum<TradeDirection>(gmxPosition.Direction),
|
||||
MiscExtensions.ParseEnum<Ticker>(gmxPosition.Ticker),
|
||||
new MoneyManagement(),
|
||||
PositionInitiator.User,
|
||||
gmxPosition.Date);
|
||||
position.Open = Map(gmxPosition.Open);
|
||||
position.TakeProfit1 = Map(gmxPosition.TakeProfit1);
|
||||
position.StopLoss = Map(gmxPosition.StopLoss);
|
||||
position.ProfitAndLoss = new ProfitAndLoss()
|
||||
{
|
||||
Net = (decimal)gmxPosition.Pnl
|
||||
};
|
||||
|
||||
position.Status = MiscExtensions.ParseEnum<PositionStatus>(gmxPosition.Status);
|
||||
positions.Add(position);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error mapping GMX position {gmxPosition?.ExchangeOrderId}: {ex.Message} \n StackTrace: {ex.StackTrace}");
|
||||
}
|
||||
}
|
||||
return positions;
|
||||
}
|
||||
|
||||
private static Trade Map(GmxTrade gmxPosition)
|
||||
{
|
||||
return new Trade(gmxPosition.Date,
|
||||
MiscExtensions.ParseEnum<TradeDirection>(gmxPosition.Direction),
|
||||
MiscExtensions.ParseEnum<TradeStatus>(gmxPosition.Status),
|
||||
MiscExtensions.ParseEnum<TradeType>(gmxPosition.TradeType),
|
||||
MiscExtensions.ParseEnum<Ticker>(gmxPosition.Ticker),
|
||||
(decimal)gmxPosition.Quantity,
|
||||
(decimal)gmxPosition.Price,
|
||||
gmxPosition.Leverage,
|
||||
gmxPosition.ExchangeOrderId, "");
|
||||
}
|
||||
|
||||
public static List<Trade> Map(List<GmxTrade> resultPositions)
|
||||
{
|
||||
var trades = new List<Trade>();
|
||||
foreach (var gmxPosition in resultPositions)
|
||||
{
|
||||
trades.Add(Map(gmxPosition));
|
||||
}
|
||||
|
||||
return trades;
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,7 @@ namespace Managing.Infrastructure.Evm.Services
|
||||
}
|
||||
catch (Exception ex) when (!(ex is Web3ProxyException))
|
||||
{
|
||||
SentrySdk.CaptureException(ex);
|
||||
throw new Web3ProxyException($"Failed to call Privy service at {endpoint}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
@@ -81,6 +82,7 @@ namespace Managing.Infrastructure.Evm.Services
|
||||
}
|
||||
catch (Exception ex) when (!(ex is Web3ProxyException))
|
||||
{
|
||||
SentrySdk.CaptureException(ex);
|
||||
throw new Web3ProxyException($"Failed to get Privy service at {endpoint}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
@@ -107,6 +109,7 @@ namespace Managing.Infrastructure.Evm.Services
|
||||
}
|
||||
catch (Exception ex) when (!(ex is Web3ProxyException))
|
||||
{
|
||||
SentrySdk.CaptureException(ex);
|
||||
throw new Web3ProxyException($"Failed to call GMX service at {endpoint}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
@@ -138,6 +141,7 @@ namespace Managing.Infrastructure.Evm.Services
|
||||
}
|
||||
catch (Exception ex) when (!(ex is Web3ProxyException))
|
||||
{
|
||||
SentrySdk.CaptureException(ex);
|
||||
throw new Web3ProxyException($"Failed to get GMX service at {endpoint}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
@@ -178,6 +182,7 @@ namespace Managing.Infrastructure.Evm.Services
|
||||
}
|
||||
catch (Exception ex) when (!(ex is Web3ProxyException))
|
||||
{
|
||||
SentrySdk.CaptureException(ex);
|
||||
// If we couldn't parse the error as JSON or another issue occurred
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
throw new Web3ProxyException($"HTTP error {statusCode}: {content}");
|
||||
|
||||
Reference in New Issue
Block a user