diff --git a/src/Managing.Web3Proxy/src/plugins/custom/gmx.ts b/src/Managing.Web3Proxy/src/plugins/custom/gmx.ts index 6e843e62..bf43794e 100644 --- a/src/Managing.Web3Proxy/src/plugins/custom/gmx.ts +++ b/src/Managing.Web3Proxy/src/plugins/custom/gmx.ts @@ -69,6 +69,7 @@ const OPERATION_TIMEOUT = 60000; // 60 seconds timeout for operations (increased const MEMORY_WARNING_THRESHOLD = 0.85; // Warn when memory usage exceeds 85% const MEMORY_CLEAR_THRESHOLD = 0.95; // Clear cache when memory usage exceeds 95% const MAX_GAS_FEE_USD = 1.5; // Maximum gas fee in USD (1 USDC) +const SWAP_BALANCE_BUFFER = 0.01; // Buffer amount to subtract when requested amount exceeds wallet balance (in token units) // Memory monitoring function function checkMemoryUsage() { @@ -3169,8 +3170,21 @@ export const swapGmxTokensImpl = async ( const tolerance = 0.000001; const difference = Math.abs(walletBalanceNumber - requestedAmountNumber); - // Use actual balance if amounts are very close (likely trying to swap entire balance) - const fromTokenAmount = difference <= tolerance ? walletBalance : requestedAmountBigInt; + // Determine the swap amount: + // - If requested <= wallet balance: use requested amount (no buffer) + // - If requested > wallet balance: apply buffer (wallet balance - buffer) to avoid overdraw + let fromTokenAmount: bigint; + if (requestedAmountNumber <= walletBalanceNumber) { + // Normal case: user has enough balance, use requested amount (or actual balance if very close) + fromTokenAmount = difference <= tolerance ? walletBalance : requestedAmountBigInt; + } else { + // Edge case: requested amount exceeds wallet balance, apply buffer + const bufferAmountBigInt = BigInt(Math.floor(SWAP_BALANCE_BUFFER * Math.pow(10, fromTokenData.decimals))); + const maxSafeAmount = walletBalance > bufferAmountBigInt ? walletBalance - bufferAmountBigInt : 0n; + fromTokenAmount = maxSafeAmount; + + console.log(`⚠️ Requested amount (${requestedAmountNumber.toFixed(6)}) exceeds wallet balance (${walletBalanceNumber.toFixed(6)}). Applying buffer: ${SWAP_BALANCE_BUFFER} ${fromTicker}`); + } console.log('💰 Wallet balance check:', { fromTicker, @@ -3235,20 +3249,42 @@ export const swapGmxTokensImpl = async ( ); } - // Re-calculate final amount using latest balance if we're using actual balance + // Re-calculate final amount using latest balance + // Apply the same logic: buffer only if requested > balance const latestBalanceNumber = Number(latestWalletBalance) / Math.pow(10, fromTokenData.decimals); const latestDifference = Math.abs(latestBalanceNumber - requestedAmountNumber); - const finalSwapAmount = latestDifference <= tolerance ? latestWalletBalance : fromTokenAmount; + + let finalSwapAmount: bigint; + if (requestedAmountNumber <= latestBalanceNumber) { + // Normal case: use requested amount (or actual balance if very close) + finalSwapAmount = latestDifference <= tolerance ? latestWalletBalance : fromTokenAmount; + } else { + // Edge case: requested amount exceeds latest balance, apply buffer + const bufferAmountBigInt = BigInt(Math.floor(SWAP_BALANCE_BUFFER * Math.pow(10, fromTokenData.decimals))); + const maxSafeAmount = latestWalletBalance > bufferAmountBigInt ? latestWalletBalance - bufferAmountBigInt : 0n; + finalSwapAmount = maxSafeAmount; + + console.log(`⚠️ Requested amount (${requestedAmountNumber.toFixed(6)}) exceeds latest wallet balance (${latestBalanceNumber.toFixed(6)}). Applying buffer: ${SWAP_BALANCE_BUFFER} ${fromTicker}`); + } // Verify we still have enough after re-check + // This check should never fail now since we apply buffer when needed, but keep it as a safety net if (latestWalletBalance < finalSwapAmount) { + // If this happens, it means buffer wasn't applied correctly - apply it now as fallback + const bufferAmountBigInt = BigInt(Math.floor(SWAP_BALANCE_BUFFER * Math.pow(10, fromTokenData.decimals))); + const maxSafeAmount = latestWalletBalance > bufferAmountBigInt ? latestWalletBalance - bufferAmountBigInt : 0n; + + if (maxSafeAmount === 0n) { const latestBalanceFormatted = Number(latestWalletBalance) / Math.pow(10, fromTokenData.decimals); - const requestedFormatted = Number(finalSwapAmount) / Math.pow(10, fromTokenData.decimals); throw new Error( - `Insufficient ${fromTicker} balance after verification! Wallet has ${latestBalanceFormatted.toFixed(6)} ${fromTicker} ` + - `but trying to swap ${requestedFormatted.toFixed(6)} ${fromTicker}. ` + + `Insufficient ${fromTicker} balance! Wallet has ${latestBalanceFormatted.toFixed(6)} ${fromTicker} ` + + `which is less than the buffer amount (${SWAP_BALANCE_BUFFER} ${fromTicker}). ` + `Please ensure you have sufficient balance.` ); + } + + console.log(`⚠️ Fallback: Applying buffer to final swap amount due to balance mismatch`); + finalSwapAmount = maxSafeAmount; } // Update fromTokenAmount to use the final verified amount