fix: use raw SSE with local matching, bulk polling, block-based confirmations, and multi-tx support
This commit is contained in:
@@ -245,12 +245,20 @@
|
||||
pollInterval = setInterval(() => pollStatus(), 10000);
|
||||
}
|
||||
|
||||
/** Subscribe to Freedom.st SSE filtered by our payment address for instant detection. */
|
||||
let watchedAddress = null;
|
||||
let watchedTxids = [];
|
||||
|
||||
/** Listen to raw SSE for this coin, match tx outputs against our address locally.
|
||||
* Tracks multiple txids (user may send across several transactions).
|
||||
* On block, checks if any of our txids got confirmed. */
|
||||
function watchAddress(coin, address) {
|
||||
if (sseAbort) sseAbort.abort();
|
||||
sseAbort = new AbortController();
|
||||
watchedAddress = address;
|
||||
watchedTxids = [];
|
||||
|
||||
const query = { crypto: coin, "data.out.script.address": address };
|
||||
// Raw stream for this coin — all txs and blocks, no query filter
|
||||
const query = { crypto: coin };
|
||||
const q = btoa(JSON.stringify(query));
|
||||
const url = `${SOCK_API}/sse?q=${q}`;
|
||||
|
||||
@@ -275,7 +283,11 @@
|
||||
if (!line.startsWith('data: ')) continue;
|
||||
try {
|
||||
const event = JSON.parse(line.slice(6));
|
||||
onTxDetected(event);
|
||||
if (event.type === 'block') {
|
||||
onBlock(event);
|
||||
} else {
|
||||
onTx(event);
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
@@ -287,16 +299,34 @@
|
||||
})();
|
||||
}
|
||||
|
||||
function onTxDetected(event) {
|
||||
// Transaction matched our address filter — payment detected instantly
|
||||
console.log('TX detected via SSE:', event);
|
||||
const statusEl = document.getElementById('pay-status');
|
||||
statusEl.innerHTML = `
|
||||
<span class="w-2 h-2 rounded-full bg-blue-500 animate-pulse"></span>
|
||||
<span class="text-blue-400">Transaction detected, waiting for confirmation...</span>
|
||||
`;
|
||||
// Immediately poll the pay API to get authoritative status update
|
||||
pollStatus();
|
||||
/** Check if any tx output matches our payment address. */
|
||||
function onTx(event) {
|
||||
if (!watchedAddress) return;
|
||||
const outputs = event.data?.out ?? [];
|
||||
for (const out of outputs) {
|
||||
if (out?.script?.address !== watchedAddress) continue;
|
||||
const txHash = event.data?.tx?.hash ?? null;
|
||||
if (!txHash || watchedTxids.includes(txHash)) return;
|
||||
watchedTxids.push(txHash);
|
||||
console.log('SSE: tx detected for our address:', txHash, `(${watchedTxids.length} total)`);
|
||||
document.getElementById('pay-status').innerHTML = `
|
||||
<span class="w-2 h-2 rounded-full bg-blue-500 animate-pulse"></span>
|
||||
<span class="text-blue-400">Transaction detected, waiting for confirmation...</span>
|
||||
`;
|
||||
pollStatus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if a new block includes any of our confirming txids. */
|
||||
function onBlock(event) {
|
||||
if (watchedTxids.length === 0) return;
|
||||
const blockTxs = event.data?.tx ?? [];
|
||||
const found = watchedTxids.some(t => blockTxs.includes(t));
|
||||
if (found) {
|
||||
console.log('SSE: block contains one of our txids');
|
||||
pollStatus();
|
||||
}
|
||||
}
|
||||
|
||||
function updateCountdown(expiresAt) {
|
||||
@@ -369,6 +399,8 @@
|
||||
if (sseAbort) { sseAbort.abort(); sseAbort = null; }
|
||||
if (pollInterval) { clearInterval(pollInterval); pollInterval = null; }
|
||||
if (countdownInterval) { clearInterval(countdownInterval); countdownInterval = null; }
|
||||
watchedAddress = null;
|
||||
watchedTxids = [];
|
||||
document.getElementById('step-select').classList.remove('hidden');
|
||||
document.getElementById('step-pay').classList.add('hidden');
|
||||
document.getElementById('pay-success').classList.add('hidden');
|
||||
|
||||
Reference in New Issue
Block a user