diff options
| author | Adam Soltys <[email protected]> | 2026-09-02 08:32:13 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-02 08:32:13 -0700 |
| commit | acd6ca748f1fc4b31648fb999e2f9342cbf5c8a1 (patch) | |
| tree | bd1f3108ecf9cce7bd0bdd1f0ca849925b9404d7 /names | |
| parent | 21418741adfa8d16c53a20a5cc0d2d78a758ed89 (diff) | |
| download | coinosv3-acd6ca748f1fc4b31648fb999e2f9342cbf5c8a1.tar.gz coinosv3-acd6ca748f1fc4b31648fb999e2f9342cbf5c8a1.zip | |
The tester with 233 sats gets to spend them: invoice coverage judges the SUM of spendable coins (the single-coin gate silently declined anything over the largest coin, though multi-input pays gather 24), an uncoverable invoice now owns its paste — board the shortfall from Savings, or say what's short — instead of dropping the bolt11 into the address field like a dead click, and chain calls gain a last-resort relay through the registrar (/esplora passthrough, tip cached) for the network that blackholes every public esplora
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
Diffstat (limited to 'names')
| -rw-r--r-- | names/server.js | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/names/server.js b/names/server.js index a56ed84..a8ffcd5 100644 --- a/names/server.js +++ b/names/server.js @@ -1051,6 +1051,39 @@ Bun.serve({ // Top up the float over Lightning: it mints an invoice against its own // ark balance, which anyone (in practice, the operator's node) can pay. // Guarded by a token from the config file — this endpoint is public. + // Chain relay for wallets whose networks can't reach any public esplora + // (one tester's ISP blackholes mempool.space AND blockstream — every + // chain-touching wallet feature died for it). A narrow passthrough to + // mempool.space: only the four paths the ark manager speaks, the tip + // briefly cached so polling wallets cost one upstream call per few + // seconds, not one each. + if (url.pathname.startsWith('/esplora/')) { + const sub = url.pathname.slice('/esplora'.length); + const okPath = sub === '/blocks/tip/height' + || /^\/tx\/[0-9a-f]{64}\/(hex|status)$/.test(sub) + || (sub === '/tx' && req.method === 'POST'); + if (!okPath) return json({ error: 'not proxied' }, 404); + if (!rateOk(ip, 120)) return json({ error: 'rate limited' }, 429); + try { + if (sub === '/blocks/tip/height' && globalThis._tipCache && Date.now() - globalThis._tipCache.t < 5000) { + return new Response(globalThis._tipCache.v, { headers: { 'access-control-allow-origin': '*' } }); + } + const r = await fetch('https://mempool.space/api' + sub, + req.method === 'POST' ? { method: 'POST', body: await req.text() } : undefined); + const body = await r.text(); + if (sub === '/blocks/tip/height' && r.ok) globalThis._tipCache = { v: body, t: Date.now() }; + return new Response(body, { + status: r.status, + headers: { + 'access-control-allow-origin': '*', + 'content-type': r.headers.get('content-type') || 'text/plain', + }, + }); + } catch { + return json({ error: 'upstream unreachable' }, 502); + } + } + // Legacy migration hand-off. coinos.io's migrate action (running with // the OLD account's authenticated session — that session IS the proof of // ownership) tells us which v3 identity may claim the released name. |
