From a9a903e7a1f80ed4a6f4163419b25d4e6de5db01 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sat, 27 Jun 2026 08:40:41 -0700 Subject: Add regtest network support New `regtest` network (bech32 `bcrt`, testnet version bytes) selectable in Settings, pointed at a configurable local Esplora (default http://localhost:3000). Adds getNetwork/setNetwork + getRegtestEsplora persistence, a regtest branch in resolveHosts, mainnet-only gating for the realtime watcher + Electrum backend, and a Network selector card. Account loading reads the active network. Co-Authored-By: Claude Opus 4.8 --- src/api.js | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'src/api.js') diff --git a/src/api.js b/src/api.js index 6f010cb..d135218 100644 --- a/src/api.js +++ b/src/api.js @@ -32,8 +32,37 @@ export function setExplorerConfig({ server, url }) { } catch {} } +// Active Bitcoin network (mainnet | testnet | regtest), persisted globally. +const NETWORK_KEY = 'btc-wallet-network'; +export function getNetwork() { + try { + const n = localStorage.getItem(NETWORK_KEY); + if (n === 'mainnet' || n === 'testnet' || n === 'regtest') return n; + } catch {} + return 'mainnet'; +} +export function setNetwork(net) { + try { localStorage.setItem(NETWORK_KEY, net); } catch {} +} + +// Regtest points at a local Esplora-compatible server (coinos's chopsticks `cs` +// at :3000 by default). Treated like a self-hosted custom explorer: the URL is +// used as the esplora base directly (no `/api` prefix, no `/testnet`). +const REGTEST_ESPLORA_KEY = 'btc-wallet-regtest-esplora'; +export function getRegtestEsplora() { + try { return (localStorage.getItem(REGTEST_ESPLORA_KEY) || '').trim() || 'http://localhost:3000'; } + catch { return 'http://localhost:3000'; } +} +export function setRegtestEsplora(url) { + try { localStorage.setItem(REGTEST_ESPLORA_KEY, (url || '').trim()); } catch {} +} + // Resolve the configured explorer to the host list the Api tries in order. function resolveHosts(net) { + if (net === 'regtest') { + const base = getRegtestEsplora().replace(/\/+$/, ''); + return [{ base, kind: 'esplora', web: base, cooldownUntil: 0 }]; + } const cfg = getExplorerConfig(); const apiPath = net === 'testnet' ? '/testnet/api' : '/api'; const host = (web, kind) => ({ base: web + apiPath, kind, web, cooldownUntil: 0 }); @@ -138,7 +167,7 @@ export function resolveElectrumUrl() { } export function wsUrl(net) { - if (net === 'testnet') return null; + if (net !== 'mainnet') return null; // coinos watcher is mainnet-only // Electrum backend selects/rotates candidates in the wallet; here we only // resolve the coinos watcher (esplora 'coinos' mode) or null (esplora 'explorer'). if (getBackend() === 'electrum') return null; @@ -182,6 +211,8 @@ export class Api { return web + (this.net === 'testnet' ? '/testnet/tx/' : '/tx/') + txid; } + get isRegtest() { return this.net === 'regtest'; } + // ---- rate-aware global scheduler -------------------------------------- #schedule(task) { return new Promise((resolve, reject) => { -- cgit v1.2.3