Phone-run fixes: hash tokens, embed wakes on tab focus, dry faucet leaves drips due (+admin retry), short drip status, claim box wraps; one drip per wallet per mission

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-19 17:57:20 -05:00
parent 438b903bd3
commit fd72ea1b84
9 changed files with 42 additions and 24 deletions
+11 -2
View File
@@ -30,16 +30,25 @@ async function tick(notify) {
let paid = 0;
try {
const due = rewards.payable();
// a dry faucet is not a failed drip: check the balance first, leave the drips due, alert once
let bal0 = null; try { bal0 = await balance(); } catch (e) {}
if (bal0 != null && due.length) {
const need = due.reduce((n, p) => n + p.pol, 0) + 0.01;
if (bal0 < due[0].pol + 0.005) { if (notify) { const st = store.read('faucet-state', {}); const day = new Date().toLocaleDateString('en-CA', { timeZone: 'America/Chicago' }); if (st.dryAlertDay !== day) { st.dryAlertDay = day; store.write('faucet-state', st); await notify('low', { balance: bal0, threshold: need, address: wallet.address }); } } ticking = false; return { paid: 0, waiting: due.length, balance: bal0 }; }
}
for (const p of due) {
if (bal0 != null && bal0 < p.pol + 0.005) break; // pay what the balance covers, leave the rest due
if (!p.wallet || !/^0x[a-f0-9]{40}$/i.test(p.wallet)) { rewards.mark(p.id, { status: 'failed', error: 'no wallet on the account' }); continue; }
try {
const tx = await wallet.sendTransaction({ to: p.wallet, value: ethers.parseEther(String(p.pol)) });
rewards.mark(p.id, { status: 'sent', tx: tx.hash });
const rc = await tx.wait(1);
rewards.mark(p.id, { status: rc && rc.status === 1 ? 'paid' : 'failed', paidAt: Date.now(), error: rc && rc.status === 1 ? null : 'reverted' });
if (rc && rc.status === 1) { paid++; if (notify) await notify('paid', Object.assign({}, p, { tx: tx.hash })); }
if (rc && rc.status === 1) { paid++; if (bal0 != null) bal0 -= p.pol; if (notify) await notify('paid', Object.assign({}, p, { tx: tx.hash })); }
} catch (e) {
rewards.mark(p.id, { status: 'failed', error: String(e.message || e).slice(0, 200) });
const msg = String(e.message || e);
if (/insufficient funds/i.test(msg)) { rewards.mark(p.id, { status: 'due', error: null }); break; } // dry: leave it due, stop this pass
rewards.mark(p.id, { status: 'failed', error: msg.slice(0, 200) });
if (notify) await notify('failed', Object.assign({}, p, { error: String(e.message || e).slice(0, 200) }));
}
}