Fix ETH openPosition
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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')
|
||||
|
||||
Reference in New Issue
Block a user