Fix ETH openPosition

This commit is contained in:
2025-08-16 19:12:20 +07:00
parent 955c358138
commit ab3e637ca7
5 changed files with 80 additions and 20 deletions

View File

@@ -170,7 +170,8 @@ public class TradingBotBase : ITradingBot
{
ExecutionCount++;
Logger.LogInformation("Bot Status - ServerDate: {ServerDate}, LastCandleDate: {LastCandleDate}, Signals: {SignalCount}, Executions: {ExecutionCount}, Positions: {PositionCount}",
Logger.LogInformation(
"Bot Status - ServerDate: {ServerDate}, LastCandleDate: {LastCandleDate}, Signals: {SignalCount}, Executions: {ExecutionCount}, Positions: {PositionCount}",
DateTime.UtcNow, LastCandle.Date, Signals.Count, ExecutionCount, Positions.Count);
}
}
@@ -1444,6 +1445,8 @@ public class TradingBotBase : ITradingBot
TradingExchanges.GmxV2,
IndicatorType.Stc, SignalType.Signal, "Manual Signal");
signal.Status = SignalStatus.WaitingForPosition; // Ensure status is correct
signal.Identifier =
signal.Identifier + "-manual" + Guid.NewGuid(); // Ensure unique identifier for manual signals
// Add the signal to our collection
await AddSignal(signal);

View File

@@ -52,7 +52,7 @@ public class LightSignal
[Id(5)] [Required] public Candle Candle { get; }
[Id(6)] [Required] public string Identifier { get; }
[Id(6)] [Required] public string Identifier { get; set; }
[Id(7)] [Required] public Ticker Ticker { get; }

View File

@@ -294,8 +294,19 @@ export const openGmxPositionImpl = async (
const marketInfo = getMarketInfoFromTicker(ticker, marketsInfoData);
const collateralToken = getTokenDataFromTicker("USDC", tokensData); // Using USDC as collateral
// For market orders, we need to get the current market price
let currentPrice = price;
if (!currentPrice) {
// Get current market price from market info
currentPrice = Number(marketInfo.indexToken.prices.minPrice) / 1e30; // Convert from 30 decimals
console.log(`No price provided, using current market price: ${currentPrice}`);
}
// Calculate the collateral amount in USDC (quantity * price)
const collateralAmount = BigInt(Math.floor((quantity || 0) * (price || 0) * 1e6)); // USDC has 6 decimals
const collateralAmount = BigInt(Math.floor((quantity || 0) * currentPrice * 1e6)); // USDC has 6 decimals
// Note: Wallet initialization should be done separately before opening positions
// This reduces position opening time and allows for better error handling
// Calculate leverage in basis points (1x = 10000)
const leverageBps = BigInt((leverage || 1) * 10000);
@@ -316,11 +327,23 @@ export const openGmxPositionImpl = async (
limitPrice: limitPrice,
};
console.log('📋 Position params:', {
payAmount: collateralAmount.toString(),
marketAddress: marketInfo.marketTokenAddress,
payTokenAddress: collateralToken.address,
collateralTokenAddress: collateralToken.address,
leverage: leverageBps.toString(),
direction: direction
});
console.log('🚀 Executing position order...');
if (direction === TradeDirection.Long) {
await sdk.orders.long(params);
} else {
await sdk.orders.short(params);
}
console.log('✅ Position order executed successfully');
return "";
} catch (error) {
@@ -485,12 +508,23 @@ export async function cancelGmxOrders(
}
function getMarketInfoFromTicker(ticker: string, marketsInfoData: MarketsInfoData): MarketInfo {
if (ticker === "ETH") {
ticker = "WETH";
}
const token = getTokenBySymbol(arbitrum.id, ticker);
const marketInfo = getMarketByIndexToken(token.address);
const marketInfoData = marketsInfoData[marketInfo.marketTokenAddress];
if (!marketInfo) {
throw new Error(`Market info not found for ticker: ${ticker}`);
}
const marketInfoData = marketsInfoData[marketInfo.marketTokenAddress];
if (!marketInfoData) {
throw new Error(`Market data not found for market: ${marketInfo.marketTokenAddress}`);
}
return marketInfoData;
}

View File

@@ -501,30 +501,31 @@ export const getTokenAllowance = async (
*/
export const initAddressImpl = async (
address: string,
): Promise<{ usdcHash: string, orderVaultHash: string, exchangeRouterHash: string }> => {
): Promise<{ usdcHash: string, orderVaultHash: string, exchangeRouterHash: string, wethSyntheticsRouterHash: string }> => {
try {
const sdk = await getClientForAddress(address);
const {tokensData} = await sdk.tokens.getTokensData();
const usdcTokenData = getTokenDataFromTicker(Ticker.USDC, tokensData);
const wrapperEtherData = getTokenDataFromTicker("WETH", tokensData);
let approveAmount = usdcTokenData.prices.maxPrice; // Large enough amount for trading
// Use max uint256 for unlimited approvals (more gas efficient than frequent approvals)
let approveAmount = BigInt("115792089237316195423570985008687907853269984665640564039457584007913129639935");
// Check approval for USDC
// Check approval for USDC (this first check is for general token approval, keeping original logic)
const usdcToken = GetToken('USDC');
const usdcAllowance = await getTokenAllowance(address, usdcToken.address, address);
let usdcHash = "";
if (usdcAllowance < approveAmount) {
// First approve USDC token for GMX trading
const usdcToken = GetToken('USDC');
usdcHash = await approveTokenImpl(
address,
usdcToken.symbol,
ARBITRUM,
usdcTokenData.prices.maxPrice
);
}else{
} else {
usdcHash = "Already allowed :" + usdcAllowance;
}
@@ -612,14 +613,34 @@ export const initAddressImpl = async (
console.log('usdcSyntheticRouterAllowance', usdcSyntheticRouterAllowance)
// Also approve WETH for SyntheticsRouter (required for ETH positions)
const wethSyntheticsRouterAllowance = await getTokenAllowance(address, wrapperEtherData.address, CONTRACTS[ARBITRUM].SyntheticsRouter);
let wethSyntheticsRouterHash = "";
if (wethSyntheticsRouterAllowance < approveAmount) {
wethSyntheticsRouterHash = await approveContractImpl(
address,
wrapperEtherData.address,
CONTRACTS[ARBITRUM].SyntheticsRouter,
ARBITRUM,
approveAmount
);
} else {
wethSyntheticsRouterHash = "Already allowed :" + wethSyntheticsRouterAllowance;
}
console.log('wethSyntheticsRouterAllowance', wethSyntheticsRouterAllowance)
console.log('usdcHash', usdcHash)
console.log('orderVaultHash', orderVaultHash)
console.log('exchangeRouterHash', exchangeRouterHash)
console.log('wethSyntheticsRouterHash', wethSyntheticsRouterHash)
return {
usdcHash,
orderVaultHash,
exchangeRouterHash
exchangeRouterHash,
wethSyntheticsRouterHash
};
} catch (error) {
console.error('Error initializing address:', error);
@@ -644,12 +665,14 @@ export async function initAddress(
throw new Error('Wallet address is required for initialization');
}
const { usdcHash, orderVaultHash } = await initAddressImpl(address);
const { usdcHash, orderVaultHash, exchangeRouterHash, wethSyntheticsRouterHash } = await initAddressImpl(address);
return {
success: true,
usdcHash,
orderVaultHash
orderVaultHash,
exchangeRouterHash,
wethSyntheticsRouterHash
};
} catch (error) {
this.log.error(error);

View File

@@ -1,7 +1,7 @@
import { test } from 'node:test'
import {test} from 'node:test'
import assert from 'node:assert'
import { getClientForAddress, openGmxPositionImpl } from '../../src/plugins/custom/gmx'
import { Ticker, TradeDirection } from '../../src/generated/ManagingApiTypes'
import {getClientForAddress, openGmxPositionImpl} from '../../src/plugins/custom/gmx'
import {Ticker, TradeDirection} from '../../src/generated/ManagingApiTypes'
test('GMX Position Opening', async (t) => {
await t.test('should open a long position for BTC', async () => {
@@ -9,13 +9,13 @@ test('GMX Position Opening', async (t) => {
const result = await openGmxPositionImpl(
sdk,
Ticker.BTC,
Ticker.ETH,
TradeDirection.Long,
0.0002,
0.00678,
2,
50003,
96001,
85002
4400,
6000,
3500
)
console.log('Position opening result:', result)
assert.ok(result, 'Position opening result should be defined')