From 49de5c60e99a75a2a86d36f02097f0ff53134d3d Mon Sep 17 00:00:00 2001 From: direkturcrypto Date: Fri, 3 Apr 2026 13:22:08 +0700 Subject: [PATCH] fix: auto-redeem after ghost recovery when holding expensive side MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When ghost fill recovery decides to hold the expensive side (not sell), set pos.holdingSide so the existing waitAndRedeem flow picks it up after executeMakerRebateStrategy — same path as CANCEL_CHEAP_ON_EXP_FILL. Co-Authored-By: Claude Sonnet 4.6 --- src/services/makerRebateExecutor.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/services/makerRebateExecutor.js b/src/services/makerRebateExecutor.js index 5cc752d..f5f1799 100644 --- a/src/services/makerRebateExecutor.js +++ b/src/services/makerRebateExecutor.js @@ -225,21 +225,24 @@ async function recoverFromGhostFill(pos, yesShares, noShares, tag) { if (yesRemainder >= 1) { if (expSide === 'yes') { - logger.warn(`MakerMM${tag}: ghost recovery — holding YES remainder ${yesRemainder.toFixed(4)} (expensive $${pos.yes.buyPrice}, not market-selling)`); + logger.warn(`MakerMM${tag}: ghost recovery — holding YES remainder ${yesRemainder.toFixed(4)} (expensive $${pos.yes.buyPrice}, scheduling redeem after resolution)`); + pos.holdingSide = 'yes'; } else { await marketSellToken(pos.yes.tokenId, yesRemainder, pos.tickSize, pos.negRisk, tag); } } if (noRemainder >= 1) { if (expSide === 'no') { - logger.warn(`MakerMM${tag}: ghost recovery — holding NO remainder ${noRemainder.toFixed(4)} (expensive $${pos.no.buyPrice}, not market-selling)`); + logger.warn(`MakerMM${tag}: ghost recovery — holding NO remainder ${noRemainder.toFixed(4)} (expensive $${pos.no.buyPrice}, scheduling redeem after resolution)`); + pos.holdingSide = 'no'; } else { await marketSellToken(pos.no.tokenId, noRemainder, pos.tickSize, pos.negRisk, tag); } } pos.totalProfit = mergeRecovered - (pos.yes.cost + pos.no.cost); - pos.status = 'done'; + // Don't mark done if holding expensive side — waitAndRedeem will close it out + if (!pos.holdingSide) pos.status = 'done'; } async function placeLimitBuy(tokenId, shares, price, tickSize, negRisk) {