diff options
| author | Adam Soltys <[email protected]> | 2026-08-18 00:16:10 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-08-18 00:16:10 -0700 |
| commit | a109c2742de15703d10aa6c30b4af7bd7ebae19b (patch) | |
| tree | 51cbba5d6da94c6219164470a8656bac5a11d963 /src/features/names.js | |
| parent | dfb37ac34f5b5aa567fd818784042b3d317e03f5 (diff) | |
| download | coinosv3-a109c2742de15703d10aa6c30b4af7bd7ebae19b.tar.gz coinosv3-a109c2742de15703d10aa6c30b4af7bd7ebae19b.zip | |
A wallet keeps one name per domain, not one name total: staging and mainnet claims stop clobbering each other, the registrar answers who-am-I per domain, and a custom name claimed on one device replaces the npub placeholder on every other
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JtaatFfAbx91Nh3xqKVqKz
Diffstat (limited to 'src/features/names.js')
| -rw-r--r-- | src/features/names.js | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/src/features/names.js b/src/features/names.js index d3971a4..cf2aa3c 100644 --- a/src/features/names.js +++ b/src/features/names.js @@ -55,8 +55,25 @@ export function namesFeature(ctx) { return j; } - const load = () => wallet.loadFeatureState('names', {}); - const save = (st) => wallet.saveFeatureState('names', st); + // One name PER DOMAIN: mainnet and staging claims live side by side in the + // wallet's state instead of overwriting each other on a network switch. + // Legacy flat state ({name, domain, …}) reads/migrates into its domain slot. + const loadAll = () => wallet.loadFeatureState('names', {}); + const load = () => { + const all = loadAll(); + if (all.byDomain) return all.byDomain[DOMAIN()] || {}; + if (all.name) return (all.domain || 'coinos.io') === DOMAIN() ? all : {}; + return {}; + }; + const save = (st) => { + const all = loadAll(); + const byDomain = all.byDomain || {}; + if (!all.byDomain && all.name) { + byDomain[all.domain || 'coinos.io'] = { name: all.name, domain: all.domain || 'coinos.io', uri: all.uri, offerPk: all.offerPk, updated: all.updated }; + } + byDomain[DOMAIN()] = st; + wallet.saveFeatureState('names', { byDomain }); + }; // Mainnet and mutinynet: staging's play network gets the full payment- // address experience (claims already registered fine — the record simply @@ -113,7 +130,7 @@ export function namesFeature(ctx) { const pk = wallet.nostrPubkey && wallet.nostrPubkey(); if (!pk) return; const r = await withTimeout( - fetch(`${REGISTRAR}/pubkey/${pk}`).then((x) => x.json()), 12000, 'registrar'); + fetch(`${REGISTRAR}/pubkey/${pk}?domain=${encodeURIComponent(DOMAIN())}`).then((x) => x.json()), 12000, 'registrar'); if (r && r.name) save({ ...load(), name: r.name, domain: r.domain || DOMAIN(), uri: r.uri }); } catch (e) { console.warn('names: lookup failed —', e.message); } } @@ -143,6 +160,23 @@ export function namesFeature(ctx) { } let st = load(); if (!st.name) { await lookupMine(); st = load(); } + // A custom name claimed on ANOTHER DEVICE by the login identity beats a + // local npub placeholder: the username people know the user by should + // show everywhere they sign in, not only where they typed it. + if (!st.name || /^npub1/.test(st.name)) { + const login = hook('nostrLoginIdentity'); + if (login && login.pubkey) { + try { + const r = await withTimeout( + fetch(`${REGISTRAR}/pubkey/${login.pubkey}?domain=${encodeURIComponent(DOMAIN())}`).then((x) => x.json()), + 8000, 'registrar'); + if (r && r.name && !/^npub1/.test(r.name)) { + save({ ...st, name: r.name, domain: r.domain || DOMAIN(), uri: r.uri }); + st = load(); + } + } catch {} + } + } if (!st.name) { // The address people see should be the identity they know the user // by: their real npub when a nostr account is linked, else the |
