Improve event types

This commit is contained in:
Alex Gleason 2023-05-06 16:51:23 -05:00 committed by fiatjaf_
parent d0bd599ce8
commit 8a53b3b8b3
8 changed files with 29 additions and 28 deletions

View File

@ -103,7 +103,6 @@
"no-octal-escape": 2,
"no-path-concat": 0,
"no-proto": 2,
"no-redeclare": 2,
"no-regex-spaces": 2,
"no-return-assign": 0,
"no-self-assign": 2,

View File

@ -6,7 +6,6 @@ import {getPublicKey} from './keys'
/* eslint-disable no-unused-vars */
export enum Kind {
UndefinedKindNumber = 255,
Metadata = 0,
Text = 1,
RecommendRelay = 2,
@ -20,6 +19,7 @@ export enum Kind {
ChannelMessage = 42,
ChannelHideMessage = 43,
ChannelMuteUser = 44,
Blank = 255,
Report = 1984,
ZapRequest = 9734,
Zap = 9735,
@ -46,24 +46,26 @@ export type Event<K extends number = Kind> = UnsignedEvent<K> & {
sig: string
}
export function getBlankEvent<K extends Kind = Kind.UndefinedKindNumber>(kind?: K): EventTemplate<K> {
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: kind || ( Kind.UndefinedKindNumber as K),
kind,
content: '',
tags: [],
created_at: 0
}
}
export function finishEvent(t: EventTemplate, privateKey: string): Event {
let event = t as Event
export function finishEvent<K extends number = Kind>(t: EventTemplate<K>, privateKey: string): Event<K> {
let event = t as Event<K>
event.pubkey = getPublicKey(privateKey)
event.id = getEventHash(event)
event.sig = getSignature(event, privateKey)
return event
}
export function serializeEvent(evt: UnsignedEvent): string {
export function serializeEvent(evt: UnsignedEvent<number>): string {
if (!validateEvent(evt))
throw new Error("can't serialize event with wrong or missing properties")
@ -77,14 +79,14 @@ export function serializeEvent(evt: UnsignedEvent): string {
])
}
export function getEventHash(event: UnsignedEvent): string {
export function getEventHash(event: UnsignedEvent<number>): string {
let eventHash = sha256(utf8Encoder.encode(serializeEvent(event)))
return secp256k1.utils.bytesToHex(eventHash)
}
const isRecord = (obj: unknown): obj is Record<string, unknown> => obj instanceof Object
export function validateEvent<T>(event: T): event is T & UnsignedEvent {
export function validateEvent<T>(event: T): event is T & UnsignedEvent<number> {
if (!isRecord(event)) return false
if (typeof event.kind !== 'number') return false
if (typeof event.content !== 'string') return false
@ -104,7 +106,7 @@ export function validateEvent<T>(event: T): event is T & UnsignedEvent {
return true
}
export function verifySignature(event: Event): boolean {
export function verifySignature(event: Event<number>): boolean {
return secp256k1.schnorr.verifySync(
event.sig,
getEventHash(event),
@ -113,7 +115,7 @@ export function verifySignature(event: Event): boolean {
}
/** @deprecated Use `getSignature` instead. */
export function signEvent(event: UnsignedEvent, key: string): string {
export function signEvent(event: UnsignedEvent<number>, key: string): string {
console.warn(
'nostr-tools: `signEvent` is deprecated and will be removed or changed in the future. Please use `getSignature` instead.'
)
@ -121,7 +123,7 @@ export function signEvent(event: UnsignedEvent, key: string): string {
}
/** Calculate the signature for an event. */
export function getSignature(event: UnsignedEvent, key: string): string {
export function getSignature(event: UnsignedEvent<number>, key: string): string {
return secp256k1.utils.bytesToHex(
secp256k1.schnorr.signSync(getEventHash(event), key)
)

View File

@ -5,7 +5,7 @@ import {base64} from '@scure/base'
import {utf8Decoder, utf8Encoder} from './utils'
// @ts-ignore
if (typeof(crypto) !== 'undefined' && !crypto.subtle && crypto.webcrypto) {
if (typeof crypto !== 'undefined' && !crypto.subtle && crypto.webcrypto) {
// @ts-ignore
crypto.subtle = crypto.webcrypto.subtle
}

View File

@ -17,9 +17,9 @@ export type ReactionEventTemplate = {
export function finishReactionEvent(
t: ReactionEventTemplate,
reacted: Event,
reacted: Event<number>,
privateKey: string,
): Event {
): Event<Kind.Reaction> {
const inheritedTags = reacted.tags.filter(
(tag) => tag.length >= 2 && (tag[0] === 'e' || tag[0] === 'p'),
)
@ -37,7 +37,7 @@ export function finishReactionEvent(
}, privateKey)
}
export function getReactedEventPointer(event: Event): undefined | EventPointer {
export function getReactedEventPointer(event: Event<number>): undefined | EventPointer {
if (event.kind !== Kind.Reaction) {
return undefined
}

View File

@ -48,7 +48,7 @@ export function createDelegation(
}
}
export function getDelegator(event: Event): string | null {
export function getDelegator(event: Event<number>): string | null {
// find delegation tag
let tag = event.tags.find(tag => tag[0] === 'delegation' && tag.length >= 4)
if (!tag) return null

View File

@ -17,7 +17,7 @@ export const authenticate = async ({
}: {
challenge: string
relay: Relay
sign: (e: EventTemplate) => Promise<Event>
sign: <K extends number = number>(e: EventTemplate<K>) => Promise<Event<K>>
}): Promise<void> => {
const e: EventTemplate = {
kind: Kind.ClientAuth,

View File

@ -13,7 +13,7 @@ export function useFetchImplementation(fetchImplementation: any) {
_fetch = fetchImplementation
}
export async function getZapEndpoint(metadata: Event): Promise<null | string> {
export async function getZapEndpoint(metadata: Event<0>): 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 {
}): EventTemplate<9734> {
if (!amount) throw new Error('amount not given')
if (!profile) throw new Error('profile not given')
let zr = {
let zr: EventTemplate<9734> = {
kind: 9734,
created_at: Math.round(Date.now() / 1000),
content: comment,
@ -113,13 +113,13 @@ export function makeZapReceipt({
preimage: string | null
bolt11: string
paidAt: Date
}): EventTemplate {
let zr: Event = JSON.parse(zapRequest)
}): EventTemplate<9735> {
let zr: Event<9734> = JSON.parse(zapRequest)
let tagsFromZapRequest = zr.tags.filter(
([t]) => t === 'e' || t === 'p' || t === 'a'
)
let zap = {
let zap: EventTemplate<9735> = {
kind: 9735,
created_at: Math.round(paidAt.getTime() / 1000),
content: '',

View File

@ -21,8 +21,8 @@ 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[],
event: Event
sortedArray: Event<number>[],
event: Event<number>
) {
let start = 0
let end = sortedArray.length - 1
@ -66,8 +66,8 @@ export function insertEventIntoDescendingList(
}
export function insertEventIntoAscendingList(
sortedArray: Event[],
event: Event
sortedArray: Event<number>[],
event: Event<number>
) {
let start = 0
let end = sortedArray.length - 1