Files
managing-apps/src/Managing.Infrastructure.Web3/Services/Gmx/GmxV2Mappers.cs

229 lines
8.6 KiB
C#

using System.Numerics;
using Managing.ABI.GmxV2.SyntheticsReader.ContractDefinition;
using Managing.Common;
using Managing.Core;
using Managing.Domain.Candles;
using Managing.Domain.MoneyManagements;
using Managing.Domain.Trades;
using Managing.Domain.Users;
using Managing.Infrastructure.Evm.Models.Gmx.v2;
using Managing.Infrastructure.Evm.Models.Proxy;
using Nethereum.Web3;
using static Managing.Common.Enums;
namespace Managing.Infrastructure.Evm.Services.Gmx;
internal static class GmxV2Mappers
{
public static Trade Map(GmxV2Position position, Ticker ticker)
{
var entryPrice = GmxV2Helpers.GetEntryPrice(position.SizeInUsd, position.SizeInTokens,
position.TokenData.Decimals);
var parsedEntryPrice = GmxHelpers.FormatAmount(entryPrice, Constants.GMX.Config.Decimals.USD - 2, 4);
var collateralLeverage = CalculateCollateralAndLeverage(position.SizeInUsd, position.CollateralAmount);
var trade = new Trade(
DateHelpers.GetFromUnixTimestamp((int)position.IncreasedAtTime),
position.IsLong ? TradeDirection.Long : TradeDirection.Short,
TradeStatus.Filled,
TradeType.Limit,
ticker,
collateralLeverage.collateral / parsedEntryPrice,
parsedEntryPrice,
collateralLeverage.leverage,
position.Key,
""
);
return trade;
}
public static List<Trade> Map(List<GmxV2Order> orders)
{
var trades = new List<Trade>();
foreach (var order in orders)
{
var shortToken = TokenV2Service.GetTokenByAddress(order.InitialCollateralTokenAddress);
var ticker = GmxV2Helpers.GetTicker(order.MarketAddress);
var indexToken = TokenV2Service.GetByTicker(ticker);
var sizeDelta = GmxHelpers.FormatAmount(order.SizeDeltaUsd, Constants.GMX.Config.Decimals.USD, 4);
var triggerPrice = GmxV2Helpers.ParseContractPrice(order.ContractTriggerPrice, indexToken.Decimals, true);
var quantity = sizeDelta / triggerPrice;
var initialCollateral =
GmxV2Helpers.ParseContractPrice(order.InitialCollateralDeltaAmount, shortToken.Decimals);
var leverage = sizeDelta == 0 || initialCollateral == 0 ? 0 : sizeDelta / initialCollateral;
var trade = new Trade(
order.Date,
order.IsLong ? TradeDirection.Long : TradeDirection.Short,
TradeStatus.PendingOpen,
GmxV2Helpers.GetTradeType(order.OrderType),
ticker,
Convert.ToDecimal(quantity),
Convert.ToDecimal(triggerPrice),
leverage,
"",
""
);
trades.Add(trade);
}
return trades;
}
//
// public static GmxV2Position MapPosition(GmxV2Service.PositionInfoDTO positionInfo)
// {
// return new GmxV2Position
// {
// PositionKey = GetPositionKeyV2(
// positionInfo.Position.Account,
// positionInfo.Position.Market,
// positionInfo.Position.CollateralToken,
// positionInfo.Position.IsLong
// ),
// SizeInUsd = positionInfo.Position.SizeInUsd,
// CollateralAmount = positionInfo.Position.CollateralAmount,
// IncreasedAtTime = positionInfo.Position.IncreasedAtTime,
// IsLong = positionInfo.Position.IsLong,
// Leverage = CalculateLeverage(positionInfo.Position.SizeInUsd, positionInfo.Position.CollateralAmount)
// };
// }
private static (decimal collateral, decimal leverage) CalculateCollateralAndLeverage(BigInteger sizeInUsd,
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, collateralDecimals);
return (collateral, collateral == 0 ? 0 : Math.Round(size / collateral));
}
public static List<MarketPrices> Map(List<ABI.GmxV2.Reader.ContractDefinition.MarketPrices> marketPrices)
{
return marketPrices.Select(mp => new MarketPrices
{
IndexTokenPrice = mp.IndexTokenPrice,
LongTokenPrice = mp.LongTokenPrice,
ShortTokenPrice = mp.ShortTokenPrice
}).ToList();
}
public static Candle Map(List<double> marketPrices, Ticker ticker, Timeframe timeframe, int timeBetween)
{
return new Candle()
{
Date = DateHelpers.GetFromUnixTimestamp((int)marketPrices[0] + timeBetween).AddSeconds(-1),
OpenTime = DateHelpers.GetFromUnixTimestamp((int)marketPrices[0]),
Open = Convert.ToDecimal(marketPrices[1]),
High = Convert.ToDecimal(marketPrices[2]),
Low = Convert.ToDecimal(marketPrices[3]),
Close = Convert.ToDecimal(marketPrices[4]),
Exchange = TradingExchanges.Evm,
Ticker = ticker.ToString(),
Timeframe = timeframe
};
}
public static List<Ticker> Map(GmxV2TokenList tokenList)
{
var tokens = new List<Ticker>();
foreach (var t in tokenList.Tokens)
{
try
{
var ticker = MiscExtensions.ParseEnum<Ticker>(t.Symbol);
tokens.Add(ticker);
}
catch (Exception 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 direction = MiscExtensions.ParseEnum<TradeDirection>(gmxPosition.Direction);
var ticker = MiscExtensions.ParseEnum<Ticker>(gmxPosition.Ticker);
var position = new Position("", "",
direction,
ticker,
new MoneyManagement(),
PositionInitiator.User,
gmxPosition.Date,
new User());
position.Open = new Trade(position.Date, direction, TradeStatus.Filled, TradeType.Market, ticker,
(decimal)gmxPosition.Quantity, (decimal)gmxPosition.Price, (decimal)gmxPosition.Leverage,
gmxPosition.Open.ExchangeOrderId, "");
if (gmxPosition.TakeProfit1 != null)
{
position.TakeProfit1 = Map(gmxPosition.TakeProfit1);
}
if (gmxPosition.StopLoss != null)
{
position.StopLoss = Map(gmxPosition.StopLoss);
}
position.ProfitAndLoss = new ProfitAndLoss()
{
Realized = (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;
}
}