remove the kind type parameter from events and filters.
This commit is contained in:
parent
1939c46eaa
commit
6a07e7c1cc
|
@ -1,44 +1,23 @@
|
|||
import {
|
||||
getBlankEvent,
|
||||
finishEvent,
|
||||
serializeEvent,
|
||||
getEventHash,
|
||||
validateEvent,
|
||||
verifySignature,
|
||||
getSignature,
|
||||
Kind,
|
||||
verifiedSymbol,
|
||||
} from './event.ts'
|
||||
import { getPublicKey } from './keys.ts'
|
||||
import { ShortTextNote } from './kinds.ts'
|
||||
|
||||
describe('Event', () => {
|
||||
describe('getBlankEvent', () => {
|
||||
it('should return a blank event object', () => {
|
||||
expect(getBlankEvent()).toEqual({
|
||||
kind: 255,
|
||||
content: '',
|
||||
tags: [],
|
||||
created_at: 0,
|
||||
})
|
||||
})
|
||||
|
||||
it('should return a blank event object with defined kind', () => {
|
||||
expect(getBlankEvent(Kind.Text)).toEqual({
|
||||
kind: 1,
|
||||
content: '',
|
||||
tags: [],
|
||||
created_at: 0,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('finishEvent', () => {
|
||||
it('should create a signed event from a template', () => {
|
||||
const privateKey = 'd217c1ff2f8a65c3e3a1740db3b9f58b8c848bb45e26d00ed4714e4a0f4ceecf'
|
||||
const publicKey = getPublicKey(privateKey)
|
||||
|
||||
const template = {
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
content: 'Hello, world!',
|
||||
created_at: 1617932115,
|
||||
|
@ -64,7 +43,7 @@ describe('Event', () => {
|
|||
const unsignedEvent = {
|
||||
pubkey: publicKey,
|
||||
created_at: 1617932115,
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
content: 'Hello, world!',
|
||||
}
|
||||
|
@ -88,7 +67,7 @@ describe('Event', () => {
|
|||
const publicKey = getPublicKey(privateKey)
|
||||
|
||||
const invalidEvent = {
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
created_at: 1617932115,
|
||||
pubkey: publicKey, // missing content
|
||||
|
@ -107,7 +86,7 @@ describe('Event', () => {
|
|||
const publicKey = getPublicKey(privateKey)
|
||||
|
||||
const unsignedEvent = {
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
content: 'Hello, world!',
|
||||
created_at: 1617932115,
|
||||
|
@ -127,7 +106,7 @@ describe('Event', () => {
|
|||
const publicKey = getPublicKey(privateKey)
|
||||
|
||||
const unsignedEvent = {
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
content: 'Hello, world!',
|
||||
created_at: 1617932115,
|
||||
|
@ -149,7 +128,7 @@ describe('Event', () => {
|
|||
|
||||
it('should return false for an event object with missing properties', () => {
|
||||
const invalidEvent = {
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
created_at: 1617932115, // missing content and pubkey
|
||||
}
|
||||
|
@ -221,7 +200,7 @@ describe('Event', () => {
|
|||
|
||||
const event = finishEvent(
|
||||
{
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
content: 'Hello, world!',
|
||||
created_at: 1617932115,
|
||||
|
@ -239,7 +218,7 @@ describe('Event', () => {
|
|||
|
||||
const { [verifiedSymbol]: _, ...event } = finishEvent(
|
||||
{
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
content: 'Hello, world!',
|
||||
created_at: 1617932115,
|
||||
|
@ -263,7 +242,7 @@ describe('Event', () => {
|
|||
|
||||
const { [verifiedSymbol]: _, ...event } = finishEvent(
|
||||
{
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
content: 'Hello, world!',
|
||||
created_at: 1617932115,
|
||||
|
@ -308,7 +287,7 @@ describe('Event', () => {
|
|||
const publicKey = getPublicKey(privateKey)
|
||||
|
||||
const unsignedEvent = {
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
content: 'Hello, world!',
|
||||
created_at: 1617932115,
|
||||
|
@ -336,7 +315,7 @@ describe('Event', () => {
|
|||
const wrongPrivateKey = 'a91e2a9d9e0f70f0877bea0dbf034e8f95d7392a27a7f07da0d14b9e9d456be7'
|
||||
|
||||
const unsignedEvent = {
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [],
|
||||
content: 'Hello, world!',
|
||||
created_at: 1617932115,
|
||||
|
|
40
event.ts
40
event.ts
|
@ -8,8 +8,8 @@ import { utf8Encoder } from './utils.ts'
|
|||
/** Designates a verified event signature. */
|
||||
export const verifiedSymbol = Symbol('verified')
|
||||
|
||||
export interface Event<K extends number = number> {
|
||||
kind: K
|
||||
export interface Event {
|
||||
kind: number
|
||||
tags: string[][]
|
||||
content: string
|
||||
created_at: number
|
||||
|
@ -19,30 +19,16 @@ export interface Event<K extends number = number> {
|
|||
[verifiedSymbol]?: boolean
|
||||
}
|
||||
|
||||
export type EventTemplate<K extends number = number> = Pick<Event<K>, 'kind' | 'tags' | 'content' | 'created_at'>
|
||||
export type UnsignedEvent<K extends number = number> = Pick<
|
||||
Event<K>,
|
||||
'kind' | 'tags' | 'content' | 'created_at' | 'pubkey'
|
||||
>
|
||||
export type EventTemplate = Pick<Event, 'kind' | 'tags' | 'content' | 'created_at'>
|
||||
export type UnsignedEvent = Pick<Event, 'kind' | 'tags' | 'content' | 'created_at' | 'pubkey'>
|
||||
|
||||
/** An event whose signature has been verified. */
|
||||
export interface VerifiedEvent<K extends number = number> extends Event<K> {
|
||||
export interface VerifiedEvent extends Event {
|
||||
[verifiedSymbol]: true
|
||||
}
|
||||
|
||||
export function getBlankEvent(): EventTemplate<Kind.Blank>
|
||||
export function getBlankEvent<K extends number>(kind: K): EventTemplate<K>
|
||||
export function getBlankEvent<K>(kind: K | Kind.Blank = Kind.Blank) {
|
||||
return {
|
||||
kind,
|
||||
content: '',
|
||||
tags: [],
|
||||
created_at: 0,
|
||||
}
|
||||
}
|
||||
|
||||
export function finishEvent<K extends number = number>(t: EventTemplate<K>, privateKey: string): VerifiedEvent<K> {
|
||||
const event = t as VerifiedEvent<K>
|
||||
export function finishEvent(t: EventTemplate, privateKey: string): VerifiedEvent {
|
||||
const event = t as VerifiedEvent
|
||||
event.pubkey = getPublicKey(privateKey)
|
||||
event.id = getEventHash(event)
|
||||
event.sig = getSignature(event, privateKey)
|
||||
|
@ -50,20 +36,20 @@ export function finishEvent<K extends number = number>(t: EventTemplate<K>, priv
|
|||
return event
|
||||
}
|
||||
|
||||
export function serializeEvent(evt: UnsignedEvent<number>): string {
|
||||
export function serializeEvent(evt: UnsignedEvent): string {
|
||||
if (!validateEvent(evt)) throw new Error("can't serialize event with wrong or missing properties")
|
||||
|
||||
return JSON.stringify([0, evt.pubkey, evt.created_at, evt.kind, evt.tags, evt.content])
|
||||
}
|
||||
|
||||
export function getEventHash(event: UnsignedEvent<number>): string {
|
||||
export function getEventHash(event: UnsignedEvent): string {
|
||||
let eventHash = sha256(utf8Encoder.encode(serializeEvent(event)))
|
||||
return bytesToHex(eventHash)
|
||||
}
|
||||
|
||||
const isRecord = (obj: unknown): obj is Record<string, unknown> => obj instanceof Object
|
||||
|
||||
export function validateEvent<T>(event: T): event is T & UnsignedEvent<number> {
|
||||
export function validateEvent<T>(event: T): event is T & UnsignedEvent {
|
||||
if (!isRecord(event)) return false
|
||||
if (typeof event.kind !== 'number') return false
|
||||
if (typeof event.content !== 'string') return false
|
||||
|
@ -84,7 +70,7 @@ export function validateEvent<T>(event: T): event is T & UnsignedEvent<number> {
|
|||
}
|
||||
|
||||
/** Verify the event's signature. This function mutates the event with a `verified` symbol, making it idempotent. */
|
||||
export function verifySignature<K extends number>(event: Event<K>): event is VerifiedEvent<K> {
|
||||
export function verifySignature(event: Event): event is VerifiedEvent {
|
||||
if (typeof event[verifiedSymbol] === 'boolean') return event[verifiedSymbol]
|
||||
|
||||
const hash = getEventHash(event)
|
||||
|
@ -100,7 +86,7 @@ export function verifySignature<K extends number>(event: Event<K>): event is Ver
|
|||
}
|
||||
|
||||
/** @deprecated Use `getSignature` instead. */
|
||||
export function signEvent(event: UnsignedEvent<number>, key: string): string {
|
||||
export function signEvent(event: UnsignedEvent, key: string): string {
|
||||
console.warn(
|
||||
'nostr-tools: `signEvent` is deprecated and will be removed or changed in the future. Please use `getSignature` instead.',
|
||||
)
|
||||
|
@ -108,6 +94,6 @@ export function signEvent(event: UnsignedEvent<number>, key: string): string {
|
|||
}
|
||||
|
||||
/** Calculate the signature for an event. */
|
||||
export function getSignature(event: UnsignedEvent<number>, key: string): string {
|
||||
export function getSignature(event: UnsignedEvent, key: string): string {
|
||||
return bytesToHex(schnorr.sign(getEventHash(event), key))
|
||||
}
|
||||
|
|
12
filter.ts
12
filter.ts
|
@ -1,8 +1,8 @@
|
|||
import { Event } from './event.ts'
|
||||
|
||||
export type Filter<K extends number = number> = {
|
||||
export type Filter = {
|
||||
ids?: string[]
|
||||
kinds?: K[]
|
||||
kinds?: number[]
|
||||
authors?: string[]
|
||||
since?: number
|
||||
until?: number
|
||||
|
@ -11,7 +11,7 @@ export type Filter<K extends number = number> = {
|
|||
[key: `#${string}`]: string[] | undefined
|
||||
}
|
||||
|
||||
export function matchFilter(filter: Filter<number>, event: Event<number>): boolean {
|
||||
export function matchFilter(filter: Filter, event: Event): boolean {
|
||||
if (filter.ids && filter.ids.indexOf(event.id) === -1) {
|
||||
if (!filter.ids.some(prefix => event.id.startsWith(prefix))) {
|
||||
return false
|
||||
|
@ -38,15 +38,15 @@ export function matchFilter(filter: Filter<number>, event: Event<number>): boole
|
|||
return true
|
||||
}
|
||||
|
||||
export function matchFilters(filters: Filter<number>[], event: Event<number>): boolean {
|
||||
export function matchFilters(filters: Filter[], event: Event): boolean {
|
||||
for (let i = 0; i < filters.length; i++) {
|
||||
if (matchFilter(filters[i], event)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export function mergeFilters(...filters: Filter<number>[]): Filter<number> {
|
||||
let result: Filter<number> = {}
|
||||
export function mergeFilters(...filters: Filter[]): Filter {
|
||||
let result: Filter = {}
|
||||
for (let i = 0; i < filters.length; i++) {
|
||||
let filter = filters[i]
|
||||
Object.entries(filter).forEach(([property, values]) => {
|
||||
|
|
11
kinds.ts
11
kinds.ts
|
@ -39,6 +39,11 @@ export const EventDeletion = 5
|
|||
export const Repost = 6
|
||||
export const Reaction = 7
|
||||
export const BadgeAward = 8
|
||||
export const ChannelCreation = 40
|
||||
export const ChannelMetadata = 41
|
||||
export const ChannelMessage = 42
|
||||
export const ChannelHideMessage = 43
|
||||
export const ChannelMuteUser = 44
|
||||
export const Report = 1984
|
||||
export const ZapRequest = 9734
|
||||
export const Zap = 9735
|
||||
|
@ -68,10 +73,10 @@ export const BlockedRelaysList = 10006
|
|||
export const SearchRelaysList = 10007
|
||||
export const InterestsList = 10015
|
||||
export const UserEmojiList = 10030
|
||||
export const WalletInfo = 13194
|
||||
export const NWCWalletInfo = 13194
|
||||
export const LightningPubRPC = 21000
|
||||
export const WalletRequest = 23194
|
||||
export const WalletResponse = 23195
|
||||
export const NWCWalletRequest = 23194
|
||||
export const NWCWalletResponse = 23195
|
||||
export const NostrConnect = 24133
|
||||
export const HTTPAuth = 27235
|
||||
export const Followsets = 30000
|
||||
|
|
4
nip13.ts
4
nip13.ts
|
@ -23,10 +23,10 @@ export function getPow(hex: string): number {
|
|||
*
|
||||
* Adapted from Snort: https://git.v0l.io/Kieran/snort/src/commit/4df6c19248184218c4c03728d61e94dae5f2d90c/packages/system/src/pow-util.ts#L14-L36
|
||||
*/
|
||||
export function minePow<K extends number>(unsigned: UnsignedEvent<K>, difficulty: number): Omit<Event<K>, 'sig'> {
|
||||
export function minePow(unsigned: UnsignedEvent, difficulty: number): Omit<Event, 'sig'> {
|
||||
let count = 0
|
||||
|
||||
const event = unsigned as Omit<Event<K>, 'sig'>
|
||||
const event = unsigned as Omit<Event, 'sig'>
|
||||
const tag = ['nonce', count.toString(), difficulty.toString()]
|
||||
|
||||
event.tags.push(tag)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { finishEvent, Kind } from './event.ts'
|
||||
import { finishEvent } from './event.ts'
|
||||
import { getPublicKey } from './keys.ts'
|
||||
import { Repost, ShortTextNote } from './kinds.ts'
|
||||
import { finishRepostEvent, getRepostedEventPointer, getRepostedEvent } from './nip18.ts'
|
||||
import { buildEvent } from './test-helpers.ts'
|
||||
|
||||
|
@ -12,7 +13,7 @@ describe('finishRepostEvent + getRepostedEventPointer + getRepostedEvent', () =>
|
|||
|
||||
const repostedEvent = finishEvent(
|
||||
{
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [
|
||||
['e', 'replied event id'],
|
||||
['p', 'replied event pubkey'],
|
||||
|
@ -30,7 +31,7 @@ describe('finishRepostEvent + getRepostedEventPointer + getRepostedEvent', () =>
|
|||
|
||||
const event = finishRepostEvent(template, repostedEvent, relayUrl, privateKey)
|
||||
|
||||
expect(event.kind).toEqual(Kind.Repost)
|
||||
expect(event.kind).toEqual(Repost)
|
||||
expect(event.tags).toEqual([
|
||||
['e', repostedEvent.id, relayUrl],
|
||||
['p', repostedEvent.pubkey],
|
||||
|
@ -61,7 +62,7 @@ describe('finishRepostEvent + getRepostedEventPointer + getRepostedEvent', () =>
|
|||
|
||||
const event = finishRepostEvent(template, repostedEvent, relayUrl, privateKey)
|
||||
|
||||
expect(event.kind).toEqual(Kind.Repost)
|
||||
expect(event.kind).toEqual(Repost)
|
||||
expect(event.tags).toEqual([
|
||||
['nonstandard', 'tag'],
|
||||
['e', repostedEvent.id, relayUrl],
|
||||
|
@ -88,7 +89,7 @@ describe('finishRepostEvent + getRepostedEventPointer + getRepostedEvent', () =>
|
|||
describe('getRepostedEventPointer', () => {
|
||||
it('should parse an event with only an `e` tag', () => {
|
||||
const event = buildEvent({
|
||||
kind: Kind.Repost,
|
||||
kind: Repost,
|
||||
tags: [['e', 'reposted event id', relayUrl]],
|
||||
})
|
||||
|
||||
|
|
22
nip18.ts
22
nip18.ts
|
@ -1,4 +1,5 @@
|
|||
import { Event, finishEvent, Kind, verifySignature } from './event.ts'
|
||||
import { Event, finishEvent, verifySignature } from './event.ts'
|
||||
import { Repost } from './kinds.ts'
|
||||
import { EventPointer } from './nip19.ts'
|
||||
|
||||
export type RepostEventTemplate = {
|
||||
|
@ -20,13 +21,13 @@ export type RepostEventTemplate = {
|
|||
|
||||
export function finishRepostEvent(
|
||||
t: RepostEventTemplate,
|
||||
reposted: Event<number>,
|
||||
reposted: Event,
|
||||
relayUrl: string,
|
||||
privateKey: string,
|
||||
): Event<Kind.Repost> {
|
||||
): Event {
|
||||
return finishEvent(
|
||||
{
|
||||
kind: Kind.Repost,
|
||||
kind: Repost,
|
||||
tags: [...(t.tags ?? []), ['e', reposted.id, relayUrl], ['p', reposted.pubkey]],
|
||||
content: t.content === '' ? '' : JSON.stringify(reposted),
|
||||
created_at: t.created_at,
|
||||
|
@ -35,8 +36,8 @@ export function finishRepostEvent(
|
|||
)
|
||||
}
|
||||
|
||||
export function getRepostedEventPointer(event: Event<number>): undefined | EventPointer {
|
||||
if (event.kind !== Kind.Repost) {
|
||||
export function getRepostedEventPointer(event: Event): undefined | EventPointer {
|
||||
if (event.kind !== Repost) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
@ -69,20 +70,17 @@ export type GetRepostedEventOptions = {
|
|||
skipVerification?: boolean
|
||||
}
|
||||
|
||||
export function getRepostedEvent(
|
||||
event: Event<number>,
|
||||
{ skipVerification }: GetRepostedEventOptions = {},
|
||||
): undefined | Event<number> {
|
||||
export function getRepostedEvent(event: Event, { skipVerification }: GetRepostedEventOptions = {}): undefined | Event {
|
||||
const pointer = getRepostedEventPointer(event)
|
||||
|
||||
if (pointer === undefined || event.content === '') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
let repostedEvent: undefined | Event<number>
|
||||
let repostedEvent: undefined | Event
|
||||
|
||||
try {
|
||||
repostedEvent = JSON.parse(event.content) as Event<number>
|
||||
repostedEvent = JSON.parse(event.content) as Event
|
||||
} catch (error) {
|
||||
return undefined
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { finishEvent, Kind } from './event.ts'
|
||||
import { finishEvent } from './event.ts'
|
||||
import { getPublicKey } from './keys.ts'
|
||||
import { Reaction, ShortTextNote } from './kinds.ts'
|
||||
import { finishReactionEvent, getReactedEventPointer } from './nip25.ts'
|
||||
|
||||
describe('finishReactionEvent + getReactedEventPointer', () => {
|
||||
|
@ -9,7 +10,7 @@ describe('finishReactionEvent + getReactedEventPointer', () => {
|
|||
|
||||
const reactedEvent = finishEvent(
|
||||
{
|
||||
kind: Kind.Text,
|
||||
kind: ShortTextNote,
|
||||
tags: [
|
||||
['e', 'replied event id'],
|
||||
['p', 'replied event pubkey'],
|
||||
|
@ -27,7 +28,7 @@ describe('finishReactionEvent + getReactedEventPointer', () => {
|
|||
|
||||
const event = finishReactionEvent(template, reactedEvent, privateKey)
|
||||
|
||||
expect(event.kind).toEqual(Kind.Reaction)
|
||||
expect(event.kind).toEqual(Reaction)
|
||||
expect(event.tags).toEqual([
|
||||
['e', 'replied event id'],
|
||||
['p', 'replied event pubkey'],
|
||||
|
@ -55,7 +56,7 @@ describe('finishReactionEvent + getReactedEventPointer', () => {
|
|||
|
||||
const event = finishReactionEvent(template, reactedEvent, privateKey)
|
||||
|
||||
expect(event.kind).toEqual(Kind.Reaction)
|
||||
expect(event.kind).toEqual(Reaction)
|
||||
expect(event.tags).toEqual([
|
||||
['nonstandard', 'tag'],
|
||||
['e', 'replied event id'],
|
||||
|
|
15
nip25.ts
15
nip25.ts
|
@ -1,4 +1,5 @@
|
|||
import { Event, finishEvent, Kind } from './event.ts'
|
||||
import { Event, finishEvent } from './event.ts'
|
||||
import { Reaction } from './kinds.ts'
|
||||
|
||||
import type { EventPointer } from './nip19.ts'
|
||||
|
||||
|
@ -16,17 +17,13 @@ export type ReactionEventTemplate = {
|
|||
created_at: number
|
||||
}
|
||||
|
||||
export function finishReactionEvent(
|
||||
t: ReactionEventTemplate,
|
||||
reacted: Event<number>,
|
||||
privateKey: string,
|
||||
): Event<Kind.Reaction> {
|
||||
export function finishReactionEvent(t: ReactionEventTemplate, reacted: Event, privateKey: string): Event {
|
||||
const inheritedTags = reacted.tags.filter(tag => tag.length >= 2 && (tag[0] === 'e' || tag[0] === 'p'))
|
||||
|
||||
return finishEvent(
|
||||
{
|
||||
...t,
|
||||
kind: Kind.Reaction,
|
||||
kind: Reaction,
|
||||
tags: [...(t.tags ?? []), ...inheritedTags, ['e', reacted.id], ['p', reacted.pubkey]],
|
||||
content: t.content ?? '+',
|
||||
},
|
||||
|
@ -34,8 +31,8 @@ export function finishReactionEvent(
|
|||
)
|
||||
}
|
||||
|
||||
export function getReactedEventPointer(event: Event<number>): undefined | EventPointer {
|
||||
if (event.kind !== Kind.Reaction) {
|
||||
export function getReactedEventPointer(event: Event): undefined | EventPointer {
|
||||
if (event.kind !== Reaction) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Kind } from './event.ts'
|
||||
import { getPublicKey } from './keys.ts'
|
||||
import * as Kind from './kinds.ts'
|
||||
import {
|
||||
channelCreateEvent,
|
||||
channelMetadataEvent,
|
||||
|
|
35
nip28.ts
35
nip28.ts
|
@ -1,4 +1,5 @@
|
|||
import { Event, finishEvent, Kind } from './event.ts'
|
||||
import { Event, finishEvent } from './event.ts'
|
||||
import { ChannelCreation, ChannelHideMessage, ChannelMessage, ChannelMetadata, ChannelMuteUser } from './kinds.ts'
|
||||
|
||||
export interface ChannelMetadata {
|
||||
name: string
|
||||
|
@ -44,10 +45,7 @@ export interface ChannelMuteUserEventTemplate {
|
|||
tags?: string[][]
|
||||
}
|
||||
|
||||
export const channelCreateEvent = (
|
||||
t: ChannelCreateEventTemplate,
|
||||
privateKey: string,
|
||||
): Event<Kind.ChannelCreation> | undefined => {
|
||||
export const channelCreateEvent = (t: ChannelCreateEventTemplate, privateKey: string): Event | undefined => {
|
||||
let content: string
|
||||
if (typeof t.content === 'object') {
|
||||
content = JSON.stringify(t.content)
|
||||
|
@ -59,7 +57,7 @@ export const channelCreateEvent = (
|
|||
|
||||
return finishEvent(
|
||||
{
|
||||
kind: Kind.ChannelCreation,
|
||||
kind: ChannelCreation,
|
||||
tags: [...(t.tags ?? [])],
|
||||
content: content,
|
||||
created_at: t.created_at,
|
||||
|
@ -68,10 +66,7 @@ export const channelCreateEvent = (
|
|||
)
|
||||
}
|
||||
|
||||
export const channelMetadataEvent = (
|
||||
t: ChannelMetadataEventTemplate,
|
||||
privateKey: string,
|
||||
): Event<Kind.ChannelMetadata> | undefined => {
|
||||
export const channelMetadataEvent = (t: ChannelMetadataEventTemplate, privateKey: string): Event | undefined => {
|
||||
let content: string
|
||||
if (typeof t.content === 'object') {
|
||||
content = JSON.stringify(t.content)
|
||||
|
@ -83,7 +78,7 @@ export const channelMetadataEvent = (
|
|||
|
||||
return finishEvent(
|
||||
{
|
||||
kind: Kind.ChannelMetadata,
|
||||
kind: ChannelMetadata,
|
||||
tags: [['e', t.channel_create_event_id], ...(t.tags ?? [])],
|
||||
content: content,
|
||||
created_at: t.created_at,
|
||||
|
@ -92,7 +87,7 @@ export const channelMetadataEvent = (
|
|||
)
|
||||
}
|
||||
|
||||
export const channelMessageEvent = (t: ChannelMessageEventTemplate, privateKey: string): Event<Kind.ChannelMessage> => {
|
||||
export const channelMessageEvent = (t: ChannelMessageEventTemplate, privateKey: string): Event => {
|
||||
const tags = [['e', t.channel_create_event_id, t.relay_url, 'root']]
|
||||
|
||||
if (t.reply_to_channel_message_event_id) {
|
||||
|
@ -101,7 +96,7 @@ export const channelMessageEvent = (t: ChannelMessageEventTemplate, privateKey:
|
|||
|
||||
return finishEvent(
|
||||
{
|
||||
kind: Kind.ChannelMessage,
|
||||
kind: ChannelMessage,
|
||||
tags: [...tags, ...(t.tags ?? [])],
|
||||
content: t.content,
|
||||
created_at: t.created_at,
|
||||
|
@ -111,10 +106,7 @@ export const channelMessageEvent = (t: ChannelMessageEventTemplate, privateKey:
|
|||
}
|
||||
|
||||
/* "e" tag should be the kind 42 event to hide */
|
||||
export const channelHideMessageEvent = (
|
||||
t: ChannelHideMessageEventTemplate,
|
||||
privateKey: string,
|
||||
): Event<Kind.ChannelHideMessage> | undefined => {
|
||||
export const channelHideMessageEvent = (t: ChannelHideMessageEventTemplate, privateKey: string): Event | undefined => {
|
||||
let content: string
|
||||
if (typeof t.content === 'object') {
|
||||
content = JSON.stringify(t.content)
|
||||
|
@ -126,7 +118,7 @@ export const channelHideMessageEvent = (
|
|||
|
||||
return finishEvent(
|
||||
{
|
||||
kind: Kind.ChannelHideMessage,
|
||||
kind: ChannelHideMessage,
|
||||
tags: [['e', t.channel_message_event_id], ...(t.tags ?? [])],
|
||||
content: content,
|
||||
created_at: t.created_at,
|
||||
|
@ -135,10 +127,7 @@ export const channelHideMessageEvent = (
|
|||
)
|
||||
}
|
||||
|
||||
export const channelMuteUserEvent = (
|
||||
t: ChannelMuteUserEventTemplate,
|
||||
privateKey: string,
|
||||
): Event<Kind.ChannelMuteUser> | undefined => {
|
||||
export const channelMuteUserEvent = (t: ChannelMuteUserEventTemplate, privateKey: string): Event | undefined => {
|
||||
let content: string
|
||||
if (typeof t.content === 'object') {
|
||||
content = JSON.stringify(t.content)
|
||||
|
@ -150,7 +139,7 @@ export const channelMuteUserEvent = (
|
|||
|
||||
return finishEvent(
|
||||
{
|
||||
kind: Kind.ChannelMuteUser,
|
||||
kind: ChannelMuteUser,
|
||||
tags: [['p', t.pubkey_to_mute], ...(t.tags ?? [])],
|
||||
content: content,
|
||||
created_at: t.created_at,
|
||||
|
|
11
nip42.ts
11
nip42.ts
|
@ -1,4 +1,5 @@
|
|||
import { Kind, type EventTemplate, type Event } from './event.ts'
|
||||
import { type EventTemplate, type Event } from './event.ts'
|
||||
import { ClientAuth } from './kinds.ts'
|
||||
import { Relay } from './relay.ts'
|
||||
|
||||
/**
|
||||
|
@ -17,10 +18,10 @@ export const authenticate = async ({
|
|||
}: {
|
||||
challenge: string
|
||||
relay: Relay
|
||||
sign: <K extends number = number>(e: EventTemplate<K>) => Promise<Event<K>> | Event<K>
|
||||
sign: (e: EventTemplate) => Promise<Event> | Event
|
||||
}): Promise<void> => {
|
||||
const e: EventTemplate = {
|
||||
kind: Kind.ClientAuth,
|
||||
const evt: EventTemplate = {
|
||||
kind: ClientAuth,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
tags: [
|
||||
['relay', relay.url],
|
||||
|
@ -28,5 +29,5 @@ export const authenticate = async ({
|
|||
],
|
||||
content: '',
|
||||
}
|
||||
return relay.auth(await sign(e))
|
||||
return relay.auth(await sign(evt))
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { makeNwcRequestEvent, parseConnectionString } from './nip47'
|
||||
import { Kind } from './event'
|
||||
import { decrypt } from './nip04.ts'
|
||||
import crypto from 'node:crypto'
|
||||
import { NWCWalletRequest } from './kinds.ts'
|
||||
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line no-undef
|
||||
|
@ -53,7 +53,7 @@ describe('makeNwcRequestEvent', () => {
|
|||
invoice,
|
||||
})
|
||||
const timeAfter = Date.now() / 1000
|
||||
expect(result.kind).toBe(Kind.NwcRequest)
|
||||
expect(result.kind).toBe(NWCWalletRequest)
|
||||
expect(result.created_at).toBeGreaterThan(timeBefore)
|
||||
expect(result.created_at).toBeLessThan(timeAfter)
|
||||
expect(await decrypt(secret, pubkey, result.content)).toEqual(
|
||||
|
|
4
nip47.ts
4
nip47.ts
|
@ -1,6 +1,6 @@
|
|||
import { finishEvent } from './event.ts'
|
||||
import { NWCWalletRequest } from './kinds.ts'
|
||||
import { encrypt } from './nip04.ts'
|
||||
import { Kind } from './event'
|
||||
|
||||
export function parseConnectionString(connectionString: string) {
|
||||
const { pathname, searchParams } = new URL(connectionString)
|
||||
|
@ -32,7 +32,7 @@ export async function makeNwcRequestEvent({
|
|||
}
|
||||
const encryptedContent = await encrypt(secret, pubkey, JSON.stringify(content))
|
||||
const eventTemplate = {
|
||||
kind: Kind.NwcRequest,
|
||||
kind: NWCWalletRequest,
|
||||
created_at: Math.round(Date.now() / 1000),
|
||||
content: encryptedContent,
|
||||
tags: [['p', pubkey]],
|
||||
|
|
14
nip57.ts
14
nip57.ts
|
@ -1,6 +1,6 @@
|
|||
import { bech32 } from '@scure/base'
|
||||
|
||||
import { Kind, validateEvent, verifySignature, type Event, type EventTemplate } from './event.ts'
|
||||
import { validateEvent, verifySignature, type Event, type EventTemplate } from './event.ts'
|
||||
import { utf8Decoder } from './utils.ts'
|
||||
|
||||
var _fetch: any
|
||||
|
@ -13,7 +13,7 @@ export function useFetchImplementation(fetchImplementation: any) {
|
|||
_fetch = fetchImplementation
|
||||
}
|
||||
|
||||
export async function getZapEndpoint(metadata: Event<Kind.Metadata>): Promise<null | string> {
|
||||
export async function getZapEndpoint(metadata: Event): Promise<null | string> {
|
||||
try {
|
||||
let lnurl: string = ''
|
||||
let { lud06, lud16 } = JSON.parse(metadata.content)
|
||||
|
@ -53,11 +53,11 @@ export function makeZapRequest({
|
|||
amount: number
|
||||
comment: string
|
||||
relays: string[]
|
||||
}): EventTemplate<Kind.ZapRequest> {
|
||||
}): EventTemplate {
|
||||
if (!amount) throw new Error('amount not given')
|
||||
if (!profile) throw new Error('profile not given')
|
||||
|
||||
let zr: EventTemplate<Kind.ZapRequest> = {
|
||||
let zr: EventTemplate = {
|
||||
kind: 9734,
|
||||
created_at: Math.round(Date.now() / 1000),
|
||||
content: comment,
|
||||
|
@ -111,11 +111,11 @@ export function makeZapReceipt({
|
|||
preimage?: string
|
||||
bolt11: string
|
||||
paidAt: Date
|
||||
}): EventTemplate<Kind.Zap> {
|
||||
let zr: Event<Kind.ZapRequest> = JSON.parse(zapRequest)
|
||||
}): EventTemplate {
|
||||
let zr: Event = JSON.parse(zapRequest)
|
||||
let tagsFromZapRequest = zr.tags.filter(([t]) => t === 'e' || t === 'p' || t === 'a')
|
||||
|
||||
let zap: EventTemplate<Kind.Zap> = {
|
||||
let zap: EventTemplate = {
|
||||
kind: 9735,
|
||||
created_at: Math.round(paidAt.getTime() / 1000),
|
||||
content: '',
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { getToken, unpackEventFromToken, validateEvent, validateToken } from './nip98.ts'
|
||||
import { Event, Kind, finishEvent } from './event.ts'
|
||||
import { Event, finishEvent } from './event.ts'
|
||||
import { generatePrivateKey, getPublicKey } from './keys.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()
|
||||
|
||||
|
@ -15,7 +16,7 @@ describe('getToken', () => {
|
|||
|
||||
expect(decodedResult.created_at).toBeGreaterThan(0)
|
||||
expect(decodedResult.content).toBe('')
|
||||
expect(decodedResult.kind).toBe(Kind.HttpAuth)
|
||||
expect(decodedResult.kind).toBe(HTTPAuth)
|
||||
expect(decodedResult.pubkey).toBe(getPublicKey(sk))
|
||||
expect(decodedResult.tags).toStrictEqual([
|
||||
['u', 'http://test.com'],
|
||||
|
@ -30,7 +31,7 @@ describe('getToken', () => {
|
|||
|
||||
expect(decodedResult.created_at).toBeGreaterThan(0)
|
||||
expect(decodedResult.content).toBe('')
|
||||
expect(decodedResult.kind).toBe(Kind.HttpAuth)
|
||||
expect(decodedResult.kind).toBe(HTTPAuth)
|
||||
expect(decodedResult.pubkey).toBe(getPublicKey(sk))
|
||||
expect(decodedResult.tags).toStrictEqual([
|
||||
['u', 'http://test.com'],
|
||||
|
@ -49,7 +50,7 @@ describe('getToken', () => {
|
|||
|
||||
expect(decodedResult.created_at).toBeGreaterThan(0)
|
||||
expect(decodedResult.content).toBe('')
|
||||
expect(decodedResult.kind).toBe(Kind.HttpAuth)
|
||||
expect(decodedResult.kind).toBe(HTTPAuth)
|
||||
expect(decodedResult.pubkey).toBe(getPublicKey(sk))
|
||||
expect(decodedResult.tags).toStrictEqual([
|
||||
['u', 'http://test.com'],
|
||||
|
@ -76,7 +77,7 @@ describe('getToken', () => {
|
|||
|
||||
expect(decodedResult.created_at).toBeGreaterThan(0)
|
||||
expect(decodedResult.content).toBe('')
|
||||
expect(decodedResult.kind).toBe(Kind.HttpAuth)
|
||||
expect(decodedResult.kind).toBe(HTTPAuth)
|
||||
expect(decodedResult.pubkey).toBe(getPublicKey(sk))
|
||||
expect(decodedResult.tags).toStrictEqual([
|
||||
['u', 'http://test.com'],
|
||||
|
|
28
nip98.ts
28
nip98.ts
|
@ -1,12 +1,13 @@
|
|||
import { bytesToHex } from '@noble/hashes/utils'
|
||||
import { sha256 } from '@noble/hashes/sha256'
|
||||
import { base64 } from '@scure/base'
|
||||
import { Event, EventTemplate, Kind, getBlankEvent, verifySignature } from './event'
|
||||
import { Event, EventTemplate, verifySignature } from './event'
|
||||
import { utf8Decoder, utf8Encoder } from './utils'
|
||||
import { HTTPAuth } from './kinds'
|
||||
|
||||
const _authorizationScheme = 'Nostr '
|
||||
|
||||
function hashPayload(payload: any): string {
|
||||
export function hashPayload(payload: any): string {
|
||||
const hash = sha256(utf8Encoder.encode(JSON.stringify(payload)))
|
||||
return bytesToHex(hash)
|
||||
}
|
||||
|
@ -21,28 +22,29 @@ function hashPayload(payload: any): string {
|
|||
export async function getToken(
|
||||
loginUrl: string,
|
||||
httpMethod: string,
|
||||
sign: <K extends number = number>(e: EventTemplate<K>) => Promise<Event<K>> | Event<K>,
|
||||
sign: (e: EventTemplate) => Promise<Event> | Event,
|
||||
includeAuthorizationScheme: boolean = false,
|
||||
payload?: Record<string, any>,
|
||||
): Promise<string> {
|
||||
if (!loginUrl || !httpMethod) throw new Error('Missing loginUrl or httpMethod')
|
||||
|
||||
const event = getBlankEvent(Kind.HttpAuth)
|
||||
|
||||
event.tags = [
|
||||
['u', loginUrl],
|
||||
['method', httpMethod],
|
||||
]
|
||||
const event: EventTemplate = {
|
||||
kind: HTTPAuth,
|
||||
tags: [
|
||||
['u', loginUrl],
|
||||
['method', httpMethod],
|
||||
],
|
||||
created_at: Math.round(new Date().getTime() / 1000),
|
||||
content: '',
|
||||
}
|
||||
|
||||
if (payload) {
|
||||
event.tags.push(['payload', bytesToHex(sha256(utf8Encoder.encode(JSON.stringify(payload))))])
|
||||
}
|
||||
|
||||
event.created_at = Math.round(new Date().getTime() / 1000)
|
||||
|
||||
const signedEvent = await sign(event)
|
||||
|
||||
const authorizationScheme = includeAuthorizationScheme ? _authorizationScheme : ''
|
||||
|
||||
return authorizationScheme + base64.encode(utf8Encoder.encode(JSON.stringify(signedEvent)))
|
||||
}
|
||||
|
||||
|
@ -86,7 +88,7 @@ export async function validateEvent(event: Event, url: string, method: string, b
|
|||
if (!verifySignature(event)) {
|
||||
throw new Error('Invalid nostr event, signature invalid')
|
||||
}
|
||||
if (event.kind !== Kind.HttpAuth) {
|
||||
if (event.kind !== HTTPAuth) {
|
||||
throw new Error('Invalid nostr event, kind invalid')
|
||||
}
|
||||
|
||||
|
|
32
pool.ts
32
pool.ts
|
@ -5,10 +5,10 @@ import type { Event } from './event.ts'
|
|||
import { matchFilters, mergeFilters, type Filter } from './filter.ts'
|
||||
|
||||
type BatchedRequest = {
|
||||
filters: Filter<any>[]
|
||||
filters: Filter[]
|
||||
relays: string[]
|
||||
resolve: (events: Event<any>[]) => void
|
||||
events: Event<any>[]
|
||||
resolve: (events: Event[]) => void
|
||||
events: Event[]
|
||||
}
|
||||
|
||||
export class SimplePool {
|
||||
|
@ -58,7 +58,7 @@ export class SimplePool {
|
|||
return relay
|
||||
}
|
||||
|
||||
sub<K extends number = number>(relays: string[], filters: Filter<K>[], opts?: SubscriptionOptions): Sub<K> {
|
||||
sub(relays: string[], filters: Filter[], opts?: SubscriptionOptions): Sub {
|
||||
let _knownIds: Set<string> = new Set()
|
||||
let modifiedOpts = { ...(opts || {}) }
|
||||
modifiedOpts.alreadyHaveEvent = (id, url) => {
|
||||
|
@ -118,7 +118,7 @@ export class SimplePool {
|
|||
}
|
||||
})
|
||||
|
||||
let greaterSub: Sub<K> = {
|
||||
let greaterSub: Sub = {
|
||||
sub(filters, opts) {
|
||||
subs.forEach(sub => sub.sub(filters, opts))
|
||||
return greaterSub as any
|
||||
|
@ -146,11 +146,7 @@ export class SimplePool {
|
|||
return greaterSub
|
||||
}
|
||||
|
||||
get<K extends number = number>(
|
||||
relays: string[],
|
||||
filter: Filter<K>,
|
||||
opts?: SubscriptionOptions,
|
||||
): Promise<Event<K> | null> {
|
||||
get(relays: string[], filter: Filter, opts?: SubscriptionOptions): Promise<Event | null> {
|
||||
return new Promise(resolve => {
|
||||
let sub = this.sub(relays, [filter], opts)
|
||||
let timeout = setTimeout(() => {
|
||||
|
@ -165,13 +161,9 @@ export class SimplePool {
|
|||
})
|
||||
}
|
||||
|
||||
list<K extends number = number>(
|
||||
relays: string[],
|
||||
filters: Filter<K>[],
|
||||
opts?: SubscriptionOptions,
|
||||
): Promise<Event<K>[]> {
|
||||
list(relays: string[], filters: Filter[], opts?: SubscriptionOptions): Promise<Event[]> {
|
||||
return new Promise(resolve => {
|
||||
let events: Event<K>[] = []
|
||||
let events: Event[] = []
|
||||
let sub = this.sub(relays, filters, opts)
|
||||
|
||||
sub.on('event', event => {
|
||||
|
@ -186,11 +178,7 @@ export class SimplePool {
|
|||
})
|
||||
}
|
||||
|
||||
batchedList<K extends number = number>(
|
||||
batchKey: string,
|
||||
relays: string[],
|
||||
filters: Filter<K>[],
|
||||
): Promise<Event<K>[]> {
|
||||
batchedList(batchKey: string, relays: string[], filters: Filter[]): Promise<Event[]> {
|
||||
return new Promise(resolve => {
|
||||
if (!this.batchedByKey[batchKey]) {
|
||||
this.batchedByKey[batchKey] = [
|
||||
|
@ -236,7 +224,7 @@ export class SimplePool {
|
|||
})
|
||||
}
|
||||
|
||||
publish(relays: string[], event: Event<number>): Promise<void>[] {
|
||||
publish(relays: string[], event: Event): Promise<void>[] {
|
||||
return relays.map(async relay => {
|
||||
let r = await this.ensureRelay(relay)
|
||||
return r.publish(event)
|
||||
|
|
48
relay.ts
48
relay.ts
|
@ -15,8 +15,8 @@ type RelayEvent = {
|
|||
export type CountPayload = {
|
||||
count: number
|
||||
}
|
||||
export type SubEvent<K extends number> = {
|
||||
event: (event: Event<K>) => void | Promise<void>
|
||||
export type SubEvent = {
|
||||
event: (event: Event) => void | Promise<void>
|
||||
count: (payload: CountPayload) => void | Promise<void>
|
||||
eose: () => void | Promise<void>
|
||||
}
|
||||
|
@ -25,21 +25,21 @@ export type Relay = {
|
|||
status: number
|
||||
connect: () => Promise<void>
|
||||
close: () => void
|
||||
sub: <K extends number = number>(filters: Filter<K>[], opts?: SubscriptionOptions) => Sub<K>
|
||||
list: <K extends number = number>(filters: Filter<K>[], opts?: SubscriptionOptions) => Promise<Event<K>[]>
|
||||
get: <K extends number = number>(filter: Filter<K>, opts?: SubscriptionOptions) => Promise<Event<K> | null>
|
||||
sub: (filters: Filter[], opts?: SubscriptionOptions) => Sub
|
||||
list: (filters: Filter[], opts?: SubscriptionOptions) => Promise<Event[]>
|
||||
get: (filter: Filter, opts?: SubscriptionOptions) => Promise<Event | null>
|
||||
count: (filters: Filter[], opts?: SubscriptionOptions) => Promise<CountPayload | null>
|
||||
publish: (event: Event<number>) => Promise<void>
|
||||
auth: (event: Event<number>) => Promise<void>
|
||||
publish: (event: Event) => Promise<void>
|
||||
auth: (event: Event) => Promise<void>
|
||||
off: <T extends keyof RelayEvent, U extends RelayEvent[T]>(event: T, listener: U) => void
|
||||
on: <T extends keyof RelayEvent, U extends RelayEvent[T]>(event: T, listener: U) => void
|
||||
}
|
||||
export type Sub<K extends number = number> = {
|
||||
sub: <K extends number = number>(filters: Filter<K>[], opts: SubscriptionOptions) => Sub<K>
|
||||
export type Sub = {
|
||||
sub: (filters: Filter[], opts: SubscriptionOptions) => Sub
|
||||
unsub: () => void
|
||||
on: <T extends keyof SubEvent<K>, U extends SubEvent<K>[T]>(event: T, listener: U) => void
|
||||
off: <T extends keyof SubEvent<K>, U extends SubEvent<K>[T]>(event: T, listener: U) => void
|
||||
events: AsyncGenerator<Event<K>, void, unknown>
|
||||
on: <T extends keyof SubEvent, U extends SubEvent[T]>(event: T, listener: U) => void
|
||||
off: <T extends keyof SubEvent, U extends SubEvent[T]>(event: T, listener: U) => void
|
||||
events: AsyncGenerator<Event, void, unknown>
|
||||
}
|
||||
|
||||
export type SubscriptionOptions = {
|
||||
|
@ -72,7 +72,7 @@ export function relayInit(
|
|||
var openSubs: { [id: string]: { filters: Filter[] } & SubscriptionOptions } = {}
|
||||
var listeners = newListeners()
|
||||
var subListeners: {
|
||||
[subid: string]: { [TK in keyof SubEvent<any>]: SubEvent<any>[TK][] }
|
||||
[subid: string]: { [TK in keyof SubEvent]: SubEvent[TK][] }
|
||||
} = {}
|
||||
var pubListeners: {
|
||||
[eventid: string]: {
|
||||
|
@ -223,15 +223,15 @@ export function relayInit(
|
|||
}
|
||||
}
|
||||
|
||||
const sub = <K extends number = number>(
|
||||
filters: Filter<K>[],
|
||||
const sub = (
|
||||
filters: Filter[],
|
||||
{
|
||||
verb = 'REQ',
|
||||
skipVerification = false,
|
||||
alreadyHaveEvent = null,
|
||||
id = Math.random().toString().slice(2),
|
||||
}: SubscriptionOptions = {},
|
||||
): Sub<K> => {
|
||||
): Sub => {
|
||||
let subid = id
|
||||
|
||||
openSubs[subid] = {
|
||||
|
@ -242,7 +242,7 @@ export function relayInit(
|
|||
}
|
||||
trySend([verb, subid, ...filters])
|
||||
|
||||
let subscription: Sub<K> = {
|
||||
let subscription: Sub = {
|
||||
sub: (newFilters, newOpts = {}) =>
|
||||
sub(newFilters || filters, {
|
||||
skipVerification: newOpts.skipVerification || skipVerification,
|
||||
|
@ -275,7 +275,7 @@ export function relayInit(
|
|||
return subscription
|
||||
}
|
||||
|
||||
function _publishEvent(event: Event<number>, type: string) {
|
||||
function _publishEvent(event: Event, type: string) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!event.id) {
|
||||
reject(new Error(`event ${event} has no id`))
|
||||
|
@ -305,7 +305,7 @@ export function relayInit(
|
|||
list: (filters, opts?: SubscriptionOptions) =>
|
||||
new Promise(resolve => {
|
||||
let s = sub(filters, opts)
|
||||
let events: Event<any>[] = []
|
||||
let events: Event[] = []
|
||||
let timeout = setTimeout(() => {
|
||||
s.unsub()
|
||||
resolve(events)
|
||||
|
@ -366,11 +366,11 @@ export function relayInit(
|
|||
}
|
||||
}
|
||||
|
||||
export async function* eventsGenerator<K extends number>(sub: Sub<K>): AsyncGenerator<Event<K>, void, unknown> {
|
||||
let nextResolve: ((event: Event<K>) => void) | undefined
|
||||
const eventQueue: Event<K>[] = []
|
||||
export async function* eventsGenerator(sub: Sub): AsyncGenerator<Event, void, unknown> {
|
||||
let nextResolve: ((event: Event) => void) | undefined
|
||||
const eventQueue: Event[] = []
|
||||
|
||||
const pushToQueue = (event: Event<K>) => {
|
||||
const pushToQueue = (event: Event) => {
|
||||
if (nextResolve) {
|
||||
nextResolve(event)
|
||||
nextResolve = undefined
|
||||
|
@ -386,7 +386,7 @@ export async function* eventsGenerator<K extends number>(sub: Sub<K>): AsyncGene
|
|||
if (eventQueue.length > 0) {
|
||||
yield eventQueue.shift()!
|
||||
} else {
|
||||
const event = await new Promise<Event<K>>(resolve => {
|
||||
const event = await new Promise<Event>(resolve => {
|
||||
nextResolve = resolve
|
||||
})
|
||||
yield event
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import type { Event } from './event.ts'
|
||||
|
||||
type EventParams<K extends number> = Partial<Event<K>>
|
||||
|
||||
/** Build an event for testing purposes. */
|
||||
export function buildEvent<K extends number = 1>(params: EventParams<K>): Event<K> {
|
||||
export function buildEvent(params: Partial<Event>): Event {
|
||||
return {
|
||||
id: '',
|
||||
kind: 1 as K,
|
||||
kind: 1,
|
||||
pubkey: '',
|
||||
created_at: 0,
|
||||
content: '',
|
||||
|
|
4
utils.ts
4
utils.ts
|
@ -16,7 +16,7 @@ export function normalizeURL(url: string): string {
|
|||
//
|
||||
// fast insert-into-sorted-array functions adapted from https://github.com/terrymorse58/fast-sorted-array
|
||||
//
|
||||
export function insertEventIntoDescendingList(sortedArray: Event<number>[], event: Event<number>) {
|
||||
export function insertEventIntoDescendingList(sortedArray: Event[], event: Event) {
|
||||
let start = 0
|
||||
let end = sortedArray.length - 1
|
||||
let midPoint
|
||||
|
@ -54,7 +54,7 @@ export function insertEventIntoDescendingList(sortedArray: Event<number>[], even
|
|||
return sortedArray
|
||||
}
|
||||
|
||||
export function insertEventIntoAscendingList(sortedArray: Event<number>[], event: Event<number>) {
|
||||
export function insertEventIntoAscendingList(sortedArray: Event[], event: Event) {
|
||||
let start = 0
|
||||
let end = sortedArray.length - 1
|
||||
let midPoint
|
||||
|
|
Loading…
Reference in New Issue