Implement buffer logic for token swaps in GMX plugin

- Introduced a new buffer amount to prevent overdraw when requested swap amounts exceed wallet balances, enhancing balance management.
- Updated swap logic to apply the buffer conditionally, ensuring safe transaction amounts are used during swaps.
- Improved logging to provide warnings when requested amounts exceed available balances, enhancing user feedback and transparency.
This commit is contained in:
2026-01-06 16:54:10 +07:00
parent b928eac031
commit 97e99d44d4

View File

@@ -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