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:
@@ -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,22 +3249,44 @@ 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
|
||||
const verifiedFromTokenAmount = finalSwapAmount;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user