aboutsummaryrefslogtreecommitdiffstats
path: root/src/app.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-06-28 04:38:18 -0700
committerAdam Soltys <[email protected]>2026-06-28 04:38:18 -0700
commit98b216605604c3fea85936a54b07344ddc7a08a6 (patch)
tree24e5ca16a8f1fa2fc1ddf0196e640d66a379d40a /src/app.js
parent76daca707a7b9cb9aafab1ceb8999ec3c708a63d (diff)
downloadcoinosv3-98b216605604c3fea85936a54b07344ddc7a08a6.tar.gz
coinosv3-98b216605604c3fea85936a54b07344ddc7a08a6.zip
Unify data sources into one list; coinos → electrum.coinos.io
- Combined the separate Electrum and Explorer settings into a single data-source list. Each preset knows its type (electrum vs esplora); a custom source's type is detected from its URL scheme (ws/wss → Electrum, http/https → Esplora). The settings UI is now one dropdown + a URL field for Custom, with a one-line note showing the detected/selected type. getBackend/electrumCandidates/resolveHosts derive from the selected source. Old split settings migrate automatically. - coinos now points at wss://electrum.coinos.io (was wss://halwallet.app/electrum). Set up as a cloudflared route on the bitcoin tunnel → the Fulcrum WS (:50003), with a DNS CNAME. Verified the endpoint serves Electrum from a browser (Fulcrum 2.1.1 replies; cloudflare Bot Fight Mode only challenges non-browser clients). Verified: combined list + auto-detection (unit + browser), old-settings migration, regtest data flow unchanged, and the app loads over electrum.coinos.io with no errors. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Diffstat (limited to 'src/app.js')
-rw-r--r--src/app.js71
1 files changed, 21 insertions, 50 deletions
diff --git a/src/app.js b/src/app.js
index 2470ac8..c49e279 100644
--- a/src/app.js
+++ b/src/app.js
@@ -8,7 +8,7 @@ import { Wallet, newMnemonic, isValidMnemonic, accountXpubFor, cacheKeyFor, utxo
import { qrSvg } from './qr.js';
import { scanQr } from './scan.js';
import { getSyncConfig, setSyncConfig } from './nostr.js';
-import { getExplorerConfig, setExplorerConfig, explorerPresets, getDataMode, setDataMode, electrumPresets, getElectrumServerConfig, setElectrumServerConfig, getNetwork, setNetwork, NETWORKS, getSpIndexerConfig, setSpIndexerConfig, spIndexerPresets } from './api.js';
+import { dataSources, getSource, setSource, getNetwork, setNetwork, NETWORKS, getSpIndexerConfig, setSpIndexerConfig, spIndexerPresets } from './api.js';
import { isSilentPaymentAddress } from './silentpay.js';
import { t, LANGS, getLang, setLang, isRTL, loadLocale } from './i18n.js';
import {
@@ -1613,63 +1613,34 @@ function networkCard() {
function explorerCard() {
const net = getNetwork();
- const mode = getDataMode();
- const cfg = getExplorerConfig();
- const ecfg = getElectrumServerConfig();
- const setMode = (m) => {
- if (m === getDataMode()) return;
- setDataMode(m);
+ const src = getSource();
+ const sources = dataSources(net);
+ const pick = (id) => {
+ setSource({ id, url: '' });
render();
- // electrum⇄explorer swaps the whole backend, so rebuild + rescan.
- if (!wallet.offline) wallet.reloadExplorer();
+ // Switching source can swap the whole backend (electrum⇄esplora), so rebuild
+ // + rescan — except an empty custom (wait for the URL).
+ if (id !== 'custom' && !wallet.offline) wallet.reloadExplorer();
};
+ const typeDesc = t(src.type === 'electrum' ? 'detectedElectrum' : 'detectedEsplora');
return h(
'div',
{ class: 'card col' },
h('h3', {}, t('dataSource')),
h('p', { class: 'small muted', style: 'margin:0' }, t('dataSourceDesc')),
- h('select', { onChange: (e) => setMode(e.target.value) },
- h('option', { value: 'electrum', selected: mode === 'electrum' }, t('modeElectrum')),
- h('option', { value: 'explorer', selected: mode === 'explorer' }, t('modeExplorer'))
- ),
- mode === 'electrum'
- ? h('div', { class: 'col', style: 'gap:8px' },
- h('div', { class: 'small faint' }, t('backendElectrumDesc')),
- h('select', {
- onChange: (e) => { setElectrumServerConfig({ server: e.target.value, url: ecfg.url }); render(); if (e.target.value !== 'custom' || ecfg.url) wallet.reloadExplorer(); },
- }, electrumPresets(net).map((o) => h('option', { value: o.id, selected: o.id === ecfg.server }, o.label))),
- ecfg.server === 'custom'
- ? h('label', { class: 'field' },
- h('span', { class: 'lab' }, t('electrumUrl')),
- h('input', {
- type: 'text', class: 'mono-input', placeholder: 'wss://your-node:50004',
- autocapitalize: 'none', autocomplete: 'off', spellcheck: 'false', value: ecfg.url,
- onChange: (e) => { setElectrumServerConfig({ server: 'custom', url: e.target.value.trim() }); wallet.reloadExplorer(); },
- }),
- h('div', { class: 'small faint' }, t('electrumUrlHint'))
- )
- : null
- )
- : null,
- mode === 'explorer'
- ? h('div', { class: 'col', style: 'gap:8px' },
- h('div', { class: 'small faint' }, t('modeExplorerDesc')),
- h('select', {
- onChange: (e) => { setExplorerConfig({ server: e.target.value, url: cfg.url }); render(); if (e.target.value !== 'custom' || cfg.url) wallet.reloadExplorer(); },
- }, explorerPresets(net).map((o) => h('option', { value: o.id, selected: o.id === cfg.server }, o.label))),
- cfg.server === 'custom'
- ? h('label', { class: 'field' },
- h('span', { class: 'lab' }, t('explorerUrl')),
- h('input', {
- type: 'text', class: 'mono-input', placeholder: 'https://mempool.space/api',
- autocapitalize: 'none', autocomplete: 'off', spellcheck: 'false', value: cfg.url,
- onChange: (e) => { setExplorerConfig({ server: 'custom', url: e.target.value.trim() }); wallet.reloadExplorer(); },
- }),
- h('div', { class: 'small faint' }, t('explorerUrlHint'))
- )
- : null
+ h('select', { onChange: (e) => pick(e.target.value) },
+ sources.map((o) => h('option', { value: o.id, selected: o.id === src.id }, o.label))),
+ src.id === 'custom'
+ ? h('label', { class: 'field' },
+ h('span', { class: 'lab' }, t('sourceUrl')),
+ h('input', {
+ type: 'text', class: 'mono-input', placeholder: 'wss://your-node:50004 · https://your-esplora/api',
+ autocapitalize: 'none', autocomplete: 'off', spellcheck: 'false', value: src.url || '',
+ onChange: (e) => { const url = e.target.value.trim(); setSource({ id: 'custom', url }); render(); if (!wallet.offline) wallet.reloadExplorer(); },
+ }),
+ h('div', { class: 'small faint' }, src.url ? typeDesc : t('sourceUrlHint'))
)
- : null
+ : h('div', { class: 'small faint' }, typeDesc)
);
}