import { nip98 } from "nostr-tools"; import type { NostrEvent } from "@nostrify/nostrify"; // Extend Window interface to include nostr declare global { interface Window { nostr?: { getPublicKey(): Promise; signEvent(event: NostrEvent): Promise; }; } } /** * Create NIP-98 auth header for HTTP requests using nostr-tools * @param url - Full URL being requested * @param method - HTTP method (GET, POST, etc.) * @param body - Request body (for POST requests) * @param signer - Signer object with signEvent method * @returns Promise - Authorization header value */ // Signer interface for NIP-98 authentication interface Nip98Signer { signEvent: (event: NostrEvent) => Promise; getPublicKey?: () => Promise; } export async function createNip98AuthHeader( url: string, method: string, body?: Record | string | undefined, signer?: Nip98Signer ): Promise { if (!signer?.signEvent) { throw new Error("Signer with signEvent method is required for NIP-98 authentication"); } // Create a safe wrapper function that doesn't expose private fields const signerFunction = async (event: NostrEvent): Promise => { return await signer.signEvent(event); }; // Use nip98.getToken which handles everything internally // This includes creating the auth event, signing it, and packing it into a token // The payload should be an object - nip98.getToken handles stringification internally let payload: Record | undefined; if (body !== undefined) { if (typeof body === 'string') { try { payload = JSON.parse(body); } catch { // If it's not valid JSON, wrap it in an object payload = { data: body }; } } else { payload = body; } } const token = await nip98.getToken( url, method, signerFunction, true, // includeAuthorizationScheme - adds "Nostr " prefix payload // payload as object ); return token; }