diff --git a/lite/build.js b/lite/build.js
index f084773..4cac4e3 100644
--- a/lite/build.js
+++ b/lite/build.js
@@ -1254,13 +1254,13 @@ class WindowNostr {
if (event.detail.method === 'extension') {
this.authenticatedExtension = event.detail.extension;
console.log('WindowNostr: Captured authenticated extension:', this.authenticatedExtension?.constructor?.name);
-
- // Re-install our facade to ensure we intercept signEvent calls
- // Extensions may overwrite window.nostr after authentication
- if (typeof window !== 'undefined') {
- console.log('WindowNostr: Re-installing facade after authentication');
- window.nostr = this;
- }
+ }
+
+ // CRITICAL FIX: Re-install our facade for ALL authentication methods
+ // Extensions may overwrite window.nostr after ANY authentication, not just extension auth
+ if (typeof window !== 'undefined') {
+ console.log('WindowNostr: Re-installing facade after', this.authState?.method, 'authentication');
+ window.nostr = this;
}
console.log('WindowNostr: Auth state updated:', this.authState?.method);
@@ -1270,6 +1270,12 @@ class WindowNostr {
this.authState = null;
this.authenticatedExtension = null;
console.log('WindowNostr: Auth state cleared');
+
+ // Re-install facade after logout to ensure we maintain control
+ if (typeof window !== 'undefined') {
+ console.log('WindowNostr: Re-installing facade after logout');
+ window.nostr = this;
+ }
});
}
}
diff --git a/lite/nostr-lite.js b/lite/nostr-lite.js
index 0bcbeb2..578ff5c 100644
--- a/lite/nostr-lite.js
+++ b/lite/nostr-lite.js
@@ -8,7 +8,7 @@
* Two-file architecture:
* 1. Load nostr.bundle.js (official nostr-tools bundle)
* 2. Load nostr-lite.js (this file - NOSTR_LOGIN_LITE library with CSS-only themes)
- * Generated on: 2025-09-15T17:48:16.817Z
+ * Generated on: 2025-09-15T18:15:24.222Z
*/
// Verify dependencies are loaded
@@ -1627,15 +1627,176 @@ class Modal {
const warningDiv = document.createElement('div');
warningDiv.textContent = '⚠️ Save your secret key securely!';
- warningDiv.style.cssText = 'background: #fef3c7; color: #92400e; padding: 12px; border-radius: 6px; margin-bottom: 16px; font-size: 14px;';
+ warningDiv.style.cssText = 'background: #fef3c7; color: #92400e; padding: 12px; border-radius: 6px; margin-bottom: 16px; font-size: 12px;';
- const nsecDiv = document.createElement('div');
- nsecDiv.innerHTML = `Your Secret Key:
${nsec}`;
- nsecDiv.style.cssText = 'margin-bottom: 16px; font-size: 14px;';
+ // Helper function to create copy button
+ const createCopyButton = (text, label) => {
+ const copyBtn = document.createElement('button');
+ copyBtn.textContent = `Copy ${label}`;
+ copyBtn.style.cssText = `
+ margin-left: 8px;
+ padding: 4px 8px;
+ font-size: 10px;
+ background: var(--nl-secondary-color);
+ color: var(--nl-primary-color);
+ border: 1px solid var(--nl-primary-color);
+ border-radius: 4px;
+ cursor: pointer;
+ font-family: var(--nl-font-family, 'Courier New', monospace);
+ `;
+ copyBtn.onclick = async (e) => {
+ e.preventDefault();
+ try {
+ await navigator.clipboard.writeText(text);
+ const originalText = copyBtn.textContent;
+ copyBtn.textContent = '✓ Copied!';
+ copyBtn.style.color = '#059669';
+ setTimeout(() => {
+ copyBtn.textContent = originalText;
+ copyBtn.style.color = 'var(--nl-primary-color)';
+ }, 2000);
+ } catch (err) {
+ console.error('Failed to copy:', err);
+ copyBtn.textContent = '✗ Failed';
+ copyBtn.style.color = '#dc2626';
+ setTimeout(() => {
+ copyBtn.textContent = originalText;
+ copyBtn.style.color = 'var(--nl-primary-color)';
+ }, 2000);
+ }
+ };
+ return copyBtn;
+ };
- const npubDiv = document.createElement('div');
- npubDiv.innerHTML = `Your Public Key:
${window.NostrTools.nip19.npubEncode(pubkey)}`;
- npubDiv.style.cssText = 'margin-bottom: 16px; font-size: 14px;';
+ // Convert pubkey to hex for verification
+ const pubkeyHex = typeof pubkey === 'string' ? pubkey : Array.from(pubkey).map(b => b.toString(16).padStart(2, '0')).join('');
+
+ // Decode nsec to get secret key as hex
+ let secretKeyHex = '';
+ try {
+ const decoded = window.NostrTools.nip19.decode(nsec);
+ secretKeyHex = Array.from(decoded.data).map(b => b.toString(16).padStart(2, '0')).join('');
+ } catch (err) {
+ console.error('Failed to decode nsec for hex display:', err);
+ }
+
+ // Secret Key Section
+ const nsecSection = document.createElement('div');
+ nsecSection.style.cssText = 'margin-bottom: 16px;';
+
+ const nsecLabel = document.createElement('div');
+ nsecLabel.innerHTML = 'Your Secret Key (nsec):';
+ nsecLabel.style.cssText = 'margin-bottom: 4px; font-size: 12px; font-weight: 600;';
+
+ const nsecContainer = document.createElement('div');
+ nsecContainer.style.cssText = 'display: flex; align-items: flex-start; margin-bottom: 8px;';
+
+ const nsecCode = document.createElement('code');
+ nsecCode.textContent = nsec;
+ nsecCode.style.cssText = `
+ flex: 1;
+ word-break: break-all;
+ background: #f3f4f6;
+ padding: 6px;
+ border-radius: 4px;
+ font-size: 10px;
+ line-height: 1.3;
+ font-family: 'Courier New', monospace;
+ display: block;
+ `;
+
+ nsecContainer.appendChild(nsecCode);
+ nsecContainer.appendChild(createCopyButton(nsec, 'nsec'));
+ nsecSection.appendChild(nsecLabel);
+ nsecSection.appendChild(nsecContainer);
+
+ // Secret Key Hex Section
+ if (secretKeyHex) {
+ const secretHexLabel = document.createElement('div');
+ secretHexLabel.innerHTML = 'Secret Key (hex):';
+ secretHexLabel.style.cssText = 'margin-bottom: 4px; font-size: 12px; font-weight: 600;';
+
+ const secretHexContainer = document.createElement('div');
+ secretHexContainer.style.cssText = 'display: flex; align-items: flex-start; margin-bottom: 8px;';
+
+ const secretHexCode = document.createElement('code');
+ secretHexCode.textContent = secretKeyHex;
+ secretHexCode.style.cssText = `
+ flex: 1;
+ word-break: break-all;
+ background: #f3f4f6;
+ padding: 6px;
+ border-radius: 4px;
+ font-size: 10px;
+ line-height: 1.3;
+ font-family: 'Courier New', monospace;
+ display: block;
+ `;
+
+ secretHexContainer.appendChild(secretHexCode);
+ secretHexContainer.appendChild(createCopyButton(secretKeyHex, 'hex'));
+ nsecSection.appendChild(secretHexLabel);
+ nsecSection.appendChild(secretHexContainer);
+ }
+
+ // Public Key Section
+ const npubSection = document.createElement('div');
+ npubSection.style.cssText = 'margin-bottom: 16px;';
+
+ const npub = window.NostrTools.nip19.npubEncode(pubkey);
+
+ const npubLabel = document.createElement('div');
+ npubLabel.innerHTML = 'Your Public Key (npub):';
+ npubLabel.style.cssText = 'margin-bottom: 4px; font-size: 12px; font-weight: 600;';
+
+ const npubContainer = document.createElement('div');
+ npubContainer.style.cssText = 'display: flex; align-items: flex-start; margin-bottom: 8px;';
+
+ const npubCode = document.createElement('code');
+ npubCode.textContent = npub;
+ npubCode.style.cssText = `
+ flex: 1;
+ word-break: break-all;
+ background: #f3f4f6;
+ padding: 6px;
+ border-radius: 4px;
+ font-size: 10px;
+ line-height: 1.3;
+ font-family: 'Courier New', monospace;
+ display: block;
+ `;
+
+ npubContainer.appendChild(npubCode);
+ npubContainer.appendChild(createCopyButton(npub, 'npub'));
+ npubSection.appendChild(npubLabel);
+ npubSection.appendChild(npubContainer);
+
+ // Public Key Hex Section
+ const pubHexLabel = document.createElement('div');
+ pubHexLabel.innerHTML = 'Public Key (hex):';
+ pubHexLabel.style.cssText = 'margin-bottom: 4px; font-size: 12px; font-weight: 600;';
+
+ const pubHexContainer = document.createElement('div');
+ pubHexContainer.style.cssText = 'display: flex; align-items: flex-start;';
+
+ const pubHexCode = document.createElement('code');
+ pubHexCode.textContent = pubkeyHex;
+ pubHexCode.style.cssText = `
+ flex: 1;
+ word-break: break-all;
+ background: #f3f4f6;
+ padding: 6px;
+ border-radius: 4px;
+ font-size: 10px;
+ line-height: 1.3;
+ font-family: 'Courier New', monospace;
+ display: block;
+ `;
+
+ pubHexContainer.appendChild(pubHexCode);
+ pubHexContainer.appendChild(createCopyButton(pubkeyHex, 'hex'));
+ npubSection.appendChild(pubHexLabel);
+ npubSection.appendChild(pubHexContainer);
const continueButton = document.createElement('button');
continueButton.textContent = 'Continue';
@@ -1644,8 +1805,8 @@ class Modal {
this.modalBody.appendChild(title);
this.modalBody.appendChild(warningDiv);
- this.modalBody.appendChild(nsecDiv);
- this.modalBody.appendChild(npubDiv);
+ this.modalBody.appendChild(nsecSection);
+ this.modalBody.appendChild(npubSection);
this.modalBody.appendChild(continueButton);
}
@@ -2562,13 +2723,13 @@ class WindowNostr {
if (event.detail.method === 'extension') {
this.authenticatedExtension = event.detail.extension;
console.log('WindowNostr: Captured authenticated extension:', this.authenticatedExtension?.constructor?.name);
-
- // Re-install our facade to ensure we intercept signEvent calls
- // Extensions may overwrite window.nostr after authentication
- if (typeof window !== 'undefined') {
- console.log('WindowNostr: Re-installing facade after authentication');
- window.nostr = this;
- }
+ }
+
+ // CRITICAL FIX: Re-install our facade for ALL authentication methods
+ // Extensions may overwrite window.nostr after ANY authentication, not just extension auth
+ if (typeof window !== 'undefined') {
+ console.log('WindowNostr: Re-installing facade after', this.authState?.method, 'authentication');
+ window.nostr = this;
}
console.log('WindowNostr: Auth state updated:', this.authState?.method);
@@ -2578,6 +2739,12 @@ class WindowNostr {
this.authState = null;
this.authenticatedExtension = null;
console.log('WindowNostr: Auth state cleared');
+
+ // Re-install facade after logout to ensure we maintain control
+ if (typeof window !== 'undefined') {
+ console.log('WindowNostr: Re-installing facade after logout');
+ window.nostr = this;
+ }
});
}
}
diff --git a/lite/ui/modal.js b/lite/ui/modal.js
index c208f6f..0628d8c 100644
--- a/lite/ui/modal.js
+++ b/lite/ui/modal.js
@@ -831,15 +831,176 @@ class Modal {
const warningDiv = document.createElement('div');
warningDiv.textContent = '⚠️ Save your secret key securely!';
- warningDiv.style.cssText = 'background: #fef3c7; color: #92400e; padding: 12px; border-radius: 6px; margin-bottom: 16px; font-size: 14px;';
+ warningDiv.style.cssText = 'background: #fef3c7; color: #92400e; padding: 12px; border-radius: 6px; margin-bottom: 16px; font-size: 12px;';
- const nsecDiv = document.createElement('div');
- nsecDiv.innerHTML = `Your Secret Key:
${nsec}`;
- nsecDiv.style.cssText = 'margin-bottom: 16px; font-size: 14px;';
+ // Helper function to create copy button
+ const createCopyButton = (text, label) => {
+ const copyBtn = document.createElement('button');
+ copyBtn.textContent = `Copy ${label}`;
+ copyBtn.style.cssText = `
+ margin-left: 8px;
+ padding: 4px 8px;
+ font-size: 10px;
+ background: var(--nl-secondary-color);
+ color: var(--nl-primary-color);
+ border: 1px solid var(--nl-primary-color);
+ border-radius: 4px;
+ cursor: pointer;
+ font-family: var(--nl-font-family, 'Courier New', monospace);
+ `;
+ copyBtn.onclick = async (e) => {
+ e.preventDefault();
+ try {
+ await navigator.clipboard.writeText(text);
+ const originalText = copyBtn.textContent;
+ copyBtn.textContent = '✓ Copied!';
+ copyBtn.style.color = '#059669';
+ setTimeout(() => {
+ copyBtn.textContent = originalText;
+ copyBtn.style.color = 'var(--nl-primary-color)';
+ }, 2000);
+ } catch (err) {
+ console.error('Failed to copy:', err);
+ copyBtn.textContent = '✗ Failed';
+ copyBtn.style.color = '#dc2626';
+ setTimeout(() => {
+ copyBtn.textContent = originalText;
+ copyBtn.style.color = 'var(--nl-primary-color)';
+ }, 2000);
+ }
+ };
+ return copyBtn;
+ };
- const npubDiv = document.createElement('div');
- npubDiv.innerHTML = `Your Public Key:
${window.NostrTools.nip19.npubEncode(pubkey)}`;
- npubDiv.style.cssText = 'margin-bottom: 16px; font-size: 14px;';
+ // Convert pubkey to hex for verification
+ const pubkeyHex = typeof pubkey === 'string' ? pubkey : Array.from(pubkey).map(b => b.toString(16).padStart(2, '0')).join('');
+
+ // Decode nsec to get secret key as hex
+ let secretKeyHex = '';
+ try {
+ const decoded = window.NostrTools.nip19.decode(nsec);
+ secretKeyHex = Array.from(decoded.data).map(b => b.toString(16).padStart(2, '0')).join('');
+ } catch (err) {
+ console.error('Failed to decode nsec for hex display:', err);
+ }
+
+ // Secret Key Section
+ const nsecSection = document.createElement('div');
+ nsecSection.style.cssText = 'margin-bottom: 16px;';
+
+ const nsecLabel = document.createElement('div');
+ nsecLabel.innerHTML = 'Your Secret Key (nsec):';
+ nsecLabel.style.cssText = 'margin-bottom: 4px; font-size: 12px; font-weight: 600;';
+
+ const nsecContainer = document.createElement('div');
+ nsecContainer.style.cssText = 'display: flex; align-items: flex-start; margin-bottom: 8px;';
+
+ const nsecCode = document.createElement('code');
+ nsecCode.textContent = nsec;
+ nsecCode.style.cssText = `
+ flex: 1;
+ word-break: break-all;
+ background: #f3f4f6;
+ padding: 6px;
+ border-radius: 4px;
+ font-size: 10px;
+ line-height: 1.3;
+ font-family: 'Courier New', monospace;
+ display: block;
+ `;
+
+ nsecContainer.appendChild(nsecCode);
+ nsecContainer.appendChild(createCopyButton(nsec, 'nsec'));
+ nsecSection.appendChild(nsecLabel);
+ nsecSection.appendChild(nsecContainer);
+
+ // Secret Key Hex Section
+ if (secretKeyHex) {
+ const secretHexLabel = document.createElement('div');
+ secretHexLabel.innerHTML = 'Secret Key (hex):';
+ secretHexLabel.style.cssText = 'margin-bottom: 4px; font-size: 12px; font-weight: 600;';
+
+ const secretHexContainer = document.createElement('div');
+ secretHexContainer.style.cssText = 'display: flex; align-items: flex-start; margin-bottom: 8px;';
+
+ const secretHexCode = document.createElement('code');
+ secretHexCode.textContent = secretKeyHex;
+ secretHexCode.style.cssText = `
+ flex: 1;
+ word-break: break-all;
+ background: #f3f4f6;
+ padding: 6px;
+ border-radius: 4px;
+ font-size: 10px;
+ line-height: 1.3;
+ font-family: 'Courier New', monospace;
+ display: block;
+ `;
+
+ secretHexContainer.appendChild(secretHexCode);
+ secretHexContainer.appendChild(createCopyButton(secretKeyHex, 'hex'));
+ nsecSection.appendChild(secretHexLabel);
+ nsecSection.appendChild(secretHexContainer);
+ }
+
+ // Public Key Section
+ const npubSection = document.createElement('div');
+ npubSection.style.cssText = 'margin-bottom: 16px;';
+
+ const npub = window.NostrTools.nip19.npubEncode(pubkey);
+
+ const npubLabel = document.createElement('div');
+ npubLabel.innerHTML = 'Your Public Key (npub):';
+ npubLabel.style.cssText = 'margin-bottom: 4px; font-size: 12px; font-weight: 600;';
+
+ const npubContainer = document.createElement('div');
+ npubContainer.style.cssText = 'display: flex; align-items: flex-start; margin-bottom: 8px;';
+
+ const npubCode = document.createElement('code');
+ npubCode.textContent = npub;
+ npubCode.style.cssText = `
+ flex: 1;
+ word-break: break-all;
+ background: #f3f4f6;
+ padding: 6px;
+ border-radius: 4px;
+ font-size: 10px;
+ line-height: 1.3;
+ font-family: 'Courier New', monospace;
+ display: block;
+ `;
+
+ npubContainer.appendChild(npubCode);
+ npubContainer.appendChild(createCopyButton(npub, 'npub'));
+ npubSection.appendChild(npubLabel);
+ npubSection.appendChild(npubContainer);
+
+ // Public Key Hex Section
+ const pubHexLabel = document.createElement('div');
+ pubHexLabel.innerHTML = 'Public Key (hex):';
+ pubHexLabel.style.cssText = 'margin-bottom: 4px; font-size: 12px; font-weight: 600;';
+
+ const pubHexContainer = document.createElement('div');
+ pubHexContainer.style.cssText = 'display: flex; align-items: flex-start;';
+
+ const pubHexCode = document.createElement('code');
+ pubHexCode.textContent = pubkeyHex;
+ pubHexCode.style.cssText = `
+ flex: 1;
+ word-break: break-all;
+ background: #f3f4f6;
+ padding: 6px;
+ border-radius: 4px;
+ font-size: 10px;
+ line-height: 1.3;
+ font-family: 'Courier New', monospace;
+ display: block;
+ `;
+
+ pubHexContainer.appendChild(pubHexCode);
+ pubHexContainer.appendChild(createCopyButton(pubkeyHex, 'hex'));
+ npubSection.appendChild(pubHexLabel);
+ npubSection.appendChild(pubHexContainer);
const continueButton = document.createElement('button');
continueButton.textContent = 'Continue';
@@ -848,8 +1009,8 @@ class Modal {
this.modalBody.appendChild(title);
this.modalBody.appendChild(warningDiv);
- this.modalBody.appendChild(nsecDiv);
- this.modalBody.appendChild(npubDiv);
+ this.modalBody.appendChild(nsecSection);
+ this.modalBody.appendChild(npubSection);
this.modalBody.appendChild(continueButton);
}