aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-28 08:23:20 -0700
committerAdam Soltys <[email protected]>2026-08-28 08:23:20 -0700
commit7064a5b282f1c8e8d6d3e5fa614013c32921454f (patch)
treed7897b08e26339f2d67156425cb014473ab67922
parent274130edd7d11a0643d9b1f7469022207e5f5563 (diff)
downloadcoinosv3-7064a5b282f1c8e8d6d3e5fa614013c32921454f.tar.gz
coinosv3-7064a5b282f1c8e8d6d3e5fa614013c32921454f.zip
The address is fetched while the key still turns in the lock: sign-in races a registrar lookup against the seed work and seeds the name before first paint, so the Receive pane opens straight onto its QR instead of "setting up your payment address"
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
-rw-r--r--src/app.js3
-rw-r--r--src/features/names.js15
-rw-r--r--src/features/nostrlogin.js9
3 files changed, 26 insertions, 1 deletions
diff --git a/src/app.js b/src/app.js
index 5b5c3d5..df62d84 100644
--- a/src/app.js
+++ b/src/app.js
@@ -1129,6 +1129,9 @@ async function activateAccount(acc, opts = {}) {
if (acc.type !== 'watch' && !acc.provisional) acc.xpub = wallet.accountXpub();
persistAccounts();
autoSave(acc);
+ // A name fetched during sign-in seeds the names state BEFORE features init
+ // and the first paint — the Receive pane opens showing its QR.
+ if (opts.nameHint) { try { featureHook('namesSeed', opts.nameHint); } catch {} }
for (const f of FEATURES) { try { f.init && f.init(); } catch {} } // per-feature wallet lifecycle
_featuresInited = true; // a deferred feature landing after this point gets its init() on arrival
// A freshly generated identity provably has no profile yet — let features
diff --git a/src/features/names.js b/src/features/names.js
index 235b834..5b2f856 100644
--- a/src/features/names.js
+++ b/src/features/names.js
@@ -650,6 +650,21 @@ export function namesFeature(ctx) {
namesAdoptIdentity(signer, npub) { return adoptIdentity(signer, npub); },
// the claimed payment address, for anyone prefilling a lightning address
namesAddress() { const st = load(); return st.name ? `${st.name}@${st.domain || DOMAIN()}` : null; },
+ // Sign-in races this lookup against the seed work: by the time the
+ // wallet opens, the answer is usually already in hand…
+ namesLookupByPk(pk) {
+ if (!pk) return null;
+ return fetch(`${REGISTRAR}/pubkey/${pk}?domain=${encodeURIComponent(DOMAIN())}`)
+ .then((x) => x.json()).catch(() => null);
+ },
+ // …and this seeds it into state just before the first paint, so the
+ // Receive pane opens with the QR instead of "setting up your address".
+ namesSeed(rec) {
+ if (!rec || !rec.name) return null;
+ const st = load();
+ if (!st.name) save({ name: rec.name, domain: rec.domain || DOMAIN(), uri: rec.uri });
+ return true;
+ },
// 'pending' while the restore/claim pass is still running — the wallet
// screen holds spending-setup prompts until the name question is settled.
namesSettled() { return checked ? 'yes' : 'pending'; },
diff --git a/src/features/nostrlogin.js b/src/features/nostrlogin.js
index 6c0889b..cef1628 100644
--- a/src/features/nostrlogin.js
+++ b/src/features/nostrlogin.js
@@ -89,6 +89,8 @@ export function nostrLoginFeature(ctx) {
// warm the identity's profile + avatar in parallel with the seed work,
// so the home screen's first paint already has the picture
ctx.hook('warmProfile', signer.pubkey);
+ // and the payment name too — the Receive pane should open with its QR
+ const nameHintP = ctx.hook('namesLookupByPk', signer.pubkey);
const res = await walletForSigner(signer);
if (res.mode === 'new') {
// No wallet on this identity yet — make one and walk straight in.
@@ -111,7 +113,12 @@ export function nostrLoginFeature(ctx) {
// re-animated the welcome screen for a beat before the wallet appeared
ctx.onbNostrLogin(res.mode === 'restored');
ui.navAnimSkip = true; // the handover swaps instantly, no fade
- await ctx.openMnemonic(res.mnemonic, res.passphrase || '', { nostrPubkey: signer.pubkey, spendingHint });
+ // usually resolved long ago; the race caps a slow registrar at 1.5s
+ const nameHint = await Promise.race([
+ Promise.resolve(nameHintP).catch(() => null),
+ new Promise((r) => setTimeout(() => r(null), 1500)),
+ ]);
+ await ctx.openMnemonic(res.mnemonic, res.passphrase || '', { nostrPubkey: signer.pubkey, spendingHint, nameHint });
save({ ...load(), pubkey: signer.pubkey, linked: Date.now(), ...sessionOf(signer) });
attaching = false;
// claim the real npub as the payment address while this signer is live