aboutsummaryrefslogtreecommitdiffstats
path: root/dev.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-06-28 21:59:07 -0700
committerAdam Soltys <[email protected]>2026-06-28 21:59:07 -0700
commitfcd971da0c110607ccdc7637667beb0fa79d42a7 (patch)
tree4b81bb348c8d6ed25bec03f6e5adf10b68908226 /dev.js
parent656726e17684071e929a2f0453cdd306c4d8dc12 (diff)
downloadcoinosv3-fcd971da0c110607ccdc7637667beb0fa79d42a7.tar.gz
coinosv3-fcd971da0c110607ccdc7637667beb0fa79d42a7.zip
Swaps(regtest dev): proxy boltz through the dev server to fix CORS 'failed to fetch'
The regtest boltz API (localhost:9001) sends no CORS headers, so the browser blocked cross-origin fetches — creating a Lightning invoice failed with 'failed to fetch', and the limits GET silently fell back to defaults (min showed 25k instead of regtest's real 50k). bun E2E tests didn't hit this (no CORS enforced). dev.js now proxies /boltz/* to localhost:9001 (adding CORS + handling the OPTIONS preflight), and the 'local' boltz preset points at the same-origin /boltz path. Public providers (mainnet/testnet) already send CORS and are unaffected. Verified: GET limits via proxy returns the real 50k/40.29M with CORS; POST create-reverse succeeds; the browser swap form now shows Min 50,000. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'dev.js')
-rw-r--r--dev.js14
1 files changed, 14 insertions, 0 deletions
diff --git a/dev.js b/dev.js
index 6dffad9..02aa772 100644
--- a/dev.js
+++ b/dev.js
@@ -13,6 +13,20 @@ Bun.serve({
const NO_STORE = 'no-store, must-revalidate';
try {
const path = new URL(req.url).pathname;
+ // The regtest boltz API (localhost:9001) sends no CORS headers, so the
+ // browser can't fetch it cross-origin. Proxy /boltz/* to it (adding CORS)
+ // so Lightning swaps work same-origin in dev.
+ if (path === '/boltz' || path.startsWith('/boltz/')) {
+ const CORS = { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,POST,OPTIONS', 'access-control-allow-headers': 'content-type' };
+ if (req.method === 'OPTIONS') return new Response(null, { status: 204, headers: CORS });
+ const target = 'http://localhost:9001' + path.replace(/^\/boltz/, '') + new URL(req.url).search;
+ const r = await fetch(target, {
+ method: req.method,
+ headers: req.headers.get('content-type') ? { 'content-type': req.headers.get('content-type') } : {},
+ body: ['GET', 'HEAD'].includes(req.method) ? undefined : await req.text(),
+ });
+ return new Response(await r.text(), { status: r.status, headers: { 'content-type': r.headers.get('content-type') || 'application/json', ...CORS } });
+ }
if (path === '/jsqr.js') {
return new Response(await buildJsQr({ minify: false }), {
headers: { 'content-type': 'text/javascript; charset=utf-8', 'cache-control': NO_STORE },