fix(nostr): handle lazy NIP-44 injection in NIP-07 adapter

Updates `js/nostr/adapters/nip07Adapter.js` to unconditionally expose encryption methods (`nip04Encrypt`, `nip44Decrypt`, etc.) and use dynamic property getters for capabilities. This fixes a race condition where the adapter would initialize without NIP-44 support if the browser extension injected the `nip44` API slightly after `window.nostr` became available, preventing encrypted user lists (subscriptions, blocks, hashtags) from loading.

Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
google-labs-jules[bot]andPR0M3TH3AN committed 2026-01-30 18:19:44 +00:00
1 parent 6a55bd9a60
commit 51924d1619
1 file changed
+21 -28
+21 -28
View File
@@ -90,12 +90,6 @@ export async function createNip07Adapter(initialExtension) {
? normalizeActorKey(await getPublicKey())
: "";
const hasNip04 =
bootstrapExtension.nip04 && typeof bootstrapExtension.nip04 === "object";
const bootstrapNip44 = resolveNip44Module(bootstrapExtension);
const hasNip44 = !!bootstrapNip44;
// Wrapper builders to ensure dynamic lookup at call time
const createNip04Encrypt = () => (pubkey, plaintext, options = {}) => {
const ext = getExtension();
@@ -206,30 +200,29 @@ export async function createNip07Adapter(initialExtension) {
requestPermissions,
destroy: async () => {},
canSign: () => typeof getExtension()?.signEvent === "function",
capabilities: {
sign: typeof bootstrapExtension.signEvent === "function",
nip44: hasNip44,
nip04: hasNip04,
},
// Always expose these methods; they perform their own existence checks at runtime.
// This handles race conditions where NIP-04/44 APIs are injected lazily.
nip04Encrypt: createNip04Encrypt(),
nip04Decrypt: createNip04Decrypt(),
nip44Encrypt: createNip44Encrypt(),
nip44Decrypt: createNip44Decrypt(),
};
if (hasNip04) {
if (typeof bootstrapExtension.nip04.encrypt === "function") {
signer.nip04Encrypt = createNip04Encrypt();
}
if (typeof bootstrapExtension.nip04.decrypt === "function") {
signer.nip04Decrypt = createNip04Decrypt();
}
}
if (hasNip44) {
if (typeof bootstrapNip44.encrypt === "function") {
signer.nip44Encrypt = createNip44Encrypt();
}
if (typeof bootstrapNip44.decrypt === "function") {
signer.nip44Decrypt = createNip44Decrypt();
}
}
// Define capabilities as dynamic properties to reflect current extension state
Object.defineProperty(signer, "capabilities", {
get: () => {
const ext = getExtension();
const hasNip04 = ext?.nip04 && typeof ext.nip04 === "object";
const hasNip44 = !!resolveNip44Module(ext);
return {
sign: typeof ext?.signEvent === "function",
nip44: hasNip44,
nip04: hasNip04,
};
},
enumerable: true,
configurable: true,
});
return signer;
}