clone of github.com/decent-newsroom/newsroom
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

85 lines
2.3 KiB

// Shared signer manager for Nostr signers (remote and extension)
import { SimplePool } from 'nostr-tools';
import { BunkerSigner } from 'nostr-tools/nip46';
const REMOTE_SIGNER_KEY = 'amber_remote_signer';
let remoteSigner = null;
let remoteSignerPromise = null;
let remoteSignerPool = null;
export async function getSigner() {
// If remote signer session is active, use it
const session = getRemoteSignerSession();
if (session) {
if (remoteSigner) return remoteSigner;
if (remoteSignerPromise) return remoteSignerPromise;
remoteSignerPromise = createRemoteSigner(session)
.then(signer => {
remoteSigner = signer;
return signer;
})
.catch(error => {
// Reset promise on failure so next call can retry
remoteSignerPromise = null;
throw error;
});
return remoteSignerPromise;
}
// Fallback to browser extension
if (window.nostr && typeof window.nostr.signEvent === 'function') {
return window.nostr;
}
throw new Error('No signer available');
}
export function setRemoteSignerSession(session) {
localStorage.setItem(REMOTE_SIGNER_KEY, JSON.stringify(session));
}
export function clearRemoteSignerSession() {
localStorage.removeItem(REMOTE_SIGNER_KEY);
remoteSigner = null;
remoteSignerPromise = null;
if (remoteSignerPool) {
try { remoteSignerPool.close?.([]); } catch (_) {}
remoteSignerPool = null;
}
}
export function getRemoteSignerSession() {
const raw = localStorage.getItem(REMOTE_SIGNER_KEY);
if (!raw) return null;
try {
return JSON.parse(raw);
} catch {
return null;
}
}
async function createRemoteSigner(session) {
remoteSignerPool = new SimplePool();
// Add timeout to prevent hanging indefinitely
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Remote signer connection timeout')), 10000);
});
try {
return await Promise.race([
BunkerSigner.fromURI(session.privkey, session.uri, { pool: remoteSignerPool }),
timeoutPromise
]);
} catch (error) {
// Clean up on error
if (remoteSignerPool) {
try { remoteSignerPool.close?.([]); } catch (_) {}
remoteSignerPool = null;
}
remoteSigner = null;
remoteSignerPromise = null;
throw error;
}
}