Refactor nostr signer access

This commit is contained in:
thePR0M3TH3AN committed 2026-01-18 09:15:18 -05:00
1 parent 2410412450
commit 52d2488d17
5 files changed
+66 -121

No files matched your search

+9 -61
View File
@@ -2,8 +2,8 @@
import {
nostrClient,
requestDefaultExtensionPermissions,
getActiveSigner,
} from "../nostrClientFacade.js";
import { getActiveSigner } from "../nostr/index.js";
import { isSessionActor } from "../nostr/sessionActor.js";
import {
buildHashtagPreferenceEvent,
@@ -622,7 +622,10 @@ class HashtagPreferencesService {
return { ok: false, error };
}
const signer = getActiveSigner();
let signer = getActiveSigner();
if (!signer && typeof nostrClient?.ensureActiveSignerForPubkey === "function") {
signer = await nostrClient.ensureActiveSignerForPubkey(userPubkey);
}
const signerHasNip04 = typeof signer?.nip04Decrypt === "function";
const signerHasNip44 = typeof signer?.nip44Decrypt === "function";
@@ -663,39 +666,6 @@ class HashtagPreferencesService {
registerDecryptor("nip04", (payload) => signer.nip04Decrypt(userPubkey, payload));
}
const nostrApi =
typeof window !== "undefined" && window && window.nostr ? window.nostr : null;
if (nostrApi) {
const nip04 =
nostrApi.nip04 && typeof nostrApi.nip04.decrypt === "function"
? nostrApi.nip04
: null;
if (nip04 && !decryptors.has("nip04")) {
registerDecryptor("nip04", (payload) => nip04.decrypt(userPubkey, payload));
}
const nip44 =
nostrApi.nip44 && typeof nostrApi.nip44 === "object"
? nostrApi.nip44
: null;
if (nip44) {
if (typeof nip44.decrypt === "function" && !decryptors.has("nip44")) {
registerDecryptor("nip44", (payload) => nip44.decrypt(userPubkey, payload));
}
const nip44v2 = nip44.v2 && typeof nip44.v2 === "object" ? nip44.v2 : null;
if (nip44v2 && typeof nip44v2.decrypt === "function") {
registerDecryptor("nip44_v2", (payload) =>
nip44v2.decrypt(userPubkey, payload),
);
if (!decryptors.has("nip44")) {
registerDecryptor("nip44", (payload) =>
nip44v2.decrypt(userPubkey, payload),
);
}
}
}
}
if (!decryptors.size) {
const error = new Error(
"No decryptors available for hashtag preferences payload.",
@@ -759,7 +729,10 @@ class HashtagPreferencesService {
signer = await nostrClient.ensureActiveSignerForPubkey(targetPubkey);
}
if (!signer || typeof signer.signEvent !== "function") {
const canSign = typeof signer?.canSign === "function"
? signer.canSign()
: typeof signer?.signEvent === "function";
if (!canSign || typeof signer?.signEvent !== "function") {
const error = new Error("An active signer is required to publish preferences.");
error.code = "hashtag-preferences-missing-signer";
throw error;
@@ -806,31 +779,6 @@ class HashtagPreferencesService {
registerEncryptor("nip04", (value) => signer.nip04Encrypt(targetPubkey, value));
}
const nostrApi =
typeof window !== "undefined" && window && window.nostr ? window.nostr : null;
if (nostrApi) {
const nip44 =
nostrApi.nip44 && typeof nostrApi.nip44 === "object"
? nostrApi.nip44
: null;
if (nip44) {
if (typeof nip44.encrypt === "function") {
registerEncryptor("nip44", (value) => nip44.encrypt(targetPubkey, value));
}
const nip44v2 = nip44.v2 && typeof nip44.v2 === "object" ? nip44.v2 : null;
if (nip44v2 && typeof nip44v2.encrypt === "function") {
registerEncryptor("nip44_v2", (value) =>
nip44v2.encrypt(targetPubkey, value),
);
}
}
if (typeof nostrApi.nip04?.encrypt === "function") {
registerEncryptor("nip04", (value) =>
nostrApi.nip04.encrypt(targetPubkey, value),
);
}
}
if (!encryptors.length) {
const error = new Error("No encryptors available to publish preferences.");
error.code = "hashtag-preferences-no-encryptor";
+17 -6
View File
@@ -1,4 +1,8 @@
import { nostrClient } from "../nostrClientFacade.js";
import {
getActiveSigner,
nostrClient,
requestDefaultExtensionPermissions,
} from "../nostrClientFacade.js";
import { publishEventToRelays, assertAnyRelayAccepted } from "../nostrPublish.js";
import { accessControl } from "../accessControl.js";
import { userBlocks, USER_BLOCK_EVENTS } from "../userBlocks.js";
@@ -1542,15 +1546,22 @@ export class ModerationService {
await this.ensurePool();
const extension = typeof window !== "undefined" ? window.nostr : null;
if (!extension || typeof extension.signEvent !== "function") {
let signer = getActiveSigner();
if (!signer && typeof this.nostrClient?.ensureActiveSignerForPubkey === "function") {
signer = await this.nostrClient.ensureActiveSignerForPubkey(viewer);
}
const canSign = typeof signer?.canSign === "function"
? signer.canSign()
: typeof signer?.signEvent === "function";
if (!canSign || typeof signer?.signEvent !== "function") {
const error = new Error("nostr-extension-missing");
error.code = "nostr-extension-missing";
throw error;
}
if (typeof this.nostrClient?.ensureExtensionPermissions === "function") {
const permissionResult = await this.nostrClient.ensureExtensionPermissions([
if (signer?.type === "extension") {
const permissionResult = await requestDefaultExtensionPermissions([
"sign_event",
"get_public_key",
]);
@@ -1583,7 +1594,7 @@ export class ModerationService {
let signedEvent;
try {
signedEvent = await extension.signEvent(event);
signedEvent = await signer.signEvent(event);
} catch (error) {
const wrapped = new Error("signature-failed");
wrapped.code = "signature-failed";
+10 -34
View File
@@ -1,12 +1,10 @@
// js/subscriptions.js
import {
getActiveSigner,
nostrClient,
requestDefaultExtensionPermissions,
} from "./nostrClientFacade.js";
import {
getActiveSigner,
convertEventToVideo as sharedConvertEventToVideo,
} from "./nostr/index.js";
import { convertEventToVideo as sharedConvertEventToVideo } from "./nostr/index.js";
import { normalizeNostrPubkey } from "./nostr/nip46Client.js";
import {
listVideoViewEvents,
@@ -557,7 +555,10 @@ class SubscriptionsManager {
decryptors.set(scheme, handler);
};
const signer = getActiveSigner();
let signer = getActiveSigner();
if (!signer && typeof nostrClient?.ensureActiveSignerForPubkey === "function") {
signer = await nostrClient.ensureActiveSignerForPubkey(userPubkey);
}
const signerHasNip04 = typeof signer?.nip04Decrypt === "function";
const signerHasNip44 = typeof signer?.nip44Decrypt === "function";
@@ -569,34 +570,6 @@ class SubscriptionsManager {
registerDecryptor("nip44", (payload) => signer.nip44Decrypt(userPubkey, payload));
}
const nostrApi =
typeof window !== "undefined" && window && window.nostr ? window.nostr : null;
if (nostrApi) {
if (!signerHasNip04 && nostrApi.nip04 && typeof nostrApi.nip04.decrypt === "function") {
registerDecryptor("nip04", (payload) =>
nostrApi.nip04.decrypt(userPubkey, payload)
);
}
const nip44 =
nostrApi.nip44 && typeof nostrApi.nip44 === "object" ? nostrApi.nip44 : null;
if (nip44) {
if (!signerHasNip44 && typeof nip44.decrypt === "function") {
registerDecryptor("nip44", (payload) => nip44.decrypt(userPubkey, payload));
}
const nip44v2 = nip44.v2 && typeof nip44.v2 === "object" ? nip44.v2 : null;
if (nip44v2 && typeof nip44v2.decrypt === "function") {
registerDecryptor("nip44_v2", (payload) =>
nip44v2.decrypt(userPubkey, payload)
);
if (!decryptors.has("nip44")) {
registerDecryptor("nip44", (payload) => nip44v2.decrypt(userPubkey, payload));
}
}
}
}
if (!decryptors.size) {
const error = new Error(
"No active signer or extension decryptors are available for subscriptions."
@@ -700,7 +673,10 @@ class SubscriptionsManager {
signer = await nostrClient.ensureActiveSignerForPubkey(userPubkey);
}
if (!signer) {
const canSign = typeof signer?.canSign === "function"
? signer.canSign()
: typeof signer?.signEvent === "function";
if (!canSign) {
const error = new Error(
"An active signer is required to update subscriptions."
);
+19 -5
View File
@@ -11,6 +11,10 @@ import { createTorrentMetadata } from "../../utils/torrentHash.js";
import { sanitizeBucketName } from "../../storage/r2-mgmt.js";
import { buildR2Key, buildPublicUrl } from "../../r2.js";
import { PROVIDERS } from "../../services/storageService.js";
import {
getActiveSigner,
requestDefaultExtensionPermissions,
} from "../../nostrClientFacade.js";
const INFO_HASH_PATTERN = /^[a-f0-9]{40}$/;
@@ -557,7 +561,7 @@ export class UploadModal {
this.toggleStorageView("form");
}
} catch (err) {
console.error("Failed to load connection", err);
userLogger.error("Failed to load connection", err);
this.toggleStorageView("form");
}
}
@@ -577,18 +581,28 @@ export class UploadModal {
const pubkey = this.getCurrentPubkey ? this.getCurrentPubkey() : null;
if (!pubkey) return;
// We need a signer. Try window.nostr or authService
let signer = window.nostr;
// We need a signer. Try active signer or authService
let signer = getActiveSigner();
if (!signer && this.authService?.signer) {
signer = this.authService.signer;
}
if (!signer) {
const canSign = typeof signer?.canSign === "function"
? signer.canSign()
: typeof signer?.signEvent === "function";
if (!canSign) {
alert("No signer available to unlock storage.");
return;
}
try {
if (signer?.type === "extension") {
const permissionResult = await requestDefaultExtensionPermissions();
if (!permissionResult?.ok) {
alert("Extension permissions are required to unlock storage.");
return;
}
}
if (this.toggles.storageUnlock) {
this.toggles.storageUnlock.textContent = "Unlocking...";
this.toggles.storageUnlock.disabled = true;
@@ -598,7 +612,7 @@ export class UploadModal {
this.updateLockUi();
await this.loadFromStorage();
} catch (err) {
console.error("Unlock failed", err);
userLogger.error("Unlock failed", err);
alert("Failed to unlock storage: " + err.message);
} finally {
if (this.toggles.storageUnlock) {
+11 -15
View File
@@ -1,6 +1,7 @@
// js/watchHistoryService.js
import {
getActiveSigner,
nostrClient,
requestDefaultExtensionPermissions,
} from "./nostrClientFacade.js";
@@ -73,31 +74,26 @@ function getSessionActorKey() {
return normalizeActorKey(nostrClient?.sessionActor?.pubkey);
}
function shouldUseExtensionForHistory(actorKey) {
async function ensureWatchHistoryExtensionPermissions(actorKey) {
const normalizedActor = normalizeActorKey(actorKey);
if (!normalizedActor) {
return false;
return { ok: true };
}
const loggedActor = normalizeActorKey(nostrClient?.pubkey);
if (!loggedActor || loggedActor !== normalizedActor) {
return false;
return { ok: true };
}
if (typeof window === "undefined") {
return false;
let signer = getActiveSigner();
if (!signer && typeof nostrClient?.ensureActiveSignerForPubkey === "function") {
signer = await nostrClient.ensureActiveSignerForPubkey(normalizedActor);
}
const extension = window.nostr;
if (!extension) {
return false;
}
return typeof extension.signEvent === "function";
}
async function ensureWatchHistoryExtensionPermissions(actorKey) {
if (!shouldUseExtensionForHistory(actorKey)) {
const canSign = typeof signer?.canSign === "function"
? signer.canSign()
: typeof signer?.signEvent === "function";
if (!canSign || signer?.type !== "extension") {
return { ok: true };
}