aboutsummaryrefslogtreecommitdiffstats
path: root/src/nostr-login.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-26 12:06:00 -0700
committerAdam Soltys <[email protected]>2026-08-26 12:06:00 -0700
commit0427a1b02c21fd5fa9f5df8a86e435dbb84a8451 (patch)
tree32e5601682e6f65e46a8811cfc2ea7184ba17119 /src/nostr-login.js
parent6be9a45c4d085988c8bfaf210df762dbc83c8ab1 (diff)
downloadcoinosv3-0427a1b02c21fd5fa9f5df8a86e435dbb84a8451.tar.gz
coinosv3-0427a1b02c21fd5fa9f5df8a86e435dbb84a8451.zip
The page arrives light and paints at once: index.html shrinks to 46KB with a static boot shell baked in — brand row, and the profile frame when the path names one — while the 789KB bundle moves to a content-addressed app-<hash>.js the browser keeps (a repeat visit re-downloads kilobytes, not the app); the nostr-tools barrel import goes subpath, and the NIP-46 signer client ships as its own lazy file fetched on first bunker login
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_019eA8JRq9Wr7z2fRQk99HLi
Diffstat (limited to 'src/nostr-login.js')
-rw-r--r--src/nostr-login.js23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/nostr-login.js b/src/nostr-login.js
index 301bbeb..6958da0 100644
--- a/src/nostr-login.js
+++ b/src/nostr-login.js
@@ -38,9 +38,25 @@ import { entropyToMnemonic } from '@scure/bip39';
import { wordlist } from '@scure/bip39/wordlists/english';
import { getPublicKey, finalizeEvent, nip44 } from './nostr.js';
import { SimplePool } from 'nostr-tools/pool';
-import { BunkerSigner, parseBunkerInput, createNostrConnectURI } from 'nostr-tools/nip46';
import { generateSecretKey } from 'nostr-tools/pure';
+// NIP-46 loads lazily from dist/nip46.js (same pattern as the QR decoder):
+// bunker logins are rare, and the module is heavy. Tests running outside a
+// browser preset globalThis.__nip46 with the real module instead.
+let _nip46 = null;
+function loadNip46() {
+ if (_nip46) return _nip46;
+ if (typeof globalThis !== 'undefined' && globalThis.__nip46) return (_nip46 = Promise.resolve(globalThis.__nip46));
+ _nip46 = new Promise((resolve, reject) => {
+ const s = document.createElement('script');
+ s.src = 'nip46.js';
+ s.onload = () => (window.__nip46 ? resolve(window.__nip46) : reject(new Error('signer module unavailable')));
+ s.onerror = () => { _nip46 = null; reject(new Error('could not load the remote-signer module')); };
+ document.head.appendChild(s);
+ });
+ return _nip46;
+}
+
const SEED_DTAG = 'coinos:wallet:v1';
const BACKUP_KIND = 30078;
const DERIVE_TAG = 'coinos:wallet-seed:v1';
@@ -91,6 +107,7 @@ export async function extensionSigner() {
}
export async function bunkerSigner(uri, { onAuth } = {}) {
+ const { BunkerSigner, parseBunkerInput } = await loadNip46();
const bp = await parseBunkerInput(String(uri || '').trim());
if (!bp) throw new Error('not a bunker:// address');
if (!bp.relays || !bp.relays.length) throw new Error('that bunker address lists no relays');
@@ -111,6 +128,7 @@ export async function bunkerSigner(uri, { onAuth } = {}) {
// prompting the user again.
export async function resumeBunker(session, { onAuth, timeoutMs = 8000 } = {}) {
if (!session || !session.local || !session.bp || !session.bp.pubkey) return null;
+ const { BunkerSigner } = await loadNip46();
const local = hex.decode(session.local);
const signer = BunkerSigner.fromBunker(local, session.bp, {
onauth: (url) => { if (onAuth) onAuth(url); },
@@ -147,7 +165,8 @@ function bunkerAdapter(signer, pubkey, local) {
// relay — no bunker URL to copy. Returns the URI (render it as a deep link
// and a QR), a promise that resolves to a signer adapter when the app
// answers, and a cancel.
-export function nostrConnect({ relays = ['wss://relay.coinos.io', 'wss://nos.lol'], timeoutMs = 180_000 } = {}) {
+export async function nostrConnect({ relays = ['wss://relay.coinos.io', 'wss://nos.lol'], timeoutMs = 180_000 } = {}) {
+ const { BunkerSigner, createNostrConnectURI } = await loadNip46();
const local = generateSecretKey();
const secret = hex.encode(crypto.getRandomValues(new Uint8Array(16)));
const uri = createNostrConnectURI({