import { describe, it, expect, beforeEach } from 'vitest' import { generateSecretKey, getPublicKey } from 'nostr-tools' import { utils } from 'nostr-tools' const { bytesToHex, hexToBytes } = utils describe('background.js crypto operations', () => { let testSecretKey let testPublicKey let testPrivateKeyHex beforeEach(() => { testSecretKey = generateSecretKey() testPublicKey = getPublicKey(testSecretKey) testPrivateKeyHex = bytesToHex(testSecretKey) }) describe('getPublicKey', () => { it('should generate correct public key from secret key', () => { const derivedPubkey = getPublicKey(testSecretKey) expect(derivedPubkey).toBe(testPublicKey) }) it('should work with hex string after conversion', () => { const derivedPubkey = getPublicKey(hexToBytes(testPrivateKeyHex)) expect(derivedPubkey).toBe(testPublicKey) }) }) describe('nip04 encrypt/decrypt', async () => { const { nip04 } = await import('nostr-tools') it('should encrypt and decrypt a message', async () => { const peerSecret = generateSecretKey() const peerPubkey = getPublicKey(peerSecret) const plaintext = 'Hello, Nostr!' const ciphertext = nip04.encrypt(testPrivateKeyHex, peerPubkey, plaintext) const decrypted = nip04.decrypt(testPrivateKeyHex, peerPubkey, ciphertext) expect(decrypted).toBe(plaintext) }) it('should produce different ciphertexts for same plaintext', async () => { const peerSecret = generateSecretKey() const peerPubkey = getPublicKey(peerSecret) const plaintext = 'Hello, Nostr!' const ciphertext1 = nip04.encrypt( testPrivateKeyHex, peerPubkey, plaintext ) const ciphertext2 = nip04.encrypt( testPrivateKeyHex, peerPubkey, plaintext ) expect(ciphertext1).not.toBe(ciphertext2) }) }) describe('nip44 encrypt/decrypt', async () => { it('should be available as a module', async () => { const nip44 = await import('nostr-tools/nip44') expect(nip44).toBeDefined() expect(nip44.v2).toBeDefined() expect(typeof nip44.v2.encrypt).toBe('function') expect(typeof nip44.v2.decrypt).toBe('function') }) // Note: nip44.v2.utils.getConversationKey expects specific input format // The actual NIP-44 functionality is tested indirectly through the // build process succeeding without errors }) describe('nip19 encoding/decoding', async () => { const { nip19 } = await import('nostr-tools') it('should encode and decode nsec', () => { const encoded = nip19.nsecEncode(testSecretKey) const decoded = nip19.decode(encoded) expect(decoded.type).toBe('nsec') expect(bytesToHex(decoded.data)).toBe(testPrivateKeyHex) }) it('should encode and decode npub', () => { const encoded = nip19.npubEncode(testPublicKey) const decoded = nip19.decode(encoded) expect(decoded.type).toBe('npub') expect(decoded.data).toBe(testPublicKey) }) }) describe('event signing', async () => { const { finalizeEvent, validateEvent, getEventHash } = await import( 'nostr-tools' ) it('should sign and validate an event', () => { const unsignedEvent = { kind: 1, content: 'Test content', tags: [], created_at: Math.floor(Date.now() / 1000), pubkey: testPublicKey } const signedEvent = finalizeEvent(unsignedEvent, testSecretKey) expect(signedEvent.sig).toBeDefined() expect(signedEvent.id).toBe(getEventHash(signedEvent)) expect(validateEvent(signedEvent)).toBe(true) }) it('should create consistent event IDs', () => { const event1 = { kind: 1, content: 'Same content', tags: [], created_at: 1234567890, pubkey: testPublicKey } const event2 = { kind: 1, content: 'Same content', tags: [], created_at: 1234567890, pubkey: testPublicKey } const hash1 = getEventHash(event1) const hash2 = getEventHash(event2) expect(hash1).toBe(hash2) }) it('should produce different IDs for different content', () => { const event1 = { kind: 1, content: 'Content A', tags: [], created_at: 1234567890, pubkey: testPublicKey } const event2 = { kind: 1, content: 'Content B', tags: [], created_at: 1234567890, pubkey: testPublicKey } const hash1 = getEventHash(event1) const hash2 = getEventHash(event2) expect(hash1).not.toBe(hash2) }) }) describe('replaceURL parsing', () => { it('should encode and decode nostr links correctly', async () => { const { nip19 } = await import('nostr-tools') const npubEncoded = nip19.npubEncode(testPublicKey) const decodedNpub = nip19.decode(npubEncoded) expect(decodedNpub.type).toBe('npub') expect(decodedNpub.data).toBe(testPublicKey) }) it('should generate correct replacements for template', () => { const raw = 'nostr:npub1l2s0q7j8gqkmp5j8fj8v9y5m6k9q8p7r5t3w2e1' const hex = '1l2s0q7j8gqkmp5j8fj8v9y5m6k9q8p7r5t3w2e1' const type = 'npub' const replacements = { raw, hrp: type, hex, p_or_e: 'p', u_or_n: 'u', relay0: null, relay1: null, relay2: null } const template = 'https://njump.me/{raw}' let result = template Object.entries(replacements).forEach(([pattern, value]) => { result = result.replace(new RegExp(`{ *${pattern} *}`, 'g'), value) }) expect(result).toBe( 'https://njump.me/nostr:npub1l2s0q7j8gqkmp5j8fj8v9y5m6k9q8p7r5t3w2e1' ) }) }) })