diff options
| author | Adam Soltys <[email protected]> | 2026-08-22 09:10:10 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-08-22 09:10:10 -0700 |
| commit | 9963c4c45ccd33cc8588fd3c1cf816cf09a82c2b (patch) | |
| tree | cdc5d6ca684ae7e6e521c575a386b8b7c04bce71 /src/nwc-bg.js | |
| parent | 16a9e78080554774d8fec8a4f29d19f97fa3722a (diff) | |
| download | coinosv3-9963c4c45ccd33cc8588fd3c1cf816cf09a82c2b.tar.gz coinosv3-9963c4c45ccd33cc8588fd3c1cf816cf09a82c2b.zip | |
One record answers, and failure learns patience: a rewritten mirror disarms stale sibling copies of its connections, the responder pays from the record whose network the invoice names (standing down when none fits), a ghost coin reconciles and retries instead of dying, and error replies wait out a grace period so a sibling's success reaches the client first
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_017Fc8SHJRvBBXgMCntjNCri
Diffstat (limited to 'src/nwc-bg.js')
| -rw-r--r-- | src/nwc-bg.js | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/src/nwc-bg.js b/src/nwc-bg.js index b22c36e..92786c0 100644 --- a/src/nwc-bg.js +++ b/src/nwc-bg.js @@ -118,6 +118,31 @@ export const bgSpendableSat = (rec) => ((rec && rec.mgr && rec.mgr.vtxos) || []).filter((v) => v.state === 'spendable') .reduce((n, v) => n + (v.amountSat || 0), 0); +// After (re)writing a wallet's record: strip its connections/offer from any +// OTHER record that still carries them — an old network's mirror, say — so +// exactly one record ever answers for a connection. The sibling's coin state +// stays put for a later merge; only its answering role is removed. A stale +// copy that races the live one answers from the wrong wallet (and a wrong- +// network mirror fails instantly, beating the real payer's reply). +export async function disarmSiblingRecords(walletKey, rec, { loadAll = allBgs, save = saveBg } = {}) { + const pks = new Set((rec.connections || []).map((c) => c.servicePk)); + if (rec.offer?.pk) pks.add(rec.offer.pk); + if (!pks.size) return 0; + let disarmed = 0; + for (const r of await loadAll()) { + if (r.walletKey === walletKey || !r.rec || r.rec.v < 3) continue; + const conns = r.rec.connections || []; + const keep = conns.filter((c) => !pks.has(c.servicePk)); + const offerHit = !!(r.rec.offer?.pk && pks.has(r.rec.offer.pk)); + if (keep.length === conns.length && !offerHit) continue; + r.rec.connections = keep; + if (offerHit) r.rec.offer = null; + await save(r.walletKey, r.rec); + disarmed++; + } + return disarmed; +} + // The worker records what it spent so the app can absorb it into budgets and // history on next open. export async function noteBgSpend(walletKey, spend) { |
