diff --git a/nip17.test.ts b/nip17.test.ts index d9bda58..2f6b438 100644 --- a/nip17.test.ts +++ b/nip17.test.ts @@ -1,7 +1,7 @@ import { test, expect } from 'bun:test' import { getPublicKey } from './pure.ts' import { decode } from './nip19.ts' -import { wrapEvent, wrapManyEvents, unwrapEvent, unwrapManyEvents, getWrappedEvents } from './nip17.ts' +import { wrapEvent, wrapManyEvents, unwrapEvent } from './nip17.ts' const senderPrivateKey = decode(`nsec1p0ht6p3wepe47sjrgesyn4m50m6avk2waqudu9rl324cg2c4ufesyp6rdg`).data @@ -94,33 +94,3 @@ test('unwrapEvent', () => { expect(result.pubkey).toEqual(expected.pubkey) expect(result.tags).toEqual(expected.tags) }) - -test('getWrappedEvents and unwrapManyEvents', async () => { - const expected = [ - { - created_at: 1729721879, - content: 'Hello!', - tags: [['p', '33d6bb037bf2e8c4571708e480e42d141bedc5a562b4884ec233b22d6fdea6aa']], - kind: 14, - pubkey: 'c0f56665e73eedc90b9565ecb34d961a2eb7ac1e2747899e4f73a813f940bc22', - id: 'aee0a3e6487b2ac8c1851cc84f3ae0fca9af8a9bdad85c4ba5fdf45d3ee817c3', - }, - { - created_at: 1729722025, - content: 'How are you?', - tags: [['p', '33d6bb037bf2e8c4571708e480e42d141bedc5a562b4884ec233b22d6fdea6aa']], - kind: 14, - pubkey: 'c0f56665e73eedc90b9565ecb34d961a2eb7ac1e2747899e4f73a813f940bc22', - id: '212387ec5efee7d6eb20b747121e9fc1adb798de6c3185e932335bb1bcc61a77', - }, - ] - const relays = ['wss://relay.damus.io', 'wss://nos.lol'] - const privateKey = '582c3e7902c10c84d1cfe899a102e56bde628972d58d63011163ce0cdf4279b6' - const publicKey = '33d6bb037bf2e8c4571708e480e42d141bedc5a562b4884ec233b22d6fdea6aa' - const wrappedEvents = await getWrappedEvents(publicKey, relays) - const unwrappedEvents = unwrapManyEvents(wrappedEvents, privateKey) - - unwrappedEvents.forEach((event, index) => { - expect(event).toEqual(expected[index]) - }) -}) diff --git a/nip17.ts b/nip17.ts index 117b3ff..7e5ece2 100644 --- a/nip17.ts +++ b/nip17.ts @@ -1,7 +1,5 @@ -import { Event } from './core.ts' -import { PrivateDirectMessage, GiftWrap } from './kinds.ts' +import { PrivateDirectMessage } from './kinds.ts' import { getPublicKey } from './pure' -import { SimplePool } from './pool' import * as nip59 from './nip59' type Recipient = { @@ -50,10 +48,7 @@ export function wrapEvent( conversationTitle?: string, replyTo?: ReplyTo, ) { - // Create the event using createEvent const event = createEvent(recipient, message, conversationTitle, replyTo) - - // Wrap the created event using nip59 return nip59.wrapEvent(event, senderPrivateKey, recipient.publicKey) } @@ -70,7 +65,7 @@ export function wrapManyEvents( const senderPublicKey = getPublicKey(senderPrivateKey) - // Initialize the wraps array with the sender's own wrapped event + // Initialize the wrappeds array with the sender's own wrapped event const wrappeds = [wrapEvent(senderPrivateKey, { publicKey: senderPublicKey }, message, conversationTitle, replyTo)] // Wrap the event for each recipient @@ -81,32 +76,6 @@ export function wrapManyEvents( return wrappeds } -export function unwrapEvent(wrappedEvent: Event, recipientPrivateKey: Uint8Array) { - return nip59.unwrapEvent(wrappedEvent, recipientPrivateKey) -} - -export function unwrapManyEvents(wrappedEvents: Event[], recipientPrivateKey: Uint8Array) { - let unwrappedEvents = [] - - wrappedEvents.forEach(e => { - unwrappedEvents.push(unwrapEvent(e, recipientPrivateKey)) - }) - - unwrappedEvents.sort((a, b) => a.created_at - b.created_at) - - return unwrappedEvents -} - -export async function getWrappedEvents(pubKey: string, relays: string[] = []): Promise { - const pool = new SimplePool() +export const unwrapEvent = nip59.unwrapEvent - try { - const events: Event[] = await pool.querySync(relays, { kinds: [GiftWrap], '#p': [pubKey] }) - pool.close(relays) - - return events - } catch (error) { - console.error('Failed to:', error) - return undefined - } -} +export const unwrapManyEvents = nip59.unwrapManyEvents diff --git a/nip59.test.ts b/nip59.test.ts index e4395b7..2863248 100644 --- a/nip59.test.ts +++ b/nip59.test.ts @@ -1,5 +1,5 @@ import { test, expect } from 'bun:test' -import { wrapEvent, unwrapEvent } from './nip59.ts' +import { wrapEvent, wrapManyEvents, unwrapEvent, unwrapManyEvents, getWrappedEvents } from './nip59.ts' import { decode } from './nip19.ts' import { getPublicKey } from './pure.ts' @@ -11,7 +11,7 @@ const event = { content: 'Are you going to the party tonight?', } -const wrapedEvent = wrapEvent(event, senderPrivateKey, recipientPublicKey) +const wrappedEvent = wrapEvent(event, senderPrivateKey, recipientPublicKey) test('wrapEvent', () => { const expected = { @@ -30,6 +30,38 @@ test('wrapEvent', () => { expect(result.tags).toEqual(expected.tags) }) +test('wrapManyEvent', () => { + const expected = [ + { + kind: 1059, + content: '', + created_at: 1729581521, + tags: [['p', '611df01bfcf85c26ae65453b772d8f1dfd25c264621c0277e1fc1518686faef9']], + pubkey: '', + id: '', + sig: '', + [Symbol('verified')]: true, + }, + { + kind: 1059, + content: '', + created_at: 1729594619, + tags: [['p', '166bf3765ebd1fc55decfe395beff2ea3b2a4e0a8946e7eb578512b555737c99']], + pubkey: '', + id: '', + sig: '', + [Symbol('verified')]: true, + }, + ] + + const wrappedEvents = wrapManyEvents(event, senderPrivateKey, [recipientPublicKey]) + + wrappedEvents.forEach((event, index) => { + expect(event.kind).toEqual(expected[index].kind) + expect(event.tags).toEqual(expected[index].tags) + }) +}) + test('unwrapEvent', () => { const expected = { kind: 1, @@ -37,10 +69,40 @@ test('unwrapEvent', () => { pubkey: '611df01bfcf85c26ae65453b772d8f1dfd25c264621c0277e1fc1518686faef9', tags: [], } - const result = unwrapEvent(wrapedEvent, recipientPrivateKey) + const result = unwrapEvent(wrappedEvent, recipientPrivateKey) expect(result.kind).toEqual(expected.kind) expect(result.content).toEqual(expected.content) expect(result.pubkey).toEqual(expected.pubkey) expect(result.tags).toEqual(expected.tags) }) + +test('getWrappedEvents and unwrapManyEvents', async () => { + const expected = [ + { + created_at: 1729721879, + content: 'Hello!', + tags: [['p', '33d6bb037bf2e8c4571708e480e42d141bedc5a562b4884ec233b22d6fdea6aa']], + kind: 14, + pubkey: 'c0f56665e73eedc90b9565ecb34d961a2eb7ac1e2747899e4f73a813f940bc22', + id: 'aee0a3e6487b2ac8c1851cc84f3ae0fca9af8a9bdad85c4ba5fdf45d3ee817c3', + }, + { + created_at: 1729722025, + content: 'How are you?', + tags: [['p', '33d6bb037bf2e8c4571708e480e42d141bedc5a562b4884ec233b22d6fdea6aa']], + kind: 14, + pubkey: 'c0f56665e73eedc90b9565ecb34d961a2eb7ac1e2747899e4f73a813f940bc22', + id: '212387ec5efee7d6eb20b747121e9fc1adb798de6c3185e932335bb1bcc61a77', + }, + ] + const relays = ['wss://relay.damus.io', 'wss://nos.lol'] + const privateKey = '582c3e7902c10c84d1cfe899a102e56bde628972d58d63011163ce0cdf4279b6' + const publicKey = '33d6bb037bf2e8c4571708e480e42d141bedc5a562b4884ec233b22d6fdea6aa' + const wrappedEvents = await getWrappedEvents(publicKey, relays) + const unwrappedEvents = unwrapManyEvents(wrappedEvents, privateKey) + + unwrappedEvents.forEach((event, index) => { + expect(event).toEqual(expected[index]) + }) +}) diff --git a/nip59.ts b/nip59.ts index fa71d8b..63a07d4 100644 --- a/nip59.ts +++ b/nip59.ts @@ -2,6 +2,7 @@ import { EventTemplate, UnsignedEvent, Event } from './core.ts' import { getConversationKey, decrypt, encrypt } from './nip44.ts' import { getEventHash, generateSecretKey, finalizeEvent, getPublicKey } from './pure.ts' import { Seal, GiftWrap } from './kinds.ts' +import { SimplePool } from './pool' type Rumor = UnsignedEvent & { id: string } @@ -65,7 +66,53 @@ export function wrapEvent(event: Partial, senderPrivateKey: Uint8 return createWrap(seal, recipientPublicKey) } +export function wrapManyEvents( + event: Partial, + senderPrivateKey: Uint8Array, + recipientsPublicKeys: string[], +) { + if (!recipientsPublicKeys || recipientsPublicKeys.length === 0) { + throw new Error('At least one recipient is required.') + } + + const senderPublicKey = getPublicKey(senderPrivateKey) + + const wrappeds = [wrapEvent(event, senderPrivateKey, senderPublicKey)] + + recipientsPublicKeys.forEach(recipientPublicKey => { + wrappeds.push(wrapEvent(event, senderPrivateKey, recipientPublicKey)) + }) + + return wrappeds +} + export function unwrapEvent(wrap: Event, recipientPrivateKey: Uint8Array) { const unwrappedSeal = nip44Decrypt(wrap, recipientPrivateKey) return nip44Decrypt(unwrappedSeal, recipientPrivateKey) } + +export function unwrapManyEvents(wrappedEvents: Event[], recipientPrivateKey: Uint8Array) { + let unwrappedEvents = [] + + wrappedEvents.forEach(e => { + unwrappedEvents.push(unwrapEvent(e, recipientPrivateKey)) + }) + + unwrappedEvents.sort((a, b) => a.created_at - b.created_at) + + return unwrappedEvents +} + +export async function getWrappedEvents(pubKey: string, relays: string[] = []): Promise { + const pool = new SimplePool() + + try { + const events: Event[] = await pool.querySync(relays, { kinds: [GiftWrap], '#p': [pubKey] }) + pool.close(relays) + + return events + } catch (error) { + console.error('Failed to:', error) + return undefined + } +}