Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Organizing and improving nip17 and nip59 #450

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 1 addition & 31 deletions nip17.test.ts
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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])
})
})
39 changes: 4 additions & 35 deletions nip17.ts
Original file line number Diff line number Diff line change
@@ -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 = {
Expand Down Expand Up @@ -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)
}

Expand All @@ -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
Expand All @@ -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<Event[] | undefined> {
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
68 changes: 65 additions & 3 deletions nip59.test.ts
Original file line number Diff line number Diff line change
@@ -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'

Expand All @@ -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 = {
Expand All @@ -30,17 +30,79 @@ 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,
content: 'Are you going to the party tonight?',
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])
})
})
47 changes: 47 additions & 0 deletions nip59.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }

Expand Down Expand Up @@ -65,7 +66,53 @@ export function wrapEvent(event: Partial<UnsignedEvent>, senderPrivateKey: Uint8
return createWrap(seal, recipientPublicKey)
}

export function wrapManyEvents(
event: Partial<UnsignedEvent>,
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<Event[] | undefined> {
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
}
}
Loading