Filter everything with users (#16)
* Filter everything with users * Fix backtests and user management * Add cursor rules * Fix backtest and bots * Update configs names * Sign until unauth * Setup delegate * Setup delegate and sign * refact * Enhance Privy signature generation with improved cryptographic methods * Add Fastify backend * Add Fastify backend routes for privy * fix privy signing * fix privy client * Fix tests * add gmx core * fix merging sdk * Fix tests * add gmx core * add gmx core * add privy to boilerplate * clean * fix * add fastify * Remove Managing.Fastify submodule * Add Managing.Fastify as regular directory instead of submodule * Update .gitignore to exclude Managing.Fastify dist and node_modules directories * Add token approval functionality to Privy plugin - Introduced a new endpoint `/approve-token` for approving ERC20 tokens. - Added `approveToken` method to the Privy plugin for handling token approvals. - Updated `signPrivyMessage` to differentiate between message signing and token approval requests. - Enhanced the plugin with additional schemas for input validation. - Included new utility functions for token data retrieval and message construction. - Updated tests to verify the new functionality and ensure proper request decoration. * Add PrivyApproveTokenResponse model for token approval response - Created a new class `PrivyApproveTokenResponse` to encapsulate the response structure for token approval requests. - The class includes properties for `Success` status and a transaction `Hash`. * Refactor trading commands and enhance API routes - Updated `OpenPositionCommandHandler` to use asynchronous methods for opening trades and canceling orders. - Introduced new Fastify routes for opening positions and canceling orders with appropriate request validation. - Modified `EvmManager` to handle both Privy and non-Privy wallet operations, utilizing the Fastify API for Privy wallets. - Adjusted test configurations to reflect changes in account types and added helper methods for testing Web3 proxy services. * Enhance GMX trading functionality and update dependencies - Updated `dev:start` script in `package.json` to include the `-d` flag for Fastify. - Upgraded `fastify-cli` dependency to version 7.3.0. - Added `sourceMap` option to `tsconfig.json`. - Refactored GMX plugin to improve position opening logic, including enhanced error handling and validation. - Introduced a new method `getMarketInfoFromTicker` for better market data retrieval. - Updated account type in `PrivateKeys.cs` to use `Privy`. - Adjusted `EvmManager` to utilize the `direction` enum directly for trade direction handling. * Refactor GMX plugin for improved trading logic and market data retrieval - Enhanced the `openGmxPositionImpl` function to utilize the `TradeDirection` enum for trade direction handling. - Introduced `getTokenDataFromTicker` and `getMarketByIndexToken` functions for better market and token data retrieval. - Updated collateral calculation and logging for clarity. - Adjusted `EvmManager` to ensure proper handling of price values in trade requests. * Refactor GMX plugin and enhance testing for position opening - Updated `test:single` script in `package.json` to include TypeScript compilation before running tests. - Removed `this` context from `getClientForAddress` function and replaced logging with `console.error`. - Improved collateral calculation in `openGmxPositionImpl` for better precision. - Adjusted type casting for `direction` in the API route to utilize `TradeDirection` enum. - Added a new test for opening a long position in GMX, ensuring functionality and correctness. * Update sdk * Update * update fastify * Refactor start script in package.json to simplify command execution - Removed the build step from the start script, allowing for a more direct launch of the Fastify server. * Update package.json for Web3Proxy - Changed the name from "Web3Proxy" to "web3-proxy". - Updated version from "0.0.0" to "1.0.0". - Modified the description to "The official Managing Web3 Proxy". * Update Dockerfile for Web3Proxy - Upgraded Node.js base image from 18-alpine to 22.14.0-alpine. - Added NODE_ENV environment variable set to production. * Refactor Dockerfile and package.json for Web3Proxy - Removed the build step from the Dockerfile to streamline the image creation process. - Updated the start script in package.json to include the build step, ensuring the application is built before starting the server. * Add fastify-tsconfig as a development dependency in Dockerfile-web3proxy * Remove fastify-tsconfig extension from tsconfig.json for Web3Proxy * Add PrivyInitAddressResponse model for handling initialization responses - Introduced a new class `PrivyInitAddressResponse` to encapsulate the response structure for Privy initialization, including properties for success status, USDC hash, order vault hash, and error message. * Update * Update * Remove fastify-tsconfig installation from Dockerfile-web3proxy * Add build step to Dockerfile-web3proxy - Included `npm run build` in the Dockerfile to ensure the application is built during the image creation process. * Update * approvals * Open position from front embedded wallet * Open position from front embedded wallet * Open position from front embedded wallet * Fix call contracts * Fix limit price * Close position * Fix close position * Fix close position * add pinky * Refactor position handling logic * Update Dockerfile-pinky to copy package.json and source code from the correct directory * Implement password protection modal and enhance UI with new styles; remove unused audio elements and update package dependencies. * add cancel orders * Update callContract function to explicitly cast account address as Address type * Update callContract function to cast transaction parameters as any type for compatibility * Cast transaction parameters as any type in approveTokenImpl for compatibility * Cast wallet address and transaction parameters as Address type in approveTokenImpl for type safety * Add .env configuration file for production setup including database and server settings * Refactor home route to update welcome message and remove unused SDK configuration code * add referral code * fix referral * Add sltp * Fix typo * Fix typo * setup sltp on backtend * get orders * get positions with slp * fixes * fixes close position * fixes * Remove MongoDB project references from Dockerfiles for managing and worker APIs * Comment out BotManagerWorker service registration and remove MongoDB project reference from Dockerfile * fixes
This commit is contained in:
@@ -11,6 +11,8 @@ using Managing.Domain.Trades;
|
||||
using Managing.Infrastructure.Evm.Abstractions;
|
||||
using Managing.Infrastructure.Evm.Models;
|
||||
using Managing.Infrastructure.Evm.Models.Gmx.v2;
|
||||
using Managing.Infrastructure.Evm.Models.Privy;
|
||||
using Managing.Infrastructure.Evm.Models.Proxy;
|
||||
using Managing.Infrastructure.Evm.Referentials;
|
||||
using Managing.Infrastructure.Evm.Services;
|
||||
using Managing.Infrastructure.Evm.Services.Gmx;
|
||||
@@ -26,6 +28,7 @@ using BalanceOfFunction = Nethereum.Contracts.Standards.ERC20.ContractDefinition
|
||||
using BalanceOfOutputDTO = Nethereum.Contracts.Standards.ERC20.ContractDefinition.BalanceOfOutputDTO;
|
||||
using Chain = Managing.Domain.Evm.Chain;
|
||||
using TransferEventDTO = Nethereum.Contracts.Standards.ERC721.ContractDefinition.TransferEventDTO;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Managing.Infrastructure.Evm;
|
||||
|
||||
@@ -37,7 +40,7 @@ public class EvmManager : IEvmManager
|
||||
private readonly IEnumerable<ISubgraphPrices> _subgraphs;
|
||||
private Dictionary<string, Dictionary<string, decimal>> _geckoPrices;
|
||||
private readonly GmxV2Service _gmxV2Service;
|
||||
private readonly IPrivyService _privyService;
|
||||
private readonly IWeb3ProxyService _web3ProxyService;
|
||||
|
||||
private readonly List<Ticker> _eligibleTickers = new List<Ticker>()
|
||||
{
|
||||
@@ -45,13 +48,14 @@ public class EvmManager : IEvmManager
|
||||
Ticker.PEPE, Ticker.DOGE, Ticker.UNI
|
||||
};
|
||||
|
||||
public EvmManager(IEnumerable<ISubgraphPrices> subgraphs, IPrivyService privyService)
|
||||
public EvmManager(IEnumerable<ISubgraphPrices> subgraphs,
|
||||
IWeb3ProxyService web3ProxyService)
|
||||
{
|
||||
var defaultChain = ChainService.GetEthereum();
|
||||
_web3 = new Web3(defaultChain.RpcUrl);
|
||||
_httpClient = new HttpClient();
|
||||
_subgraphs = subgraphs;
|
||||
_privyService = privyService;
|
||||
_web3ProxyService = web3ProxyService;
|
||||
_geckoPrices = _geckoPrices != null && _geckoPrices.Any()
|
||||
? _geckoPrices
|
||||
: new Dictionary<string, Dictionary<string, decimal>>();
|
||||
@@ -426,19 +430,20 @@ public class EvmManager : IEvmManager
|
||||
return lastPrices.Last();
|
||||
}
|
||||
|
||||
public async Task<bool> InitAddress(string chainName, string publicAddress, string privateKey)
|
||||
public async Task<bool> InitAddress(string publicAddress)
|
||||
{
|
||||
try
|
||||
{
|
||||
var chain = ChainService.GetChain(chainName);
|
||||
var account = new Wallet(privateKey, _password).GetAccount(publicAddress);
|
||||
var web3 = new Web3(account, chain.RpcUrl);
|
||||
var tickers = await GetAvailableTicker();
|
||||
await GmxService.InitAccountForTrading(web3, publicAddress, tickers);
|
||||
return true;
|
||||
var response = await _web3ProxyService.CallPrivyServiceAsync<PrivyInitAddressResponse>(
|
||||
"/init-address",
|
||||
new { address = publicAddress });
|
||||
|
||||
return response.Success;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log the error
|
||||
Console.Error.WriteLine($"Error initializing address: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -512,12 +517,34 @@ public class EvmManager : IEvmManager
|
||||
|
||||
public async Task<bool> CancelOrders(Account account, Ticker ticker)
|
||||
{
|
||||
var wallet = new Wallet(account.Secret, _password).GetAccount(account.Key);
|
||||
var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
|
||||
var web3 = new Web3(wallet, chain.RpcUrl);
|
||||
// return await GmxService.CancelOrders(web3, account.Key, ticker);
|
||||
var service = new GmxV2Service();
|
||||
return await service.CancelOrders(web3, account.Key, ticker);
|
||||
if (account.IsPrivyWallet)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _web3ProxyService.CallGmxServiceAsync<dynamic>("/cancel-orders",
|
||||
new
|
||||
{
|
||||
account = account.Key,
|
||||
walletId = account.Secret,
|
||||
ticker = ticker.ToString()
|
||||
});
|
||||
|
||||
return response.success ?? false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Error.WriteLine($"Error canceling orders via Fastify API: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var wallet = new Wallet(account.Secret, _password).GetAccount(account.Key);
|
||||
var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
|
||||
var web3 = new Web3(wallet, chain.RpcUrl);
|
||||
var service = new GmxV2Service();
|
||||
return await service.CancelOrders(web3, account.Key, ticker);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Trade> IncreasePosition(
|
||||
@@ -526,17 +553,67 @@ public class EvmManager : IEvmManager
|
||||
TradeDirection direction,
|
||||
decimal price,
|
||||
decimal quantity,
|
||||
decimal? leverage)
|
||||
decimal? leverage,
|
||||
decimal? stopLossPrice = null,
|
||||
decimal? takeProfitPrice = null)
|
||||
{
|
||||
var wallet = new Wallet(account.Secret, _password).GetAccount(account.Key);
|
||||
var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
|
||||
var web3 = new Web3(wallet, chain.RpcUrl);
|
||||
|
||||
Trade trade = null;
|
||||
|
||||
try
|
||||
{
|
||||
trade = await _gmxV2Service.IncreasePosition(web3, account.Key, ticker, direction, price, quantity,
|
||||
leverage);
|
||||
// If this is a Privy wallet, call the GMX service through Fastify API
|
||||
if (account.IsPrivyWallet)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _web3ProxyService.CallGmxServiceAsync<object>("/open-position",
|
||||
new
|
||||
{
|
||||
account = account.Key,
|
||||
walletId = account.Secret,
|
||||
tradeType = price > 0 ? "limit" : "market",
|
||||
ticker = ticker.ToString(),
|
||||
direction = direction.ToString(),
|
||||
price = price,
|
||||
quantity,
|
||||
leverage = leverage ?? 1.0m,
|
||||
stopLossPrice = stopLossPrice,
|
||||
takeProfitPrice = takeProfitPrice
|
||||
});
|
||||
|
||||
// Create a trade object using the returned hash
|
||||
var tradeType = price > 0 ? TradeType.Limit : TradeType.Market;
|
||||
var tradeStatus = TradeStatus.Requested; // Use a valid enum value that exists in TradeStatus
|
||||
|
||||
trade = new Trade(
|
||||
DateTime.UtcNow,
|
||||
direction,
|
||||
tradeStatus,
|
||||
tradeType,
|
||||
ticker,
|
||||
quantity,
|
||||
price,
|
||||
leverage ?? 1.0m,
|
||||
account.Key,
|
||||
""
|
||||
);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Continue with the existing direct service call for non-Privy wallets
|
||||
var wallet = new Wallet(account.Secret, _password).GetAccount(account.Key);
|
||||
var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
|
||||
var web3 = new Web3(wallet, chain.RpcUrl);
|
||||
|
||||
trade = await _gmxV2Service.IncreasePosition(web3, account.Key, ticker, direction, price, quantity,
|
||||
leverage);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -554,11 +631,45 @@ public class EvmManager : IEvmManager
|
||||
decimal quantity,
|
||||
decimal? leverage)
|
||||
{
|
||||
Trade trade = null;
|
||||
|
||||
if (account.IsPrivyWallet)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _web3ProxyService.CallGmxServiceAsync<ClosePositionResponse>("/close-position",
|
||||
new
|
||||
{
|
||||
account = account.Key,
|
||||
ticker = ticker.ToString(),
|
||||
direction = direction.ToString(),
|
||||
});
|
||||
trade = new Trade(
|
||||
DateTime.UtcNow,
|
||||
direction,
|
||||
TradeStatus.Requested,
|
||||
TradeType.Market,
|
||||
ticker,
|
||||
quantity,
|
||||
price,
|
||||
leverage ?? 1,
|
||||
response.Hash,
|
||||
""
|
||||
);
|
||||
|
||||
return trade;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
var wallet = new Wallet(account.Secret, _password).GetAccount(account.Key);
|
||||
var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
|
||||
var web3 = new Web3(wallet, chain.RpcUrl);
|
||||
|
||||
Trade trade = null;
|
||||
try
|
||||
{
|
||||
trade = await _gmxV2Service.DecreasePosition(web3, account.Key, ticker, direction, price, quantity,
|
||||
@@ -573,7 +684,9 @@ public class EvmManager : IEvmManager
|
||||
}
|
||||
|
||||
public async Task<Trade> DecreaseOrder(Account account, TradeType tradeType, Ticker ticker,
|
||||
TradeDirection direction, decimal price, decimal quantity, decimal? leverage)
|
||||
TradeDirection direction, decimal price, decimal quantity, decimal? leverage,
|
||||
decimal? stopLossPrice = null,
|
||||
decimal? takeProfitPrice = null)
|
||||
{
|
||||
var wallet = new Wallet(account.Secret, _password).GetAccount(account.Key);
|
||||
var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
|
||||
@@ -582,8 +695,11 @@ public class EvmManager : IEvmManager
|
||||
Trade trade;
|
||||
try
|
||||
{
|
||||
trade = await GmxService.DecreaseOrder(web3, tradeType, account.Key, ticker, direction, price, quantity,
|
||||
leverage);
|
||||
// TODO: This method in GmxV2Service might not exist or needs different handling for Privy wallets.
|
||||
// Commenting out for now as IncreasePosition is the priority.
|
||||
// trade = await _gmxV2Service.DecreaseOrder(web3, account.Key, tradeType, ticker, direction, price,
|
||||
// quantity, leverage);
|
||||
trade = null; // Placeholder return
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -595,6 +711,34 @@ public class EvmManager : IEvmManager
|
||||
|
||||
public async Task<Trade> GetTrade(Account account, string chainName, Ticker ticker)
|
||||
{
|
||||
if (account.IsPrivyWallet)
|
||||
{
|
||||
var result = await _web3ProxyService.GetGmxServiceAsync<GetGmxPositionsResponse>(
|
||||
"/positions",
|
||||
new { account = account.Key, ticker = ticker.ToString() });
|
||||
|
||||
var position = result.Positions.FirstOrDefault(p => p.Ticker == ticker.ToString());
|
||||
|
||||
if (position == null)
|
||||
return null;
|
||||
|
||||
// TODO: Map the position object to a Trade object
|
||||
var trade = new Trade(
|
||||
position.Date,
|
||||
MiscExtensions.ParseEnum<TradeDirection>(position.Direction),
|
||||
MiscExtensions.ParseEnum<TradeStatus>(position.Status),
|
||||
MiscExtensions.ParseEnum<TradeType>(position.TradeType),
|
||||
MiscExtensions.ParseEnum<Ticker>(position.Ticker),
|
||||
(decimal)position.Quantity,
|
||||
(decimal)position.Price,
|
||||
(decimal?)position.Leverage,
|
||||
account.Key,
|
||||
position.ExchangeOrderId
|
||||
);
|
||||
|
||||
return trade;
|
||||
}
|
||||
|
||||
return await GetTrade(account.Key, chainName, ticker);
|
||||
}
|
||||
|
||||
@@ -608,12 +752,7 @@ public class EvmManager : IEvmManager
|
||||
|
||||
public async Task<List<FundingRate>> GetFundingRates()
|
||||
{
|
||||
var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
|
||||
var web3 = new Web3(chain.RpcUrl);
|
||||
var service = new GmxV2Service();
|
||||
var fundingRates = await service.GetFundingRates(web3);
|
||||
|
||||
return fundingRates;
|
||||
return await _web3ProxyService.CallGmxServiceAsync<List<FundingRate>>("/gmx/funding-rates", new { });
|
||||
}
|
||||
|
||||
public async Task<decimal> QuantityInPosition(string chainName, string publicAddress, Ticker ticker)
|
||||
@@ -635,17 +774,39 @@ public class EvmManager : IEvmManager
|
||||
|
||||
public async Task<List<Trade>> GetOrders(Account account, Ticker ticker)
|
||||
{
|
||||
var wallet = new Wallet(account.Secret, _password).GetAccount(account.Key);
|
||||
var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
|
||||
var web3 = new Web3(wallet, chain.RpcUrl);
|
||||
// var orders = await GmxService.GetOrders(web3, account.Key, ticker);
|
||||
var orders = await _gmxV2Service.GetOrders(web3, account.Key, ticker);
|
||||
if (account.IsPrivyWallet)
|
||||
{
|
||||
var orders = await _web3ProxyService.CallGmxServiceAsync<List<Trade>>("/get-orders",
|
||||
new { address = account.Key, walletId = account.Secret, ticker = ticker.ToString() });
|
||||
|
||||
return GmxV2Mappers.Map(orders);
|
||||
return orders;
|
||||
}
|
||||
else
|
||||
{
|
||||
var chain = ChainService.GetChain(Constants.Chains.Arbitrum);
|
||||
var web3 = new Web3(chain.RpcUrl);
|
||||
// var orders = await GmxService.GetOrders(web3, account.Key, ticker);
|
||||
var orders = await _gmxV2Service.GetOrders(web3, account.Key, ticker);
|
||||
|
||||
return GmxV2Mappers.Map(orders);
|
||||
}
|
||||
|
||||
return new List<Trade>();
|
||||
}
|
||||
|
||||
public async Task<bool> SetAllowance(Account account, Ticker ticker, BigInteger amount)
|
||||
{
|
||||
if (account.IsPrivyWallet)
|
||||
{
|
||||
var allowance = await _web3ProxyService.CallPrivyServiceAsync<PrivyApproveTokenResponse>("/approve-token",
|
||||
new
|
||||
{
|
||||
address = account.Key, walletId = account.Secret, ticker = ticker.ToString(),
|
||||
amount = amount.Equals(0) ? null : amount.ToString()
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
var web3 = BuildWeb3ForAccount(account);
|
||||
var contractAddress = TokenService.GetContractAddress(ticker);
|
||||
var approval = await EvmBase.ApproveToken(web3, account.Key, contractAddress,
|
||||
@@ -663,7 +824,29 @@ public class EvmManager : IEvmManager
|
||||
|
||||
public async Task<(string Id, string Address)> CreatePrivyWallet()
|
||||
{
|
||||
var privyWallet = await _privyService.CreateWalletAsync();
|
||||
var privyWallet = await _web3ProxyService.CallPrivyServiceAsync<PrivyWallet>("/privy/create-wallet", new { });
|
||||
return (privyWallet.Id, privyWallet.Address);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signs a message using the embedded wallet
|
||||
/// </summary>
|
||||
/// <param name="embeddedWalletId">The wallet id of the embedded wallet</param>
|
||||
/// <param name="address">The address of the embedded wallet</param>
|
||||
/// <param name="message">The message to sign</param>
|
||||
/// <returns>The signature response</returns>
|
||||
public async Task<string> SignMessageAsync(string embeddedWalletId, string address, string message)
|
||||
{
|
||||
// Construct the request body using the exact format from Privy documentati
|
||||
var requestBody = new
|
||||
{
|
||||
address = address,
|
||||
walletId = embeddedWalletId,
|
||||
message = message,
|
||||
};
|
||||
|
||||
var response =
|
||||
await _web3ProxyService.CallPrivyServiceAsync<PrivySigningResponse>("sign-message", requestBody);
|
||||
return response.Signature;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user