diff --git a/README.md b/README.md
index 8e03269..68c62bd 100644
--- a/README.md
+++ b/README.md
@@ -19,36 +19,31 @@ If using TypeScript, this package requires TypeScript >= 5.0.
### Generating a private key and a public key
```js
-import { generatePrivateKey, getPublicKey } from 'nostr-tools'
+import { generateSecretKey, getPublicKey } from 'nostr-tools'
-let sk = generatePrivateKey() // `sk` is a hex string
+let sk = generateSecretKey() // `sk` is a hex string
let pk = getPublicKey(sk) // `pk` is a hex string
```
### Creating, signing and verifying events
```js
-import { validateEvent, verifySignature, getSignature, getEventHash, getPublicKey } from 'nostr-tools'
+import { finalizeEvent, verifyEvent } from 'nostr-tools'
-let event = {
+let event = finalizeEvent({
kind: 1,
created_at: Math.floor(Date.now() / 1000),
tags: [],
content: 'hello',
- pubkey: getPublicKey(privateKey),
-}
+}, privateKey)
-event.id = getEventHash(event)
-event.sig = getSignature(event, privateKey)
-
-let ok = validateEvent(event)
-let veryOk = verifySignature(event)
+let isGood = verifyEvent(event)
```
### Interacting with a relay
```js
-import { relayConnect, finishEvent, generatePrivateKey, getPublicKey } from 'nostr-tools'
+import { relayConnect, finalizeEvent, generateSecretKey, getPublicKey } from 'nostr-tools'
const relay = await relayConnect('wss://relay.example.com')
console.log(`connected to ${relay.url}`)
@@ -68,7 +63,7 @@ const sub = relay.subscribe([
})
// let's publish a new event while simultaneously monitoring the relay for it
-let sk = generatePrivateKey()
+let sk = generateSecretKey()
let pk = getPublicKey(sk)
let sub = relay.sub([
@@ -90,7 +85,7 @@ let event = {
}
// this assigns the pubkey, calculates the event id and signs the event in a single step
-const signedEvent = finishEvent(event, sk)
+const signedEvent = finalizeEvent(event, sk)
await relay.publish(signedEvent)
let events = await relay.list([{ kinds: [0, 1] }])
@@ -184,21 +179,21 @@ nip05.useFetchImplementation(require('node-fetch'))
### Encoding and decoding NIP-19 codes
```js
-import { nip19, generatePrivateKey, getPublicKey } from 'nostr-tools'
+import { nip19, generateSecretKey, getPublicKey } from 'nostr-tools'
-let sk = generatePrivateKey()
+let sk = generateSecretKey()
let nsec = nip19.nsecEncode(sk)
let { type, data } = nip19.decode(nsec)
assert(type === 'nsec')
assert(data === sk)
-let pk = getPublicKey(generatePrivateKey())
+let pk = getPublicKey(generateSecretKey())
let npub = nip19.npubEncode(pk)
let { type, data } = nip19.decode(npub)
assert(type === 'npub')
assert(data === pk)
-let pk = getPublicKey(generatePrivateKey())
+let pk = getPublicKey(generateSecretKey())
let relays = ['wss://relay.nostr.example.mydomain.example.com', 'wss://nostr.banana.com']
let nprofile = nip19.nprofileEncode({ pubkey: pk, relays })
let { type, data } = nip19.decode(nprofile)
@@ -212,7 +207,7 @@ assert(data.relays.length === 2)
```html
```
diff --git a/core.test.ts b/core.test.ts
index 2b9aba3..72f2153 100644
--- a/core.test.ts
+++ b/core.test.ts
@@ -11,10 +11,10 @@ import {
generateSecretKey,
} from './pure.ts'
import { ShortTextNote } from './kinds.ts'
-import { hexToBytes } from '@noble/hashes/utils'
+import { bytesToHex, hexToBytes } from '@noble/hashes/utils'
test('private key generation', () => {
- expect(generateSecretKey()).toMatch(/[a-f0-9]{64}/)
+ expect(bytesToHex(generateSecretKey())).toMatch(/[a-f0-9]{64}/)
})
test('public key generation', () => {
@@ -30,7 +30,7 @@ test('public key from private key deterministic', () => {
}
})
-describe('finishEvent', () => {
+describe('finalizeEvent', () => {
test('should create a signed event from a template', () => {
const privateKey = hexToBytes('d217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf')
const publicKey = getPublicKey(privateKey)
@@ -211,7 +211,7 @@ describe('validateEvent', () => {
})
})
-describe('verifySignature', () => {
+describe('verifyEvent', () => {
test('should return true for a valid event signature', () => {
const privateKey = hexToBytes('d217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf')
const event = finalizeEvent(
diff --git a/filter.ts b/filter.ts
index 203f6ec..4cda3b6 100644
--- a/filter.ts
+++ b/filter.ts
@@ -1,4 +1,4 @@
-import { Event } from './event.ts'
+import { Event } from './pure.ts'
export type Filter = {
ids?: string[]
diff --git a/index.ts b/index.ts
index ae85ccb..76d5626 100644
--- a/index.ts
+++ b/index.ts
@@ -1,6 +1,6 @@
-export * from './keys.ts'
+export * from './pure.ts'
export * from './relay.ts'
-export * from './event.ts'
+export * from './pure.ts'
export * from './filter.ts'
export * from './pool.ts'
export * from './references.ts'
diff --git a/nip04.test.ts b/nip04.test.ts
index 4e744ac..67cada3 100644
--- a/nip04.test.ts
+++ b/nip04.test.ts
@@ -2,7 +2,8 @@ import { test, expect } from 'bun:test'
import crypto from 'node:crypto'
import { encrypt, decrypt } from './nip04.ts'
-import { getPublicKey, generatePrivateKey } from './keys.ts'
+import { getPublicKey, generateSecretKey } from './pure.ts'
+import { bytesToHex, hexToBytes } from '@noble/hashes/utils'
try {
// @ts-ignore
@@ -13,20 +14,20 @@ try {
}
test('encrypt and decrypt message', async () => {
- let sk1 = generatePrivateKey()
- let sk2 = generatePrivateKey()
+ let sk1 = generateSecretKey()
+ let sk2 = generateSecretKey()
let pk1 = getPublicKey(sk1)
let pk2 = getPublicKey(sk2)
- let ciphertext = await encrypt(sk1, pk2, 'hello')
+ let ciphertext = await encrypt(bytesToHex(sk1), pk2, 'hello')
- expect(await decrypt(sk2, pk1, ciphertext)).toEqual('hello')
+ expect(await decrypt(bytesToHex(sk2), pk1, ciphertext)).toEqual('hello')
})
test('decrypt message from go-nostr', async () => {
let sk1 = '91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe'
let sk2 = '96f6fa197aa07477ab88f6981118466ae3a982faab8ad5db9d5426870c73d220'
- let pk1 = getPublicKey(sk1)
+ let pk1 = getPublicKey(hexToBytes(sk1))
let ciphertext = 'zJxfaJ32rN5Dg1ODjOlEew==?iv=EV5bUjcc4OX2Km/zPp4ndQ=='
@@ -36,7 +37,7 @@ test('decrypt message from go-nostr', async () => {
test('decrypt big payload from go-nostr', async () => {
let sk1 = '91ba716fa9e7ea2fcbad360cf4f8e0d312f73984da63d90f524ad61a6a1e7dbe'
let sk2 = '96f6fa197aa07477ab88f6981118466ae3a982faab8ad5db9d5426870c73d220'
- let pk1 = getPublicKey(sk1)
+ let pk1 = getPublicKey(hexToBytes(sk1))
let ciphertext =
'6f8dMstm+udOu7yipSn33orTmwQpWbtfuY95NH+eTU1kArysWJIDkYgI2D25EAGIDJsNd45jOJ2NbVOhFiL3ZP/NWsTwXokk34iyHyA/lkjzugQ1bHXoMD1fP/Ay4hB4al1NHb8HXHKZaxPrErwdRDb8qa/I6dXb/1xxyVvNQBHHvmsM5yIFaPwnCN1DZqXf2KbTA/Ekz7Hy+7R+Sy3TXLQDFpWYqykppkXc7Fs0qSuPRyxz5+anuN0dxZa9GTwTEnBrZPbthKkNRrvZMdTGJ6WumOh9aUq8OJJWy9aOgsXvs7qjN1UqcCqQqYaVnEOhCaqWNDsVtsFrVDj+SaLIBvCiomwF4C4nIgngJ5I69tx0UNI0q+ZnvOGQZ7m1PpW2NYP7Yw43HJNdeUEQAmdCPnh/PJwzLTnIxHmQU7n7SPlMdV0SFa6H8y2HHvex697GAkyE5t8c2uO24OnqIwF1tR3blIqXzTSRl0GA6QvrSj2p4UtnWjvF7xT7RiIEyTtgU/AsihTrXyXzWWZaIBJogpgw6erlZqWjCH7sZy/WoGYEiblobOAqMYxax6vRbeuGtoYksr/myX+x9rfLrYuoDRTw4woXOLmMrrj+Mf0TbAgc3SjdkqdsPU1553rlSqIEZXuFgoWmxvVQDtekgTYyS97G81TDSK9nTJT5ilku8NVq2LgtBXGwsNIw/xekcOUzJke3kpnFPutNaexR1VF3ohIuqRKYRGcd8ADJP2lfwMcaGRiplAmFoaVS1YUhQwYFNq9rMLf7YauRGV4BJg/t9srdGxf5RoKCvRo+XM/nLxxysTR9MVaEP/3lDqjwChMxs+eWfLHE5vRWV8hUEqdrWNZV29gsx5nQpzJ4PARGZVu310pQzc6JAlc2XAhhFk6RamkYJnmCSMnb/RblzIATBi2kNrCVAlaXIon188inB62rEpZGPkRIP7PUfu27S/elLQHBHeGDsxOXsBRo1gl3te+raoBHsxo6zvRnYbwdAQa5taDE63eh+fT6kFI+xYmXNAQkU8Dp0MVhEh4JQI06Ni/AKrvYpC95TXXIphZcF+/Pv/vaGkhG2X9S3uhugwWK?iv=2vWkOQQi0WynNJz/aZ4k2g=='
diff --git a/nip04.ts b/nip04.ts
index 334f3a3..bbb9447 100644
--- a/nip04.ts
+++ b/nip04.ts
@@ -1,4 +1,4 @@
-import { randomBytes } from '@noble/hashes/utils'
+import { bytesToHex, randomBytes } from '@noble/hashes/utils'
import { secp256k1 } from '@noble/curves/secp256k1'
import { base64 } from '@scure/base'
@@ -10,7 +10,8 @@ if (typeof crypto !== 'undefined' && !crypto.subtle && crypto.webcrypto) {
crypto.subtle = crypto.webcrypto.subtle
}
-export async function encrypt(privkey: string, pubkey: string, text: string): Promise {
+export async function encrypt(secretKey: string | Uint8Array, pubkey: string, text: string): Promise {
+ const privkey: string = secretKey instanceof Uint8Array ? bytesToHex(secretKey) : secretKey
const key = secp256k1.getSharedSecret(privkey, '02' + pubkey)
const normalizedKey = getNormalizedX(key)
@@ -24,7 +25,8 @@ export async function encrypt(privkey: string, pubkey: string, text: string): Pr
return `${ctb64}?iv=${ivb64}`
}
-export async function decrypt(privkey: string, pubkey: string, data: string): Promise {
+export async function decrypt(secretKey: string | Uint8Array, pubkey: string, data: string): Promise {
+ const privkey: string = secretKey instanceof Uint8Array ? bytesToHex(secretKey) : secretKey
let [ctb64, ivb64] = data.split('?iv=')
let key = secp256k1.getSharedSecret(privkey, '02' + pubkey)
let normalizedKey = getNormalizedX(key)
diff --git a/nip10.ts b/nip10.ts
index 87c4cb4..d01c00a 100644
--- a/nip10.ts
+++ b/nip10.ts
@@ -1,4 +1,4 @@
-import type { Event } from './event.ts'
+import type { Event } from './pure.ts'
import type { EventPointer, ProfilePointer } from './nip19.ts'
export type NIP10Result = {
diff --git a/nip13.ts b/nip13.ts
index c3ef403..8f1bfc2 100644
--- a/nip13.ts
+++ b/nip13.ts
@@ -1,4 +1,4 @@
-import { type UnsignedEvent, type Event, getEventHash } from './event.ts'
+import { type UnsignedEvent, type Event, getEventHash } from './pure.ts'
/** Get POW difficulty from a Nostr hex ID. */
export function getPow(hex: string): number {
diff --git a/nip18.test.ts b/nip18.test.ts
index 0374c4b..d424090 100644
--- a/nip18.test.ts
+++ b/nip18.test.ts
@@ -1,6 +1,6 @@
import { describe, test, expect } from 'bun:test'
-import { finishEvent } from './event.ts'
-import { getPublicKey } from './keys.ts'
+import { hexToBytes } from '@noble/hashes/utils'
+import { finalizeEvent, getPublicKey } from './pure.ts'
import { Repost, ShortTextNote } from './kinds.ts'
import { finishRepostEvent, getRepostedEventPointer, getRepostedEvent } from './nip18.ts'
import { buildEvent } from './test-helpers.ts'
@@ -8,11 +8,10 @@ import { buildEvent } from './test-helpers.ts'
const relayUrl = 'https://relay.example.com'
describe('finishRepostEvent + getRepostedEventPointer + getRepostedEvent', () => {
- const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
-
+ const privateKey = hexToBytes('d217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf')
const publicKey = getPublicKey(privateKey)
- const repostedEvent = finishEvent(
+ const repostedEvent = finalizeEvent(
{
kind: ShortTextNote,
tags: [
diff --git a/nip18.ts b/nip18.ts
index df5e963..a721bb8 100644
--- a/nip18.ts
+++ b/nip18.ts
@@ -1,4 +1,4 @@
-import { Event, finishEvent, verifySignature } from './event.ts'
+import { Event, finalizeEvent, verifyEvent } from './pure.ts'
import { Repost } from './kinds.ts'
import { EventPointer } from './nip19.ts'
@@ -23,9 +23,9 @@ export function finishRepostEvent(
t: RepostEventTemplate,
reposted: Event,
relayUrl: string,
- privateKey: string,
+ privateKey: Uint8Array,
): Event {
- return finishEvent(
+ return finalizeEvent(
{
kind: Repost,
tags: [...(t.tags ?? []), ['e', reposted.id, relayUrl], ['p', reposted.pubkey]],
@@ -89,7 +89,7 @@ export function getRepostedEvent(event: Event, { skipVerification }: GetReposted
return undefined
}
- if (!skipVerification && !verifySignature(repostedEvent)) {
+ if (!skipVerification && !verifyEvent(repostedEvent)) {
return undefined
}
diff --git a/nip19.test.ts b/nip19.test.ts
index 1d5e9a7..fe38e28 100644
--- a/nip19.test.ts
+++ b/nip19.test.ts
@@ -1,5 +1,5 @@
import { test, expect } from 'bun:test'
-import { generatePrivateKey, getPublicKey } from './keys.ts'
+import { generateSecretKey, getPublicKey } from './pure.ts'
import {
decode,
naddrEncode,
@@ -14,7 +14,7 @@ import {
} from './nip19.ts'
test('encode and decode nsec', () => {
- let sk = generatePrivateKey()
+ let sk = generateSecretKey()
let nsec = nsecEncode(sk)
expect(nsec).toMatch(/nsec1\w+/)
let { type, data } = decode(nsec)
@@ -23,7 +23,7 @@ test('encode and decode nsec', () => {
})
test('encode and decode npub', () => {
- let pk = getPublicKey(generatePrivateKey())
+ let pk = getPublicKey(generateSecretKey())
let npub = npubEncode(pk)
expect(npub).toMatch(/npub1\w+/)
let { type, data } = decode(npub)
@@ -32,7 +32,7 @@ test('encode and decode npub', () => {
})
test('encode and decode nprofile', () => {
- let pk = getPublicKey(generatePrivateKey())
+ let pk = getPublicKey(generateSecretKey())
let relays = ['wss://relay.nostr.example.mydomain.example.com', 'wss://nostr.banana.com']
let nprofile = nprofileEncode({ pubkey: pk, relays })
expect(nprofile).toMatch(/nprofile1\w+/)
@@ -56,7 +56,7 @@ test('decode nprofile without relays', () => {
})
test('encode and decode naddr', () => {
- let pk = getPublicKey(generatePrivateKey())
+ let pk = getPublicKey(generateSecretKey())
let relays = ['wss://relay.nostr.example.mydomain.example.com', 'wss://nostr.banana.com']
let naddr = naddrEncode({
pubkey: pk,
@@ -76,7 +76,7 @@ test('encode and decode naddr', () => {
})
test('encode and decode nevent', () => {
- let pk = getPublicKey(generatePrivateKey())
+ let pk = getPublicKey(generateSecretKey())
let relays = ['wss://relay.nostr.example.mydomain.example.com', 'wss://nostr.banana.com']
let naddr = neventEncode({
id: pk,
@@ -93,7 +93,7 @@ test('encode and decode nevent', () => {
})
test('encode and decode nevent with kind 0', () => {
- let pk = getPublicKey(generatePrivateKey())
+ let pk = getPublicKey(generateSecretKey())
let relays = ['wss://relay.nostr.example.mydomain.example.com', 'wss://nostr.banana.com']
let naddr = neventEncode({
id: pk,
diff --git a/nip19.ts b/nip19.ts
index d817865..64d0471 100644
--- a/nip19.ts
+++ b/nip19.ts
@@ -48,7 +48,7 @@ type Prefixes = {
nrelay: string
nevent: EventPointer
naddr: AddressPointer
- nsec: string
+ nsec: Uint8Array
npub: string
note: string
}
@@ -130,6 +130,8 @@ export function decode(nip19: string): DecodeResult {
}
case 'nsec':
+ return { type: prefix, data }
+
case 'npub':
case 'note':
return { type: prefix, data: bytesToHex(data) }
@@ -157,16 +159,16 @@ function parseTLV(data: Uint8Array): TLV {
return result
}
-export function nsecEncode(hex: string): `nsec1${string}` {
- return encodeBytes('nsec', hex)
+export function nsecEncode(key: Uint8Array): `nsec1${string}` {
+ return encodeBytes('nsec', key)
}
export function npubEncode(hex: string): `npub1${string}` {
- return encodeBytes('npub', hex)
+ return encodeBytes('npub', hexToBytes(hex))
}
export function noteEncode(hex: string): `note1${string}` {
- return encodeBytes('note', hex)
+ return encodeBytes('note', hexToBytes(hex))
}
function encodeBech32(prefix: Prefix, data: Uint8Array): `${Prefix}1${string}` {
@@ -174,9 +176,8 @@ function encodeBech32(prefix: Prefix, data: Uint8Array):
return bech32.encode(prefix, words, Bech32MaxSize) as `${Prefix}1${string}`
}
-function encodeBytes(prefix: Prefix, hex: string): `${Prefix}1${string}` {
- let data = hexToBytes(hex)
- return encodeBech32(prefix, data)
+function encodeBytes(prefix: Prefix, bytes: Uint8Array): `${Prefix}1${string}` {
+ return encodeBech32(prefix, bytes)
}
export function nprofileEncode(profile: ProfilePointer): `nprofile1${string}` {
diff --git a/nip25.test.ts b/nip25.test.ts
index 61fef0d..f1d86bc 100644
--- a/nip25.test.ts
+++ b/nip25.test.ts
@@ -1,15 +1,14 @@
import { describe, test, expect } from 'bun:test'
-import { finishEvent } from './event.ts'
-import { getPublicKey } from './keys.ts'
+import { hexToBytes } from '@noble/hashes/utils'
+import { finalizeEvent, getPublicKey } from './pure.ts'
import { Reaction, ShortTextNote } from './kinds.ts'
import { finishReactionEvent, getReactedEventPointer } from './nip25.ts'
describe('finishReactionEvent + getReactedEventPointer', () => {
- const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
-
+ const privateKey = hexToBytes('d217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf')
const publicKey = getPublicKey(privateKey)
- const reactedEvent = finishEvent(
+ const reactedEvent = finalizeEvent(
{
kind: ShortTextNote,
tags: [
diff --git a/nip25.ts b/nip25.ts
index ffd97b7..92d1699 100644
--- a/nip25.ts
+++ b/nip25.ts
@@ -1,4 +1,4 @@
-import { Event, finishEvent } from './event.ts'
+import { Event, finalizeEvent } from './pure.ts'
import { Reaction } from './kinds.ts'
import type { EventPointer } from './nip19.ts'
@@ -17,10 +17,10 @@ export type ReactionEventTemplate = {
created_at: number
}
-export function finishReactionEvent(t: ReactionEventTemplate, reacted: Event, privateKey: string): Event {
+export function finishReactionEvent(t: ReactionEventTemplate, reacted: Event, privateKey: Uint8Array): Event {
const inheritedTags = reacted.tags.filter(tag => tag.length >= 2 && (tag[0] === 'e' || tag[0] === 'p'))
- return finishEvent(
+ return finalizeEvent(
{
...t,
kind: Reaction,
diff --git a/nip28.test.ts b/nip28.test.ts
index a458fe2..446d28d 100644
--- a/nip28.test.ts
+++ b/nip28.test.ts
@@ -1,5 +1,6 @@
import { describe, test, expect } from 'bun:test'
-import { getPublicKey } from './keys.ts'
+import { hexToBytes } from '@noble/hashes/utils'
+import { getPublicKey } from './pure.ts'
import * as Kind from './kinds.ts'
import {
channelCreateEvent,
@@ -11,7 +12,7 @@ import {
ChannelMessageEventTemplate,
} from './nip28.ts'
-const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
+const privateKey = hexToBytes('d217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf')
const publicKey = getPublicKey(privateKey)
describe('NIP-28 Functions', () => {
diff --git a/nip28.ts b/nip28.ts
index 38383c9..cfe281d 100644
--- a/nip28.ts
+++ b/nip28.ts
@@ -1,4 +1,4 @@
-import { Event, finishEvent } from './event.ts'
+import { Event, finalizeEvent } from './pure.ts'
import { ChannelCreation, ChannelHideMessage, ChannelMessage, ChannelMetadata, ChannelMuteUser } from './kinds.ts'
export interface ChannelMetadata {
@@ -45,7 +45,7 @@ export interface ChannelMuteUserEventTemplate {
tags?: string[][]
}
-export const channelCreateEvent = (t: ChannelCreateEventTemplate, privateKey: string): Event | undefined => {
+export const channelCreateEvent = (t: ChannelCreateEventTemplate, privateKey: Uint8Array): Event | undefined => {
let content: string
if (typeof t.content === 'object') {
content = JSON.stringify(t.content)
@@ -55,7 +55,7 @@ export const channelCreateEvent = (t: ChannelCreateEventTemplate, privateKey: st
return undefined
}
- return finishEvent(
+ return finalizeEvent(
{
kind: ChannelCreation,
tags: [...(t.tags ?? [])],
@@ -66,7 +66,7 @@ export const channelCreateEvent = (t: ChannelCreateEventTemplate, privateKey: st
)
}
-export const channelMetadataEvent = (t: ChannelMetadataEventTemplate, privateKey: string): Event | undefined => {
+export const channelMetadataEvent = (t: ChannelMetadataEventTemplate, privateKey: Uint8Array): Event | undefined => {
let content: string
if (typeof t.content === 'object') {
content = JSON.stringify(t.content)
@@ -76,7 +76,7 @@ export const channelMetadataEvent = (t: ChannelMetadataEventTemplate, privateKey
return undefined
}
- return finishEvent(
+ return finalizeEvent(
{
kind: ChannelMetadata,
tags: [['e', t.channel_create_event_id], ...(t.tags ?? [])],
@@ -87,14 +87,14 @@ export const channelMetadataEvent = (t: ChannelMetadataEventTemplate, privateKey
)
}
-export const channelMessageEvent = (t: ChannelMessageEventTemplate, privateKey: string): Event => {
+export const channelMessageEvent = (t: ChannelMessageEventTemplate, privateKey: Uint8Array): Event => {
const tags = [['e', t.channel_create_event_id, t.relay_url, 'root']]
if (t.reply_to_channel_message_event_id) {
tags.push(['e', t.reply_to_channel_message_event_id, t.relay_url, 'reply'])
}
- return finishEvent(
+ return finalizeEvent(
{
kind: ChannelMessage,
tags: [...tags, ...(t.tags ?? [])],
@@ -106,7 +106,10 @@ export const channelMessageEvent = (t: ChannelMessageEventTemplate, privateKey:
}
/* "e" tag should be the kind 42 event to hide */
-export const channelHideMessageEvent = (t: ChannelHideMessageEventTemplate, privateKey: string): Event | undefined => {
+export const channelHideMessageEvent = (
+ t: ChannelHideMessageEventTemplate,
+ privateKey: Uint8Array,
+): Event | undefined => {
let content: string
if (typeof t.content === 'object') {
content = JSON.stringify(t.content)
@@ -116,7 +119,7 @@ export const channelHideMessageEvent = (t: ChannelHideMessageEventTemplate, priv
return undefined
}
- return finishEvent(
+ return finalizeEvent(
{
kind: ChannelHideMessage,
tags: [['e', t.channel_message_event_id], ...(t.tags ?? [])],
@@ -127,7 +130,7 @@ export const channelHideMessageEvent = (t: ChannelHideMessageEventTemplate, priv
)
}
-export const channelMuteUserEvent = (t: ChannelMuteUserEventTemplate, privateKey: string): Event | undefined => {
+export const channelMuteUserEvent = (t: ChannelMuteUserEventTemplate, privateKey: Uint8Array): Event | undefined => {
let content: string
if (typeof t.content === 'object') {
content = JSON.stringify(t.content)
@@ -137,7 +140,7 @@ export const channelMuteUserEvent = (t: ChannelMuteUserEventTemplate, privateKey
return undefined
}
- return finishEvent(
+ return finalizeEvent(
{
kind: ChannelMuteUser,
tags: [['p', t.pubkey_to_mute], ...(t.tags ?? [])],
diff --git a/nip42.ts b/nip42.ts
index 18862a8..f8fd1ec 100644
--- a/nip42.ts
+++ b/nip42.ts
@@ -1,4 +1,4 @@
-import { EventTemplate } from './event.ts'
+import { EventTemplate } from './pure.ts'
import { ClientAuth } from './kinds.ts'
/**
diff --git a/nip47.test.ts b/nip47.test.ts
index d7c571d..6c9f1b5 100644
--- a/nip47.test.ts
+++ b/nip47.test.ts
@@ -1,7 +1,8 @@
+import crypto from 'node:crypto'
import { describe, test, expect } from 'bun:test'
+import { hexToBytes } from '@noble/hashes/utils'
import { makeNwcRequestEvent, parseConnectionString } from './nip47'
import { decrypt } from './nip04.ts'
-import crypto from 'node:crypto'
import { NWCWalletRequest } from './kinds.ts'
// @ts-ignore
@@ -44,14 +45,10 @@ describe('parseConnectionString', () => {
describe('makeNwcRequestEvent', () => {
test('returns a valid NWC request event', async () => {
const pubkey = 'b889ff5b1513b641e2a139f661a661364979c5beee91842f8f0ef42ab558e9d4'
- const secret = '71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c'
+ const secret = hexToBytes('71a8c14c1407c113601079c4302dab36460f0ccd0ad506f1f2dc73b5100e4f3c')
const invoice =
'lnbc210n1pjdgyvupp5x43awdarnfd4mdlsklelux0nyckwfu5c708ykuet8vcjnjp3rnpqdqu2askcmr9wssx7e3q2dshgmmndp5scqzzsxqyz5vqsp52l7y9peq9pka3vd3j7aps7gjnalsmy46ndj2mlkz00dltjgqfumq9qyyssq5fasr5dxed8l4qjfnqq48a02jzss3asf8sly7sfaqtr9w3yu2q9spsxhghs3y9aqdf44zkrrg9jjjdg6amade4h0hulllkwk33eqpucp6d5jye'
- const result = await makeNwcRequestEvent({
- pubkey,
- secret,
- invoice,
- })
+ const result = await makeNwcRequestEvent(pubkey, secret, invoice)
expect(result.kind).toBe(NWCWalletRequest)
expect(await decrypt(secret, pubkey, result.content)).toEqual(
JSON.stringify({
diff --git a/nip47.ts b/nip47.ts
index f8915a5..cab1b1b 100644
--- a/nip47.ts
+++ b/nip47.ts
@@ -1,4 +1,4 @@
-import { finishEvent } from './event.ts'
+import { finalizeEvent } from './pure.ts'
import { NWCWalletRequest } from './kinds.ts'
import { encrypt } from './nip04.ts'
@@ -15,22 +15,14 @@ export function parseConnectionString(connectionString: string) {
return { pubkey, relay, secret }
}
-export async function makeNwcRequestEvent({
- pubkey,
- secret,
- invoice,
-}: {
- pubkey: string
- secret: string
- invoice: string
-}) {
+export async function makeNwcRequestEvent(pubkey: string, secretKey: Uint8Array, invoice: string) {
const content = {
method: 'pay_invoice',
params: {
invoice,
},
}
- const encryptedContent = await encrypt(secret, pubkey, JSON.stringify(content))
+ const encryptedContent = await encrypt(secretKey, pubkey, JSON.stringify(content))
const eventTemplate = {
kind: NWCWalletRequest,
created_at: Math.round(Date.now() / 1000),
@@ -38,5 +30,5 @@ export async function makeNwcRequestEvent({
tags: [['p', pubkey]],
}
- return finishEvent(eventTemplate, secret)
+ return finalizeEvent(eventTemplate, secretKey)
}
diff --git a/nip57.test.ts b/nip57.test.ts
index d34acdf..465ff2c 100644
--- a/nip57.test.ts
+++ b/nip57.test.ts
@@ -1,6 +1,6 @@
import { describe, test, expect, mock } from 'bun:test'
-import { finishEvent } from './event.ts'
-import { getPublicKey, generatePrivateKey } from './keys.ts'
+import { finalizeEvent } from './pure.ts'
+import { getPublicKey, generateSecretKey } from './pure.ts'
import { getZapEndpoint, makeZapReceipt, makeZapRequest, useFetchImplementation, validateZapRequest } from './nip57.ts'
import { buildEvent } from './test-helpers.ts'
@@ -122,7 +122,7 @@ describe('validateZapRequest', () => {
})
test('returns an error message if the signature on the Zap request is invalid', () => {
- const privateKey = generatePrivateKey()
+ const privateKey = generateSecretKey()
const publicKey = getPublicKey(privateKey)
const zapRequest = {
@@ -141,9 +141,8 @@ describe('validateZapRequest', () => {
})
test('returns an error message if the Zap request does not have a "p" tag', () => {
- const privateKey = generatePrivateKey()
-
- const zapRequest = finishEvent(
+ const privateKey = generateSecretKey()
+ const zapRequest = finalizeEvent(
{
kind: 9734,
created_at: Date.now() / 1000,
@@ -160,9 +159,8 @@ describe('validateZapRequest', () => {
})
test('returns an error message if the "p" tag on the Zap request is not valid hex', () => {
- const privateKey = generatePrivateKey()
-
- const zapRequest = finishEvent(
+ const privateKey = generateSecretKey()
+ const zapRequest = finalizeEvent(
{
kind: 9734,
created_at: Date.now() / 1000,
@@ -180,10 +178,10 @@ describe('validateZapRequest', () => {
})
test('returns an error message if the "e" tag on the Zap request is not valid hex', () => {
- const privateKey = generatePrivateKey()
+ const privateKey = generateSecretKey()
const publicKey = getPublicKey(privateKey)
- const zapRequest = finishEvent(
+ const zapRequest = finalizeEvent(
{
kind: 9734,
created_at: Date.now() / 1000,
@@ -202,10 +200,10 @@ describe('validateZapRequest', () => {
})
test('returns an error message if the Zap request does not have a relays tag', () => {
- const privateKey = generatePrivateKey()
+ const privateKey = generateSecretKey()
const publicKey = getPublicKey(privateKey)
- const zapRequest = finishEvent(
+ const zapRequest = finalizeEvent(
{
kind: 9734,
created_at: Date.now() / 1000,
@@ -222,10 +220,10 @@ describe('validateZapRequest', () => {
})
test('returns null for a valid Zap request', () => {
- const privateKey = generatePrivateKey()
+ const privateKey = generateSecretKey()
const publicKey = getPublicKey(privateKey)
- const zapRequest = finishEvent(
+ const zapRequest = finalizeEvent(
{
kind: 9734,
created_at: Date.now() / 1000,
@@ -245,11 +243,11 @@ describe('validateZapRequest', () => {
describe('makeZapReceipt', () => {
test('returns a valid Zap receipt with a preimage', () => {
- const privateKey = generatePrivateKey()
+ const privateKey = generateSecretKey()
const publicKey = getPublicKey(privateKey)
const zapRequest = JSON.stringify(
- finishEvent(
+ finalizeEvent(
{
kind: 9734,
created_at: Date.now() / 1000,
@@ -283,11 +281,11 @@ describe('makeZapReceipt', () => {
})
test('returns a valid Zap receipt without a preimage', () => {
- const privateKey = generatePrivateKey()
+ const privateKey = generateSecretKey()
const publicKey = getPublicKey(privateKey)
const zapRequest = JSON.stringify(
- finishEvent(
+ finalizeEvent(
{
kind: 9734,
created_at: Date.now() / 1000,
diff --git a/nip57.ts b/nip57.ts
index cdebd72..0770007 100644
--- a/nip57.ts
+++ b/nip57.ts
@@ -1,6 +1,6 @@
import { bech32 } from '@scure/base'
-import { validateEvent, verifySignature, type Event, type EventTemplate } from './event.ts'
+import { validateEvent, verifyEvent, type Event, type EventTemplate } from './pure.ts'
import { utf8Decoder } from './utils.ts'
var _fetch: any
@@ -86,7 +86,7 @@ export function validateZapRequest(zapRequestString: string): string | null {
if (!validateEvent(zapRequest)) return 'Zap request is not a valid Nostr event.'
- if (!verifySignature(zapRequest)) return 'Invalid signature on zap request.'
+ if (!verifyEvent(zapRequest)) return 'Invalid signature on zap request.'
let p = zapRequest.tags.find(([t, v]) => t === 'p' && v)
if (!p) return "Zap request doesn't have a 'p' tag."
diff --git a/nip98.test.ts b/nip98.test.ts
index db7944b..0a21463 100644
--- a/nip98.test.ts
+++ b/nip98.test.ts
@@ -1,17 +1,17 @@
import { describe, test, expect } from 'bun:test'
import { getToken, unpackEventFromToken, validateEvent, validateToken } from './nip98.ts'
-import { Event, finishEvent } from './event.ts'
-import { generatePrivateKey, getPublicKey } from './keys.ts'
+import { Event, finalizeEvent } from './pure.ts'
+import { generateSecretKey, getPublicKey } from './pure.ts'
import { sha256 } from '@noble/hashes/sha256'
import { utf8Encoder } from './utils.ts'
import { bytesToHex } from '@noble/hashes/utils'
import { HTTPAuth } from './kinds.ts'
-const sk = generatePrivateKey()
+const sk = generateSecretKey()
describe('getToken', () => {
test('getToken GET returns without authorization scheme', async () => {
- let result = await getToken('http://test.com', 'get', e => finishEvent(e, sk))
+ let result = await getToken('http://test.com', 'get', e => finalizeEvent(e, sk))
const decodedResult: Event = await unpackEventFromToken(result)
@@ -26,7 +26,7 @@ describe('getToken', () => {
})
test('getToken POST returns token without authorization scheme', async () => {
- let result = await getToken('http://test.com', 'post', e => finishEvent(e, sk))
+ let result = await getToken('http://test.com', 'post', e => finalizeEvent(e, sk))
const decodedResult: Event = await unpackEventFromToken(result)
@@ -43,7 +43,7 @@ describe('getToken', () => {
test('getToken GET returns token WITH authorization scheme', async () => {
const authorizationScheme = 'Nostr '
- let result = await getToken('http://test.com', 'post', e => finishEvent(e, sk), true)
+ let result = await getToken('http://test.com', 'post', e => finalizeEvent(e, sk), true)
expect(result.startsWith(authorizationScheme)).toBe(true)
@@ -62,7 +62,7 @@ describe('getToken', () => {
test('getToken returns token with a valid payload tag when payload is present', async () => {
const payload = { test: 'payload' }
const payloadHash = bytesToHex(sha256(utf8Encoder.encode(JSON.stringify(payload))))
- let result = await getToken('http://test.com', 'post', e => finishEvent(e, sk), true, payload)
+ let result = await getToken('http://test.com', 'post', e => finalizeEvent(e, sk), true, payload)
const decodedResult: Event = await unpackEventFromToken(result)
@@ -80,14 +80,14 @@ describe('getToken', () => {
describe('validateToken', () => {
test('validateToken returns true for valid token without authorization scheme', async () => {
- const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk))
+ const validToken = await getToken('http://test.com', 'get', e => finalizeEvent(e, sk))
const result = await validateToken(validToken, 'http://test.com', 'get')
expect(result).toBe(true)
})
test('validateToken returns true for valid token with authorization scheme', async () => {
- const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk), true)
+ const validToken = await getToken('http://test.com', 'get', e => finalizeEvent(e, sk), true)
const result = await validateToken(validToken, 'http://test.com', 'get')
expect(result).toBe(true)
@@ -104,21 +104,21 @@ describe('validateToken', () => {
})
test('validateToken throws an error for a wrong url', async () => {
- const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk))
+ const validToken = await getToken('http://test.com', 'get', e => finalizeEvent(e, sk))
const result = validateToken(validToken, 'http://wrong-test.com', 'get')
expect(result).rejects.toThrow(Error)
})
test('validateToken throws an error for a wrong method', async () => {
- const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk))
+ const validToken = await getToken('http://test.com', 'get', e => finalizeEvent(e, sk))
const result = validateToken(validToken, 'http://test.com', 'post')
expect(result).rejects.toThrow(Error)
})
test('validateEvent returns true for valid decoded token with authorization scheme', async () => {
- const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk), true)
+ const validToken = await getToken('http://test.com', 'get', e => finalizeEvent(e, sk), true)
const decodedResult: Event = await unpackEventFromToken(validToken)
const result = await validateEvent(decodedResult, 'http://test.com', 'get')
@@ -126,7 +126,7 @@ describe('validateToken', () => {
})
test('validateEvent throws an error for a wrong url', async () => {
- const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk), true)
+ const validToken = await getToken('http://test.com', 'get', e => finalizeEvent(e, sk), true)
const decodedResult: Event = await unpackEventFromToken(validToken)
const result = validateEvent(decodedResult, 'http://wrong-test.com', 'get')
@@ -134,7 +134,7 @@ describe('validateToken', () => {
})
test('validateEvent throws an error for a wrong method', async () => {
- const validToken = await getToken('http://test.com', 'get', e => finishEvent(e, sk), true)
+ const validToken = await getToken('http://test.com', 'get', e => finalizeEvent(e, sk), true)
const decodedResult: Event = await unpackEventFromToken(validToken)
const result = validateEvent(decodedResult, 'http://test.com', 'post')
@@ -142,7 +142,7 @@ describe('validateToken', () => {
})
test('validateEvent returns true for valid payload tag hash', async () => {
- const validToken = await getToken('http://test.com', 'post', e => finishEvent(e, sk), true, { test: 'payload' })
+ const validToken = await getToken('http://test.com', 'post', e => finalizeEvent(e, sk), true, { test: 'payload' })
const decodedResult: Event = await unpackEventFromToken(validToken)
const result = await validateEvent(decodedResult, 'http://test.com', 'post', { test: 'payload' })
@@ -150,7 +150,7 @@ describe('validateToken', () => {
})
test('validateEvent returns false for invalid payload tag hash', async () => {
- const validToken = await getToken('http://test.com', 'post', e => finishEvent(e, sk), true, { test: 'a-payload' })
+ const validToken = await getToken('http://test.com', 'post', e => finalizeEvent(e, sk), true, { test: 'a-payload' })
const decodedResult: Event = await unpackEventFromToken(validToken)
const result = validateEvent(decodedResult, 'http://test.com', 'post', { test: 'a-different-payload' })
diff --git a/nip98.ts b/nip98.ts
index d0dff18..5dd195c 100644
--- a/nip98.ts
+++ b/nip98.ts
@@ -1,9 +1,9 @@
import { bytesToHex } from '@noble/hashes/utils'
import { sha256 } from '@noble/hashes/sha256'
import { base64 } from '@scure/base'
-import { Event, EventTemplate, verifySignature } from './event'
-import { utf8Decoder, utf8Encoder } from './utils'
-import { HTTPAuth } from './kinds'
+import { Event, EventTemplate, verifyEvent } from './pure.ts'
+import { utf8Decoder, utf8Encoder } from './utils.ts'
+import { HTTPAuth } from './kinds.ts'
const _authorizationScheme = 'Nostr '
@@ -83,7 +83,7 @@ export async function validateEvent(event: Event, url: string, method: string, b
if (!event) {
throw new Error('Invalid nostr event')
}
- if (!verifySignature(event)) {
+ if (!verifyEvent(event)) {
throw new Error('Invalid nostr event, signature invalid')
}
if (event.kind !== HTTPAuth) {
diff --git a/pool.test.ts b/pool.test.ts
index 49e3e0f..c7c003f 100644
--- a/pool.test.ts
+++ b/pool.test.ts
@@ -1,7 +1,7 @@
import { test, expect, afterAll } from 'bun:test'
-import { finishEvent, type Event } from './event.ts'
-import { generatePrivateKey, getPublicKey } from './keys.ts'
+import { finalizeEvent, type Event } from './pure.ts'
+import { generateSecretKey, getPublicKey } from './pure.ts'
import { SimplePool } from './pool.ts'
let pool = new SimplePool()
@@ -13,7 +13,7 @@ afterAll(() => {
})
test('removing duplicates when querying', async () => {
- let priv = generatePrivateKey()
+ let priv = generateSecretKey()
let pub = getPublicKey(priv)
pool.subscribeMany(relays, [{ authors: [pub] }], {
@@ -26,7 +26,7 @@ test('removing duplicates when querying', async () => {
})
let received: Event[] = []
- let event = finishEvent(
+ let event = finalizeEvent(
{
created_at: Math.round(Date.now() / 1000),
content: 'test',
@@ -44,7 +44,7 @@ test('removing duplicates when querying', async () => {
})
test('same with double querying', async () => {
- let priv = generatePrivateKey()
+ let priv = generateSecretKey()
let pub = getPublicKey(priv)
pool.subscribeMany(relays, [{ authors: [pub] }], {
@@ -60,7 +60,7 @@ test('same with double querying', async () => {
let received: Event[] = []
- let event = finishEvent(
+ let event = finalizeEvent(
{
created_at: Math.round(Date.now() / 1000),
content: 'test2',
diff --git a/pool.ts b/pool.ts
index 3cf39c5..c8687d1 100644
--- a/pool.ts
+++ b/pool.ts
@@ -1,7 +1,7 @@
import { Relay, SubscriptionParams, Subscription } from './relay.ts'
import { normalizeURL } from './utils.ts'
-import type { Event } from './event.ts'
+import type { Event } from './pure.ts'
import { type Filter } from './filter.ts'
export type SubCloser = { close: () => void }
@@ -103,7 +103,7 @@ export class SimplePool {
return
}
- let subscription = await relay.subscribe(filters, {
+ let subscription = relay.subscribe(filters, {
...params,
oneose: () => handleEose(i),
onclose: reason => handleClose(i, reason),
diff --git a/pure.ts b/pure.ts
index e8af48d..e29b3e8 100644
--- a/pure.ts
+++ b/pure.ts
@@ -14,7 +14,7 @@ class JS implements Nostr {
}
finalizeEvent(t: EventTemplate, secretKey: Uint8Array): VerifiedEvent {
const event = t as VerifiedEvent
- event.pubkey = this.getPublicKey(secretKey)
+ event.pubkey = bytesToHex(schnorr.getPublicKey(secretKey))
event.id = getEventHash(event)
event.sig = bytesToHex(schnorr.sign(getEventHash(event), secretKey))
event[verifiedSymbol] = true
diff --git a/references.ts b/references.ts
index 2ceb511..9d62537 100644
--- a/references.ts
+++ b/references.ts
@@ -1,6 +1,6 @@
import { decode, type AddressPointer, type ProfilePointer, type EventPointer } from './nip19.ts'
-import type { Event } from './event.ts'
+import type { Event } from './pure.ts'
type Reference = {
text: string
diff --git a/relay.test.ts b/relay.test.ts
index 6c3bb42..4376b79 100644
--- a/relay.test.ts
+++ b/relay.test.ts
@@ -1,7 +1,7 @@
import { test, expect, afterEach, beforeEach } from 'bun:test'
-import { finishEvent } from './event.ts'
-import { generatePrivateKey, getPublicKey } from './keys.ts'
+import { finalizeEvent } from './pure.ts'
+import { generateSecretKey, getPublicKey } from './pure.ts'
import { Relay } from './relay.ts'
let relay = new Relay('wss://public.relaying.io')
@@ -57,7 +57,7 @@ test('querying', async () => {
}, 10000)
test('listening and publishing and closing', async () => {
- let sk = generatePrivateKey()
+ let sk = generateSecretKey()
let pk = getPublicKey(sk)
var resolve1: (_: void) => void
var resolve2: (_: void) => void
@@ -91,7 +91,7 @@ test('listening and publishing and closing', async () => {
},
)
- let event = finishEvent(
+ let event = finalizeEvent(
{
kind: 23571,
created_at: Math.floor(Date.now() / 1000),
diff --git a/relay.ts b/relay.ts
index f007b34..212d910 100644
--- a/relay.ts
+++ b/relay.ts
@@ -1,6 +1,6 @@
/* global WebSocket */
-import { verifySignature, validateEvent, type Event, EventTemplate } from './event.ts'
+import { verifyEvent, validateEvent, type Event, EventTemplate } from './pure.ts'
import { matchFilters, type Filter } from './filter.ts'
import { getHex64, getSubscriptionId } from './fakejson.ts'
import { Queue, normalizeURL } from './utils.ts'
@@ -161,7 +161,7 @@ export class Relay {
case 'EVENT': {
const so = this.openSubs.get(data[1] as string) as Subscription
const event = data[2] as Event
- if ((this.trusted || (validateEvent(event) && verifySignature(event))) && matchFilters(so.filters, event)) {
+ if ((this.trusted || (validateEvent(event) && verifyEvent(event))) && matchFilters(so.filters, event)) {
so.onevent(event)
}
return
diff --git a/test-helpers.ts b/test-helpers.ts
index 6169aa6..b75f510 100644
--- a/test-helpers.ts
+++ b/test-helpers.ts
@@ -1,4 +1,4 @@
-import type { Event } from './event.ts'
+import type { Event } from './pure.ts'
/** Build an event for testing purposes. */
export function buildEvent(params: Partial): Event {
diff --git a/utils.test.ts b/utils.test.ts
index ff9ba57..7f9cd25 100644
--- a/utils.test.ts
+++ b/utils.test.ts
@@ -2,7 +2,7 @@ import { describe, test, expect } from 'bun:test'
import { buildEvent } from './test-helpers.ts'
import { Queue, insertEventIntoAscendingList, insertEventIntoDescendingList, binarySearch } from './utils.ts'
-import type { Event } from './event.ts'
+import type { Event } from './pure.ts'
describe('inserting into a desc sorted list of events', () => {
test('insert into an empty list', async () => {
diff --git a/utils.ts b/utils.ts
index 33d6d70..b22134d 100644
--- a/utils.ts
+++ b/utils.ts
@@ -1,4 +1,4 @@
-import type { Event } from './event.ts'
+import type { Event } from './pure.ts'
export const utf8Decoder = new TextDecoder('utf-8')
export const utf8Encoder = new TextEncoder()