From f5430774e972c3e40cb18b732565de7c96e1063f Mon Sep 17 00:00:00 2001 From: heyitsStylez Date: Mon, 11 May 2026 13:46:53 +0800 Subject: [PATCH] Fix auto-detect outcomes missing corrected trades + silent failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs in autoDetectOutcomes flow: 1. syncRysk corrected path (OPEN→EXPIRED for already-synced trades) never fed into autoDetectOutcomes, so re-synced expired options were never upgraded to CALLED/ASSIGNED 2. CoinGecko price lookup failures were silent — outcome stayed EXPIRED with no user-facing signal to check manually Fix: collect correctedTrades alongside expiredNew before calling autoDetectOutcomes; toast when price lookup returns null. Co-Authored-By: Claude Sonnet 4.6 --- src/js/18-chain-sync.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/js/18-chain-sync.js b/src/js/18-chain-sync.js index 37313c5..2788d95 100644 --- a/src/js/18-chain-sync.js +++ b/src/js/18-chain-sync.js @@ -112,9 +112,10 @@ async function syncRysk(address) { throw e; } - const synced = loadSynced(); - const newTrades = []; - let corrected = 0; + const synced = loadSynced(); + const newTrades = []; + const correctedTrades = []; + let corrected = 0; for (const r of (positions || [])) { if (r.txHash && synced.has(r.txHash)) { @@ -126,6 +127,7 @@ async function syncRysk(address) { const existing = trades.find(t => t.txHash === r.txHash); if (existing && existing.outcome === 'OPEN') { existing.outcome = 'EXPIRED'; + correctedTrades.push(existing); corrected++; } } @@ -148,9 +150,12 @@ async function syncRysk(address) { save(); render(); saveSynced(synced); - const expiredNew = openTrades.filter(t => t.outcome === 'EXPIRED'); - if (expiredNew.length) { - autoDetectOutcomes(expiredNew).then(changed => { if (changed) { save(); render(); } }); + const toDetect = [ + ...openTrades.filter(t => t.outcome === 'EXPIRED'), + ...correctedTrades, + ]; + if (toDetect.length) { + autoDetectOutcomes(toDetect).then(changed => { if (changed) { save(); render(); } }); } } @@ -390,14 +395,18 @@ async function autoDetectOutcomes(newTrades) { } let changed = false; + let unresolved = 0; for (const t of toCheck) { const spot = priceCache[t.asset + '|' + t.expiry]; - if (spot == null) continue; + if (spot == null) { unresolved++; continue; } const trade = trades.find(tr => tr.id === t.id); if (!trade || trade.outcome !== 'EXPIRED') continue; if (t.type === 'CALL' && spot >= t.strike) { trade.outcome = 'CALLED'; changed = true; } if (t.type === 'PUT' && spot <= t.strike) { trade.outcome = 'ASSIGNED'; changed = true; } } + if (unresolved > 0) { + toast(unresolved + ' expired option' + (unresolved > 1 ? 's' : '') + ' — verify outcome manually', 'info'); + } return changed; }